xref: /aosp_15_r20/tools/acloud/internal/lib/adb_tools.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
1*800a58d9SAndroid Build Coastguard Worker# Copyright 2019 - The Android Open Source Project
2*800a58d9SAndroid Build Coastguard Worker#
3*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*800a58d9SAndroid Build Coastguard Worker#
7*800a58d9SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*800a58d9SAndroid Build Coastguard Worker#
9*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*800a58d9SAndroid Build Coastguard Worker# limitations under the License.
14*800a58d9SAndroid Build Coastguard Worker"""A tool that help to run adb to check device status."""
15*800a58d9SAndroid Build Coastguard Worker
16*800a58d9SAndroid Build Coastguard Workerimport re
17*800a58d9SAndroid Build Coastguard Workerimport subprocess
18*800a58d9SAndroid Build Coastguard Worker
19*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors
20*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants
21*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils
22*800a58d9SAndroid Build Coastguard Worker
23*800a58d9SAndroid Build Coastguard Worker_ADB_CONNECT = "connect"
24*800a58d9SAndroid Build Coastguard Worker_ADB_DEVICE = "devices"
25*800a58d9SAndroid Build Coastguard Worker_ADB_DISCONNECT = "disconnect"
26*800a58d9SAndroid Build Coastguard Worker_ADB_STATUS_DEVICE = "device"
27*800a58d9SAndroid Build Coastguard Worker_ADB_STATUS_DEVICE_ARGS = "-l"
28*800a58d9SAndroid Build Coastguard Worker_RE_ADB_DEVICE_INFO = (r"%s\s*(?P<adb_status>[\S]+)? ?"
29*800a58d9SAndroid Build Coastguard Worker                       r"(usb:(?P<usb>[\S]+))? ?"
30*800a58d9SAndroid Build Coastguard Worker                       r"(product:(?P<product>[\S]+))? ?"
31*800a58d9SAndroid Build Coastguard Worker                       r"(model:(?P<model>[\S]+))? ?"
32*800a58d9SAndroid Build Coastguard Worker                       r"(device:(?P<device>[\S]+))? ?"
33*800a58d9SAndroid Build Coastguard Worker                       r"(transport_id:(?P<transport_id>[\S]+))? ?")
34*800a58d9SAndroid Build Coastguard Worker_RE_SERIAL = r"(?P<ip>.+):(?P<port>.+)"
35*800a58d9SAndroid Build Coastguard Worker_DEVICE_ATTRIBUTES = ["adb_status", "usb", "product", "model", "device", "transport_id"]
36*800a58d9SAndroid Build Coastguard Worker_MAX_RETRIES_ON_WAIT_ADB_GONE = 5
37*800a58d9SAndroid Build Coastguard Worker#KEY_CODE 82 = KEY_MENU
38*800a58d9SAndroid Build Coastguard Worker_UNLOCK_SCREEN_KEYEVENT = ("%(adb_bin)s -s %(device_serial)s "
39*800a58d9SAndroid Build Coastguard Worker                           "shell input keyevent 82")
40*800a58d9SAndroid Build Coastguard Worker_WAIT_ADB_RETRY_BACKOFF_FACTOR = 1.5
41*800a58d9SAndroid Build Coastguard Worker_WAIT_ADB_SLEEP_MULTIPLIER = 2
42*800a58d9SAndroid Build Coastguard Worker
43*800a58d9SAndroid Build Coastguard Worker
44*800a58d9SAndroid Build Coastguard Workerclass AdbTools:
45*800a58d9SAndroid Build Coastguard Worker    """Adb tools.
46*800a58d9SAndroid Build Coastguard Worker
47*800a58d9SAndroid Build Coastguard Worker    Attributes:
48*800a58d9SAndroid Build Coastguard Worker        _adb_command: String, combine adb commands then execute it.
49*800a58d9SAndroid Build Coastguard Worker        _adb_port: Integer, Specified adb port to establish connection.
50*800a58d9SAndroid Build Coastguard Worker        _device_address: String, the device's host and port for adb to connect
51*800a58d9SAndroid Build Coastguard Worker                         to. For example, adb connect 127.0.0.1:5555.
52*800a58d9SAndroid Build Coastguard Worker        _device_serial: String, adb device's serial number. The value can be
53*800a58d9SAndroid Build Coastguard Worker                        different from _device_address. For example,
54*800a58d9SAndroid Build Coastguard Worker                        adb -s emulator-5554 shell.
55*800a58d9SAndroid Build Coastguard Worker        _device_information: Dict, will be added to adb information include usb,
56*800a58d9SAndroid Build Coastguard Worker                            product model, device and transport_id
57*800a58d9SAndroid Build Coastguard Worker    """
58*800a58d9SAndroid Build Coastguard Worker    _adb_command = None
59*800a58d9SAndroid Build Coastguard Worker
60*800a58d9SAndroid Build Coastguard Worker    def __init__(self, adb_port=None, device_serial=""):
61*800a58d9SAndroid Build Coastguard Worker        """Initialize.
62*800a58d9SAndroid Build Coastguard Worker
63*800a58d9SAndroid Build Coastguard Worker        Args:
64*800a58d9SAndroid Build Coastguard Worker            adb_port: String of adb port number.
65*800a58d9SAndroid Build Coastguard Worker            device_serial: String, adb device's serial number.
66*800a58d9SAndroid Build Coastguard Worker        """
67*800a58d9SAndroid Build Coastguard Worker        self._adb_port = adb_port
68*800a58d9SAndroid Build Coastguard Worker        self._device_address = ""
69*800a58d9SAndroid Build Coastguard Worker        self._device_serial = ""
70*800a58d9SAndroid Build Coastguard Worker        self._SetDeviceSerial(device_serial)
71*800a58d9SAndroid Build Coastguard Worker        self._device_information = {}
72*800a58d9SAndroid Build Coastguard Worker        self._CheckAdb()
73*800a58d9SAndroid Build Coastguard Worker        self._GetAdbInformation()
74*800a58d9SAndroid Build Coastguard Worker
75*800a58d9SAndroid Build Coastguard Worker    def _SetDeviceSerial(self, device_serial):
76*800a58d9SAndroid Build Coastguard Worker        """Set device serial and address.
77*800a58d9SAndroid Build Coastguard Worker
78*800a58d9SAndroid Build Coastguard Worker        Args:
79*800a58d9SAndroid Build Coastguard Worker            device_serial: String, the device's serial number. If this
80*800a58d9SAndroid Build Coastguard Worker                           argument is empty, the serial number is set to the
81*800a58d9SAndroid Build Coastguard Worker                           network address.
82*800a58d9SAndroid Build Coastguard Worker        """
83*800a58d9SAndroid Build Coastguard Worker        if device_serial:
84*800a58d9SAndroid Build Coastguard Worker            match = re.match(_RE_SERIAL, device_serial)
85*800a58d9SAndroid Build Coastguard Worker            if match:
86*800a58d9SAndroid Build Coastguard Worker                self._adb_port = match.group("port")
87*800a58d9SAndroid Build Coastguard Worker                self._device_address = device_serial
88*800a58d9SAndroid Build Coastguard Worker                self._device_serial = device_serial
89*800a58d9SAndroid Build Coastguard Worker                return
90*800a58d9SAndroid Build Coastguard Worker        self._device_address = ("127.0.0.1:%s" % self._adb_port if
91*800a58d9SAndroid Build Coastguard Worker                                self._adb_port else "")
92*800a58d9SAndroid Build Coastguard Worker        self._device_serial = (device_serial if device_serial else
93*800a58d9SAndroid Build Coastguard Worker                               self._device_address)
94*800a58d9SAndroid Build Coastguard Worker
95*800a58d9SAndroid Build Coastguard Worker    @classmethod
96*800a58d9SAndroid Build Coastguard Worker    def _CheckAdb(cls):
97*800a58d9SAndroid Build Coastguard Worker        """Find adb bin path.
98*800a58d9SAndroid Build Coastguard Worker
99*800a58d9SAndroid Build Coastguard Worker        Raises:
100*800a58d9SAndroid Build Coastguard Worker            errors.NoExecuteCmd: Can't find the execute adb bin.
101*800a58d9SAndroid Build Coastguard Worker        """
102*800a58d9SAndroid Build Coastguard Worker        if cls._adb_command:
103*800a58d9SAndroid Build Coastguard Worker            return
104*800a58d9SAndroid Build Coastguard Worker        cls._adb_command = utils.FindExecutable(constants.ADB_BIN)
105*800a58d9SAndroid Build Coastguard Worker        if not cls._adb_command:
106*800a58d9SAndroid Build Coastguard Worker            raise errors.NoExecuteCmd("Can't find the adb command.")
107*800a58d9SAndroid Build Coastguard Worker
108*800a58d9SAndroid Build Coastguard Worker    def GetAdbConnectionStatus(self):
109*800a58d9SAndroid Build Coastguard Worker        """Get Adb connect status.
110*800a58d9SAndroid Build Coastguard Worker
111*800a58d9SAndroid Build Coastguard Worker        Check if self._adb_port is null (ssh tunnel is broken).
112*800a58d9SAndroid Build Coastguard Worker
113*800a58d9SAndroid Build Coastguard Worker        Returns:
114*800a58d9SAndroid Build Coastguard Worker            String, the result of adb connection.
115*800a58d9SAndroid Build Coastguard Worker        """
116*800a58d9SAndroid Build Coastguard Worker        if not self._adb_port:
117*800a58d9SAndroid Build Coastguard Worker            return None
118*800a58d9SAndroid Build Coastguard Worker
119*800a58d9SAndroid Build Coastguard Worker        return self._device_information["adb_status"]
120*800a58d9SAndroid Build Coastguard Worker
121*800a58d9SAndroid Build Coastguard Worker    def _GetAdbInformation(self):
122*800a58d9SAndroid Build Coastguard Worker        """Get Adb connect information.
123*800a58d9SAndroid Build Coastguard Worker
124*800a58d9SAndroid Build Coastguard Worker        1. Check adb devices command to get the connection information.
125*800a58d9SAndroid Build Coastguard Worker
126*800a58d9SAndroid Build Coastguard Worker        2. Gather information include usb, product model, device and transport_id
127*800a58d9SAndroid Build Coastguard Worker        when the attached field is device.
128*800a58d9SAndroid Build Coastguard Worker
129*800a58d9SAndroid Build Coastguard Worker        e.g.
130*800a58d9SAndroid Build Coastguard Worker            Case 1:
131*800a58d9SAndroid Build Coastguard Worker            List of devices attached
132*800a58d9SAndroid Build Coastguard Worker            127.0.0.1:48451 device product:aosp_cf model:Cuttlefish device:vsoc_x86 transport_id:147
133*800a58d9SAndroid Build Coastguard Worker            _device_information = {"adb_status":"device",
134*800a58d9SAndroid Build Coastguard Worker                                   "usb":None,
135*800a58d9SAndroid Build Coastguard Worker                                   "product":"aosp_cf",
136*800a58d9SAndroid Build Coastguard Worker                                   "model":"Cuttlefish",
137*800a58d9SAndroid Build Coastguard Worker                                   "device":"vsoc_x86",
138*800a58d9SAndroid Build Coastguard Worker                                   "transport_id":"147"}
139*800a58d9SAndroid Build Coastguard Worker
140*800a58d9SAndroid Build Coastguard Worker            Case 2:
141*800a58d9SAndroid Build Coastguard Worker            List of devices attached
142*800a58d9SAndroid Build Coastguard Worker            127.0.0.1:48451 offline
143*800a58d9SAndroid Build Coastguard Worker            _device_information = {"adb_status":"offline",
144*800a58d9SAndroid Build Coastguard Worker                                   "usb":None,
145*800a58d9SAndroid Build Coastguard Worker                                   "product":None,
146*800a58d9SAndroid Build Coastguard Worker                                   "model":None,
147*800a58d9SAndroid Build Coastguard Worker                                   "device":None,
148*800a58d9SAndroid Build Coastguard Worker                                   "transport_id":None}
149*800a58d9SAndroid Build Coastguard Worker
150*800a58d9SAndroid Build Coastguard Worker            Case 3:
151*800a58d9SAndroid Build Coastguard Worker            List of devices attached
152*800a58d9SAndroid Build Coastguard Worker            _device_information = {"adb_status":None,
153*800a58d9SAndroid Build Coastguard Worker                                   "usb":None,
154*800a58d9SAndroid Build Coastguard Worker                                   "product":None,
155*800a58d9SAndroid Build Coastguard Worker                                   "model":None,
156*800a58d9SAndroid Build Coastguard Worker                                   "device":None,
157*800a58d9SAndroid Build Coastguard Worker                                   "transport_id":None}
158*800a58d9SAndroid Build Coastguard Worker        """
159*800a58d9SAndroid Build Coastguard Worker        adb_cmd = [self._adb_command, _ADB_DEVICE, _ADB_STATUS_DEVICE_ARGS]
160*800a58d9SAndroid Build Coastguard Worker        device_info = utils.CheckOutput(adb_cmd)
161*800a58d9SAndroid Build Coastguard Worker        self._device_information = {
162*800a58d9SAndroid Build Coastguard Worker            attribute: None for attribute in _DEVICE_ATTRIBUTES}
163*800a58d9SAndroid Build Coastguard Worker
164*800a58d9SAndroid Build Coastguard Worker        for device in device_info.splitlines():
165*800a58d9SAndroid Build Coastguard Worker            match = re.match(_RE_ADB_DEVICE_INFO % self._device_serial, device)
166*800a58d9SAndroid Build Coastguard Worker            if match:
167*800a58d9SAndroid Build Coastguard Worker                self._device_information = {
168*800a58d9SAndroid Build Coastguard Worker                    attribute: match.group(attribute) if match.group(attribute)
169*800a58d9SAndroid Build Coastguard Worker                               else None for attribute in _DEVICE_ATTRIBUTES}
170*800a58d9SAndroid Build Coastguard Worker
171*800a58d9SAndroid Build Coastguard Worker    @classmethod
172*800a58d9SAndroid Build Coastguard Worker    def GetDeviceSerials(cls):
173*800a58d9SAndroid Build Coastguard Worker        """Get the serial numbers of connected devices."""
174*800a58d9SAndroid Build Coastguard Worker        cls._CheckAdb()
175*800a58d9SAndroid Build Coastguard Worker        adb_cmd = [cls._adb_command, _ADB_DEVICE]
176*800a58d9SAndroid Build Coastguard Worker        device_info = utils.CheckOutput(adb_cmd)
177*800a58d9SAndroid Build Coastguard Worker        serials = []
178*800a58d9SAndroid Build Coastguard Worker        # Skip the first line which is "List of devices attached". Each of the
179*800a58d9SAndroid Build Coastguard Worker        # following lines consists of the serial number, a tab character, and
180*800a58d9SAndroid Build Coastguard Worker        # the state. The last line is empty.
181*800a58d9SAndroid Build Coastguard Worker        for line in device_info.splitlines()[1:]:
182*800a58d9SAndroid Build Coastguard Worker            serial_state = line.split()
183*800a58d9SAndroid Build Coastguard Worker            if len(serial_state) > 1:
184*800a58d9SAndroid Build Coastguard Worker                serials.append(serial_state[0])
185*800a58d9SAndroid Build Coastguard Worker        return serials
186*800a58d9SAndroid Build Coastguard Worker
187*800a58d9SAndroid Build Coastguard Worker    def IsAdbConnectionAlive(self):
188*800a58d9SAndroid Build Coastguard Worker        """Check devices connect alive.
189*800a58d9SAndroid Build Coastguard Worker
190*800a58d9SAndroid Build Coastguard Worker        Returns:
191*800a58d9SAndroid Build Coastguard Worker            Boolean, True if adb status is device. False otherwise.
192*800a58d9SAndroid Build Coastguard Worker        """
193*800a58d9SAndroid Build Coastguard Worker        return self.GetAdbConnectionStatus() == _ADB_STATUS_DEVICE
194*800a58d9SAndroid Build Coastguard Worker
195*800a58d9SAndroid Build Coastguard Worker    def IsAdbConnected(self):
196*800a58d9SAndroid Build Coastguard Worker        """Check devices connected or not.
197*800a58d9SAndroid Build Coastguard Worker
198*800a58d9SAndroid Build Coastguard Worker        If adb connected and the status is device or offline, return True.
199*800a58d9SAndroid Build Coastguard Worker        If there is no any connection, return False.
200*800a58d9SAndroid Build Coastguard Worker
201*800a58d9SAndroid Build Coastguard Worker        Returns:
202*800a58d9SAndroid Build Coastguard Worker            Boolean, True if adb status not none. False otherwise.
203*800a58d9SAndroid Build Coastguard Worker        """
204*800a58d9SAndroid Build Coastguard Worker        return self.GetAdbConnectionStatus() is not None
205*800a58d9SAndroid Build Coastguard Worker
206*800a58d9SAndroid Build Coastguard Worker    def _DisconnectAndRaiseError(self):
207*800a58d9SAndroid Build Coastguard Worker        """Disconnect adb.
208*800a58d9SAndroid Build Coastguard Worker
209*800a58d9SAndroid Build Coastguard Worker        Disconnect from the device's network address if it shows up in adb
210*800a58d9SAndroid Build Coastguard Worker        devices. For example, adb disconnect 127.0.0.1:5555.
211*800a58d9SAndroid Build Coastguard Worker
212*800a58d9SAndroid Build Coastguard Worker        Raises:
213*800a58d9SAndroid Build Coastguard Worker            errors.WaitForAdbDieError: adb is alive after disconnect adb.
214*800a58d9SAndroid Build Coastguard Worker        """
215*800a58d9SAndroid Build Coastguard Worker        try:
216*800a58d9SAndroid Build Coastguard Worker            if self.IsAdbConnected():
217*800a58d9SAndroid Build Coastguard Worker                adb_disconnect_args = [self._adb_command,
218*800a58d9SAndroid Build Coastguard Worker                                       _ADB_DISCONNECT,
219*800a58d9SAndroid Build Coastguard Worker                                       self._device_address]
220*800a58d9SAndroid Build Coastguard Worker                subprocess.check_call(adb_disconnect_args)
221*800a58d9SAndroid Build Coastguard Worker                # check adb device status
222*800a58d9SAndroid Build Coastguard Worker                self._GetAdbInformation()
223*800a58d9SAndroid Build Coastguard Worker                if self.IsAdbConnected():
224*800a58d9SAndroid Build Coastguard Worker                    raise errors.AdbDisconnectFailed(
225*800a58d9SAndroid Build Coastguard Worker                        "adb disconnect failed, device is still connected and "
226*800a58d9SAndroid Build Coastguard Worker                        "has status: [%s]" % self.GetAdbConnectionStatus())
227*800a58d9SAndroid Build Coastguard Worker
228*800a58d9SAndroid Build Coastguard Worker        except subprocess.CalledProcessError:
229*800a58d9SAndroid Build Coastguard Worker            utils.PrintColorString("Failed to adb disconnect %s" %
230*800a58d9SAndroid Build Coastguard Worker                                   self._device_address,
231*800a58d9SAndroid Build Coastguard Worker                                   utils.TextColors.FAIL)
232*800a58d9SAndroid Build Coastguard Worker
233*800a58d9SAndroid Build Coastguard Worker    def DisconnectAdb(self, retry=False):
234*800a58d9SAndroid Build Coastguard Worker        """Retry to disconnect adb.
235*800a58d9SAndroid Build Coastguard Worker
236*800a58d9SAndroid Build Coastguard Worker        When retry=True, this method will retry to disconnect adb until adb
237*800a58d9SAndroid Build Coastguard Worker        device is completely gone.
238*800a58d9SAndroid Build Coastguard Worker
239*800a58d9SAndroid Build Coastguard Worker        Args:
240*800a58d9SAndroid Build Coastguard Worker            retry: Boolean, True to retry disconnect on error.
241*800a58d9SAndroid Build Coastguard Worker        """
242*800a58d9SAndroid Build Coastguard Worker        retry_count = _MAX_RETRIES_ON_WAIT_ADB_GONE if retry else 0
243*800a58d9SAndroid Build Coastguard Worker        # Wait for adb device is reset and gone.
244*800a58d9SAndroid Build Coastguard Worker        utils.RetryExceptionType(exception_types=errors.AdbDisconnectFailed,
245*800a58d9SAndroid Build Coastguard Worker                                 max_retries=retry_count,
246*800a58d9SAndroid Build Coastguard Worker                                 functor=self._DisconnectAndRaiseError,
247*800a58d9SAndroid Build Coastguard Worker                                 sleep_multiplier=_WAIT_ADB_SLEEP_MULTIPLIER,
248*800a58d9SAndroid Build Coastguard Worker                                 retry_backoff_factor=
249*800a58d9SAndroid Build Coastguard Worker                                 _WAIT_ADB_RETRY_BACKOFF_FACTOR)
250*800a58d9SAndroid Build Coastguard Worker
251*800a58d9SAndroid Build Coastguard Worker    def ConnectAdb(self):
252*800a58d9SAndroid Build Coastguard Worker        """Connect adb.
253*800a58d9SAndroid Build Coastguard Worker
254*800a58d9SAndroid Build Coastguard Worker        Connect adb to the device's network address if the connection is not
255*800a58d9SAndroid Build Coastguard Worker        alive. For example, adb connect 127.0.0.1:5555.
256*800a58d9SAndroid Build Coastguard Worker        """
257*800a58d9SAndroid Build Coastguard Worker        try:
258*800a58d9SAndroid Build Coastguard Worker            if not self.IsAdbConnectionAlive():
259*800a58d9SAndroid Build Coastguard Worker                adb_connect_args = [self._adb_command,
260*800a58d9SAndroid Build Coastguard Worker                                    _ADB_CONNECT,
261*800a58d9SAndroid Build Coastguard Worker                                    self._device_address]
262*800a58d9SAndroid Build Coastguard Worker                subprocess.check_call(adb_connect_args)
263*800a58d9SAndroid Build Coastguard Worker        except subprocess.CalledProcessError:
264*800a58d9SAndroid Build Coastguard Worker            utils.PrintColorString("Failed to adb connect %s" %
265*800a58d9SAndroid Build Coastguard Worker                                   self._device_address,
266*800a58d9SAndroid Build Coastguard Worker                                   utils.TextColors.FAIL)
267*800a58d9SAndroid Build Coastguard Worker
268*800a58d9SAndroid Build Coastguard Worker    def AutoUnlockScreen(self):
269*800a58d9SAndroid Build Coastguard Worker        """Auto unlock screen.
270*800a58d9SAndroid Build Coastguard Worker
271*800a58d9SAndroid Build Coastguard Worker        Auto unlock screen after invoke vnc client.
272*800a58d9SAndroid Build Coastguard Worker        """
273*800a58d9SAndroid Build Coastguard Worker        try:
274*800a58d9SAndroid Build Coastguard Worker            adb_unlock_args = _UNLOCK_SCREEN_KEYEVENT % {
275*800a58d9SAndroid Build Coastguard Worker                "adb_bin": self._adb_command,
276*800a58d9SAndroid Build Coastguard Worker                "device_serial": self._device_serial}
277*800a58d9SAndroid Build Coastguard Worker            subprocess.check_call(adb_unlock_args.split())
278*800a58d9SAndroid Build Coastguard Worker        except subprocess.CalledProcessError:
279*800a58d9SAndroid Build Coastguard Worker            utils.PrintColorString("Failed to unlock screen."
280*800a58d9SAndroid Build Coastguard Worker                                   "(adb_port: %s)" % self._adb_port,
281*800a58d9SAndroid Build Coastguard Worker                                   utils.TextColors.WARNING)
282*800a58d9SAndroid Build Coastguard Worker
283*800a58d9SAndroid Build Coastguard Worker    def EmuCommand(self, *args):
284*800a58d9SAndroid Build Coastguard Worker        """Send an emulator command to the device.
285*800a58d9SAndroid Build Coastguard Worker
286*800a58d9SAndroid Build Coastguard Worker        Args:
287*800a58d9SAndroid Build Coastguard Worker            args: List of strings, the emulator command.
288*800a58d9SAndroid Build Coastguard Worker
289*800a58d9SAndroid Build Coastguard Worker        Returns:
290*800a58d9SAndroid Build Coastguard Worker            Integer, the return code of the adb command.
291*800a58d9SAndroid Build Coastguard Worker            The return code is 0 if adb successfully sends the command to
292*800a58d9SAndroid Build Coastguard Worker            emulator. It is irrelevant to the result of the command.
293*800a58d9SAndroid Build Coastguard Worker        """
294*800a58d9SAndroid Build Coastguard Worker        adb_cmd = [self._adb_command, "-s", self._device_serial, "emu"]
295*800a58d9SAndroid Build Coastguard Worker        adb_cmd.extend(args)
296*800a58d9SAndroid Build Coastguard Worker        proc = subprocess.Popen(adb_cmd, stdin=subprocess.PIPE,
297*800a58d9SAndroid Build Coastguard Worker                                stdout=subprocess.PIPE,
298*800a58d9SAndroid Build Coastguard Worker                                stderr=subprocess.PIPE)
299*800a58d9SAndroid Build Coastguard Worker        proc.communicate()
300*800a58d9SAndroid Build Coastguard Worker        return proc.returncode
301*800a58d9SAndroid Build Coastguard Worker
302*800a58d9SAndroid Build Coastguard Worker    @property
303*800a58d9SAndroid Build Coastguard Worker    def device_information(self):
304*800a58d9SAndroid Build Coastguard Worker        """Return the device information."""
305*800a58d9SAndroid Build Coastguard Worker        return self._device_information
306