1# Copyright (c) 2014 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"""
6This module provides bindings for PseudoModem Manager.
7
8"""
9
10import dbus
11import logging
12
13import mm1_proxy
14
15from autotest_lib.client.bin import utils
16from autotest_lib.client.cros.cellular import mm1_constants
17from autotest_lib.client.cros.cellular.pseudomodem import pm_constants
18
19
20class PseudoMMProxy(mm1_proxy.ModemManager1Proxy):
21    """A wrapper around a DBus proxy for PseudoModem Manager."""
22
23    # Used for software message propagation latencies.
24    SHORT_TIMEOUT_SECONDS = 2
25
26    @property
27    def iface_testing(self):
28        """@return org.chromium.Pseudomodem.Testing DBus interface."""
29        return dbus.Interface(
30                self._bus.get_object(mm1_constants.I_MODEM_MANAGER,
31                                     pm_constants.TESTING_PATH),
32                pm_constants.I_TESTING)
33
34
35    def iface_ism(self, machine_name, timeout_seconds=SHORT_TIMEOUT_SECONDS):
36        """
37        Get the testing interface of the given interactive state machine.
38
39        @param machine_name: The name of the interactive state machine.
40        @param timeout_seconds: Max number of seconds to wait until interactive
41            state machine becomes available.
42        @return dbus.Interface for the testing interface of
43            InteractiveScanningMachine.
44        @raise mm1_proxy.ModemManager1ProxyError if a valid DBus object can't
45            be found.
46
47        """
48        def _get_machine(ignore_error):
49            machine = self._bus.get_object(
50                    mm1_constants.I_MODEM_MANAGER,
51                    '/'.join([pm_constants.TESTING_PATH, machine_name]))
52            if machine is None:
53                return None
54
55            i_machine = dbus.Interface(machine, pm_constants.I_TESTING_ISM)
56            # Only way to know if this DBus object is valid is to call a
57            # method on it.
58            try:
59                i_machine.IsWaiting()  # Ignore result.
60                return i_machine
61            except dbus.exceptions.DBusException as e:
62                if ignore_error:
63                    return None
64                logging.debug(e)
65                raise mm1_proxy.ModemManager1ProxyError(
66                        'Failed to obtain a valid object for interactive '
67                        'state machine %s. DBus error: %s',
68                        machine_name,
69                        repr(e))
70
71        try:
72            utils.poll_for_condition(
73                lambda: _get_machine(True), timeout=timeout_seconds)
74        except utils.TimeoutError as e:
75            pass
76
77        return _get_machine(False)
78