Home | History | Annotate | Download | only in pseudomodem
      1 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import datetime
      6 import dbus
      7 import dbus.types
      8 import logging
      9 
     10 import sms
     11 
     12 from autotest_lib.client.cros.cellular import mm1_constants
     13 
     14 class SmsHandlerException(Exception):
     15     """ Exception class for errors raised by SmsHandler. """
     16     pass
     17 
     18 
     19 class SmsHandler(object):
     20     """
     21     Handles all SMS operations, which includes storing received SMS messages,
     22     as well as notifying the modem when a new SMS is received.
     23 
     24     """
     25 
     26     # TODO(armansito): Apply a character limit to SMS messages for multi-part
     27     # delivery. This constant here is defined for future reference but is
     28     # currently unusued. The value that is currently assigned to it is
     29     # arbitrary and a more meaningful default value should be used, though it
     30     # really doesn't matter from a testing perspective.
     31     SMS_CHAR_LIMIT = 200
     32 
     33     def __init__(self, modem, bus=None):
     34         self._modem = modem
     35         self._messages = {}  # Mapping from DBus Object paths to sms.SMS.
     36         self._bus = bus
     37 
     38 
     39     @property
     40     def bus(self):
     41         """
     42         Returns the current bus assigned to this object. This is the bus
     43         on which new SMS objects will be created.
     44 
     45         @returns: An instance of dbus.Bus.
     46 
     47         """
     48         return self._bus
     49 
     50 
     51     @bus.setter
     52     def bus(self, bus):
     53         """
     54         Sets the current bus on which SMS objects should be created.
     55 
     56         @param bus: An instance of dbus.Bus.
     57 
     58         """
     59         self._bus = bus
     60 
     61 
     62     @classmethod
     63     def set_char_limit(cls, limit):
     64         cls.SMS_CHAR_LIMIT = limit
     65 
     66 
     67     def clear_messages(self):
     68         """ Clears all SMS messages. """
     69         self._messages.clear()
     70 
     71 
     72     def delete_message(self, path):
     73         """
     74         Removes the message with DBus object path |path|. This operation
     75         has no effect if and SMS object with path |path| is unknown.
     76 
     77         @param path: DBus object path of the SMS object to remove.
     78 
     79         """
     80         try:
     81             self._messages.pop(path)
     82         except KeyError:
     83             logging.info('SMS object with path "%s" not found.', path)
     84             pass
     85 
     86 
     87     def list_messages(self):
     88         """
     89         Returns a list of DBus object paths belonging to stored SMS messages.
     90 
     91         """
     92         return self._messages.keys()
     93 
     94 
     95     def get_message_with_path(self, path):
     96         """
     97         Returns the SMS message with the DBus object path that matches |path|.
     98 
     99         @param path: DBus object path of the requested SMS object.
    100         @returns: An instance of sms.SMS or None, if an SMS object with the
    101                 requested path is not found.
    102 
    103         """
    104         sms_object = self._messages.get(path, None)
    105         if sms_object:
    106             assert sms_object.path == path
    107         return sms_object
    108 
    109 
    110     def construct_sms(self, text, sender):
    111         """
    112         Constructs an SMS object and stores it internally. SMS messages should
    113         be created using this method instead of being instantiated directly.
    114         Once an SMS is created, it can be obtained via get_message_with_path.
    115 
    116         @param text: The message contents, in UTF-8 format.
    117         @param sender: The phone number of the sender.
    118         @returns: An instance of sms.SMS.
    119 
    120         """
    121         if self._bus is None:
    122             raise SmsHandlerException('A bus has to be set before SMS objects '
    123                                       'can be created.')
    124         sms_object = sms.SMS(self._bus, sender, text)
    125         self._messages[sms_object.path] = sms_object
    126         # TODO(armansito): Split SMSs that are too big into multiple chunks.
    127         return sms_object
    128 
    129 
    130     def send_sms(self, text, sender):
    131         """
    132         Queues up an SMS to be sent and simulates SMS delivery state updates.
    133 
    134         @param text: The message contents, in UTF-8 format.
    135         @param sender: The phone number of the sender.
    136 
    137         """
    138         # TODO(armansito): Support this if it's ever needed (unlikely).
    139         raise SmsHandlerException('Sending SMSs is not supported.')
    140 
    141 
    142     def receive_sms(self, text, sender, is_status_report=False):
    143         """
    144         Simulates a received SMS message.
    145 
    146         @param text: The message contents, in UTF-8 format.
    147         @param sender: The phone number of the sender.
    148         @param is_status_report: If True, the SMS will be formatted as a status
    149                 report.
    150 
    151         """
    152         sms_object = self.construct_sms(text, sender)
    153 
    154         # Use the current time for both DischargeTimestamp and Timestamp. Our
    155         # SMS messages travel faster than the speed of light.
    156         timestamp = datetime.datetime.isoformat(datetime.datetime.now())
    157         sms_object.Set(mm1_constants.I_SMS, 'Timestamp', timestamp)
    158         sms_object.Set(mm1_constants.I_SMS, 'DischargeTimestamp', timestamp)
    159 
    160         # Receive messages right away.
    161         sms_object.Set(mm1_constants.I_SMS, 'State',
    162                        mm1_constants.MM_SMS_STATE_RECEIVED)
    163         sms_object.Set(mm1_constants.I_SMS, 'PduType',
    164                        mm1_constants.MM_SMS_PDU_TYPE_DELIVER)
    165 
    166         # Emit an Added message.
    167         self._modem.Added(dbus.types.ObjectPath(sms_object.path), True)
    168