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