xref: /aosp_15_r20/external/bazelbuild-rules_android/mobile_install/launcher.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
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(":deploy_info.bzl", "make_deploy_info_pb")
17*9e965d6fSRomain Jobredeauxload(":providers.bzl", "MIAppInfo", "MIAppLaunchInfo")
18*9e965d6fSRomain Jobredeauxload(":utils.bzl", "utils")
19*9e965d6fSRomain Jobredeauxload(":workspace.bzl", "make_dex_sync", "make_generic_sync", "merge_syncs")
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 JobredeauxAPP_FLAGS={app_flags}
29*9e965d6fSRomain JobredeauxGOOGPLAYSRVCS_CONTAINER_FLAGS={googplayservices_container_flags}
30*9e965d6fSRomain JobredeauxTEST_FLAGS={test_flags}
31*9e965d6fSRomain JobredeauxDEPLOY={deploy}
32*9e965d6fSRomain Jobredeaux
33*9e965d6fSRomain JobredeauxALL_TEST_ARGS=("$@")
34*9e965d6fSRomain Jobredeauxif [[ ! -z ${{TEST_FLAGS}} ]]; then
35*9e965d6fSRomain Jobredeaux  RULE_TEST_ARGS={test_args}
36*9e965d6fSRomain Jobredeaux  ALL_TEST_ARGS=("--nolaunch_app" "${{RULE_TEST_ARGS[@]}}" "$@")
37*9e965d6fSRomain Jobredeauxfi
38*9e965d6fSRomain Jobredeaux
39*9e965d6fSRomain Jobredeauxif [[ ! -z ${{GOOGPLAYSRVCS_CONTAINER_FLAGS}} ]]; then
40*9e965d6fSRomain Jobredeaux  "${{DEPLOY}}" \
41*9e965d6fSRomain Jobredeaux      -flagfile="${{GOOGPLAYSRVCS_CONTAINER_FLAGS}}" \
42*9e965d6fSRomain Jobredeaux        "${{ALL_TEST_ARGS[@]}}"
43*9e965d6fSRomain Jobredeauxfi
44*9e965d6fSRomain Jobredeaux
45*9e965d6fSRomain Jobredeauxif [[ ! -z ${{APP_FLAGS}} ]]; then
46*9e965d6fSRomain Jobredeaux  "${{DEPLOY}}" \
47*9e965d6fSRomain Jobredeaux      -flagfile="${{APP_FLAGS}}" \
48*9e965d6fSRomain Jobredeaux      "${{ALL_TEST_ARGS[@]}}"
49*9e965d6fSRomain Jobredeauxfi
50*9e965d6fSRomain Jobredeaux
51*9e965d6fSRomain Jobredeauxif [[ ! -z ${{TEST_FLAGS}} ]]; then
52*9e965d6fSRomain Jobredeaux  "${{DEPLOY}}" \
53*9e965d6fSRomain Jobredeaux      -flagfile="${{TEST_FLAGS}}" \
54*9e965d6fSRomain Jobredeaux      --is_test=true \
55*9e965d6fSRomain Jobredeaux      "${{ALL_TEST_ARGS[@]}}"
56*9e965d6fSRomain Jobredeauxfi
57*9e965d6fSRomain Jobredeaux'''
58*9e965d6fSRomain Jobredeaux
59*9e965d6fSRomain Jobredeauxdef _make_deploy_script(
60*9e965d6fSRomain Jobredeaux        ctx,
61*9e965d6fSRomain Jobredeaux        out_script,
62*9e965d6fSRomain Jobredeaux        deploy,
63*9e965d6fSRomain Jobredeaux        app_flags = "",
64*9e965d6fSRomain Jobredeaux        googplayservices_container_flags = "",
65*9e965d6fSRomain Jobredeaux        test_flags = "",
66*9e965d6fSRomain Jobredeaux        test_args = ""):
67*9e965d6fSRomain Jobredeaux    deploy_contents = _DEPLOY_SCRIPT.format(
68*9e965d6fSRomain Jobredeaux        app_flags = app_flags,
69*9e965d6fSRomain Jobredeaux        googplayservices_container_flags = googplayservices_container_flags,
70*9e965d6fSRomain Jobredeaux        deploy = deploy,
71*9e965d6fSRomain Jobredeaux        test_flags = test_flags,
72*9e965d6fSRomain Jobredeaux        test_args = test_args,
73*9e965d6fSRomain Jobredeaux    )
74*9e965d6fSRomain Jobredeaux    ctx.actions.write(out_script, deploy_contents, is_executable = True)
75*9e965d6fSRomain Jobredeaux
76*9e965d6fSRomain Jobredeauxdef _make_app_runner(
77*9e965d6fSRomain Jobredeaux        ctx,
78*9e965d6fSRomain Jobredeaux        data_sync,
79*9e965d6fSRomain Jobredeaux        manifest_package_name_path,
80*9e965d6fSRomain Jobredeaux        out_launcher,
81*9e965d6fSRomain Jobredeaux        out_launcher_flags,
82*9e965d6fSRomain Jobredeaux        shell_apk = None,
83*9e965d6fSRomain Jobredeaux        splits = None,
84*9e965d6fSRomain Jobredeaux        deploy_info_pb = None,
85*9e965d6fSRomain Jobredeaux        test_apk = None,
86*9e965d6fSRomain Jobredeaux        test_support_apks = None,
87*9e965d6fSRomain Jobredeaux        test_data = None,
88*9e965d6fSRomain Jobredeaux        test_args = None,
89*9e965d6fSRomain Jobredeaux        instrumented_app = None,
90*9e965d6fSRomain Jobredeaux        googplayservices_container_app = None,
91*9e965d6fSRomain Jobredeaux        use_adb_root = True,
92*9e965d6fSRomain Jobredeaux        enable_metrics_logging = False,
93*9e965d6fSRomain Jobredeaux        is_test = False):
94*9e965d6fSRomain Jobredeaux    path_type = "path" if ctx.attr._mi_is_cmd else "short_path"
95*9e965d6fSRomain Jobredeaux
96*9e965d6fSRomain Jobredeaux    deploy = utils.first(ctx.attr._deploy.files.to_list())
97*9e965d6fSRomain Jobredeaux
98*9e965d6fSRomain Jobredeaux    args = {
99*9e965d6fSRomain Jobredeaux        "data_sync_path": getattr(data_sync, path_type),
100*9e965d6fSRomain Jobredeaux        "is_cmd": str(ctx.attr._mi_is_cmd).lower(),
101*9e965d6fSRomain Jobredeaux        "manifest_package_name_path": getattr(manifest_package_name_path, path_type),
102*9e965d6fSRomain Jobredeaux        "target": ctx.label,
103*9e965d6fSRomain Jobredeaux    }
104*9e965d6fSRomain Jobredeaux    if shell_apk:
105*9e965d6fSRomain Jobredeaux        args["shell_app_path"] = getattr(shell_apk, path_type)
106*9e965d6fSRomain Jobredeaux
107*9e965d6fSRomain Jobredeaux    if splits:
108*9e965d6fSRomain Jobredeaux        args["splits"] = [getattr(s, path_type) for s in splits]
109*9e965d6fSRomain Jobredeaux        args["enable_splits"] = True
110*9e965d6fSRomain Jobredeaux
111*9e965d6fSRomain Jobredeaux    if ctx.attr._mi_is_cmd:
112*9e965d6fSRomain Jobredeaux        args["host_test_runner_workspace"] = HOST_TEST_WORKSPACE
113*9e965d6fSRomain Jobredeaux    if test_support_apks or test_apk:
114*9e965d6fSRomain Jobredeaux        args["apks"] = ",".join([apk.short_path for apk in [test_apk] + test_support_apks])
115*9e965d6fSRomain Jobredeaux
116*9e965d6fSRomain Jobredeaux    args["java_home"] = utils.host_jvm_path(ctx)
117*9e965d6fSRomain Jobredeaux
118*9e965d6fSRomain Jobredeaux    args["studio_deployer"] = getattr(ctx.file._studio_deployer, path_type)
119*9e965d6fSRomain Jobredeaux    args["use_adb_root"] = str(use_adb_root).lower()
120*9e965d6fSRomain Jobredeaux    args["enable_metrics_logging"] = str(enable_metrics_logging).lower()
121*9e965d6fSRomain Jobredeaux
122*9e965d6fSRomain Jobredeaux    android_test_runner = None
123*9e965d6fSRomain Jobredeaux    if is_test and hasattr(ctx.attr, "_android_test_runner"):
124*9e965d6fSRomain Jobredeaux        android_test_runner = ctx.file._android_test_runner
125*9e965d6fSRomain Jobredeaux        args["android_test_runner"] = getattr(android_test_runner, path_type)
126*9e965d6fSRomain Jobredeaux
127*9e965d6fSRomain Jobredeaux    if test_data:
128*9e965d6fSRomain Jobredeaux        args["data_files"] = ",".join([f.short_path for f in test_data])
129*9e965d6fSRomain Jobredeaux
130*9e965d6fSRomain Jobredeaux    if test_apk:
131*9e965d6fSRomain Jobredeaux        args["test_apk"] = test_apk.path
132*9e965d6fSRomain Jobredeaux
133*9e965d6fSRomain Jobredeaux    if deploy_info_pb:
134*9e965d6fSRomain Jobredeaux        args["deploy_info"] = getattr(deploy_info_pb, path_type)
135*9e965d6fSRomain Jobredeaux
136*9e965d6fSRomain Jobredeaux    utils.create_flag_file(ctx, out_launcher_flags, **args)
137*9e965d6fSRomain Jobredeaux
138*9e965d6fSRomain Jobredeaux    _make_deploy_script(
139*9e965d6fSRomain Jobredeaux        ctx,
140*9e965d6fSRomain Jobredeaux        out_launcher,
141*9e965d6fSRomain Jobredeaux        getattr(deploy, path_type),
142*9e965d6fSRomain Jobredeaux        app_flags = (
143*9e965d6fSRomain Jobredeaux            getattr(instrumented_app[MIAppLaunchInfo].launcher_flags, path_type) if instrumented_app else getattr(out_launcher_flags, path_type)
144*9e965d6fSRomain Jobredeaux        ),
145*9e965d6fSRomain Jobredeaux        googplayservices_container_flags = (
146*9e965d6fSRomain Jobredeaux            getattr(googplayservices_container_app[MIAppLaunchInfo].launcher_flags, path_type) if googplayservices_container_app else ""
147*9e965d6fSRomain Jobredeaux        ),
148*9e965d6fSRomain Jobredeaux        # Converts the python array of args into a bash array. Each arg is
149*9e965d6fSRomain Jobredeaux        # wrapped with quotes to handle "space" separted flag value entries
150*9e965d6fSRomain Jobredeaux        # and as result also escapes existing quotes.
151*9e965d6fSRomain Jobredeaux        test_args = ("(%s)" % " ".join([
152*9e965d6fSRomain Jobredeaux            '"--test_arg=%s"' % arg.replace('"', '\\"')
153*9e965d6fSRomain Jobredeaux            for arg in test_args
154*9e965d6fSRomain Jobredeaux        ])) if test_args else "",
155*9e965d6fSRomain Jobredeaux        test_flags = getattr(out_launcher_flags, path_type) if test_args or is_test else "",
156*9e965d6fSRomain Jobredeaux    )
157*9e965d6fSRomain Jobredeaux
158*9e965d6fSRomain Jobredeaux    runner = [deploy]
159*9e965d6fSRomain Jobredeaux    if android_test_runner:
160*9e965d6fSRomain Jobredeaux        runner.extend(ctx.attr._java_jdk.files.to_list())
161*9e965d6fSRomain Jobredeaux        runner.append(android_test_runner)
162*9e965d6fSRomain Jobredeaux    return runner
163*9e965d6fSRomain Jobredeaux
164*9e965d6fSRomain Jobredeauxdef make_launcher(
165*9e965d6fSRomain Jobredeaux        ctx,
166*9e965d6fSRomain Jobredeaux        mi_app_info,
167*9e965d6fSRomain Jobredeaux        launcher,
168*9e965d6fSRomain Jobredeaux        test_data = None,
169*9e965d6fSRomain Jobredeaux        test_args = None,
170*9e965d6fSRomain Jobredeaux        test_support_apks = None,
171*9e965d6fSRomain Jobredeaux        googplayservices_container_app = None,
172*9e965d6fSRomain Jobredeaux        use_adb_root = True,
173*9e965d6fSRomain Jobredeaux        is_test = False):
174*9e965d6fSRomain Jobredeaux    """ Runfiles for launching the apps are created.
175*9e965d6fSRomain Jobredeaux
176*9e965d6fSRomain Jobredeaux    Args:
177*9e965d6fSRomain Jobredeaux        ctx: The context
178*9e965d6fSRomain Jobredeaux        mi_app_info: The MIAppInfo provider
179*9e965d6fSRomain Jobredeaux        launcher: The launcher file
180*9e965d6fSRomain Jobredeaux        test_data: The test data
181*9e965d6fSRomain Jobredeaux        test_support_apks: The test support apks
182*9e965d6fSRomain Jobredeaux        test_args: The test arguments
183*9e965d6fSRomain Jobredeaux        googplayservices_container_app: The Google Play Services container app
184*9e965d6fSRomain Jobredeaux        use_adb_root: Boolean argument to restart adb with root permissions.
185*9e965d6fSRomain Jobredeaux        is_test: Boolean argument to identify if it's a test
186*9e965d6fSRomain Jobredeaux    Returns:
187*9e965d6fSRomain Jobredeaux        A list of files required for runtime common for both running binary and test.
188*9e965d6fSRomain Jobredeaux    """
189*9e965d6fSRomain Jobredeaux    sync_pbs = []
190*9e965d6fSRomain Jobredeaux    runfiles = []
191*9e965d6fSRomain Jobredeaux
192*9e965d6fSRomain Jobredeaux    launcher_flags = utils.isolated_declare_file(ctx, "launcher.flag", sibling = launcher)
193*9e965d6fSRomain Jobredeaux
194*9e965d6fSRomain Jobredeaux    runfiles.extend([launcher, launcher_flags])
195*9e965d6fSRomain Jobredeaux
196*9e965d6fSRomain Jobredeaux    runfiles.append(ctx.file._studio_deployer)
197*9e965d6fSRomain Jobredeaux    if getattr(mi_app_info, "merged_manifest", None):
198*9e965d6fSRomain Jobredeaux        runfiles.append(mi_app_info.merged_manifest)
199*9e965d6fSRomain Jobredeaux    runfiles.append(mi_app_info.manifest_package_name)
200*9e965d6fSRomain Jobredeaux    shell_apk = None
201*9e965d6fSRomain Jobredeaux    splits = None
202*9e965d6fSRomain Jobredeaux    if not is_test:
203*9e965d6fSRomain Jobredeaux        if hasattr(mi_app_info, "shell_apk"):
204*9e965d6fSRomain Jobredeaux            shell_apk = mi_app_info.shell_apk
205*9e965d6fSRomain Jobredeaux            runfiles.append(mi_app_info.shell_apk)
206*9e965d6fSRomain Jobredeaux
207*9e965d6fSRomain Jobredeaux        if hasattr(mi_app_info, "splits"):
208*9e965d6fSRomain Jobredeaux            splits = mi_app_info.splits
209*9e965d6fSRomain Jobredeaux            runfiles.extend(mi_app_info.splits)
210*9e965d6fSRomain Jobredeaux
211*9e965d6fSRomain Jobredeaux        if hasattr(mi_app_info, "native_zip") and mi_app_info.native_zip:
212*9e965d6fSRomain Jobredeaux            sync_pbs.append(make_generic_sync(ctx, zips = [mi_app_info.native_zip], sibling = launcher))
213*9e965d6fSRomain Jobredeaux            runfiles.append(mi_app_info.native_zip)
214*9e965d6fSRomain Jobredeaux
215*9e965d6fSRomain Jobredeaux        if hasattr(mi_app_info, "r_dex"):
216*9e965d6fSRomain Jobredeaux            runfiles.append(mi_app_info.r_dex)
217*9e965d6fSRomain Jobredeaux            sync_pbs.append(make_dex_sync(ctx, mi_app_info.r_dex, dir_name = "rdexes", sibling = launcher))
218*9e965d6fSRomain Jobredeaux
219*9e965d6fSRomain Jobredeaux    if hasattr(mi_app_info, "merged_dex_shards"):
220*9e965d6fSRomain Jobredeaux        runfiles.extend(mi_app_info.merged_dex_shards)
221*9e965d6fSRomain Jobredeaux        bin_dex_sync = merge_syncs(
222*9e965d6fSRomain Jobredeaux            ctx,
223*9e965d6fSRomain Jobredeaux            [
224*9e965d6fSRomain Jobredeaux                make_dex_sync(ctx, dex_shard, sibling = launcher)
225*9e965d6fSRomain Jobredeaux                for dex_shard in mi_app_info.merged_dex_shards
226*9e965d6fSRomain Jobredeaux            ],
227*9e965d6fSRomain Jobredeaux            "bin",
228*9e965d6fSRomain Jobredeaux            sibling = launcher,
229*9e965d6fSRomain Jobredeaux        )
230*9e965d6fSRomain Jobredeaux        sync_pbs.append(bin_dex_sync)
231*9e965d6fSRomain Jobredeaux
232*9e965d6fSRomain Jobredeaux    instrumented_app = None
233*9e965d6fSRomain Jobredeaux    if hasattr(mi_app_info, "instrumented_app") and mi_app_info.instrumented_app:
234*9e965d6fSRomain Jobredeaux        instrumented_app = mi_app_info.instrumented_app
235*9e965d6fSRomain Jobredeaux        runfiles.extend(mi_app_info.instrumented_app[MIAppInfo].merged_dex_shards)
236*9e965d6fSRomain Jobredeaux
237*9e965d6fSRomain Jobredeaux        # Add the binary under test dex shards to find additional tests.
238*9e965d6fSRomain Jobredeaux        but_dex_sync = merge_syncs(
239*9e965d6fSRomain Jobredeaux            ctx,
240*9e965d6fSRomain Jobredeaux            [
241*9e965d6fSRomain Jobredeaux                make_dex_sync(ctx, dex_shard, sibling = launcher)
242*9e965d6fSRomain Jobredeaux                for dex_shard in mi_app_info.instrumented_app[MIAppInfo].merged_dex_shards
243*9e965d6fSRomain Jobredeaux            ],
244*9e965d6fSRomain Jobredeaux            "but",
245*9e965d6fSRomain Jobredeaux            sibling = launcher,
246*9e965d6fSRomain Jobredeaux        )
247*9e965d6fSRomain Jobredeaux        sync_pbs.append(but_dex_sync)
248*9e965d6fSRomain Jobredeaux
249*9e965d6fSRomain Jobredeaux    if test_data:
250*9e965d6fSRomain Jobredeaux        runfiles.extend(test_data)
251*9e965d6fSRomain Jobredeaux    if test_support_apks:
252*9e965d6fSRomain Jobredeaux        runfiles.extend(test_support_apks)
253*9e965d6fSRomain Jobredeaux    if is_test:
254*9e965d6fSRomain Jobredeaux        test_apk = mi_app_info.apk
255*9e965d6fSRomain Jobredeaux        runfiles.append(test_apk)
256*9e965d6fSRomain Jobredeaux    else:
257*9e965d6fSRomain Jobredeaux        test_apk = None
258*9e965d6fSRomain Jobredeaux
259*9e965d6fSRomain Jobredeaux    if hasattr(mi_app_info, "shell_apk") and mi_app_info.shell_apk and not is_test:
260*9e965d6fSRomain Jobredeaux        sync_pbs.append(
261*9e965d6fSRomain Jobredeaux            make_generic_sync(
262*9e965d6fSRomain Jobredeaux                ctx,
263*9e965d6fSRomain Jobredeaux                files = [mi_app_info.shell_apk],
264*9e965d6fSRomain Jobredeaux                replacements = [
265*9e965d6fSRomain Jobredeaux                    mi_app_info.shell_apk.short_path[:mi_app_info.shell_apk.short_path.rindex("/")],
266*9e965d6fSRomain Jobredeaux                    "apk",
267*9e965d6fSRomain Jobredeaux                ],
268*9e965d6fSRomain Jobredeaux                sibling = launcher,
269*9e965d6fSRomain Jobredeaux            ),
270*9e965d6fSRomain Jobredeaux        )
271*9e965d6fSRomain Jobredeaux    deploy_info_pb = None
272*9e965d6fSRomain Jobredeaux    if hasattr(mi_app_info, "merged_manifest"):
273*9e965d6fSRomain Jobredeaux        deploy_info_pb = make_deploy_info_pb(
274*9e965d6fSRomain Jobredeaux            ctx,
275*9e965d6fSRomain Jobredeaux            mi_app_info.merged_manifest,
276*9e965d6fSRomain Jobredeaux            mi_app_info.splits if mi_app_info.splits else [mi_app_info.shell_apk],
277*9e965d6fSRomain Jobredeaux        )
278*9e965d6fSRomain Jobredeaux        runfiles.append(deploy_info_pb)
279*9e965d6fSRomain Jobredeaux
280*9e965d6fSRomain Jobredeaux    final_sync_pb = None
281*9e965d6fSRomain Jobredeaux
282*9e965d6fSRomain Jobredeaux    # Create the final sync pb.
283*9e965d6fSRomain Jobredeaux    if ctx.var.get("use_direct_deploy"):
284*9e965d6fSRomain Jobredeaux        final_sync_pb = utils.make_sync(ctx, sync_pbs, mi_app_info.manifest_package_name, "app", sibling = launcher)
285*9e965d6fSRomain Jobredeaux    else:
286*9e965d6fSRomain Jobredeaux        final_sync_pb = merge_syncs(ctx, sync_pbs, "app", sibling = launcher)
287*9e965d6fSRomain Jobredeaux    runfiles.append(final_sync_pb)
288*9e965d6fSRomain Jobredeaux
289*9e965d6fSRomain Jobredeaux    runfiles.extend(_make_app_runner(
290*9e965d6fSRomain Jobredeaux        ctx,
291*9e965d6fSRomain Jobredeaux        final_sync_pb,
292*9e965d6fSRomain Jobredeaux        mi_app_info.manifest_package_name,
293*9e965d6fSRomain Jobredeaux        launcher,
294*9e965d6fSRomain Jobredeaux        launcher_flags,
295*9e965d6fSRomain Jobredeaux        shell_apk = shell_apk,
296*9e965d6fSRomain Jobredeaux        splits = splits,
297*9e965d6fSRomain Jobredeaux        deploy_info_pb = deploy_info_pb,
298*9e965d6fSRomain Jobredeaux        test_apk = test_apk,
299*9e965d6fSRomain Jobredeaux        test_support_apks = test_support_apks,
300*9e965d6fSRomain Jobredeaux        test_data = test_data,
301*9e965d6fSRomain Jobredeaux        test_args = test_args,
302*9e965d6fSRomain Jobredeaux        instrumented_app = instrumented_app,
303*9e965d6fSRomain Jobredeaux        googplayservices_container_app = googplayservices_container_app,
304*9e965d6fSRomain Jobredeaux        use_adb_root = use_adb_root,
305*9e965d6fSRomain Jobredeaux        enable_metrics_logging = flags.get(ctx).enable_metrics_logging,
306*9e965d6fSRomain Jobredeaux        is_test = is_test,
307*9e965d6fSRomain Jobredeaux    ))
308*9e965d6fSRomain Jobredeaux
309*9e965d6fSRomain Jobredeaux    # Collect launcher details for additional apps
310*9e965d6fSRomain Jobredeaux    mi_app_launch_infos = []
311*9e965d6fSRomain Jobredeaux    if instrumented_app:
312*9e965d6fSRomain Jobredeaux        mi_app_launch_infos.append(mi_app_info.instrumented_app[MIAppLaunchInfo])
313*9e965d6fSRomain Jobredeaux    if googplayservices_container_app:
314*9e965d6fSRomain Jobredeaux        mi_app_launch_infos.append(googplayservices_container_app[MIAppLaunchInfo])
315*9e965d6fSRomain Jobredeaux
316*9e965d6fSRomain Jobredeaux    # Append the additional launch and launcher flags.
317*9e965d6fSRomain Jobredeaux    if mi_app_launch_infos:
318*9e965d6fSRomain Jobredeaux        for mi_app_launch_info in mi_app_launch_infos:
319*9e965d6fSRomain Jobredeaux            runfiles.append(mi_app_launch_info.launcher_flags)
320*9e965d6fSRomain Jobredeaux            runfiles.extend(mi_app_launch_info.runfiles)
321*9e965d6fSRomain Jobredeaux
322*9e965d6fSRomain Jobredeaux    return MIAppLaunchInfo(
323*9e965d6fSRomain Jobredeaux        launcher = launcher,
324*9e965d6fSRomain Jobredeaux        launcher_flags = launcher_flags,
325*9e965d6fSRomain Jobredeaux        runfiles = runfiles,
326*9e965d6fSRomain Jobredeaux    )
327