1# Copyright (c) 2012 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
5import dbus
6
7import dbus_std_ifaces
8
9from autotest_lib.client.cros.cellular import mm1_constants
10
11class SMSConfigException(Exception):
12    """
13    Raised when an error occurs while setting the SMS property template.
14
15    """
16    pass
17
18
19class SMS(dbus_std_ifaces.DBusProperties):
20    """
21    Pseudomodem implementation of the org.freedesktop.ModemManager1.Sms
22    interface.
23
24    The SMS interface defines operations and properties of a single SMS
25    message.
26
27    Modems implementing the Messaging interface will export one SMS object for
28    each SMS stored in the device.
29
30    """
31
32    _sms_index = 0
33    _props_template = {}
34    _settable_props = set([ 'SMSC', 'Validity', 'Class', 'Storage',
35                            'DeliveryReportRequest' ])
36
37    def __init__(self, bus, sender_number, content):
38        self._sender_number = sender_number
39        self._content = content
40        dbus_std_ifaces.DBusProperties.__init__(
41                self, self._get_next_sms_path(), bus)
42
43
44    @classmethod
45    def _get_next_sms_path(cls):
46        path = mm1_constants.SMS_PATH + '/' + str(cls._sms_index)
47        cls._sms_index += 1
48        return path
49
50
51    @classmethod
52    def set_config(cls, params):
53        """
54        Sets the values that should be used for SMS properties when a new
55        SMS is constructed.
56
57        @param params: A dictionary containing properties and values to set.
58                Only some properties are allowed to be set through this method,
59                which are contained in |_settable_props|. A value of "default"
60                can be used (which is a string) to use the default value for
61                that dictionary when constructing the next SMS object.
62        @raises: SMSConfigException, if params is malformed or contains a
63                disallowed property.
64
65        """
66        if not isinstance(params, dict):
67            raise SMSConfigException('sms.SMS.set_config only accepts '
68                                     'dictionaries.')
69        keyset = set(params)
70        if not keyset.issubset(cls._settable_props):
71            raise SMSConfigException(
72                    'Properties: ' + repr(keyset.difference(params)) + ' are '
73                    'not settable.')
74
75        for key, value in params.iteritems():
76            if value == 'default' and cls._props_template.has_key(key):
77                cls._props_template.pop(key)
78            else:
79                cls._props_template[key] = value
80
81
82    def _InitializeProperties(self):
83        props = {}
84        props['State'] = dbus.types.UInt32(mm1_constants.MM_SMS_STATE_UNKNOWN)
85        props['PduType'] = dbus.types.UInt32(
86                mm1_constants.MM_SMS_PDU_TYPE_UNKNOWN)
87        props['Number'] = self._sender_number
88        # For now, only support 'Text' and not 'Data'
89        props['Text'] = self._content
90        props['SMSC'] = self._props_template.get('SMSC', '1231212')
91        props['Validity'] = self._props_template.get('Validity',
92                dbus.types.Struct(
93                        [dbus.types.UInt32(
94                                mm1_constants.MM_SMS_VALIDITY_TYPE_UNKNOWN),
95                         dbus.types.UInt32(0)],
96                        signature='uv'))
97        props['Class'] = self._props_template.get('Class', dbus.types.Int32(-1))
98        props['DeliveryReportRequest'] = self._props_template.get(
99                'DeliveryReportRequest',
100                dbus.types.Boolean(False))
101        props['Storage'] = self._props_template.get(
102                'Storage',
103                dbus.types.UInt32(mm1_constants.MM_SMS_STORAGE_UNKNOWN))
104        # TODO(armansito): This may be useful for split SMS messages. Need to
105        # study the SMS standard to figure out how to make use of this
106        # property.
107        props['MessageReference'] =  dbus.types.UInt32(0)
108
109        # Timestamp, DischargeTimestamp, and DeliveryState won't be available
110        # until an action (such as send, receive, status report) is take with
111        # the SMS.
112        props['Timestamp'] = ''
113        props['DischargeTimestamp'] = ''
114        return { mm1_constants.I_SMS: props }
115
116
117    # Remember to decorate your concrete implementation with
118    # @utils.log_dbus_method()
119    @dbus.service.method(mm1_constants.I_SMS)
120    def Send(self):
121        """ If the message has not yet been sent, queue it for delivery. """
122        raise NotImplementedError()
123
124
125    # Remember to decorate your concrete implementation with
126    # @utils.log_dbus_method()
127    @dbus.service.method(mm1_constants.I_SMS, in_signature='u')
128    def Store(self, storage):
129        """
130        Stores the message in the device if not already done.
131
132        @param storage: An MMSmsStorage value.
133
134        """
135        raise NotImplementedError()
136