1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env vpython3 2*6777b538SAndroid Build Coastguard Worker# Copyright 2017 The Chromium Authors 3*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 5*6777b538SAndroid Build Coastguard Worker 6*6777b538SAndroid Build Coastguard Worker# Using colorama.Fore/Back/Style members 7*6777b538SAndroid Build Coastguard Worker# pylint: disable=no-member 8*6777b538SAndroid Build Coastguard Worker 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Workerimport argparse 11*6777b538SAndroid Build Coastguard Workerimport collections 12*6777b538SAndroid Build Coastguard Workerimport json 13*6777b538SAndroid Build Coastguard Workerimport logging 14*6777b538SAndroid Build Coastguard Workerimport os 15*6777b538SAndroid Build Coastguard Workerimport posixpath 16*6777b538SAndroid Build Coastguard Workerimport random 17*6777b538SAndroid Build Coastguard Workerimport re 18*6777b538SAndroid Build Coastguard Workerimport shlex 19*6777b538SAndroid Build Coastguard Workerimport shutil 20*6777b538SAndroid Build Coastguard Workerimport subprocess 21*6777b538SAndroid Build Coastguard Workerimport sys 22*6777b538SAndroid Build Coastguard Workerimport tempfile 23*6777b538SAndroid Build Coastguard Workerimport textwrap 24*6777b538SAndroid Build Coastguard Workerimport zipfile 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Workerimport adb_command_line 27*6777b538SAndroid Build Coastguard Workerimport devil_chromium 28*6777b538SAndroid Build Coastguard Workerfrom devil import devil_env 29*6777b538SAndroid Build Coastguard Workerfrom devil.android import apk_helper 30*6777b538SAndroid Build Coastguard Workerfrom devil.android import device_errors 31*6777b538SAndroid Build Coastguard Workerfrom devil.android import device_utils 32*6777b538SAndroid Build Coastguard Workerfrom devil.android import flag_changer 33*6777b538SAndroid Build Coastguard Workerfrom devil.android.sdk import adb_wrapper 34*6777b538SAndroid Build Coastguard Workerfrom devil.android.sdk import build_tools 35*6777b538SAndroid Build Coastguard Workerfrom devil.android.sdk import intent 36*6777b538SAndroid Build Coastguard Workerfrom devil.android.sdk import version_codes 37*6777b538SAndroid Build Coastguard Workerfrom devil.utils import run_tests_helper 38*6777b538SAndroid Build Coastguard Worker 39*6777b538SAndroid Build Coastguard Worker_DIR_SOURCE_ROOT = os.path.normpath( 40*6777b538SAndroid Build Coastguard Worker os.path.join(os.path.dirname(__file__), '..', '..')) 41*6777b538SAndroid Build Coastguard Worker_JAVA_HOME = os.path.join(_DIR_SOURCE_ROOT, 'third_party', 'jdk', 'current') 42*6777b538SAndroid Build Coastguard Worker 43*6777b538SAndroid Build Coastguard Workerwith devil_env.SysPath( 44*6777b538SAndroid Build Coastguard Worker os.path.join(_DIR_SOURCE_ROOT, 'third_party', 'colorama', 'src')): 45*6777b538SAndroid Build Coastguard Worker import colorama 46*6777b538SAndroid Build Coastguard Worker 47*6777b538SAndroid Build Coastguard Workerfrom incremental_install import installer 48*6777b538SAndroid Build Coastguard Workerfrom pylib import constants 49*6777b538SAndroid Build Coastguard Workerfrom pylib.symbols import deobfuscator 50*6777b538SAndroid Build Coastguard Workerfrom pylib.utils import simpleperf 51*6777b538SAndroid Build Coastguard Workerfrom pylib.utils import app_bundle_utils 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Workerwith devil_env.SysPath( 54*6777b538SAndroid Build Coastguard Worker os.path.join(_DIR_SOURCE_ROOT, 'build', 'android', 'gyp')): 55*6777b538SAndroid Build Coastguard Worker import bundletool 56*6777b538SAndroid Build Coastguard Worker 57*6777b538SAndroid Build Coastguard WorkerBASE_MODULE = 'base' 58*6777b538SAndroid Build Coastguard Worker 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard Workerdef _Colorize(text, style=''): 61*6777b538SAndroid Build Coastguard Worker return (style 62*6777b538SAndroid Build Coastguard Worker + text 63*6777b538SAndroid Build Coastguard Worker + colorama.Style.RESET_ALL) 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard Worker 66*6777b538SAndroid Build Coastguard Workerdef _InstallApk(devices, apk, install_dict): 67*6777b538SAndroid Build Coastguard Worker def install(device): 68*6777b538SAndroid Build Coastguard Worker if install_dict: 69*6777b538SAndroid Build Coastguard Worker installer.Install(device, install_dict, apk=apk, permissions=[]) 70*6777b538SAndroid Build Coastguard Worker else: 71*6777b538SAndroid Build Coastguard Worker device.Install(apk, permissions=[], allow_downgrade=True, reinstall=True) 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Worker logging.info('Installing %sincremental apk.', '' if install_dict else 'non-') 74*6777b538SAndroid Build Coastguard Worker device_utils.DeviceUtils.parallel(devices).pMap(install) 75*6777b538SAndroid Build Coastguard Worker 76*6777b538SAndroid Build Coastguard Worker 77*6777b538SAndroid Build Coastguard Worker# A named tuple containing the information needed to convert a bundle into 78*6777b538SAndroid Build Coastguard Worker# an installable .apks archive. 79*6777b538SAndroid Build Coastguard Worker# Fields: 80*6777b538SAndroid Build Coastguard Worker# bundle_path: Path to input bundle file. 81*6777b538SAndroid Build Coastguard Worker# bundle_apk_path: Path to output bundle .apks archive file. 82*6777b538SAndroid Build Coastguard Worker# aapt2_path: Path to aapt2 tool. 83*6777b538SAndroid Build Coastguard Worker# keystore_path: Path to keystore file. 84*6777b538SAndroid Build Coastguard Worker# keystore_password: Password for the keystore file. 85*6777b538SAndroid Build Coastguard Worker# keystore_alias: Signing key name alias within the keystore file. 86*6777b538SAndroid Build Coastguard Worker# system_image_locales: List of Chromium locales to include in system .apks. 87*6777b538SAndroid Build Coastguard WorkerBundleGenerationInfo = collections.namedtuple( 88*6777b538SAndroid Build Coastguard Worker 'BundleGenerationInfo', 89*6777b538SAndroid Build Coastguard Worker 'bundle_path,bundle_apks_path,aapt2_path,keystore_path,keystore_password,' 90*6777b538SAndroid Build Coastguard Worker 'keystore_alias,system_image_locales') 91*6777b538SAndroid Build Coastguard Worker 92*6777b538SAndroid Build Coastguard Worker 93*6777b538SAndroid Build Coastguard Workerdef _GenerateBundleApks(info, 94*6777b538SAndroid Build Coastguard Worker output_path=None, 95*6777b538SAndroid Build Coastguard Worker minimal=False, 96*6777b538SAndroid Build Coastguard Worker minimal_sdk_version=None, 97*6777b538SAndroid Build Coastguard Worker mode=None, 98*6777b538SAndroid Build Coastguard Worker optimize_for=None): 99*6777b538SAndroid Build Coastguard Worker """Generate an .apks archive from a bundle on demand. 100*6777b538SAndroid Build Coastguard Worker 101*6777b538SAndroid Build Coastguard Worker Args: 102*6777b538SAndroid Build Coastguard Worker info: A BundleGenerationInfo instance. 103*6777b538SAndroid Build Coastguard Worker output_path: Path of output .apks archive. 104*6777b538SAndroid Build Coastguard Worker minimal: Create the minimal set of apks possible (english-only). 105*6777b538SAndroid Build Coastguard Worker minimal_sdk_version: When minimal=True, use this sdkVersion. 106*6777b538SAndroid Build Coastguard Worker mode: Build mode, either None, or one of app_bundle_utils.BUILD_APKS_MODES. 107*6777b538SAndroid Build Coastguard Worker optimize_for: Override split config, either None, or one of 108*6777b538SAndroid Build Coastguard Worker app_bundle_utils.OPTIMIZE_FOR_OPTIONS. 109*6777b538SAndroid Build Coastguard Worker """ 110*6777b538SAndroid Build Coastguard Worker logging.info('Generating .apks file') 111*6777b538SAndroid Build Coastguard Worker app_bundle_utils.GenerateBundleApks( 112*6777b538SAndroid Build Coastguard Worker info.bundle_path, 113*6777b538SAndroid Build Coastguard Worker # Store .apks file beside the .aab file by default so that it gets cached. 114*6777b538SAndroid Build Coastguard Worker output_path or info.bundle_apks_path, 115*6777b538SAndroid Build Coastguard Worker info.aapt2_path, 116*6777b538SAndroid Build Coastguard Worker info.keystore_path, 117*6777b538SAndroid Build Coastguard Worker info.keystore_password, 118*6777b538SAndroid Build Coastguard Worker info.keystore_alias, 119*6777b538SAndroid Build Coastguard Worker system_image_locales=info.system_image_locales, 120*6777b538SAndroid Build Coastguard Worker mode=mode, 121*6777b538SAndroid Build Coastguard Worker minimal=minimal, 122*6777b538SAndroid Build Coastguard Worker minimal_sdk_version=minimal_sdk_version, 123*6777b538SAndroid Build Coastguard Worker optimize_for=optimize_for) 124*6777b538SAndroid Build Coastguard Worker 125*6777b538SAndroid Build Coastguard Worker 126*6777b538SAndroid Build Coastguard Workerdef _InstallBundle(devices, apk_helper_instance, modules, fake_modules): 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker def Install(device): 129*6777b538SAndroid Build Coastguard Worker device.Install(apk_helper_instance, 130*6777b538SAndroid Build Coastguard Worker permissions=[], 131*6777b538SAndroid Build Coastguard Worker modules=modules, 132*6777b538SAndroid Build Coastguard Worker fake_modules=fake_modules, 133*6777b538SAndroid Build Coastguard Worker allow_downgrade=True, 134*6777b538SAndroid Build Coastguard Worker reinstall=True) 135*6777b538SAndroid Build Coastguard Worker 136*6777b538SAndroid Build Coastguard Worker # Basic checks for |modules| and |fake_modules|. 137*6777b538SAndroid Build Coastguard Worker # * |fake_modules| cannot include 'base'. 138*6777b538SAndroid Build Coastguard Worker # * If |fake_modules| is given, ensure |modules| includes 'base'. 139*6777b538SAndroid Build Coastguard Worker # * They must be disjoint (checked by device.Install). 140*6777b538SAndroid Build Coastguard Worker modules_set = set(modules) if modules else set() 141*6777b538SAndroid Build Coastguard Worker fake_modules_set = set(fake_modules) if fake_modules else set() 142*6777b538SAndroid Build Coastguard Worker if BASE_MODULE in fake_modules_set: 143*6777b538SAndroid Build Coastguard Worker raise Exception('\'-f {}\' is disallowed.'.format(BASE_MODULE)) 144*6777b538SAndroid Build Coastguard Worker if fake_modules_set and BASE_MODULE not in modules_set: 145*6777b538SAndroid Build Coastguard Worker raise Exception( 146*6777b538SAndroid Build Coastguard Worker '\'-f FAKE\' must be accompanied by \'-m {}\''.format(BASE_MODULE)) 147*6777b538SAndroid Build Coastguard Worker 148*6777b538SAndroid Build Coastguard Worker logging.info('Installing bundle.') 149*6777b538SAndroid Build Coastguard Worker device_utils.DeviceUtils.parallel(devices).pMap(Install) 150*6777b538SAndroid Build Coastguard Worker 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Workerdef _UninstallApk(devices, install_dict, package_name): 153*6777b538SAndroid Build Coastguard Worker def uninstall(device): 154*6777b538SAndroid Build Coastguard Worker if install_dict: 155*6777b538SAndroid Build Coastguard Worker installer.Uninstall(device, package_name) 156*6777b538SAndroid Build Coastguard Worker else: 157*6777b538SAndroid Build Coastguard Worker device.Uninstall(package_name) 158*6777b538SAndroid Build Coastguard Worker device_utils.DeviceUtils.parallel(devices).pMap(uninstall) 159*6777b538SAndroid Build Coastguard Worker 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Workerdef _IsWebViewProvider(apk_helper_instance): 162*6777b538SAndroid Build Coastguard Worker meta_data = apk_helper_instance.GetAllMetadata() 163*6777b538SAndroid Build Coastguard Worker meta_data_keys = [pair[0] for pair in meta_data] 164*6777b538SAndroid Build Coastguard Worker return 'com.android.webview.WebViewLibrary' in meta_data_keys 165*6777b538SAndroid Build Coastguard Worker 166*6777b538SAndroid Build Coastguard Worker 167*6777b538SAndroid Build Coastguard Workerdef _SetWebViewProvider(devices, package_name): 168*6777b538SAndroid Build Coastguard Worker 169*6777b538SAndroid Build Coastguard Worker def switch_provider(device): 170*6777b538SAndroid Build Coastguard Worker if device.build_version_sdk < version_codes.NOUGAT: 171*6777b538SAndroid Build Coastguard Worker logging.error('No need to switch provider on pre-Nougat devices (%s)', 172*6777b538SAndroid Build Coastguard Worker device.serial) 173*6777b538SAndroid Build Coastguard Worker else: 174*6777b538SAndroid Build Coastguard Worker device.SetWebViewImplementation(package_name) 175*6777b538SAndroid Build Coastguard Worker 176*6777b538SAndroid Build Coastguard Worker device_utils.DeviceUtils.parallel(devices).pMap(switch_provider) 177*6777b538SAndroid Build Coastguard Worker 178*6777b538SAndroid Build Coastguard Worker 179*6777b538SAndroid Build Coastguard Workerdef _NormalizeProcessName(debug_process_name, package_name): 180*6777b538SAndroid Build Coastguard Worker if not debug_process_name: 181*6777b538SAndroid Build Coastguard Worker debug_process_name = package_name 182*6777b538SAndroid Build Coastguard Worker elif debug_process_name.startswith(':'): 183*6777b538SAndroid Build Coastguard Worker debug_process_name = package_name + debug_process_name 184*6777b538SAndroid Build Coastguard Worker elif '.' not in debug_process_name: 185*6777b538SAndroid Build Coastguard Worker debug_process_name = package_name + ':' + debug_process_name 186*6777b538SAndroid Build Coastguard Worker return debug_process_name 187*6777b538SAndroid Build Coastguard Worker 188*6777b538SAndroid Build Coastguard Worker 189*6777b538SAndroid Build Coastguard Workerdef _ResolveActivity(device, package_name, category, action): 190*6777b538SAndroid Build Coastguard Worker # E.g.: 191*6777b538SAndroid Build Coastguard Worker # Activity Resolver Table: 192*6777b538SAndroid Build Coastguard Worker # Schemes: 193*6777b538SAndroid Build Coastguard Worker # http: 194*6777b538SAndroid Build Coastguard Worker # 67e97c0 org.chromium.pkg/.MainActivityfilter c91d43e 195*6777b538SAndroid Build Coastguard Worker # Action: "android.intent.action.VIEW" 196*6777b538SAndroid Build Coastguard Worker # Category: "android.intent.category.DEFAULT" 197*6777b538SAndroid Build Coastguard Worker # Category: "android.intent.category.BROWSABLE" 198*6777b538SAndroid Build Coastguard Worker # Scheme: "http" 199*6777b538SAndroid Build Coastguard Worker # Scheme: "https" 200*6777b538SAndroid Build Coastguard Worker # 201*6777b538SAndroid Build Coastguard Worker # Non-Data Actions: 202*6777b538SAndroid Build Coastguard Worker # android.intent.action.MAIN: 203*6777b538SAndroid Build Coastguard Worker # 67e97c0 org.chromium.pkg/.MainActivity filter 4a34cf9 204*6777b538SAndroid Build Coastguard Worker # Action: "android.intent.action.MAIN" 205*6777b538SAndroid Build Coastguard Worker # Category: "android.intent.category.LAUNCHER" 206*6777b538SAndroid Build Coastguard Worker lines = device.RunShellCommand(['dumpsys', 'package', package_name], 207*6777b538SAndroid Build Coastguard Worker check_return=True) 208*6777b538SAndroid Build Coastguard Worker 209*6777b538SAndroid Build Coastguard Worker # Extract the Activity Resolver Table: section. 210*6777b538SAndroid Build Coastguard Worker start_idx = next((i for i, l in enumerate(lines) 211*6777b538SAndroid Build Coastguard Worker if l.startswith('Activity Resolver Table:')), None) 212*6777b538SAndroid Build Coastguard Worker if start_idx is None: 213*6777b538SAndroid Build Coastguard Worker if not device.IsApplicationInstalled(package_name): 214*6777b538SAndroid Build Coastguard Worker raise Exception('Package not installed: ' + package_name) 215*6777b538SAndroid Build Coastguard Worker raise Exception('No Activity Resolver Table in:\n' + '\n'.join(lines)) 216*6777b538SAndroid Build Coastguard Worker line_count = next(i for i, l in enumerate(lines[start_idx + 1:]) 217*6777b538SAndroid Build Coastguard Worker if l and not l[0].isspace()) 218*6777b538SAndroid Build Coastguard Worker data = '\n'.join(lines[start_idx:start_idx + line_count]) 219*6777b538SAndroid Build Coastguard Worker 220*6777b538SAndroid Build Coastguard Worker # Split on each Activity entry. 221*6777b538SAndroid Build Coastguard Worker entries = re.split(r'^ [0-9a-f]+ ', data, flags=re.MULTILINE) 222*6777b538SAndroid Build Coastguard Worker 223*6777b538SAndroid Build Coastguard Worker def activity_name_from_entry(entry): 224*6777b538SAndroid Build Coastguard Worker assert entry.startswith(package_name), 'Got: ' + entry 225*6777b538SAndroid Build Coastguard Worker activity_name = entry[len(package_name) + 1:].split(' ', 1)[0] 226*6777b538SAndroid Build Coastguard Worker if activity_name[0] == '.': 227*6777b538SAndroid Build Coastguard Worker activity_name = package_name + activity_name 228*6777b538SAndroid Build Coastguard Worker return activity_name 229*6777b538SAndroid Build Coastguard Worker 230*6777b538SAndroid Build Coastguard Worker # Find the one with the text we want. 231*6777b538SAndroid Build Coastguard Worker category_text = f'Category: "{category}"' 232*6777b538SAndroid Build Coastguard Worker action_text = f'Action: "{action}"' 233*6777b538SAndroid Build Coastguard Worker matched_entries = [ 234*6777b538SAndroid Build Coastguard Worker e for e in entries[1:] if category_text in e and action_text in e 235*6777b538SAndroid Build Coastguard Worker ] 236*6777b538SAndroid Build Coastguard Worker 237*6777b538SAndroid Build Coastguard Worker if not matched_entries: 238*6777b538SAndroid Build Coastguard Worker raise Exception(f'Did not find {category_text}, {action_text} in\n{data}') 239*6777b538SAndroid Build Coastguard Worker if len(matched_entries) > 1: 240*6777b538SAndroid Build Coastguard Worker # When there are multiple matches, look for the one marked as default. 241*6777b538SAndroid Build Coastguard Worker # Necessary for Monochrome, which also has MonochromeLauncherActivity. 242*6777b538SAndroid Build Coastguard Worker default_entries = [ 243*6777b538SAndroid Build Coastguard Worker e for e in matched_entries if 'android.intent.category.DEFAULT' in e 244*6777b538SAndroid Build Coastguard Worker ] 245*6777b538SAndroid Build Coastguard Worker matched_entries = default_entries or matched_entries 246*6777b538SAndroid Build Coastguard Worker 247*6777b538SAndroid Build Coastguard Worker # See if all matches point to the same activity. 248*6777b538SAndroid Build Coastguard Worker activity_names = {activity_name_from_entry(e) for e in matched_entries} 249*6777b538SAndroid Build Coastguard Worker 250*6777b538SAndroid Build Coastguard Worker if len(activity_names) > 1: 251*6777b538SAndroid Build Coastguard Worker raise Exception('Found multiple launcher activities:\n * ' + 252*6777b538SAndroid Build Coastguard Worker '\n * '.join(sorted(activity_names))) 253*6777b538SAndroid Build Coastguard Worker return next(iter(activity_names)) 254*6777b538SAndroid Build Coastguard Worker 255*6777b538SAndroid Build Coastguard Worker 256*6777b538SAndroid Build Coastguard Workerdef _LaunchUrl(devices, 257*6777b538SAndroid Build Coastguard Worker package_name, 258*6777b538SAndroid Build Coastguard Worker argv=None, 259*6777b538SAndroid Build Coastguard Worker command_line_flags_file=None, 260*6777b538SAndroid Build Coastguard Worker url=None, 261*6777b538SAndroid Build Coastguard Worker wait_for_java_debugger=False, 262*6777b538SAndroid Build Coastguard Worker debug_process_name=None, 263*6777b538SAndroid Build Coastguard Worker nokill=None): 264*6777b538SAndroid Build Coastguard Worker if argv and command_line_flags_file is None: 265*6777b538SAndroid Build Coastguard Worker raise Exception('This apk does not support any flags.') 266*6777b538SAndroid Build Coastguard Worker 267*6777b538SAndroid Build Coastguard Worker debug_process_name = _NormalizeProcessName(debug_process_name, package_name) 268*6777b538SAndroid Build Coastguard Worker 269*6777b538SAndroid Build Coastguard Worker if url is None: 270*6777b538SAndroid Build Coastguard Worker category = 'android.intent.category.LAUNCHER' 271*6777b538SAndroid Build Coastguard Worker action = 'android.intent.action.MAIN' 272*6777b538SAndroid Build Coastguard Worker else: 273*6777b538SAndroid Build Coastguard Worker category = 'android.intent.category.BROWSABLE' 274*6777b538SAndroid Build Coastguard Worker action = 'android.intent.action.VIEW' 275*6777b538SAndroid Build Coastguard Worker 276*6777b538SAndroid Build Coastguard Worker def launch(device): 277*6777b538SAndroid Build Coastguard Worker activity = _ResolveActivity(device, package_name, category, action) 278*6777b538SAndroid Build Coastguard Worker # --persistent is required to have Settings.Global.DEBUG_APP be set, which 279*6777b538SAndroid Build Coastguard Worker # we currently use to allow reading of flags. https://crbug.com/784947 280*6777b538SAndroid Build Coastguard Worker if not nokill: 281*6777b538SAndroid Build Coastguard Worker cmd = ['am', 'set-debug-app', '--persistent', debug_process_name] 282*6777b538SAndroid Build Coastguard Worker if wait_for_java_debugger: 283*6777b538SAndroid Build Coastguard Worker cmd[-1:-1] = ['-w'] 284*6777b538SAndroid Build Coastguard Worker # Ignore error since it will fail if apk is not debuggable. 285*6777b538SAndroid Build Coastguard Worker device.RunShellCommand(cmd, check_return=False) 286*6777b538SAndroid Build Coastguard Worker 287*6777b538SAndroid Build Coastguard Worker # The flags are first updated with input args. 288*6777b538SAndroid Build Coastguard Worker if command_line_flags_file: 289*6777b538SAndroid Build Coastguard Worker changer = flag_changer.FlagChanger(device, command_line_flags_file) 290*6777b538SAndroid Build Coastguard Worker flags = [] 291*6777b538SAndroid Build Coastguard Worker if argv: 292*6777b538SAndroid Build Coastguard Worker adb_command_line.CheckBuildTypeSupportsFlags(device, 293*6777b538SAndroid Build Coastguard Worker command_line_flags_file) 294*6777b538SAndroid Build Coastguard Worker flags = shlex.split(argv) 295*6777b538SAndroid Build Coastguard Worker try: 296*6777b538SAndroid Build Coastguard Worker changer.ReplaceFlags(flags) 297*6777b538SAndroid Build Coastguard Worker except device_errors.AdbShellCommandFailedError: 298*6777b538SAndroid Build Coastguard Worker logging.exception('Failed to set flags') 299*6777b538SAndroid Build Coastguard Worker 300*6777b538SAndroid Build Coastguard Worker launch_intent = intent.Intent(action=action, 301*6777b538SAndroid Build Coastguard Worker activity=activity, 302*6777b538SAndroid Build Coastguard Worker data=url, 303*6777b538SAndroid Build Coastguard Worker package=package_name) 304*6777b538SAndroid Build Coastguard Worker logging.info('Sending launch intent for %s', activity) 305*6777b538SAndroid Build Coastguard Worker device.StartActivity(launch_intent) 306*6777b538SAndroid Build Coastguard Worker 307*6777b538SAndroid Build Coastguard Worker device_utils.DeviceUtils.parallel(devices).pMap(launch) 308*6777b538SAndroid Build Coastguard Worker if wait_for_java_debugger: 309*6777b538SAndroid Build Coastguard Worker print('Waiting for debugger to attach to process: ' + 310*6777b538SAndroid Build Coastguard Worker _Colorize(debug_process_name, colorama.Fore.YELLOW)) 311*6777b538SAndroid Build Coastguard Worker 312*6777b538SAndroid Build Coastguard Worker 313*6777b538SAndroid Build Coastguard Workerdef _ChangeFlags(devices, argv, command_line_flags_file): 314*6777b538SAndroid Build Coastguard Worker if argv is None: 315*6777b538SAndroid Build Coastguard Worker _DisplayArgs(devices, command_line_flags_file) 316*6777b538SAndroid Build Coastguard Worker else: 317*6777b538SAndroid Build Coastguard Worker flags = shlex.split(argv) 318*6777b538SAndroid Build Coastguard Worker def update(device): 319*6777b538SAndroid Build Coastguard Worker adb_command_line.CheckBuildTypeSupportsFlags(device, 320*6777b538SAndroid Build Coastguard Worker command_line_flags_file) 321*6777b538SAndroid Build Coastguard Worker changer = flag_changer.FlagChanger(device, command_line_flags_file) 322*6777b538SAndroid Build Coastguard Worker changer.ReplaceFlags(flags) 323*6777b538SAndroid Build Coastguard Worker device_utils.DeviceUtils.parallel(devices).pMap(update) 324*6777b538SAndroid Build Coastguard Worker 325*6777b538SAndroid Build Coastguard Worker 326*6777b538SAndroid Build Coastguard Workerdef _TargetCpuToTargetArch(target_cpu): 327*6777b538SAndroid Build Coastguard Worker if target_cpu == 'x64': 328*6777b538SAndroid Build Coastguard Worker return 'x86_64' 329*6777b538SAndroid Build Coastguard Worker if target_cpu == 'mipsel': 330*6777b538SAndroid Build Coastguard Worker return 'mips' 331*6777b538SAndroid Build Coastguard Worker return target_cpu 332*6777b538SAndroid Build Coastguard Worker 333*6777b538SAndroid Build Coastguard Worker 334*6777b538SAndroid Build Coastguard Workerdef _RunGdb(device, package_name, debug_process_name, pid, output_directory, 335*6777b538SAndroid Build Coastguard Worker target_cpu, port, ide, verbose): 336*6777b538SAndroid Build Coastguard Worker if not pid: 337*6777b538SAndroid Build Coastguard Worker debug_process_name = _NormalizeProcessName(debug_process_name, package_name) 338*6777b538SAndroid Build Coastguard Worker pid = device.GetApplicationPids(debug_process_name, at_most_one=True) 339*6777b538SAndroid Build Coastguard Worker if not pid: 340*6777b538SAndroid Build Coastguard Worker # Attaching gdb makes the app run so slow that it takes *minutes* to start 341*6777b538SAndroid Build Coastguard Worker # up (as of 2018). Better to just fail than to start & attach. 342*6777b538SAndroid Build Coastguard Worker raise Exception('App not running.') 343*6777b538SAndroid Build Coastguard Worker 344*6777b538SAndroid Build Coastguard Worker gdb_script_path = os.path.dirname(__file__) + '/adb_gdb' 345*6777b538SAndroid Build Coastguard Worker cmd = [ 346*6777b538SAndroid Build Coastguard Worker gdb_script_path, 347*6777b538SAndroid Build Coastguard Worker '--package-name=%s' % package_name, 348*6777b538SAndroid Build Coastguard Worker '--output-directory=%s' % output_directory, 349*6777b538SAndroid Build Coastguard Worker '--adb=%s' % adb_wrapper.AdbWrapper.GetAdbPath(), 350*6777b538SAndroid Build Coastguard Worker '--device=%s' % device.serial, 351*6777b538SAndroid Build Coastguard Worker '--pid=%s' % pid, 352*6777b538SAndroid Build Coastguard Worker '--port=%d' % port, 353*6777b538SAndroid Build Coastguard Worker ] 354*6777b538SAndroid Build Coastguard Worker if ide: 355*6777b538SAndroid Build Coastguard Worker cmd.append('--ide') 356*6777b538SAndroid Build Coastguard Worker # Enable verbose output of adb_gdb if it's set for this script. 357*6777b538SAndroid Build Coastguard Worker if verbose: 358*6777b538SAndroid Build Coastguard Worker cmd.append('--verbose') 359*6777b538SAndroid Build Coastguard Worker if target_cpu: 360*6777b538SAndroid Build Coastguard Worker cmd.append('--target-arch=%s' % _TargetCpuToTargetArch(target_cpu)) 361*6777b538SAndroid Build Coastguard Worker logging.warning('Running: %s', ' '.join(shlex.quote(x) for x in cmd)) 362*6777b538SAndroid Build Coastguard Worker print(_Colorize('All subsequent output is from adb_gdb script.', 363*6777b538SAndroid Build Coastguard Worker colorama.Fore.YELLOW)) 364*6777b538SAndroid Build Coastguard Worker os.execv(gdb_script_path, cmd) 365*6777b538SAndroid Build Coastguard Worker 366*6777b538SAndroid Build Coastguard Worker 367*6777b538SAndroid Build Coastguard Workerdef _RunLldb(device, 368*6777b538SAndroid Build Coastguard Worker package_name, 369*6777b538SAndroid Build Coastguard Worker debug_process_name, 370*6777b538SAndroid Build Coastguard Worker pid, 371*6777b538SAndroid Build Coastguard Worker output_directory, 372*6777b538SAndroid Build Coastguard Worker port, 373*6777b538SAndroid Build Coastguard Worker target_cpu=None, 374*6777b538SAndroid Build Coastguard Worker ndk_dir=None, 375*6777b538SAndroid Build Coastguard Worker lldb_server=None, 376*6777b538SAndroid Build Coastguard Worker lldb=None, 377*6777b538SAndroid Build Coastguard Worker verbose=None): 378*6777b538SAndroid Build Coastguard Worker if not pid: 379*6777b538SAndroid Build Coastguard Worker debug_process_name = _NormalizeProcessName(debug_process_name, package_name) 380*6777b538SAndroid Build Coastguard Worker pid = device.GetApplicationPids(debug_process_name, at_most_one=True) 381*6777b538SAndroid Build Coastguard Worker if not pid: 382*6777b538SAndroid Build Coastguard Worker # Attaching lldb makes the app run so slow that it takes *minutes* to start 383*6777b538SAndroid Build Coastguard Worker # up (as of 2018). Better to just fail than to start & attach. 384*6777b538SAndroid Build Coastguard Worker raise Exception('App not running.') 385*6777b538SAndroid Build Coastguard Worker 386*6777b538SAndroid Build Coastguard Worker lldb_script_path = os.path.dirname(__file__) + '/connect_lldb.sh' 387*6777b538SAndroid Build Coastguard Worker cmd = [ 388*6777b538SAndroid Build Coastguard Worker lldb_script_path, 389*6777b538SAndroid Build Coastguard Worker '--package-name=%s' % package_name, 390*6777b538SAndroid Build Coastguard Worker '--output-directory=%s' % output_directory, 391*6777b538SAndroid Build Coastguard Worker '--adb=%s' % adb_wrapper.AdbWrapper.GetAdbPath(), 392*6777b538SAndroid Build Coastguard Worker '--device=%s' % device.serial, 393*6777b538SAndroid Build Coastguard Worker '--pid=%s' % pid, 394*6777b538SAndroid Build Coastguard Worker '--port=%d' % port, 395*6777b538SAndroid Build Coastguard Worker ] 396*6777b538SAndroid Build Coastguard Worker # Enable verbose output of connect_lldb.sh if it's set for this script. 397*6777b538SAndroid Build Coastguard Worker if verbose: 398*6777b538SAndroid Build Coastguard Worker cmd.append('--verbose') 399*6777b538SAndroid Build Coastguard Worker if target_cpu: 400*6777b538SAndroid Build Coastguard Worker cmd.append('--target-arch=%s' % _TargetCpuToTargetArch(target_cpu)) 401*6777b538SAndroid Build Coastguard Worker if ndk_dir: 402*6777b538SAndroid Build Coastguard Worker cmd.append('--ndk-dir=%s' % ndk_dir) 403*6777b538SAndroid Build Coastguard Worker if lldb_server: 404*6777b538SAndroid Build Coastguard Worker cmd.append('--lldb-server=%s' % lldb_server) 405*6777b538SAndroid Build Coastguard Worker if lldb: 406*6777b538SAndroid Build Coastguard Worker cmd.append('--lldb=%s' % lldb) 407*6777b538SAndroid Build Coastguard Worker logging.warning('Running: %s', ' '.join(shlex.quote(x) for x in cmd)) 408*6777b538SAndroid Build Coastguard Worker print( 409*6777b538SAndroid Build Coastguard Worker _Colorize('All subsequent output is from connect_lldb.sh script.', 410*6777b538SAndroid Build Coastguard Worker colorama.Fore.YELLOW)) 411*6777b538SAndroid Build Coastguard Worker os.execv(lldb_script_path, cmd) 412*6777b538SAndroid Build Coastguard Worker 413*6777b538SAndroid Build Coastguard Worker 414*6777b538SAndroid Build Coastguard Workerdef _PrintPerDeviceOutput(devices, results, single_line=False): 415*6777b538SAndroid Build Coastguard Worker for d, result in zip(devices, results): 416*6777b538SAndroid Build Coastguard Worker if not single_line and d is not devices[0]: 417*6777b538SAndroid Build Coastguard Worker sys.stdout.write('\n') 418*6777b538SAndroid Build Coastguard Worker sys.stdout.write( 419*6777b538SAndroid Build Coastguard Worker _Colorize('{} ({}):'.format(d, d.build_description), 420*6777b538SAndroid Build Coastguard Worker colorama.Fore.YELLOW)) 421*6777b538SAndroid Build Coastguard Worker sys.stdout.write(' ' if single_line else '\n') 422*6777b538SAndroid Build Coastguard Worker yield result 423*6777b538SAndroid Build Coastguard Worker 424*6777b538SAndroid Build Coastguard Worker 425*6777b538SAndroid Build Coastguard Workerdef _RunMemUsage(devices, package_name, query_app=False): 426*6777b538SAndroid Build Coastguard Worker cmd_args = ['dumpsys', 'meminfo'] 427*6777b538SAndroid Build Coastguard Worker if not query_app: 428*6777b538SAndroid Build Coastguard Worker cmd_args.append('--local') 429*6777b538SAndroid Build Coastguard Worker 430*6777b538SAndroid Build Coastguard Worker def mem_usage_helper(d): 431*6777b538SAndroid Build Coastguard Worker ret = [] 432*6777b538SAndroid Build Coastguard Worker for process in sorted(_GetPackageProcesses(d, package_name)): 433*6777b538SAndroid Build Coastguard Worker meminfo = d.RunShellCommand(cmd_args + [str(process.pid)]) 434*6777b538SAndroid Build Coastguard Worker ret.append((process.name, '\n'.join(meminfo))) 435*6777b538SAndroid Build Coastguard Worker return ret 436*6777b538SAndroid Build Coastguard Worker 437*6777b538SAndroid Build Coastguard Worker parallel_devices = device_utils.DeviceUtils.parallel(devices) 438*6777b538SAndroid Build Coastguard Worker all_results = parallel_devices.pMap(mem_usage_helper).pGet(None) 439*6777b538SAndroid Build Coastguard Worker for result in _PrintPerDeviceOutput(devices, all_results): 440*6777b538SAndroid Build Coastguard Worker if not result: 441*6777b538SAndroid Build Coastguard Worker print('No processes found.') 442*6777b538SAndroid Build Coastguard Worker else: 443*6777b538SAndroid Build Coastguard Worker for name, usage in sorted(result): 444*6777b538SAndroid Build Coastguard Worker print(_Colorize('==== Output of "dumpsys meminfo %s" ====' % name, 445*6777b538SAndroid Build Coastguard Worker colorama.Fore.GREEN)) 446*6777b538SAndroid Build Coastguard Worker print(usage) 447*6777b538SAndroid Build Coastguard Worker 448*6777b538SAndroid Build Coastguard Worker 449*6777b538SAndroid Build Coastguard Workerdef _DuHelper(device, path_spec, run_as=None): 450*6777b538SAndroid Build Coastguard Worker """Runs "du -s -k |path_spec|" on |device| and returns parsed result. 451*6777b538SAndroid Build Coastguard Worker 452*6777b538SAndroid Build Coastguard Worker Args: 453*6777b538SAndroid Build Coastguard Worker device: A DeviceUtils instance. 454*6777b538SAndroid Build Coastguard Worker path_spec: The list of paths to run du on. May contain shell expansions 455*6777b538SAndroid Build Coastguard Worker (will not be escaped). 456*6777b538SAndroid Build Coastguard Worker run_as: Package name to run as, or None to run as shell user. If not None 457*6777b538SAndroid Build Coastguard Worker and app is not android:debuggable (run-as fails), then command will be 458*6777b538SAndroid Build Coastguard Worker run as root. 459*6777b538SAndroid Build Coastguard Worker 460*6777b538SAndroid Build Coastguard Worker Returns: 461*6777b538SAndroid Build Coastguard Worker A dict of path->size in KiB containing all paths in |path_spec| that exist 462*6777b538SAndroid Build Coastguard Worker on device. Paths that do not exist are silently ignored. 463*6777b538SAndroid Build Coastguard Worker """ 464*6777b538SAndroid Build Coastguard Worker # Example output for: du -s -k /data/data/org.chromium.chrome/{*,.*} 465*6777b538SAndroid Build Coastguard Worker # 144 /data/data/org.chromium.chrome/cache 466*6777b538SAndroid Build Coastguard Worker # 8 /data/data/org.chromium.chrome/files 467*6777b538SAndroid Build Coastguard Worker # <snip> 468*6777b538SAndroid Build Coastguard Worker # du: .*: No such file or directory 469*6777b538SAndroid Build Coastguard Worker 470*6777b538SAndroid Build Coastguard Worker # The -d flag works differently across android version, so use -s instead. 471*6777b538SAndroid Build Coastguard Worker # Without the explicit 2>&1, stderr and stdout get combined at random :(. 472*6777b538SAndroid Build Coastguard Worker cmd_str = 'du -s -k ' + path_spec + ' 2>&1' 473*6777b538SAndroid Build Coastguard Worker lines = device.RunShellCommand(cmd_str, run_as=run_as, shell=True, 474*6777b538SAndroid Build Coastguard Worker check_return=False) 475*6777b538SAndroid Build Coastguard Worker output = '\n'.join(lines) 476*6777b538SAndroid Build Coastguard Worker # run-as: Package 'com.android.chrome' is not debuggable 477*6777b538SAndroid Build Coastguard Worker if output.startswith('run-as:'): 478*6777b538SAndroid Build Coastguard Worker # check_return=False needed for when some paths in path_spec do not exist. 479*6777b538SAndroid Build Coastguard Worker lines = device.RunShellCommand(cmd_str, as_root=True, shell=True, 480*6777b538SAndroid Build Coastguard Worker check_return=False) 481*6777b538SAndroid Build Coastguard Worker ret = {} 482*6777b538SAndroid Build Coastguard Worker try: 483*6777b538SAndroid Build Coastguard Worker for line in lines: 484*6777b538SAndroid Build Coastguard Worker # du: .*: No such file or directory 485*6777b538SAndroid Build Coastguard Worker if line.startswith('du:'): 486*6777b538SAndroid Build Coastguard Worker continue 487*6777b538SAndroid Build Coastguard Worker size, subpath = line.split(None, 1) 488*6777b538SAndroid Build Coastguard Worker ret[subpath] = int(size) 489*6777b538SAndroid Build Coastguard Worker return ret 490*6777b538SAndroid Build Coastguard Worker except ValueError: 491*6777b538SAndroid Build Coastguard Worker logging.error('du command was: %s', cmd_str) 492*6777b538SAndroid Build Coastguard Worker logging.error('Failed to parse du output:\n%s', output) 493*6777b538SAndroid Build Coastguard Worker raise 494*6777b538SAndroid Build Coastguard Worker 495*6777b538SAndroid Build Coastguard Worker 496*6777b538SAndroid Build Coastguard Workerdef _RunDiskUsage(devices, package_name): 497*6777b538SAndroid Build Coastguard Worker # Measuring dex size is a bit complicated: 498*6777b538SAndroid Build Coastguard Worker # https://source.android.com/devices/tech/dalvik/jit-compiler 499*6777b538SAndroid Build Coastguard Worker # 500*6777b538SAndroid Build Coastguard Worker # For KitKat and below: 501*6777b538SAndroid Build Coastguard Worker # dumpsys package contains: 502*6777b538SAndroid Build Coastguard Worker # dataDir=/data/data/org.chromium.chrome 503*6777b538SAndroid Build Coastguard Worker # codePath=/data/app/org.chromium.chrome-1.apk 504*6777b538SAndroid Build Coastguard Worker # resourcePath=/data/app/org.chromium.chrome-1.apk 505*6777b538SAndroid Build Coastguard Worker # nativeLibraryPath=/data/app-lib/org.chromium.chrome-1 506*6777b538SAndroid Build Coastguard Worker # To measure odex: 507*6777b538SAndroid Build Coastguard Worker # ls -l /data/dalvik-cache/data@[email protected]@classes.dex 508*6777b538SAndroid Build Coastguard Worker # 509*6777b538SAndroid Build Coastguard Worker # For Android L and M (and maybe for N+ system apps): 510*6777b538SAndroid Build Coastguard Worker # dumpsys package contains: 511*6777b538SAndroid Build Coastguard Worker # codePath=/data/app/org.chromium.chrome-1 512*6777b538SAndroid Build Coastguard Worker # resourcePath=/data/app/org.chromium.chrome-1 513*6777b538SAndroid Build Coastguard Worker # legacyNativeLibraryDir=/data/app/org.chromium.chrome-1/lib 514*6777b538SAndroid Build Coastguard Worker # To measure odex: 515*6777b538SAndroid Build Coastguard Worker # # Option 1: 516*6777b538SAndroid Build Coastguard Worker # /data/dalvik-cache/arm/data@[email protected]@[email protected] 517*6777b538SAndroid Build Coastguard Worker # /data/dalvik-cache/arm/data@[email protected]@[email protected] 518*6777b538SAndroid Build Coastguard Worker # ls -l /data/dalvik-cache/profiles/org.chromium.chrome 519*6777b538SAndroid Build Coastguard Worker # (these profiles all appear to be 0 bytes) 520*6777b538SAndroid Build Coastguard Worker # # Option 2: 521*6777b538SAndroid Build Coastguard Worker # ls -l /data/app/org.chromium.chrome-1/oat/arm/base.odex 522*6777b538SAndroid Build Coastguard Worker # 523*6777b538SAndroid Build Coastguard Worker # For Android N+: 524*6777b538SAndroid Build Coastguard Worker # dumpsys package contains: 525*6777b538SAndroid Build Coastguard Worker # dataDir=/data/user/0/org.chromium.chrome 526*6777b538SAndroid Build Coastguard Worker # codePath=/data/app/org.chromium.chrome-UuCZ71IE-i5sZgHAkU49_w== 527*6777b538SAndroid Build Coastguard Worker # resourcePath=/data/app/org.chromium.chrome-UuCZ71IE-i5sZgHAkU49_w== 528*6777b538SAndroid Build Coastguard Worker # legacyNativeLibraryDir=/data/app/org.chromium.chrome-GUID/lib 529*6777b538SAndroid Build Coastguard Worker # Instruction Set: arm 530*6777b538SAndroid Build Coastguard Worker # path: /data/app/org.chromium.chrome-UuCZ71IE-i5sZgHAkU49_w==/base.apk 531*6777b538SAndroid Build Coastguard Worker # status: /data/.../oat/arm/base.odex[status=kOatUpToDate, compilation_f 532*6777b538SAndroid Build Coastguard Worker # ilter=quicken] 533*6777b538SAndroid Build Coastguard Worker # Instruction Set: arm64 534*6777b538SAndroid Build Coastguard Worker # path: /data/app/org.chromium.chrome-UuCZ71IE-i5sZgHAkU49_w==/base.apk 535*6777b538SAndroid Build Coastguard Worker # status: /data/.../oat/arm64/base.odex[status=..., compilation_filter=q 536*6777b538SAndroid Build Coastguard Worker # uicken] 537*6777b538SAndroid Build Coastguard Worker # To measure odex: 538*6777b538SAndroid Build Coastguard Worker # ls -l /data/app/.../oat/arm/base.odex 539*6777b538SAndroid Build Coastguard Worker # ls -l /data/app/.../oat/arm/base.vdex (optional) 540*6777b538SAndroid Build Coastguard Worker # To measure the correct odex size: 541*6777b538SAndroid Build Coastguard Worker # cmd package compile -m speed org.chromium.chrome # For webview 542*6777b538SAndroid Build Coastguard Worker # cmd package compile -m speed-profile org.chromium.chrome # For others 543*6777b538SAndroid Build Coastguard Worker def disk_usage_helper(d): 544*6777b538SAndroid Build Coastguard Worker package_output = '\n'.join(d.RunShellCommand( 545*6777b538SAndroid Build Coastguard Worker ['dumpsys', 'package', package_name], check_return=True)) 546*6777b538SAndroid Build Coastguard Worker # Does not return error when apk is not installed. 547*6777b538SAndroid Build Coastguard Worker if not package_output or 'Unable to find package:' in package_output: 548*6777b538SAndroid Build Coastguard Worker return None 549*6777b538SAndroid Build Coastguard Worker 550*6777b538SAndroid Build Coastguard Worker # Ignore system apks that have updates installed. 551*6777b538SAndroid Build Coastguard Worker package_output = re.sub(r'Hidden system packages:.*?^\b', '', 552*6777b538SAndroid Build Coastguard Worker package_output, flags=re.S | re.M) 553*6777b538SAndroid Build Coastguard Worker 554*6777b538SAndroid Build Coastguard Worker try: 555*6777b538SAndroid Build Coastguard Worker data_dir = re.search(r'dataDir=(.*)', package_output).group(1) 556*6777b538SAndroid Build Coastguard Worker code_path = re.search(r'codePath=(.*)', package_output).group(1) 557*6777b538SAndroid Build Coastguard Worker lib_path = re.search(r'(?:legacyN|n)ativeLibrary(?:Dir|Path)=(.*)', 558*6777b538SAndroid Build Coastguard Worker package_output).group(1) 559*6777b538SAndroid Build Coastguard Worker except AttributeError as e: 560*6777b538SAndroid Build Coastguard Worker raise Exception('Error parsing dumpsys output: ' + package_output) from e 561*6777b538SAndroid Build Coastguard Worker 562*6777b538SAndroid Build Coastguard Worker if code_path.startswith('/system'): 563*6777b538SAndroid Build Coastguard Worker logging.warning('Measurement of system image apks can be innacurate') 564*6777b538SAndroid Build Coastguard Worker 565*6777b538SAndroid Build Coastguard Worker compilation_filters = set() 566*6777b538SAndroid Build Coastguard Worker # Match "compilation_filter=value", where a line break can occur at any spot 567*6777b538SAndroid Build Coastguard Worker # (refer to examples above). 568*6777b538SAndroid Build Coastguard Worker awful_wrapping = r'\s*'.join('compilation_filter=') 569*6777b538SAndroid Build Coastguard Worker for m in re.finditer(awful_wrapping + r'([\s\S]+?)[\],]', package_output): 570*6777b538SAndroid Build Coastguard Worker compilation_filters.add(re.sub(r'\s+', '', m.group(1))) 571*6777b538SAndroid Build Coastguard Worker # Starting Android Q, output looks like: 572*6777b538SAndroid Build Coastguard Worker # arm: [status=speed-profile] [reason=install] 573*6777b538SAndroid Build Coastguard Worker for m in re.finditer(r'\[status=(.+?)\]', package_output): 574*6777b538SAndroid Build Coastguard Worker compilation_filters.add(m.group(1)) 575*6777b538SAndroid Build Coastguard Worker compilation_filter = ','.join(sorted(compilation_filters)) 576*6777b538SAndroid Build Coastguard Worker 577*6777b538SAndroid Build Coastguard Worker data_dir_sizes = _DuHelper(d, '%s/{*,.*}' % data_dir, run_as=package_name) 578*6777b538SAndroid Build Coastguard Worker # Measure code_cache separately since it can be large. 579*6777b538SAndroid Build Coastguard Worker code_cache_sizes = {} 580*6777b538SAndroid Build Coastguard Worker code_cache_dir = next( 581*6777b538SAndroid Build Coastguard Worker (k for k in data_dir_sizes if k.endswith('/code_cache')), None) 582*6777b538SAndroid Build Coastguard Worker if code_cache_dir: 583*6777b538SAndroid Build Coastguard Worker data_dir_sizes.pop(code_cache_dir) 584*6777b538SAndroid Build Coastguard Worker code_cache_sizes = _DuHelper(d, '%s/{*,.*}' % code_cache_dir, 585*6777b538SAndroid Build Coastguard Worker run_as=package_name) 586*6777b538SAndroid Build Coastguard Worker 587*6777b538SAndroid Build Coastguard Worker apk_path_spec = code_path 588*6777b538SAndroid Build Coastguard Worker if not apk_path_spec.endswith('.apk'): 589*6777b538SAndroid Build Coastguard Worker apk_path_spec += '/*.apk' 590*6777b538SAndroid Build Coastguard Worker apk_sizes = _DuHelper(d, apk_path_spec) 591*6777b538SAndroid Build Coastguard Worker if lib_path.endswith('/lib'): 592*6777b538SAndroid Build Coastguard Worker # Shows architecture subdirectory. 593*6777b538SAndroid Build Coastguard Worker lib_sizes = _DuHelper(d, '%s/{*,.*}' % lib_path) 594*6777b538SAndroid Build Coastguard Worker else: 595*6777b538SAndroid Build Coastguard Worker lib_sizes = _DuHelper(d, lib_path) 596*6777b538SAndroid Build Coastguard Worker 597*6777b538SAndroid Build Coastguard Worker # Look at all possible locations for odex files. 598*6777b538SAndroid Build Coastguard Worker odex_paths = [] 599*6777b538SAndroid Build Coastguard Worker for apk_path in apk_sizes: 600*6777b538SAndroid Build Coastguard Worker mangled_apk_path = apk_path[1:].replace('/', '@') 601*6777b538SAndroid Build Coastguard Worker apk_basename = posixpath.basename(apk_path)[:-4] 602*6777b538SAndroid Build Coastguard Worker for ext in ('dex', 'odex', 'vdex', 'art'): 603*6777b538SAndroid Build Coastguard Worker # Easier to check all architectures than to determine active ones. 604*6777b538SAndroid Build Coastguard Worker for arch in ('arm', 'arm64', 'x86', 'x86_64', 'mips', 'mips64'): 605*6777b538SAndroid Build Coastguard Worker odex_paths.append( 606*6777b538SAndroid Build Coastguard Worker '%s/oat/%s/%s.%s' % (code_path, arch, apk_basename, ext)) 607*6777b538SAndroid Build Coastguard Worker # No app could possibly have more than 6 dex files. 608*6777b538SAndroid Build Coastguard Worker for suffix in ('', '2', '3', '4', '5'): 609*6777b538SAndroid Build Coastguard Worker odex_paths.append('/data/dalvik-cache/%s/%s@classes%s.%s' % ( 610*6777b538SAndroid Build Coastguard Worker arch, mangled_apk_path, suffix, ext)) 611*6777b538SAndroid Build Coastguard Worker # This path does not have |arch|, so don't repeat it for every arch. 612*6777b538SAndroid Build Coastguard Worker if arch == 'arm': 613*6777b538SAndroid Build Coastguard Worker odex_paths.append('/data/dalvik-cache/%s@classes%s.dex' % ( 614*6777b538SAndroid Build Coastguard Worker mangled_apk_path, suffix)) 615*6777b538SAndroid Build Coastguard Worker 616*6777b538SAndroid Build Coastguard Worker odex_sizes = _DuHelper(d, ' '.join(shlex.quote(p) for p in odex_paths)) 617*6777b538SAndroid Build Coastguard Worker 618*6777b538SAndroid Build Coastguard Worker return (data_dir_sizes, code_cache_sizes, apk_sizes, lib_sizes, odex_sizes, 619*6777b538SAndroid Build Coastguard Worker compilation_filter) 620*6777b538SAndroid Build Coastguard Worker 621*6777b538SAndroid Build Coastguard Worker def print_sizes(desc, sizes): 622*6777b538SAndroid Build Coastguard Worker print('%s: %d KiB' % (desc, sum(sizes.values()))) 623*6777b538SAndroid Build Coastguard Worker for path, size in sorted(sizes.items()): 624*6777b538SAndroid Build Coastguard Worker print(' %s: %s KiB' % (path, size)) 625*6777b538SAndroid Build Coastguard Worker 626*6777b538SAndroid Build Coastguard Worker parallel_devices = device_utils.DeviceUtils.parallel(devices) 627*6777b538SAndroid Build Coastguard Worker all_results = parallel_devices.pMap(disk_usage_helper).pGet(None) 628*6777b538SAndroid Build Coastguard Worker for result in _PrintPerDeviceOutput(devices, all_results): 629*6777b538SAndroid Build Coastguard Worker if not result: 630*6777b538SAndroid Build Coastguard Worker print('APK is not installed.') 631*6777b538SAndroid Build Coastguard Worker continue 632*6777b538SAndroid Build Coastguard Worker 633*6777b538SAndroid Build Coastguard Worker (data_dir_sizes, code_cache_sizes, apk_sizes, lib_sizes, odex_sizes, 634*6777b538SAndroid Build Coastguard Worker compilation_filter) = result 635*6777b538SAndroid Build Coastguard Worker total = sum(sum(sizes.values()) for sizes in result[:-1]) 636*6777b538SAndroid Build Coastguard Worker 637*6777b538SAndroid Build Coastguard Worker print_sizes('Apk', apk_sizes) 638*6777b538SAndroid Build Coastguard Worker print_sizes('App Data (non-code cache)', data_dir_sizes) 639*6777b538SAndroid Build Coastguard Worker print_sizes('App Data (code cache)', code_cache_sizes) 640*6777b538SAndroid Build Coastguard Worker print_sizes('Native Libs', lib_sizes) 641*6777b538SAndroid Build Coastguard Worker show_warning = compilation_filter and 'speed' not in compilation_filter 642*6777b538SAndroid Build Coastguard Worker compilation_filter = compilation_filter or 'n/a' 643*6777b538SAndroid Build Coastguard Worker print_sizes('odex (compilation_filter=%s)' % compilation_filter, odex_sizes) 644*6777b538SAndroid Build Coastguard Worker if show_warning: 645*6777b538SAndroid Build Coastguard Worker logging.warning('For a more realistic odex size, run:') 646*6777b538SAndroid Build Coastguard Worker logging.warning(' %s compile-dex [speed|speed-profile]', sys.argv[0]) 647*6777b538SAndroid Build Coastguard Worker print('Total: %s KiB (%.1f MiB)' % (total, total / 1024.0)) 648*6777b538SAndroid Build Coastguard Worker 649*6777b538SAndroid Build Coastguard Worker 650*6777b538SAndroid Build Coastguard Workerclass _LogcatProcessor: 651*6777b538SAndroid Build Coastguard Worker ParsedLine = collections.namedtuple( 652*6777b538SAndroid Build Coastguard Worker 'ParsedLine', 653*6777b538SAndroid Build Coastguard Worker ['date', 'invokation_time', 'pid', 'tid', 'priority', 'tag', 'message']) 654*6777b538SAndroid Build Coastguard Worker 655*6777b538SAndroid Build Coastguard Worker class NativeStackSymbolizer: 656*6777b538SAndroid Build Coastguard Worker """Buffers lines from native stacks and symbolizes them when done.""" 657*6777b538SAndroid Build Coastguard Worker # E.g.: #06 pc 0x0000d519 /apex/com.android.runtime/lib/libart.so 658*6777b538SAndroid Build Coastguard Worker # E.g.: #01 pc 00180c8d /data/data/.../lib/libbase.cr.so 659*6777b538SAndroid Build Coastguard Worker _STACK_PATTERN = re.compile(r'\s*#\d+\s+(?:pc )?(0x)?[0-9a-f]{8,16}\s') 660*6777b538SAndroid Build Coastguard Worker 661*6777b538SAndroid Build Coastguard Worker def __init__(self, stack_script_context, print_func): 662*6777b538SAndroid Build Coastguard Worker # To symbolize native stacks, we need to pass all lines at once. 663*6777b538SAndroid Build Coastguard Worker self._stack_script_context = stack_script_context 664*6777b538SAndroid Build Coastguard Worker self._print_func = print_func 665*6777b538SAndroid Build Coastguard Worker self._crash_lines_buffer = None 666*6777b538SAndroid Build Coastguard Worker 667*6777b538SAndroid Build Coastguard Worker def _FlushLines(self): 668*6777b538SAndroid Build Coastguard Worker """Prints queued lines after sending them through stack.py.""" 669*6777b538SAndroid Build Coastguard Worker if self._crash_lines_buffer is None: 670*6777b538SAndroid Build Coastguard Worker return 671*6777b538SAndroid Build Coastguard Worker 672*6777b538SAndroid Build Coastguard Worker crash_lines = self._crash_lines_buffer 673*6777b538SAndroid Build Coastguard Worker self._crash_lines_buffer = None 674*6777b538SAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile(mode='w') as f: 675*6777b538SAndroid Build Coastguard Worker f.writelines(x[0].message + '\n' for x in crash_lines) 676*6777b538SAndroid Build Coastguard Worker f.flush() 677*6777b538SAndroid Build Coastguard Worker proc = self._stack_script_context.Popen( 678*6777b538SAndroid Build Coastguard Worker input_file=f.name, stdout=subprocess.PIPE) 679*6777b538SAndroid Build Coastguard Worker lines = proc.communicate()[0].splitlines() 680*6777b538SAndroid Build Coastguard Worker 681*6777b538SAndroid Build Coastguard Worker for i, line in enumerate(lines): 682*6777b538SAndroid Build Coastguard Worker parsed_line, dim = crash_lines[min(i, len(crash_lines) - 1)] 683*6777b538SAndroid Build Coastguard Worker d = parsed_line._asdict() 684*6777b538SAndroid Build Coastguard Worker d['message'] = line 685*6777b538SAndroid Build Coastguard Worker parsed_line = _LogcatProcessor.ParsedLine(**d) 686*6777b538SAndroid Build Coastguard Worker self._print_func(parsed_line, dim) 687*6777b538SAndroid Build Coastguard Worker 688*6777b538SAndroid Build Coastguard Worker def AddLine(self, parsed_line, dim): 689*6777b538SAndroid Build Coastguard Worker # Assume all lines from DEBUG are stacks. 690*6777b538SAndroid Build Coastguard Worker # Also look for "stack-looking" lines to catch manual stack prints. 691*6777b538SAndroid Build Coastguard Worker # It's important to not buffer non-stack lines because stack.py does not 692*6777b538SAndroid Build Coastguard Worker # pass them through. 693*6777b538SAndroid Build Coastguard Worker is_crash_line = parsed_line.tag == 'DEBUG' or (self._STACK_PATTERN.match( 694*6777b538SAndroid Build Coastguard Worker parsed_line.message)) 695*6777b538SAndroid Build Coastguard Worker 696*6777b538SAndroid Build Coastguard Worker if is_crash_line: 697*6777b538SAndroid Build Coastguard Worker if self._crash_lines_buffer is None: 698*6777b538SAndroid Build Coastguard Worker self._crash_lines_buffer = [] 699*6777b538SAndroid Build Coastguard Worker self._crash_lines_buffer.append((parsed_line, dim)) 700*6777b538SAndroid Build Coastguard Worker return 701*6777b538SAndroid Build Coastguard Worker 702*6777b538SAndroid Build Coastguard Worker self._FlushLines() 703*6777b538SAndroid Build Coastguard Worker 704*6777b538SAndroid Build Coastguard Worker self._print_func(parsed_line, dim) 705*6777b538SAndroid Build Coastguard Worker 706*6777b538SAndroid Build Coastguard Worker 707*6777b538SAndroid Build Coastguard Worker # Logcat tags for messages that are generally relevant but are not from PIDs 708*6777b538SAndroid Build Coastguard Worker # associated with the apk. 709*6777b538SAndroid Build Coastguard Worker _ALLOWLISTED_TAGS = { 710*6777b538SAndroid Build Coastguard Worker 'ActivityManager', # Shows activity lifecycle messages. 711*6777b538SAndroid Build Coastguard Worker 'ActivityTaskManager', # More activity lifecycle messages. 712*6777b538SAndroid Build Coastguard Worker 'AndroidRuntime', # Java crash dumps 713*6777b538SAndroid Build Coastguard Worker 'AppZygoteInit', # Android's native application zygote support. 714*6777b538SAndroid Build Coastguard Worker 'DEBUG', # Native crash dump. 715*6777b538SAndroid Build Coastguard Worker } 716*6777b538SAndroid Build Coastguard Worker 717*6777b538SAndroid Build Coastguard Worker # Matches messages only on pre-L (Dalvik) that are spammy and unimportant. 718*6777b538SAndroid Build Coastguard Worker _DALVIK_IGNORE_PATTERN = re.compile('|'.join([ 719*6777b538SAndroid Build Coastguard Worker r'^Added shared lib', 720*6777b538SAndroid Build Coastguard Worker r'^Could not find ', 721*6777b538SAndroid Build Coastguard Worker r'^DexOpt:', 722*6777b538SAndroid Build Coastguard Worker r'^GC_', 723*6777b538SAndroid Build Coastguard Worker r'^Late-enabling CheckJNI', 724*6777b538SAndroid Build Coastguard Worker r'^Link of class', 725*6777b538SAndroid Build Coastguard Worker r'^No JNI_OnLoad found in', 726*6777b538SAndroid Build Coastguard Worker r'^Trying to load lib', 727*6777b538SAndroid Build Coastguard Worker r'^Unable to resolve superclass', 728*6777b538SAndroid Build Coastguard Worker r'^VFY:', 729*6777b538SAndroid Build Coastguard Worker r'^WAIT_', 730*6777b538SAndroid Build Coastguard Worker ])) 731*6777b538SAndroid Build Coastguard Worker 732*6777b538SAndroid Build Coastguard Worker def __init__(self, 733*6777b538SAndroid Build Coastguard Worker device, 734*6777b538SAndroid Build Coastguard Worker package_name, 735*6777b538SAndroid Build Coastguard Worker stack_script_context, 736*6777b538SAndroid Build Coastguard Worker deobfuscate=None, 737*6777b538SAndroid Build Coastguard Worker verbose=False, 738*6777b538SAndroid Build Coastguard Worker exit_on_match=None, 739*6777b538SAndroid Build Coastguard Worker extra_package_names=None): 740*6777b538SAndroid Build Coastguard Worker self._device = device 741*6777b538SAndroid Build Coastguard Worker self._package_name = package_name 742*6777b538SAndroid Build Coastguard Worker self._extra_package_names = extra_package_names or [] 743*6777b538SAndroid Build Coastguard Worker self._verbose = verbose 744*6777b538SAndroid Build Coastguard Worker self._deobfuscator = deobfuscate 745*6777b538SAndroid Build Coastguard Worker if exit_on_match is not None: 746*6777b538SAndroid Build Coastguard Worker self._exit_on_match = re.compile(exit_on_match) 747*6777b538SAndroid Build Coastguard Worker else: 748*6777b538SAndroid Build Coastguard Worker self._exit_on_match = None 749*6777b538SAndroid Build Coastguard Worker self._found_exit_match = False 750*6777b538SAndroid Build Coastguard Worker if stack_script_context: 751*6777b538SAndroid Build Coastguard Worker self._print_func = _LogcatProcessor.NativeStackSymbolizer( 752*6777b538SAndroid Build Coastguard Worker stack_script_context, self._PrintParsedLine).AddLine 753*6777b538SAndroid Build Coastguard Worker else: 754*6777b538SAndroid Build Coastguard Worker self._print_func = self._PrintParsedLine 755*6777b538SAndroid Build Coastguard Worker # Process ID for the app's main process (with no :name suffix). 756*6777b538SAndroid Build Coastguard Worker self._primary_pid = None 757*6777b538SAndroid Build Coastguard Worker # Set of all Process IDs that belong to the app. 758*6777b538SAndroid Build Coastguard Worker self._my_pids = set() 759*6777b538SAndroid Build Coastguard Worker # Set of all Process IDs that we've parsed at some point. 760*6777b538SAndroid Build Coastguard Worker self._seen_pids = set() 761*6777b538SAndroid Build Coastguard Worker # Start proc 22953:com.google.chromeremotedesktop/ 762*6777b538SAndroid Build Coastguard Worker self._pid_pattern = re.compile(r'Start proc (\d+):{}/'.format(package_name)) 763*6777b538SAndroid Build Coastguard Worker # START u0 {act=android.intent.action.MAIN \ 764*6777b538SAndroid Build Coastguard Worker # cat=[android.intent.category.LAUNCHER] \ 765*6777b538SAndroid Build Coastguard Worker # flg=0x10000000 pkg=com.google.chromeremotedesktop} from uid 2000 766*6777b538SAndroid Build Coastguard Worker self._start_pattern = re.compile(r'START .*(?:cmp|pkg)=' + package_name) 767*6777b538SAndroid Build Coastguard Worker 768*6777b538SAndroid Build Coastguard Worker self.nonce = 'Chromium apk_operations.py nonce={}'.format(random.random()) 769*6777b538SAndroid Build Coastguard Worker # Holds lines buffered on start-up, before we find our nonce message. 770*6777b538SAndroid Build Coastguard Worker self._initial_buffered_lines = [] 771*6777b538SAndroid Build Coastguard Worker self._UpdateMyPids() 772*6777b538SAndroid Build Coastguard Worker # Give preference to PID reported by "ps" over those found from 773*6777b538SAndroid Build Coastguard Worker # _start_pattern. There can be multiple "Start proc" messages from prior 774*6777b538SAndroid Build Coastguard Worker # runs of the app. 775*6777b538SAndroid Build Coastguard Worker self._found_initial_pid = self._primary_pid is not None 776*6777b538SAndroid Build Coastguard Worker # Retrieve any additional patterns that are relevant for the User. 777*6777b538SAndroid Build Coastguard Worker self._user_defined_highlight = None 778*6777b538SAndroid Build Coastguard Worker user_regex = os.environ.get('CHROMIUM_LOGCAT_HIGHLIGHT') 779*6777b538SAndroid Build Coastguard Worker if user_regex: 780*6777b538SAndroid Build Coastguard Worker self._user_defined_highlight = re.compile(user_regex) 781*6777b538SAndroid Build Coastguard Worker if not self._user_defined_highlight: 782*6777b538SAndroid Build Coastguard Worker print(_Colorize( 783*6777b538SAndroid Build Coastguard Worker 'Rejecting invalid regular expression: {}'.format(user_regex), 784*6777b538SAndroid Build Coastguard Worker colorama.Fore.RED + colorama.Style.BRIGHT)) 785*6777b538SAndroid Build Coastguard Worker 786*6777b538SAndroid Build Coastguard Worker def _UpdateMyPids(self): 787*6777b538SAndroid Build Coastguard Worker # We intentionally do not clear self._my_pids to make sure that the 788*6777b538SAndroid Build Coastguard Worker # ProcessLine method below also includes lines from processes which may 789*6777b538SAndroid Build Coastguard Worker # have already exited. 790*6777b538SAndroid Build Coastguard Worker self._primary_pid = None 791*6777b538SAndroid Build Coastguard Worker for package_name in [self._package_name] + self._extra_package_names: 792*6777b538SAndroid Build Coastguard Worker for process in _GetPackageProcesses(self._device, package_name): 793*6777b538SAndroid Build Coastguard Worker # We take only the first "main" process found in order to account for 794*6777b538SAndroid Build Coastguard Worker # possibly forked() processes. 795*6777b538SAndroid Build Coastguard Worker if ':' not in process.name and self._primary_pid is None: 796*6777b538SAndroid Build Coastguard Worker self._primary_pid = process.pid 797*6777b538SAndroid Build Coastguard Worker self._my_pids.add(process.pid) 798*6777b538SAndroid Build Coastguard Worker 799*6777b538SAndroid Build Coastguard Worker def _GetPidStyle(self, pid, dim=False): 800*6777b538SAndroid Build Coastguard Worker if pid == self._primary_pid: 801*6777b538SAndroid Build Coastguard Worker return colorama.Fore.WHITE 802*6777b538SAndroid Build Coastguard Worker if pid in self._my_pids: 803*6777b538SAndroid Build Coastguard Worker # TODO(wnwen): Use one separate persistent color per process, pop LRU 804*6777b538SAndroid Build Coastguard Worker return colorama.Fore.YELLOW 805*6777b538SAndroid Build Coastguard Worker if dim: 806*6777b538SAndroid Build Coastguard Worker return colorama.Style.DIM 807*6777b538SAndroid Build Coastguard Worker return '' 808*6777b538SAndroid Build Coastguard Worker 809*6777b538SAndroid Build Coastguard Worker def _GetPriorityStyle(self, priority, dim=False): 810*6777b538SAndroid Build Coastguard Worker # pylint:disable=no-self-use 811*6777b538SAndroid Build Coastguard Worker if dim: 812*6777b538SAndroid Build Coastguard Worker return '' 813*6777b538SAndroid Build Coastguard Worker style = colorama.Fore.BLACK 814*6777b538SAndroid Build Coastguard Worker if priority in ('E', 'F'): 815*6777b538SAndroid Build Coastguard Worker style += colorama.Back.RED 816*6777b538SAndroid Build Coastguard Worker elif priority == 'W': 817*6777b538SAndroid Build Coastguard Worker style += colorama.Back.YELLOW 818*6777b538SAndroid Build Coastguard Worker elif priority == 'I': 819*6777b538SAndroid Build Coastguard Worker style += colorama.Back.GREEN 820*6777b538SAndroid Build Coastguard Worker elif priority == 'D': 821*6777b538SAndroid Build Coastguard Worker style += colorama.Back.BLUE 822*6777b538SAndroid Build Coastguard Worker return style 823*6777b538SAndroid Build Coastguard Worker 824*6777b538SAndroid Build Coastguard Worker def _ParseLine(self, line): 825*6777b538SAndroid Build Coastguard Worker tokens = line.split(None, 6) 826*6777b538SAndroid Build Coastguard Worker 827*6777b538SAndroid Build Coastguard Worker def consume_token_or_default(default): 828*6777b538SAndroid Build Coastguard Worker return tokens.pop(0) if len(tokens) > 0 else default 829*6777b538SAndroid Build Coastguard Worker 830*6777b538SAndroid Build Coastguard Worker def consume_integer_token_or_default(default): 831*6777b538SAndroid Build Coastguard Worker if len(tokens) == 0: 832*6777b538SAndroid Build Coastguard Worker return default 833*6777b538SAndroid Build Coastguard Worker 834*6777b538SAndroid Build Coastguard Worker try: 835*6777b538SAndroid Build Coastguard Worker return int(tokens.pop(0)) 836*6777b538SAndroid Build Coastguard Worker except ValueError: 837*6777b538SAndroid Build Coastguard Worker return default 838*6777b538SAndroid Build Coastguard Worker 839*6777b538SAndroid Build Coastguard Worker date = consume_token_or_default('') 840*6777b538SAndroid Build Coastguard Worker invokation_time = consume_token_or_default('') 841*6777b538SAndroid Build Coastguard Worker pid = consume_integer_token_or_default(-1) 842*6777b538SAndroid Build Coastguard Worker tid = consume_integer_token_or_default(-1) 843*6777b538SAndroid Build Coastguard Worker priority = consume_token_or_default('') 844*6777b538SAndroid Build Coastguard Worker tag = consume_token_or_default('') 845*6777b538SAndroid Build Coastguard Worker original_message = consume_token_or_default('') 846*6777b538SAndroid Build Coastguard Worker 847*6777b538SAndroid Build Coastguard Worker # Example: 848*6777b538SAndroid Build Coastguard Worker # 09-19 06:35:51.113 9060 9154 W GCoreFlp: No location... 849*6777b538SAndroid Build Coastguard Worker # 09-19 06:01:26.174 9060 10617 I Auth : [ReflectiveChannelBinder]... 850*6777b538SAndroid Build Coastguard Worker # Parsing "GCoreFlp:" vs "Auth :", we only want tag to contain the word, 851*6777b538SAndroid Build Coastguard Worker # and we don't want to keep the colon for the message. 852*6777b538SAndroid Build Coastguard Worker if tag and tag[-1] == ':': 853*6777b538SAndroid Build Coastguard Worker tag = tag[:-1] 854*6777b538SAndroid Build Coastguard Worker elif len(original_message) > 2: 855*6777b538SAndroid Build Coastguard Worker original_message = original_message[2:] 856*6777b538SAndroid Build Coastguard Worker return self.ParsedLine( 857*6777b538SAndroid Build Coastguard Worker date, invokation_time, pid, tid, priority, tag, original_message) 858*6777b538SAndroid Build Coastguard Worker 859*6777b538SAndroid Build Coastguard Worker def _PrintParsedLine(self, parsed_line, dim=False): 860*6777b538SAndroid Build Coastguard Worker if self._exit_on_match and self._exit_on_match.search(parsed_line.message): 861*6777b538SAndroid Build Coastguard Worker self._found_exit_match = True 862*6777b538SAndroid Build Coastguard Worker 863*6777b538SAndroid Build Coastguard Worker tid_style = colorama.Style.NORMAL 864*6777b538SAndroid Build Coastguard Worker user_match = self._user_defined_highlight and ( 865*6777b538SAndroid Build Coastguard Worker re.search(self._user_defined_highlight, parsed_line.tag) 866*6777b538SAndroid Build Coastguard Worker or re.search(self._user_defined_highlight, parsed_line.message)) 867*6777b538SAndroid Build Coastguard Worker 868*6777b538SAndroid Build Coastguard Worker # Make the main thread bright. 869*6777b538SAndroid Build Coastguard Worker if not dim and parsed_line.pid == parsed_line.tid: 870*6777b538SAndroid Build Coastguard Worker tid_style = colorama.Style.BRIGHT 871*6777b538SAndroid Build Coastguard Worker pid_style = self._GetPidStyle(parsed_line.pid, dim) 872*6777b538SAndroid Build Coastguard Worker msg_style = pid_style if not user_match else (colorama.Fore.GREEN + 873*6777b538SAndroid Build Coastguard Worker colorama.Style.BRIGHT) 874*6777b538SAndroid Build Coastguard Worker # We have to pad before adding color as that changes the width of the tag. 875*6777b538SAndroid Build Coastguard Worker pid_str = _Colorize('{:5}'.format(parsed_line.pid), pid_style) 876*6777b538SAndroid Build Coastguard Worker tid_str = _Colorize('{:5}'.format(parsed_line.tid), tid_style) 877*6777b538SAndroid Build Coastguard Worker tag = _Colorize('{:8}'.format(parsed_line.tag), 878*6777b538SAndroid Build Coastguard Worker pid_style + ('' if dim else colorama.Style.BRIGHT)) 879*6777b538SAndroid Build Coastguard Worker priority = _Colorize(parsed_line.priority, 880*6777b538SAndroid Build Coastguard Worker self._GetPriorityStyle(parsed_line.priority)) 881*6777b538SAndroid Build Coastguard Worker messages = [parsed_line.message] 882*6777b538SAndroid Build Coastguard Worker if self._deobfuscator: 883*6777b538SAndroid Build Coastguard Worker messages = self._deobfuscator.TransformLines(messages) 884*6777b538SAndroid Build Coastguard Worker for message in messages: 885*6777b538SAndroid Build Coastguard Worker message = _Colorize(message, msg_style) 886*6777b538SAndroid Build Coastguard Worker sys.stdout.write('{} {} {} {} {} {}: {}\n'.format( 887*6777b538SAndroid Build Coastguard Worker parsed_line.date, parsed_line.invokation_time, pid_str, tid_str, 888*6777b538SAndroid Build Coastguard Worker priority, tag, message)) 889*6777b538SAndroid Build Coastguard Worker 890*6777b538SAndroid Build Coastguard Worker def _TriggerNonceFound(self): 891*6777b538SAndroid Build Coastguard Worker # Once the nonce is hit, we have confidence that we know which lines 892*6777b538SAndroid Build Coastguard Worker # belong to the current run of the app. Process all of the buffered lines. 893*6777b538SAndroid Build Coastguard Worker if self._primary_pid: 894*6777b538SAndroid Build Coastguard Worker for args in self._initial_buffered_lines: 895*6777b538SAndroid Build Coastguard Worker self._print_func(*args) 896*6777b538SAndroid Build Coastguard Worker self._initial_buffered_lines = None 897*6777b538SAndroid Build Coastguard Worker self.nonce = None 898*6777b538SAndroid Build Coastguard Worker 899*6777b538SAndroid Build Coastguard Worker def FoundExitMatch(self): 900*6777b538SAndroid Build Coastguard Worker return self._found_exit_match 901*6777b538SAndroid Build Coastguard Worker 902*6777b538SAndroid Build Coastguard Worker def ProcessLine(self, line): 903*6777b538SAndroid Build Coastguard Worker if not line or line.startswith('------'): 904*6777b538SAndroid Build Coastguard Worker return 905*6777b538SAndroid Build Coastguard Worker 906*6777b538SAndroid Build Coastguard Worker if self.nonce and self.nonce in line: 907*6777b538SAndroid Build Coastguard Worker self._TriggerNonceFound() 908*6777b538SAndroid Build Coastguard Worker 909*6777b538SAndroid Build Coastguard Worker nonce_found = self.nonce is None 910*6777b538SAndroid Build Coastguard Worker 911*6777b538SAndroid Build Coastguard Worker log = self._ParseLine(line) 912*6777b538SAndroid Build Coastguard Worker if log.pid not in self._seen_pids: 913*6777b538SAndroid Build Coastguard Worker self._seen_pids.add(log.pid) 914*6777b538SAndroid Build Coastguard Worker if nonce_found: 915*6777b538SAndroid Build Coastguard Worker # Update list of owned PIDs each time a new PID is encountered. 916*6777b538SAndroid Build Coastguard Worker self._UpdateMyPids() 917*6777b538SAndroid Build Coastguard Worker 918*6777b538SAndroid Build Coastguard Worker # Search for "Start proc $pid:$package_name/" message. 919*6777b538SAndroid Build Coastguard Worker if not nonce_found: 920*6777b538SAndroid Build Coastguard Worker # Capture logs before the nonce. Start with the most recent "am start". 921*6777b538SAndroid Build Coastguard Worker if self._start_pattern.match(log.message): 922*6777b538SAndroid Build Coastguard Worker self._initial_buffered_lines = [] 923*6777b538SAndroid Build Coastguard Worker 924*6777b538SAndroid Build Coastguard Worker # If we didn't find the PID via "ps", then extract it from log messages. 925*6777b538SAndroid Build Coastguard Worker # This will happen if the app crashes too quickly. 926*6777b538SAndroid Build Coastguard Worker if not self._found_initial_pid: 927*6777b538SAndroid Build Coastguard Worker m = self._pid_pattern.match(log.message) 928*6777b538SAndroid Build Coastguard Worker if m: 929*6777b538SAndroid Build Coastguard Worker # Find the most recent "Start proc" line before the nonce. 930*6777b538SAndroid Build Coastguard Worker # Track only the primary pid in this mode. 931*6777b538SAndroid Build Coastguard Worker # The main use-case is to find app logs when no current PIDs exist. 932*6777b538SAndroid Build Coastguard Worker # E.g.: When the app crashes on launch. 933*6777b538SAndroid Build Coastguard Worker self._primary_pid = m.group(1) 934*6777b538SAndroid Build Coastguard Worker self._my_pids.clear() 935*6777b538SAndroid Build Coastguard Worker self._my_pids.add(m.group(1)) 936*6777b538SAndroid Build Coastguard Worker 937*6777b538SAndroid Build Coastguard Worker owned_pid = log.pid in self._my_pids 938*6777b538SAndroid Build Coastguard Worker if owned_pid and not self._verbose and log.tag == 'dalvikvm': 939*6777b538SAndroid Build Coastguard Worker if self._DALVIK_IGNORE_PATTERN.match(log.message): 940*6777b538SAndroid Build Coastguard Worker return 941*6777b538SAndroid Build Coastguard Worker 942*6777b538SAndroid Build Coastguard Worker if owned_pid or self._verbose or (log.priority == 'F' or # Java crash dump 943*6777b538SAndroid Build Coastguard Worker log.tag in self._ALLOWLISTED_TAGS): 944*6777b538SAndroid Build Coastguard Worker if nonce_found: 945*6777b538SAndroid Build Coastguard Worker self._print_func(log, not owned_pid) 946*6777b538SAndroid Build Coastguard Worker else: 947*6777b538SAndroid Build Coastguard Worker self._initial_buffered_lines.append((log, not owned_pid)) 948*6777b538SAndroid Build Coastguard Worker 949*6777b538SAndroid Build Coastguard Worker 950*6777b538SAndroid Build Coastguard Workerdef _RunLogcat(device, 951*6777b538SAndroid Build Coastguard Worker package_name, 952*6777b538SAndroid Build Coastguard Worker stack_script_context, 953*6777b538SAndroid Build Coastguard Worker deobfuscate, 954*6777b538SAndroid Build Coastguard Worker verbose, 955*6777b538SAndroid Build Coastguard Worker exit_on_match=None, 956*6777b538SAndroid Build Coastguard Worker extra_package_names=None): 957*6777b538SAndroid Build Coastguard Worker logcat_processor = _LogcatProcessor(device, 958*6777b538SAndroid Build Coastguard Worker package_name, 959*6777b538SAndroid Build Coastguard Worker stack_script_context, 960*6777b538SAndroid Build Coastguard Worker deobfuscate, 961*6777b538SAndroid Build Coastguard Worker verbose, 962*6777b538SAndroid Build Coastguard Worker exit_on_match=exit_on_match, 963*6777b538SAndroid Build Coastguard Worker extra_package_names=extra_package_names) 964*6777b538SAndroid Build Coastguard Worker device.RunShellCommand(['log', logcat_processor.nonce]) 965*6777b538SAndroid Build Coastguard Worker for line in device.adb.Logcat(logcat_format='threadtime'): 966*6777b538SAndroid Build Coastguard Worker try: 967*6777b538SAndroid Build Coastguard Worker logcat_processor.ProcessLine(line) 968*6777b538SAndroid Build Coastguard Worker if logcat_processor.FoundExitMatch(): 969*6777b538SAndroid Build Coastguard Worker return 970*6777b538SAndroid Build Coastguard Worker except: 971*6777b538SAndroid Build Coastguard Worker sys.stderr.write('Failed to process line: ' + line + '\n') 972*6777b538SAndroid Build Coastguard Worker # Skip stack trace for the common case of the adb server being 973*6777b538SAndroid Build Coastguard Worker # restarted. 974*6777b538SAndroid Build Coastguard Worker if 'unexpected EOF' in line: 975*6777b538SAndroid Build Coastguard Worker sys.exit(1) 976*6777b538SAndroid Build Coastguard Worker raise 977*6777b538SAndroid Build Coastguard Worker 978*6777b538SAndroid Build Coastguard Worker 979*6777b538SAndroid Build Coastguard Workerdef _GetPackageProcesses(device, package_name): 980*6777b538SAndroid Build Coastguard Worker my_names = (package_name, package_name + '_zygote') 981*6777b538SAndroid Build Coastguard Worker return [ 982*6777b538SAndroid Build Coastguard Worker p for p in device.ListProcesses(package_name) 983*6777b538SAndroid Build Coastguard Worker if p.name in my_names or p.name.startswith(package_name + ':') 984*6777b538SAndroid Build Coastguard Worker ] 985*6777b538SAndroid Build Coastguard Worker 986*6777b538SAndroid Build Coastguard Worker 987*6777b538SAndroid Build Coastguard Workerdef _RunPs(devices, package_name): 988*6777b538SAndroid Build Coastguard Worker parallel_devices = device_utils.DeviceUtils.parallel(devices) 989*6777b538SAndroid Build Coastguard Worker all_processes = parallel_devices.pMap( 990*6777b538SAndroid Build Coastguard Worker lambda d: _GetPackageProcesses(d, package_name)).pGet(None) 991*6777b538SAndroid Build Coastguard Worker for processes in _PrintPerDeviceOutput(devices, all_processes): 992*6777b538SAndroid Build Coastguard Worker if not processes: 993*6777b538SAndroid Build Coastguard Worker print('No processes found.') 994*6777b538SAndroid Build Coastguard Worker else: 995*6777b538SAndroid Build Coastguard Worker proc_map = collections.defaultdict(list) 996*6777b538SAndroid Build Coastguard Worker for p in processes: 997*6777b538SAndroid Build Coastguard Worker proc_map[p.name].append(str(p.pid)) 998*6777b538SAndroid Build Coastguard Worker for name, pids in sorted(proc_map.items()): 999*6777b538SAndroid Build Coastguard Worker print(name, ','.join(pids)) 1000*6777b538SAndroid Build Coastguard Worker 1001*6777b538SAndroid Build Coastguard Worker 1002*6777b538SAndroid Build Coastguard Workerdef _RunShell(devices, package_name, cmd): 1003*6777b538SAndroid Build Coastguard Worker if cmd: 1004*6777b538SAndroid Build Coastguard Worker parallel_devices = device_utils.DeviceUtils.parallel(devices) 1005*6777b538SAndroid Build Coastguard Worker outputs = parallel_devices.RunShellCommand( 1006*6777b538SAndroid Build Coastguard Worker cmd, run_as=package_name).pGet(None) 1007*6777b538SAndroid Build Coastguard Worker for output in _PrintPerDeviceOutput(devices, outputs): 1008*6777b538SAndroid Build Coastguard Worker for line in output: 1009*6777b538SAndroid Build Coastguard Worker print(line) 1010*6777b538SAndroid Build Coastguard Worker else: 1011*6777b538SAndroid Build Coastguard Worker adb_path = adb_wrapper.AdbWrapper.GetAdbPath() 1012*6777b538SAndroid Build Coastguard Worker cmd = [adb_path, '-s', devices[0].serial, 'shell'] 1013*6777b538SAndroid Build Coastguard Worker # Pre-N devices do not support -t flag. 1014*6777b538SAndroid Build Coastguard Worker if devices[0].build_version_sdk >= version_codes.NOUGAT: 1015*6777b538SAndroid Build Coastguard Worker cmd += ['-t', 'run-as', package_name] 1016*6777b538SAndroid Build Coastguard Worker else: 1017*6777b538SAndroid Build Coastguard Worker print('Upon entering the shell, run:') 1018*6777b538SAndroid Build Coastguard Worker print('run-as', package_name) 1019*6777b538SAndroid Build Coastguard Worker print() 1020*6777b538SAndroid Build Coastguard Worker os.execv(adb_path, cmd) 1021*6777b538SAndroid Build Coastguard Worker 1022*6777b538SAndroid Build Coastguard Worker 1023*6777b538SAndroid Build Coastguard Workerdef _RunCompileDex(devices, package_name, compilation_filter): 1024*6777b538SAndroid Build Coastguard Worker cmd = ['cmd', 'package', 'compile', '-f', '-m', compilation_filter, 1025*6777b538SAndroid Build Coastguard Worker package_name] 1026*6777b538SAndroid Build Coastguard Worker parallel_devices = device_utils.DeviceUtils.parallel(devices) 1027*6777b538SAndroid Build Coastguard Worker outputs = parallel_devices.RunShellCommand(cmd, timeout=120).pGet(None) 1028*6777b538SAndroid Build Coastguard Worker for output in _PrintPerDeviceOutput(devices, outputs): 1029*6777b538SAndroid Build Coastguard Worker for line in output: 1030*6777b538SAndroid Build Coastguard Worker print(line) 1031*6777b538SAndroid Build Coastguard Worker 1032*6777b538SAndroid Build Coastguard Worker 1033*6777b538SAndroid Build Coastguard Workerdef _RunProfile(device, package_name, host_build_directory, pprof_out_path, 1034*6777b538SAndroid Build Coastguard Worker process_specifier, thread_specifier, events, extra_args): 1035*6777b538SAndroid Build Coastguard Worker simpleperf.PrepareDevice(device) 1036*6777b538SAndroid Build Coastguard Worker device_simpleperf_path = simpleperf.InstallSimpleperf(device, package_name) 1037*6777b538SAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile() as fh: 1038*6777b538SAndroid Build Coastguard Worker host_simpleperf_out_path = fh.name 1039*6777b538SAndroid Build Coastguard Worker 1040*6777b538SAndroid Build Coastguard Worker with simpleperf.RunSimpleperf(device, device_simpleperf_path, package_name, 1041*6777b538SAndroid Build Coastguard Worker process_specifier, thread_specifier, 1042*6777b538SAndroid Build Coastguard Worker events, extra_args, host_simpleperf_out_path): 1043*6777b538SAndroid Build Coastguard Worker sys.stdout.write('Profiler is running; press Enter to stop...\n') 1044*6777b538SAndroid Build Coastguard Worker sys.stdin.read(1) 1045*6777b538SAndroid Build Coastguard Worker sys.stdout.write('Post-processing data...\n') 1046*6777b538SAndroid Build Coastguard Worker 1047*6777b538SAndroid Build Coastguard Worker simpleperf.ConvertSimpleperfToPprof(host_simpleperf_out_path, 1048*6777b538SAndroid Build Coastguard Worker host_build_directory, pprof_out_path) 1049*6777b538SAndroid Build Coastguard Worker print(textwrap.dedent(""" 1050*6777b538SAndroid Build Coastguard Worker Profile data written to %(s)s. 1051*6777b538SAndroid Build Coastguard Worker 1052*6777b538SAndroid Build Coastguard Worker To view profile as a call graph in browser: 1053*6777b538SAndroid Build Coastguard Worker pprof -web %(s)s 1054*6777b538SAndroid Build Coastguard Worker 1055*6777b538SAndroid Build Coastguard Worker To print the hottest methods: 1056*6777b538SAndroid Build Coastguard Worker pprof -top %(s)s 1057*6777b538SAndroid Build Coastguard Worker 1058*6777b538SAndroid Build Coastguard Worker pprof has many useful customization options; `pprof --help` for details. 1059*6777b538SAndroid Build Coastguard Worker """ % {'s': pprof_out_path})) 1060*6777b538SAndroid Build Coastguard Worker 1061*6777b538SAndroid Build Coastguard Worker 1062*6777b538SAndroid Build Coastguard Workerclass _StackScriptContext: 1063*6777b538SAndroid Build Coastguard Worker """Maintains temporary files needed by stack.py.""" 1064*6777b538SAndroid Build Coastguard Worker 1065*6777b538SAndroid Build Coastguard Worker def __init__(self, 1066*6777b538SAndroid Build Coastguard Worker output_directory, 1067*6777b538SAndroid Build Coastguard Worker apk_path, 1068*6777b538SAndroid Build Coastguard Worker bundle_generation_info, 1069*6777b538SAndroid Build Coastguard Worker quiet=False): 1070*6777b538SAndroid Build Coastguard Worker self._output_directory = output_directory 1071*6777b538SAndroid Build Coastguard Worker self._apk_path = apk_path 1072*6777b538SAndroid Build Coastguard Worker self._bundle_generation_info = bundle_generation_info 1073*6777b538SAndroid Build Coastguard Worker self._staging_dir = None 1074*6777b538SAndroid Build Coastguard Worker self._quiet = quiet 1075*6777b538SAndroid Build Coastguard Worker 1076*6777b538SAndroid Build Coastguard Worker def _CreateStaging(self): 1077*6777b538SAndroid Build Coastguard Worker # In many cases, stack decoding requires APKs to map trace lines to native 1078*6777b538SAndroid Build Coastguard Worker # libraries. Create a temporary directory, and either unpack a bundle's 1079*6777b538SAndroid Build Coastguard Worker # APKS into it, or simply symlink the standalone APK into it. This 1080*6777b538SAndroid Build Coastguard Worker # provides an unambiguous set of APK files for the stack decoding process 1081*6777b538SAndroid Build Coastguard Worker # to inspect. 1082*6777b538SAndroid Build Coastguard Worker logging.debug('Creating stack staging directory') 1083*6777b538SAndroid Build Coastguard Worker self._staging_dir = tempfile.mkdtemp() 1084*6777b538SAndroid Build Coastguard Worker bundle_generation_info = self._bundle_generation_info 1085*6777b538SAndroid Build Coastguard Worker 1086*6777b538SAndroid Build Coastguard Worker if bundle_generation_info: 1087*6777b538SAndroid Build Coastguard Worker # TODO(wnwen): Use apk_helper instead. 1088*6777b538SAndroid Build Coastguard Worker _GenerateBundleApks(bundle_generation_info) 1089*6777b538SAndroid Build Coastguard Worker logging.debug('Extracting .apks file') 1090*6777b538SAndroid Build Coastguard Worker with zipfile.ZipFile(bundle_generation_info.bundle_apks_path, 'r') as z: 1091*6777b538SAndroid Build Coastguard Worker files_to_extract = [ 1092*6777b538SAndroid Build Coastguard Worker f for f in z.namelist() if f.endswith('-master.apk') 1093*6777b538SAndroid Build Coastguard Worker ] 1094*6777b538SAndroid Build Coastguard Worker z.extractall(self._staging_dir, files_to_extract) 1095*6777b538SAndroid Build Coastguard Worker elif self._apk_path: 1096*6777b538SAndroid Build Coastguard Worker # Otherwise an incremental APK and an empty apks directory is correct. 1097*6777b538SAndroid Build Coastguard Worker output = os.path.join(self._staging_dir, os.path.basename(self._apk_path)) 1098*6777b538SAndroid Build Coastguard Worker os.symlink(self._apk_path, output) 1099*6777b538SAndroid Build Coastguard Worker 1100*6777b538SAndroid Build Coastguard Worker def Close(self): 1101*6777b538SAndroid Build Coastguard Worker if self._staging_dir: 1102*6777b538SAndroid Build Coastguard Worker logging.debug('Clearing stack staging directory') 1103*6777b538SAndroid Build Coastguard Worker shutil.rmtree(self._staging_dir) 1104*6777b538SAndroid Build Coastguard Worker self._staging_dir = None 1105*6777b538SAndroid Build Coastguard Worker 1106*6777b538SAndroid Build Coastguard Worker def Popen(self, input_file=None, **kwargs): 1107*6777b538SAndroid Build Coastguard Worker if self._staging_dir is None: 1108*6777b538SAndroid Build Coastguard Worker self._CreateStaging() 1109*6777b538SAndroid Build Coastguard Worker stack_script = os.path.join( 1110*6777b538SAndroid Build Coastguard Worker constants.host_paths.ANDROID_PLATFORM_DEVELOPMENT_SCRIPTS_PATH, 1111*6777b538SAndroid Build Coastguard Worker 'stack.py') 1112*6777b538SAndroid Build Coastguard Worker cmd = [ 1113*6777b538SAndroid Build Coastguard Worker stack_script, '--output-directory', self._output_directory, 1114*6777b538SAndroid Build Coastguard Worker '--apks-directory', self._staging_dir 1115*6777b538SAndroid Build Coastguard Worker ] 1116*6777b538SAndroid Build Coastguard Worker if self._quiet: 1117*6777b538SAndroid Build Coastguard Worker cmd.append('--quiet') 1118*6777b538SAndroid Build Coastguard Worker if input_file: 1119*6777b538SAndroid Build Coastguard Worker cmd.append(input_file) 1120*6777b538SAndroid Build Coastguard Worker logging.info('Running: %s', shlex.join(cmd)) 1121*6777b538SAndroid Build Coastguard Worker return subprocess.Popen(cmd, universal_newlines=True, **kwargs) 1122*6777b538SAndroid Build Coastguard Worker 1123*6777b538SAndroid Build Coastguard Worker 1124*6777b538SAndroid Build Coastguard Workerdef _GenerateAvailableDevicesMessage(devices): 1125*6777b538SAndroid Build Coastguard Worker devices_obj = device_utils.DeviceUtils.parallel(devices) 1126*6777b538SAndroid Build Coastguard Worker descriptions = devices_obj.pMap(lambda d: d.build_description).pGet(None) 1127*6777b538SAndroid Build Coastguard Worker msg = 'Available devices:\n' 1128*6777b538SAndroid Build Coastguard Worker for d, desc in zip(devices, descriptions): 1129*6777b538SAndroid Build Coastguard Worker msg += ' %s (%s)\n' % (d, desc) 1130*6777b538SAndroid Build Coastguard Worker return msg 1131*6777b538SAndroid Build Coastguard Worker 1132*6777b538SAndroid Build Coastguard Worker 1133*6777b538SAndroid Build Coastguard Worker# TODO(agrieve):add "--all" in the MultipleDevicesError message and use it here. 1134*6777b538SAndroid Build Coastguard Workerdef _GenerateMissingAllFlagMessage(devices): 1135*6777b538SAndroid Build Coastguard Worker return ('More than one device available. Use --all to select all devices, ' + 1136*6777b538SAndroid Build Coastguard Worker 'or use --device to select a device by serial.\n\n' + 1137*6777b538SAndroid Build Coastguard Worker _GenerateAvailableDevicesMessage(devices)) 1138*6777b538SAndroid Build Coastguard Worker 1139*6777b538SAndroid Build Coastguard Worker 1140*6777b538SAndroid Build Coastguard Workerdef _DisplayArgs(devices, command_line_flags_file): 1141*6777b538SAndroid Build Coastguard Worker def flags_helper(d): 1142*6777b538SAndroid Build Coastguard Worker changer = flag_changer.FlagChanger(d, command_line_flags_file) 1143*6777b538SAndroid Build Coastguard Worker return changer.GetCurrentFlags() 1144*6777b538SAndroid Build Coastguard Worker 1145*6777b538SAndroid Build Coastguard Worker parallel_devices = device_utils.DeviceUtils.parallel(devices) 1146*6777b538SAndroid Build Coastguard Worker outputs = parallel_devices.pMap(flags_helper).pGet(None) 1147*6777b538SAndroid Build Coastguard Worker print('Existing flags per-device (via /data/local/tmp/{}):'.format( 1148*6777b538SAndroid Build Coastguard Worker command_line_flags_file)) 1149*6777b538SAndroid Build Coastguard Worker for flags in _PrintPerDeviceOutput(devices, outputs, single_line=True): 1150*6777b538SAndroid Build Coastguard Worker quoted_flags = ' '.join(shlex.quote(f) for f in flags) 1151*6777b538SAndroid Build Coastguard Worker print(quoted_flags or 'No flags set.') 1152*6777b538SAndroid Build Coastguard Worker 1153*6777b538SAndroid Build Coastguard Worker 1154*6777b538SAndroid Build Coastguard Workerdef _DeviceCachePath(device, output_directory): 1155*6777b538SAndroid Build Coastguard Worker file_name = 'device_cache_%s.json' % device.serial 1156*6777b538SAndroid Build Coastguard Worker return os.path.join(output_directory, file_name) 1157*6777b538SAndroid Build Coastguard Worker 1158*6777b538SAndroid Build Coastguard Worker 1159*6777b538SAndroid Build Coastguard Workerdef _LoadDeviceCaches(devices, output_directory): 1160*6777b538SAndroid Build Coastguard Worker if not output_directory: 1161*6777b538SAndroid Build Coastguard Worker return 1162*6777b538SAndroid Build Coastguard Worker for d in devices: 1163*6777b538SAndroid Build Coastguard Worker cache_path = _DeviceCachePath(d, output_directory) 1164*6777b538SAndroid Build Coastguard Worker if os.path.exists(cache_path): 1165*6777b538SAndroid Build Coastguard Worker logging.debug('Using device cache: %s', cache_path) 1166*6777b538SAndroid Build Coastguard Worker with open(cache_path) as f: 1167*6777b538SAndroid Build Coastguard Worker d.LoadCacheData(f.read()) 1168*6777b538SAndroid Build Coastguard Worker # Delete the cached file so that any exceptions cause it to be cleared. 1169*6777b538SAndroid Build Coastguard Worker os.unlink(cache_path) 1170*6777b538SAndroid Build Coastguard Worker else: 1171*6777b538SAndroid Build Coastguard Worker logging.debug('No cache present for device: %s', d) 1172*6777b538SAndroid Build Coastguard Worker 1173*6777b538SAndroid Build Coastguard Worker 1174*6777b538SAndroid Build Coastguard Workerdef _SaveDeviceCaches(devices, output_directory): 1175*6777b538SAndroid Build Coastguard Worker if not output_directory: 1176*6777b538SAndroid Build Coastguard Worker return 1177*6777b538SAndroid Build Coastguard Worker for d in devices: 1178*6777b538SAndroid Build Coastguard Worker cache_path = _DeviceCachePath(d, output_directory) 1179*6777b538SAndroid Build Coastguard Worker with open(cache_path, 'w') as f: 1180*6777b538SAndroid Build Coastguard Worker f.write(d.DumpCacheData()) 1181*6777b538SAndroid Build Coastguard Worker logging.info('Wrote device cache: %s', cache_path) 1182*6777b538SAndroid Build Coastguard Worker 1183*6777b538SAndroid Build Coastguard Worker 1184*6777b538SAndroid Build Coastguard Workerclass _Command: 1185*6777b538SAndroid Build Coastguard Worker name = None 1186*6777b538SAndroid Build Coastguard Worker description = None 1187*6777b538SAndroid Build Coastguard Worker long_description = None 1188*6777b538SAndroid Build Coastguard Worker needs_package_name = False 1189*6777b538SAndroid Build Coastguard Worker needs_output_directory = False 1190*6777b538SAndroid Build Coastguard Worker needs_apk_helper = False 1191*6777b538SAndroid Build Coastguard Worker supports_incremental = False 1192*6777b538SAndroid Build Coastguard Worker accepts_command_line_flags = False 1193*6777b538SAndroid Build Coastguard Worker accepts_args = False 1194*6777b538SAndroid Build Coastguard Worker need_device_args = True 1195*6777b538SAndroid Build Coastguard Worker all_devices_by_default = False 1196*6777b538SAndroid Build Coastguard Worker calls_exec = False 1197*6777b538SAndroid Build Coastguard Worker supports_multiple_devices = True 1198*6777b538SAndroid Build Coastguard Worker 1199*6777b538SAndroid Build Coastguard Worker def __init__(self, from_wrapper_script, is_bundle, is_test_apk): 1200*6777b538SAndroid Build Coastguard Worker self._parser = None 1201*6777b538SAndroid Build Coastguard Worker self._from_wrapper_script = from_wrapper_script 1202*6777b538SAndroid Build Coastguard Worker self.args = None 1203*6777b538SAndroid Build Coastguard Worker self.apk_helper = None 1204*6777b538SAndroid Build Coastguard Worker self.additional_apk_helpers = None 1205*6777b538SAndroid Build Coastguard Worker self.install_dict = None 1206*6777b538SAndroid Build Coastguard Worker self.devices = None 1207*6777b538SAndroid Build Coastguard Worker self.is_bundle = is_bundle 1208*6777b538SAndroid Build Coastguard Worker self.is_test_apk = is_test_apk 1209*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info = None 1210*6777b538SAndroid Build Coastguard Worker # Only support incremental install from APK wrapper scripts. 1211*6777b538SAndroid Build Coastguard Worker if is_bundle or not from_wrapper_script: 1212*6777b538SAndroid Build Coastguard Worker self.supports_incremental = False 1213*6777b538SAndroid Build Coastguard Worker 1214*6777b538SAndroid Build Coastguard Worker def RegisterBundleGenerationInfo(self, bundle_generation_info): 1215*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info = bundle_generation_info 1216*6777b538SAndroid Build Coastguard Worker 1217*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1218*6777b538SAndroid Build Coastguard Worker pass 1219*6777b538SAndroid Build Coastguard Worker 1220*6777b538SAndroid Build Coastguard Worker def RegisterArgs(self, parser): 1221*6777b538SAndroid Build Coastguard Worker subp = parser.add_parser( 1222*6777b538SAndroid Build Coastguard Worker self.name, help=self.description, 1223*6777b538SAndroid Build Coastguard Worker description=self.long_description or self.description, 1224*6777b538SAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter) 1225*6777b538SAndroid Build Coastguard Worker self._parser = subp 1226*6777b538SAndroid Build Coastguard Worker subp.set_defaults(command=self) 1227*6777b538SAndroid Build Coastguard Worker if self.need_device_args: 1228*6777b538SAndroid Build Coastguard Worker subp.add_argument('--all', 1229*6777b538SAndroid Build Coastguard Worker action='store_true', 1230*6777b538SAndroid Build Coastguard Worker default=self.all_devices_by_default, 1231*6777b538SAndroid Build Coastguard Worker help='Operate on all connected devices.',) 1232*6777b538SAndroid Build Coastguard Worker subp.add_argument('-d', 1233*6777b538SAndroid Build Coastguard Worker '--device', 1234*6777b538SAndroid Build Coastguard Worker action='append', 1235*6777b538SAndroid Build Coastguard Worker default=[], 1236*6777b538SAndroid Build Coastguard Worker dest='devices', 1237*6777b538SAndroid Build Coastguard Worker help='Target device for script to work on. Enter ' 1238*6777b538SAndroid Build Coastguard Worker 'multiple times for multiple devices.') 1239*6777b538SAndroid Build Coastguard Worker subp.add_argument('-v', 1240*6777b538SAndroid Build Coastguard Worker '--verbose', 1241*6777b538SAndroid Build Coastguard Worker action='count', 1242*6777b538SAndroid Build Coastguard Worker default=0, 1243*6777b538SAndroid Build Coastguard Worker dest='verbose_count', 1244*6777b538SAndroid Build Coastguard Worker help='Verbose level (multiple times for more)') 1245*6777b538SAndroid Build Coastguard Worker group = subp.add_argument_group('%s arguments' % self.name) 1246*6777b538SAndroid Build Coastguard Worker 1247*6777b538SAndroid Build Coastguard Worker if self.needs_package_name: 1248*6777b538SAndroid Build Coastguard Worker # Three cases to consider here, since later code assumes 1249*6777b538SAndroid Build Coastguard Worker # self.args.package_name always exists, even if None: 1250*6777b538SAndroid Build Coastguard Worker # 1251*6777b538SAndroid Build Coastguard Worker # - Called from a bundle wrapper script, the package_name is already 1252*6777b538SAndroid Build Coastguard Worker # set through parser.set_defaults(), so don't call add_argument() 1253*6777b538SAndroid Build Coastguard Worker # to avoid overriding its value. 1254*6777b538SAndroid Build Coastguard Worker # 1255*6777b538SAndroid Build Coastguard Worker # - Called from an apk wrapper script. The --package-name argument 1256*6777b538SAndroid Build Coastguard Worker # should not appear, but self.args.package_name will be gleaned from 1257*6777b538SAndroid Build Coastguard Worker # the --apk-path file later. 1258*6777b538SAndroid Build Coastguard Worker # 1259*6777b538SAndroid Build Coastguard Worker # - Called directly, then --package-name is required on the command-line. 1260*6777b538SAndroid Build Coastguard Worker # 1261*6777b538SAndroid Build Coastguard Worker if not self.is_bundle: 1262*6777b538SAndroid Build Coastguard Worker group.add_argument( 1263*6777b538SAndroid Build Coastguard Worker '--package-name', 1264*6777b538SAndroid Build Coastguard Worker help=argparse.SUPPRESS if self._from_wrapper_script else ( 1265*6777b538SAndroid Build Coastguard Worker "App's package name.")) 1266*6777b538SAndroid Build Coastguard Worker 1267*6777b538SAndroid Build Coastguard Worker if self.needs_apk_helper or self.needs_package_name: 1268*6777b538SAndroid Build Coastguard Worker # Adding this argument to the subparser would override the set_defaults() 1269*6777b538SAndroid Build Coastguard Worker # value set by on the parent parser (even if None). 1270*6777b538SAndroid Build Coastguard Worker if not self._from_wrapper_script and not self.is_bundle: 1271*6777b538SAndroid Build Coastguard Worker group.add_argument( 1272*6777b538SAndroid Build Coastguard Worker '--apk-path', required=self.needs_apk_helper, help='Path to .apk') 1273*6777b538SAndroid Build Coastguard Worker 1274*6777b538SAndroid Build Coastguard Worker if self.supports_incremental: 1275*6777b538SAndroid Build Coastguard Worker group.add_argument('--incremental', 1276*6777b538SAndroid Build Coastguard Worker action='store_true', 1277*6777b538SAndroid Build Coastguard Worker default=False, 1278*6777b538SAndroid Build Coastguard Worker help='Always install an incremental apk.') 1279*6777b538SAndroid Build Coastguard Worker group.add_argument('--non-incremental', 1280*6777b538SAndroid Build Coastguard Worker action='store_true', 1281*6777b538SAndroid Build Coastguard Worker default=False, 1282*6777b538SAndroid Build Coastguard Worker help='Always install a non-incremental apk.') 1283*6777b538SAndroid Build Coastguard Worker 1284*6777b538SAndroid Build Coastguard Worker # accepts_command_line_flags and accepts_args are mutually exclusive. 1285*6777b538SAndroid Build Coastguard Worker # argparse will throw if they are both set. 1286*6777b538SAndroid Build Coastguard Worker if self.accepts_command_line_flags: 1287*6777b538SAndroid Build Coastguard Worker group.add_argument( 1288*6777b538SAndroid Build Coastguard Worker '--args', help='Command-line flags. Use = to assign args.') 1289*6777b538SAndroid Build Coastguard Worker 1290*6777b538SAndroid Build Coastguard Worker if self.accepts_args: 1291*6777b538SAndroid Build Coastguard Worker group.add_argument( 1292*6777b538SAndroid Build Coastguard Worker '--args', help='Extra arguments. Use = to assign args') 1293*6777b538SAndroid Build Coastguard Worker 1294*6777b538SAndroid Build Coastguard Worker if not self._from_wrapper_script and self.accepts_command_line_flags: 1295*6777b538SAndroid Build Coastguard Worker # Provided by wrapper scripts. 1296*6777b538SAndroid Build Coastguard Worker group.add_argument( 1297*6777b538SAndroid Build Coastguard Worker '--command-line-flags-file', 1298*6777b538SAndroid Build Coastguard Worker help='Name of the command-line flags file') 1299*6777b538SAndroid Build Coastguard Worker 1300*6777b538SAndroid Build Coastguard Worker self._RegisterExtraArgs(group) 1301*6777b538SAndroid Build Coastguard Worker 1302*6777b538SAndroid Build Coastguard Worker def _CreateApkHelpers(self, args, incremental_apk_path, install_dict): 1303*6777b538SAndroid Build Coastguard Worker """Returns true iff self.apk_helper was created and assigned.""" 1304*6777b538SAndroid Build Coastguard Worker if self.apk_helper is None: 1305*6777b538SAndroid Build Coastguard Worker if args.apk_path: 1306*6777b538SAndroid Build Coastguard Worker self.apk_helper = apk_helper.ToHelper(args.apk_path) 1307*6777b538SAndroid Build Coastguard Worker elif incremental_apk_path: 1308*6777b538SAndroid Build Coastguard Worker self.install_dict = install_dict 1309*6777b538SAndroid Build Coastguard Worker self.apk_helper = apk_helper.ToHelper(incremental_apk_path) 1310*6777b538SAndroid Build Coastguard Worker elif self.is_bundle: 1311*6777b538SAndroid Build Coastguard Worker _GenerateBundleApks(self.bundle_generation_info) 1312*6777b538SAndroid Build Coastguard Worker self.apk_helper = apk_helper.ToHelper( 1313*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info.bundle_apks_path) 1314*6777b538SAndroid Build Coastguard Worker if args.additional_apk_paths and self.additional_apk_helpers is None: 1315*6777b538SAndroid Build Coastguard Worker self.additional_apk_helpers = [ 1316*6777b538SAndroid Build Coastguard Worker apk_helper.ToHelper(apk_path) 1317*6777b538SAndroid Build Coastguard Worker for apk_path in args.additional_apk_paths 1318*6777b538SAndroid Build Coastguard Worker ] 1319*6777b538SAndroid Build Coastguard Worker return self.apk_helper is not None 1320*6777b538SAndroid Build Coastguard Worker 1321*6777b538SAndroid Build Coastguard Worker def _FindSupportedDevices(self, devices): 1322*6777b538SAndroid Build Coastguard Worker """Returns supported devices and reasons for each not supported one.""" 1323*6777b538SAndroid Build Coastguard Worker app_abis = self.apk_helper.GetAbis() 1324*6777b538SAndroid Build Coastguard Worker calling_script_name = os.path.basename(sys.argv[0]) 1325*6777b538SAndroid Build Coastguard Worker is_webview = 'webview' in calling_script_name 1326*6777b538SAndroid Build Coastguard Worker requires_32_bit = self.apk_helper.Get32BitAbiOverride() == '0xffffffff' 1327*6777b538SAndroid Build Coastguard Worker logging.debug('App supports (requires 32bit: %r, is webview: %r): %r', 1328*6777b538SAndroid Build Coastguard Worker requires_32_bit, is_webview, app_abis) 1329*6777b538SAndroid Build Coastguard Worker # Webview 32_64 targets can work even on 64-bit only devices since only the 1330*6777b538SAndroid Build Coastguard Worker # webview library in the target needs the correct bitness. 1331*6777b538SAndroid Build Coastguard Worker if requires_32_bit and not is_webview: 1332*6777b538SAndroid Build Coastguard Worker app_abis = [abi for abi in app_abis if '64' not in abi] 1333*6777b538SAndroid Build Coastguard Worker logging.debug('App supports (filtered): %r', app_abis) 1334*6777b538SAndroid Build Coastguard Worker if not app_abis: 1335*6777b538SAndroid Build Coastguard Worker # The app does not have any native libs, so all devices can support it. 1336*6777b538SAndroid Build Coastguard Worker return devices, None 1337*6777b538SAndroid Build Coastguard Worker fully_supported = [] 1338*6777b538SAndroid Build Coastguard Worker not_supported_reasons = {} 1339*6777b538SAndroid Build Coastguard Worker for device in devices: 1340*6777b538SAndroid Build Coastguard Worker device_abis = device.GetSupportedABIs() 1341*6777b538SAndroid Build Coastguard Worker device_primary_abi = device_abis[0] 1342*6777b538SAndroid Build Coastguard Worker logging.debug('Device primary: %s', device_primary_abi) 1343*6777b538SAndroid Build Coastguard Worker logging.debug('Device supports: %r', device_abis) 1344*6777b538SAndroid Build Coastguard Worker 1345*6777b538SAndroid Build Coastguard Worker # x86/x86_64 emulators sometimes advertises arm support but arm builds do 1346*6777b538SAndroid Build Coastguard Worker # not work on them. Thus these non-functional ABIs need to be filtered out 1347*6777b538SAndroid Build Coastguard Worker # here to avoid resulting in hard to understand runtime failures. 1348*6777b538SAndroid Build Coastguard Worker if device_primary_abi in ('x86', 'x86_64'): 1349*6777b538SAndroid Build Coastguard Worker device_abis = [abi for abi in device_abis if not abi.startswith('arm')] 1350*6777b538SAndroid Build Coastguard Worker logging.debug('Device supports (filtered): %r', device_abis) 1351*6777b538SAndroid Build Coastguard Worker 1352*6777b538SAndroid Build Coastguard Worker if any(abi in app_abis for abi in device_abis): 1353*6777b538SAndroid Build Coastguard Worker fully_supported.append(device) 1354*6777b538SAndroid Build Coastguard Worker else: # No common supported ABIs between the device and app. 1355*6777b538SAndroid Build Coastguard Worker if device_primary_abi == 'x86': 1356*6777b538SAndroid Build Coastguard Worker target_cpu = 'x86' 1357*6777b538SAndroid Build Coastguard Worker elif device_primary_abi == 'x86_64': 1358*6777b538SAndroid Build Coastguard Worker target_cpu = 'x64' 1359*6777b538SAndroid Build Coastguard Worker elif device_primary_abi.startswith('arm64'): 1360*6777b538SAndroid Build Coastguard Worker target_cpu = 'arm64' 1361*6777b538SAndroid Build Coastguard Worker elif device_primary_abi.startswith('armeabi'): 1362*6777b538SAndroid Build Coastguard Worker target_cpu = 'arm' 1363*6777b538SAndroid Build Coastguard Worker else: 1364*6777b538SAndroid Build Coastguard Worker target_cpu = '<something else>' 1365*6777b538SAndroid Build Coastguard Worker # pylint: disable=line-too-long 1366*6777b538SAndroid Build Coastguard Worker native_lib_link = 'https://chromium.googlesource.com/chromium/src/+/main/docs/android_native_libraries.md' 1367*6777b538SAndroid Build Coastguard Worker not_supported_reasons[device.serial] = ( 1368*6777b538SAndroid Build Coastguard Worker f"none of the app's ABIs ({','.join(app_abis)}) match this " 1369*6777b538SAndroid Build Coastguard Worker f"device's ABIs ({','.join(device_abis)}), you may need to set " 1370*6777b538SAndroid Build Coastguard Worker f'target_cpu="{target_cpu}" in your args.gn. If you already set ' 1371*6777b538SAndroid Build Coastguard Worker 'the target_cpu arg, you may need to use one of the _64 or _64_32 ' 1372*6777b538SAndroid Build Coastguard Worker f'targets, see {native_lib_link} for more details.') 1373*6777b538SAndroid Build Coastguard Worker return fully_supported, not_supported_reasons 1374*6777b538SAndroid Build Coastguard Worker 1375*6777b538SAndroid Build Coastguard Worker def ProcessArgs(self, args): 1376*6777b538SAndroid Build Coastguard Worker self.args = args 1377*6777b538SAndroid Build Coastguard Worker # Ensure these keys always exist. They are set by wrapper scripts, but not 1378*6777b538SAndroid Build Coastguard Worker # always added when not using wrapper scripts. 1379*6777b538SAndroid Build Coastguard Worker args.__dict__.setdefault('apk_path', None) 1380*6777b538SAndroid Build Coastguard Worker args.__dict__.setdefault('incremental_json', None) 1381*6777b538SAndroid Build Coastguard Worker 1382*6777b538SAndroid Build Coastguard Worker incremental_apk_path = None 1383*6777b538SAndroid Build Coastguard Worker install_dict = None 1384*6777b538SAndroid Build Coastguard Worker if args.incremental_json and not (self.supports_incremental and 1385*6777b538SAndroid Build Coastguard Worker args.non_incremental): 1386*6777b538SAndroid Build Coastguard Worker with open(args.incremental_json) as f: 1387*6777b538SAndroid Build Coastguard Worker install_dict = json.load(f) 1388*6777b538SAndroid Build Coastguard Worker incremental_apk_path = os.path.join(args.output_directory, 1389*6777b538SAndroid Build Coastguard Worker install_dict['apk_path']) 1390*6777b538SAndroid Build Coastguard Worker if not os.path.exists(incremental_apk_path): 1391*6777b538SAndroid Build Coastguard Worker incremental_apk_path = None 1392*6777b538SAndroid Build Coastguard Worker 1393*6777b538SAndroid Build Coastguard Worker if self.supports_incremental: 1394*6777b538SAndroid Build Coastguard Worker if args.incremental and args.non_incremental: 1395*6777b538SAndroid Build Coastguard Worker self._parser.error('Must use only one of --incremental and ' 1396*6777b538SAndroid Build Coastguard Worker '--non-incremental') 1397*6777b538SAndroid Build Coastguard Worker elif args.non_incremental: 1398*6777b538SAndroid Build Coastguard Worker if not args.apk_path: 1399*6777b538SAndroid Build Coastguard Worker self._parser.error('Apk has not been built.') 1400*6777b538SAndroid Build Coastguard Worker elif args.incremental: 1401*6777b538SAndroid Build Coastguard Worker if not incremental_apk_path: 1402*6777b538SAndroid Build Coastguard Worker self._parser.error('Incremental apk has not been built.') 1403*6777b538SAndroid Build Coastguard Worker args.apk_path = None 1404*6777b538SAndroid Build Coastguard Worker 1405*6777b538SAndroid Build Coastguard Worker if args.apk_path and incremental_apk_path: 1406*6777b538SAndroid Build Coastguard Worker self._parser.error('Both incremental and non-incremental apks exist. ' 1407*6777b538SAndroid Build Coastguard Worker 'Select using --incremental or --non-incremental') 1408*6777b538SAndroid Build Coastguard Worker 1409*6777b538SAndroid Build Coastguard Worker 1410*6777b538SAndroid Build Coastguard Worker # Gate apk_helper creation with _CreateApkHelpers since for bundles it takes 1411*6777b538SAndroid Build Coastguard Worker # a while to unpack the apks file from the aab file, so avoid this slowdown 1412*6777b538SAndroid Build Coastguard Worker # for simple commands that don't need apk_helper. 1413*6777b538SAndroid Build Coastguard Worker if self.needs_apk_helper: 1414*6777b538SAndroid Build Coastguard Worker if not self._CreateApkHelpers(args, incremental_apk_path, install_dict): 1415*6777b538SAndroid Build Coastguard Worker self._parser.error('App is not built.') 1416*6777b538SAndroid Build Coastguard Worker 1417*6777b538SAndroid Build Coastguard Worker if self.needs_package_name and not args.package_name: 1418*6777b538SAndroid Build Coastguard Worker if self._CreateApkHelpers(args, incremental_apk_path, install_dict): 1419*6777b538SAndroid Build Coastguard Worker args.package_name = self.apk_helper.GetPackageName() 1420*6777b538SAndroid Build Coastguard Worker elif self._from_wrapper_script: 1421*6777b538SAndroid Build Coastguard Worker self._parser.error('App is not built.') 1422*6777b538SAndroid Build Coastguard Worker else: 1423*6777b538SAndroid Build Coastguard Worker self._parser.error('One of --package-name or --apk-path is required.') 1424*6777b538SAndroid Build Coastguard Worker 1425*6777b538SAndroid Build Coastguard Worker self.devices = [] 1426*6777b538SAndroid Build Coastguard Worker if self.need_device_args: 1427*6777b538SAndroid Build Coastguard Worker # Avoid filtering by ABIs with catapult since some x86 or x86_64 emulators 1428*6777b538SAndroid Build Coastguard Worker # can still work with the right target_cpu GN arg and the right targets. 1429*6777b538SAndroid Build Coastguard Worker # Doing this manually allows us to output more informative warnings to 1430*6777b538SAndroid Build Coastguard Worker # help devs towards the right course, see: https://crbug.com/1335139 1431*6777b538SAndroid Build Coastguard Worker available_devices = device_utils.DeviceUtils.HealthyDevices( 1432*6777b538SAndroid Build Coastguard Worker device_arg=args.devices, 1433*6777b538SAndroid Build Coastguard Worker enable_device_files_cache=bool(args.output_directory), 1434*6777b538SAndroid Build Coastguard Worker default_retries=0) 1435*6777b538SAndroid Build Coastguard Worker if not available_devices: 1436*6777b538SAndroid Build Coastguard Worker raise Exception('Cannot find any available devices.') 1437*6777b538SAndroid Build Coastguard Worker 1438*6777b538SAndroid Build Coastguard Worker if not self._CreateApkHelpers(args, incremental_apk_path, install_dict): 1439*6777b538SAndroid Build Coastguard Worker self.devices = available_devices 1440*6777b538SAndroid Build Coastguard Worker else: 1441*6777b538SAndroid Build Coastguard Worker fully_supported, not_supported_reasons = self._FindSupportedDevices( 1442*6777b538SAndroid Build Coastguard Worker available_devices) 1443*6777b538SAndroid Build Coastguard Worker if fully_supported: 1444*6777b538SAndroid Build Coastguard Worker self.devices = fully_supported 1445*6777b538SAndroid Build Coastguard Worker else: 1446*6777b538SAndroid Build Coastguard Worker reason_string = '\n'.join( 1447*6777b538SAndroid Build Coastguard Worker 'The device (serial={}) is not supported because {}'.format( 1448*6777b538SAndroid Build Coastguard Worker serial, reason) 1449*6777b538SAndroid Build Coastguard Worker for serial, reason in not_supported_reasons.items()) 1450*6777b538SAndroid Build Coastguard Worker raise Exception('Cannot find any supported devices for this app.\n\n' 1451*6777b538SAndroid Build Coastguard Worker f'{reason_string}') 1452*6777b538SAndroid Build Coastguard Worker 1453*6777b538SAndroid Build Coastguard Worker # TODO(agrieve): Device cache should not depend on output directory. 1454*6777b538SAndroid Build Coastguard Worker # Maybe put into /tmp? 1455*6777b538SAndroid Build Coastguard Worker _LoadDeviceCaches(self.devices, args.output_directory) 1456*6777b538SAndroid Build Coastguard Worker 1457*6777b538SAndroid Build Coastguard Worker try: 1458*6777b538SAndroid Build Coastguard Worker if len(self.devices) > 1: 1459*6777b538SAndroid Build Coastguard Worker if not self.supports_multiple_devices: 1460*6777b538SAndroid Build Coastguard Worker self._parser.error(device_errors.MultipleDevicesError(self.devices)) 1461*6777b538SAndroid Build Coastguard Worker if not args.all and not args.devices: 1462*6777b538SAndroid Build Coastguard Worker self._parser.error(_GenerateMissingAllFlagMessage(self.devices)) 1463*6777b538SAndroid Build Coastguard Worker # Save cache now if command will not get a chance to afterwards. 1464*6777b538SAndroid Build Coastguard Worker if self.calls_exec: 1465*6777b538SAndroid Build Coastguard Worker _SaveDeviceCaches(self.devices, args.output_directory) 1466*6777b538SAndroid Build Coastguard Worker except: 1467*6777b538SAndroid Build Coastguard Worker _SaveDeviceCaches(self.devices, args.output_directory) 1468*6777b538SAndroid Build Coastguard Worker raise 1469*6777b538SAndroid Build Coastguard Worker 1470*6777b538SAndroid Build Coastguard Worker 1471*6777b538SAndroid Build Coastguard Workerclass _DevicesCommand(_Command): 1472*6777b538SAndroid Build Coastguard Worker name = 'devices' 1473*6777b538SAndroid Build Coastguard Worker description = 'Describe attached devices.' 1474*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1475*6777b538SAndroid Build Coastguard Worker 1476*6777b538SAndroid Build Coastguard Worker def Run(self): 1477*6777b538SAndroid Build Coastguard Worker print(_GenerateAvailableDevicesMessage(self.devices)) 1478*6777b538SAndroid Build Coastguard Worker 1479*6777b538SAndroid Build Coastguard Worker 1480*6777b538SAndroid Build Coastguard Workerclass _PackageInfoCommand(_Command): 1481*6777b538SAndroid Build Coastguard Worker name = 'package-info' 1482*6777b538SAndroid Build Coastguard Worker description = 'Show various attributes of this app.' 1483*6777b538SAndroid Build Coastguard Worker need_device_args = False 1484*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1485*6777b538SAndroid Build Coastguard Worker needs_apk_helper = True 1486*6777b538SAndroid Build Coastguard Worker 1487*6777b538SAndroid Build Coastguard Worker def Run(self): 1488*6777b538SAndroid Build Coastguard Worker # Format all (even ints) as strings, to handle cases where APIs return None 1489*6777b538SAndroid Build Coastguard Worker print('Package name: "%s"' % self.args.package_name) 1490*6777b538SAndroid Build Coastguard Worker print('versionCode: %s' % self.apk_helper.GetVersionCode()) 1491*6777b538SAndroid Build Coastguard Worker print('versionName: "%s"' % self.apk_helper.GetVersionName()) 1492*6777b538SAndroid Build Coastguard Worker print('minSdkVersion: %s' % self.apk_helper.GetMinSdkVersion()) 1493*6777b538SAndroid Build Coastguard Worker print('targetSdkVersion: %s' % self.apk_helper.GetTargetSdkVersion()) 1494*6777b538SAndroid Build Coastguard Worker print('Supported ABIs: %r' % self.apk_helper.GetAbis()) 1495*6777b538SAndroid Build Coastguard Worker 1496*6777b538SAndroid Build Coastguard Worker 1497*6777b538SAndroid Build Coastguard Workerclass _InstallCommand(_Command): 1498*6777b538SAndroid Build Coastguard Worker name = 'install' 1499*6777b538SAndroid Build Coastguard Worker description = 'Installs the APK or bundle to one or more devices.' 1500*6777b538SAndroid Build Coastguard Worker needs_apk_helper = True 1501*6777b538SAndroid Build Coastguard Worker supports_incremental = True 1502*6777b538SAndroid Build Coastguard Worker default_modules = [] 1503*6777b538SAndroid Build Coastguard Worker 1504*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1505*6777b538SAndroid Build Coastguard Worker if self.is_bundle: 1506*6777b538SAndroid Build Coastguard Worker group.add_argument( 1507*6777b538SAndroid Build Coastguard Worker '-m', 1508*6777b538SAndroid Build Coastguard Worker '--module', 1509*6777b538SAndroid Build Coastguard Worker action='append', 1510*6777b538SAndroid Build Coastguard Worker default=self.default_modules, 1511*6777b538SAndroid Build Coastguard Worker help='Module to install. Can be specified multiple times.') 1512*6777b538SAndroid Build Coastguard Worker group.add_argument( 1513*6777b538SAndroid Build Coastguard Worker '-f', 1514*6777b538SAndroid Build Coastguard Worker '--fake', 1515*6777b538SAndroid Build Coastguard Worker action='append', 1516*6777b538SAndroid Build Coastguard Worker default=[], 1517*6777b538SAndroid Build Coastguard Worker help='Fake bundle module install. Can be specified multiple times. ' 1518*6777b538SAndroid Build Coastguard Worker 'Requires \'-m {0}\' to be given, and \'-f {0}\' is illegal.'.format( 1519*6777b538SAndroid Build Coastguard Worker BASE_MODULE)) 1520*6777b538SAndroid Build Coastguard Worker # Add even if |self.default_modules| is empty, for consistency. 1521*6777b538SAndroid Build Coastguard Worker group.add_argument('--no-module', 1522*6777b538SAndroid Build Coastguard Worker action='append', 1523*6777b538SAndroid Build Coastguard Worker choices=self.default_modules, 1524*6777b538SAndroid Build Coastguard Worker default=[], 1525*6777b538SAndroid Build Coastguard Worker help='Module to exclude from default install.') 1526*6777b538SAndroid Build Coastguard Worker 1527*6777b538SAndroid Build Coastguard Worker def Run(self): 1528*6777b538SAndroid Build Coastguard Worker if self.additional_apk_helpers: 1529*6777b538SAndroid Build Coastguard Worker for additional_apk_helper in self.additional_apk_helpers: 1530*6777b538SAndroid Build Coastguard Worker _InstallApk(self.devices, additional_apk_helper, None) 1531*6777b538SAndroid Build Coastguard Worker if self.is_bundle: 1532*6777b538SAndroid Build Coastguard Worker modules = list( 1533*6777b538SAndroid Build Coastguard Worker set(self.args.module) - set(self.args.no_module) - 1534*6777b538SAndroid Build Coastguard Worker set(self.args.fake)) 1535*6777b538SAndroid Build Coastguard Worker _InstallBundle(self.devices, self.apk_helper, modules, self.args.fake) 1536*6777b538SAndroid Build Coastguard Worker else: 1537*6777b538SAndroid Build Coastguard Worker _InstallApk(self.devices, self.apk_helper, self.install_dict) 1538*6777b538SAndroid Build Coastguard Worker 1539*6777b538SAndroid Build Coastguard Worker 1540*6777b538SAndroid Build Coastguard Workerclass _UninstallCommand(_Command): 1541*6777b538SAndroid Build Coastguard Worker name = 'uninstall' 1542*6777b538SAndroid Build Coastguard Worker description = 'Removes the APK or bundle from one or more devices.' 1543*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1544*6777b538SAndroid Build Coastguard Worker 1545*6777b538SAndroid Build Coastguard Worker def Run(self): 1546*6777b538SAndroid Build Coastguard Worker _UninstallApk(self.devices, self.install_dict, self.args.package_name) 1547*6777b538SAndroid Build Coastguard Worker 1548*6777b538SAndroid Build Coastguard Worker 1549*6777b538SAndroid Build Coastguard Workerclass _SetWebViewProviderCommand(_Command): 1550*6777b538SAndroid Build Coastguard Worker name = 'set-webview-provider' 1551*6777b538SAndroid Build Coastguard Worker description = ("Sets the device's WebView provider to this APK's " 1552*6777b538SAndroid Build Coastguard Worker "package name.") 1553*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1554*6777b538SAndroid Build Coastguard Worker needs_apk_helper = True 1555*6777b538SAndroid Build Coastguard Worker 1556*6777b538SAndroid Build Coastguard Worker def Run(self): 1557*6777b538SAndroid Build Coastguard Worker if not _IsWebViewProvider(self.apk_helper): 1558*6777b538SAndroid Build Coastguard Worker raise Exception('This package does not have a WebViewLibrary meta-data ' 1559*6777b538SAndroid Build Coastguard Worker 'tag. Are you sure it contains a WebView implementation?') 1560*6777b538SAndroid Build Coastguard Worker _SetWebViewProvider(self.devices, self.args.package_name) 1561*6777b538SAndroid Build Coastguard Worker 1562*6777b538SAndroid Build Coastguard Worker 1563*6777b538SAndroid Build Coastguard Workerclass _LaunchCommand(_Command): 1564*6777b538SAndroid Build Coastguard Worker name = 'launch' 1565*6777b538SAndroid Build Coastguard Worker description = ('Sends a launch intent for the APK or bundle after first ' 1566*6777b538SAndroid Build Coastguard Worker 'writing the command-line flags file.') 1567*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1568*6777b538SAndroid Build Coastguard Worker accepts_command_line_flags = True 1569*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1570*6777b538SAndroid Build Coastguard Worker 1571*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1572*6777b538SAndroid Build Coastguard Worker group.add_argument('-w', '--wait-for-java-debugger', action='store_true', 1573*6777b538SAndroid Build Coastguard Worker help='Pause execution until debugger attaches. Applies ' 1574*6777b538SAndroid Build Coastguard Worker 'only to the main process. To have renderers wait, ' 1575*6777b538SAndroid Build Coastguard Worker 'use --args="--renderer-wait-for-java-debugger"') 1576*6777b538SAndroid Build Coastguard Worker group.add_argument('--debug-process-name', 1577*6777b538SAndroid Build Coastguard Worker help='Name of the process to debug. ' 1578*6777b538SAndroid Build Coastguard Worker 'E.g. "privileged_process0", or "foo.bar:baz"') 1579*6777b538SAndroid Build Coastguard Worker group.add_argument('--nokill', action='store_true', 1580*6777b538SAndroid Build Coastguard Worker help='Do not set the debug-app, nor set command-line ' 1581*6777b538SAndroid Build Coastguard Worker 'flags. Useful to load a URL without having the ' 1582*6777b538SAndroid Build Coastguard Worker 'app restart.') 1583*6777b538SAndroid Build Coastguard Worker group.add_argument('url', nargs='?', help='A URL to launch with.') 1584*6777b538SAndroid Build Coastguard Worker 1585*6777b538SAndroid Build Coastguard Worker def Run(self): 1586*6777b538SAndroid Build Coastguard Worker if self.is_test_apk: 1587*6777b538SAndroid Build Coastguard Worker raise Exception('Use the bin/run_* scripts to run test apks.') 1588*6777b538SAndroid Build Coastguard Worker _LaunchUrl(self.devices, 1589*6777b538SAndroid Build Coastguard Worker self.args.package_name, 1590*6777b538SAndroid Build Coastguard Worker argv=self.args.args, 1591*6777b538SAndroid Build Coastguard Worker command_line_flags_file=self.args.command_line_flags_file, 1592*6777b538SAndroid Build Coastguard Worker url=self.args.url, 1593*6777b538SAndroid Build Coastguard Worker wait_for_java_debugger=self.args.wait_for_java_debugger, 1594*6777b538SAndroid Build Coastguard Worker debug_process_name=self.args.debug_process_name, 1595*6777b538SAndroid Build Coastguard Worker nokill=self.args.nokill) 1596*6777b538SAndroid Build Coastguard Worker 1597*6777b538SAndroid Build Coastguard Worker 1598*6777b538SAndroid Build Coastguard Workerclass _StopCommand(_Command): 1599*6777b538SAndroid Build Coastguard Worker name = 'stop' 1600*6777b538SAndroid Build Coastguard Worker description = 'Force-stops the app.' 1601*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1602*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1603*6777b538SAndroid Build Coastguard Worker 1604*6777b538SAndroid Build Coastguard Worker def Run(self): 1605*6777b538SAndroid Build Coastguard Worker device_utils.DeviceUtils.parallel(self.devices).ForceStop( 1606*6777b538SAndroid Build Coastguard Worker self.args.package_name) 1607*6777b538SAndroid Build Coastguard Worker 1608*6777b538SAndroid Build Coastguard Worker 1609*6777b538SAndroid Build Coastguard Workerclass _ClearDataCommand(_Command): 1610*6777b538SAndroid Build Coastguard Worker name = 'clear-data' 1611*6777b538SAndroid Build Coastguard Worker descriptions = 'Clears all app data.' 1612*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1613*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1614*6777b538SAndroid Build Coastguard Worker 1615*6777b538SAndroid Build Coastguard Worker def Run(self): 1616*6777b538SAndroid Build Coastguard Worker device_utils.DeviceUtils.parallel(self.devices).ClearApplicationState( 1617*6777b538SAndroid Build Coastguard Worker self.args.package_name) 1618*6777b538SAndroid Build Coastguard Worker 1619*6777b538SAndroid Build Coastguard Worker 1620*6777b538SAndroid Build Coastguard Workerclass _ArgvCommand(_Command): 1621*6777b538SAndroid Build Coastguard Worker name = 'argv' 1622*6777b538SAndroid Build Coastguard Worker description = 'Display and optionally update command-line flags file.' 1623*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1624*6777b538SAndroid Build Coastguard Worker accepts_command_line_flags = True 1625*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1626*6777b538SAndroid Build Coastguard Worker 1627*6777b538SAndroid Build Coastguard Worker def Run(self): 1628*6777b538SAndroid Build Coastguard Worker _ChangeFlags(self.devices, self.args.args, 1629*6777b538SAndroid Build Coastguard Worker self.args.command_line_flags_file) 1630*6777b538SAndroid Build Coastguard Worker 1631*6777b538SAndroid Build Coastguard Worker 1632*6777b538SAndroid Build Coastguard Workerclass _GdbCommand(_Command): 1633*6777b538SAndroid Build Coastguard Worker name = 'gdb' 1634*6777b538SAndroid Build Coastguard Worker description = 'Runs //build/android/adb_gdb with apk-specific args.' 1635*6777b538SAndroid Build Coastguard Worker long_description = description + """ 1636*6777b538SAndroid Build Coastguard Worker 1637*6777b538SAndroid Build Coastguard WorkerTo attach to a process other than the APK's main process, use --pid=1234. 1638*6777b538SAndroid Build Coastguard WorkerTo list all PIDs, use the "ps" command. 1639*6777b538SAndroid Build Coastguard Worker 1640*6777b538SAndroid Build Coastguard WorkerIf no apk process is currently running, sends a launch intent. 1641*6777b538SAndroid Build Coastguard Worker""" 1642*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1643*6777b538SAndroid Build Coastguard Worker needs_output_directory = True 1644*6777b538SAndroid Build Coastguard Worker calls_exec = True 1645*6777b538SAndroid Build Coastguard Worker supports_multiple_devices = False 1646*6777b538SAndroid Build Coastguard Worker 1647*6777b538SAndroid Build Coastguard Worker def Run(self): 1648*6777b538SAndroid Build Coastguard Worker _RunGdb(self.devices[0], self.args.package_name, 1649*6777b538SAndroid Build Coastguard Worker self.args.debug_process_name, self.args.pid, 1650*6777b538SAndroid Build Coastguard Worker self.args.output_directory, self.args.target_cpu, self.args.port, 1651*6777b538SAndroid Build Coastguard Worker self.args.ide, bool(self.args.verbose_count)) 1652*6777b538SAndroid Build Coastguard Worker 1653*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1654*6777b538SAndroid Build Coastguard Worker pid_group = group.add_mutually_exclusive_group() 1655*6777b538SAndroid Build Coastguard Worker pid_group.add_argument('--debug-process-name', 1656*6777b538SAndroid Build Coastguard Worker help='Name of the process to attach to. ' 1657*6777b538SAndroid Build Coastguard Worker 'E.g. "privileged_process0", or "foo.bar:baz"') 1658*6777b538SAndroid Build Coastguard Worker pid_group.add_argument('--pid', 1659*6777b538SAndroid Build Coastguard Worker help='The process ID to attach to. Defaults to ' 1660*6777b538SAndroid Build Coastguard Worker 'the main process for the package.') 1661*6777b538SAndroid Build Coastguard Worker group.add_argument('--ide', action='store_true', 1662*6777b538SAndroid Build Coastguard Worker help='Rather than enter a gdb prompt, set up the ' 1663*6777b538SAndroid Build Coastguard Worker 'gdb connection and wait for an IDE to ' 1664*6777b538SAndroid Build Coastguard Worker 'connect.') 1665*6777b538SAndroid Build Coastguard Worker # Same default port that ndk-gdb.py uses. 1666*6777b538SAndroid Build Coastguard Worker group.add_argument('--port', type=int, default=5039, 1667*6777b538SAndroid Build Coastguard Worker help='Use the given port for the GDB connection') 1668*6777b538SAndroid Build Coastguard Worker 1669*6777b538SAndroid Build Coastguard Worker 1670*6777b538SAndroid Build Coastguard Workerclass _LldbCommand(_Command): 1671*6777b538SAndroid Build Coastguard Worker name = 'lldb' 1672*6777b538SAndroid Build Coastguard Worker description = 'Runs //build/android/connect_lldb.sh with apk-specific args.' 1673*6777b538SAndroid Build Coastguard Worker long_description = description + """ 1674*6777b538SAndroid Build Coastguard Worker 1675*6777b538SAndroid Build Coastguard WorkerTo attach to a process other than the APK's main process, use --pid=1234. 1676*6777b538SAndroid Build Coastguard WorkerTo list all PIDs, use the "ps" command. 1677*6777b538SAndroid Build Coastguard Worker 1678*6777b538SAndroid Build Coastguard WorkerIf no apk process is currently running, sends a launch intent. 1679*6777b538SAndroid Build Coastguard Worker""" 1680*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1681*6777b538SAndroid Build Coastguard Worker needs_output_directory = True 1682*6777b538SAndroid Build Coastguard Worker calls_exec = True 1683*6777b538SAndroid Build Coastguard Worker supports_multiple_devices = False 1684*6777b538SAndroid Build Coastguard Worker 1685*6777b538SAndroid Build Coastguard Worker def Run(self): 1686*6777b538SAndroid Build Coastguard Worker _RunLldb(device=self.devices[0], 1687*6777b538SAndroid Build Coastguard Worker package_name=self.args.package_name, 1688*6777b538SAndroid Build Coastguard Worker debug_process_name=self.args.debug_process_name, 1689*6777b538SAndroid Build Coastguard Worker pid=self.args.pid, 1690*6777b538SAndroid Build Coastguard Worker output_directory=self.args.output_directory, 1691*6777b538SAndroid Build Coastguard Worker port=self.args.port, 1692*6777b538SAndroid Build Coastguard Worker target_cpu=self.args.target_cpu, 1693*6777b538SAndroid Build Coastguard Worker ndk_dir=self.args.ndk_dir, 1694*6777b538SAndroid Build Coastguard Worker lldb_server=self.args.lldb_server, 1695*6777b538SAndroid Build Coastguard Worker lldb=self.args.lldb, 1696*6777b538SAndroid Build Coastguard Worker verbose=bool(self.args.verbose_count)) 1697*6777b538SAndroid Build Coastguard Worker 1698*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1699*6777b538SAndroid Build Coastguard Worker pid_group = group.add_mutually_exclusive_group() 1700*6777b538SAndroid Build Coastguard Worker pid_group.add_argument('--debug-process-name', 1701*6777b538SAndroid Build Coastguard Worker help='Name of the process to attach to. ' 1702*6777b538SAndroid Build Coastguard Worker 'E.g. "privileged_process0", or "foo.bar:baz"') 1703*6777b538SAndroid Build Coastguard Worker pid_group.add_argument('--pid', 1704*6777b538SAndroid Build Coastguard Worker help='The process ID to attach to. Defaults to ' 1705*6777b538SAndroid Build Coastguard Worker 'the main process for the package.') 1706*6777b538SAndroid Build Coastguard Worker group.add_argument('--ndk-dir', 1707*6777b538SAndroid Build Coastguard Worker help='Select alternative NDK root directory.') 1708*6777b538SAndroid Build Coastguard Worker group.add_argument('--lldb-server', 1709*6777b538SAndroid Build Coastguard Worker help='Select alternative on-device lldb-server.') 1710*6777b538SAndroid Build Coastguard Worker group.add_argument('--lldb', help='Select alternative client lldb.sh.') 1711*6777b538SAndroid Build Coastguard Worker # Same default port that ndk-gdb.py uses. 1712*6777b538SAndroid Build Coastguard Worker group.add_argument('--port', 1713*6777b538SAndroid Build Coastguard Worker type=int, 1714*6777b538SAndroid Build Coastguard Worker default=5039, 1715*6777b538SAndroid Build Coastguard Worker help='Use the given port for the LLDB connection') 1716*6777b538SAndroid Build Coastguard Worker 1717*6777b538SAndroid Build Coastguard Worker 1718*6777b538SAndroid Build Coastguard Workerclass _LogcatCommand(_Command): 1719*6777b538SAndroid Build Coastguard Worker name = 'logcat' 1720*6777b538SAndroid Build Coastguard Worker description = 'Runs "adb logcat" with filters relevant the current APK.' 1721*6777b538SAndroid Build Coastguard Worker long_description = description + """ 1722*6777b538SAndroid Build Coastguard Worker 1723*6777b538SAndroid Build Coastguard Worker"Relevant filters" means: 1724*6777b538SAndroid Build Coastguard Worker * Log messages from processes belonging to the apk, 1725*6777b538SAndroid Build Coastguard Worker * Plus log messages from log tags: ActivityManager|DEBUG, 1726*6777b538SAndroid Build Coastguard Worker * Plus fatal logs from any process, 1727*6777b538SAndroid Build Coastguard Worker * Minus spamy dalvikvm logs (for pre-L devices). 1728*6777b538SAndroid Build Coastguard Worker 1729*6777b538SAndroid Build Coastguard WorkerColors: 1730*6777b538SAndroid Build Coastguard Worker * Primary process is white 1731*6777b538SAndroid Build Coastguard Worker * Other processes (gpu, renderer) are yellow 1732*6777b538SAndroid Build Coastguard Worker * Non-apk processes are grey 1733*6777b538SAndroid Build Coastguard Worker * UI thread has a bolded Thread-ID 1734*6777b538SAndroid Build Coastguard Worker 1735*6777b538SAndroid Build Coastguard WorkerJava stack traces are detected and deobfuscated (for release builds). 1736*6777b538SAndroid Build Coastguard Worker 1737*6777b538SAndroid Build Coastguard WorkerTo disable filtering, (but keep coloring), use --verbose. 1738*6777b538SAndroid Build Coastguard Worker""" 1739*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1740*6777b538SAndroid Build Coastguard Worker supports_multiple_devices = False 1741*6777b538SAndroid Build Coastguard Worker 1742*6777b538SAndroid Build Coastguard Worker def Run(self): 1743*6777b538SAndroid Build Coastguard Worker deobfuscate = None 1744*6777b538SAndroid Build Coastguard Worker if self.args.proguard_mapping_path and not self.args.no_deobfuscate: 1745*6777b538SAndroid Build Coastguard Worker deobfuscate = deobfuscator.Deobfuscator(self.args.proguard_mapping_path) 1746*6777b538SAndroid Build Coastguard Worker 1747*6777b538SAndroid Build Coastguard Worker if self.args.apk_path or self.bundle_generation_info: 1748*6777b538SAndroid Build Coastguard Worker stack_script_context = _StackScriptContext(self.args.output_directory, 1749*6777b538SAndroid Build Coastguard Worker self.args.apk_path, 1750*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info, 1751*6777b538SAndroid Build Coastguard Worker quiet=True) 1752*6777b538SAndroid Build Coastguard Worker else: 1753*6777b538SAndroid Build Coastguard Worker stack_script_context = None 1754*6777b538SAndroid Build Coastguard Worker 1755*6777b538SAndroid Build Coastguard Worker extra_package_names = [] 1756*6777b538SAndroid Build Coastguard Worker if self.is_test_apk and self.additional_apk_helpers: 1757*6777b538SAndroid Build Coastguard Worker for additional_apk_helper in self.additional_apk_helpers: 1758*6777b538SAndroid Build Coastguard Worker extra_package_names.append(additional_apk_helper.GetPackageName()) 1759*6777b538SAndroid Build Coastguard Worker 1760*6777b538SAndroid Build Coastguard Worker try: 1761*6777b538SAndroid Build Coastguard Worker _RunLogcat(self.devices[0], 1762*6777b538SAndroid Build Coastguard Worker self.args.package_name, 1763*6777b538SAndroid Build Coastguard Worker stack_script_context, 1764*6777b538SAndroid Build Coastguard Worker deobfuscate, 1765*6777b538SAndroid Build Coastguard Worker bool(self.args.verbose_count), 1766*6777b538SAndroid Build Coastguard Worker self.args.exit_on_match, 1767*6777b538SAndroid Build Coastguard Worker extra_package_names=extra_package_names) 1768*6777b538SAndroid Build Coastguard Worker except KeyboardInterrupt: 1769*6777b538SAndroid Build Coastguard Worker pass # Don't show stack trace upon Ctrl-C 1770*6777b538SAndroid Build Coastguard Worker finally: 1771*6777b538SAndroid Build Coastguard Worker if stack_script_context: 1772*6777b538SAndroid Build Coastguard Worker stack_script_context.Close() 1773*6777b538SAndroid Build Coastguard Worker if deobfuscate: 1774*6777b538SAndroid Build Coastguard Worker deobfuscate.Close() 1775*6777b538SAndroid Build Coastguard Worker 1776*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1777*6777b538SAndroid Build Coastguard Worker if self._from_wrapper_script: 1778*6777b538SAndroid Build Coastguard Worker group.add_argument('--no-deobfuscate', action='store_true', 1779*6777b538SAndroid Build Coastguard Worker help='Disables ProGuard deobfuscation of logcat.') 1780*6777b538SAndroid Build Coastguard Worker else: 1781*6777b538SAndroid Build Coastguard Worker group.set_defaults(no_deobfuscate=False) 1782*6777b538SAndroid Build Coastguard Worker group.add_argument('--proguard-mapping-path', 1783*6777b538SAndroid Build Coastguard Worker help='Path to ProGuard map (enables deobfuscation)') 1784*6777b538SAndroid Build Coastguard Worker group.add_argument('--exit-on-match', 1785*6777b538SAndroid Build Coastguard Worker help='Exits logcat when a message matches this regex.') 1786*6777b538SAndroid Build Coastguard Worker 1787*6777b538SAndroid Build Coastguard Worker 1788*6777b538SAndroid Build Coastguard Workerclass _PsCommand(_Command): 1789*6777b538SAndroid Build Coastguard Worker name = 'ps' 1790*6777b538SAndroid Build Coastguard Worker description = 'Show PIDs of any APK processes currently running.' 1791*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1792*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1793*6777b538SAndroid Build Coastguard Worker 1794*6777b538SAndroid Build Coastguard Worker def Run(self): 1795*6777b538SAndroid Build Coastguard Worker _RunPs(self.devices, self.args.package_name) 1796*6777b538SAndroid Build Coastguard Worker 1797*6777b538SAndroid Build Coastguard Worker 1798*6777b538SAndroid Build Coastguard Workerclass _DiskUsageCommand(_Command): 1799*6777b538SAndroid Build Coastguard Worker name = 'disk-usage' 1800*6777b538SAndroid Build Coastguard Worker description = 'Show how much device storage is being consumed by the app.' 1801*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1802*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1803*6777b538SAndroid Build Coastguard Worker 1804*6777b538SAndroid Build Coastguard Worker def Run(self): 1805*6777b538SAndroid Build Coastguard Worker _RunDiskUsage(self.devices, self.args.package_name) 1806*6777b538SAndroid Build Coastguard Worker 1807*6777b538SAndroid Build Coastguard Worker 1808*6777b538SAndroid Build Coastguard Workerclass _MemUsageCommand(_Command): 1809*6777b538SAndroid Build Coastguard Worker name = 'mem-usage' 1810*6777b538SAndroid Build Coastguard Worker description = 'Show memory usage of currently running APK processes.' 1811*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1812*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1813*6777b538SAndroid Build Coastguard Worker 1814*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1815*6777b538SAndroid Build Coastguard Worker group.add_argument('--query-app', action='store_true', 1816*6777b538SAndroid Build Coastguard Worker help='Do not add --local to "dumpsys meminfo". This will output ' 1817*6777b538SAndroid Build Coastguard Worker 'additional metrics (e.g. Context count), but also cause memory ' 1818*6777b538SAndroid Build Coastguard Worker 'to be used in order to gather the metrics.') 1819*6777b538SAndroid Build Coastguard Worker 1820*6777b538SAndroid Build Coastguard Worker def Run(self): 1821*6777b538SAndroid Build Coastguard Worker _RunMemUsage(self.devices, self.args.package_name, 1822*6777b538SAndroid Build Coastguard Worker query_app=self.args.query_app) 1823*6777b538SAndroid Build Coastguard Worker 1824*6777b538SAndroid Build Coastguard Worker 1825*6777b538SAndroid Build Coastguard Workerclass _ShellCommand(_Command): 1826*6777b538SAndroid Build Coastguard Worker name = 'shell' 1827*6777b538SAndroid Build Coastguard Worker description = ('Same as "adb shell <command>", but runs as the apk\'s uid ' 1828*6777b538SAndroid Build Coastguard Worker '(via run-as). Useful for inspecting the app\'s data ' 1829*6777b538SAndroid Build Coastguard Worker 'directory.') 1830*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1831*6777b538SAndroid Build Coastguard Worker 1832*6777b538SAndroid Build Coastguard Worker @property 1833*6777b538SAndroid Build Coastguard Worker def calls_exec(self): 1834*6777b538SAndroid Build Coastguard Worker return not self.args.cmd 1835*6777b538SAndroid Build Coastguard Worker 1836*6777b538SAndroid Build Coastguard Worker @property 1837*6777b538SAndroid Build Coastguard Worker def supports_multiple_devices(self): 1838*6777b538SAndroid Build Coastguard Worker return not self.args.cmd 1839*6777b538SAndroid Build Coastguard Worker 1840*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1841*6777b538SAndroid Build Coastguard Worker group.add_argument( 1842*6777b538SAndroid Build Coastguard Worker 'cmd', nargs=argparse.REMAINDER, help='Command to run.') 1843*6777b538SAndroid Build Coastguard Worker 1844*6777b538SAndroid Build Coastguard Worker def Run(self): 1845*6777b538SAndroid Build Coastguard Worker _RunShell(self.devices, self.args.package_name, self.args.cmd) 1846*6777b538SAndroid Build Coastguard Worker 1847*6777b538SAndroid Build Coastguard Worker 1848*6777b538SAndroid Build Coastguard Workerclass _CompileDexCommand(_Command): 1849*6777b538SAndroid Build Coastguard Worker name = 'compile-dex' 1850*6777b538SAndroid Build Coastguard Worker description = ('Applicable only for Android N+. Forces .odex files to be ' 1851*6777b538SAndroid Build Coastguard Worker 'compiled with the given compilation filter. To see existing ' 1852*6777b538SAndroid Build Coastguard Worker 'filter, use "disk-usage" command.') 1853*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1854*6777b538SAndroid Build Coastguard Worker all_devices_by_default = True 1855*6777b538SAndroid Build Coastguard Worker 1856*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1857*6777b538SAndroid Build Coastguard Worker group.add_argument( 1858*6777b538SAndroid Build Coastguard Worker 'compilation_filter', 1859*6777b538SAndroid Build Coastguard Worker choices=['verify', 'quicken', 'space-profile', 'space', 1860*6777b538SAndroid Build Coastguard Worker 'speed-profile', 'speed'], 1861*6777b538SAndroid Build Coastguard Worker help='For WebView/Monochrome, use "speed". For other apks, use ' 1862*6777b538SAndroid Build Coastguard Worker '"speed-profile".') 1863*6777b538SAndroid Build Coastguard Worker 1864*6777b538SAndroid Build Coastguard Worker def Run(self): 1865*6777b538SAndroid Build Coastguard Worker _RunCompileDex(self.devices, self.args.package_name, 1866*6777b538SAndroid Build Coastguard Worker self.args.compilation_filter) 1867*6777b538SAndroid Build Coastguard Worker 1868*6777b538SAndroid Build Coastguard Worker 1869*6777b538SAndroid Build Coastguard Workerclass _PrintCertsCommand(_Command): 1870*6777b538SAndroid Build Coastguard Worker name = 'print-certs' 1871*6777b538SAndroid Build Coastguard Worker description = 'Print info about certificates used to sign this APK.' 1872*6777b538SAndroid Build Coastguard Worker need_device_args = False 1873*6777b538SAndroid Build Coastguard Worker needs_apk_helper = True 1874*6777b538SAndroid Build Coastguard Worker 1875*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1876*6777b538SAndroid Build Coastguard Worker group.add_argument( 1877*6777b538SAndroid Build Coastguard Worker '--full-cert', 1878*6777b538SAndroid Build Coastguard Worker action='store_true', 1879*6777b538SAndroid Build Coastguard Worker help=("Print the certificate's full signature, Base64-encoded. " 1880*6777b538SAndroid Build Coastguard Worker "Useful when configuring an Android image's " 1881*6777b538SAndroid Build Coastguard Worker "config_webview_packages.xml.")) 1882*6777b538SAndroid Build Coastguard Worker 1883*6777b538SAndroid Build Coastguard Worker def Run(self): 1884*6777b538SAndroid Build Coastguard Worker keytool = os.path.join(_JAVA_HOME, 'bin', 'keytool') 1885*6777b538SAndroid Build Coastguard Worker pem_certificate_pattern = re.compile( 1886*6777b538SAndroid Build Coastguard Worker r'-+BEGIN CERTIFICATE-+([\r\n0-9A-Za-z+/=]+)-+END CERTIFICATE-+[\r\n]*') 1887*6777b538SAndroid Build Coastguard Worker if self.is_bundle: 1888*6777b538SAndroid Build Coastguard Worker # Bundles are not signed until converted to .apks. The wrapper scripts 1889*6777b538SAndroid Build Coastguard Worker # record which key will be used to sign though. 1890*6777b538SAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile() as f: 1891*6777b538SAndroid Build Coastguard Worker logging.warning('Bundles are not signed until turned into .apk files.') 1892*6777b538SAndroid Build Coastguard Worker logging.warning('Showing signing info based on associated keystore.') 1893*6777b538SAndroid Build Coastguard Worker cmd = [ 1894*6777b538SAndroid Build Coastguard Worker keytool, '-exportcert', '-keystore', 1895*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info.keystore_path, '-storepass', 1896*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info.keystore_password, '-alias', 1897*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info.keystore_alias, '-file', f.name 1898*6777b538SAndroid Build Coastguard Worker ] 1899*6777b538SAndroid Build Coastguard Worker logging.warning('Running: %s', shlex.join(cmd)) 1900*6777b538SAndroid Build Coastguard Worker subprocess.check_output(cmd, stderr=subprocess.STDOUT) 1901*6777b538SAndroid Build Coastguard Worker cmd = [keytool, '-printcert', '-file', f.name] 1902*6777b538SAndroid Build Coastguard Worker logging.warning('Running: %s', shlex.join(cmd)) 1903*6777b538SAndroid Build Coastguard Worker subprocess.check_call(cmd) 1904*6777b538SAndroid Build Coastguard Worker if self.args.full_cert: 1905*6777b538SAndroid Build Coastguard Worker # Redirect stderr to hide a keytool warning about using non-standard 1906*6777b538SAndroid Build Coastguard Worker # keystore format. 1907*6777b538SAndroid Build Coastguard Worker cmd += ['-rfc'] 1908*6777b538SAndroid Build Coastguard Worker logging.warning('Running: %s', shlex.join(cmd)) 1909*6777b538SAndroid Build Coastguard Worker pem_encoded_certificate = subprocess.check_output( 1910*6777b538SAndroid Build Coastguard Worker cmd, stderr=subprocess.STDOUT).decode() 1911*6777b538SAndroid Build Coastguard Worker else: 1912*6777b538SAndroid Build Coastguard Worker 1913*6777b538SAndroid Build Coastguard Worker def run_apksigner(min_sdk_version): 1914*6777b538SAndroid Build Coastguard Worker cmd = [ 1915*6777b538SAndroid Build Coastguard Worker build_tools.GetPath('apksigner'), 'verify', '--min-sdk-version', 1916*6777b538SAndroid Build Coastguard Worker str(min_sdk_version), '--print-certs-pem', '--verbose', 1917*6777b538SAndroid Build Coastguard Worker self.apk_helper.path 1918*6777b538SAndroid Build Coastguard Worker ] 1919*6777b538SAndroid Build Coastguard Worker logging.warning('Running: %s', shlex.join(cmd)) 1920*6777b538SAndroid Build Coastguard Worker env = os.environ.copy() 1921*6777b538SAndroid Build Coastguard Worker env['PATH'] = os.path.pathsep.join( 1922*6777b538SAndroid Build Coastguard Worker [os.path.join(_JAVA_HOME, 'bin'), 1923*6777b538SAndroid Build Coastguard Worker env.get('PATH')]) 1924*6777b538SAndroid Build Coastguard Worker # Redirect stderr to hide verification failures (see explanation below). 1925*6777b538SAndroid Build Coastguard Worker return subprocess.check_output(cmd, 1926*6777b538SAndroid Build Coastguard Worker env=env, 1927*6777b538SAndroid Build Coastguard Worker universal_newlines=True, 1928*6777b538SAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 1929*6777b538SAndroid Build Coastguard Worker 1930*6777b538SAndroid Build Coastguard Worker # apksigner's default behavior is nonintuitive: it will print "Verified 1931*6777b538SAndroid Build Coastguard Worker # using <scheme number>...: false" for any scheme which is obsolete for 1932*6777b538SAndroid Build Coastguard Worker # the APK's minSdkVersion even if it actually was signed with that scheme 1933*6777b538SAndroid Build Coastguard Worker # (ex. it prints "Verified using v1 scheme: false" for Monochrome because 1934*6777b538SAndroid Build Coastguard Worker # v1 was obsolete by N). To workaround this, we force apksigner to use the 1935*6777b538SAndroid Build Coastguard Worker # lowest possible minSdkVersion. We need to fallback to higher 1936*6777b538SAndroid Build Coastguard Worker # minSdkVersions in case the APK fails to verify for that minSdkVersion 1937*6777b538SAndroid Build Coastguard Worker # (which means the APK is genuinely not signed with that scheme). These 1938*6777b538SAndroid Build Coastguard Worker # SDK values are the highest SDK version before the next scheme is 1939*6777b538SAndroid Build Coastguard Worker # available: 1940*6777b538SAndroid Build Coastguard Worker versions = [ 1941*6777b538SAndroid Build Coastguard Worker version_codes.MARSHMALLOW, # before v2 launched in N 1942*6777b538SAndroid Build Coastguard Worker version_codes.OREO_MR1, # before v3 launched in P 1943*6777b538SAndroid Build Coastguard Worker version_codes.Q, # before v4 launched in R 1944*6777b538SAndroid Build Coastguard Worker version_codes.R, 1945*6777b538SAndroid Build Coastguard Worker ] 1946*6777b538SAndroid Build Coastguard Worker stdout = None 1947*6777b538SAndroid Build Coastguard Worker for min_sdk_version in versions: 1948*6777b538SAndroid Build Coastguard Worker try: 1949*6777b538SAndroid Build Coastguard Worker stdout = run_apksigner(min_sdk_version) 1950*6777b538SAndroid Build Coastguard Worker break 1951*6777b538SAndroid Build Coastguard Worker except subprocess.CalledProcessError: 1952*6777b538SAndroid Build Coastguard Worker # Doesn't verify with this min-sdk-version, so try again with a higher 1953*6777b538SAndroid Build Coastguard Worker # one 1954*6777b538SAndroid Build Coastguard Worker continue 1955*6777b538SAndroid Build Coastguard Worker if not stdout: 1956*6777b538SAndroid Build Coastguard Worker raise RuntimeError('apksigner was not able to verify APK') 1957*6777b538SAndroid Build Coastguard Worker 1958*6777b538SAndroid Build Coastguard Worker # Separate what the '--print-certs' flag would output vs. the additional 1959*6777b538SAndroid Build Coastguard Worker # signature output included by '--print-certs-pem'. The additional PEM 1960*6777b538SAndroid Build Coastguard Worker # output is only printed when self.args.full_cert is specified. 1961*6777b538SAndroid Build Coastguard Worker verification_hash_info = pem_certificate_pattern.sub('', stdout) 1962*6777b538SAndroid Build Coastguard Worker print(verification_hash_info) 1963*6777b538SAndroid Build Coastguard Worker if self.args.full_cert: 1964*6777b538SAndroid Build Coastguard Worker m = pem_certificate_pattern.search(stdout) 1965*6777b538SAndroid Build Coastguard Worker if not m: 1966*6777b538SAndroid Build Coastguard Worker raise Exception('apksigner did not print a certificate') 1967*6777b538SAndroid Build Coastguard Worker pem_encoded_certificate = m.group(0) 1968*6777b538SAndroid Build Coastguard Worker 1969*6777b538SAndroid Build Coastguard Worker 1970*6777b538SAndroid Build Coastguard Worker if self.args.full_cert: 1971*6777b538SAndroid Build Coastguard Worker m = pem_certificate_pattern.search(pem_encoded_certificate) 1972*6777b538SAndroid Build Coastguard Worker if not m: 1973*6777b538SAndroid Build Coastguard Worker raise Exception( 1974*6777b538SAndroid Build Coastguard Worker 'Unable to parse certificate:\n{}'.format(pem_encoded_certificate)) 1975*6777b538SAndroid Build Coastguard Worker signature = re.sub(r'[\r\n]+', '', m.group(1)) 1976*6777b538SAndroid Build Coastguard Worker print() 1977*6777b538SAndroid Build Coastguard Worker print('Full Signature:') 1978*6777b538SAndroid Build Coastguard Worker print(signature) 1979*6777b538SAndroid Build Coastguard Worker 1980*6777b538SAndroid Build Coastguard Worker 1981*6777b538SAndroid Build Coastguard Workerclass _ProfileCommand(_Command): 1982*6777b538SAndroid Build Coastguard Worker name = 'profile' 1983*6777b538SAndroid Build Coastguard Worker description = ('Run the simpleperf sampling CPU profiler on the currently-' 1984*6777b538SAndroid Build Coastguard Worker 'running APK. If --args is used, the extra arguments will be ' 1985*6777b538SAndroid Build Coastguard Worker 'passed on to simpleperf; otherwise, the following default ' 1986*6777b538SAndroid Build Coastguard Worker 'arguments are used: -g -f 1000 -o /data/local/tmp/perf.data') 1987*6777b538SAndroid Build Coastguard Worker needs_package_name = True 1988*6777b538SAndroid Build Coastguard Worker needs_output_directory = True 1989*6777b538SAndroid Build Coastguard Worker supports_multiple_devices = False 1990*6777b538SAndroid Build Coastguard Worker accepts_args = True 1991*6777b538SAndroid Build Coastguard Worker 1992*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 1993*6777b538SAndroid Build Coastguard Worker group.add_argument( 1994*6777b538SAndroid Build Coastguard Worker '--profile-process', default='browser', 1995*6777b538SAndroid Build Coastguard Worker help=('Which process to profile. This may be a process name or pid ' 1996*6777b538SAndroid Build Coastguard Worker 'such as you would get from running `%s ps`; or ' 1997*6777b538SAndroid Build Coastguard Worker 'it can be one of (browser, renderer, gpu).' % sys.argv[0])) 1998*6777b538SAndroid Build Coastguard Worker group.add_argument( 1999*6777b538SAndroid Build Coastguard Worker '--profile-thread', default=None, 2000*6777b538SAndroid Build Coastguard Worker help=('(Optional) Profile only a single thread. This may be either a ' 2001*6777b538SAndroid Build Coastguard Worker 'thread ID such as you would get by running `adb shell ps -t` ' 2002*6777b538SAndroid Build Coastguard Worker '(pre-Oreo) or `adb shell ps -e -T` (Oreo and later); or it may ' 2003*6777b538SAndroid Build Coastguard Worker 'be one of (io, compositor, main, render), in which case ' 2004*6777b538SAndroid Build Coastguard Worker '--profile-process is also required. (Note that "render" thread ' 2005*6777b538SAndroid Build Coastguard Worker 'refers to a thread in the browser process that manages a ' 2006*6777b538SAndroid Build Coastguard Worker 'renderer; to profile the main thread of the renderer process, ' 2007*6777b538SAndroid Build Coastguard Worker 'use --profile-thread=main).')) 2008*6777b538SAndroid Build Coastguard Worker group.add_argument('--profile-output', default='profile.pb', 2009*6777b538SAndroid Build Coastguard Worker help='Output file for profiling data') 2010*6777b538SAndroid Build Coastguard Worker group.add_argument('--profile-events', default='cpu-cycles', 2011*6777b538SAndroid Build Coastguard Worker help=('A comma separated list of perf events to capture ' 2012*6777b538SAndroid Build Coastguard Worker '(e.g. \'cpu-cycles,branch-misses\'). Run ' 2013*6777b538SAndroid Build Coastguard Worker '`simpleperf list` on your device to see available ' 2014*6777b538SAndroid Build Coastguard Worker 'events.')) 2015*6777b538SAndroid Build Coastguard Worker 2016*6777b538SAndroid Build Coastguard Worker def Run(self): 2017*6777b538SAndroid Build Coastguard Worker extra_args = shlex.split(self.args.args or '') 2018*6777b538SAndroid Build Coastguard Worker _RunProfile(self.devices[0], self.args.package_name, 2019*6777b538SAndroid Build Coastguard Worker self.args.output_directory, self.args.profile_output, 2020*6777b538SAndroid Build Coastguard Worker self.args.profile_process, self.args.profile_thread, 2021*6777b538SAndroid Build Coastguard Worker self.args.profile_events, extra_args) 2022*6777b538SAndroid Build Coastguard Worker 2023*6777b538SAndroid Build Coastguard Worker 2024*6777b538SAndroid Build Coastguard Workerclass _RunCommand(_InstallCommand, _LaunchCommand, _LogcatCommand): 2025*6777b538SAndroid Build Coastguard Worker name = 'run' 2026*6777b538SAndroid Build Coastguard Worker description = 'Install, launch, and show logcat (when targeting one device).' 2027*6777b538SAndroid Build Coastguard Worker all_devices_by_default = False 2028*6777b538SAndroid Build Coastguard Worker supports_multiple_devices = True 2029*6777b538SAndroid Build Coastguard Worker 2030*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 2031*6777b538SAndroid Build Coastguard Worker _InstallCommand._RegisterExtraArgs(self, group) 2032*6777b538SAndroid Build Coastguard Worker _LaunchCommand._RegisterExtraArgs(self, group) 2033*6777b538SAndroid Build Coastguard Worker _LogcatCommand._RegisterExtraArgs(self, group) 2034*6777b538SAndroid Build Coastguard Worker group.add_argument('--no-logcat', action='store_true', 2035*6777b538SAndroid Build Coastguard Worker help='Install and launch, but do not enter logcat.') 2036*6777b538SAndroid Build Coastguard Worker 2037*6777b538SAndroid Build Coastguard Worker def Run(self): 2038*6777b538SAndroid Build Coastguard Worker if self.is_test_apk: 2039*6777b538SAndroid Build Coastguard Worker raise Exception('Use the bin/run_* scripts to run test apks.') 2040*6777b538SAndroid Build Coastguard Worker logging.warning('Installing...') 2041*6777b538SAndroid Build Coastguard Worker _InstallCommand.Run(self) 2042*6777b538SAndroid Build Coastguard Worker logging.warning('Sending launch intent...') 2043*6777b538SAndroid Build Coastguard Worker _LaunchCommand.Run(self) 2044*6777b538SAndroid Build Coastguard Worker if len(self.devices) == 1 and not self.args.no_logcat: 2045*6777b538SAndroid Build Coastguard Worker logging.warning('Entering logcat...') 2046*6777b538SAndroid Build Coastguard Worker _LogcatCommand.Run(self) 2047*6777b538SAndroid Build Coastguard Worker 2048*6777b538SAndroid Build Coastguard Worker 2049*6777b538SAndroid Build Coastguard Workerclass _BuildBundleApks(_Command): 2050*6777b538SAndroid Build Coastguard Worker name = 'build-bundle-apks' 2051*6777b538SAndroid Build Coastguard Worker description = ('Build the .apks archive from an Android app bundle, and ' 2052*6777b538SAndroid Build Coastguard Worker 'optionally copy it to a specific destination.') 2053*6777b538SAndroid Build Coastguard Worker need_device_args = False 2054*6777b538SAndroid Build Coastguard Worker 2055*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 2056*6777b538SAndroid Build Coastguard Worker group.add_argument( 2057*6777b538SAndroid Build Coastguard Worker '--output-apks', required=True, help='Destination path for .apks file.') 2058*6777b538SAndroid Build Coastguard Worker group.add_argument( 2059*6777b538SAndroid Build Coastguard Worker '--minimal', 2060*6777b538SAndroid Build Coastguard Worker action='store_true', 2061*6777b538SAndroid Build Coastguard Worker help='Build .apks archive that targets the bundle\'s minSdkVersion and ' 2062*6777b538SAndroid Build Coastguard Worker 'contains only english splits. It still contains optional splits.') 2063*6777b538SAndroid Build Coastguard Worker group.add_argument( 2064*6777b538SAndroid Build Coastguard Worker '--sdk-version', help='The sdkVersion to build the .apks for.') 2065*6777b538SAndroid Build Coastguard Worker group.add_argument( 2066*6777b538SAndroid Build Coastguard Worker '--build-mode', 2067*6777b538SAndroid Build Coastguard Worker choices=app_bundle_utils.BUILD_APKS_MODES, 2068*6777b538SAndroid Build Coastguard Worker help='Specify which type of APKs archive to build. "default" ' 2069*6777b538SAndroid Build Coastguard Worker 'generates regular splits, "universal" generates an archive with a ' 2070*6777b538SAndroid Build Coastguard Worker 'single universal APK, "system" generates an archive with a system ' 2071*6777b538SAndroid Build Coastguard Worker 'image APK, while "system_compressed" generates a compressed system ' 2072*6777b538SAndroid Build Coastguard Worker 'APK, with an additional stub APK for the system image.') 2073*6777b538SAndroid Build Coastguard Worker group.add_argument( 2074*6777b538SAndroid Build Coastguard Worker '--optimize-for', 2075*6777b538SAndroid Build Coastguard Worker choices=app_bundle_utils.OPTIMIZE_FOR_OPTIONS, 2076*6777b538SAndroid Build Coastguard Worker help='Override split configuration.') 2077*6777b538SAndroid Build Coastguard Worker 2078*6777b538SAndroid Build Coastguard Worker def Run(self): 2079*6777b538SAndroid Build Coastguard Worker _GenerateBundleApks( 2080*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info, 2081*6777b538SAndroid Build Coastguard Worker output_path=self.args.output_apks, 2082*6777b538SAndroid Build Coastguard Worker minimal=self.args.minimal, 2083*6777b538SAndroid Build Coastguard Worker minimal_sdk_version=self.args.sdk_version, 2084*6777b538SAndroid Build Coastguard Worker mode=self.args.build_mode, 2085*6777b538SAndroid Build Coastguard Worker optimize_for=self.args.optimize_for) 2086*6777b538SAndroid Build Coastguard Worker 2087*6777b538SAndroid Build Coastguard Worker 2088*6777b538SAndroid Build Coastguard Workerclass _ManifestCommand(_Command): 2089*6777b538SAndroid Build Coastguard Worker name = 'dump-manifest' 2090*6777b538SAndroid Build Coastguard Worker description = 'Dump the android manifest as XML, to stdout.' 2091*6777b538SAndroid Build Coastguard Worker need_device_args = False 2092*6777b538SAndroid Build Coastguard Worker needs_apk_helper = True 2093*6777b538SAndroid Build Coastguard Worker 2094*6777b538SAndroid Build Coastguard Worker def Run(self): 2095*6777b538SAndroid Build Coastguard Worker if self.is_bundle: 2096*6777b538SAndroid Build Coastguard Worker sys.stdout.write( 2097*6777b538SAndroid Build Coastguard Worker bundletool.RunBundleTool([ 2098*6777b538SAndroid Build Coastguard Worker 'dump', 'manifest', '--bundle', 2099*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info.bundle_path 2100*6777b538SAndroid Build Coastguard Worker ])) 2101*6777b538SAndroid Build Coastguard Worker else: 2102*6777b538SAndroid Build Coastguard Worker apkanalyzer = os.path.join(_DIR_SOURCE_ROOT, 'third_party', 'android_sdk', 2103*6777b538SAndroid Build Coastguard Worker 'public', 'cmdline-tools', 'latest', 'bin', 2104*6777b538SAndroid Build Coastguard Worker 'apkanalyzer') 2105*6777b538SAndroid Build Coastguard Worker cmd = [apkanalyzer, 'manifest', 'print', self.apk_helper.path] 2106*6777b538SAndroid Build Coastguard Worker logging.info('Running: %s', shlex.join(cmd)) 2107*6777b538SAndroid Build Coastguard Worker subprocess.check_call(cmd) 2108*6777b538SAndroid Build Coastguard Worker 2109*6777b538SAndroid Build Coastguard Worker 2110*6777b538SAndroid Build Coastguard Workerclass _StackCommand(_Command): 2111*6777b538SAndroid Build Coastguard Worker name = 'stack' 2112*6777b538SAndroid Build Coastguard Worker description = 'Decodes an Android stack.' 2113*6777b538SAndroid Build Coastguard Worker need_device_args = False 2114*6777b538SAndroid Build Coastguard Worker 2115*6777b538SAndroid Build Coastguard Worker def _RegisterExtraArgs(self, group): 2116*6777b538SAndroid Build Coastguard Worker group.add_argument( 2117*6777b538SAndroid Build Coastguard Worker 'file', 2118*6777b538SAndroid Build Coastguard Worker nargs='?', 2119*6777b538SAndroid Build Coastguard Worker help='File to decode. If not specified, stdin is processed.') 2120*6777b538SAndroid Build Coastguard Worker 2121*6777b538SAndroid Build Coastguard Worker def Run(self): 2122*6777b538SAndroid Build Coastguard Worker context = _StackScriptContext(self.args.output_directory, 2123*6777b538SAndroid Build Coastguard Worker self.args.apk_path, 2124*6777b538SAndroid Build Coastguard Worker self.bundle_generation_info) 2125*6777b538SAndroid Build Coastguard Worker try: 2126*6777b538SAndroid Build Coastguard Worker proc = context.Popen(input_file=self.args.file) 2127*6777b538SAndroid Build Coastguard Worker if proc.wait(): 2128*6777b538SAndroid Build Coastguard Worker raise Exception('stack script returned {}'.format(proc.returncode)) 2129*6777b538SAndroid Build Coastguard Worker finally: 2130*6777b538SAndroid Build Coastguard Worker context.Close() 2131*6777b538SAndroid Build Coastguard Worker 2132*6777b538SAndroid Build Coastguard Worker 2133*6777b538SAndroid Build Coastguard Worker# Shared commands for regular APKs and app bundles. 2134*6777b538SAndroid Build Coastguard Worker_COMMANDS = [ 2135*6777b538SAndroid Build Coastguard Worker _DevicesCommand, 2136*6777b538SAndroid Build Coastguard Worker _PackageInfoCommand, 2137*6777b538SAndroid Build Coastguard Worker _InstallCommand, 2138*6777b538SAndroid Build Coastguard Worker _UninstallCommand, 2139*6777b538SAndroid Build Coastguard Worker _SetWebViewProviderCommand, 2140*6777b538SAndroid Build Coastguard Worker _LaunchCommand, 2141*6777b538SAndroid Build Coastguard Worker _StopCommand, 2142*6777b538SAndroid Build Coastguard Worker _ClearDataCommand, 2143*6777b538SAndroid Build Coastguard Worker _ArgvCommand, 2144*6777b538SAndroid Build Coastguard Worker _GdbCommand, 2145*6777b538SAndroid Build Coastguard Worker _LldbCommand, 2146*6777b538SAndroid Build Coastguard Worker _LogcatCommand, 2147*6777b538SAndroid Build Coastguard Worker _PsCommand, 2148*6777b538SAndroid Build Coastguard Worker _DiskUsageCommand, 2149*6777b538SAndroid Build Coastguard Worker _MemUsageCommand, 2150*6777b538SAndroid Build Coastguard Worker _ShellCommand, 2151*6777b538SAndroid Build Coastguard Worker _CompileDexCommand, 2152*6777b538SAndroid Build Coastguard Worker _PrintCertsCommand, 2153*6777b538SAndroid Build Coastguard Worker _ProfileCommand, 2154*6777b538SAndroid Build Coastguard Worker _RunCommand, 2155*6777b538SAndroid Build Coastguard Worker _StackCommand, 2156*6777b538SAndroid Build Coastguard Worker _ManifestCommand, 2157*6777b538SAndroid Build Coastguard Worker] 2158*6777b538SAndroid Build Coastguard Worker 2159*6777b538SAndroid Build Coastguard Worker# Commands specific to app bundles. 2160*6777b538SAndroid Build Coastguard Worker_BUNDLE_COMMANDS = [ 2161*6777b538SAndroid Build Coastguard Worker _BuildBundleApks, 2162*6777b538SAndroid Build Coastguard Worker] 2163*6777b538SAndroid Build Coastguard Worker 2164*6777b538SAndroid Build Coastguard Worker 2165*6777b538SAndroid Build Coastguard Workerdef _ParseArgs(parser, from_wrapper_script, is_bundle, is_test_apk): 2166*6777b538SAndroid Build Coastguard Worker subparsers = parser.add_subparsers() 2167*6777b538SAndroid Build Coastguard Worker command_list = _COMMANDS + (_BUNDLE_COMMANDS if is_bundle else []) 2168*6777b538SAndroid Build Coastguard Worker commands = [ 2169*6777b538SAndroid Build Coastguard Worker clazz(from_wrapper_script, is_bundle, is_test_apk) 2170*6777b538SAndroid Build Coastguard Worker for clazz in command_list 2171*6777b538SAndroid Build Coastguard Worker ] 2172*6777b538SAndroid Build Coastguard Worker 2173*6777b538SAndroid Build Coastguard Worker for command in commands: 2174*6777b538SAndroid Build Coastguard Worker if from_wrapper_script or not command.needs_output_directory: 2175*6777b538SAndroid Build Coastguard Worker command.RegisterArgs(subparsers) 2176*6777b538SAndroid Build Coastguard Worker 2177*6777b538SAndroid Build Coastguard Worker # Show extended help when no command is passed. 2178*6777b538SAndroid Build Coastguard Worker argv = sys.argv[1:] 2179*6777b538SAndroid Build Coastguard Worker if not argv: 2180*6777b538SAndroid Build Coastguard Worker argv = ['--help'] 2181*6777b538SAndroid Build Coastguard Worker 2182*6777b538SAndroid Build Coastguard Worker return parser.parse_args(argv) 2183*6777b538SAndroid Build Coastguard Worker 2184*6777b538SAndroid Build Coastguard Worker 2185*6777b538SAndroid Build Coastguard Workerdef _RunInternal(parser, 2186*6777b538SAndroid Build Coastguard Worker output_directory=None, 2187*6777b538SAndroid Build Coastguard Worker additional_apk_paths=None, 2188*6777b538SAndroid Build Coastguard Worker bundle_generation_info=None, 2189*6777b538SAndroid Build Coastguard Worker is_test_apk=False): 2190*6777b538SAndroid Build Coastguard Worker colorama.init() 2191*6777b538SAndroid Build Coastguard Worker parser.set_defaults( 2192*6777b538SAndroid Build Coastguard Worker additional_apk_paths=additional_apk_paths, 2193*6777b538SAndroid Build Coastguard Worker output_directory=output_directory) 2194*6777b538SAndroid Build Coastguard Worker from_wrapper_script = bool(output_directory) 2195*6777b538SAndroid Build Coastguard Worker args = _ParseArgs(parser, 2196*6777b538SAndroid Build Coastguard Worker from_wrapper_script, 2197*6777b538SAndroid Build Coastguard Worker is_bundle=bool(bundle_generation_info), 2198*6777b538SAndroid Build Coastguard Worker is_test_apk=is_test_apk) 2199*6777b538SAndroid Build Coastguard Worker run_tests_helper.SetLogLevel(args.verbose_count) 2200*6777b538SAndroid Build Coastguard Worker if bundle_generation_info: 2201*6777b538SAndroid Build Coastguard Worker args.command.RegisterBundleGenerationInfo(bundle_generation_info) 2202*6777b538SAndroid Build Coastguard Worker if args.additional_apk_paths: 2203*6777b538SAndroid Build Coastguard Worker for path in additional_apk_paths: 2204*6777b538SAndroid Build Coastguard Worker if not path or not os.path.exists(path): 2205*6777b538SAndroid Build Coastguard Worker raise Exception('Invalid additional APK path "{}"'.format(path)) 2206*6777b538SAndroid Build Coastguard Worker args.command.ProcessArgs(args) 2207*6777b538SAndroid Build Coastguard Worker args.command.Run() 2208*6777b538SAndroid Build Coastguard Worker # Incremental install depends on the cache being cleared when uninstalling. 2209*6777b538SAndroid Build Coastguard Worker if args.command.name != 'uninstall': 2210*6777b538SAndroid Build Coastguard Worker _SaveDeviceCaches(args.command.devices, output_directory) 2211*6777b538SAndroid Build Coastguard Worker 2212*6777b538SAndroid Build Coastguard Worker 2213*6777b538SAndroid Build Coastguard Workerdef Run(output_directory, apk_path, additional_apk_paths, incremental_json, 2214*6777b538SAndroid Build Coastguard Worker command_line_flags_file, target_cpu, proguard_mapping_path): 2215*6777b538SAndroid Build Coastguard Worker """Entry point for generated wrapper scripts.""" 2216*6777b538SAndroid Build Coastguard Worker constants.SetOutputDirectory(output_directory) 2217*6777b538SAndroid Build Coastguard Worker devil_chromium.Initialize(output_directory=output_directory) 2218*6777b538SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 2219*6777b538SAndroid Build Coastguard Worker exists_or_none = lambda p: p if p and os.path.exists(p) else None 2220*6777b538SAndroid Build Coastguard Worker 2221*6777b538SAndroid Build Coastguard Worker parser.set_defaults( 2222*6777b538SAndroid Build Coastguard Worker command_line_flags_file=command_line_flags_file, 2223*6777b538SAndroid Build Coastguard Worker target_cpu=target_cpu, 2224*6777b538SAndroid Build Coastguard Worker apk_path=exists_or_none(apk_path), 2225*6777b538SAndroid Build Coastguard Worker incremental_json=exists_or_none(incremental_json), 2226*6777b538SAndroid Build Coastguard Worker proguard_mapping_path=proguard_mapping_path) 2227*6777b538SAndroid Build Coastguard Worker _RunInternal( 2228*6777b538SAndroid Build Coastguard Worker parser, 2229*6777b538SAndroid Build Coastguard Worker output_directory=output_directory, 2230*6777b538SAndroid Build Coastguard Worker additional_apk_paths=additional_apk_paths) 2231*6777b538SAndroid Build Coastguard Worker 2232*6777b538SAndroid Build Coastguard Worker 2233*6777b538SAndroid Build Coastguard Workerdef RunForBundle(output_directory, bundle_path, bundle_apks_path, 2234*6777b538SAndroid Build Coastguard Worker additional_apk_paths, aapt2_path, keystore_path, 2235*6777b538SAndroid Build Coastguard Worker keystore_password, keystore_alias, package_name, 2236*6777b538SAndroid Build Coastguard Worker command_line_flags_file, proguard_mapping_path, target_cpu, 2237*6777b538SAndroid Build Coastguard Worker system_image_locales, default_modules): 2238*6777b538SAndroid Build Coastguard Worker """Entry point for generated app bundle wrapper scripts. 2239*6777b538SAndroid Build Coastguard Worker 2240*6777b538SAndroid Build Coastguard Worker Args: 2241*6777b538SAndroid Build Coastguard Worker output_dir: Chromium output directory path. 2242*6777b538SAndroid Build Coastguard Worker bundle_path: Input bundle path. 2243*6777b538SAndroid Build Coastguard Worker bundle_apks_path: Output bundle .apks archive path. 2244*6777b538SAndroid Build Coastguard Worker additional_apk_paths: Additional APKs to install prior to bundle install. 2245*6777b538SAndroid Build Coastguard Worker aapt2_path: Aapt2 tool path. 2246*6777b538SAndroid Build Coastguard Worker keystore_path: Keystore file path. 2247*6777b538SAndroid Build Coastguard Worker keystore_password: Keystore password. 2248*6777b538SAndroid Build Coastguard Worker keystore_alias: Signing key name alias in keystore file. 2249*6777b538SAndroid Build Coastguard Worker package_name: Application's package name. 2250*6777b538SAndroid Build Coastguard Worker command_line_flags_file: Optional. Name of an on-device file that will be 2251*6777b538SAndroid Build Coastguard Worker used to store command-line flags for this bundle. 2252*6777b538SAndroid Build Coastguard Worker proguard_mapping_path: Input path to the Proguard mapping file, used to 2253*6777b538SAndroid Build Coastguard Worker deobfuscate Java stack traces. 2254*6777b538SAndroid Build Coastguard Worker target_cpu: Chromium target CPU name, used by the 'gdb' command. 2255*6777b538SAndroid Build Coastguard Worker system_image_locales: List of Chromium locales that should be included in 2256*6777b538SAndroid Build Coastguard Worker system image APKs. 2257*6777b538SAndroid Build Coastguard Worker default_modules: List of modules that are installed in addition to those 2258*6777b538SAndroid Build Coastguard Worker given by the '-m' switch. 2259*6777b538SAndroid Build Coastguard Worker """ 2260*6777b538SAndroid Build Coastguard Worker constants.SetOutputDirectory(output_directory) 2261*6777b538SAndroid Build Coastguard Worker devil_chromium.Initialize(output_directory=output_directory) 2262*6777b538SAndroid Build Coastguard Worker bundle_generation_info = BundleGenerationInfo( 2263*6777b538SAndroid Build Coastguard Worker bundle_path=bundle_path, 2264*6777b538SAndroid Build Coastguard Worker bundle_apks_path=bundle_apks_path, 2265*6777b538SAndroid Build Coastguard Worker aapt2_path=aapt2_path, 2266*6777b538SAndroid Build Coastguard Worker keystore_path=keystore_path, 2267*6777b538SAndroid Build Coastguard Worker keystore_password=keystore_password, 2268*6777b538SAndroid Build Coastguard Worker keystore_alias=keystore_alias, 2269*6777b538SAndroid Build Coastguard Worker system_image_locales=system_image_locales) 2270*6777b538SAndroid Build Coastguard Worker _InstallCommand.default_modules = default_modules 2271*6777b538SAndroid Build Coastguard Worker 2272*6777b538SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 2273*6777b538SAndroid Build Coastguard Worker parser.set_defaults( 2274*6777b538SAndroid Build Coastguard Worker package_name=package_name, 2275*6777b538SAndroid Build Coastguard Worker command_line_flags_file=command_line_flags_file, 2276*6777b538SAndroid Build Coastguard Worker proguard_mapping_path=proguard_mapping_path, 2277*6777b538SAndroid Build Coastguard Worker target_cpu=target_cpu) 2278*6777b538SAndroid Build Coastguard Worker _RunInternal( 2279*6777b538SAndroid Build Coastguard Worker parser, 2280*6777b538SAndroid Build Coastguard Worker output_directory=output_directory, 2281*6777b538SAndroid Build Coastguard Worker additional_apk_paths=additional_apk_paths, 2282*6777b538SAndroid Build Coastguard Worker bundle_generation_info=bundle_generation_info) 2283*6777b538SAndroid Build Coastguard Worker 2284*6777b538SAndroid Build Coastguard Worker 2285*6777b538SAndroid Build Coastguard Workerdef RunForTestApk(*, output_directory, package_name, test_apk_path, 2286*6777b538SAndroid Build Coastguard Worker test_apk_json, proguard_mapping_path, additional_apk_paths): 2287*6777b538SAndroid Build Coastguard Worker """Entry point for generated test apk wrapper scripts. 2288*6777b538SAndroid Build Coastguard Worker 2289*6777b538SAndroid Build Coastguard Worker This is intended to make commands like logcat (with proguard deobfuscation) 2290*6777b538SAndroid Build Coastguard Worker available. The run_* scripts should be used to actually run tests. 2291*6777b538SAndroid Build Coastguard Worker 2292*6777b538SAndroid Build Coastguard Worker Args: 2293*6777b538SAndroid Build Coastguard Worker output_dir: Chromium output directory path. 2294*6777b538SAndroid Build Coastguard Worker package_name: The package name for the test apk. 2295*6777b538SAndroid Build Coastguard Worker test_apk_path: The test apk to install. 2296*6777b538SAndroid Build Coastguard Worker test_apk_json: The incremental json dict for the test apk. 2297*6777b538SAndroid Build Coastguard Worker proguard_mapping_path: Input path to the Proguard mapping file, used to 2298*6777b538SAndroid Build Coastguard Worker deobfuscate Java stack traces. 2299*6777b538SAndroid Build Coastguard Worker additional_apk_paths: Additional APKs to install. 2300*6777b538SAndroid Build Coastguard Worker """ 2301*6777b538SAndroid Build Coastguard Worker constants.SetOutputDirectory(output_directory) 2302*6777b538SAndroid Build Coastguard Worker devil_chromium.Initialize(output_directory=output_directory) 2303*6777b538SAndroid Build Coastguard Worker 2304*6777b538SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 2305*6777b538SAndroid Build Coastguard Worker exists_or_none = lambda p: p if p and os.path.exists(p) else None 2306*6777b538SAndroid Build Coastguard Worker 2307*6777b538SAndroid Build Coastguard Worker parser.set_defaults(apk_path=exists_or_none(test_apk_path), 2308*6777b538SAndroid Build Coastguard Worker incremental_json=exists_or_none(test_apk_json), 2309*6777b538SAndroid Build Coastguard Worker package_name=package_name, 2310*6777b538SAndroid Build Coastguard Worker proguard_mapping_path=proguard_mapping_path) 2311*6777b538SAndroid Build Coastguard Worker 2312*6777b538SAndroid Build Coastguard Worker _RunInternal(parser, 2313*6777b538SAndroid Build Coastguard Worker output_directory=output_directory, 2314*6777b538SAndroid Build Coastguard Worker additional_apk_paths=additional_apk_paths, 2315*6777b538SAndroid Build Coastguard Worker is_test_apk=True) 2316*6777b538SAndroid Build Coastguard Worker 2317*6777b538SAndroid Build Coastguard Worker 2318*6777b538SAndroid Build Coastguard Workerdef main(): 2319*6777b538SAndroid Build Coastguard Worker devil_chromium.Initialize() 2320*6777b538SAndroid Build Coastguard Worker _RunInternal(argparse.ArgumentParser()) 2321*6777b538SAndroid Build Coastguard Worker 2322*6777b538SAndroid Build Coastguard Worker 2323*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__': 2324*6777b538SAndroid Build Coastguard Worker main() 2325