1*9e965d6fSRomain Jobredeaux# Copyright 2018 The Bazel Authors. All rights reserved. 2*9e965d6fSRomain Jobredeaux# 3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License"); 4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License. 5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at 6*9e965d6fSRomain Jobredeaux# 7*9e965d6fSRomain Jobredeaux# http://www.apache.org/licenses/LICENSE-2.0 8*9e965d6fSRomain Jobredeaux# 9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software 10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS, 11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and 13*9e965d6fSRomain Jobredeaux# limitations under the License. 14*9e965d6fSRomain Jobredeaux"""Creates the app launcher scripts.""" 15*9e965d6fSRomain Jobredeaux 16*9e965d6fSRomain Jobredeauxload(":utils.bzl", "utils") 17*9e965d6fSRomain Jobredeauxload(":workspace.bzl", "make_dex_sync", "make_generic_sync", "merge_syncs") 18*9e965d6fSRomain Jobredeauxload(":deploy_info.bzl", "make_deploy_info_pb") 19*9e965d6fSRomain Jobredeauxload(":providers.bzl", "MIAppInfo", "MIAppLaunchInfo") 20*9e965d6fSRomain Jobredeauxload("//rules/flags:flags.bzl", "flags") 21*9e965d6fSRomain Jobredeaux 22*9e965d6fSRomain JobredeauxHOST_TEST_WORKSPACE = "host_test_runner_workspace" 23*9e965d6fSRomain Jobredeaux 24*9e965d6fSRomain Jobredeaux_DEPLOY_SCRIPT = '''#!/bin/bash 25*9e965d6fSRomain Jobredeauxset -e # exit on failure 26*9e965d6fSRomain Jobredeauxumask 022 # set default file/dir creation mode to 755 27*9e965d6fSRomain Jobredeaux 28*9e965d6fSRomain JobredeauxFLAGS={flags} 29*9e965d6fSRomain JobredeauxTEST_FLAGS={test_flags} 30*9e965d6fSRomain JobredeauxDEPLOY={deploy} 31*9e965d6fSRomain Jobredeaux 32*9e965d6fSRomain Jobredeaux 33*9e965d6fSRomain JobredeauxALL_TEST_ARGS=("$@") 34*9e965d6fSRomain Jobredeauxif [[ ! -z ${{TEST_FLAGS}} ]]; 35*9e965d6fSRomain Jobredeauxthen 36*9e965d6fSRomain Jobredeaux RULE_TEST_ARGS={test_args} 37*9e965d6fSRomain Jobredeaux ALL_TEST_ARGS=("--nolaunch_app" "${{RULE_TEST_ARGS[@]}}" "$@") 38*9e965d6fSRomain Jobredeaux "${{DEPLOY}}" \ 39*9e965d6fSRomain Jobredeaux -flagfile="${{TEST_FLAGS}}" \ 40*9e965d6fSRomain Jobredeaux "${{ALL_TEST_ARGS[@]}}" 41*9e965d6fSRomain Jobredeauxelse 42*9e965d6fSRomain Jobredeaux "${{DEPLOY}}" -flagfile="${{FLAGS}}" \ 43*9e965d6fSRomain Jobredeaux "${{ALL_TEST_ARGS[@]}}" 44*9e965d6fSRomain Jobredeauxfi 45*9e965d6fSRomain Jobredeaux 46*9e965d6fSRomain Jobredeaux''' 47*9e965d6fSRomain Jobredeaux 48*9e965d6fSRomain Jobredeauxdef _make_deploy_script( 49*9e965d6fSRomain Jobredeaux ctx, 50*9e965d6fSRomain Jobredeaux out_script, 51*9e965d6fSRomain Jobredeaux deploy, 52*9e965d6fSRomain Jobredeaux flags, 53*9e965d6fSRomain Jobredeaux test_args = "", 54*9e965d6fSRomain Jobredeaux test_flags = ""): 55*9e965d6fSRomain Jobredeaux deploy_contents = _DEPLOY_SCRIPT.format( 56*9e965d6fSRomain Jobredeaux deploy = deploy, 57*9e965d6fSRomain Jobredeaux flags = flags, 58*9e965d6fSRomain Jobredeaux test_flags = test_flags, 59*9e965d6fSRomain Jobredeaux test_args = test_args, 60*9e965d6fSRomain Jobredeaux ) 61*9e965d6fSRomain Jobredeaux ctx.actions.write(out_script, deploy_contents, is_executable = True) 62*9e965d6fSRomain Jobredeaux 63*9e965d6fSRomain Jobredeauxdef _make_app_runner( 64*9e965d6fSRomain Jobredeaux ctx, 65*9e965d6fSRomain Jobredeaux sync, 66*9e965d6fSRomain Jobredeaux manifest_package_name_path, 67*9e965d6fSRomain Jobredeaux out_launcher, 68*9e965d6fSRomain Jobredeaux out_launcher_flags, 69*9e965d6fSRomain Jobredeaux shell_apk = None, 70*9e965d6fSRomain Jobredeaux splits = None, 71*9e965d6fSRomain Jobredeaux deploy_info_pb = None, 72*9e965d6fSRomain Jobredeaux test_apk = None, 73*9e965d6fSRomain Jobredeaux test_data = None, 74*9e965d6fSRomain Jobredeaux test_args = None, 75*9e965d6fSRomain Jobredeaux instrumented_app_package_name = None, 76*9e965d6fSRomain Jobredeaux use_adb_root = True, 77*9e965d6fSRomain Jobredeaux enable_metrics_logging = False, 78*9e965d6fSRomain Jobredeaux use_studio_deployer = True, 79*9e965d6fSRomain Jobredeaux is_test = False): 80*9e965d6fSRomain Jobredeaux path_type = "path" if ctx.attr._mi_is_cmd else "short_path" 81*9e965d6fSRomain Jobredeaux 82*9e965d6fSRomain Jobredeaux deploy = utils.first(ctx.attr._deploy.files.to_list()) 83*9e965d6fSRomain Jobredeaux 84*9e965d6fSRomain Jobredeaux args = { 85*9e965d6fSRomain Jobredeaux "data_sync_path": getattr(sync, path_type), 86*9e965d6fSRomain Jobredeaux "is_cmd": str(ctx.attr._mi_is_cmd).lower(), 87*9e965d6fSRomain Jobredeaux "manifest_package_name_path": getattr(manifest_package_name_path, path_type), 88*9e965d6fSRomain Jobredeaux "target": ctx.label, 89*9e965d6fSRomain Jobredeaux } 90*9e965d6fSRomain Jobredeaux if shell_apk: 91*9e965d6fSRomain Jobredeaux args["shell_app_path"] = getattr(shell_apk, path_type) 92*9e965d6fSRomain Jobredeaux 93*9e965d6fSRomain Jobredeaux if splits: 94*9e965d6fSRomain Jobredeaux args["splits"] = [getattr(s, path_type) for s in splits] 95*9e965d6fSRomain Jobredeaux args["enable_splits"] = True 96*9e965d6fSRomain Jobredeaux 97*9e965d6fSRomain Jobredeaux if ctx.attr._mi_is_cmd: 98*9e965d6fSRomain Jobredeaux args["host_test_runner_workspace"] = HOST_TEST_WORKSPACE 99*9e965d6fSRomain Jobredeaux 100*9e965d6fSRomain Jobredeaux args["java_home"] = utils.host_jvm_path(ctx) 101*9e965d6fSRomain Jobredeaux 102*9e965d6fSRomain Jobredeaux args["studio_deployer"] = getattr(ctx.file._studio_deployer, path_type) 103*9e965d6fSRomain Jobredeaux args["use_adb_root"] = str(use_adb_root).lower() 104*9e965d6fSRomain Jobredeaux args["enable_metrics_logging"] = str(enable_metrics_logging).lower() 105*9e965d6fSRomain Jobredeaux args["use_studio_deployer"] = str(use_studio_deployer).lower() 106*9e965d6fSRomain Jobredeaux 107*9e965d6fSRomain Jobredeaux args["use_direct_deploy"] = True 108*9e965d6fSRomain Jobredeaux 109*9e965d6fSRomain Jobredeaux android_test_runner = None 110*9e965d6fSRomain Jobredeaux if is_test and hasattr(ctx.attr, "_android_test_runner"): 111*9e965d6fSRomain Jobredeaux android_test_runner = ctx.file._android_test_runner 112*9e965d6fSRomain Jobredeaux args["android_test_runner"] = getattr(android_test_runner, path_type) 113*9e965d6fSRomain Jobredeaux args["is_test"] = True 114*9e965d6fSRomain Jobredeaux 115*9e965d6fSRomain Jobredeaux if test_data: 116*9e965d6fSRomain Jobredeaux args["data_files"] = ",".join([f.short_path for f in test_data]) 117*9e965d6fSRomain Jobredeaux 118*9e965d6fSRomain Jobredeaux if test_apk: 119*9e965d6fSRomain Jobredeaux args["test_apk"] = test_apk.path 120*9e965d6fSRomain Jobredeaux 121*9e965d6fSRomain Jobredeaux if instrumented_app_package_name: 122*9e965d6fSRomain Jobredeaux args["instrumented_app_package_name"] = getattr(instrumented_app_package_name, path_type) 123*9e965d6fSRomain Jobredeaux 124*9e965d6fSRomain Jobredeaux if deploy_info_pb: 125*9e965d6fSRomain Jobredeaux args["deploy_info"] = getattr(deploy_info_pb, path_type) 126*9e965d6fSRomain Jobredeaux 127*9e965d6fSRomain Jobredeaux utils.create_flag_file(ctx, out_launcher_flags, **args) 128*9e965d6fSRomain Jobredeaux 129*9e965d6fSRomain Jobredeaux _make_deploy_script( 130*9e965d6fSRomain Jobredeaux ctx, 131*9e965d6fSRomain Jobredeaux out_launcher, 132*9e965d6fSRomain Jobredeaux getattr(deploy, path_type), 133*9e965d6fSRomain Jobredeaux flags = getattr(out_launcher_flags, path_type), 134*9e965d6fSRomain Jobredeaux # Converts the python array of args into a bash array. Each arg is 135*9e965d6fSRomain Jobredeaux # wrapped with quotes to handle "space" separted flag value entries 136*9e965d6fSRomain Jobredeaux # and as result also escapes existing quotes. 137*9e965d6fSRomain Jobredeaux test_args = ("(%s)" % " ".join([ 138*9e965d6fSRomain Jobredeaux '"--test_arg=%s"' % arg.replace('"', '\\"') 139*9e965d6fSRomain Jobredeaux for arg in test_args 140*9e965d6fSRomain Jobredeaux ])) if test_args else "", 141*9e965d6fSRomain Jobredeaux test_flags = getattr(out_launcher_flags, path_type) if test_args or is_test else "", 142*9e965d6fSRomain Jobredeaux ) 143*9e965d6fSRomain Jobredeaux 144*9e965d6fSRomain Jobredeaux runner = [deploy] 145*9e965d6fSRomain Jobredeaux if android_test_runner: 146*9e965d6fSRomain Jobredeaux runner.extend(ctx.attr._java_jdk.files.to_list()) 147*9e965d6fSRomain Jobredeaux runner.append(android_test_runner) 148*9e965d6fSRomain Jobredeaux return runner 149*9e965d6fSRomain Jobredeaux 150*9e965d6fSRomain Jobredeauxdef make_direct_launcher( 151*9e965d6fSRomain Jobredeaux ctx, 152*9e965d6fSRomain Jobredeaux mi_app_info, 153*9e965d6fSRomain Jobredeaux launcher, 154*9e965d6fSRomain Jobredeaux test_data = None, 155*9e965d6fSRomain Jobredeaux test_args = None, 156*9e965d6fSRomain Jobredeaux test_support_apps = None, 157*9e965d6fSRomain Jobredeaux use_adb_root = True, 158*9e965d6fSRomain Jobredeaux is_test = False): 159*9e965d6fSRomain Jobredeaux """ Runfiles for launching the apps are created. 160*9e965d6fSRomain Jobredeaux 161*9e965d6fSRomain Jobredeaux Args: 162*9e965d6fSRomain Jobredeaux ctx: The context 163*9e965d6fSRomain Jobredeaux mi_app_info: The MIAppInfo provider 164*9e965d6fSRomain Jobredeaux launcher: The launcher file 165*9e965d6fSRomain Jobredeaux test_data: The test data 166*9e965d6fSRomain Jobredeaux test_support_apps: The test support apps 167*9e965d6fSRomain Jobredeaux test_args: The test arguments 168*9e965d6fSRomain Jobredeaux use_adb_root: Boolean argument to restart adb with root permissions. 169*9e965d6fSRomain Jobredeaux is_test: Boolean argument to identify if it's a test 170*9e965d6fSRomain Jobredeaux Returns: 171*9e965d6fSRomain Jobredeaux A list of files required for runtime common for both running binary and test. 172*9e965d6fSRomain Jobredeaux """ 173*9e965d6fSRomain Jobredeaux app_pbs = [] 174*9e965d6fSRomain Jobredeaux runfiles = [] 175*9e965d6fSRomain Jobredeaux 176*9e965d6fSRomain Jobredeaux launcher_flags = utils.isolated_declare_file(ctx, "launcher.flag", sibling = launcher) 177*9e965d6fSRomain Jobredeaux 178*9e965d6fSRomain Jobredeaux runfiles.extend([launcher, launcher_flags]) 179*9e965d6fSRomain Jobredeaux 180*9e965d6fSRomain Jobredeaux runfiles.append(ctx.file._studio_deployer) 181*9e965d6fSRomain Jobredeaux if getattr(mi_app_info, "merged_manifest", None): 182*9e965d6fSRomain Jobredeaux runfiles.append(mi_app_info.merged_manifest) 183*9e965d6fSRomain Jobredeaux runfiles.append(mi_app_info.manifest_package_name) 184*9e965d6fSRomain Jobredeaux 185*9e965d6fSRomain Jobredeaux shell_apk = None 186*9e965d6fSRomain Jobredeaux if hasattr(mi_app_info, "shell_apk") and mi_app_info.shell_apk: 187*9e965d6fSRomain Jobredeaux shell_apk = mi_app_info.shell_apk 188*9e965d6fSRomain Jobredeaux app_pbs.append( 189*9e965d6fSRomain Jobredeaux make_generic_sync( 190*9e965d6fSRomain Jobredeaux ctx, 191*9e965d6fSRomain Jobredeaux files = [shell_apk], 192*9e965d6fSRomain Jobredeaux replacements = [ 193*9e965d6fSRomain Jobredeaux shell_apk.short_path[:shell_apk.short_path.rindex("/")], 194*9e965d6fSRomain Jobredeaux "apk", 195*9e965d6fSRomain Jobredeaux ], 196*9e965d6fSRomain Jobredeaux sibling = launcher, 197*9e965d6fSRomain Jobredeaux ), 198*9e965d6fSRomain Jobredeaux ) 199*9e965d6fSRomain Jobredeaux runfiles.append(mi_app_info.shell_apk) 200*9e965d6fSRomain Jobredeaux 201*9e965d6fSRomain Jobredeaux splits = None 202*9e965d6fSRomain Jobredeaux if hasattr(mi_app_info, "splits"): 203*9e965d6fSRomain Jobredeaux splits = mi_app_info.splits 204*9e965d6fSRomain Jobredeaux runfiles.extend(mi_app_info.splits) 205*9e965d6fSRomain Jobredeaux 206*9e965d6fSRomain Jobredeaux if hasattr(mi_app_info, "native_zip") and mi_app_info.native_zip: 207*9e965d6fSRomain Jobredeaux app_pbs.append(make_generic_sync(ctx, zips = [mi_app_info.native_zip], sibling = launcher)) 208*9e965d6fSRomain Jobredeaux runfiles.append(mi_app_info.native_zip) 209*9e965d6fSRomain Jobredeaux 210*9e965d6fSRomain Jobredeaux if hasattr(mi_app_info, "r_dex"): 211*9e965d6fSRomain Jobredeaux runfiles.append(mi_app_info.r_dex) 212*9e965d6fSRomain Jobredeaux app_pbs.append(make_dex_sync(ctx, mi_app_info.r_dex, dir_name = "rdexes", sibling = launcher)) 213*9e965d6fSRomain Jobredeaux 214*9e965d6fSRomain Jobredeaux if hasattr(mi_app_info, "merged_dex_shards"): 215*9e965d6fSRomain Jobredeaux runfiles.extend(mi_app_info.merged_dex_shards) 216*9e965d6fSRomain Jobredeaux bin_dex_sync = merge_syncs( 217*9e965d6fSRomain Jobredeaux ctx, 218*9e965d6fSRomain Jobredeaux [ 219*9e965d6fSRomain Jobredeaux make_dex_sync(ctx, dex_shard, sibling = launcher) 220*9e965d6fSRomain Jobredeaux for dex_shard in mi_app_info.merged_dex_shards 221*9e965d6fSRomain Jobredeaux ], 222*9e965d6fSRomain Jobredeaux "bin", 223*9e965d6fSRomain Jobredeaux sibling = launcher, 224*9e965d6fSRomain Jobredeaux ) 225*9e965d6fSRomain Jobredeaux app_pbs.append(bin_dex_sync) 226*9e965d6fSRomain Jobredeaux 227*9e965d6fSRomain Jobredeaux deploy_info_pb = None 228*9e965d6fSRomain Jobredeaux if hasattr(mi_app_info, "merged_manifest"): 229*9e965d6fSRomain Jobredeaux deploy_info_pb = make_deploy_info_pb( 230*9e965d6fSRomain Jobredeaux ctx, 231*9e965d6fSRomain Jobredeaux mi_app_info.merged_manifest, 232*9e965d6fSRomain Jobredeaux mi_app_info.splits if mi_app_info.splits else [mi_app_info.shell_apk], 233*9e965d6fSRomain Jobredeaux ) 234*9e965d6fSRomain Jobredeaux runfiles.append(deploy_info_pb) 235*9e965d6fSRomain Jobredeaux 236*9e965d6fSRomain Jobredeaux if test_data: 237*9e965d6fSRomain Jobredeaux runfiles.extend(test_data) 238*9e965d6fSRomain Jobredeaux if is_test: 239*9e965d6fSRomain Jobredeaux test_apk = mi_app_info.apk 240*9e965d6fSRomain Jobredeaux runfiles.append(test_apk) 241*9e965d6fSRomain Jobredeaux else: 242*9e965d6fSRomain Jobredeaux test_apk = None 243*9e965d6fSRomain Jobredeaux 244*9e965d6fSRomain Jobredeaux sync = utils.make_sync(ctx, app_pbs, mi_app_info.manifest_package_name, "app", sibling = launcher) 245*9e965d6fSRomain Jobredeaux runfiles.append(sync) 246*9e965d6fSRomain Jobredeaux 247*9e965d6fSRomain Jobredeaux sync_pbs = [] 248*9e965d6fSRomain Jobredeaux sync_pbs.append(sync) 249*9e965d6fSRomain Jobredeaux instrumented_app_package_name = None 250*9e965d6fSRomain Jobredeaux instrumented_app = None 251*9e965d6fSRomain Jobredeaux if hasattr(mi_app_info, "instrumented_app") and mi_app_info.instrumented_app: 252*9e965d6fSRomain Jobredeaux sync_pbs.append(mi_app_info.instrumented_app[MIAppLaunchInfo].sync) 253*9e965d6fSRomain Jobredeaux runfiles.extend(mi_app_info.instrumented_app[MIAppLaunchInfo].runfiles) 254*9e965d6fSRomain Jobredeaux instrumented_app_package_name = mi_app_info.instrumented_app[MIAppInfo].manifest_package_name 255*9e965d6fSRomain Jobredeaux 256*9e965d6fSRomain Jobredeaux if test_support_apps: 257*9e965d6fSRomain Jobredeaux for support_app in test_support_apps: 258*9e965d6fSRomain Jobredeaux if MIAppLaunchInfo in support_app: 259*9e965d6fSRomain Jobredeaux sync_pbs.append(support_app[MIAppLaunchInfo].sync) 260*9e965d6fSRomain Jobredeaux runfiles.extend(support_app[MIAppLaunchInfo].runfiles) 261*9e965d6fSRomain Jobredeaux 262*9e965d6fSRomain Jobredeaux if len(sync_pbs) > 1: 263*9e965d6fSRomain Jobredeaux final_sync_pb = utils.sync_merger(ctx, sync_pbs, sibling = launcher) 264*9e965d6fSRomain Jobredeaux runfiles.append(final_sync_pb) 265*9e965d6fSRomain Jobredeaux else: 266*9e965d6fSRomain Jobredeaux final_sync_pb = sync 267*9e965d6fSRomain Jobredeaux 268*9e965d6fSRomain Jobredeaux runfiles.extend(_make_app_runner( 269*9e965d6fSRomain Jobredeaux ctx, 270*9e965d6fSRomain Jobredeaux final_sync_pb, 271*9e965d6fSRomain Jobredeaux mi_app_info.manifest_package_name, 272*9e965d6fSRomain Jobredeaux launcher, 273*9e965d6fSRomain Jobredeaux launcher_flags, 274*9e965d6fSRomain Jobredeaux shell_apk = shell_apk, 275*9e965d6fSRomain Jobredeaux splits = splits, 276*9e965d6fSRomain Jobredeaux deploy_info_pb = deploy_info_pb, 277*9e965d6fSRomain Jobredeaux test_apk = test_apk, 278*9e965d6fSRomain Jobredeaux test_data = test_data, 279*9e965d6fSRomain Jobredeaux test_args = test_args, 280*9e965d6fSRomain Jobredeaux instrumented_app_package_name = instrumented_app_package_name, 281*9e965d6fSRomain Jobredeaux use_adb_root = use_adb_root, 282*9e965d6fSRomain Jobredeaux enable_metrics_logging = flags.get(ctx).enable_metrics_logging, 283*9e965d6fSRomain Jobredeaux use_studio_deployer = flags.get(ctx).use_studio_deployer, 284*9e965d6fSRomain Jobredeaux is_test = is_test, 285*9e965d6fSRomain Jobredeaux )) 286*9e965d6fSRomain Jobredeaux 287*9e965d6fSRomain Jobredeaux return MIAppLaunchInfo( 288*9e965d6fSRomain Jobredeaux launcher = launcher, 289*9e965d6fSRomain Jobredeaux launcher_flags = launcher_flags, 290*9e965d6fSRomain Jobredeaux runfiles = runfiles, 291*9e965d6fSRomain Jobredeaux sync = sync, 292*9e965d6fSRomain Jobredeaux ) 293