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