15bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Copyright (C) 2016 The Android Open Source Project
25bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond#
35bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Licensed under the Apache License, Version 2.0 (the "License");
45bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# you may not use this file except in compliance with the License.
55bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# You may obtain a copy of the License at
65bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond#
75bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond#      http://www.apache.org/licenses/LICENSE-2.0
85bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond#
95bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Unless required by applicable law or agreed to in writing, software
105bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# distributed under the License is distributed on an "AS IS" BASIS,
115bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# See the License for the specific language governing permissions and
135bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# limitations under the License.
145bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond
15dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo'''Module that contains the class UtilAndroid, providing utility method to
16dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leointerface with Android ADB.'''
17dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
18a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondfrom __future__ import absolute_import
19a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
20dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport logging
21dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport re
22dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport subprocess
23dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport time
24dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport collections
25dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport multiprocessing
26a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondtry:
27a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    # Python 3
28a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    import queue
29a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondexcept ImportError:
30a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    import Queue as queue
31a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
32a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondfrom .exception import TestSuiteException
33dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom . import util_log
34dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
35dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
36dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoclass UtilAndroid(object):
37dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''Provides some utility methods that interface with Android using adb.'''
38dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    # pylint: disable=too-many-public-methods
39dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
40dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def __init__(self, adb_path, lldb_server_path_device, device):
41dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # The path to the adb binary on the local machine
42dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._path_adb = adb_path
43dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # The path to the lldb server binary on the device
44dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._path_lldbserver = lldb_server_path_device
45dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._log = util_log.get_logger()
46dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.device = device
47dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._prop_stacks = collections.defaultdict(list)
48dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return
49dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
50dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    @staticmethod
51dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _validate_string(string):
52dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Check that a string is valid and not empty.
53dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
54dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
55dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            string: The string to be checked.
56dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
57dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        assert isinstance(string, str)
58dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        assert len(string) > 0
59dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
60dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def adb(self, args, async=False, device=True, timeout=None):
61dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Run an adb command (async optional).
62dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
63dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
64dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            args: The command (including arguments) to run in adb.
65dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            async: Boolean to specify whether adb should run the command
66dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                   asynchronously.
67dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            device: boolean to specify whether the serial id of the android
68dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    device should be inserted in the adb command.
69dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            timeout: it specifies the number of seconds to wait for
70dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                     a synchronous invocation before aborting. If unspecified or
71dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                     None it waits indefinitely for the command to complete.
72dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
73dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
74dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            ValueError: it can be caused by any of the following situations:
75dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                        - when both the combination async=True and timeout are
76dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                          given.
77dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                        - when a timeout <= 0 is specified.
78dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
79dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
80dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            If adb was synchronously run and the command completed by the
81dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            specified timeout, a string which is the output (standard out and
82dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            error) from adb. Otherwise it returns None.
83dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
84dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
85dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # Form the command
86dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if device:
87dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            cmd = '{0} -s {1} {2}'.format(self._path_adb, self.device, args)
88dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        else:
89dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            cmd = '{0} {1}'.format(self._path_adb, args)
90dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
91dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._log.debug('Execute ADB: %s', cmd)
92dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
93dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if timeout is None:
94dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            # local invocation
95dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return_code, output = UtilAndroid._execute_command_local(cmd, async)
96dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
97dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        else:
98dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            # remote invocation
99dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if async:
100dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                raise ValueError('Invalid combination: asynchronous invocation '
101dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                 'with timeout specified')
102dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
103dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return_code, output = UtilAndroid._execute_command_remote(cmd,
104dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                                                      timeout)
105dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
106dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if return_code is None:
107dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                self._log.warn('[ADB] The command timed out: %s', cmd)
108dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
109dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # log the output message
110dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if output is not None:
111dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._adb_log_output(cmd, output, return_code)
112dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
113dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return output
114dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
115dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def adb_retry(self, args, max_num_attempts, timeout):
116dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Attempt to execute the given adb command a certain number of times.
117dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
118dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        The function executes the given command through adb, waiting for its
119dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        completion up to 'timeout' seconds. If the command completes then it
120dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        returns its output. Otherwise it aborts the execution of the adb
121dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        command and re-issues it anew with the same parameters. In case of
122dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        timeout this process is repeated up to 'max_num_attempts'.
123dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
124dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        The purpose of this function is to handle the cases when, for some
125dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        reason, a command sent to 'adb' freezes, blocking the whole test suite
126dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        indefinitely.
127dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
128dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
129dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            args: The command (including arguments) to run in adb.
130dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            max_num_attempts: the max number of attempts to repeat the command
131dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                              in case of timeout.
132dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            timeout: it specifies the number of seconds to wait for the adb
133dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                     command to complete.
134dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
135dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
136dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            ValueError: when the parameter timeout is invalid (None or <= 0).
137dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
138dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
139dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            If adb was synchronously run and the command completes by the
140dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            specified timeout, a string which is the output (standard out and
141dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            error) from adb. Otherwise it returns None.
142dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
143dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if timeout is None or timeout <= 0:
144dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            raise ValueError('Invalid value for timeout')
145dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
146dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        output = None
147dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
148dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        for attempt in range(max_num_attempts):
149dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._log.debug('[ADB] Attempt #%d: %s', attempt + 1, args)
150dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            output = self.adb(args, False, True, timeout)
151dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if output:
152dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                break
153dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
154dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return output
155dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
156dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _adb_log_output(self, cmd, output, return_code):
157dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Save in the log the command & output from `adb`.
158dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
159dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Internal function, helper to record in the log the issued adb command
160dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        together with its output and return code.
161dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
162dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Params:
163dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            cmd: string, the command issued to `adb`.
164dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            output: string, the output retrieved from `adb`.
165dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return_code: int, the return code from `adb`.
166dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
167dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
168dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        message = output.strip()
169dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
170dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # if return_code != 0, we wish to also record the command executed
171dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # (which occurs if and only if we are in verbose mode)
172dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        is_warning = return_code != 0
173dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        threshold = self._log.getEffectiveLevel()
174dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if is_warning and threshold > logging.DEBUG:
175dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._log.warn("[ADB] Command executed: {0}".format(cmd))
176dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
177dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        level = logging.WARNING if is_warning else logging.DEBUG
178dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if message:
179dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            # if message is composed by multiple lines, then print it after
180dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            # the log preamble
181dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if re.search('\n', message):
182dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                message = '\n' + message
183dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        else:
184dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            message = '<empty>'
185dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
186dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._log.log(level, 'RC: {0}, Output: {1}'.format(return_code,
187dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                                           message))
188dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
189dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def check_adb_alive(self):
190dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Ping the device and raise an exception in case of timeout.
191dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
192dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        It sends a ping message through 'adb shell'. The emulator/device should
193dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        echo the same message back by one minute. If it does not, it raises
194dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        a TestSuiteException.
195dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
196dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Purpose of this method is to check whether 'adb' became frozen or
197dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        stuck.
198dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
199dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
200dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            TestSuiteException: in case the device/emulator does not reply by
201dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                one minute or the `ping' message is not echoed
202dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                back.
203dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
204dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        token = 'PING'
205dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        log = util_log.get_logger()
206dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        cmd = "echo {0}".format(token)
207dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
208dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        tries = 10
209dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        try_number = tries
210dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        while try_number > 0:
211dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            log.debug('Sending a ping through "adb shell" (try #%s)...',
212dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                      try_number)
213dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            output = self.shell(cmd, False, 60)
214dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
215dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if output is None:
216dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                raise TestSuiteException(
217dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    'Timeout when pinging the device/emulator through '
218dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    '"adb shell".  Is "adb" stuck or dead?')
219dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            elif token not in output:
220dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                log.debug('Ping failed. Cannot match the token "%s" in "adb '
221dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                          'shell %s"', token, cmd)
222dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            else:
223dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                log.debug('Pong message received')
224dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                return
225dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
226dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            try_number -= 1
227dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            time.sleep(5)
228dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
229dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        raise TestSuiteException('Cannot ping the device/emulator through '
230dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                 '"adb shell". Tried %s times. Is "adb" stuck '
231dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                 'or dead?' % tries)
232dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
233dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def shell(self, cmd, async=False, timeout=None):
234dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Run a command via the adb shell.
235dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
236dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
237dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            cmd: The command (including arguments) to run in the adb shell.
238dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            async: Boolean to specify whether adb should run the command
239dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                   asynchronously.
240dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            timeout: it specifies the number of seconds to wait for
241dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                     a synchronous invocation before aborting. If unspecified or
242dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                     None it waits indefinitely for the command to complete
243dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
244dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
245dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            If adb was synchronously run, a string which is the output (standard
246dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            out and error) from adb. Otherwise None.
247dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
248dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return self.adb('shell "{0}"'.format(cmd), async, True, timeout)
249dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
250dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def find_app_pid(self, process_name):
251dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Find the process ID of a process with a given name.
252dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
253dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        If more than one instance of the process is running return the first pid
254dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        it finds.
255dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
256dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
257dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            process_name: A string representing the name of the package or
258dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                          binary for which the id should be found. I.e. the
259dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                          string or part of the string that shows up in the "ps"
260dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                          command.
261dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
262dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
263dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            An integer representing the id of the process, or None if it was not
264dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            found.
265dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
266dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._validate_string(process_name)
267dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
268dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        pid_output = self.shell('pidof ' + process_name)
269dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        pid_output = re.sub(r'\*.+\*', '', pid_output)
270dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        pids = pid_output.split()
271dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
272dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if len(pids) < 1:
273dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._log.warn('Unable to find pid of: {0}'.format(process_name))
274dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return None
275dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
276dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if len(pids) > 1:
277dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._log.warn('Found multiple instances of {0} running: {1}'
278dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                           .format(process_name, pids))
279dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
280dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        try:
281dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            pid = int(pids[0])
282dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._log.info('App pid found: {0}'.format(pids[0]))
283dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return pid
284dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        except ValueError:
285dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return None
286dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
287dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def adb_root(self):
288dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Set adb to be in root mode.'''
289dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.adb('root')
290dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
291dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _adb_remount(self):
292dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Remount the filesystem of the device.'''
293dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.adb('remount')
294dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
295dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def validate_adb(self):
296dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Validate adb that it can be run.
297dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
298dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
299dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            TestSuiteException: Unable to validate that adb exists and runs
300dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                successfully.
301dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
302dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        out = self.adb('version', False, False)
303dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if out and 'Android' in out and 'version' in out:
304dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._log.info('adb found: {0}'.format(out))
305dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return None
306dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        raise TestSuiteException('unable to validate adb')
307dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
308dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def is_booted(self):
309dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        ''' Check if the device/emulator has finished booting.
310dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
311dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns: True if the property sys.boot_completed is true, False
312dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                 otherwise.
313dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
314dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return self._get_prop('sys.boot_completed').strip() == '1'
315dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
316dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def validate_device(self, check_boot=True, device_substring=''):
317dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Validate that there is at least one device.
318dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
319dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
320dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            check_boot: Boolean to specify whether to check whether the device
321dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                        has finished booting as well as being present.
322dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            device_substring: String that needs to be part of the name of the
323dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                              device.
324dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
325dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
326dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            TestSuiteException: There was a failure to run adb to list the
327dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                devices or there is no device connected or
328dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                multiple devices connected without the user
329dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                having specified the device to use.
330dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
331dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
332dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        out = self.adb('devices', False, False)
333dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if not 'List of devices attached' in out:
334dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            raise TestSuiteException('Unable to list devices')
335dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
336dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        lines = out.split('\n')
337dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        found_device = False # True if the specified device is found
338dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        devices = []
339dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
340dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        for line in lines[1:]:
341dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if '\tdevice' in line and device_substring in line:
342dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                device = line.split()[0]
343dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                devices.append(device)
344dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                if self.device:
345dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    if self.device == device:
346dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                        found_device = True
347dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
348dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if len(devices) == 0:
349dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            raise TestSuiteException('adb is unable to find a connected '
350dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                     'device/emulator to test.')
351dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
352dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if not self.device:
353dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if len(devices) == 1:
354dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                self.device = devices[0]
355dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            else:
356dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                raise TestSuiteException('Multiple devices connected,'
357dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                         'specify -d device id.')
358dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        else:
359dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if not found_device:
360dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                raise TestSuiteException('Couldn\'t find the device {0} that '
361dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                         'was specified, please check -d '
362dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                         'argument'.format(self.device))
363dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
364dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if check_boot and not self.is_booted():
365dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            raise TestSuiteException(
366dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                'The device {0} has not yet finished booting.'
367dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                .format(self.device))
368dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
369dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def device_with_substring_exists(self, device_substring):
370dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Check whether a device exists whose name contains a given string.
371dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
372dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
373dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            device_substring: String that is part of the name of the device to
374dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                              look for.
375dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
376dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
377dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            TestSuiteException: There was a failure to run adb to list the
378dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                devices.
379dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
380dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        out = self.adb('devices', False, False)
381dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if not 'List of devices attached' in out:
382dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            raise TestSuiteException('Unable to list devices')
383dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
384dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        lines = out.split('\n')
385dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
386dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        for line in lines[1:]:
387dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if '\tdevice' in line:
388dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                device = line.split()[0]
389dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                if device.find(device_substring) != -1:
390dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    return True
391dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
392dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return False
393dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
394dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def get_device_id(self):
395dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Return ID of the device that will be used for running the tests on.
396dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
397dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
398dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            String representing device ID.
399dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
400dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return self.device
401dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
402dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _kill_pid(self, pid):
403dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Kill a process identified by its pid by issuing a "kill" command.
404dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
405dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
406dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            pid: The integer that is the process id of the process to be killed.
407dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
408dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.shell('kill -9 ' + str(pid))
409dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
410dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def stop_app(self, package_name):
411dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Terminate an app by calling am force-stop.
412dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
413dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
414dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            package_name: The string representing the name of the package of the
415dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                          app that is to be stopped.
416dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
417dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._validate_string(package_name)
418dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.shell('am force-stop ' + package_name)
419dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
420dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def kill_process(self, name):
421dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Kill a process identified by its name (package name in case of apk).
422dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
423dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Issues the "kill" command.
424dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
425dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
426dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            name: The string representing the name of the binary of the process
427dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                  that is to be killed.
428dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
429dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
430dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            True if the kill command was executed, False if it could not be
431dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            found.
432dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
433dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        pid = self.find_app_pid(name)
434dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if pid:
435dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._kill_pid(pid)
436dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return True
437dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return False
438dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
439dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def kill_all_processes(self, name):
440dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Repeatedly try to call "kill" on a process to ensure it is gone.
441dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
442dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        If the process is still there after 5 attempts reboot the device.
443dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
444dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
445dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            name: The string representing the name of the binary of the process
446dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                  that is to be killed.
447dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
448dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
449dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            TestSuiteException: If the process could not be killed after 5
450dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                attempts and the device then failed to boot
451dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                after rebooting.
452dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
453dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
454dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # try 5 times to kill this process
455dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        for _ in range(1, 5):
456dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if not self.kill_process(name):
457dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                return
458dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # stalled process must reboot
459dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._reboot_device()
460dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
461dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def kill_servers(self):
462dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Kill all gdbserver and lldb-server instances.
463dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
464dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
465dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            TestSuiteException: If gdbserver or lldb-server could not be killed
466dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                after 5 attempts and the device then failed to
467dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                boot after rebooting.
468dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
469dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.kill_all_processes('gdbserver')
470dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.kill_all_processes('lldb-server')
471dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
472dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def launch_elf(self, binary_name):
473dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Launch a binary (compiled with the NDK).
474dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
475dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
476dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            binary_name: The string representing the name of the binary that is
477dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                         to be launched.
478dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
479dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
480dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            Boolean, failure if the app is not installed, success otherwise.
481dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
482dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # Ensure the apk is actually installed.
483dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        output = self.shell('ls /data/ | grep ' + binary_name)
484dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if binary_name not in output:
485dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return False
486dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
487dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        stdout = self.shell('exec /data/' + binary_name, True)
488dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._log.info(str(stdout))
489dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
490dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return True
491dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
492dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def wait_for_device(self):
493dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Ask ADB to wait for a device to become ready.'''
494dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.adb('wait-for-device')
495dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
496dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _reboot_device(self):
497dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Reboot the remote device.
498dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
499dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Raises:
500dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            TestSuiteException: If the device failed to boot after rebooting.
501dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
502dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.adb('reboot')
503dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.wait_for_device()
504dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # Allow 20  mins boot time to give emulators such as MIPS enough time
505dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        sleeping_countdown = 60*20
506dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        while not self.is_booted():
507dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            time.sleep(1)
508dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            sleeping_countdown -= 1
509dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if sleeping_countdown == 0:
510dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                raise TestSuiteException('Failed to reboot. Terminating.')
511dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
512dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.adb_root()
513dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.wait_for_device()
514dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._adb_remount()
515dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.wait_for_device()
516dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
517dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def launch_app(self, name, activity):
518dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Launch a Renderscript application.
519dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
520dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
521dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            name: The string representing the name of the app that is to be
522dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                  launched.
523dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            activity: The string representing the activity of the app that is to
524dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                      be started.
525dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
526dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
527dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            Boolean, failure if the apk is not installed, success otherwise.
528dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
529dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        assert name and activity
530dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
531dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # Ensure the apk is actually installed.
532dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        output = self.shell('pm list packages ' + name)
533dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if not output:
534dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return False
535dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
536a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        cmd = 'am start -S -W {0}/{0}.{1}'.format(name, activity)
537dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        stdout = self.shell(cmd)
538dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
539dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._log.info(str(stdout))
540dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
541dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return True
542dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
543dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def launch_lldb_platform(self, port):
544dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Launch lldb server and attach to target app.
545dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
546dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
547dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            port: The integer that is the port on which lldb should listen.
548dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
549ea7cbdf5a4f4f987969ca2200ab590b8a4482a54I-Jui (Ray) Sung        cmd = "export LLDB_DEBUGSERVER_PATH='{0}';{0} p --listen *:{1}"\
550dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            .format(self._path_lldbserver, port)
551dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.shell(cmd, True)
552dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        time.sleep(5)
553dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
554dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def forward_port(self, local, remote):
555dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Use adb to forward a device port onto the local machine.
556dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
557dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
558dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            local: The integer that is the local port to forward.
559dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            remote: The integer that is the remote port to which to forward.
560dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
561dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        cmd = 'forward tcp:%s tcp:%s' % (str(local), str(remote))
562dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.adb(cmd)
563dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
564dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def remove_port_forwarding(self):
565dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Remove all of the forward socket connections open in adb.
566dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
567dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Avoids a windows adb error where we can't bind to a listener
568dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        because too many files are open.
569dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
570dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.adb('forward --remove-all')
571dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
572dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _get_prop(self, name):
573dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Get the value of an Android system property.
574dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
575dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
576dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            name: Name of the property of interest [string].
577dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
578dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
579dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            Current value of the property [string].
580dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
581dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return self.shell('getprop %s' % str(name))
582dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
583dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _set_prop(self, name, value):
584dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Set the value of an Android system property.
585dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
586dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
587dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            name: Name of the property of interest [string].
588dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            value: Desired new value for the property [string or integer].
589dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
590dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.shell("setprop %s '%s'" % (str(name), str(value)))
591dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
592dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def push_prop(self, name, new_value):
593dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Save the value of an Android system property and set a new value.
594dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
595dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Saves the old value onto a stack so it can be restored later.
596dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
597dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
598dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            name: Name of the property of interest [string].
599dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            new_value: Desired new value for the property [string or integer].
600dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
601dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        old_value = self._get_prop(name)
602dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._set_prop(name, new_value)
603dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._prop_stacks[name].append(old_value.strip())
604dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
605dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def pop_prop(self, name):
606dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Restore the value of an Android system property previously set by
607dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        push_prop.
608dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
609dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
610dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            name: Name of the property of interest [string].
611dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
612dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
613dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            Current value of the property [string].
614dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
615dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        old_value = self._prop_stacks[name].pop()
616dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._set_prop(name, old_value)
617dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
618dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def reset_all_props(self):
619dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Restore all the android properties to the state before the first push
620dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
621dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        This is equivalent to popping each property the number of times it has
622dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        been pushed.
623dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
624dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        for name in self._prop_stacks:
625dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if self._prop_stacks[name] != []:
626dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                self._set_prop(name, self._prop_stacks[name][0])
627dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                self._prop_stacks[name] = []
628dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
629dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def make_device_writeable(self):
630dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        ''' Ensure the device is full writable, in particular the system folder.
631dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
632dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        This disables verity and remounts.
633dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
634dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        output = self.adb('disable-verity')
635dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
636dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # if the remote is an emulator do not even try to reboot
637dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # otherwise check whether a reboot is advised
638dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if (self._get_prop('ro.kernel.qemu') != '1' and output and
639dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                'Now reboot your device for settings to take effect' in output):
640dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            self._reboot_device()
641dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
642dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self._adb_remount()
643dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.wait_for_device()
644dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.adb_root()
645dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        self.wait_for_device()
646dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
647dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    @staticmethod
648dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _execute_command_local(command, async=False):
649dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Execute the given shell command in the same process.
650dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
651dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
652dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            command: String, the command to execute
653dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            async: Boolean to specify whether adb should run the command
654dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                   asynchronously.
655dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
656dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
657dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            if async == False, it returns a tuple with the return code and
658dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            the output from the executed command. Otherwise the tuple
659dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            (None, None).
660dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
661dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        proc = subprocess.Popen(command,
662dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                stdout=subprocess.PIPE,
663dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                stderr=subprocess.STDOUT,
664dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                                shell=True)
665dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if async:
666dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return None, None
667dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
668dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # read the whole output from the command
669dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        with proc.stdout as file_proc:
670dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            output = ''.join(line for line in file_proc)
671dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
672dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # release the process state
673dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        proc.terminate()
674dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return_code = proc.wait()
675dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
676dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return return_code, output
677dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
678dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    @staticmethod
679dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def _execute_command_remote(command, timeout):
680dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''Execute the given shell command remotely, in a separate process.
681dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
682dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        It spawns an ad hoc process to execute the given command. It waits up
683dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        to timeout for the command to complete, otherwise it aborts the
684dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        execution and returns None.
685dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
686dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Args:
687dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            command: String, the command to execute.
688dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            timeout: the number of seconds to wait for the command to complete.
689dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
690dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        Returns:
691dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            a pair with the return code and the output from the command, if it
692dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            completed by the specified 'timeout' seconds. Otherwise the tuple
693dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            (None, None).
694dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''
695dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
696dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        channel = multiprocessing.Queue()
697dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        proc = multiprocessing.Process(
698dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            target=_handle_remote_request,
699dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            name="Executor of `{0}'".format(command),
700dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            args=(command, channel)
701dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        )
702dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
703dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # execute the command
704dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        proc.start()
705dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return_code = None
706dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        output = None
707dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
708dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # wait for the result
709dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        try:
710dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return_code, output = channel.get(True, timeout)
711a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        except queue.Empty:
712dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            # timeout hit, the remote process has not fulfilled our request by
713dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            # the given time. We are going to return <None, None>, nothing to
714dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            # do here as it already holds return_code = output = None.
715dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            pass
716dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
717dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # terminate the helper process
718dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        proc.terminate()
719dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
720dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return return_code, output
721dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
722dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
723dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef _handle_remote_request(command, channel):
724dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''Entry point for the remote process.
725dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
726dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    It executes the given command and reports the result into the channel.
727dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    This function is supposed to be only called by
728dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    UtilAndroid._execute_command_remote to handle the inter-process
729dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    communication.
730dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
731dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Args:
732dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        command: the command to execute.
733dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        channel: the channel to communicate with the caller process.
734dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
735dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    channel.put(UtilAndroid._execute_command_local(command))
736dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
737