blob: f5a5da01beafe032ee7623f2a55c803b6c95bffc [file] [log] [blame]
Colin Cross30e076a2015-04-13 13:58:27 -07001// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17// This file contains the module types for compiling Android apps.
18
19import (
Jaewoong Junga5e5abc2019-04-26 14:31:50 -070020 "path/filepath"
21 "reflect"
Jaewoong Jung5b425e22019-06-17 17:40:56 -070022 "sort"
Jaewoong Junga5e5abc2019-04-26 14:31:50 -070023 "strings"
Colin Cross30e076a2015-04-13 13:58:27 -070024
Colin Cross50ddcc42019-05-16 12:28:22 -070025 "github.com/google/blueprint"
26 "github.com/google/blueprint/proptools"
27
Colin Cross635c3b02016-05-18 15:37:25 -070028 "android/soong/android"
Colin Crossa4f08812018-10-02 22:03:40 -070029 "android/soong/cc"
Colin Cross303e21f2018-08-07 16:49:25 -070030 "android/soong/tradefed"
Colin Cross30e076a2015-04-13 13:58:27 -070031)
32
Jaewoong Jung3e18b192019-06-11 12:25:34 -070033var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
Jaewoong Junga5e5abc2019-04-26 14:31:50 -070034
Colin Cross3bc7ffa2017-11-22 16:19:37 -080035func init() {
Colin Cross5ab4e6d2017-11-22 16:20:45 -080036 android.RegisterModuleType("android_app", AndroidAppFactory)
Colin Crossae5caf52018-05-22 11:11:52 -070037 android.RegisterModuleType("android_test", AndroidTestFactory)
Colin Cross252fc6f2018-10-04 15:22:03 -070038 android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
Colin Crossbd01e2a2018-10-04 15:21:03 -070039 android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
Jaewoong Jung525443a2019-02-28 15:35:54 -080040 android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
Jaewoong Jungccbb3932019-04-15 09:48:31 -070041 android.RegisterModuleType("android_app_import", AndroidAppImportFactory)
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -070042
43 initAndroidAppImportVariantGroupTypes()
Colin Cross3bc7ffa2017-11-22 16:19:37 -080044}
45
Colin Cross30e076a2015-04-13 13:58:27 -070046// AndroidManifest.xml merging
47// package splits
48
Colin Crossfabb6082018-02-20 17:22:23 -080049type appProperties struct {
Colin Crossbd01e2a2018-10-04 15:21:03 -070050 // Names of extra android_app_certificate modules to sign the apk with in the form ":module".
Colin Cross7d5136f2015-05-11 13:39:40 -070051 Additional_certificates []string
52
53 // If set, create package-export.apk, which other packages can
54 // use to get PRODUCT-agnostic resource data like IDs and type definitions.
Nan Zhangea568a42017-11-08 21:20:04 -080055 Export_package_resources *bool
Colin Cross7d5136f2015-05-11 13:39:40 -070056
Colin Cross16056062017-12-13 22:46:28 -080057 // Specifies that this app should be installed to the priv-app directory,
58 // where the system will grant it additional privileges not available to
59 // normal apps.
60 Privileged *bool
Colin Crossa97c5d32018-03-28 14:58:31 -070061
62 // list of resource labels to generate individual resource packages
63 Package_splits []string
Jason Monkd4122be2018-08-10 09:33:36 -040064
65 // Names of modules to be overridden. Listed modules can only be other binaries
66 // (in Make or Soong).
67 // This does not completely prevent installation of the overridden binaries, but if both
68 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
69 // from PRODUCT_PACKAGES.
70 Overrides []string
Colin Crossa4f08812018-10-02 22:03:40 -070071
72 // list of native libraries that will be provided in or alongside the resulting jar
73 Jni_libs []string `android:"arch_variant"`
74
Jaewoong Jungbc625cd2019-05-06 15:48:44 -070075 // STL library to use for JNI libraries.
76 Stl *string `android:"arch_variant"`
77
Colin Crosse4246ab2019-02-05 21:55:21 -080078 // Store native libraries uncompressed in the APK and set the android:extractNativeLibs="false" manifest
79 // flag so that they are used from inside the APK at runtime. Defaults to true for android_test modules unless
80 // sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to false for other
81 // module types where the native libraries are generally preinstalled outside the APK.
82 Use_embedded_native_libs *bool
Colin Cross46abdad2019-02-07 13:07:08 -080083
84 // Store dex files uncompressed in the APK and set the android:useEmbeddedDex="true" manifest attribute so that
85 // they are used from inside the APK at runtime.
86 Use_embedded_dex *bool
Colin Cross47fa9d32019-03-26 10:51:39 -070087
88 // Forces native libraries to always be packaged into the APK,
89 // Use_embedded_native_libs still selects whether they are stored uncompressed and aligned or compressed.
90 // True for android_test* modules.
91 AlwaysPackageNativeLibs bool `blueprint:"mutated"`
Jaewoong Jung5b425e22019-06-17 17:40:56 -070092
93 // If set, find and merge all NOTICE files that this module and its dependencies have and store
94 // it in the APK as an asset.
95 Embed_notices *bool
Colin Cross7d5136f2015-05-11 13:39:40 -070096}
97
Jaewoong Jung525443a2019-02-28 15:35:54 -080098// android_app properties that can be overridden by override_android_app
99type overridableAppProperties struct {
100 // The name of a certificate in the default certificate directory, blank to use the default product certificate,
101 // or an android_app_certificate module name in the form ":module".
102 Certificate *string
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700103
104 // the package name of this app. The package name in the manifest file is used if one was not given.
105 Package_name *string
Jaewoong Jung525443a2019-02-28 15:35:54 -0800106}
107
Colin Cross30e076a2015-04-13 13:58:27 -0700108type AndroidApp struct {
Colin Crossa97c5d32018-03-28 14:58:31 -0700109 Library
110 aapt
Jaewoong Jung525443a2019-02-28 15:35:54 -0800111 android.OverridableModuleBase
Colin Crossa97c5d32018-03-28 14:58:31 -0700112
Colin Cross50ddcc42019-05-16 12:28:22 -0700113 usesLibrary usesLibrary
114
Jiyong Parkc00cbd92018-10-30 21:20:05 +0900115 certificate Certificate
Colin Cross30e076a2015-04-13 13:58:27 -0700116
Colin Crossfabb6082018-02-20 17:22:23 -0800117 appProperties appProperties
Colin Crossae5caf52018-05-22 11:11:52 -0700118
Jaewoong Jung525443a2019-02-28 15:35:54 -0800119 overridableAppProperties overridableAppProperties
120
Colin Crossa4f08812018-10-02 22:03:40 -0700121 installJniLibs []jniLib
Colin Crossf6237212018-10-29 23:14:58 -0700122
123 bundleFile android.Path
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800124
125 // the install APK name is normally the same as the module name, but can be overridden with PRODUCT_PACKAGE_NAME_OVERRIDES.
126 installApkName string
Jaewoong Jung4102e5d2019-02-27 16:26:28 -0800127
128 additionalAaptFlags []string
Jaewoong Jung98772792019-07-01 17:15:13 -0700129
130 noticeOutputs android.NoticeOutputs
Colin Crosse1731a52017-12-14 11:22:55 -0800131}
132
Colin Cross89c31582018-04-30 15:55:11 -0700133func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
134 return nil
135}
136
Colin Cross66f78822018-05-02 12:58:28 -0700137func (a *AndroidApp) ExportedStaticPackages() android.Paths {
138 return nil
139}
140
Colin Crossa97c5d32018-03-28 14:58:31 -0700141var _ AndroidLibraryDependency = (*AndroidApp)(nil)
142
Jiyong Parkc00cbd92018-10-30 21:20:05 +0900143type Certificate struct {
144 Pem, Key android.Path
Colin Cross30e076a2015-04-13 13:58:27 -0700145}
146
Colin Cross46c9b8b2017-06-22 16:51:17 -0700147func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
148 a.Module.deps(ctx)
Colin Crossa4f08812018-10-02 22:03:40 -0700149
Jaewoong Jungbc625cd2019-05-06 15:48:44 -0700150 if String(a.appProperties.Stl) == "c++_shared" && a.sdkVersion() == "" {
151 ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
152 }
153
Paul Duffin250e6192019-06-07 10:44:37 +0100154 sdkDep := decodeSdkDep(ctx, sdkContext(a))
155 if sdkDep.hasFrameworkLibs() {
156 a.aapt.deps(ctx, sdkDep)
Colin Cross30e076a2015-04-13 13:58:27 -0700157 }
Colin Crossa4f08812018-10-02 22:03:40 -0700158
Jaewoong Jungbc625cd2019-05-06 15:48:44 -0700159 embedJni := a.shouldEmbedJnis(ctx)
Colin Crossa4f08812018-10-02 22:03:40 -0700160 for _, jniTarget := range ctx.MultiTargets() {
161 variation := []blueprint.Variation{
162 {Mutator: "arch", Variation: jniTarget.String()},
163 {Mutator: "link", Variation: "shared"},
164 }
165 tag := &jniDependencyTag{
166 target: jniTarget,
167 }
168 ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
Jaewoong Jungbc625cd2019-05-06 15:48:44 -0700169 if String(a.appProperties.Stl) == "c++_shared" {
170 if embedJni {
Jaewoong Jung710756a2019-06-04 11:53:47 -0700171 ctx.AddFarVariationDependencies(variation, tag, "ndk_libc++_shared")
Jaewoong Jungbc625cd2019-05-06 15:48:44 -0700172 }
173 }
Colin Crossa4f08812018-10-02 22:03:40 -0700174 }
Colin Cross50ddcc42019-05-16 12:28:22 -0700175
Paul Duffin250e6192019-06-07 10:44:37 +0100176 a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700177}
Colin Crossbd01e2a2018-10-04 15:21:03 -0700178
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700179func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800180 cert := android.SrcIsModule(a.getCertString(ctx))
Colin Crossbd01e2a2018-10-04 15:21:03 -0700181 if cert != "" {
182 ctx.AddDependency(ctx.Module(), certificateTag, cert)
183 }
184
185 for _, cert := range a.appProperties.Additional_certificates {
186 cert = android.SrcIsModule(cert)
187 if cert != "" {
188 ctx.AddDependency(ctx.Module(), certificateTag, cert)
189 } else {
190 ctx.PropertyErrorf("additional_certificates",
191 `must be names of android_app_certificate modules in the form ":module"`)
192 }
193 }
Colin Cross30e076a2015-04-13 13:58:27 -0700194}
195
Jeongik Cha538c0d02019-07-11 15:54:27 +0900196func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
197 a.generateAndroidBuildActions(ctx)
198}
199
Colin Cross46c9b8b2017-06-22 16:51:17 -0700200func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Jeongik Cha538c0d02019-07-11 15:54:27 +0900201 a.checkPlatformAPI(ctx)
Colin Crossae5caf52018-05-22 11:11:52 -0700202 a.generateAndroidBuildActions(ctx)
203}
204
Sasha Smundak6ad77252019-05-01 13:16:22 -0700205// Returns true if the native libraries should be stored in the APK uncompressed and the
Colin Crosse4246ab2019-02-05 21:55:21 -0800206// extractNativeLibs application flag should be set to false in the manifest.
Sasha Smundak6ad77252019-05-01 13:16:22 -0700207func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
Colin Crosse4246ab2019-02-05 21:55:21 -0800208 minSdkVersion, err := sdkVersionToNumber(ctx, a.minSdkVersion())
209 if err != nil {
210 ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.minSdkVersion(), err)
211 }
212
213 return minSdkVersion >= 23 && Bool(a.appProperties.Use_embedded_native_libs)
214}
215
Colin Cross43f08db2018-11-12 10:13:39 -0800216// Returns whether this module should have the dex file stored uncompressed in the APK.
217func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool {
Colin Cross46abdad2019-02-07 13:07:08 -0800218 if Bool(a.appProperties.Use_embedded_dex) {
219 return true
220 }
221
Colin Cross53a87f52019-06-25 13:35:30 -0700222 // Uncompress dex in APKs of privileged apps (even for unbundled builds, they may
223 // be preinstalled as prebuilts).
Jaewoong Jungacf18d72019-05-02 14:55:29 -0700224 if ctx.Config().UncompressPrivAppDex() && Bool(a.appProperties.Privileged) {
Nicolas Geoffrayfa6e9ec2019-02-12 13:12:16 +0000225 return true
226 }
227
Colin Cross53a87f52019-06-25 13:35:30 -0700228 if ctx.Config().UnbundledBuild() {
229 return false
230 }
231
Jaewoong Jungacf18d72019-05-02 14:55:29 -0700232 return shouldUncompressDex(ctx, &a.dexpreopter)
Colin Cross5a0dcd52018-10-05 14:20:06 -0700233}
234
Jaewoong Jungbc625cd2019-05-06 15:48:44 -0700235func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
236 return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
237 a.appProperties.AlwaysPackageNativeLibs
238}
239
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800240func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
David Brazdild25060a2019-02-18 18:24:16 +0000241 a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
242
Jaewoong Jungc27ab662019-05-30 15:51:14 -0700243 // Ask manifest_fixer to add or update the application element indicating this app has no code.
244 a.aapt.hasNoCode = !a.hasCode(ctx)
245
Jaewoong Jungde4c02f2019-01-22 11:19:56 -0800246 aaptLinkFlags := []string{}
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800247
Jaewoong Jungde4c02f2019-01-22 11:19:56 -0800248 // Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
Colin Crosse78dcd32018-04-19 15:25:19 -0700249 hasProduct := false
250 for _, f := range a.aaptProperties.Aaptflags {
251 if strings.HasPrefix(f, "--product") {
252 hasProduct = true
Jaewoong Jungde4c02f2019-01-22 11:19:56 -0800253 break
Colin Crosse78dcd32018-04-19 15:25:19 -0700254 }
255 }
Colin Crosse78dcd32018-04-19 15:25:19 -0700256 if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
Jaewoong Jungde4c02f2019-01-22 11:19:56 -0800257 aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
Colin Crosse78dcd32018-04-19 15:25:19 -0700258 }
259
Dan Willemsen72be5902018-10-24 20:24:57 -0700260 if !Bool(a.aaptProperties.Aapt_include_all_resources) {
261 // Product AAPT config
262 for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
Jaewoong Jungde4c02f2019-01-22 11:19:56 -0800263 aaptLinkFlags = append(aaptLinkFlags, "-c", aaptConfig)
Dan Willemsen72be5902018-10-24 20:24:57 -0700264 }
Colin Crosse78dcd32018-04-19 15:25:19 -0700265
Dan Willemsen72be5902018-10-24 20:24:57 -0700266 // Product AAPT preferred config
267 if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
Jaewoong Jungde4c02f2019-01-22 11:19:56 -0800268 aaptLinkFlags = append(aaptLinkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
Dan Willemsen72be5902018-10-24 20:24:57 -0700269 }
Colin Crosse78dcd32018-04-19 15:25:19 -0700270 }
271
Jiyong Park7f67f482019-01-05 12:57:48 +0900272 manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700273 if overridden || a.overridableAppProperties.Package_name != nil {
274 // The product override variable has a priority over the package_name property.
275 if !overridden {
276 manifestPackageName = *a.overridableAppProperties.Package_name
277 }
Jaewoong Jungde4c02f2019-01-22 11:19:56 -0800278 aaptLinkFlags = append(aaptLinkFlags, "--rename-manifest-package "+manifestPackageName)
Jiyong Park7f67f482019-01-05 12:57:48 +0900279 }
280
Jaewoong Jung4102e5d2019-02-27 16:26:28 -0800281 aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
282
Colin Crosse560c4a2019-03-19 16:03:11 -0700283 a.aapt.splitNames = a.appProperties.Package_splits
Colin Cross50ddcc42019-05-16 12:28:22 -0700284 a.aapt.sdkLibraries = a.exportedSdkLibs
Colin Crosse560c4a2019-03-19 16:03:11 -0700285
Jaewoong Jungde4c02f2019-01-22 11:19:56 -0800286 a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...)
Colin Cross30e076a2015-04-13 13:58:27 -0700287
Colin Cross46c9b8b2017-06-22 16:51:17 -0700288 // apps manifests are handled by aapt, don't let Module see them
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700289 a.properties.Manifest = nil
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800290}
Colin Cross30e076a2015-04-13 13:58:27 -0700291
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800292func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
Colin Cross89c31582018-04-30 15:55:11 -0700293 var staticLibProguardFlagFiles android.Paths
294 ctx.VisitDirectDeps(func(m android.Module) {
295 if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
296 staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
297 }
298 })
299
300 staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
301
302 a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...)
303 a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800304}
Colin Cross66dbc0b2017-12-28 12:23:20 -0800305
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800306func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
Colin Cross43f08db2018-11-12 10:13:39 -0800307
308 var installDir string
309 if ctx.ModuleName() == "framework-res" {
310 // framework-res.apk is installed as system/framework/framework-res.apk
311 installDir = "framework"
312 } else if Bool(a.appProperties.Privileged) {
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800313 installDir = filepath.Join("priv-app", a.installApkName)
Colin Cross43f08db2018-11-12 10:13:39 -0800314 } else {
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800315 installDir = filepath.Join("app", a.installApkName)
Colin Cross43f08db2018-11-12 10:13:39 -0800316 }
Colin Cross50ddcc42019-05-16 12:28:22 -0700317
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800318 a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
Nicolas Geoffrayfa6e9ec2019-02-12 13:12:16 +0000319 a.dexpreopter.isInstallable = Bool(a.properties.Installable)
320 a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
Colin Cross50ddcc42019-05-16 12:28:22 -0700321
322 a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
323 a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
324 a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
325 a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
326 a.dexpreopter.manifestFile = a.mergedManifestFile
327
Nicolas Geoffrayfa6e9ec2019-02-12 13:12:16 +0000328 a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex
Colin Cross5a0dcd52018-10-05 14:20:06 -0700329
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800330 if ctx.ModuleName() != "framework-res" {
331 a.Module.compile(ctx, a.aaptSrcJar)
332 }
Colin Cross30e076a2015-04-13 13:58:27 -0700333
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800334 return a.maybeStrippedDexJarFile
335}
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800336
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800337func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
Colin Crossa4f08812018-10-02 22:03:40 -0700338 var jniJarFile android.WritablePath
Colin Crossa4f08812018-10-02 22:03:40 -0700339 if len(jniLibs) > 0 {
Jaewoong Jungbc625cd2019-05-06 15:48:44 -0700340 if a.shouldEmbedJnis(ctx) {
Colin Crossa4f08812018-10-02 22:03:40 -0700341 jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
Sasha Smundak6ad77252019-05-01 13:16:22 -0700342 TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
Colin Crossa4f08812018-10-02 22:03:40 -0700343 } else {
344 a.installJniLibs = jniLibs
345 }
346 }
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800347 return jniJarFile
348}
Colin Crossa4f08812018-10-02 22:03:40 -0700349
Jaewoong Jung98772792019-07-01 17:15:13 -0700350func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext, installDir android.OutputPath) {
Jaewoong Jung5b425e22019-06-17 17:40:56 -0700351 // Collect NOTICE files from all dependencies.
352 seenModules := make(map[android.Module]bool)
353 noticePathSet := make(map[android.Path]bool)
354
355 ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
356 // Have we already seen this?
357 if _, ok := seenModules[child]; ok {
358 return false
359 }
360 seenModules[child] = true
361
362 // Skip host modules.
363 if child.Target().Os.Class == android.Host || child.Target().Os.Class == android.HostCross {
364 return false
365 }
366
367 path := child.(android.Module).NoticeFile()
368 if path.Valid() {
369 noticePathSet[path.Path()] = true
370 }
371 return true
372 })
373
374 // If the app has one, add it too.
375 if a.NoticeFile().Valid() {
376 noticePathSet[a.NoticeFile().Path()] = true
377 }
378
379 if len(noticePathSet) == 0 {
Jaewoong Jung98772792019-07-01 17:15:13 -0700380 return
Jaewoong Jung5b425e22019-06-17 17:40:56 -0700381 }
382 var noticePaths []android.Path
383 for path := range noticePathSet {
384 noticePaths = append(noticePaths, path)
385 }
386 sort.Slice(noticePaths, func(i, j int) bool {
387 return noticePaths[i].String() < noticePaths[j].String()
388 })
Jaewoong Jung5b425e22019-06-17 17:40:56 -0700389
Jaewoong Jung98772792019-07-01 17:15:13 -0700390 a.noticeOutputs = android.BuildNoticeOutput(ctx, installDir, a.installApkName+".apk", noticePaths)
Jaewoong Jung5b425e22019-06-17 17:40:56 -0700391}
392
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700393// Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
394// isn't a cert module reference. Also checks and enforces system cert restriction if applicable.
395func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate, ctx android.ModuleContext) []Certificate {
396 if android.SrcIsModule(certPropValue) == "" {
397 var mainCert Certificate
398 if certPropValue != "" {
399 defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
400 mainCert = Certificate{
401 defaultDir.Join(ctx, certPropValue+".x509.pem"),
402 defaultDir.Join(ctx, certPropValue+".pk8"),
403 }
404 } else {
405 pem, key := ctx.Config().DefaultAppCertificate(ctx)
406 mainCert = Certificate{pem, key}
Colin Crossbd01e2a2018-10-04 15:21:03 -0700407 }
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700408 certificates = append([]Certificate{mainCert}, certificates...)
Colin Crossbd01e2a2018-10-04 15:21:03 -0700409 }
410
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700411 if !m.Platform() {
412 certPath := certificates[0].Pem.String()
Jeongik Chac9464142019-01-07 12:07:27 +0900413 systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String()
414 if strings.HasPrefix(certPath, systemCertPath) {
415 enforceSystemCert := ctx.Config().EnforceSystemCertificate()
416 whitelist := ctx.Config().EnforceSystemCertificateWhitelist()
417
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700418 if enforceSystemCert && !inList(m.Name(), whitelist) {
Jeongik Chac9464142019-01-07 12:07:27 +0900419 ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.")
420 }
421 }
422 }
423
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700424 return certificates
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800425}
426
427func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross50ddcc42019-05-16 12:28:22 -0700428 var apkDeps android.Paths
429
Jeongik Cha538c0d02019-07-11 15:54:27 +0900430 a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
431 a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
432
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800433 // Check if the install APK name needs to be overridden.
Jaewoong Jung525443a2019-02-28 15:35:54 -0800434 a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800435
Jaewoong Jung5b425e22019-06-17 17:40:56 -0700436 var installDir android.OutputPath
437 if ctx.ModuleName() == "framework-res" {
438 // framework-res.apk is installed as system/framework/framework-res.apk
439 installDir = android.PathForModuleInstall(ctx, "framework")
440 } else if Bool(a.appProperties.Privileged) {
441 installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
442 } else {
443 installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
444 }
445
Jaewoong Jung98772792019-07-01 17:15:13 -0700446 a.noticeBuildActions(ctx, installDir)
447 if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
448 a.aapt.noticeFile = a.noticeOutputs.HtmlGzOutput
449 }
Jaewoong Jung5b425e22019-06-17 17:40:56 -0700450
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800451 // Process all building blocks, from AAPT to certificates.
452 a.aaptBuildActions(ctx)
453
Colin Cross50ddcc42019-05-16 12:28:22 -0700454 if a.usesLibrary.enforceUsesLibraries() {
455 manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(ctx, a.mergedManifestFile)
456 apkDeps = append(apkDeps, manifestCheckFile)
457 }
458
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800459 a.proguardBuildActions(ctx)
460
461 dexJarFile := a.dexBuildActions(ctx)
462
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700463 jniLibs, certificateDeps := collectAppDeps(ctx)
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800464 jniJarFile := a.jniBuildActions(jniLibs, ctx)
465
466 if ctx.Failed() {
467 return
468 }
469
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700470 certificates := processMainCert(a.ModuleBase, a.getCertString(ctx), certificateDeps, ctx)
471 a.certificate = certificates[0]
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800472
473 // Build a final signed app package.
Jaewoong Jung525443a2019-02-28 15:35:54 -0800474 // TODO(jungjw): Consider changing this to installApkName.
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800475 packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
Colin Cross50ddcc42019-05-16 12:28:22 -0700476 CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps)
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800477 a.outputFile = packageFile
478
Colin Crosse560c4a2019-03-19 16:03:11 -0700479 for _, split := range a.aapt.splits {
480 // Sign the split APKs
481 packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk")
Colin Cross50ddcc42019-05-16 12:28:22 -0700482 CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps)
Colin Crosse560c4a2019-03-19 16:03:11 -0700483 a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
484 }
485
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800486 // Build an app bundle.
Colin Crossf6237212018-10-29 23:14:58 -0700487 bundleFile := android.PathForModuleOut(ctx, "base.zip")
488 BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
489 a.bundleFile = bundleFile
490
Jaewoong Jung590b1ae2019-01-22 16:40:58 -0800491 // Install the app package.
Colin Crosse560c4a2019-03-19 16:03:11 -0700492 ctx.InstallFile(installDir, a.installApkName+".apk", a.outputFile)
493 for _, split := range a.aapt.splits {
494 ctx.InstallFile(installDir, a.installApkName+"_"+split.suffix+".apk", split.path)
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800495 }
Colin Cross30e076a2015-04-13 13:58:27 -0700496}
497
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700498func collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) {
Colin Crossa4f08812018-10-02 22:03:40 -0700499 var jniLibs []jniLib
Jiyong Parkc00cbd92018-10-30 21:20:05 +0900500 var certificates []Certificate
Colin Crossa4f08812018-10-02 22:03:40 -0700501
502 ctx.VisitDirectDeps(func(module android.Module) {
503 otherName := ctx.OtherModuleName(module)
504 tag := ctx.OtherModuleDependencyTag(module)
505
506 if jniTag, ok := tag.(*jniDependencyTag); ok {
507 if dep, ok := module.(*cc.Module); ok {
508 lib := dep.OutputFile()
509 if lib.Valid() {
510 jniLibs = append(jniLibs, jniLib{
511 name: ctx.OtherModuleName(module),
512 path: lib.Path(),
513 target: jniTag.target,
514 })
515 } else {
516 ctx.ModuleErrorf("dependency %q missing output file", otherName)
517 }
518 } else {
519 ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName)
Colin Crossa4f08812018-10-02 22:03:40 -0700520 }
Colin Crossbd01e2a2018-10-04 15:21:03 -0700521 } else if tag == certificateTag {
522 if dep, ok := module.(*AndroidAppCertificate); ok {
Jiyong Parkc00cbd92018-10-30 21:20:05 +0900523 certificates = append(certificates, dep.Certificate)
Colin Crossbd01e2a2018-10-04 15:21:03 -0700524 } else {
525 ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
526 }
Colin Crossa4f08812018-10-02 22:03:40 -0700527 }
528 })
529
Colin Crossbd01e2a2018-10-04 15:21:03 -0700530 return jniLibs, certificates
Colin Crossa4f08812018-10-02 22:03:40 -0700531}
532
Colin Cross0ea8ba82019-06-06 14:33:29 -0700533func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string {
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800534 certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
535 if overridden {
Jaewoong Jungacb6db32019-02-28 16:22:30 +0000536 return ":" + certificate
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800537 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800538 return String(a.overridableAppProperties.Certificate)
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800539}
540
Colin Cross1b16b0e2019-02-12 14:41:32 -0800541// android_app compiles sources and Android resources into an Android application package `.apk` file.
Colin Cross36242852017-06-23 15:06:31 -0700542func AndroidAppFactory() android.Module {
Colin Cross30e076a2015-04-13 13:58:27 -0700543 module := &AndroidApp{}
544
Sasha Smundak2057f822019-04-16 17:16:58 -0700545 module.Module.deviceProperties.Optimize.EnabledByDefault = true
Colin Cross66dbc0b2017-12-28 12:23:20 -0800546 module.Module.deviceProperties.Optimize.Shrink = proptools.BoolPtr(true)
547
Colin Crossae5caf52018-05-22 11:11:52 -0700548 module.Module.properties.Instrument = true
Colin Cross9ae1b922018-06-26 17:59:05 -0700549 module.Module.properties.Installable = proptools.BoolPtr(true)
Colin Crossae5caf52018-05-22 11:11:52 -0700550
Colin Cross36242852017-06-23 15:06:31 -0700551 module.AddProperties(
Colin Cross540eff82017-06-22 17:01:52 -0700552 &module.Module.properties,
553 &module.Module.deviceProperties,
Colin Cross43f08db2018-11-12 10:13:39 -0800554 &module.Module.dexpreoptProperties,
Colin Crossa97c5d32018-03-28 14:58:31 -0700555 &module.Module.protoProperties,
556 &module.aaptProperties,
Jaewoong Jung525443a2019-02-28 15:35:54 -0800557 &module.appProperties,
Colin Cross50ddcc42019-05-16 12:28:22 -0700558 &module.overridableAppProperties,
559 &module.usesLibrary.usesLibraryProperties)
Colin Cross36242852017-06-23 15:06:31 -0700560
Colin Crossa9d8bee2018-10-02 13:59:46 -0700561 module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
562 return class == android.Device && ctx.Config().DevicePrefer32BitApps()
563 })
564
Colin Crossa4f08812018-10-02 22:03:40 -0700565 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
566 android.InitDefaultableModule(module)
Jaewoong Jung525443a2019-02-28 15:35:54 -0800567 android.InitOverridableModule(module, &module.appProperties.Overrides)
Colin Crossa4f08812018-10-02 22:03:40 -0700568
Colin Cross36242852017-06-23 15:06:31 -0700569 return module
Colin Cross30e076a2015-04-13 13:58:27 -0700570}
Colin Crossae5caf52018-05-22 11:11:52 -0700571
572type appTestProperties struct {
573 Instrumentation_for *string
574}
575
576type AndroidTest struct {
577 AndroidApp
578
579 appTestProperties appTestProperties
580
581 testProperties testProperties
Colin Cross303e21f2018-08-07 16:49:25 -0700582
583 testConfig android.Path
Colin Crossd96ca352018-08-10 16:06:24 -0700584 data android.Paths
Colin Crossae5caf52018-05-22 11:11:52 -0700585}
586
587func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Jaewoong Jung4102e5d2019-02-27 16:26:28 -0800588 // Check if the instrumentation target package is overridden before generating build actions.
589 if a.appTestProperties.Instrumentation_for != nil {
590 manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(*a.appTestProperties.Instrumentation_for)
591 if overridden {
592 a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName)
593 }
594 }
Colin Crossae5caf52018-05-22 11:11:52 -0700595 a.generateAndroidBuildActions(ctx)
Colin Cross303e21f2018-08-07 16:49:25 -0700596
yangbill4f41bc22019-02-13 21:45:47 +0800597 a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites)
Colin Cross8a497952019-03-05 22:25:09 -0800598 a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
Colin Cross303e21f2018-08-07 16:49:25 -0700599}
600
601func (a *AndroidTest) DepsMutator(ctx android.BottomUpMutatorContext) {
Colin Cross303e21f2018-08-07 16:49:25 -0700602 a.AndroidApp.DepsMutator(ctx)
Colin Cross4b964c02018-10-15 16:18:06 -0700603 if a.appTestProperties.Instrumentation_for != nil {
604 // The android_app dependency listed in instrumentation_for needs to be added to the classpath for javac,
605 // but not added to the aapt2 link includes like a normal android_app or android_library dependency, so
606 // use instrumentationForTag instead of libTag.
607 ctx.AddVariationDependencies(nil, instrumentationForTag, String(a.appTestProperties.Instrumentation_for))
608 }
Colin Crossae5caf52018-05-22 11:11:52 -0700609}
610
Colin Cross1b16b0e2019-02-12 14:41:32 -0800611// android_test compiles test sources and Android resources into an Android application package `.apk` file and
612// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
Colin Crossae5caf52018-05-22 11:11:52 -0700613func AndroidTestFactory() android.Module {
614 module := &AndroidTest{}
615
Sasha Smundak2057f822019-04-16 17:16:58 -0700616 module.Module.deviceProperties.Optimize.EnabledByDefault = true
Colin Cross5067db92018-09-17 16:46:35 -0700617
618 module.Module.properties.Instrument = true
Colin Cross9ae1b922018-06-26 17:59:05 -0700619 module.Module.properties.Installable = proptools.BoolPtr(true)
Colin Crosse4246ab2019-02-05 21:55:21 -0800620 module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
Colin Cross47fa9d32019-03-26 10:51:39 -0700621 module.appProperties.AlwaysPackageNativeLibs = true
Colin Cross43f08db2018-11-12 10:13:39 -0800622 module.Module.dexpreopter.isTest = true
Colin Crossae5caf52018-05-22 11:11:52 -0700623
624 module.AddProperties(
625 &module.Module.properties,
626 &module.Module.deviceProperties,
Colin Cross43f08db2018-11-12 10:13:39 -0800627 &module.Module.dexpreoptProperties,
Colin Crossae5caf52018-05-22 11:11:52 -0700628 &module.Module.protoProperties,
629 &module.aaptProperties,
630 &module.appProperties,
Dan Willemsenf5531d22018-07-16 17:21:19 -0700631 &module.appTestProperties,
Jaewoong Jung525443a2019-02-28 15:35:54 -0800632 &module.overridableAppProperties,
Colin Cross50ddcc42019-05-16 12:28:22 -0700633 &module.usesLibrary.usesLibraryProperties,
Dan Willemsenf5531d22018-07-16 17:21:19 -0700634 &module.testProperties)
Colin Crossae5caf52018-05-22 11:11:52 -0700635
Colin Crossa4f08812018-10-02 22:03:40 -0700636 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
637 android.InitDefaultableModule(module)
Colin Crossae5caf52018-05-22 11:11:52 -0700638 return module
639}
Colin Crossbd01e2a2018-10-04 15:21:03 -0700640
Colin Cross252fc6f2018-10-04 15:22:03 -0700641type appTestHelperAppProperties struct {
642 // list of compatibility suites (for example "cts", "vts") that the module should be
643 // installed into.
644 Test_suites []string `android:"arch_variant"`
645}
646
647type AndroidTestHelperApp struct {
648 AndroidApp
649
650 appTestHelperAppProperties appTestHelperAppProperties
651}
652
Colin Cross1b16b0e2019-02-12 14:41:32 -0800653// android_test_helper_app compiles sources and Android resources into an Android application package `.apk` file that
654// will be used by tests, but does not produce an `AndroidTest.xml` file so the module will not be run directly as a
655// test.
Colin Cross252fc6f2018-10-04 15:22:03 -0700656func AndroidTestHelperAppFactory() android.Module {
657 module := &AndroidTestHelperApp{}
658
Sasha Smundak2057f822019-04-16 17:16:58 -0700659 module.Module.deviceProperties.Optimize.EnabledByDefault = true
Colin Cross252fc6f2018-10-04 15:22:03 -0700660
661 module.Module.properties.Installable = proptools.BoolPtr(true)
Colin Crosse4246ab2019-02-05 21:55:21 -0800662 module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
Colin Cross47fa9d32019-03-26 10:51:39 -0700663 module.appProperties.AlwaysPackageNativeLibs = true
Colin Cross43f08db2018-11-12 10:13:39 -0800664 module.Module.dexpreopter.isTest = true
Colin Cross252fc6f2018-10-04 15:22:03 -0700665
666 module.AddProperties(
667 &module.Module.properties,
668 &module.Module.deviceProperties,
Colin Cross43f08db2018-11-12 10:13:39 -0800669 &module.Module.dexpreoptProperties,
Colin Cross252fc6f2018-10-04 15:22:03 -0700670 &module.Module.protoProperties,
671 &module.aaptProperties,
672 &module.appProperties,
Jaewoong Jung525443a2019-02-28 15:35:54 -0800673 &module.appTestHelperAppProperties,
Colin Cross50ddcc42019-05-16 12:28:22 -0700674 &module.overridableAppProperties,
675 &module.usesLibrary.usesLibraryProperties)
Colin Cross252fc6f2018-10-04 15:22:03 -0700676
677 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
678 android.InitDefaultableModule(module)
679 return module
680}
681
Colin Crossbd01e2a2018-10-04 15:21:03 -0700682type AndroidAppCertificate struct {
683 android.ModuleBase
684 properties AndroidAppCertificateProperties
Jiyong Parkc00cbd92018-10-30 21:20:05 +0900685 Certificate Certificate
Colin Crossbd01e2a2018-10-04 15:21:03 -0700686}
687
688type AndroidAppCertificateProperties struct {
689 // Name of the certificate files. Extensions .x509.pem and .pk8 will be added to the name.
690 Certificate *string
691}
692
Colin Cross1b16b0e2019-02-12 14:41:32 -0800693// android_app_certificate modules can be referenced by the certificates property of android_app modules to select
694// the signing key.
Colin Crossbd01e2a2018-10-04 15:21:03 -0700695func AndroidAppCertificateFactory() android.Module {
696 module := &AndroidAppCertificate{}
697 module.AddProperties(&module.properties)
698 android.InitAndroidModule(module)
699 return module
700}
701
Colin Crossbd01e2a2018-10-04 15:21:03 -0700702func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
703 cert := String(c.properties.Certificate)
Jiyong Parkc00cbd92018-10-30 21:20:05 +0900704 c.Certificate = Certificate{
Colin Crossbd01e2a2018-10-04 15:21:03 -0700705 android.PathForModuleSrc(ctx, cert+".x509.pem"),
706 android.PathForModuleSrc(ctx, cert+".pk8"),
707 }
708}
Jaewoong Jung525443a2019-02-28 15:35:54 -0800709
710type OverrideAndroidApp struct {
711 android.ModuleBase
712 android.OverrideModuleBase
713}
714
715func (i *OverrideAndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
716 // All the overrides happen in the base module.
717 // TODO(jungjw): Check the base module type.
718}
719
720// override_android_app is used to create an android_app module based on another android_app by overriding
721// some of its properties.
722func OverrideAndroidAppModuleFactory() android.Module {
723 m := &OverrideAndroidApp{}
724 m.AddProperties(&overridableAppProperties{})
725
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700726 android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
Jaewoong Jung525443a2019-02-28 15:35:54 -0800727 android.InitOverrideModule(m)
728 return m
729}
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700730
731type AndroidAppImport struct {
732 android.ModuleBase
733 android.DefaultableModuleBase
734 prebuilt android.Prebuilt
735
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700736 properties AndroidAppImportProperties
737 dpiVariants interface{}
738 archVariants interface{}
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700739
740 outputFile android.Path
741 certificate *Certificate
742
743 dexpreopter
Colin Cross50ddcc42019-05-16 12:28:22 -0700744
745 usesLibrary usesLibrary
Jaewoong Jung8aae22e2019-07-17 10:21:49 -0700746
747 installPath android.OutputPath
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700748}
749
750type AndroidAppImportProperties struct {
751 // A prebuilt apk to import
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700752 Apk *string
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700753
Jaewoong Jung961d4fd2019-08-22 14:25:58 -0700754 // The name of a certificate in the default certificate directory or an android_app_certificate
755 // module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700756 Certificate *string
757
758 // Set this flag to true if the prebuilt apk is already signed. The certificate property must not
759 // be set for presigned modules.
760 Presigned *bool
761
Jaewoong Jung961d4fd2019-08-22 14:25:58 -0700762 // Sign with the default system dev certificate. Must be used judiciously. Most imported apps
763 // need to either specify a specific certificate or be presigned.
764 Default_dev_cert *bool
765
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700766 // Specifies that this app should be installed to the priv-app directory,
767 // where the system will grant it additional privileges not available to
768 // normal apps.
769 Privileged *bool
770
771 // Names of modules to be overridden. Listed modules can only be other binaries
772 // (in Make or Soong).
773 // This does not completely prevent installation of the overridden binaries, but if both
774 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
775 // from PRODUCT_PACKAGES.
776 Overrides []string
Jaewoong Jung8aae22e2019-07-17 10:21:49 -0700777
778 // Optional name for the installed app. If unspecified, it is derived from the module name.
779 Filename *string
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700780}
781
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700782// Updates properties with variant-specific values.
783func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700784 config := ctx.Config()
785
786 dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName("Dpi_variants")
787 // Try DPI variant matches in the reverse-priority order so that the highest priority match
788 // overwrites everything else.
789 // TODO(jungjw): Can we optimize this by making it priority order?
790 for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700791 MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPrebuiltDPI()[i])
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700792 }
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700793 if config.ProductAAPTPreferredConfig() != "" {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700794 MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPreferredConfig())
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700795 }
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700796
797 archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
798 archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
799 MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700800}
801
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700802func MergePropertiesFromVariant(ctx android.BaseModuleContext,
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700803 dst interface{}, variantGroup reflect.Value, variant string) {
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700804 src := variantGroup.FieldByName(proptools.FieldNameForProperty(variant))
805 if !src.IsValid() {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700806 return
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700807 }
808
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700809 err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, proptools.OrderAppend)
810 if err != nil {
811 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
812 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
813 } else {
814 panic(err)
815 }
816 }
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700817}
818
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700819func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
820 cert := android.SrcIsModule(String(a.properties.Certificate))
821 if cert != "" {
822 ctx.AddDependency(ctx.Module(), certificateTag, cert)
823 }
Colin Cross50ddcc42019-05-16 12:28:22 -0700824
Paul Duffin250e6192019-06-07 10:44:37 +0100825 a.usesLibrary.deps(ctx, true)
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700826}
827
828func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
829 ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
830 rule := android.NewRuleBuilder()
831 rule.Command().
832 Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
Colin Crossee94d6a2019-07-08 17:08:34 -0700833 BuiltTool(ctx, "zip2zip").
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700834 FlagWithInput("-i ", inputPath).
835 FlagWithOutput("-o ", outputPath).
836 FlagWithArg("-0 ", "'lib/**/*.so'").
837 Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
838 rule.Build(pctx, ctx, "uncompress-embedded-jni-libs", "Uncompress embedded JIN libs")
839}
840
Jaewoong Jungacf18d72019-05-02 14:55:29 -0700841// Returns whether this module should have the dex file stored uncompressed in the APK.
842func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
843 if ctx.Config().UnbundledBuild() {
844 return false
845 }
846
847 // Uncompress dex in APKs of privileged apps
848 if ctx.Config().UncompressPrivAppDex() && Bool(a.properties.Privileged) {
849 return true
850 }
851
852 return shouldUncompressDex(ctx, &a.dexpreopter)
853}
854
Jaewoong Jungea1bdb02019-05-09 14:36:34 -0700855func (a *AndroidAppImport) uncompressDex(
856 ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
857 rule := android.NewRuleBuilder()
858 rule.Command().
859 Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
Colin Crossee94d6a2019-07-08 17:08:34 -0700860 BuiltTool(ctx, "zip2zip").
Jaewoong Jungea1bdb02019-05-09 14:36:34 -0700861 FlagWithInput("-i ", inputPath).
862 FlagWithOutput("-o ", outputPath).
863 FlagWithArg("-0 ", "'classes*.dex'").
864 Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
865 rule.Build(pctx, ctx, "uncompress-dex", "Uncompress dex files")
866}
867
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700868func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Jaewoong Jung961d4fd2019-08-22 14:25:58 -0700869 numCertPropsSet := 0
870 if String(a.properties.Certificate) != "" {
871 numCertPropsSet++
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700872 }
Jaewoong Jung961d4fd2019-08-22 14:25:58 -0700873 if Bool(a.properties.Presigned) {
874 numCertPropsSet++
875 }
876 if Bool(a.properties.Default_dev_cert) {
877 numCertPropsSet++
878 }
879 if numCertPropsSet != 1 {
880 ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700881 }
882
883 _, certificates := collectAppDeps(ctx)
884
885 // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700886 // TODO: LOCAL_PACKAGE_SPLITS
887
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700888 srcApk := a.prebuilt.SingleSourcePath(ctx)
Colin Cross50ddcc42019-05-16 12:28:22 -0700889
890 if a.usesLibrary.enforceUsesLibraries() {
891 srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
892 }
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700893
894 // TODO: Install or embed JNI libraries
895
896 // Uncompress JNI libraries in the apk
897 jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk")
898 a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
899
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700900 installDir := android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
901 a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
902 a.dexpreopter.isInstallable = true
903 a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
Jaewoong Jungacf18d72019-05-02 14:55:29 -0700904 a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
Colin Cross50ddcc42019-05-16 12:28:22 -0700905
906 a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
907 a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
908 a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
909 a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
910
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700911 dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
Jaewoong Jungea1bdb02019-05-09 14:36:34 -0700912 if a.dexpreopter.uncompressedDex {
913 dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
914 a.uncompressDex(ctx, dexOutput, dexUncompressed.OutputPath)
915 dexOutput = dexUncompressed
916 }
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700917
918 // Sign or align the package
919 // TODO: Handle EXTERNAL
920 if !Bool(a.properties.Presigned) {
Jaewoong Jung961d4fd2019-08-22 14:25:58 -0700921 // If the certificate property is empty at this point, default_dev_cert must be set to true.
922 // Which makes processMainCert's behavior for the empty cert string WAI.
923 certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700924 if len(certificates) != 1 {
925 ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
926 }
927 a.certificate = &certificates[0]
928 signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk")
929 SignAppPackage(ctx, signed, dexOutput, certificates)
930 a.outputFile = signed
931 } else {
932 alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk")
933 TransformZipAlign(ctx, alignedApk, dexOutput)
934 a.outputFile = alignedApk
935 }
936
937 // TODO: Optionally compress the output apk.
938
Jaewoong Jung8aae22e2019-07-17 10:21:49 -0700939 a.installPath = ctx.InstallFile(installDir,
940 proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk"), a.outputFile)
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700941
942 // TODO: androidmk converter jni libs
943}
944
945func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
946 return &a.prebuilt
947}
948
949func (a *AndroidAppImport) Name() string {
950 return a.prebuilt.Name(a.ModuleBase.Name())
951}
952
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700953var dpiVariantGroupType reflect.Type
954var archVariantGroupType reflect.Type
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700955
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700956func initAndroidAppImportVariantGroupTypes() {
957 dpiVariantGroupType = createVariantGroupType(supportedDpis, "Dpi_variants")
958
959 archNames := make([]string, len(android.ArchTypeList()))
960 for i, archType := range android.ArchTypeList() {
961 archNames[i] = archType.Name
962 }
963 archVariantGroupType = createVariantGroupType(archNames, "Arch")
964}
965
966// Populates all variant struct properties at creation time.
967func (a *AndroidAppImport) populateAllVariantStructs() {
968 a.dpiVariants = reflect.New(dpiVariantGroupType).Interface()
969 a.AddProperties(a.dpiVariants)
970
971 a.archVariants = reflect.New(archVariantGroupType).Interface()
972 a.AddProperties(a.archVariants)
973}
974
975func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
976 props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
977
978 variantFields := make([]reflect.StructField, len(variants))
979 for i, variant := range variants {
980 variantFields[i] = reflect.StructField{
981 Name: proptools.FieldNameForProperty(variant),
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700982 Type: props,
983 }
984 }
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700985
986 variantGroupStruct := reflect.StructOf(variantFields)
987 return reflect.StructOf([]reflect.StructField{
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700988 {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700989 Name: variantGroupName,
990 Type: variantGroupStruct,
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700991 },
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700992 })
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700993}
994
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700995// android_app_import imports a prebuilt apk with additional processing specified in the module.
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700996// DPI-specific apk source files can be specified using dpi_variants. Example:
997//
998// android_app_import {
999// name: "example_import",
1000// apk: "prebuilts/example.apk",
1001// dpi_variants: {
1002// mdpi: {
1003// apk: "prebuilts/example_mdpi.apk",
1004// },
1005// xhdpi: {
1006// apk: "prebuilts/example_xhdpi.apk",
1007// },
1008// },
1009// certificate: "PRESIGNED",
1010// }
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001011func AndroidAppImportFactory() android.Module {
1012 module := &AndroidAppImport{}
1013 module.AddProperties(&module.properties)
1014 module.AddProperties(&module.dexpreoptProperties)
Colin Cross50ddcc42019-05-16 12:28:22 -07001015 module.AddProperties(&module.usesLibrary.usesLibraryProperties)
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -07001016 module.populateAllVariantStructs()
Jaewoong Jung3e18b192019-06-11 12:25:34 -07001017 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -07001018 module.processVariants(ctx)
Jaewoong Jung3e18b192019-06-11 12:25:34 -07001019 })
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001020
1021 InitJavaModule(module, android.DeviceSupported)
Jaewoong Jung3e18b192019-06-11 12:25:34 -07001022 android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001023
1024 return module
1025}
Colin Cross50ddcc42019-05-16 12:28:22 -07001026
1027type UsesLibraryProperties struct {
1028 // A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file.
1029 Uses_libs []string
1030
1031 // A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file with
1032 // required=false.
1033 Optional_uses_libs []string
1034
1035 // If true, the list of uses_libs and optional_uses_libs modules must match the AndroidManifest.xml file. Defaults
1036 // to true if either uses_libs or optional_uses_libs is set. Will unconditionally default to true in the future.
1037 Enforce_uses_libs *bool
1038}
1039
1040// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
1041// <uses-library> tags that end up in the manifest of an APK match the ones known to the build system through the
1042// uses_libs and optional_uses_libs properties. The build system's values are used by dexpreopt to preopt apps
1043// with knowledge of their shared libraries.
1044type usesLibrary struct {
1045 usesLibraryProperties UsesLibraryProperties
1046}
1047
Paul Duffin250e6192019-06-07 10:44:37 +01001048func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs bool) {
Colin Cross3245b2c2019-06-07 13:18:09 -07001049 if !ctx.Config().UnbundledBuild() {
1050 ctx.AddVariationDependencies(nil, usesLibTag, u.usesLibraryProperties.Uses_libs...)
1051 ctx.AddVariationDependencies(nil, usesLibTag, u.presentOptionalUsesLibs(ctx)...)
Paul Duffin250e6192019-06-07 10:44:37 +01001052 // Only add these extra dependencies if the module depends on framework libs. This avoids
1053 // creating a cyclic dependency:
1054 // e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
1055 if hasFrameworkLibs {
Colin Cross3245b2c2019-06-07 13:18:09 -07001056 // dexpreopt/dexpreopt.go needs the paths to the dex jars of these libraries in case construct_context.sh needs
1057 // to pass them to dex2oat. Add them as a dependency so we can determine the path to the dex jar of each
1058 // library to dexpreopt.
1059 ctx.AddVariationDependencies(nil, usesLibTag,
1060 "org.apache.http.legacy",
1061 "android.hidl.base-V1.0-java",
1062 "android.hidl.manager-V1.0-java")
1063 }
Colin Cross50ddcc42019-05-16 12:28:22 -07001064 }
1065}
1066
1067// presentOptionalUsesLibs returns optional_uses_libs after filtering out MissingUsesLibraries, which don't exist in the
1068// build.
1069func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
1070 optionalUsesLibs, _ := android.FilterList(u.usesLibraryProperties.Optional_uses_libs, ctx.Config().MissingUsesLibraries())
1071 return optionalUsesLibs
1072}
1073
1074// usesLibraryPaths returns a map of module names of shared library dependencies to the paths to their dex jars.
1075func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) map[string]android.Path {
1076 usesLibPaths := make(map[string]android.Path)
1077
1078 if !ctx.Config().UnbundledBuild() {
1079 ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
1080 if lib, ok := m.(Dependency); ok {
1081 if dexJar := lib.DexJar(); dexJar != nil {
1082 usesLibPaths[ctx.OtherModuleName(m)] = dexJar
1083 } else {
1084 ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must produce a dex jar, does it have installable: true?",
1085 ctx.OtherModuleName(m))
1086 }
1087 } else if ctx.Config().AllowMissingDependencies() {
1088 ctx.AddMissingDependencies([]string{ctx.OtherModuleName(m)})
1089 } else {
1090 ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library",
1091 ctx.OtherModuleName(m))
1092 }
1093 })
1094 }
1095
1096 return usesLibPaths
1097}
1098
1099// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
1100// properties. Defaults to true if either of uses_libs or optional_uses_libs is specified. Will default to true
1101// unconditionally in the future.
1102func (u *usesLibrary) enforceUsesLibraries() bool {
1103 defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs) > 0 ||
1104 len(u.usesLibraryProperties.Optional_uses_libs) > 0
1105 return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, defaultEnforceUsesLibs)
1106}
1107
1108// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against the ones specified
1109// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the manifest.
1110func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
1111 outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
1112
1113 rule := android.NewRuleBuilder()
Colin Crossee94d6a2019-07-08 17:08:34 -07001114 cmd := rule.Command().BuiltTool(ctx, "manifest_check").
Colin Cross50ddcc42019-05-16 12:28:22 -07001115 Flag("--enforce-uses-libraries").
1116 Input(manifest).
1117 FlagWithOutput("-o ", outputFile)
1118
1119 for _, lib := range u.usesLibraryProperties.Uses_libs {
1120 cmd.FlagWithArg("--uses-library ", lib)
1121 }
1122
1123 for _, lib := range u.usesLibraryProperties.Optional_uses_libs {
1124 cmd.FlagWithArg("--optional-uses-library ", lib)
1125 }
1126
1127 rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
1128
1129 return outputFile
1130}
1131
1132// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the ones specified
1133// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the APK.
1134func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) android.Path {
1135 outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
1136
1137 rule := android.NewRuleBuilder()
1138 aapt := ctx.Config().HostToolPath(ctx, "aapt")
1139 rule.Command().
1140 Textf("aapt_binary=%s", aapt.String()).Implicit(aapt).
1141 Textf(`uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Uses_libs, " ")).
1142 Textf(`optional_uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Optional_uses_libs, " ")).
1143 Tool(android.PathForSource(ctx, "build/make/core/verify_uses_libraries.sh")).Input(apk)
1144 rule.Command().Text("cp -f").Input(apk).Output(outputFile)
1145
1146 rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
1147
1148 return outputFile
1149}