def _initializeApkAttributes(self, args, error_func): if args.apk_under_test.endswith('.apk'): self._apk_under_test = args.apk_under_test else: self._apk_under_test = os.path.join(constants.GetOutDirectory(), constants.SDK_BUILD_APKS_DIR, '%s.apk' % args.apk_under_test) if not os.path.exists(self._apk_under_test): error_func('Unable to find APK under test: %s' % self._apk_under_test) apk = apk_helper.ApkHelper(self._apk_under_test) self._apk_under_test_permissions = apk.GetPermissions() if args.test_apk.endswith('.apk'): self._suite = os.path.splitext(os.path.basename(args.test_apk))[0] self._test_apk = args.test_apk else: self._suite = args.test_apk self._test_apk = os.path.join(constants.GetOutDirectory(), constants.SDK_BUILD_APKS_DIR, '%s.apk' % args.test_apk) self._test_jar = os.path.join(constants.GetOutDirectory(), constants.SDK_BUILD_TEST_JAVALIB_DIR, '%s.jar' % self._suite) self._test_support_apk = os.path.join( constants.GetOutDirectory(), constants.SDK_BUILD_TEST_JAVALIB_DIR, '%sSupport.apk' % self._suite) if not os.path.exists(self._test_apk): error_func('Unable to find test APK: %s' % self._test_apk) if not os.path.exists(self._test_jar): error_func('Unable to find test JAR: %s' % self._test_jar) apk = apk_helper.ApkHelper(self.test_apk) self._test_package = apk.GetPackageName() self._test_permissions = apk.GetPermissions() self._test_runner = apk.GetInstrumentationName() self._package_info = None for package_info in constants.PACKAGE_INFO.itervalues(): if self._test_package == package_info.test_package: self._package_info = package_info if not self._package_info: logging.warning('Unable to find package info for %s', self._test_package) for apk in args.additional_apks: if not os.path.exists(apk): error_func('Unable to find additional APK: %s' % apk) self._additional_apks = args.additional_apks
def main(): parser = argparse.ArgumentParser() parser.add_argument( '--adb-path', type=os.path.realpath, help='adb binary') parser.add_argument( '--apk-path', type=os.path.realpath, required=True, help='APK to profile') parser.add_argument( '--output-directory', type=os.path.realpath, required=True, help='Chromium output directory (e.g. out/Release)') parser.add_argument( '--trace-directory', type=os.path.realpath, help='Directory in which cyglog traces will be stored. ' 'Defaults to <output-directory>/cyglog_data') args = parser.parse_args() devil_chromium.Initialize( output_directory=args.output_directory, adb_path=args.adb_path) apk = apk_helper.ApkHelper(args.apk_path) package_info = None for p in constants.PACKAGE_INFO.itervalues(): if p.package == apk.GetPackageName(): package_info = p break else: raise Exception('Unable to determine package info for %s' % args.apk_path) profiler = AndroidProfileTool( args.output_directory, host_cyglog_dir=args.trace_directory) profiler.CollectProfile(args.apk_path, package_info) return 0
def _InstallApk(install_incremental, inc_install_script, devices_obj, apk_to_install): if install_incremental: helper = apk_helper.ApkHelper(apk_to_install) try: install_wrapper = imp.load_source('install_wrapper', inc_install_script) except IOError: raise Exception('Incremental install script not found: %s\n' % inc_install_script) params = install_wrapper.GetInstallParameters() def install_incremental_apk(device): from incremental_install import installer installer.Install(device, helper, split_globs=params['splits'], native_libs=params['native_libs'], dex_files=params['dex_files'], permissions=None) devices_obj.pMap(install_incremental_apk) else: # Install the regular apk on devices. def install(device): device.Install(apk_to_install) devices_obj.pMap(install)
def main(): parser = CreateArgumentParser() args = parser.parse_args() devil_chromium.Initialize(output_directory=args.output_directory, adb_path=args.adb_path) apk = apk_helper.ApkHelper(args.apk_path) package_info = None for p in constants.PACKAGE_INFO.itervalues(): if p.package == apk.GetPackageName(): package_info = p break else: raise Exception('Unable to determine package info for %s' % args.apk_path) trace_directory = args.trace_directory if not trace_directory: trace_directory = os.path.join(args.output_directory, 'profile_data') profiler = AndroidProfileTool(args.output_directory, host_profile_dir=trace_directory, use_wpr=not args.no_wpr, urls=args.urls, simulate_user=args.simulate_user) profiler.CollectProfile(args.apk_path, package_info) return 0
def testGetArchitectures(self): AbiPair = collections.namedtuple('AbiPair', ['abi32bit', 'abi64bit']) for abi_pair in [AbiPair('lib/' + abis.ARM, 'lib/' + abis.ARM_64), AbiPair('lib/' + abis.X86, 'lib/' + abis.X86_64)]: with _MockListApkPaths([abi_pair.abi32bit]): helper = apk_helper.ApkHelper('') self.assertEquals(set([os.path.basename(abi_pair.abi32bit), os.path.basename(abi_pair.abi64bit)]), set(helper.GetAbis())) with _MockListApkPaths([abi_pair.abi32bit, abi_pair.abi64bit]): helper = apk_helper.ApkHelper('') self.assertEquals(set([os.path.basename(abi_pair.abi32bit), os.path.basename(abi_pair.abi64bit)]), set(helper.GetAbis())) with _MockListApkPaths([abi_pair.abi64bit]): helper = apk_helper.ApkHelper('') self.assertEquals(set([os.path.basename(abi_pair.abi64bit)]), set(helper.GetAbis()))
def __init__(self, apk_path, jar_path, test_support_apk_path, additional_apks=None, apk_under_test=None): test_jar.TestJar.__init__(self, jar_path) if not os.path.exists(apk_path): raise Exception('%s not found, please build it' % apk_path) self._additional_apks = additional_apks or [] self._apk_name = os.path.splitext(os.path.basename(apk_path))[0] if apk_under_test: self._apk_under_test = apk_helper.ApkHelper(apk_under_test) else: self._apk_under_test = None self._test_apk = apk_helper.ApkHelper(apk_path) self._test_support_apk_path = test_support_apk_path
def testGetAllInstrumentations(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') all_instrumentations = helper.GetAllInstrumentations() self.assertEquals(len(all_instrumentations), 2) self.assertEquals(all_instrumentations[0]['android:name'], 'org.chromium.RandomJUnit4TestRunner') self.assertEquals(all_instrumentations[1]['android:name'], 'org.chromium.RandomTestRunner')
def _initializeDriverAttributes(self): self._driver_apk = os.path.join( constants.GetOutDirectory(), constants.SDK_BUILD_APKS_DIR, 'OnDeviceInstrumentationDriver.apk') if os.path.exists(self._driver_apk): driver_apk = apk_helper.ApkHelper(self._driver_apk) self._driver_package = driver_apk.GetPackageName() self._driver_name = driver_apk.GetInstrumentationName() else: self._driver_apk = None
def testGetPermssions(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') all_permissions = helper.GetPermissions() self.assertEquals(len(all_permissions), 3) self.assertTrue('android.permission.INTERNET' in all_permissions) self.assertTrue( 'android.permission.READ_EXTERNAL_STORAGE' in all_permissions) self.assertTrue( 'android.permission.ACCESS_FINE_LOCATION' in all_permissions)
def testGetAllMetadata(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals([('name1', 'value1'), ('name2', 'value2')], helper.GetAllMetadata())
def testGetSingleJUnit4InstrumentationName(self): with _MockAaptDump(_SINGLE_J4_INSTRUMENTATION_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals('org.chromium.RandomJ4TestRunner', helper.GetInstrumentationName())
def testHasIsolatedProcesses_oneIsolatedProcess(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertTrue(helper.HasIsolatedProcesses())
def testHasIsolatedProcesses_oneNotIsolatedProcess(self): with _MockAaptDump(_NO_ISOLATED_SERVICES): helper = apk_helper.ApkHelper('') self.assertFalse(helper.HasIsolatedProcesses())
def testHasIsolatedProcesses_noServices(self): with _MockAaptDump(_NO_SERVICES): helper = apk_helper.ApkHelper('') self.assertFalse(helper.HasIsolatedProcesses())
def __init__(self, args, isolate_delegate, error_func): super(GtestTestInstance, self).__init__() # TODO(jbudorick): Support multiple test suites. if len(args.suite_name) > 1: raise ValueError( 'Platform mode currently supports only 1 gtest suite') self._extract_test_list_from_filter = args.extract_test_list_from_filter self._shard_timeout = args.shard_timeout self._suite = args.suite_name[0] self._exe_dist_dir = None # GYP: if args.executable_dist_dir: self._exe_dist_dir = os.path.abspath(args.executable_dist_dir) else: # TODO(agrieve): Remove auto-detection once recipes pass flag explicitly. exe_dist_dir = os.path.join(constants.GetOutDirectory(), '%s__dist' % self._suite) if os.path.exists(exe_dist_dir): self._exe_dist_dir = exe_dist_dir incremental_part = '' if args.test_apk_incremental_install_script: incremental_part = '_incremental' apk_path = os.path.join( constants.GetOutDirectory(), '%s_apk' % self._suite, '%s-debug%s.apk' % (self._suite, incremental_part)) self._test_apk_incremental_install_script = ( args.test_apk_incremental_install_script) if not os.path.exists(apk_path): self._apk_helper = None else: self._apk_helper = apk_helper.ApkHelper(apk_path) self._extras = { _EXTRA_NATIVE_TEST_ACTIVITY: self._apk_helper.GetActivityName(), } if self._suite in RUN_IN_SUB_THREAD_TEST_SUITES: self._extras[_EXTRA_RUN_IN_SUB_THREAD] = 1 if self._suite in BROWSER_TEST_SUITES: self._extras[_EXTRA_SHARD_SIZE_LIMIT] = 1 self._extras[EXTRA_SHARD_NANO_TIMEOUT] = int( 1e9 * self._shard_timeout) self._shard_timeout = 10 * self._shard_timeout if not self._apk_helper and not self._exe_dist_dir: error_func('Could not find apk or executable for %s' % self._suite) self._data_deps = [] if args.test_filter: self._gtest_filter = args.test_filter elif args.test_filter_file: with open(args.test_filter_file, 'r') as f: self._gtest_filter = ':'.join(l.strip() for l in f) else: self._gtest_filter = None if (args.isolate_file_path and not isolator.IsIsolateEmpty(args.isolate_file_path)): self._isolate_abs_path = os.path.abspath(args.isolate_file_path) self._isolate_delegate = isolate_delegate self._isolated_abs_path = os.path.join(constants.GetOutDirectory(), '%s.isolated' % self._suite) else: logging.warning( '%s isolate file provided. No data deps will be pushed.', 'Empty' if args.isolate_file_path else 'No') self._isolate_delegate = None if args.app_data_files: self._app_data_files = args.app_data_files if args.app_data_file_dir: self._app_data_file_dir = args.app_data_file_dir else: self._app_data_file_dir = tempfile.mkdtemp() logging.critical('Saving app files to %s', self._app_data_file_dir) else: self._app_data_files = None self._app_data_file_dir = None self._test_arguments = args.test_arguments # TODO(jbudorick): Remove this once it's deployed. self._enable_xml_result_parsing = args.enable_xml_result_parsing
def testGetTargetSdkVersion_integerValue(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals('28', helper.GetTargetSdkVersion())
def __init__(self, args, isolate_delegate, error_func): super(GtestTestInstance, self).__init__() # TODO(jbudorick): Support multiple test suites. if len(args.suite_name) > 1: raise ValueError( 'Platform mode currently supports only 1 gtest suite') self._suite = args.suite_name[0] self._shard_timeout = args.shard_timeout incremental_part = '_incremental' if args.incremental_install else '' apk_path = os.path.join( constants.GetOutDirectory(), '%s_apk' % self._suite, '%s-debug%s.apk' % (self._suite, incremental_part)) self._exe_path = os.path.join(constants.GetOutDirectory(), self._suite) if not os.path.exists(apk_path): self._apk_helper = None else: self._apk_helper = apk_helper.ApkHelper(apk_path) self._extras = { _EXTRA_NATIVE_TEST_ACTIVITY: self._apk_helper.GetActivityName(), } if self._suite in RUN_IN_SUB_THREAD_TEST_SUITES: self._extras[_EXTRA_RUN_IN_SUB_THREAD] = 1 if self._suite in BROWSER_TEST_SUITES: self._extras[_EXTRA_SHARD_SIZE_LIMIT] = 1 self._extras[EXTRA_SHARD_NANO_TIMEOUT] = int( 1e9 * self._shard_timeout) self._shard_timeout = 900 if not os.path.exists(self._exe_path): self._exe_path = None if not self._apk_helper and not self._exe_path: error_func('Could not find apk or executable for %s' % self._suite) self._data_deps = [] if args.test_filter: self._gtest_filter = args.test_filter elif args.test_filter_file: with open(args.test_filter_file, 'r') as f: self._gtest_filter = ':'.join(l.strip() for l in f) else: self._gtest_filter = None if not args.isolate_file_path: default_isolate_file_path = _DEFAULT_ISOLATE_FILE_PATHS.get( self._suite) if default_isolate_file_path: args.isolate_file_path = os.path.join( host_paths.DIR_SOURCE_ROOT, default_isolate_file_path) if args.isolate_file_path: self._isolate_abs_path = os.path.abspath(args.isolate_file_path) self._isolate_delegate = isolate_delegate self._isolated_abs_path = os.path.join(constants.GetOutDirectory(), '%s.isolated' % self._suite) else: logging.warning( 'No isolate file provided. No data deps will be pushed.') self._isolate_delegate = None if args.app_data_files: self._app_data_files = args.app_data_files if args.app_data_file_dir: self._app_data_file_dir = args.app_data_file_dir else: self._app_data_file_dir = tempfile.mkdtemp() logging.critical('Saving app files to %s', self._app_data_file_dir) else: self._app_data_files = None self._app_data_file_dir = None self._test_arguments = args.test_arguments
def testGetViewActivityName(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals(helper.GetViewActivityName(), 'org.chromium.ViewActivity')
def testGetSingleInstrumentationName_strippedNamespaces(self): with _MockAaptDump(_NO_NAMESPACE_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals('org.chromium.RandomTestRunner', helper.GetInstrumentationName())
def testGetInstrumentationName(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') with self.assertRaises(base_error.BaseError): helper.GetInstrumentationName()
def __init__(self, args, data_deps_delegate, error_func): super(GtestTestInstance, self).__init__() # TODO(jbudorick): Support multiple test suites. if len(args.suite_name) > 1: raise ValueError( 'Platform mode currently supports only 1 gtest suite') self._coverage_dir = args.coverage_dir self._exe_dist_dir = None self._external_shard_index = args.test_launcher_shard_index self._extract_test_list_from_filter = args.extract_test_list_from_filter self._filter_tests_lock = threading.Lock() self._gs_test_artifacts_bucket = args.gs_test_artifacts_bucket self._isolated_script_test_output = args.isolated_script_test_output self._isolated_script_test_perf_output = ( args.isolated_script_test_perf_output) self._render_test_output_dir = args.render_test_output_dir self._shard_timeout = args.shard_timeout self._store_tombstones = args.store_tombstones self._suite = args.suite_name[0] self._symbolizer = stack_symbolizer.Symbolizer(None) self._total_external_shards = args.test_launcher_total_shards self._wait_for_java_debugger = args.wait_for_java_debugger # GYP: if args.executable_dist_dir: self._exe_dist_dir = os.path.abspath(args.executable_dist_dir) else: # TODO(agrieve): Remove auto-detection once recipes pass flag explicitly. exe_dist_dir = os.path.join(constants.GetOutDirectory(), '%s__dist' % self._suite) if os.path.exists(exe_dist_dir): self._exe_dist_dir = exe_dist_dir incremental_part = '' if args.test_apk_incremental_install_json: incremental_part = '_incremental' self._test_launcher_batch_limit = MAX_SHARDS if (args.test_launcher_batch_limit and 0 < args.test_launcher_batch_limit < MAX_SHARDS): self._test_launcher_batch_limit = args.test_launcher_batch_limit apk_path = os.path.join( constants.GetOutDirectory(), '%s_apk' % self._suite, '%s-debug%s.apk' % (self._suite, incremental_part)) self._test_apk_incremental_install_json = ( args.test_apk_incremental_install_json) if not os.path.exists(apk_path): self._apk_helper = None else: self._apk_helper = apk_helper.ApkHelper(apk_path) self._extras = { _EXTRA_NATIVE_TEST_ACTIVITY: self._apk_helper.GetActivityName(), } if self._suite in RUN_IN_SUB_THREAD_TEST_SUITES: self._extras[_EXTRA_RUN_IN_SUB_THREAD] = 1 if self._suite in BROWSER_TEST_SUITES: self._extras[_EXTRA_SHARD_SIZE_LIMIT] = 1 self._extras[EXTRA_SHARD_NANO_TIMEOUT] = int( 1e9 * self._shard_timeout) self._shard_timeout = 10 * self._shard_timeout if args.wait_for_java_debugger: self._extras[EXTRA_SHARD_NANO_TIMEOUT] = int(1e15) # Forever if not self._apk_helper and not self._exe_dist_dir: error_func('Could not find apk or executable for %s' % self._suite) self._data_deps = [] self._gtest_filter = test_filter.InitializeFilterFromArgs(args) self._run_disabled = args.run_disabled self._data_deps_delegate = data_deps_delegate self._runtime_deps_path = args.runtime_deps_path if not self._runtime_deps_path: logging.warning('No data dependencies will be pushed.') if args.app_data_files: self._app_data_files = args.app_data_files if args.app_data_file_dir: self._app_data_file_dir = args.app_data_file_dir else: self._app_data_file_dir = tempfile.mkdtemp() logging.critical('Saving app files to %s', self._app_data_file_dir) else: self._app_data_files = None self._app_data_file_dir = None self._flags = None self._initializeCommandLineFlags(args) # TODO(jbudorick): Remove this once it's deployed. self._enable_xml_result_parsing = args.enable_xml_result_parsing
def run_test(options, crash_dir, symbols_dir, platform, additional_arguments=[]): global failure print '# Run content_shell and make it crash.' if platform == 'android': device = GetDevice() failure = None clear_android_dumps(options, device) apk_path = os.path.join(options.build_dir, 'apks', 'ContentShell.apk') apk = apk_helper.ApkHelper(apk_path) view_activity = apk.GetViewActivityName() package_name = apk.GetPackageName() device.RunShellCommand( ['am', 'set-debug-app', '--persistent', package_name]) changer = flag_changer.FlagChanger(device, 'content-shell-command-line') changer.ReplaceFlags([ '--enable-crash-reporter', '--crash-dumps-dir=%s' % ANDROID_CRASH_DIR ]) launch_intent = intent.Intent(action='android.intent.action.VIEW', activity=view_activity, data='chrome://crash', package=package_name) device.StartActivity(launch_intent) else: cmd = [ options.binary, '--run-web-tests', 'chrome://crash', '--enable-crash-reporter', '--crash-dumps-dir=%s' % crash_dir ] cmd += additional_arguments if options.verbose: print ' '.join(cmd) failure = 'Failed to run content_shell.' if options.verbose: subprocess.check_call(cmd) else: # On Windows, using os.devnull can cause check_call to never return, # so use a temporary file for the output. with tempfile.TemporaryFile() as tmpfile: subprocess.check_call(cmd, stdout=tmpfile, stderr=tmpfile) print '# Retrieve crash dump.' if platform == 'android': dmp_file = get_android_dump(crash_dir) else: dmp_dir = crash_dir # TODO(crbug.com/782923): This test should not reach directly into the # Crashpad database, but instead should use crashpad_database_util. if platform == 'darwin': dmp_dir = os.path.join(dmp_dir, 'pending') elif platform == 'win32': dmp_dir = os.path.join(dmp_dir, 'reports') dmp_files = glob.glob(os.path.join(dmp_dir, '*.dmp')) failure = 'Expected 1 crash dump, found %d.' % len(dmp_files) if len(dmp_files) != 1: raise Exception(failure) dmp_file = dmp_files[0] if platform not in ('darwin', 'win32', 'android'): minidump = os.path.join(crash_dir, 'minidump') dmp_to_minidump = os.path.join(BREAKPAD_TOOLS_DIR, 'dmp2minidump.py') cmd = [dmp_to_minidump, dmp_file, minidump] if options.verbose: print ' '.join(cmd) failure = 'Failed to run dmp_to_minidump.' subprocess.check_call(cmd) else: minidump = dmp_file print '# Symbolize crash dump.' if platform == 'win32': cdb_exe = os.path.join(options.build_dir, 'cdb', 'cdb.exe') cmd = [ cdb_exe, '-y', options.build_dir, '-c', '.lines;.excr;k30;q', '-z', dmp_file ] if options.verbose: print ' '.join(cmd) failure = 'Failed to run cdb.exe.' proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stack = proc.communicate()[0] else: minidump_stackwalk = os.path.join(options.build_dir, 'minidump_stackwalk') cmd = [minidump_stackwalk, minidump, symbols_dir] if options.verbose: print ' '.join(cmd) failure = 'Failed to run minidump_stackwalk.' proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stack = proc.communicate()[0] # Check whether the stack contains a CrashIntentionally symbol. found_symbol = 'CrashIntentionally' in stack os.remove(dmp_file) if options.no_symbols: if found_symbol: if options.verbose: print stack failure = 'Found unexpected reference to CrashIntentionally in stack' raise Exception(failure) else: if not found_symbol: if options.verbose: print stack failure = 'Could not find reference to CrashIntentionally in stack.' raise Exception(failure)
def testGetVersionCode(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals(376300010, helper.GetVersionCode())
def testGetSplitName(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals(helper.GetSplitName(), 'random_split')
def testGetVersionName(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals('75.0.3763.0', helper.GetVersionName())
def testHasIsolatedProcesses_noApplication(self): with _MockAaptDump(_NO_APPLICATION): helper = apk_helper.ApkHelper('') self.assertFalse(helper.HasIsolatedProcesses())
def testGetTargetSdkVersion_stringValue(self): with _MockAaptDump(_TARGETING_PRE_RELEASE_Q_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals('Q', helper.GetTargetSdkVersion())
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', default=[], help='Target device for apk to install on. Enter multiple' ' times for multiple devices.') parser.add_argument('--adb-path', type=os.path.abspath, 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.') parser.add_argument('--timeout', type=int, default=device_utils.DeviceUtils.INSTALL_DEFAULT_TIMEOUT, help='Seconds to wait for APK installation. ' '(default: %(default)s)') args = parser.parse_args() run_tests_helper.SetLogLevel(args.verbose) constants.SetBuildType(args.build_type) devil_chromium.Initialize( output_directory=constants.GetOutDirectory(), adb_path=args.adb_path) 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=blacklist, device_arg=args.devices) 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, timeout=args.timeout) 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)
def testGetPackageName(self): with _MockAaptDump(_MANIFEST_DUMP): helper = apk_helper.ApkHelper('') self.assertEquals(helper.GetPackageName(), 'org.chromium.abc')
def main(): parser = argparse.ArgumentParser() parser.add_argument('apk_path', help='The path to the APK to install.') parser.add_argument('--split', action='append', dest='splits', help='A glob matching the apk splits. ' 'Can be specified multiple times.') parser.add_argument('--lib-dir', help='Path to native libraries directory.') parser.add_argument('--dex-files', help='List of dex files to push.', action='append', default=[]) parser.add_argument('-d', '--device', dest='device', help='Target device for apk to install on.') parser.add_argument('--uninstall', action='store_true', default=False, help='Remove the app and all side-loaded files.') parser.add_argument('--output-directory', help='Path to the root build directory.') parser.add_argument('--no-threading', action='store_true', default=False, help='Do not install and push concurrently') parser.add_argument('-v', '--verbose', dest='verbose_count', default=0, action='count', help='Verbose level (multiple times for more)') args = parser.parse_args() run_tests_helper.SetLogLevel(args.verbose_count) constants.SetBuildType('Debug') if args.output_directory: constants.SetOutputDirectory(args.output_directory) main_timer = time_profile.TimeProfile() install_timer = time_profile.TimeProfile() push_native_timer = time_profile.TimeProfile() push_dex_timer = time_profile.TimeProfile() if args.device: # Retries are annoying when commands fail for legitimate reasons. Might want # to enable them if this is ever used on bots though. device = device_utils.DeviceUtils(args.device, default_retries=0) else: devices = device_utils.DeviceUtils.HealthyDevices(default_retries=0) if not devices: raise device_errors.NoDevicesError() elif len(devices) == 1: device = devices[0] else: all_devices = device_utils.DeviceUtils.parallel(devices) msg = ('More than one device available.\n' 'Use --device=SERIAL to select a device.\n' 'Available devices:\n') descriptions = all_devices.pMap(lambda d: d.build_description).pGet(None) for d, desc in zip(devices, descriptions): msg += ' %s (%s)\n' % (d, desc) raise Exception(msg) apk_help = apk_helper.ApkHelper(args.apk_path) apk_package = apk_help.GetPackageName() device_incremental_dir = '/data/local/tmp/incremental-app-%s' % apk_package if args.uninstall: device.Uninstall(apk_package) device.RunShellCommand(['rm', '-rf', device_incremental_dir], check_return=True) logging.info('Uninstall took %s seconds.', main_timer.GetDelta()) return if device.build_version_sdk >= version_codes.MARSHMALLOW: if apk_help.HasIsolatedProcesses(): raise Exception('Cannot use perform incremental installs on Android M+ ' 'without first disabling isolated processes. Use GN arg: ' 'disable_incremental_isolated_processes=true to do so.') # Install .apk(s) if any of them have changed. def do_install(): install_timer.Start() if args.splits: splits = [] for split_glob in args.splits: splits.extend((f for f in glob.glob(split_glob))) device.InstallSplitApk(args.apk_path, splits, reinstall=True, allow_cached_props=True, permissions=()) else: device.Install(args.apk_path, reinstall=True, permissions=()) install_timer.Stop(log=False) # Push .so and .dex files to the device (if they have changed). def do_push_files(): if args.lib_dir: push_native_timer.Start() device_lib_dir = posixpath.join(device_incremental_dir, 'lib') device.PushChangedFiles([(args.lib_dir, device_lib_dir)], delete_device_stale=True) push_native_timer.Stop(log=False) if args.dex_files: push_dex_timer.Start() # Put all .dex files to be pushed into a temporary directory so that we # can use delete_device_stale=True. with build_utils.TempDir() as temp_dir: device_dex_dir = posixpath.join(device_incremental_dir, 'dex') # Ensure no two files have the same name. transformed_names = _TransformDexPaths(args.dex_files) for src_path, dest_name in zip(args.dex_files, transformed_names): shutil.copyfile(src_path, os.path.join(temp_dir, dest_name)) device.PushChangedFiles([(temp_dir, device_dex_dir)], delete_device_stale=True) push_dex_timer.Stop(log=False) # Create 2 lock files: # * install.lock tells the app to pause on start-up (until we release it). # * firstrun.lock is used by the app to pause all secondary processes until # the primary process finishes loading the .dex / .so files. def create_lock_files(): # Creates or zeros out lock files. cmd = ('D="%s";' 'mkdir -p $D &&' 'echo -n >$D/install.lock 2>$D/firstrun.lock') device.RunShellCommand(cmd % device_incremental_dir, check_return=True) # The firstrun.lock is released by the app itself. def release_installer_lock(): device.RunShellCommand('echo > %s/install.lock' % device_incremental_dir, check_return=True) create_lock_files() # Concurrency here speeds things up quite a bit, but DeviceUtils hasn't # been designed for multi-threading. Enabling only because this is a # developer-only tool. if args.no_threading: do_install() do_push_files() else: reraiser_thread.RunAsync((do_install, do_push_files)) release_installer_lock() logging.info('Took %s seconds (install=%s, libs=%s, dex=%s)', main_timer.GetDelta(), install_timer.GetDelta(), push_native_timer.GetDelta(), push_dex_timer.GetDelta())