1# Copyright 2016 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4# 5# This file contains things that are shared by arc.py and arc_util.py. 6 7import logging 8import subprocess 9import time 10 11from autotest_lib.client.bin import utils 12from autotest_lib.client.common_lib import error 13 14 15# Ask Chrome to start ARC instance and the script will block until ARC's boot 16# completed event. 17ARC_MODE_ENABLED = "enabled" 18# Similar to "enabled", except that it will not block. 19ARC_MODE_ENABLED_ASYNC = "enabled_async" 20# Ask Chrome to not start ARC instance. This is the default. 21ARC_MODE_DISABLED = "disabled" 22# All available ARC options. 23ARC_MODES = [ARC_MODE_ENABLED, ARC_MODE_ENABLED_ASYNC, ARC_MODE_DISABLED] 24 25_BOOT_CHECK_INTERVAL_SECONDS = 2 26_WAIT_FOR_ANDROID_BOOT_SECONDS = 120 27 28_VAR_LOGCAT_PATH = '/var/log/logcat' 29_VAR_LOGCAT_BOOT_PATH = '/var/log/logcat-boot' 30 31 32class Logcat(object): 33 """Saves the output of logcat to a file.""" 34 35 def __init__(self, path=_VAR_LOGCAT_PATH): 36 with open(path, 'w') as f: 37 self._proc = subprocess.Popen( 38 ['android-sh', '-c', 'logcat'], 39 stdout=f, 40 stderr=subprocess.STDOUT, 41 close_fds=True) 42 43 def __enter__(self): 44 """Support for context manager.""" 45 return self 46 47 def __exit__(self, *args): 48 """Support for context manager. 49 50 Calls close(). 51 """ 52 self.close() 53 54 def close(self): 55 """Stop the logcat process gracefully.""" 56 if not self._proc: 57 return 58 self._proc.terminate() 59 60 class TimeoutException(Exception): 61 """Termination timeout timed out.""" 62 63 try: 64 utils.poll_for_condition( 65 condition=lambda: self._proc.poll() is not None, 66 exception=TimeoutException, 67 timeout=10, 68 sleep_interval=0.1, 69 desc='Waiting for logcat to terminate') 70 except TimeoutException: 71 logging.info('Killing logcat due to timeout') 72 self._proc.kill() 73 self._proc.wait() 74 finally: 75 self._proc = None 76 77 78def wait_for_android_boot(timeout=None): 79 """Sleep until Android has completed booting or timeout occurs.""" 80 if timeout is None: 81 timeout = _WAIT_FOR_ANDROID_BOOT_SECONDS 82 83 def _is_container_started(): 84 return utils.system('android-sh -c true', ignore_status=True) == 0 85 86 def _is_android_booted(): 87 output = utils.system_output( 88 'android-sh -c "getprop sys.boot_completed"', ignore_status=True) 89 return output.strip() == '1' 90 91 logging.info('Waiting for Android to boot completely.') 92 93 start_time = time.time() 94 utils.poll_for_condition(condition=_is_container_started, 95 desc='Container has started', 96 timeout=timeout, 97 exception=error.TestFail('Android did not boot!'), 98 sleep_interval=_BOOT_CHECK_INTERVAL_SECONDS) 99 with Logcat(_VAR_LOGCAT_BOOT_PATH): 100 boot_timeout = timeout - (time.time() - start_time) 101 utils.poll_for_condition( 102 condition=_is_android_booted, 103 desc='Android has booted', 104 timeout=boot_timeout, 105 exception=error.TestFail('Android did not boot!'), 106 sleep_interval=_BOOT_CHECK_INTERVAL_SECONDS) 107 logging.info('Android has booted completely.') 108