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