1*b7c941bbSAndroid Build Coastguard Worker#!/usr/bin/python3 2*b7c941bbSAndroid Build Coastguard Worker# 3*b7c941bbSAndroid Build Coastguard Worker# Copyright (C) 2015 The Android Open Source Project 4*b7c941bbSAndroid Build Coastguard Worker# 5*b7c941bbSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the 'License'); 6*b7c941bbSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*b7c941bbSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*b7c941bbSAndroid Build Coastguard Worker# 9*b7c941bbSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*b7c941bbSAndroid Build Coastguard Worker# 11*b7c941bbSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*b7c941bbSAndroid Build Coastguard Worker# distributed under the License is distributed on an 'AS IS' BASIS, 13*b7c941bbSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*b7c941bbSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*b7c941bbSAndroid Build Coastguard Worker# limitations under the License. 16*b7c941bbSAndroid Build Coastguard Worker# 17*b7c941bbSAndroid Build Coastguard Worker 18*b7c941bbSAndroid Build Coastguard Workerimport os 19*b7c941bbSAndroid Build Coastguard Workerimport re 20*b7c941bbSAndroid Build Coastguard Workerimport subprocess 21*b7c941bbSAndroid Build Coastguard Workerimport sys 22*b7c941bbSAndroid Build Coastguard Workerimport threading 23*b7c941bbSAndroid Build Coastguard Workerimport time 24*b7c941bbSAndroid Build Coastguard Worker 25*b7c941bbSAndroid Build Coastguard Workerfrom subprocess import PIPE 26*b7c941bbSAndroid Build Coastguard Worker 27*b7c941bbSAndroid Build Coastguard Worker 28*b7c941bbSAndroid Build Coastguard Worker# class for running android device from python 29*b7c941bbSAndroid Build Coastguard Worker# it will fork the device processor 30*b7c941bbSAndroid Build Coastguard Workerclass AndroidDevice(object): 31*b7c941bbSAndroid Build Coastguard Worker def __init__(self, serial): 32*b7c941bbSAndroid Build Coastguard Worker self._serial = serial 33*b7c941bbSAndroid Build Coastguard Worker 34*b7c941bbSAndroid Build Coastguard Worker def run_adb_command(self, cmd, timeout=None): 35*b7c941bbSAndroid Build Coastguard Worker adb_cmd = "adb -s %s %s" % (self._serial, cmd) 36*b7c941bbSAndroid Build Coastguard Worker print(adb_cmd) 37*b7c941bbSAndroid Build Coastguard Worker 38*b7c941bbSAndroid Build Coastguard Worker adb_process = subprocess.Popen(args=adb_cmd.split(), bufsize=-1, stderr=PIPE, stdout=PIPE) 39*b7c941bbSAndroid Build Coastguard Worker (out, err) = adb_process.communicate(timeout=timeout) 40*b7c941bbSAndroid Build Coastguard Worker return out.decode('utf-8').strip(), err.decode('utf-8').strip() 41*b7c941bbSAndroid Build Coastguard Worker 42*b7c941bbSAndroid Build Coastguard Worker def run_shell_command(self, cmd): 43*b7c941bbSAndroid Build Coastguard Worker return self.run_adb_command("shell %s" % cmd) 44*b7c941bbSAndroid Build Coastguard Worker 45*b7c941bbSAndroid Build Coastguard Worker def wait_for_device(self, timeout=30): 46*b7c941bbSAndroid Build Coastguard Worker return self.run_adb_command('wait-for-device', timeout) 47*b7c941bbSAndroid Build Coastguard Worker 48*b7c941bbSAndroid Build Coastguard Worker def wait_for_prop(self, key, value, timeout=30): 49*b7c941bbSAndroid Build Coastguard Worker boot_complete = False 50*b7c941bbSAndroid Build Coastguard Worker attempts = 0 51*b7c941bbSAndroid Build Coastguard Worker wait_period = 1 52*b7c941bbSAndroid Build Coastguard Worker while not boot_complete and (attempts*wait_period) < timeout: 53*b7c941bbSAndroid Build Coastguard Worker (out, err) = self.run_shell_command("getprop %s" % key) 54*b7c941bbSAndroid Build Coastguard Worker if out == value: 55*b7c941bbSAndroid Build Coastguard Worker boot_complete = True 56*b7c941bbSAndroid Build Coastguard Worker else: 57*b7c941bbSAndroid Build Coastguard Worker time.sleep(wait_period) 58*b7c941bbSAndroid Build Coastguard Worker attempts += 1 59*b7c941bbSAndroid Build Coastguard Worker if not boot_complete: 60*b7c941bbSAndroid Build Coastguard Worker print("%s not set to %s within timeout!" % (key, value)) 61*b7c941bbSAndroid Build Coastguard Worker return boot_complete 62*b7c941bbSAndroid Build Coastguard Worker 63*b7c941bbSAndroid Build Coastguard Worker def wait_for_service(self, name, timeout=30): 64*b7c941bbSAndroid Build Coastguard Worker service_found = False 65*b7c941bbSAndroid Build Coastguard Worker attempts = 0 66*b7c941bbSAndroid Build Coastguard Worker wait_period = 1 67*b7c941bbSAndroid Build Coastguard Worker while not service_found and (attempts*wait_period) < timeout: 68*b7c941bbSAndroid Build Coastguard Worker (output, err) = self.run_shell_command("service check %s" % name) 69*b7c941bbSAndroid Build Coastguard Worker if 'not found' not in output: 70*b7c941bbSAndroid Build Coastguard Worker service_found = True 71*b7c941bbSAndroid Build Coastguard Worker else: 72*b7c941bbSAndroid Build Coastguard Worker time.sleep(wait_period) 73*b7c941bbSAndroid Build Coastguard Worker attempts += 1 74*b7c941bbSAndroid Build Coastguard Worker if not service_found: 75*b7c941bbSAndroid Build Coastguard Worker print("Service '%s' not found within timeout!" % name) 76*b7c941bbSAndroid Build Coastguard Worker return service_found 77*b7c941bbSAndroid Build Coastguard Worker 78*b7c941bbSAndroid Build Coastguard Worker def wait_for_boot_complete(self, timeout=60): 79*b7c941bbSAndroid Build Coastguard Worker return self.wait_for_prop('dev.bootcomplete', '1', timeout) 80*b7c941bbSAndroid Build Coastguard Worker 81*b7c941bbSAndroid Build Coastguard Worker def install_apk(self, apk_path): 82*b7c941bbSAndroid Build Coastguard Worker self.wait_for_service('package') 83*b7c941bbSAndroid Build Coastguard Worker (out, err) = self.run_adb_command("install -r -d -g %s" % apk_path) 84*b7c941bbSAndroid Build Coastguard Worker result = out.split() 85*b7c941bbSAndroid Build Coastguard Worker return out, err, "Success" in result 86*b7c941bbSAndroid Build Coastguard Worker 87*b7c941bbSAndroid Build Coastguard Worker def uninstall_package(self, package): 88*b7c941bbSAndroid Build Coastguard Worker self.wait_for_service('package') 89*b7c941bbSAndroid Build Coastguard Worker (out, err) = self.run_adb_command("uninstall %s" % package) 90*b7c941bbSAndroid Build Coastguard Worker result = out.split() 91*b7c941bbSAndroid Build Coastguard Worker return "Success" in result 92*b7c941bbSAndroid Build Coastguard Worker 93*b7c941bbSAndroid Build Coastguard Worker def run_instrumentation_test(self, option): 94*b7c941bbSAndroid Build Coastguard Worker self.wait_for_service('activity') 95*b7c941bbSAndroid Build Coastguard Worker return self.run_shell_command("am instrument -w --no-window-animation %s" % option) 96*b7c941bbSAndroid Build Coastguard Worker 97*b7c941bbSAndroid Build Coastguard Worker def is_process_alive(self, process_name): 98*b7c941bbSAndroid Build Coastguard Worker (out, err) = self.run_shell_command("ps") 99*b7c941bbSAndroid Build Coastguard Worker names = out.split() 100*b7c941bbSAndroid Build Coastguard Worker # very lazy implementation as it does not filter out things like uid 101*b7c941bbSAndroid Build Coastguard Worker # should work mostly unless processName is too simple to overlap with 102*b7c941bbSAndroid Build Coastguard Worker # uid. So only use name like com.android.xyz 103*b7c941bbSAndroid Build Coastguard Worker return process_name in names 104*b7c941bbSAndroid Build Coastguard Worker 105*b7c941bbSAndroid Build Coastguard Worker def get_version_sdk(self): 106*b7c941bbSAndroid Build Coastguard Worker return int(self.run_shell_command("getprop ro.build.version.sdk")[0]) 107*b7c941bbSAndroid Build Coastguard Worker 108*b7c941bbSAndroid Build Coastguard Worker def get_version_codename(self): 109*b7c941bbSAndroid Build Coastguard Worker return self.run_shell_command("getprop ro.build.version.codename")[0].strip() 110*b7c941bbSAndroid Build Coastguard Worker 111*b7c941bbSAndroid Build Coastguard Worker def get_density(self): 112*b7c941bbSAndroid Build Coastguard Worker if "emulator" in self._serial: 113*b7c941bbSAndroid Build Coastguard Worker return int(self.run_shell_command("getprop qemu.sf.lcd_density")[0]) 114*b7c941bbSAndroid Build Coastguard Worker else: 115*b7c941bbSAndroid Build Coastguard Worker return int(self.run_shell_command("getprop ro.sf.lcd_density")[0]) 116*b7c941bbSAndroid Build Coastguard Worker 117*b7c941bbSAndroid Build Coastguard Worker def get_orientation(self): 118*b7c941bbSAndroid Build Coastguard Worker return int(self.run_shell_command("dumpsys | grep SurfaceOrientation")[0].split()[1]) 119*b7c941bbSAndroid Build Coastguard Worker 120*b7c941bbSAndroid Build Coastguard Worker 121*b7c941bbSAndroid Build Coastguard Workerdef enumerate_android_devices(require_prefix=''): 122*b7c941bbSAndroid Build Coastguard Worker devices = subprocess.check_output(["adb", "devices"]) 123*b7c941bbSAndroid Build Coastguard Worker if not devices: 124*b7c941bbSAndroid Build Coastguard Worker return [] 125*b7c941bbSAndroid Build Coastguard Worker 126*b7c941bbSAndroid Build Coastguard Worker devices = devices.decode('UTF-8').split('\n')[1:] 127*b7c941bbSAndroid Build Coastguard Worker device_list = [] 128*b7c941bbSAndroid Build Coastguard Worker 129*b7c941bbSAndroid Build Coastguard Worker for device in devices: 130*b7c941bbSAndroid Build Coastguard Worker if device != "" and device.startswith(require_prefix): 131*b7c941bbSAndroid Build Coastguard Worker info = device.split('\t') 132*b7c941bbSAndroid Build Coastguard Worker if info[1] == "device": 133*b7c941bbSAndroid Build Coastguard Worker device_list.append(info[0]) 134*b7c941bbSAndroid Build Coastguard Worker 135*b7c941bbSAndroid Build Coastguard Worker return device_list 136