diff --git a/layout/tools/reftest/mach_commands.py b/layout/tools/reftest/mach_commands.py index 461f3e9229bf..65c23bcc785f 100644 --- a/layout/tools/reftest/mach_commands.py +++ b/layout/tools/reftest/mach_commands.py @@ -137,7 +137,7 @@ class ReftestRunner(MozbuildObject): args.printDeviceInfo = False from mozrunner.devices.android_device import grant_runtime_permissions, get_adb_path - grant_runtime_permissions(self, args.app) + grant_runtime_permissions(self, args.app, device_serial=args.deviceSerial) if not args.adb_path: args.adb_path = get_adb_path(self) @@ -231,6 +231,7 @@ class MachCommands(MachCommandBase): reftest = self._spawn(ReftestRunner) if conditions.is_android(self): from mozrunner.devices.android_device import verify_android_device - verify_android_device(self, install=True, xre=True, app=kwargs["app"]) + verify_android_device(self, install=True, xre=True, app=kwargs["app"], + device_serial=kwargs["deviceSerial"]) return reftest.run_android_test(**kwargs) return reftest.run_desktop_test(**kwargs) diff --git a/testing/mochitest/mach_commands.py b/testing/mochitest/mach_commands.py index c7b661e30191..8bac433a1355 100644 --- a/testing/mochitest/mach_commands.py +++ b/testing/mochitest/mach_commands.py @@ -403,10 +403,12 @@ class MachCommands(MachCommandBase): app = kwargs.get('app') if not app: app = self.substs["ANDROID_PACKAGE_NAME"] + device_serial = kwargs.get('deviceSerial') # verify installation - verify_android_device(self, install=True, xre=False, app=app) - grant_runtime_permissions(self, app) + verify_android_device(self, install=True, xre=False, app=app, + device_serial=device_serial) + grant_runtime_permissions(self, app, device_serial=device_serial) run_mochitest = mochitest.run_android_test else: run_mochitest = mochitest.run_desktop_test @@ -481,8 +483,10 @@ class RobocopCommands(MachCommandBase): app = kwargs.get('app') if not app: app = self.substs["ANDROID_PACKAGE_NAME"] - verify_android_device(self, install=True, xre=False, app=app) - grant_runtime_permissions(self, app) + device_serial = kwargs.get('deviceSerial') + verify_android_device(self, install=True, xre=False, app=app, + device_serial=device_serial) + grant_runtime_permissions(self, app, device_serial=device_serial) if not kwargs['adbPath']: kwargs['adbPath'] = get_adb_path(self) diff --git a/testing/mozbase/mozrunner/mozrunner/devices/android_device.py b/testing/mozbase/mozrunner/mozrunner/devices/android_device.py index 4cb9bd3b1039..49a3e71e8688 100644 --- a/testing/mozbase/mozrunner/mozrunner/devices/android_device.py +++ b/testing/mozbase/mozrunner/mozrunner/devices/android_device.py @@ -19,7 +19,7 @@ import urlparse import urllib2 from distutils.spawn import find_executable -from mozdevice import DeviceManagerADB, DMError +from mozdevice import ADBHost, ADBAndroid from mozprocess import ProcessHandler EMULATOR_HOME_DIR = os.path.join(os.path.expanduser('~'), '.mozbuild', 'android-device') @@ -33,6 +33,7 @@ TRY_URL = 'https://hg.mozilla.org/try/raw-file/default' MANIFEST_PATH = 'testing/config/tooltool-manifests' verbose_logging = False +devices = {} class AvdInfo(object): @@ -106,6 +107,19 @@ AVD_DICT = { } +def _get_device(substs, device_serial=None): + global devices + if device_serial in devices: + device = devices[device_serial] + else: + adb_path = _find_sdk_exe(substs, 'adb', False) + if not adb_path: + adb_path = 'adb' + device = ADBAndroid(adb=adb_path, verbose=verbose_logging, device=device_serial) + devices[device_serial] = device + return device + + def _install_host_utils(build_obj): _log_info("Installing host utilities. This may take a while...") installed = False @@ -178,7 +192,7 @@ def _maybe_update_host_utils(build_obj): def verify_android_device(build_obj, install=False, xre=False, debugger=False, - verbose=False, app=None): + verbose=False, app=None, device_serial=None): """ Determine if any Android device is connected via adb. If no device is found, prompt to start an emulator. @@ -195,8 +209,12 @@ def verify_android_device(build_obj, install=False, xre=False, debugger=False, """ device_verified = False emulator = AndroidEmulator('*', substs=build_obj.substs, verbose=verbose) - devices = emulator.dm.devices() - if (len(devices) > 0) and ('device' in [d[1] for d in devices]): + adb_path = _find_sdk_exe(build_obj.substs, 'adb', False) + if not adb_path: + adb_path = 'adb' + adbhost = ADBHost(adb=adb_path, verbose=verbose, timeout=10) + devices = adbhost.devices(timeout=10) + if 'device' in [d['state'] for d in devices]: device_verified = True elif emulator.is_available(): response = raw_input( @@ -224,11 +242,10 @@ def verify_android_device(build_obj, install=False, xre=False, debugger=False, # Installing every time is problematic because: # - it prevents testing against other builds (downloaded apk) # - installation may take a couple of minutes. - installed = emulator.dm.shellCheckOutput(['pm', 'list', - 'packages', 'org.mozilla.']) if not app: app = build_obj.substs["ANDROID_PACKAGE_NAME"] - if app not in installed: + device = _get_device(build_obj.substs, device_serial) + if not device.is_app_installed(app): if 'fennec' not in app and 'firefox' not in app: raw_input( "It looks like %s is not installed on this device,\n" @@ -334,10 +351,7 @@ def run_firefox_for_android(build_obj, params): Launch Firefox for Android on the connected device. Optional 'params' allow parameters to be passed to Firefox. """ - adb_path = _find_sdk_exe(build_obj.substs, 'adb', False) - if not adb_path: - adb_path = 'adb' - dm = DeviceManagerADB(autoconnect=False, adbPath=adb_path, retryLimit=1) + device = _get_device(build_obj.substs) try: # # Construct an adb command similar to: @@ -347,45 +361,37 @@ def run_firefox_for_android(build_obj, params): # -d \ # --es args "" # - app = "%s/org.mozilla.gecko.BrowserApp" % build_obj.substs['ANDROID_PACKAGE_NAME'] - cmd = ['am', 'start', '-a', 'android.activity.MAIN', '-n', app] + app = build_obj.substs['ANDROID_PACKAGE_NAME'] + url = None if params: for p in params: if urlparse.urlparse(p).scheme != "": - cmd.extend(['-d', p]) + url = p params.remove(p) break - if params: - cmd.extend(['--es', 'args', '"%s"' % ' '.join(params)]) - _log_debug(cmd) - output = dm.shellCheckOutput(cmd, timeout=10) - _log_info(output) - except DMError: + device.launch_fennec(app, extra_args=params, url=url) + except Exception: _log_warning("unable to launch Firefox for Android") return 1 return 0 -def grant_runtime_permissions(build_obj, app): +def grant_runtime_permissions(build_obj, app, device_serial=None): """ Grant required runtime permissions to the specified app (typically org.mozilla.fennec_$USER). """ - adb_path = _find_sdk_exe(build_obj.substs, 'adb', False) - if not adb_path: - adb_path = 'adb' - dm = DeviceManagerADB(autoconnect=False, adbPath=adb_path, retryLimit=1) - dm.default_timeout = 10 + device = _get_device(build_obj.substs, device_serial) try: - sdk_level = dm.shellCheckOutput(['getprop', 'ro.build.version.sdk']) - if sdk_level and int(sdk_level) >= 23: + sdk_level = device.version + if sdk_level and sdk_level >= 23: _log_info("Granting important runtime permissions to %s" % app) - dm.shellCheckOutput(['pm', 'grant', app, 'android.permission.WRITE_EXTERNAL_STORAGE']) - dm.shellCheckOutput(['pm', 'grant', app, 'android.permission.READ_EXTERNAL_STORAGE']) - dm.shellCheckOutput(['pm', 'grant', app, 'android.permission.ACCESS_COARSE_LOCATION']) - dm.shellCheckOutput(['pm', 'grant', app, 'android.permission.ACCESS_FINE_LOCATION']) - dm.shellCheckOutput(['pm', 'grant', app, 'android.permission.CAMERA']) - except DMError: + device.shell_output('pm grant %s android.permission.WRITE_EXTERNAL_STORAGE' % app) + device.shell_output('pm grant %s android.permission.READ_EXTERNAL_STORAGE' % app) + device.shell_output('pm grant %s android.permission.ACCESS_COARSE_LOCATION' % app) + device.shell_output('pm grant %s android.permission.ACCESS_FINE_LOCATION' % app) + device.shell_output('pm grant %s android.permission.CAMERA' % app) + except Exception: _log_warning("Unable to grant runtime permissions to %s" % app) @@ -416,12 +422,7 @@ class AndroidEmulator(object): self.avd_info = AVD_DICT[self.avd_type] self.gpu = True self.restarted = False - adb_path = _find_sdk_exe(substs, 'adb', False) - if not adb_path: - adb_path = 'adb' - self.dm = DeviceManagerADB(autoconnect=False, adbPath=adb_path, retryLimit=1, - deviceSerial=device_serial) - self.dm.default_timeout = 10 + self.device_serial = device_serial _log_debug("Running on %s" % platform.platform()) _log_debug("Emulator created with type %s" % self.avd_type) @@ -543,20 +544,28 @@ class AndroidEmulator(object): if self.check_completed(): return False _log_debug("Waiting for device status...") - while(('emulator-5554', 'device') not in self.dm.devices()): + adb_path = _find_sdk_exe(self.substs, 'adb', False) + if not adb_path: + adb_path = 'adb' + adbhost = ADBHost(adb=adb_path, verbose=verbose_logging, timeout=10) + devs = adbhost.devices(timeout=10) + devs = [(d['device_serial'], d['state']) for d in devs] + while ('emulator-5554', 'device') not in devs: time.sleep(10) if self.check_completed(): return False + devs = adbhost.devices(timeout=10) + devs = [(d['device_serial'], d['state']) for d in devs] _log_debug("Device status verified.") _log_debug("Checking that Android has booted...") + device = _get_device(self.substs, self.device_serial) complete = False - while(not complete): + while not complete: output = '' try: - output = self.dm.shellCheckOutput( - ['getprop', 'sys.boot_completed'], timeout=5) - except DMError: + output = device.get_prop('sys.boot_completed', timeout=5) + except Exception: # adb not yet responding...keep trying pass if output.strip() == '1': @@ -843,19 +852,8 @@ def _get_host_platform(): def _get_device_platform(substs): # PIE executables are required when SDK level >= 21 - important for gdbserver - adb_path = _find_sdk_exe(substs, 'adb', False) - if not adb_path: - adb_path = 'adb' - dm = DeviceManagerADB(autoconnect=False, adbPath=adb_path, retryLimit=1) - sdk_level = None - try: - cmd = ['getprop', 'ro.build.version.sdk'] - _log_debug(cmd) - output = dm.shellCheckOutput(cmd, timeout=10) - if output: - sdk_level = int(output) - except Exception: - _log_warning("unable to determine Android sdk level") + device = _get_device(substs) + sdk_level = device.version pie = '' if sdk_level and sdk_level >= 21: pie = '-pie' diff --git a/testing/mozbase/mozrunner/mozrunner/devices/autophone.py b/testing/mozbase/mozrunner/mozrunner/devices/autophone.py index aeae19166fb5..bea6ba4a4369 100644 --- a/testing/mozbase/mozrunner/mozrunner/devices/autophone.py +++ b/testing/mozbase/mozrunner/mozrunner/devices/autophone.py @@ -19,7 +19,7 @@ import BaseHTTPServer import SimpleHTTPServer from mozbuild.virtualenv import VirtualenvManager -from mozdevice import DeviceManagerADB +from mozdevice import ADBHost, ADBAndroid from mozprocess import ProcessHandler @@ -193,12 +193,13 @@ class AutophoneRunner(object): "adb not found. Enter path to adb: ").strip() if self.verbose: print("Using adb at %s" % adb_path) - dm = DeviceManagerADB(autoconnect=False, adbPath=adb_path, retryLimit=1) + + adbhost = ADBHost(adb=adb_path, timeout=10) device_index = 1 try: with open(os.path.join(self.config['base-dir'], 'devices.ini'), 'w') as f: - for device in dm.devices(): - serial = device[0] + for device in adbhost.devices(): + serial = device['device_serial'] if self.verify_device(adb_path, serial): f.write("[device-%d]\nserialno=%s\n" % (device_index, serial)) device_index += 1 @@ -444,8 +445,8 @@ time_out = 300""" % (xre_path, xre_path)) Check that the specified device is available and rooted. """ try: - dm = DeviceManagerADB(adbPath=adb_path, retryLimit=1, deviceSerial=device) - if dm._haveSu or dm._haveRootShell: + device = ADBAndroid(adb=adb_path, device=device, timeout=10) + if device._have_su or device._have_android_su or device._have_root_shell: return True except Exception: self.build_obj.log( diff --git a/testing/xpcshell/mach_commands.py b/testing/xpcshell/mach_commands.py index 7024eb448d95..5cebd78e63a0 100644 --- a/testing/xpcshell/mach_commands.py +++ b/testing/xpcshell/mach_commands.py @@ -247,7 +247,8 @@ class MachCommands(MachCommandBase): if conditions.is_android(self): from mozrunner.devices.android_device import verify_android_device, get_adb_path - verify_android_device(self) + device_serial = params.get('deviceSerial') + verify_android_device(self, device_serial=device_serial) if not params['adbPath']: params['adbPath'] = get_adb_path(self) xpcshell = self._spawn(AndroidXPCShellRunner)