blob: 31f07d36e6a8200241b5c663fcba74c944316e85 [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 Jungccbb3932019-04-15 09:48:31 -0700754 // The name of a certificate in the default certificate directory, blank to use the default
755 // product certificate, or an android_app_certificate module name in the form ":module".
756 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
762 // Specifies that this app should be installed to the priv-app directory,
763 // where the system will grant it additional privileges not available to
764 // normal apps.
765 Privileged *bool
766
767 // Names of modules to be overridden. Listed modules can only be other binaries
768 // (in Make or Soong).
769 // This does not completely prevent installation of the overridden binaries, but if both
770 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
771 // from PRODUCT_PACKAGES.
772 Overrides []string
Jaewoong Jung8aae22e2019-07-17 10:21:49 -0700773
774 // Optional name for the installed app. If unspecified, it is derived from the module name.
775 Filename *string
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700776}
777
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700778// Updates properties with variant-specific values.
779func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700780 config := ctx.Config()
781
782 dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName("Dpi_variants")
783 // Try DPI variant matches in the reverse-priority order so that the highest priority match
784 // overwrites everything else.
785 // TODO(jungjw): Can we optimize this by making it priority order?
786 for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700787 MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPrebuiltDPI()[i])
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700788 }
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700789 if config.ProductAAPTPreferredConfig() != "" {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700790 MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPreferredConfig())
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700791 }
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700792
793 archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
794 archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
795 MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700796}
797
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700798func MergePropertiesFromVariant(ctx android.BaseModuleContext,
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700799 dst interface{}, variantGroup reflect.Value, variant string) {
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700800 src := variantGroup.FieldByName(proptools.FieldNameForProperty(variant))
801 if !src.IsValid() {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700802 return
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700803 }
804
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700805 err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, proptools.OrderAppend)
806 if err != nil {
807 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
808 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
809 } else {
810 panic(err)
811 }
812 }
Jaewoong Junga5e5abc2019-04-26 14:31:50 -0700813}
814
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700815func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
816 cert := android.SrcIsModule(String(a.properties.Certificate))
817 if cert != "" {
818 ctx.AddDependency(ctx.Module(), certificateTag, cert)
819 }
Colin Cross50ddcc42019-05-16 12:28:22 -0700820
Paul Duffin250e6192019-06-07 10:44:37 +0100821 a.usesLibrary.deps(ctx, true)
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700822}
823
824func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
825 ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
826 rule := android.NewRuleBuilder()
827 rule.Command().
828 Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
Colin Crossee94d6a2019-07-08 17:08:34 -0700829 BuiltTool(ctx, "zip2zip").
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700830 FlagWithInput("-i ", inputPath).
831 FlagWithOutput("-o ", outputPath).
832 FlagWithArg("-0 ", "'lib/**/*.so'").
833 Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
834 rule.Build(pctx, ctx, "uncompress-embedded-jni-libs", "Uncompress embedded JIN libs")
835}
836
Jaewoong Jungacf18d72019-05-02 14:55:29 -0700837// Returns whether this module should have the dex file stored uncompressed in the APK.
838func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
839 if ctx.Config().UnbundledBuild() {
840 return false
841 }
842
843 // Uncompress dex in APKs of privileged apps
844 if ctx.Config().UncompressPrivAppDex() && Bool(a.properties.Privileged) {
845 return true
846 }
847
848 return shouldUncompressDex(ctx, &a.dexpreopter)
849}
850
Jaewoong Jungea1bdb02019-05-09 14:36:34 -0700851func (a *AndroidAppImport) uncompressDex(
852 ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
853 rule := android.NewRuleBuilder()
854 rule.Command().
855 Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
Colin Crossee94d6a2019-07-08 17:08:34 -0700856 BuiltTool(ctx, "zip2zip").
Jaewoong Jungea1bdb02019-05-09 14:36:34 -0700857 FlagWithInput("-i ", inputPath).
858 FlagWithOutput("-o ", outputPath).
859 FlagWithArg("-0 ", "'classes*.dex'").
860 Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
861 rule.Build(pctx, ctx, "uncompress-dex", "Uncompress dex files")
862}
863
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700864func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
865 if String(a.properties.Certificate) == "" && !Bool(a.properties.Presigned) {
866 ctx.PropertyErrorf("certificate", "No certificate specified for prebuilt")
867 }
868 if String(a.properties.Certificate) != "" && Bool(a.properties.Presigned) {
869 ctx.PropertyErrorf("certificate", "Certificate can't be specified for presigned modules")
870 }
871
872 _, certificates := collectAppDeps(ctx)
873
874 // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700875 // TODO: LOCAL_PACKAGE_SPLITS
876
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700877 srcApk := a.prebuilt.SingleSourcePath(ctx)
Colin Cross50ddcc42019-05-16 12:28:22 -0700878
879 if a.usesLibrary.enforceUsesLibraries() {
880 srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
881 }
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700882
883 // TODO: Install or embed JNI libraries
884
885 // Uncompress JNI libraries in the apk
886 jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk")
887 a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
888
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700889 installDir := android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
890 a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
891 a.dexpreopter.isInstallable = true
892 a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
Jaewoong Jungacf18d72019-05-02 14:55:29 -0700893 a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
Colin Cross50ddcc42019-05-16 12:28:22 -0700894
895 a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
896 a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
897 a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
898 a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
899
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700900 dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
Jaewoong Jungea1bdb02019-05-09 14:36:34 -0700901 if a.dexpreopter.uncompressedDex {
902 dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
903 a.uncompressDex(ctx, dexOutput, dexUncompressed.OutputPath)
904 dexOutput = dexUncompressed
905 }
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700906
907 // Sign or align the package
908 // TODO: Handle EXTERNAL
909 if !Bool(a.properties.Presigned) {
910 certificates = processMainCert(a.ModuleBase, *a.properties.Certificate, certificates, ctx)
911 if len(certificates) != 1 {
912 ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
913 }
914 a.certificate = &certificates[0]
915 signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk")
916 SignAppPackage(ctx, signed, dexOutput, certificates)
917 a.outputFile = signed
918 } else {
919 alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk")
920 TransformZipAlign(ctx, alignedApk, dexOutput)
921 a.outputFile = alignedApk
922 }
923
924 // TODO: Optionally compress the output apk.
925
Jaewoong Jung8aae22e2019-07-17 10:21:49 -0700926 a.installPath = ctx.InstallFile(installDir,
927 proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk"), a.outputFile)
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700928
929 // TODO: androidmk converter jni libs
930}
931
932func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
933 return &a.prebuilt
934}
935
936func (a *AndroidAppImport) Name() string {
937 return a.prebuilt.Name(a.ModuleBase.Name())
938}
939
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700940var dpiVariantGroupType reflect.Type
941var archVariantGroupType reflect.Type
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700942
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700943func initAndroidAppImportVariantGroupTypes() {
944 dpiVariantGroupType = createVariantGroupType(supportedDpis, "Dpi_variants")
945
946 archNames := make([]string, len(android.ArchTypeList()))
947 for i, archType := range android.ArchTypeList() {
948 archNames[i] = archType.Name
949 }
950 archVariantGroupType = createVariantGroupType(archNames, "Arch")
951}
952
953// Populates all variant struct properties at creation time.
954func (a *AndroidAppImport) populateAllVariantStructs() {
955 a.dpiVariants = reflect.New(dpiVariantGroupType).Interface()
956 a.AddProperties(a.dpiVariants)
957
958 a.archVariants = reflect.New(archVariantGroupType).Interface()
959 a.AddProperties(a.archVariants)
960}
961
962func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
963 props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
964
965 variantFields := make([]reflect.StructField, len(variants))
966 for i, variant := range variants {
967 variantFields[i] = reflect.StructField{
968 Name: proptools.FieldNameForProperty(variant),
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700969 Type: props,
970 }
971 }
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700972
973 variantGroupStruct := reflect.StructOf(variantFields)
974 return reflect.StructOf([]reflect.StructField{
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700975 {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700976 Name: variantGroupName,
977 Type: variantGroupStruct,
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700978 },
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -0700979 })
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700980}
981
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700982// android_app_import imports a prebuilt apk with additional processing specified in the module.
Jaewoong Jung3e18b192019-06-11 12:25:34 -0700983// DPI-specific apk source files can be specified using dpi_variants. Example:
984//
985// android_app_import {
986// name: "example_import",
987// apk: "prebuilts/example.apk",
988// dpi_variants: {
989// mdpi: {
990// apk: "prebuilts/example_mdpi.apk",
991// },
992// xhdpi: {
993// apk: "prebuilts/example_xhdpi.apk",
994// },
995// },
996// certificate: "PRESIGNED",
997// }
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700998func AndroidAppImportFactory() android.Module {
999 module := &AndroidAppImport{}
1000 module.AddProperties(&module.properties)
1001 module.AddProperties(&module.dexpreoptProperties)
Colin Cross50ddcc42019-05-16 12:28:22 -07001002 module.AddProperties(&module.usesLibrary.usesLibraryProperties)
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -07001003 module.populateAllVariantStructs()
Jaewoong Jung3e18b192019-06-11 12:25:34 -07001004 android.AddLoadHook(module, func(ctx android.LoadHookContext) {
Jaewoong Jung1ce9ac62019-08-13 14:11:33 -07001005 module.processVariants(ctx)
Jaewoong Jung3e18b192019-06-11 12:25:34 -07001006 })
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001007
1008 InitJavaModule(module, android.DeviceSupported)
Jaewoong Jung3e18b192019-06-11 12:25:34 -07001009 android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001010
1011 return module
1012}
Colin Cross50ddcc42019-05-16 12:28:22 -07001013
1014type UsesLibraryProperties struct {
1015 // A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file.
1016 Uses_libs []string
1017
1018 // A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file with
1019 // required=false.
1020 Optional_uses_libs []string
1021
1022 // If true, the list of uses_libs and optional_uses_libs modules must match the AndroidManifest.xml file. Defaults
1023 // to true if either uses_libs or optional_uses_libs is set. Will unconditionally default to true in the future.
1024 Enforce_uses_libs *bool
1025}
1026
1027// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
1028// <uses-library> tags that end up in the manifest of an APK match the ones known to the build system through the
1029// uses_libs and optional_uses_libs properties. The build system's values are used by dexpreopt to preopt apps
1030// with knowledge of their shared libraries.
1031type usesLibrary struct {
1032 usesLibraryProperties UsesLibraryProperties
1033}
1034
Paul Duffin250e6192019-06-07 10:44:37 +01001035func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs bool) {
Colin Cross3245b2c2019-06-07 13:18:09 -07001036 if !ctx.Config().UnbundledBuild() {
1037 ctx.AddVariationDependencies(nil, usesLibTag, u.usesLibraryProperties.Uses_libs...)
1038 ctx.AddVariationDependencies(nil, usesLibTag, u.presentOptionalUsesLibs(ctx)...)
Paul Duffin250e6192019-06-07 10:44:37 +01001039 // Only add these extra dependencies if the module depends on framework libs. This avoids
1040 // creating a cyclic dependency:
1041 // e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
1042 if hasFrameworkLibs {
Colin Cross3245b2c2019-06-07 13:18:09 -07001043 // dexpreopt/dexpreopt.go needs the paths to the dex jars of these libraries in case construct_context.sh needs
1044 // to pass them to dex2oat. Add them as a dependency so we can determine the path to the dex jar of each
1045 // library to dexpreopt.
1046 ctx.AddVariationDependencies(nil, usesLibTag,
1047 "org.apache.http.legacy",
1048 "android.hidl.base-V1.0-java",
1049 "android.hidl.manager-V1.0-java")
1050 }
Colin Cross50ddcc42019-05-16 12:28:22 -07001051 }
1052}
1053
1054// presentOptionalUsesLibs returns optional_uses_libs after filtering out MissingUsesLibraries, which don't exist in the
1055// build.
1056func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
1057 optionalUsesLibs, _ := android.FilterList(u.usesLibraryProperties.Optional_uses_libs, ctx.Config().MissingUsesLibraries())
1058 return optionalUsesLibs
1059}
1060
1061// usesLibraryPaths returns a map of module names of shared library dependencies to the paths to their dex jars.
1062func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) map[string]android.Path {
1063 usesLibPaths := make(map[string]android.Path)
1064
1065 if !ctx.Config().UnbundledBuild() {
1066 ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
1067 if lib, ok := m.(Dependency); ok {
1068 if dexJar := lib.DexJar(); dexJar != nil {
1069 usesLibPaths[ctx.OtherModuleName(m)] = dexJar
1070 } else {
1071 ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must produce a dex jar, does it have installable: true?",
1072 ctx.OtherModuleName(m))
1073 }
1074 } else if ctx.Config().AllowMissingDependencies() {
1075 ctx.AddMissingDependencies([]string{ctx.OtherModuleName(m)})
1076 } else {
1077 ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library",
1078 ctx.OtherModuleName(m))
1079 }
1080 })
1081 }
1082
1083 return usesLibPaths
1084}
1085
1086// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
1087// properties. Defaults to true if either of uses_libs or optional_uses_libs is specified. Will default to true
1088// unconditionally in the future.
1089func (u *usesLibrary) enforceUsesLibraries() bool {
1090 defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs) > 0 ||
1091 len(u.usesLibraryProperties.Optional_uses_libs) > 0
1092 return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, defaultEnforceUsesLibs)
1093}
1094
1095// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against the ones specified
1096// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the manifest.
1097func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
1098 outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
1099
1100 rule := android.NewRuleBuilder()
Colin Crossee94d6a2019-07-08 17:08:34 -07001101 cmd := rule.Command().BuiltTool(ctx, "manifest_check").
Colin Cross50ddcc42019-05-16 12:28:22 -07001102 Flag("--enforce-uses-libraries").
1103 Input(manifest).
1104 FlagWithOutput("-o ", outputFile)
1105
1106 for _, lib := range u.usesLibraryProperties.Uses_libs {
1107 cmd.FlagWithArg("--uses-library ", lib)
1108 }
1109
1110 for _, lib := range u.usesLibraryProperties.Optional_uses_libs {
1111 cmd.FlagWithArg("--optional-uses-library ", lib)
1112 }
1113
1114 rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
1115
1116 return outputFile
1117}
1118
1119// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the ones specified
1120// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the APK.
1121func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) android.Path {
1122 outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
1123
1124 rule := android.NewRuleBuilder()
1125 aapt := ctx.Config().HostToolPath(ctx, "aapt")
1126 rule.Command().
1127 Textf("aapt_binary=%s", aapt.String()).Implicit(aapt).
1128 Textf(`uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Uses_libs, " ")).
1129 Textf(`optional_uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Optional_uses_libs, " ")).
1130 Tool(android.PathForSource(ctx, "build/make/core/verify_uses_libraries.sh")).Input(apk)
1131 rule.Command().Text("cp -f").Input(apk).Output(outputFile)
1132
1133 rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
1134
1135 return outputFile
1136}