xref: /aosp_15_r20/cts/hostsidetests/theme/android_device.py (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
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