blob: 4361f9b95bf902d915f019b18b6c3896e4ba4ce2 [file]
#!/usr/bin/env python
#
# Copyright (C) 2020 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import subprocess
import time
from threading import Timer
from vts.testcases.vndk import utils
SYSPROP_DEV_BOOTCOMPLETE = "dev.bootcomplete"
SYSPROP_SYS_BOOT_COMPLETED = "sys.boot_completed"
class Shell(object):
"""This class to wrap adb shell command."""
def __init__(self, serial_number):
self._serial_number = serial_number
def Execute(self, *args):
"""Executes a command.
Args:
args: Strings, the arguments.
Returns:
Stdout as a string, stderr as a string, and return code as an
integer.
"""
cmd = ["adb", "-s", self._serial_number, "shell"]
cmd.extend(args)
return RunCommand(cmd)
class ADB(object):
"""This class to wrap adb command."""
def __init__(self, serial_number):
self._serial_number = serial_number
def Execute(self, cmd_list, timeout=None):
"""Executes a command.
Args:
args: Strings, the arguments.
Returns:
Stdout as a string, stderr as a string, and return code as an
integer.
"""
cmd = ["adb", "-s", self._serial_number]
cmd.extend(cmd_list)
return RunCommand(cmd, timeout)
class AndroidDevice(utils.AndroidDevice):
"""This class controls the device via adb commands."""
def __init__(self, serial_number):
super(AndroidDevice, self).__init__(serial_number)
self._serial_number = serial_number
self.shell = Shell(serial_number)
self.adb = ADB(serial_number)
def GetPermission(self, filepath):
"""Get file permission."""
out, err, r_code = self.shell.Execute('stat -c %%a %s' % filepath)
if r_code != 0 or err.strip():
raise IOError("`stat -c %%a '%s'` stdout: %s\nstderr: %s" %
(filepath, out, err))
return out.strip()
def WaitForBootCompletion(self, timeout=None):
"""Get file permission."""
start = time.time()
cmd = ['wait-for-device']
self.adb.Execute(cmd, timeout)
while not self.isBootCompleted():
if time.time() - start >= timeout:
logging.error("Timeout while waiting for boot completion.")
return False
time.sleep(1)
return True
def isBootCompleted(self):
"""Checks whether the device has booted.
Returns:
True if booted, False otherwise.
"""
try:
if (self._GetProp(SYSPROP_SYS_BOOT_COMPLETED) == '1' and
self._GetProp(SYSPROP_DEV_BOOTCOMPLETE) == '1'):
return True
except Exception as e:
# adb shell calls may fail during certain period of booting
# process, which is normal. Ignoring these errors.
pass
return False
def IsShutdown(self, timeout=0):
"""Checks whether the device has booted.
Returns:
True if booted, False otherwise.
"""
start = time.time()
while (time.time() - start) <= timeout:
if not self.isBootCompleted():
return True
time.sleep(1)
return self.isBootCompleted()
def Root(self):
try:
self.adb.Execute(["root"])
RETRIES = 3
for i in range(RETRIES):
self.adb.Execute(["wait-for-device"])
# Verify that we haven't raced with the exit of the old,
# non-root adbd
out, err, r_code = self.shell.Execute("id -un")
if r_code == 0 and not err.strip() and out.strip() == "root":
return True
time.sleep(1)
except subprocess.CalledProcessError as e:
logging.exception(e)
return False
def ReadFileContent(self, filepath):
"""Read the content of a file and perform assertions.
Args:
filepath: string, path to file
Returns:
string, content of file
"""
cmd = "cat %s" % filepath
out, err, r_code = self.shell.Execute(cmd)
# checks the exit code
if r_code != 0 or err.strip():
raise IOError("%s: Error happened while reading the file due to %s."
% (filepath, err))
return out
def RunCommand(cmd, timeout=None):
kill = lambda process:process.kill()
proc = subprocess.Popen(args=cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
_timer = Timer(timeout, kill, [proc])
try:
_timer.start()
(out, err) = proc.communicate()
finally:
_timer.cancel()
try:
return out.decode('UTF-8'), err.decode('UTF-8'), proc.returncode
except UnicodeDecodeError:
# ProcUidCpuPowerTimeInStateTest, ProcUidCpuPowerConcurrentActiveTimeTest,
# and ProcUidCpuPowerConcurrentPolicyTimeTest output could not be decode
# to UTF-8.
return out.decode('ISO-8859-1'), err.decode('ISO-8859-1'), proc.returncode