def _StartActivityAndWaitForLinkerTestStatus(device, timeout): """Force-start an activity and wait up to |timeout| seconds until the full linker test status lines appear in the logcat, recorded through |device|. Args: device: A DeviceUtils instance. timeout: Timeout in seconds Returns: A (status, logs) tuple, where status is a ResultType constant, and logs if the final logcat output as a string. """ # 1. Start recording logcat with appropriate filters. with device.GetLogcatMonitor(filter_specs=_LOGCAT_FILTERS) as logmon: # 2. Force-start activity. device.StartActivity( intent.Intent(package=_PACKAGE_NAME, activity=_ACTIVITY_NAME), force_stop=True) # 3. Wait up to |timeout| seconds until the test status is in the logcat. result = ResultType.PASS try: browser_match = logmon.WaitFor(_RE_BROWSER_STATUS_LINE, timeout=timeout) logging.debug('Found browser match: %s', browser_match.group(0)) renderer_match = logmon.WaitFor(_RE_RENDERER_STATUS_LINE, timeout=timeout) logging.debug('Found renderer match: %s', renderer_match.group(0)) if (browser_match.group(1) != 'SUCCESS' or renderer_match.group(1) != 'SUCCESS'): result = ResultType.FAIL except device_errors.CommandTimeoutError: result = ResultType.TIMEOUT return result, '\n'.join(device.adb.Logcat(dump=True))
def GetCategories(device, package_info): with device.GetLogcatMonitor() as logmon: device.BroadcastIntent( intent.Intent(action='%s.GPU_PROFILER_LIST_CATEGORIES' % package_info.package)) try: json_category_list = logmon.WaitFor( re.compile(r'{"traceCategoriesList(.*)'), timeout=5).group(0) except device_errors.CommandTimeoutError: raise RuntimeError( 'Performance trace category list marker not found. ' 'Is the correct version of the browser running?') record_categories = set() disabled_by_default_categories = set() json_data = json.loads(json_category_list)['traceCategoriesList'] for item in json_data: for category in item.split(','): if category.startswith('disabled-by-default'): disabled_by_default_categories.add(category) else: record_categories.add(category) return list(record_categories), list(disabled_by_default_categories)
def testWebView(self): if self._device is None: logging.warning('No device found, skipping test.') return start_intent = intent.Intent( package='com.google.android.googlequicksearchbox', activity='.SearchActivity', action='com.google.android.googlequicksearchbox.GOOGLE_SEARCH', data=None, extras={'query': 'google'}, category=None) search_app = self.CreateAndroidApp(start_intent) search_process = search_app.GetProcess(':search') search_process._UpdateDevToolsClient() # TODO(ariblue): Replace the app used in this test with one in which the # setWebContentsDebuggingEnabled method is called on the WebView class. # This will configure webviews for debugging with chrome devtools inspector # and allow us to remove this check. if search_process._devtools_client is None: return webview = search_app.GetProcess(':search').GetWebViews().pop() webview.Navigate('https://www.google.com/search?q=flowers') time.sleep(5)
def StartTracing(self, interval): self._trace_interval = interval self._device.old_interface.SyncLogCat() start_extras = {'categories': ','.join(self._categories)} if self._ring_buffer: start_extras['continuous'] = None self._device.BroadcastIntent(intent.Intent( action='%s.GPU_PROFILER_START' % self._package_info.package, extras=start_extras)) if self._trace_memory: self._device.old_interface.EnableAdbRoot() self._device.SetProp(_HEAP_PROFILE_MMAP_PROPERTY, 1) # Chrome logs two different messages related to tracing: # # 1. "Logging performance trace to file" # 2. "Profiler finished. Results are in [...]" # # The first one is printed when tracing starts and the second one indicates # that the trace file is ready to be pulled. try: self._device.old_interface.WaitForLogMatch( self._trace_start_re, None, timeout=5) self._is_tracing = True except pexpect.TIMEOUT: raise RuntimeError('Trace start marker not found. Is the correct version ' 'of the browser running?')
def StopTracing(self): self._device.BroadcastIntent( intent.Intent(action='%s.GPU_PROFILER_STOP' % self._package_info.package)) self._trace_file = self._device.old_interface.WaitForLogMatch( self._trace_finish_re, None, timeout=120).group(1) if self._trace_memory: self._device.SetProp(_HEAP_PROFILE_MMAP_PROPERTY, 0)
def _StartActivity(self, device, force_stop=True): device.StartActivity( intent.Intent(package=self._package_info.package, activity=self._package_info.activity, action='android.intent.action.MAIN'), # No wait since the runner waits for FIFO creation anyway. blocking=False, force_stop=force_stop)
def _StartChrome(self, package_info, url): print 'Launching chrome...' self._device.StartActivity( intent.Intent(package=package_info.package, activity=package_info.activity, data=url, extras={'create_new_tab' : True}), blocking=True, force_stop=True)
def RunTest(self, test_name): """Run a Monkey test on the device. Args: test_name: String to use for logging the test result. Returns: A tuple of (TestRunResults, retry). """ self.device.StartActivity(intent.Intent( package=self._package, activity=self._activity, action='android.intent.action.MAIN'), blocking=True, force_stop=True) # Chrome crashes are not always caught by Monkey test runner. # Verify Chrome has the same PID before and after the test. before_pids = self.device.GetPids(self._package) # Run the test. output = '' if before_pids: output = '\n'.join(self._LaunchMonkeyTest()) after_pids = self.device.GetPids(self._package) crashed = True if not self._package in before_pids: logging.error('Failed to start the process.') elif not self._package in after_pids: logging.error('Process %s has died.', before_pids[self._package]) elif before_pids[self._package] != after_pids[self._package]: logging.error('Detected process restart %s -> %s', before_pids[self._package], after_pids[self._package]) else: crashed = False results = base_test_result.TestRunResults() success_pattern = 'Events injected: %d' % self._options.event_count if success_pattern in output and not crashed: result = base_test_result.BaseTestResult( test_name, base_test_result.ResultType.PASS, log=output) else: result = base_test_result.BaseTestResult( test_name, base_test_result.ResultType.FAIL, log=output) if 'chrome' in self._options.package: logging.warning('Starting MinidumpUploadService...') try: self.device.old_interface.StartCrashUploadService( self._package) except AssertionError as e: logging.error('Failed to start MinidumpUploadService: %s', e) results.AddResult(result) return results, False
def setUp(self): devices = android_commands.GetAttachedDevices() self.browser = 'stable' self.package_info = profiler.GetSupportedBrowsers()[self.browser] self.device = device_utils.DeviceUtils(devices[0]) self.device.StartActivity(intent.Intent( activity=self.package_info.activity, package=self.package_info.package), blocking=True)
def StopTracing(self): if self._is_tracing: self._device.BroadcastIntent( intent.Intent(action='%s.GPU_PROFILER_STOP' % self._package_info.package)) self._trace_file = self._logcat_monitor.WaitFor( self._trace_finish_re, timeout=120).group(1) self._is_tracing = False if self._trace_memory: self._device.SetProp(_HEAP_PROFILE_MMAP_PROPERTY, 0)
def setUp(self): devices = device_utils.DeviceUtils.HealthyDevices() self.browser = 'stable' self.package_info = profiler.GetSupportedBrowsers()[self.browser] self.device = devices[0] self.device.ForceStop(self.package_info.package) self.device.StartActivity( intent.Intent(activity=self.package_info.activity, package=self.package_info.package), blocking=True)
def _SetupTracing(self): # TODO(lizeb): Figure out how to clean up the command-line file when # _TearDownTracing() is not executed in StopTracing(). changer = flag_changer.FlagChanger(self._device, self._package_info.cmdline_file) changer.AddFlags(['--trace-startup']) self._device.ForceStop(self._package_info.package) if self._cold: self._device.EnableRoot() cache_control.CacheControl(self._device).DropRamCaches() launch_intent = None if self._url == '': launch_intent = intent.Intent(action='android.intent.action.MAIN', package=self._package_info.package, activity=self._package_info.activity) else: launch_intent = intent.Intent(package=self._package_info.package, activity=self._package_info.activity, data=self._url, extras={'create_new_tab': True}) self._device.StartActivity(launch_intent, blocking=True)
def Start(self): self._SetUpCommandLine() self._adb.device().RunShellCommand('logcat -c') if self.browser_options.startup_url: url = self.browser_options.startup_url elif self.browser_options.profile_dir: url = None else: # If we have no existing tabs start with a blank page since default # startup with the NTP can lead to race conditions with Telemetry url = 'about:blank' # Dismiss any error dialogs. Limit the number in case we have an error loop # or we are failing to dismiss. for _ in xrange(10): if not self._adb.device().old_interface.DismissCrashDialogIfNeeded( ): break self._adb.device().StartActivity(intent.Intent( package=self._backend_settings.package, activity=self._backend_settings.activity, action=None, data=url, category=None), blocking=True) self._adb.Forward( 'tcp:%d' % self._port, self._backend_settings.GetDevtoolsRemotePort(self._adb)) try: self._WaitForBrowserToComeUp() except exceptions.BrowserGoneException: logging.critical('Failed to connect to browser.') if not self._adb.device( ).old_interface.CanAccessProtectedFileContents(): logging.critical( 'Resolve this by either: ' '(1) Flashing to a userdebug build OR ' '(2) Manually enabling web debugging in Chrome at ' 'Settings > Developer tools > Enable USB Web debugging.') sys.exit(1) except: import traceback traceback.print_exc() self.Close() raise finally: self._RestoreCommandLine()
def RunPageInteractions(self, action_runner): action_runner.tab.WaitForDocumentReadyStateToBeComplete() # Launch clock app, pushing Chrome to the background. android_platform = action_runner.tab.browser.platform android_platform.LaunchAndroidApplication( intent.Intent(package='com.google.android.deskclock', activity='com.android.deskclock.DeskClock'), app_has_webviews=False) # Take measurement. self._TakeMemoryMeasurement(action_runner, 'background') # Go back to Chrome. android_platform.android_action_runner.InputKeyEvent(keyevent.KEYCODE_BACK)
def GoHome(self, timeout=None, retries=None): """Return to the home screen. Args: timeout: timeout in seconds retries: number of retries Raises: CommandTimeoutError on timeout. DeviceUnreachableError on missing device. """ self.StartActivity(intent.Intent( action='android.intent.action.MAIN', category='android.intent.category.HOME'), blocking=True)
def _RunTest(self, test, timeout): self.device.ClearApplicationState(self._package) if self.flags: if 'Feature:FirstRunExperience' in self.test_pkg.GetTestAnnotations( test): self.flags.RemoveFlags(['--disable-fre']) else: self.flags.AddFlags(['--disable-fre']) self.device.StartActivity(intent.Intent( action='android.intent.action.MAIN', activity=self._activity, package=self._package), blocking=True, force_stop=True) return self.device.old_interface.RunUIAutomatorTest( test, self.test_pkg.GetPackageName(), timeout)
def testWebView(self): if self._device is None: logging.warning('No device found, skipping test.') return start_intent = intent.Intent( package='com.google.android.googlequicksearchbox', activity='.SearchActivity', action='com.google.android.googlequicksearchbox.GOOGLE_SEARCH', data=None, extras={'query': 'google'}, category=None) search_app = self.CreateAndroidApp(start_intent) webview = search_app.GetProcess(':search').GetWebViews().pop() webview.Navigate('https://www.google.com/search?q=flowers') time.sleep(5)
def Start(self): self._adb.device().RunShellCommand('logcat -c') if self.browser_options.startup_url: url = self.browser_options.startup_url elif self.browser_options.profile_dir: url = None else: # If we have no existing tabs start with a blank page since default # startup with the NTP can lead to race conditions with Telemetry url = 'about:blank' self.platform_backend.DismissCrashDialogIfNeeded() browser_startup_args = self.GetBrowserStartupArgs() with android_command_line_backend.SetUpCommandLineFlags( self._adb, self._backend_settings, browser_startup_args): self._adb.device().StartActivity(intent.Intent( package=self._backend_settings.package, activity=self._backend_settings.activity, action=None, data=url, category=None), blocking=True) remote_devtools_port = self._backend_settings.GetDevtoolsRemotePort( self._adb) self.platform_backend.ForwardHostToDevice(self._port, remote_devtools_port) try: self._WaitForBrowserToComeUp() self._InitDevtoolsClientBackend(remote_devtools_port) except exceptions.BrowserGoneException: logging.critical('Failed to connect to browser.') device = self._adb.device() if not device.old_interface.CanAccessProtectedFileContents(): logging.critical( 'Resolve this by either: ' '(1) Flashing to a userdebug build OR ' '(2) Manually enabling web debugging in Chrome at ' 'Settings > Developer tools > Enable USB Web debugging.' ) sys.exit(1) except: import traceback traceback.print_exc() self.Close() raise
def __init__(self, adb): self._adb = adb adb.RunShellCommand('rm %s' % DONE_FILE) config = BENCHMARK_CONFIG config['HOST'] = GetServersHost(adb) start_intent = intent.Intent( package=APP_PACKAGE, activity=APP_ACTIVITY, action=APP_ACTION, # |config| maps from configuration value names to the configured values. # |config| is encoded as URL parameter names and values and passed to # the Cronet perf test app via the Intent data field. data='http://dummy/?' + urllib.urlencode(config), extras=None, category=None) super(CronetPerfTestAndroidStory, self).__init__(start_intent, name='CronetPerfTest')
def __init__(self, browser_backend, platform_backend, output_path, state): super(OOMKillerProfiler, self).__init__( browser_backend, platform_backend, output_path, state) if not 'mem_consumer_launched' in state: state['mem_consumer_launched'] = True mem_consumer_path = support_binaries.FindPath( os.path.join('apks', 'MemConsumer.apk'), 'android') assert mem_consumer_path, ('Could not find memconsumer app. Please build ' 'memconsumer target.') self._browser_backend.adb.Install(mem_consumer_path) self._browser_backend.adb.device().GoHome() self._platform_backend.LaunchApplication( 'org.chromium.memconsumer/.MemConsumer', '--ei memory 20') # Bring the browser to the foreground after launching the mem consumer self._browser_backend.adb.device().StartActivity( intent.Intent(package=browser_backend.package, activity=browser_backend.activity), blocking=True)
def _RunTest(self, test, timeout): self.device.ClearApplicationState(self._package) if self.flags: if 'Feature:FirstRunExperience' in self.test_pkg.GetTestAnnotations( test): self.flags.RemoveFlags(['--disable-fre']) else: self.flags.AddFlags(['--disable-fre']) self.device.StartActivity(intent.Intent( action='android.intent.action.MAIN', activity=self._activity, package=self._package), blocking=True, force_stop=True) cmd = [ 'uiautomator', 'runtest', self.test_pkg.GetPackageName(), '-e', 'class', test ] return self.device.RunShellCommand(cmd, timeout=timeout, retries=0)
def _StartActivityAndWaitForLinkerTestStatus(device, timeout): """Force-start an activity and wait up to |timeout| seconds until the full linker test status lines appear in the logcat, recorded through |device|. Args: device: A DeviceUtils instance. timeout: Timeout in seconds Returns: A (status, logs) tuple, where status is a ResultType constant, and logs if the final logcat output as a string. """ # 1. Start recording logcat with appropriate filters. device.old_interface.StartRecordingLogcat(clear=True, filters=_LOGCAT_FILTERS) try: # 2. Force-start activity. device.StartActivity(intent.Intent(package=_PACKAGE_NAME, activity=_ACTIVITY_NAME), force_stop=True) # 3. Wait up to |timeout| seconds until the test status is in the logcat. num_tries = 0 max_tries = timeout found = False while num_tries < max_tries: time.sleep(1) num_tries += 1 found, browser_ok, renderer_ok = _CheckLinkerTestStatus( device.old_interface.GetCurrentRecordedLogcat()) if found: break finally: logs = device.old_interface.StopRecordingLogcat() if num_tries >= max_tries: return ResultType.TIMEOUT, logs if browser_ok and renderer_ok: return ResultType.PASS, logs return ResultType.FAIL, logs
def __init__(self, device): self._device = device device.RunShellCommand('rm %s' % DONE_FILE) config = BENCHMARK_CONFIG config['HOST_IP'] = GetServersHost(device) start_intent = intent.Intent( package=APP_PACKAGE, activity=APP_ACTIVITY, action=APP_ACTION, # |config| maps from configuration value names to the configured values. # |config| is encoded as URL parameter names and values and passed to # the Cronet perf test app via the Intent data field. data='http://dummy/?'+urllib.urlencode(config), extras=None, category=None) super(CronetPerfTestAndroidStory, self).__init__( start_intent, name='CronetPerfTest', # No reason to wait for app; Run() will wait for results. By default # StartActivity will timeout waiting for CronetPerfTest, so override # |is_app_ready_predicate| to not wait. is_app_ready_predicate=lambda app: True)
def GetCategories(device, package_info): device.BroadcastIntent( intent.Intent(action='%s.GPU_PROFILER_LIST_CATEGORIES' % package_info.package)) try: json_category_list = device.old_interface.WaitForLogMatch( re.compile(r'{"traceCategoriesList(.*)'), None, timeout=5).group(0) except pexpect.TIMEOUT: raise RuntimeError( 'Performance trace category list marker not found. ' 'Is the correct version of the browser running?') record_categories = [] disabled_by_default_categories = [] json_data = json.loads(json_category_list)['traceCategoriesList'] for item in json_data: if item.startswith('disabled-by-default'): disabled_by_default_categories.append(item) else: record_categories.append(item) return record_categories, disabled_by_default_categories
def RunTest(self, test_name): """Run a Monkey test on the device. Args: test_name: String to use for logging the test result. Returns: A tuple of (TestRunResults, retry). """ self.device.StartActivity(intent.Intent( package=self._package, activity=self._activity, action='android.intent.action.MAIN'), blocking=True, force_stop=True) # Chrome crashes are not always caught by Monkey test runner. # Verify Chrome has the same PID before and after the test. before_pids = self.device.GetPids(self._package) # Run the test. output = '' if before_pids: if len(before_pids.get(self._package, [])) > 1: raise Exception( 'At most one instance of process %s expected but found pids: ' '%s' % (self._package, before_pids)) output = '\n'.join(self._LaunchMonkeyTest()) after_pids = self.device.GetPids(self._package) crashed = True if not self._package in before_pids: logging.error('Failed to start the process.') elif not self._package in after_pids: logging.error('Process %s has died.', before_pids[self._package]) elif before_pids[self._package] != after_pids[self._package]: logging.error('Detected process restart %s -> %s', before_pids[self._package], after_pids[self._package]) else: crashed = False results = base_test_result.TestRunResults() success_pattern = 'Events injected: %d' % self._options.event_count if success_pattern in output and not crashed: result = base_test_result.BaseTestResult( test_name, base_test_result.ResultType.PASS, log=output) else: result = base_test_result.BaseTestResult( test_name, base_test_result.ResultType.FAIL, log=output) if 'chrome' in self._options.package: logging.warning('Starting MinidumpUploadService...') # TODO(jbudorick): Update this after upstreaming. minidump_intent = intent.Intent( action='%s.crash.ACTION_FIND_ALL' % _CHROME_PACKAGE, package=self._package, activity='%s.crash.MinidumpUploadService' % _CHROME_PACKAGE) try: self.device.RunShellCommand(['am', 'startservice'] + minidump_intent.am_args, as_root=True, check_return=True) except device_errors.CommandFailedError: logging.exception('Failed to start MinidumpUploadService') results.AddResult(result) return results, False
def main(argv): option_parser = optparse.OptionParser() option_parser.add_option('-l', '--low', help='Simulate Activity#onLowMemory()', action='store_true') option_parser.add_option( '-t', '--trim', help=('Simulate Activity#onTrimMemory(...) with ' + ', '.join(ACTION_TRIM.keys())), type='string') option_parser.add_option('-b', '--browser', default=DEFAULT_BROWSER, help=('Which browser to use. One of ' + ', '.join(constants.PACKAGE_INFO.keys()) + ' [default: %default]'), type='string') (options, args) = option_parser.parse_args(argv) if len(args) > 1: print 'Unknown argument: ', args[1:] option_parser.print_help() sys.exit(1) if options.low and options.trim: option_parser.error('options --low and --trim are mutually exclusive') if not options.low and not options.trim: option_parser.print_help() sys.exit(1) action = None if options.low: action = ACTION_LOW elif options.trim in ACTION_TRIM.keys(): action = ACTION_TRIM[options.trim] if action is None: option_parser.print_help() sys.exit(1) if not options.browser in constants.PACKAGE_INFO.keys(): option_parser.error('Unknown browser option ' + options.browser) package_info = constants.PACKAGE_INFO[options.browser] package = package_info.package activity = package_info.activity devices = device_utils.DeviceUtils.HealthyDevices() if not devices: raise device_errors.NoDevicesError() elif len(devices) > 1: logging.warning('Multiple devices attached. Using %s.', str(devices[0])) device = devices[0] try: device.EnableRoot() except device_errors.CommandFailedError as e: # Try to change the flags and start the activity anyway. # TODO(jbudorick) Handle this exception appropriately after interface # conversions are finished. logging.error(str(e)) flags = flag_changer.FlagChanger(device, package_info.cmdline_file) if ENABLE_TEST_INTENTS_FLAG not in flags.Get(): flags.AddFlags([ENABLE_TEST_INTENTS_FLAG]) device.StartActivity( intent.Intent(package=package, activity=activity, action=action))
def Start(self): self._SetUpCommandLine() # Disables android.net SSL certificate check. This is necessary for # applications using the android.net stack to work with proxy HTTPS server # created by telemetry if self._backend_settings.relax_ssl_check: self._saved_sslflag = self._adb.device().GetProp( 'socket.relaxsslcheck') self._adb.device().SetProp('socket.relaxsslcheck', 'yes') self._adb.device().RunShellCommand('logcat -c') if self.browser_options.startup_url: url = self.browser_options.startup_url elif self.browser_options.profile_dir: url = None else: # If we have no existing tabs start with a blank page since default # startup with the NTP can lead to race conditions with Telemetry url = 'about:blank' # Dismiss any error dialogs. Limit the number in case we have an error loop # or we are failing to dismiss. for _ in xrange(10): if not self._adb.device().old_interface.DismissCrashDialogIfNeeded( ): break self._adb.device().StartActivity(intent.Intent( package=self._backend_settings.package, activity=self._backend_settings.activity, action=None, data=url, category=None), blocking=True) self._adb.Forward('tcp:%d' % self._port, self._backend_settings.GetDevtoolsRemotePort()) try: self._WaitForBrowserToComeUp() except exceptions.BrowserGoneException: logging.critical('Failed to connect to browser.') if not self._adb.device( ).old_interface.CanAccessProtectedFileContents(): logging.critical( 'Resolve this by either: ' '(1) Flashing to a userdebug build OR ' '(2) Manually enabling web debugging in Chrome at ' 'Settings > Developer tools > Enable USB Web debugging.') sys.exit(1) except: import traceback traceback.print_exc() self.Close() raise finally: # Restore the saved command line if it appears to have come from a user. # If it appears to be a Telemetry created command line, then don't restore # it. This is to prevent a common bug where --host-resolver-rules borks # people's browsers if something goes wrong with Telemetry. self._SetCommandLineFile( self._saved_cmdline if '--host-resolver-rules' not in self._saved_cmdline else '')
def Start(self): self.device.RunShellCommand('logcat -c') if self.browser_options.startup_url: url = self.browser_options.startup_url elif self.browser_options.profile_dir: url = None else: # If we have no existing tabs start with a blank page since default # startup with the NTP can lead to race conditions with Telemetry url = 'about:blank' self.platform_backend.DismissCrashDialogIfNeeded() browser_startup_args = self.GetBrowserStartupArgs() with android_command_line_backend.SetUpCommandLineFlags( self.device, self._backend_settings, browser_startup_args): self.device.StartActivity(intent.Intent( package=self._backend_settings.package, activity=self._backend_settings.activity, action=None, data=url, category=None), blocking=True) remote_devtools_port = self._backend_settings.GetDevtoolsRemotePort( self.device) try: self.platform_backend.ForwardHostToDevice( self._port, remote_devtools_port) except Exception: logging.exception('Failed to forward %s to %s.', str(self._port), str(remote_devtools_port)) logging.warning('Currently forwarding:') try: for line in self.device.adb.ForwardList().splitlines(): logging.warning(' %s', line) except Exception: logging.warning('Exception raised while listing forwarded ' 'connections.') logging.warning('Device unix domain sockets in use:') try: for line in self.device.ReadFile( '/proc/net/unix', as_root=True, force_pull=True).splitlines(): logging.warning(' %s', line) except Exception: logging.warning( 'Exception raised while listing unix domain sockets.') raise try: self._WaitForBrowserToComeUp() self._InitDevtoolsClientBackend(remote_devtools_port) except exceptions.BrowserGoneException: logging.critical('Failed to connect to browser.') if not (self.device.HasRoot() or self.device.NeedsSU()): logging.critical( 'Resolve this by either: ' '(1) Flashing to a userdebug build OR ' '(2) Manually enabling web debugging in Chrome at ' 'Settings > Developer tools > Enable USB Web debugging.' ) self.Close() raise except: self.Close() raise