def wait_for_start(self): """ Verify that the emulator is running, the emulator device is visible to adb, and Android has booted. """ if not self.proc: _log_warning("Emulator not started!") return False if self.check_completed(): return False _log_debug("Waiting for device status...") 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=SHORT_TIMEOUT) devs = adbhost.devices(timeout=SHORT_TIMEOUT) 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=SHORT_TIMEOUT) 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: output = '' try: output = device.get_prop('sys.boot_completed', timeout=5) except Exception: # adb not yet responding...keep trying pass if output.strip() == '1': complete = True else: time.sleep(10) if self.check_completed(): return False _log_debug("Android boot status verified.") if not self._verify_emulator(): return False if self.avd_info.x86: _log_info( "Running the x86/x86_64 emulator; be sure to install an x86 or x86_64 APK!" ) else: _log_info( "Running the arm emulator; be sure to install an arm APK!") return True
def _get_online_devices(self): adbhost = ADBHost() devices = adbhost.devices() return [ d['device_serial'] for d in devices if d['state'] != 'offline' if not d['device_serial'].startswith('emulator') ]
class FennecLauncher(Launcher): app_info = None def _get_device_status(self): self.adbhost = ADBHost() if self.adbhost.devices(): return True if "y" == raw_input("WARNING: no device connected." " Connect a device and try again.\n" "Try again? (y or n): "): return self.get_device_status() raise Exception("Aborting!") def _install(self, dest): if self._get_device_status(): self.adb = ADBAndroid() if "y" != raw_input("WARNING: bisecting nightly fennec builds will" " clobber your existing nightly profile." " Continue? (y or n)"): raise Exception("Aborting!") self.adb.uninstall_app("org.mozilla.fennec") self.adb.install_app(dest) # get info now, as dest may be removed self.app_info = mozversion.get_version(binary=dest) def _start(self, **args): self.adb.launch_fennec("org.mozilla.fennec") def _stop(self): self.adb.stop_application("org.mozilla.fennec") def _get_app_info(self): return self.app_info
def _get_online_devices(self): adbhost = ADBHost(adb=self.app_ctx.adb) return [ d["device_serial"] for d in adbhost.devices() if d["state"] != "offline" if d["device_serial"].startswith("emulator") ]
def _get_online_devices(self): adbhost = ADBHost(adb=self.app_ctx.adb) return [ d['device_serial'] for d in adbhost.devices() if d['state'] != 'offline' if d['device_serial'].startswith('emulator') ]
def run_raptor(self, **kwargs): build_obj = self is_android = Conditions.is_android(build_obj) or \ kwargs['app'] in FIREFOX_ANDROID_BROWSERS if is_android: from mozrunner.devices.android_device import ( verify_android_device, InstallIntent) from mozdevice import ADBAndroid, ADBHost install = InstallIntent.NO if kwargs.pop( 'noinstall', False) else InstallIntent.PROMPT if not verify_android_device( build_obj, install=install, app=kwargs['binary'], xre=True): # Equivalent to 'run_local' = True. return 1 debug_command = '--debug-command' if debug_command in sys.argv: sys.argv.remove(debug_command) raptor = self._spawn(RaptorRunner) try: if is_android and kwargs['power_test']: device = ADBAndroid(verbose=True) adbhost = ADBHost(verbose=True) device_serial = "{}:5555".format(device.get_ip_address()) device.command_output(["tcpip", "5555"]) six.input( "Please disconnect your device from USB then press Enter/return..." ) adbhost.command_output(["connect", device_serial]) while len(adbhost.devices()) > 1: six.input( "You must disconnect your device from USB before continuing." ) # must reset the environment DEVICE_SERIAL which was set during # verify_android_device to match our new tcpip value. os.environ["DEVICE_SERIAL"] = device_serial return raptor.run_test(sys.argv[2:], kwargs) except Exception as e: print(repr(e)) return 1 finally: try: if is_android and kwargs['power_test']: six.input( "Connect device via USB and press Enter/return...") device = ADBAndroid(device=device_serial, verbose=True) device.command_output(["usb"]) adbhost.command_output(["disconnect", device_serial]) except Exception: adbhost.command_output(["kill-server"])
def run_raptor_test(self, **kwargs): build_obj = MozbuildObject.from_environment(cwd=HERE) firefox_android_browsers = ["fennec", "geckoview", "refbrow", "fenix"] if conditions.is_android( build_obj) or kwargs['app'] in firefox_android_browsers: from mozrunner.devices.android_device import verify_android_device from mozdevice import ADBAndroid, ADBHost if not verify_android_device( build_obj, install=True, app=kwargs['binary'], xre=True): # Equivalent to 'run_local' = True. return 1 debug_command = '--debug-command' if debug_command in sys.argv: sys.argv.remove(debug_command) raptor = self._spawn(RaptorRunner) try: if kwargs['app'] in firefox_android_browsers and kwargs[ 'power_test']: device = ADBAndroid(verbose=True) adbhost = ADBHost(verbose=True) device_serial = "%s:5555" % device.get_ip_address() device.command_output(["tcpip", "5555"]) raw_input( "Please disconnect your device from USB then press Enter/return..." ) adbhost.command_output(["connect", device_serial]) while len(adbhost.devices()) > 1: raw_input( "You must disconnect your device from USB before continuing." ) # must reset the environment DEVICE_SERIAL which was set during # verify_android_device to match our new tcpip value. os.environ["DEVICE_SERIAL"] = device_serial return raptor.run_test(sys.argv[2:], kwargs) except Exception as e: print(repr(e)) return 1 finally: try: if kwargs['app'] in firefox_android_browsers and kwargs[ 'power_test']: raw_input( "Connect device via USB and press Enter/return...") device = ADBAndroid(device=device_serial, verbose=True) device.command_output(["usb"]) adbhost.command_output(["disconnect", device_serial]) except Exception: adbhost.command_output(["kill-server"])
def is_running(self): """ Returns True if the Android emulator is running. """ 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=SHORT_TIMEOUT) devs = adbhost.devices(timeout=SHORT_TIMEOUT) devs = [(d['device_serial'], d['state']) for d in devs] _log_debug(devs) if ('emulator-5554', 'device') in devs: return True return False
class FennecNightly(Nightly): app_name = 'fennec' name = 'fennec' profile_class = FirefoxProfile build_regex = r'fennec-.*\.apk' build_info_regex = r'fennec-.*\.txt' binary = 'org.mozilla.fennec/.App' bits = None build_base_repo_name = "mobile" def get_device_status(self): self.adbhost = ADBHost() if self.adbhost.devices(): return True if "y" == raw_input("WARNING: no device connected." " Connect a device and try again.\n" "Try again? (y or n): "): return self.get_device_status() raise Exception("Aborting!") def __init__(self, inbound_branch=None, bits=mozinfo.bits, persist=None): self.inbound_branch = inbound_branch self.persist = persist if self.get_device_status(): self.adb = ADBAndroid() if "y" != raw_input("WARNING: bisecting nightly fennec builds will" " clobber your existing nightly profile." " Continue? (y or n)"): raise Exception("Aborting!") def get_inbound_branch(self, date): return "mozilla-central-android" def install(self): self.adb.uninstall_app("org.mozilla.fennec") self.adb.install_app(self.dest) return True def start(self, profile, addons, cmdargs): self.adb.launch_fennec("org.mozilla.fennec") return True def stop(self): self.adb.stop_application("org.mozilla.fennec") return True def get_app_info(self): return mozversion.get_version(binary=self.dest)
def is_running(self): """ Returns True if the Android emulator is running. """ 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=SHORT_TIMEOUT) devs = adbhost.devices(timeout=SHORT_TIMEOUT) devs = [(d["device_serial"], d["state"]) for d in devs] _log_debug(devs) if ("emulator-5554", "device") in devs: return True return False
def verify_android_device(build_obj, install=InstallIntent.NO, xre=False, debugger=False, network=False, 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. If a device is found or an emulator started and 'install' is specified, also check whether Firefox is installed on the device; if not, prompt to install Firefox. If 'xre' is specified, also check with MOZ_HOST_BIN is set to a valid xre/host-utils directory; if not, prompt to set one up. If 'debugger' is specified, also check that JimDB is installed; if JimDB is not found, prompt to set up JimDB. If 'network' is specified, also check that the device has basic network connectivity. Returns True if the emulator was started or another device was already connected. """ if "MOZ_DISABLE_ADB_INSTALL" in os.environ: install = InstallIntent.NO _log_info( "Found MOZ_DISABLE_ADB_INSTALL in environment, skipping android app" "installation") device_verified = False emulator = AndroidEmulator('*', substs=build_obj.substs, verbose=verbose) 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=SHORT_TIMEOUT) devices = adbhost.devices(timeout=SHORT_TIMEOUT) if 'device' in [d['state'] for d in devices]: device_verified = True elif emulator.is_available(): response = input( "No Android devices connected. Start an emulator? (Y/n) ").strip() if response.lower().startswith('y') or response == '': if not emulator.check_avd(): _log_info("Fetching AVD...") emulator.update_avd() _log_info("Starting emulator running %s..." % emulator.get_avd_description()) emulator.start() emulator.wait_for_start() device_verified = True if device_verified and "DEVICE_SERIAL" not in os.environ: devices = adbhost.devices(timeout=SHORT_TIMEOUT) for d in devices: if d['state'] == 'device': os.environ["DEVICE_SERIAL"] = d['device_serial'] break if device_verified and install != InstallIntent.NO: # Determine if test app is installed on the device; if not, # prompt to install. This feature allows a test command to # launch an emulator, install the test app, and proceed with testing # in one operation. It is also a basic safeguard against other # cases where testing is requested but test app installation has # been forgotten. # If a test app is installed, there is no way to determine whether # the current build is installed, and certainly no way to # determine if the installed build is the desired build. # Installing every time (without prompting) is problematic because: # - it prevents testing against other builds (downloaded apk) # - installation may take a couple of minutes. if not app: app = "org.mozilla.geckoview.test" device = _get_device(build_obj.substs, device_serial) response = '' installed = device.is_app_installed(app) if not installed: _log_info("It looks like %s is not installed on this device." % app) if 'fennec' in app or 'firefox' in app: if installed: device.uninstall_app(app) _log_info("Installing Firefox...") build_obj._run_make(directory=".", target='install', ensure_exit_code=False) elif app == 'org.mozilla.geckoview.test': if installed: device.uninstall_app(app) _log_info("Installing geckoview AndroidTest...") sub = 'geckoview:installWithGeckoBinariesDebugAndroidTest' build_obj._mach_context.commands.dispatch('gradle', build_obj._mach_context, args=[sub]) elif app == 'org.mozilla.geckoview_example': if installed: device.uninstall_app(app) _log_info("Installing geckoview_example...") sub = 'install-geckoview_example' build_obj._mach_context.commands.dispatch('android', build_obj._mach_context, subcommand=sub, args=[]) elif not installed: response = input( "It looks like %s is not installed on this device,\n" "but I don't know how to install it.\n" "Install it now, then hit Enter " % app) device.run_as_package = app if device_verified and xre: # Check whether MOZ_HOST_BIN has been set to a valid xre; if not, # prompt to install one. xre_path = os.environ.get('MOZ_HOST_BIN') err = None if not xre_path: err = "environment variable MOZ_HOST_BIN is not set to a directory " \ "containing host xpcshell" elif not os.path.isdir(xre_path): err = '$MOZ_HOST_BIN does not specify a directory' elif not os.path.isfile(os.path.join(xre_path, _get_xpcshell_name())): err = '$MOZ_HOST_BIN/xpcshell does not exist' if err: _maybe_update_host_utils(build_obj) xre_path = glob.glob(os.path.join(EMULATOR_HOME_DIR, 'host-utils*')) for path in xre_path: if os.path.isdir(path) and os.path.isfile( os.path.join(path, _get_xpcshell_name())): os.environ["MOZ_HOST_BIN"] = path err = None break if err: _log_info("Host utilities not found: %s" % err) response = input( "Download and setup your host utilities? (Y/n) ").strip() if response.lower().startswith('y') or response == '': _install_host_utils(build_obj) if device_verified and network: # Optionally check the network: If on a device that does not look like # an emulator, verify that the device IP address can be obtained # and check that this host can ping the device. serial = device_serial or os.environ.get('DEVICE_SERIAL') if not serial or ('emulator' not in serial): device = _get_device(build_obj.substs, serial) device.run_as_package = app try: addr = device.get_ip_address() if not addr: _log_warning("unable to get Android device's IP address!") _log_warning( "tests may fail without network connectivity to the device!" ) else: _log_info("Android device's IP address: %s" % addr) response = subprocess.check_output( ["ping", "-c", "1", addr]) _log_debug(response) except Exception as e: _log_warning( "unable to verify network connection to device: %s" % str(e)) _log_warning( "tests may fail without network connectivity to the device!" ) else: _log_debug("network check skipped on emulator") if debugger: _log_warning("JimDB is no longer supported") return device_verified
def main(): parser = argparse.ArgumentParser( usage='%(prog)s [options] <test command> (<test command option> ...)', description="Wrapper script for tests run on physical Android devices at Bitbar. Runs the provided command " "wrapped with required setup and teardown.") _args, extra_args = parser.parse_known_args() logging.basicConfig(format='%(asctime)-15s %(levelname)s %(message)s', level=logging.INFO, stream=sys.stdout) print('\nscript.py: starting') with open('/builds/worker/version') as versionfile: version = versionfile.read().strip() print('\nDockerfile version {}'.format(version)) taskcluster_debug = '*' task_cwd = os.getcwd() print('Current working directory: {}'.format(task_cwd)) with open('/builds/taskcluster/scriptvars.json') as scriptvars: scriptvarsenv = json.loads(scriptvars.read()) print('Bitbar test run: https://mozilla.testdroid.com/#testing/device-session/{}/{}/{}'.format( scriptvarsenv['TESTDROID_PROJECT_ID'], scriptvarsenv['TESTDROID_BUILD_ID'], scriptvarsenv['TESTDROID_RUN_ID'])) env = dict(os.environ) if 'PATH' in os.environ: path = os.environ['PATH'] else: path = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin' path += ':/builds/worker/android-sdk-linux/tools/bin:/builds/worker/android-sdk-linux/platform-tools' env['PATH'] = os.environ['PATH'] = path env['NEED_XVFB'] = 'false' env['DEVICE_NAME'] = scriptvarsenv['DEVICE_NAME'] env['ANDROID_DEVICE'] = scriptvarsenv['ANDROID_DEVICE'] env['DEVICE_SERIAL'] = scriptvarsenv['DEVICE_SERIAL'] env['HOST_IP'] = scriptvarsenv['HOST_IP'] env['DEVICE_IP'] = scriptvarsenv['DEVICE_IP'] env['DOCKER_IMAGE_VERSION'] = scriptvarsenv['DOCKER_IMAGE_VERSION'] if 'HOME' not in env: env['HOME'] = '/builds/worker' print('setting HOME to {}'.format(env['HOME'])) show_df() # If we are running normal tests we will be connected via usb and # there should be only one device connected. If we are running # power tests, the framework will have already called adb tcpip # 5555 on the device before it disconnected usb. There should be # no devices connected and we will need to perform an adb connect # to connect to the device. DEVICE_SERIAL will be set to either # the device's serial number or its ipaddress:5555 by the framework. try: adbhost = ADBHost(verbose=True) if env['DEVICE_SERIAL'].endswith(':5555'): # Power testing with adb over wifi. adbhost.command_output(["connect", env['DEVICE_SERIAL']]) devices = adbhost.devices() print(json.dumps(devices, indent=4)) if len(devices) != 1: fatal('Must have exactly one connected device. {} found.'.format(len(devices)), retry=True) except (ADBError, ADBTimeoutError) as e: fatal('{} Unable to obtain attached devices'.format(e), retry=True) try: for f in glob('/tmp/adb.*.log'): print('\n{}:\n'.format(f)) with open(f) as afile: print(afile.read()) except Exception as e: print('{} while reading adb logs'.format(e)) print('Connecting to Android device {}'.format(env['DEVICE_SERIAL'])) try: device = ADBDevice(device=env['DEVICE_SERIAL']) android_version = device.get_prop('ro.build.version.release') print('Android device version (ro.build.version.release): {}'.format(android_version)) # this can explode if an unknown device, explode now vs in an hour... device_type = get_device_type(device) # set device to UTC if device.is_rooted: device.shell_output('setprop persist.sys.timezone "UTC"', timeout=ADB_COMMAND_TIMEOUT) # show date for visual confirmation device_datetime = device.shell_output("date", timeout=ADB_COMMAND_TIMEOUT) print('Android device datetime: {}'.format(device_datetime)) # clean up the device. device.rm('/data/local/tests', recursive=True, force=True) device.rm('/data/local/tmp/*', recursive=True, force=True) device.rm('/data/local/tmp/xpcb', recursive=True, force=True) device.rm('/sdcard/tests', recursive=True, force=True) device.rm('/sdcard/raptor-profile', recursive=True, force=True) except (ADBError, ADBTimeoutError) as e: fatal("{} attempting to clean up device".format(e), retry=True) if taskcluster_debug: env['DEBUG'] = taskcluster_debug print('environment = {}'.format(json.dumps(env, indent=4))) # run the payload's command and ensure that: # - all output is printed # - no deadlock occurs between proc.poll() and sys.stdout.readline() # - more info # - https://bugzilla.mozilla.org/show_bug.cgi?id=1611936 # - https://stackoverflow.com/questions/58471094/python-subprocess-readline-hangs-cant-use-normal-options print("script.py: running command '%s'" % ' '.join(extra_args)) rc = None proc = subprocess.Popen(extra_args, # use standard os buffer size bufsize=-1, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) # Create the queue instance q = queue.Queue() # Kick off the monitoring thread thread = threading.Thread(target=_monitor_readline, args=(proc, q)) thread.daemon = True thread.start() start = datetime.now() while True: time.sleep(0.1) bail = True rc = proc.poll() if rc is None: bail = False # Re-set the thread timer start = datetime.now() out = "" while not q.empty(): out += q.get() if out: print(out.rstrip()) # In the case where the thread is still alive and reading, and # the process has exited and finished, give it up to X seconds # to finish reading if bail and thread.is_alive() and (datetime.now() - start).total_seconds() < 5: bail = False if bail: break print("script.py: command finished") # enable charging on device if it is disabled # see https://bugzilla.mozilla.org/show_bug.cgi?id=1565324 enable_charging(device, device_type) try: if env['DEVICE_SERIAL'].endswith(':5555'): device.command_output(["usb"]) adbhost.command_output(["disconnect", env['DEVICE_SERIAL']]) adbhost.kill_server() except (ADBError, ADBTimeoutError) as e: print('{} attempting adb kill-server'.format(e)) try: print('\nnetstat -aop\n%s\n\n' % subprocess.check_output( ['netstat', '-aop'], stderr=subprocess.STDOUT).decode()) except subprocess.CalledProcessError as e: print('{} attempting netstat'.format(e)) show_df() print('script.py: exiting with exitcode {}.'.format(rc)) return rc
def main(): parser = argparse.ArgumentParser( usage='%(prog)s [options] <test command> (<test command option> ...)', description= "Wrapper script for tests run on physical Android devices at Bitbar. Runs the provided command wrapped with required setup and teardown." ) _args, extra_args = parser.parse_known_args() logging.basicConfig(format='%(asctime)-15s %(levelname)s %(message)s', level=logging.INFO, stream=sys.stdout) print('\nBegin script.py') with open('/builds/worker/version') as versionfile: version = versionfile.read().strip() print('\nDockerfile version {}'.format(version)) taskcluster_debug = '*' task_cwd = os.getcwd() print('Current working directory: {}'.format(task_cwd)) with open('/builds/taskcluster/scriptvars.json') as scriptvars: scriptvarsenv = json.loads(scriptvars.read()) print( 'Bitbar test run: https://mozilla.testdroid.com/#testing/device-session/{}/{}/{}' .format(scriptvarsenv['TESTDROID_PROJECT_ID'], scriptvarsenv['TESTDROID_BUILD_ID'], scriptvarsenv['TESTDROID_RUN_ID'])) env = dict(os.environ) if 'PATH' in os.environ: path = os.environ['PATH'] else: path = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin' path += ':/builds/worker/android-sdk-linux/tools/bin:/builds/worker/android-sdk-linux/platform-tools' env['PATH'] = os.environ['PATH'] = path env['NEED_XVFB'] = 'false' env['DEVICE_NAME'] = scriptvarsenv['DEVICE_NAME'] env['ANDROID_DEVICE'] = scriptvarsenv['ANDROID_DEVICE'] env['DEVICE_SERIAL'] = scriptvarsenv['DEVICE_SERIAL'] env['HOST_IP'] = scriptvarsenv['HOST_IP'] env['DEVICE_IP'] = scriptvarsenv['DEVICE_IP'] env['DOCKER_IMAGE_VERSION'] = scriptvarsenv['DOCKER_IMAGE_VERSION'] if 'HOME' not in env: env['HOME'] = '/builds/worker' print('setting HOME to {}'.format(env['HOME'])) # If we are running normal tests we will be connected via usb and # there should be only one device connected. If we are running # power tests, the framework will have already called adb tcpip # 5555 on the device before it disconnected usb. There should be # no devices connected and we will need to perform an adb connect # to connect to the device. DEVICE_SERIAL will be set to either # the device's serial number or its ipaddress:5555 by the framework. try: adbhost = ADBHost() if env['DEVICE_SERIAL'].endswith(':5555'): # Power testing with adb over wifi. adbhost.command_output(["connect", env['DEVICE_SERIAL']]) devices = adbhost.devices() print(json.dumps(devices, indent=4)) if len(devices) != 1: fatal('Must have exactly one connected device. {} found.'.format( len(devices))) except ADBError as e: fatal('{} Unable to obtain attached devices'.format(e)) try: for f in glob('/tmp/adb.*.log'): print('\n{}:\n'.format(f)) with open(f) as afile: print(afile.read()) except Exception as e: print('{} while reading adb logs'.format(e)) print('Connecting to Android device {}'.format(env['DEVICE_SERIAL'])) try: device = ADBDevice(device=env['DEVICE_SERIAL']) android_version = device.get_prop('ro.build.version.release') print('Android device version (ro.build.version.release): {}'.format( android_version)) # this can explode if an unknown device, explode now vs in an hour... device_type = get_device_type(device) # clean up the device. device.rm('/data/local/tests', recursive=True, force=True, root=True) device.rm('/data/local/tmp/*', recursive=True, force=True, root=True) device.rm('/data/local/tmp/xpcb', recursive=True, force=True, root=True) device.rm('/sdcard/tests', recursive=True, force=True, root=True) device.rm('/sdcard/raptor-profile', recursive=True, force=True, root=True) except ADBError as e: fatal("{} attempting to clean up device".format(e)) if taskcluster_debug: env['DEBUG'] = taskcluster_debug print('environment = {}'.format(json.dumps(env, indent=4))) # run the payload's command print(' '.join(extra_args)) rc = None proc = subprocess.Popen(extra_args, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while rc == None: line = proc.stdout.readline() sys.stdout.write(line) rc = proc.poll() # enable charging on device if it is disabled # see https://bugzilla.mozilla.org/show_bug.cgi?id=1565324 enable_charging(device, device_type) try: if env['DEVICE_SERIAL'].endswith(':5555'): device.command_output(["usb"]) adbhost.command_output(["disconnect", env['DEVICE_SERIAL']]) adbhost.kill_server() except ADBError as e: print('{} attempting adb kill-server'.format(e)) try: print('\nnetstat -aop\n%s\n\n' % subprocess.check_output( ['netstat', '-aop'], stderr=subprocess.STDOUT)) except subprocess.CalledProcessError as e: print('{} attempting netstat'.format(e)) print('script.py exitcode {}'.format(rc)) return rc
def verify_android_device(build_obj, install=False, xre=False, debugger=False, 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. If a device is found or an emulator started and 'install' is specified, also check whether Firefox is installed on the device; if not, prompt to install Firefox. If 'xre' is specified, also check with MOZ_HOST_BIN is set to a valid xre/host-utils directory; if not, prompt to set one up. If 'debugger' is specified, also check that JimDB is installed; if JimDB is not found, prompt to set up JimDB. Returns True if the emulator was started or another device was already connected. """ device_verified = False emulator = AndroidEmulator('*', substs=build_obj.substs, verbose=verbose) 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( "No Android devices connected. Start an emulator? (Y/n) ").strip() if response.lower().startswith('y') or response == '': if not emulator.check_avd(): _log_info("Fetching AVD. This may take a while...") emulator.update_avd() _log_info("Starting emulator running %s..." % emulator.get_avd_description()) emulator.start() emulator.wait_for_start() device_verified = True if device_verified and install: # Determine if Firefox is installed on the device; if not, # prompt to install. This feature allows a test command to # launch an emulator, install Firefox, and proceed with testing # in one operation. It is also a basic safeguard against other # cases where testing is requested but Firefox installation has # been forgotten. # If Firefox is installed, there is no way to determine whether # the current build is installed, and certainly no way to # determine if the installed build is the desired build. # Installing every time is problematic because: # - it prevents testing against other builds (downloaded apk) # - installation may take a couple of minutes. if not app: app = build_obj.substs["ANDROID_PACKAGE_NAME"] 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" "but I don't know how to install it.\n" "Install it now, then hit Enter " % app) else: response = raw_input( "It looks like %s is not installed on this device.\n" "Install Firefox? (Y/n) " % app).strip() if response.lower().startswith('y') or response == '': _log_info("Installing Firefox. This may take a while...") build_obj._run_make(directory=".", target='install', ensure_exit_code=False) if device_verified and xre: # Check whether MOZ_HOST_BIN has been set to a valid xre; if not, # prompt to install one. xre_path = os.environ.get('MOZ_HOST_BIN') err = None if not xre_path: err = "environment variable MOZ_HOST_BIN is not set to a directory " \ "containing host xpcshell" elif not os.path.isdir(xre_path): err = '$MOZ_HOST_BIN does not specify a directory' elif not os.path.isfile(os.path.join(xre_path, 'xpcshell')): err = '$MOZ_HOST_BIN/xpcshell does not exist' if err: _maybe_update_host_utils(build_obj) xre_path = glob.glob(os.path.join(EMULATOR_HOME_DIR, 'host-utils*')) for path in xre_path: if os.path.isdir(path) and os.path.isfile( os.path.join(path, 'xpcshell')): os.environ['MOZ_HOST_BIN'] = path err = None break if err: _log_info("Host utilities not found: %s" % err) response = raw_input( "Download and setup your host utilities? (Y/n) ").strip() if response.lower().startswith('y') or response == '': _install_host_utils(build_obj) if debugger: # Optionally set up JimDB. See https://wiki.mozilla.org/Mobile/Fennec/Android/GDB. build_platform = _get_device_platform(build_obj.substs) jimdb_path = os.path.join(EMULATOR_HOME_DIR, 'jimdb-%s' % build_platform) jimdb_utils_path = os.path.join(jimdb_path, 'utils') gdb_path = os.path.join(jimdb_path, 'bin', 'gdb') err = None if not os.path.isdir(jimdb_path): err = '%s does not exist' % jimdb_path elif not os.path.isfile(gdb_path): err = '%s not found' % gdb_path if err: _log_info("JimDB (%s) not found: %s" % (build_platform, err)) response = raw_input("Download and setup JimDB (%s)? (Y/n) " % build_platform).strip() if response.lower().startswith('y') or response == '': host_platform = _get_host_platform() if host_platform: _log_info( "Installing JimDB (%s/%s). This may take a while..." % (host_platform, build_platform)) path = os.path.join(MANIFEST_PATH, host_platform, 'jimdb-%s.manifest' % build_platform) _get_tooltool_manifest(build_obj.substs, path, EMULATOR_HOME_DIR, 'releng.manifest') _tooltool_fetch() if os.path.isfile(gdb_path): # Get JimDB utilities from git repository proc = ProcessHandler(['git', 'pull'], cwd=jimdb_utils_path) proc.run() git_pull_complete = False try: proc.wait() if proc.proc.returncode == 0: git_pull_complete = True except Exception: if proc.poll() is None: proc.kill(signal.SIGTERM) if not git_pull_complete: _log_warning( "Unable to update JimDB utils from git -- " "some JimDB features may be unavailable.") else: _log_warning( "Unable to install JimDB -- unable to fetch from tooltool." ) else: _log_warning( "Unable to install JimDB -- your platform is not supported!" ) if os.path.isfile(gdb_path): # sync gdbinit.local with build settings _update_gdbinit(build_obj.substs, os.path.join(jimdb_utils_path, "gdbinit.local")) # ensure JimDB is in system path, so that mozdebug can find it bin_path = os.path.join(jimdb_path, 'bin') os.environ['PATH'] = "%s:%s" % (bin_path, os.environ['PATH']) return device_verified
def configure_devices(self): """ Ensure devices.ini is set up. """ keep_going = True device_ini = os.path.join(self.config['base-dir'], 'devices.ini') if os.path.exists(device_ini): response = raw_input( "Use existing device configuration at %s? (Y/n) " % device_ini).strip() if 'n' not in response.lower(): self.build_obj.log(logging.INFO, "autophone", {}, "Using device configuration at %s" % device_ini) return keep_going keep_going = False self.build_obj.log(logging.INFO, "autophone", {}, "You must configure at least one Android device " "before running autophone.") response = raw_input( "Configure devices now? (Y/n) ").strip() if response.lower().startswith('y') or response == '': response = raw_input( "Connect your rooted Android test device(s) with usb and press Enter ") adb_path = 'adb' try: if os.path.exists(self.build_obj.substs["ADB"]): adb_path = self.build_obj.substs["ADB"] except Exception: if self.verbose: self.build_obj.log(logging.ERROR, "autophone", {}, str(sys.exc_info()[0])) # No build environment? try: adb_path = which.which('adb') except which.WhichError: adb_path = raw_input( "adb not found. Enter path to adb: ").strip() if self.verbose: print("Using adb at %s" % adb_path) 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 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 self.build_obj.log(logging.INFO, "autophone", {}, "Added '%s' to device configuration." % serial) keep_going = True else: self.build_obj.log(logging.WARNING, "autophone", {}, "Device '%s' is not rooted - skipping" % serial) except Exception: self.build_obj.log(logging.ERROR, "autophone", {}, "Failed to get list of connected Android devices.") if self.verbose: self.build_obj.log(logging.ERROR, "autophone", {}, str(sys.exc_info()[0])) keep_going = False if device_index <= 1: self.build_obj.log(logging.ERROR, "autophone", {}, "No devices configured! (Can you see your rooted test device(s)" " in 'adb devices'?") keep_going = False if keep_going: self.config['devices-configured'] = True return keep_going