def InitShell(self, device=None): ''' Runs adb as root, and installs the apk as needed. |device| is the target device to run on, if multiple devices are connected. Returns 0 on success or a non-zero exit code on a terminal failure. ''' try: devices = device_utils.DeviceUtils.HealthyDevices() if device: self.device = next((d for d in devices if d == device), None) if not self.device: raise device_errors.DeviceUnreachableError(device) elif devices: self.device = devices[0] else: raise device_errors.NoDevicesError() logging.getLogger().debug('Using device: %s', self.device) # Clean the logs on the device to avoid displaying prior activity. subprocess.check_call(self._CreateADBCommand(['logcat', '-c'])) self.device.EnableRoot() self.device.Install(self.paths.apk_path) except base_error.BaseError as e: # Report 'device not found' as infra failures. See http://crbug.com/493900 print 'Exception in AndroidShell.InitShell:\n%s' % str(e) if e.is_infra_error or 'error: device not found' in str(e): return constants.INFRA_EXIT_CODE return constants.ERROR_EXIT_CODE return 0
def SetUp(self): available_devices = device_utils.DeviceUtils.HealthyDevices( self._blacklist, enable_device_files_cache=self._enable_device_cache) if not available_devices: raise device_errors.NoDevicesError if self._device_serial: self._devices = [ d for d in available_devices if d.adb.GetDeviceSerial() == self._device_serial ] if not self._devices: raise device_errors.DeviceUnreachableError( 'Could not find device %r' % self._device_serial) else: self._devices = available_devices if self._enable_device_cache: for d in self._devices: cache_path = _DeviceCachePath(d) if os.path.exists(cache_path): logging.info('Using device cache: %s', cache_path) with open(cache_path) as f: d.LoadCacheData(f.read()) os.unlink(cache_path)
def _GetAttachedDevices(blacklist_file, test_device): """Get all attached devices. Args: test_device: Name of a specific device to use. Returns: A list of attached devices. """ blacklist = (device_blacklist.Blacklist(blacklist_file) if blacklist_file else None) attached_devices = device_utils.DeviceUtils.HealthyDevices(blacklist) if test_device: test_device = [d for d in attached_devices if d == test_device] if not test_device: raise device_errors.DeviceUnreachableError( 'Did not find device %s among attached device. Attached devices: %s' % (test_device, ', '.join(attached_devices))) return test_device else: if not attached_devices: raise device_errors.NoDevicesError() return sorted(attached_devices)
def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None, check_error=True, cpu_affinity=None, ensure_logs_on_timeout=True): timeout = timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime() if ensure_logs_on_timeout and timeout: timeout = 0.95 * timeout try: status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout( cls._BuildAdbCmd(args, device_serial, cpu_affinity=cpu_affinity), timeout, env=cls._ADB_ENV) except OSError as e: if e.errno in (errno.ENOENT, errno.ENOEXEC): raise device_errors.NoAdbError(msg=str(e)) else: raise # Best effort to catch errors from adb; unfortunately adb is very # inconsistent with error reporting so many command failures present # differently. if status != 0 or (check_error and output.startswith('error:')): not_found_m = _DEVICE_NOT_FOUND_RE.match(output) device_waiting_m = _WAITING_FOR_DEVICE_RE.match(output) if (device_waiting_m is not None or (not_found_m is not None and not_found_m.group('serial') == device_serial)): raise device_errors.DeviceUnreachableError(device_serial) else: raise device_errors.AdbCommandFailedError( args, output, status, device_serial) return output
def SetUp(self): available_devices = device_utils.DeviceUtils.HealthyDevices( self._blacklist, enable_device_files_cache=self._enable_device_cache) if not available_devices: raise device_errors.NoDevicesError if self._device_serial: self._devices = [d for d in available_devices if d.adb.GetDeviceSerial() == self._device_serial] if not self._devices: raise device_errors.DeviceUnreachableError( 'Could not find device %r' % self._device_serial) else: self._devices = available_devices if self._enable_device_cache: for d in self._devices: cache_path = _DeviceCachePath(d) if os.path.exists(cache_path): logging.info('Using device cache: %s', cache_path) with open(cache_path) as f: d.LoadCacheData(f.read()) os.unlink(cache_path) if self._logcat_output_dir: for d in self._devices: logcat_file = os.path.join( self._logcat_output_dir, '%s_%s' % (d.adb.GetDeviceSerial(), datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%S'))) monitor = logcat_monitor.LogcatMonitor( d.adb, clear=True, output_file=logcat_file) self._logcat_monitors.append(monitor) monitor.Start()
def _GetAttachedDevices(blacklist_file, test_device, enable_cache, num_retries): """Get all attached devices. Args: blacklist_file: Path to device blacklist. test_device: Name of a specific device to use. enable_cache: Whether to enable checksum caching. Returns: A list of attached devices. """ blacklist = (device_blacklist.Blacklist(blacklist_file) if blacklist_file else None) attached_devices = device_utils.DeviceUtils.HealthyDevices( blacklist, enable_device_files_cache=enable_cache, default_retries=num_retries) if test_device: test_device = [d for d in attached_devices if d == test_device] if not test_device: raise device_errors.DeviceUnreachableError( 'Did not find device %s among attached device. Attached devices: %s' % (test_device, ', '.join(attached_devices))) return test_device else: if not attached_devices: raise device_errors.NoDevicesError() return sorted(attached_devices)
def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None, check_error=True, cpu_affinity=None): # pylint: disable=no-member try: status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout( cls._BuildAdbCmd(args, device_serial, cpu_affinity=cpu_affinity), timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime()) except OSError as e: if e.errno in (errno.ENOENT, errno.ENOEXEC): raise device_errors.NoAdbError(msg=str(e)) else: raise # Best effort to catch errors from adb; unfortunately adb is very # inconsistent with error reporting so many command failures present # differently. if status != 0 or (check_error and output.startswith('error:')): m = _DEVICE_NOT_FOUND_RE.match(output) if m is not None and m.group('serial') == device_serial: raise device_errors.DeviceUnreachableError(device_serial) else: raise device_errors.AdbCommandFailedError( args, output, status, device_serial) return output
def ProvisionDevices(args): blacklist = (device_blacklist.Blacklist(args.blacklist_file) if args.blacklist_file else None) devices = [ d for d in device_utils.DeviceUtils.HealthyDevices(blacklist) if not args.emulators or d.adb.is_emulator ] if args.device: devices = [d for d in devices if d == args.device] if not devices: raise device_errors.DeviceUnreachableError(args.device) parallel_devices = device_utils.DeviceUtils.parallel(devices) if args.emulators: parallel_devices.pMap(SetProperties, args) else: parallel_devices.pMap(ProvisionDevice, blacklist, args) if args.auto_reconnect: _LaunchHostHeartbeat() blacklisted_devices = blacklist.Read() if blacklist else [] if args.output_device_blacklist: with open(args.output_device_blacklist, 'w') as f: json.dump(blacklisted_devices, f) if all(d in blacklisted_devices for d in devices): raise device_errors.NoDevicesError return 0
def main(argv): parser = optparse.OptionParser(usage='Usage: %prog [options] device_port ' 'host_port [device_port_2 host_port_2] ...', description=__doc__) parser.add_option('-v', '--verbose', dest='verbose_count', default=0, action='count', help='Verbose level (multiple times for more)') parser.add_option('--device', help='Serial number of device we should use.') parser.add_option('--blacklist-file', help='Device blacklist JSON file.') parser.add_option('--debug', action='store_const', const='Debug', dest='build_type', default='Release', help='Use Debug build of host tools instead of Release.') options, args = parser.parse_args(argv) run_tests_helper.SetLogLevel(options.verbose_count) devil_chromium.Initialize() if len(args) < 2 or not len(args) % 2: parser.error('Need even number of port pairs') sys.exit(1) try: port_pairs = [int(a) for a in args[1:]] port_pairs = zip(port_pairs[::2], port_pairs[1::2]) except ValueError: parser.error('Bad port number') sys.exit(1) blacklist = (device_blacklist.Blacklist(options.blacklist_file) if options.blacklist_file else None) devices = device_utils.DeviceUtils.HealthyDevices(blacklist) if options.device: device = next((d for d in devices if d == options.device), None) if not device: raise device_errors.DeviceUnreachableError(options.device) elif devices: device = devices[0] logging.info('No device specified. Defaulting to %s', devices[0]) else: raise device_errors.NoDevicesError() constants.SetBuildType(options.build_type) try: forwarder.Forwarder.Map(port_pairs, device) while True: time.sleep(60) except KeyboardInterrupt: sys.exit(0) finally: forwarder.Forwarder.UnmapAllDevicePorts(device)
def main(): # Parse options. parser = optparse.OptionParser(description=__doc__, usage='screenshot.py [options] [filename]') parser.add_option('-d', '--device', metavar='ANDROID_DEVICE', help='Serial ' 'number of Android device to use.', default=None) parser.add_option('--blacklist-file', help='Device blacklist JSON file.') parser.add_option('-f', '--file', help='Save result to file instead of ' 'generating a timestamped file name.', metavar='FILE') parser.add_option('-v', '--verbose', help='Verbose logging.', action='store_true') video_options = optparse.OptionGroup(parser, 'Video capture') video_options.add_option('--video', help='Enable video capturing. Requires ' 'Android KitKat or later', action='store_true') video_options.add_option('-b', '--bitrate', help='Bitrate in megabits/s, ' 'from 0.1 to 100 mbps, %default mbps by default.', default=4, type='float') video_options.add_option('-r', '--rotate', help='Rotate video by 90 degrees.', default=False, action='store_true') video_options.add_option('-s', '--size', metavar='WIDTHxHEIGHT', help='Frame size to use instead of the device ' 'screen size.', default=None) parser.add_option_group(video_options) (options, args) = parser.parse_args() if len(args) > 1: parser.error('Too many positional arguments.') host_file = args[0] if args else options.file if options.verbose: logging.getLogger().setLevel(logging.DEBUG) blacklist = (device_blacklist.Blacklist(options.blacklist_file) if options.blacklist_file else None) devices = device_utils.DeviceUtils.HealthyDevices(blacklist) if options.device: device = next((d for d in devices if d == options.device), None) if not device: raise device_errors.DeviceUnreachableError(options.device) else: if len(devices) > 1: parser.error('Multiple devices are attached. ' 'Please specify device serial number with --device.') elif len(devices) == 1: device = devices[0] else: raise device_errors.NoDevicesError() if options.video: _CaptureVideo(device, host_file, options) else: _CaptureScreenshot(device, host_file) return 0
def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None, check_error=True, cpu_affinity=None, additional_env=None): if timeout: remaining = timeout_retry.CurrentTimeoutThreadGroup( ).GetRemainingTime() if remaining: # Use a slightly smaller timeout than remaining time to ensure that we # have time to collect output from the command. timeout = 0.95 * remaining else: timeout = None env = cls._ADB_ENV.copy() if additional_env: env.update(additional_env) try: adb_cmd = cls._BuildAdbCmd(args, device_serial, cpu_affinity=cpu_affinity) status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout( adb_cmd, timeout, env=env) except OSError as e: if e.errno in (errno.ENOENT, errno.ENOEXEC): raise device_errors.NoAdbError(msg=str(e)) else: raise except cmd_helper.TimeoutError: logger.error('Timeout on adb command: %r', adb_cmd) raise # Best effort to catch errors from adb; unfortunately adb is very # inconsistent with error reporting so many command failures present # differently. if status != 0 or (check_error and output.startswith('error:')): not_found_m = _DEVICE_NOT_FOUND_RE.search(output) device_waiting_m = _WAITING_FOR_DEVICE_RE.match(output) if (device_waiting_m is not None or (not_found_m is not None and not_found_m.group('serial') == device_serial)): raise device_errors.DeviceUnreachableError(device_serial) else: raise device_errors.AdbCommandFailedError( args, output, status, device_serial) return output
def SetUp(self): available_devices = device_utils.DeviceUtils.HealthyDevices( self._blacklist) if not available_devices: raise device_errors.NoDevicesError if self._device_serial: self._devices = [ d for d in available_devices if d.adb.GetDeviceSerial() == self._device_serial ] if not self._devices: raise device_errors.DeviceUnreachableError( 'Could not find device %r' % self._device_serial) else: self._devices = available_devices
def reset_android_usb(serial): """Reset the USB device for the given Android device.""" lsusb_info = lsusb.lsusb() bus = None device = None for device_info in lsusb_info: device_serial = lsusb.get_lsusb_serial(device_info) if device_serial == serial: bus = int(device_info.get('bus')) device = int(device_info.get('device')) if bus and device: reset_usb(bus, device) else: raise device_errors.DeviceUnreachableError( 'Unable to determine bus or device for device %s' % serial)
def GetDevices(requested_devices, blacklist_file): blacklist = (device_blacklist.Blacklist(blacklist_file) if blacklist_file else None) devices = device_utils.DeviceUtils.HealthyDevices(blacklist) if not devices: raise device_errors.NoDevicesError() elif requested_devices: requested = set(requested_devices) available = set(str(d) for d in devices) missing = requested.difference(available) if missing: raise device_errors.DeviceUnreachableError(next(iter(missing))) return sorted( device_utils.DeviceUtils(d) for d in available.intersection(requested)) else: return devices
def reset_android_usb(serial): """Reset the USB presentation.device for the given Android presentation.device.""" lsusb_info = lsusb.lsusb() bus = None presentation.device = None for device_info in lsusb_info: device_serial = lsusb.get_lsusb_serial(device_info) if device_serial == serial: bus = int(device_info.get('bus')) presentation.device = int(device_info.get('presentation.device')) if bus and presentation.device: reset_usb(bus, presentation.device) else: raise device_errors.DeviceUnreachableError( 'Unable to determine bus(%s) or presentation.device(%s) for presentation.device %s' % (bus, presentation.device, serial))
def GetDevices(requested_devices, denylist_file): """Gets a list of healthy devices matching the given parameters.""" if not isinstance(denylist_file, device_denylist.Denylist): denylist_file = (device_denylist.Denylist(denylist_file) if denylist_file else None) devices = device_utils.DeviceUtils.HealthyDevices(denylist_file) if not devices: raise device_errors.NoDevicesError() elif requested_devices: requested = set(requested_devices) available = set(str(d) for d in devices) missing = requested.difference(available) if missing: raise device_errors.DeviceUnreachableError(next(iter(missing))) return sorted( device_utils.DeviceUtils(d) for d in available.intersection(requested)) else: return devices
def _TestSetUp(self, test): if not self._device.IsOnline(): msg = 'Device %s is unresponsive.' % str(self._device) raise device_errors.DeviceUnreachableError(msg) logging.info('Charge level: %s%%', str(self._battery.GetBatteryInfo().get('level'))) if self._test_instance.min_battery_level: self._battery.ChargeDeviceToLevel(self._test_instance.min_battery_level) logging.info('temperature: %s (0.1 C)', str(self._battery.GetBatteryInfo().get('temperature'))) if self._test_instance.max_battery_temp: self._battery.LetBatteryCoolToTemperature( self._test_instance.max_battery_temp) if not self._device.IsScreenOn(): self._device.SetScreen(True) super(DeviceTestShard, self)._TestSetUp(test)
def _RunTestsFromQueue(runner, collection, out_results, watcher, num_retries, tag_results_with_device=False): """Runs tests from the collection until empty using the given runner. Adds TestRunResults objects to the out_results list and may add tests to the out_retry list. Args: runner: A TestRunner object used to run the tests. collection: A TestCollection from which to get _Test objects to run. out_results: A list to add TestRunResults to. watcher: A watchdog_timer.WatchdogTimer object, used as a shared timeout. num_retries: Number of retries for a test. tag_results_with_device: If True, appends the name of the device on which the test was run to the test name. Used when replicating to identify which device ran each copy of the test, and to ensure each copy of the test is recorded separately. """ def TagTestRunResults(test_run_results): """Tags all results with the last 4 digits of the device id. Used when replicating tests to distinguish the same tests run on different devices. We use a set to store test results, so the hash (generated from name and tag) must be unique to be considered different results. """ new_test_run_results = base_test_result.TestRunResults() for test_result in test_run_results.GetAll(): test_result.SetName('%s_%s' % (runner.device_serial[-4:], test_result.GetName())) new_test_run_results.AddResult(test_result) return new_test_run_results for test in collection: watcher.Reset() try: if not runner.device.IsOnline(): # Device is unresponsive, stop handling tests on this device. msg = 'Device %s is unresponsive.' % runner.device_serial logging.warning(msg) raise device_errors.DeviceUnreachableError(msg) result, retry = runner.RunTest(test.test) if tag_results_with_device: result = TagTestRunResults(result) test.tries += 1 if retry and test.tries <= num_retries: # Retry non-passing results, only record passing results. pass_results = base_test_result.TestRunResults() pass_results.AddResults(result.GetPass()) out_results.append(pass_results) logging.warning('Will retry test %s, try #%s.', retry, test.tries) collection.add(_Test(test=retry, tries=test.tries)) else: # All tests passed or retry limit reached. Either way, record results. out_results.append(result) except: # An unhandleable exception, ensure tests get run by another device and # reraise this exception on the main thread. collection.add(test) raise finally: # Retries count as separate tasks so always mark the popped test as done. collection.test_completed()
def main(): parser = argparse.ArgumentParser() apk_group = parser.add_mutually_exclusive_group(required=True) apk_group.add_argument('--apk', dest='apk_name', help='DEPRECATED The name of the apk containing the' ' application (with the .apk extension).') apk_group.add_argument('apk_path', nargs='?', help='The path to the APK to install.') # TODO(jbudorick): Remove once no clients pass --apk_package parser.add_argument('--apk_package', help='DEPRECATED unused') parser.add_argument('--split', action='append', dest='splits', help='A glob matching the apk splits. ' 'Can be specified multiple times.') parser.add_argument('--keep_data', action='store_true', default=False, help='Keep the package data when installing ' 'the application.') parser.add_argument('--debug', action='store_const', const='Debug', dest='build_type', default=os.environ.get('BUILDTYPE', 'Debug'), help='If set, run test suites under out/Debug. ' 'Default is env var BUILDTYPE or Debug') parser.add_argument('--release', action='store_const', const='Release', dest='build_type', help='If set, run test suites under out/Release. ' 'Default is env var BUILDTYPE or Debug.') parser.add_argument( '-d', '--device', dest='devices', action='append', help='Target device for apk to install on. Enter multiple' ' times for multiple devices.') parser.add_argument('--adb-path', help='Absolute path to the adb binary to use.') parser.add_argument('--blacklist-file', help='Device blacklist JSON file.') parser.add_argument('-v', '--verbose', action='count', help='Enable verbose logging.') parser.add_argument('--downgrade', action='store_true', help='If set, allows downgrading of apk.') args = parser.parse_args() run_tests_helper.SetLogLevel(args.verbose) constants.SetBuildType(args.build_type) devil_custom_deps = None if args.adb_path: devil_custom_deps = { 'adb': { devil_env.GetPlatform(): [args.adb_path], }, } devil_chromium.Initialize(output_directory=constants.GetOutDirectory(), custom_deps=devil_custom_deps) apk = args.apk_path or args.apk_name if not apk.endswith('.apk'): apk += '.apk' if not os.path.exists(apk): apk = os.path.join(constants.GetOutDirectory(), 'apks', apk) if not os.path.exists(apk): parser.error('%s not found.' % apk) if args.splits: splits = [] base_apk_package = apk_helper.ApkHelper(apk).GetPackageName() for split_glob in args.splits: apks = [f for f in glob.glob(split_glob) if f.endswith('.apk')] if not apks: logging.warning('No apks matched for %s.', split_glob) for f in apks: helper = apk_helper.ApkHelper(f) if (helper.GetPackageName() == base_apk_package and helper.GetSplitName()): splits.append(f) blacklist = (device_blacklist.Blacklist(args.blacklist_file) if args.blacklist_file else None) devices = device_utils.DeviceUtils.HealthyDevices(blacklist) if args.devices: devices = [d for d in devices if d in args.devices] if not devices: raise device_errors.DeviceUnreachableError(args.devices) elif not devices: raise device_errors.NoDevicesError() def blacklisting_install(device): try: if args.splits: device.InstallSplitApk(apk, splits, reinstall=args.keep_data, allow_downgrade=args.downgrade) else: device.Install(apk, reinstall=args.keep_data, allow_downgrade=args.downgrade) except device_errors.CommandFailedError: logging.exception('Failed to install %s', args.apk_name) if blacklist: blacklist.Extend([str(device)], reason='install_failure') logging.warning('Blacklisting %s', str(device)) except device_errors.CommandTimeoutError: logging.exception('Timed out while installing %s', args.apk_name) if blacklist: blacklist.Extend([str(device)], reason='install_timeout') logging.warning('Blacklisting %s', str(device)) device_utils.DeviceUtils.parallel(devices).pMap(blacklisting_install)