You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.1 KiB
168 lines
5.1 KiB
7 months ago
|
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
||
|
# Use of this source code is governed by a BSD-style license that can be
|
||
|
# found in the LICENSE file.
|
||
|
|
||
|
import datetime
|
||
|
import dbus
|
||
|
import dbus.types
|
||
|
import logging
|
||
|
|
||
|
import sms
|
||
|
|
||
|
from autotest_lib.client.cros.cellular import mm1_constants
|
||
|
|
||
|
class SmsHandlerException(Exception):
|
||
|
""" Exception class for errors raised by SmsHandler. """
|
||
|
pass
|
||
|
|
||
|
|
||
|
class SmsHandler(object):
|
||
|
"""
|
||
|
Handles all SMS operations, which includes storing received SMS messages,
|
||
|
as well as notifying the modem when a new SMS is received.
|
||
|
|
||
|
"""
|
||
|
|
||
|
# TODO(armansito): Apply a character limit to SMS messages for multi-part
|
||
|
# delivery. This constant here is defined for future reference but is
|
||
|
# currently unusued. The value that is currently assigned to it is
|
||
|
# arbitrary and a more meaningful default value should be used, though it
|
||
|
# really doesn't matter from a testing perspective.
|
||
|
SMS_CHAR_LIMIT = 200
|
||
|
|
||
|
def __init__(self, modem, bus=None):
|
||
|
self._modem = modem
|
||
|
self._messages = {} # Mapping from DBus Object paths to sms.SMS.
|
||
|
self._bus = bus
|
||
|
|
||
|
|
||
|
@property
|
||
|
def bus(self):
|
||
|
"""
|
||
|
Returns the current bus assigned to this object. This is the bus
|
||
|
on which new SMS objects will be created.
|
||
|
|
||
|
@returns: An instance of dbus.Bus.
|
||
|
|
||
|
"""
|
||
|
return self._bus
|
||
|
|
||
|
|
||
|
@bus.setter
|
||
|
def bus(self, bus):
|
||
|
"""
|
||
|
Sets the current bus on which SMS objects should be created.
|
||
|
|
||
|
@param bus: An instance of dbus.Bus.
|
||
|
|
||
|
"""
|
||
|
self._bus = bus
|
||
|
|
||
|
|
||
|
@classmethod
|
||
|
def set_char_limit(cls, limit):
|
||
|
cls.SMS_CHAR_LIMIT = limit
|
||
|
|
||
|
|
||
|
def clear_messages(self):
|
||
|
""" Clears all SMS messages. """
|
||
|
self._messages.clear()
|
||
|
|
||
|
|
||
|
def delete_message(self, path):
|
||
|
"""
|
||
|
Removes the message with DBus object path |path|. This operation
|
||
|
has no effect if and SMS object with path |path| is unknown.
|
||
|
|
||
|
@param path: DBus object path of the SMS object to remove.
|
||
|
|
||
|
"""
|
||
|
try:
|
||
|
self._messages.pop(path)
|
||
|
except KeyError:
|
||
|
logging.info('SMS object with path "%s" not found.', path)
|
||
|
pass
|
||
|
|
||
|
|
||
|
def list_messages(self):
|
||
|
"""
|
||
|
Returns a list of DBus object paths belonging to stored SMS messages.
|
||
|
|
||
|
"""
|
||
|
return self._messages.keys()
|
||
|
|
||
|
|
||
|
def get_message_with_path(self, path):
|
||
|
"""
|
||
|
Returns the SMS message with the DBus object path that matches |path|.
|
||
|
|
||
|
@param path: DBus object path of the requested SMS object.
|
||
|
@returns: An instance of sms.SMS or None, if an SMS object with the
|
||
|
requested path is not found.
|
||
|
|
||
|
"""
|
||
|
sms_object = self._messages.get(path, None)
|
||
|
if sms_object:
|
||
|
assert sms_object.path == path
|
||
|
return sms_object
|
||
|
|
||
|
|
||
|
def construct_sms(self, text, sender):
|
||
|
"""
|
||
|
Constructs an SMS object and stores it internally. SMS messages should
|
||
|
be created using this method instead of being instantiated directly.
|
||
|
Once an SMS is created, it can be obtained via get_message_with_path.
|
||
|
|
||
|
@param text: The message contents, in UTF-8 format.
|
||
|
@param sender: The phone number of the sender.
|
||
|
@returns: An instance of sms.SMS.
|
||
|
|
||
|
"""
|
||
|
if self._bus is None:
|
||
|
raise SmsHandlerException('A bus has to be set before SMS objects '
|
||
|
'can be created.')
|
||
|
sms_object = sms.SMS(self._bus, sender, text)
|
||
|
self._messages[sms_object.path] = sms_object
|
||
|
# TODO(armansito): Split SMSs that are too big into multiple chunks.
|
||
|
return sms_object
|
||
|
|
||
|
|
||
|
def send_sms(self, text, sender):
|
||
|
"""
|
||
|
Queues up an SMS to be sent and simulates SMS delivery state updates.
|
||
|
|
||
|
@param text: The message contents, in UTF-8 format.
|
||
|
@param sender: The phone number of the sender.
|
||
|
|
||
|
"""
|
||
|
# TODO(armansito): Support this if it's ever needed (unlikely).
|
||
|
raise SmsHandlerException('Sending SMSs is not supported.')
|
||
|
|
||
|
|
||
|
def receive_sms(self, text, sender, is_status_report=False):
|
||
|
"""
|
||
|
Simulates a received SMS message.
|
||
|
|
||
|
@param text: The message contents, in UTF-8 format.
|
||
|
@param sender: The phone number of the sender.
|
||
|
@param is_status_report: If True, the SMS will be formatted as a status
|
||
|
report.
|
||
|
|
||
|
"""
|
||
|
sms_object = self.construct_sms(text, sender)
|
||
|
|
||
|
# Use the current time for both DischargeTimestamp and Timestamp. Our
|
||
|
# SMS messages travel faster than the speed of light.
|
||
|
timestamp = datetime.datetime.isoformat(datetime.datetime.now())
|
||
|
sms_object.Set(mm1_constants.I_SMS, 'Timestamp', timestamp)
|
||
|
sms_object.Set(mm1_constants.I_SMS, 'DischargeTimestamp', timestamp)
|
||
|
|
||
|
# Receive messages right away.
|
||
|
sms_object.Set(mm1_constants.I_SMS, 'State',
|
||
|
mm1_constants.MM_SMS_STATE_RECEIVED)
|
||
|
sms_object.Set(mm1_constants.I_SMS, 'PduType',
|
||
|
mm1_constants.MM_SMS_PDU_TYPE_DELIVER)
|
||
|
|
||
|
# Emit an Added message.
|
||
|
self._modem.Added(dbus.types.ObjectPath(sms_object.path), True)
|