1*333d2b36SAndroid Build Coastguard Worker// Copyright 2020 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage java 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Worker// This file contains the module implementation for android_app_set. 18*333d2b36SAndroid Build Coastguard Worker 19*333d2b36SAndroid Build Coastguard Workerimport ( 20*333d2b36SAndroid Build Coastguard Worker "strconv" 21*333d2b36SAndroid Build Coastguard Worker "strings" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 26*333d2b36SAndroid Build Coastguard Worker) 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard Workerfunc init() { 29*333d2b36SAndroid Build Coastguard Worker RegisterAppSetBuildComponents(android.InitRegistrationContext) 30*333d2b36SAndroid Build Coastguard Worker} 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Workerfunc RegisterAppSetBuildComponents(ctx android.RegistrationContext) { 33*333d2b36SAndroid Build Coastguard Worker ctx.RegisterModuleType("android_app_set", AndroidAppSetFactory) 34*333d2b36SAndroid Build Coastguard Worker} 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Workertype AndroidAppSetProperties struct { 37*333d2b36SAndroid Build Coastguard Worker // APK Set path 38*333d2b36SAndroid Build Coastguard Worker Set *string `android:"path"` 39*333d2b36SAndroid Build Coastguard Worker 40*333d2b36SAndroid Build Coastguard Worker // Specifies that this app should be installed to the priv-app directory, 41*333d2b36SAndroid Build Coastguard Worker // where the system will grant it additional privileges not available to 42*333d2b36SAndroid Build Coastguard Worker // normal apps. 43*333d2b36SAndroid Build Coastguard Worker Privileged *bool 44*333d2b36SAndroid Build Coastguard Worker 45*333d2b36SAndroid Build Coastguard Worker // APKs in this set use prerelease SDK version 46*333d2b36SAndroid Build Coastguard Worker Prerelease *bool 47*333d2b36SAndroid Build Coastguard Worker 48*333d2b36SAndroid Build Coastguard Worker // Names of modules to be overridden. Listed modules can only be other apps 49*333d2b36SAndroid Build Coastguard Worker // (in Make or Soong). 50*333d2b36SAndroid Build Coastguard Worker Overrides []string 51*333d2b36SAndroid Build Coastguard Worker 52*333d2b36SAndroid Build Coastguard Worker // Path to the .prebuilt_info file of the prebuilt app. 53*333d2b36SAndroid Build Coastguard Worker // In case of mainline modules, the .prebuilt_info file contains the build_id that was used 54*333d2b36SAndroid Build Coastguard Worker // to generate the prebuilt. 55*333d2b36SAndroid Build Coastguard Worker Prebuilt_info *string `android:"path"` 56*333d2b36SAndroid Build Coastguard Worker} 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Workertype AndroidAppSet struct { 59*333d2b36SAndroid Build Coastguard Worker android.ModuleBase 60*333d2b36SAndroid Build Coastguard Worker android.DefaultableModuleBase 61*333d2b36SAndroid Build Coastguard Worker prebuilt android.Prebuilt 62*333d2b36SAndroid Build Coastguard Worker 63*333d2b36SAndroid Build Coastguard Worker properties AndroidAppSetProperties 64*333d2b36SAndroid Build Coastguard Worker packedOutput android.WritablePath 65*333d2b36SAndroid Build Coastguard Worker primaryOutput android.WritablePath 66*333d2b36SAndroid Build Coastguard Worker apkcertsFile android.ModuleOutPath 67*333d2b36SAndroid Build Coastguard Worker} 68*333d2b36SAndroid Build Coastguard Worker 69*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) Name() string { 70*333d2b36SAndroid Build Coastguard Worker return as.prebuilt.Name(as.ModuleBase.Name()) 71*333d2b36SAndroid Build Coastguard Worker} 72*333d2b36SAndroid Build Coastguard Worker 73*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) IsInstallable() bool { 74*333d2b36SAndroid Build Coastguard Worker return true 75*333d2b36SAndroid Build Coastguard Worker} 76*333d2b36SAndroid Build Coastguard Worker 77*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) Prebuilt() *android.Prebuilt { 78*333d2b36SAndroid Build Coastguard Worker return &as.prebuilt 79*333d2b36SAndroid Build Coastguard Worker} 80*333d2b36SAndroid Build Coastguard Worker 81*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) Privileged() bool { 82*333d2b36SAndroid Build Coastguard Worker return Bool(as.properties.Privileged) 83*333d2b36SAndroid Build Coastguard Worker} 84*333d2b36SAndroid Build Coastguard Worker 85*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) OutputFile() android.Path { 86*333d2b36SAndroid Build Coastguard Worker return as.primaryOutput 87*333d2b36SAndroid Build Coastguard Worker} 88*333d2b36SAndroid Build Coastguard Worker 89*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) PackedAdditionalOutputs() android.Path { 90*333d2b36SAndroid Build Coastguard Worker return as.packedOutput 91*333d2b36SAndroid Build Coastguard Worker} 92*333d2b36SAndroid Build Coastguard Worker 93*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) APKCertsFile() android.Path { 94*333d2b36SAndroid Build Coastguard Worker return as.apkcertsFile 95*333d2b36SAndroid Build Coastguard Worker} 96*333d2b36SAndroid Build Coastguard Worker 97*333d2b36SAndroid Build Coastguard Workervar TargetCpuAbi = map[string]string{ 98*333d2b36SAndroid Build Coastguard Worker "arm": "ARMEABI_V7A", 99*333d2b36SAndroid Build Coastguard Worker "arm64": "ARM64_V8A", 100*333d2b36SAndroid Build Coastguard Worker // TODO: use "RISCV64" when that is supported in bundles 101*333d2b36SAndroid Build Coastguard Worker "riscv64": "ARM64_V8A", 102*333d2b36SAndroid Build Coastguard Worker "x86": "X86", 103*333d2b36SAndroid Build Coastguard Worker "x86_64": "X86_64", 104*333d2b36SAndroid Build Coastguard Worker} 105*333d2b36SAndroid Build Coastguard Worker 106*333d2b36SAndroid Build Coastguard Workerfunc SupportedAbis(ctx android.ModuleContext, excludeNativeBridgeAbis bool) []string { 107*333d2b36SAndroid Build Coastguard Worker abiName := func(targetIdx int, deviceArch string) string { 108*333d2b36SAndroid Build Coastguard Worker if abi, found := TargetCpuAbi[deviceArch]; found { 109*333d2b36SAndroid Build Coastguard Worker return abi 110*333d2b36SAndroid Build Coastguard Worker } 111*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("Target %d has invalid Arch: %s", targetIdx, deviceArch) 112*333d2b36SAndroid Build Coastguard Worker return "BAD_ABI" 113*333d2b36SAndroid Build Coastguard Worker } 114*333d2b36SAndroid Build Coastguard Worker 115*333d2b36SAndroid Build Coastguard Worker var result []string 116*333d2b36SAndroid Build Coastguard Worker for i, target := range ctx.Config().Targets[android.Android] { 117*333d2b36SAndroid Build Coastguard Worker if target.NativeBridge == android.NativeBridgeEnabled && excludeNativeBridgeAbis { 118*333d2b36SAndroid Build Coastguard Worker continue 119*333d2b36SAndroid Build Coastguard Worker } 120*333d2b36SAndroid Build Coastguard Worker result = append(result, abiName(i, target.Arch.ArchType.String())) 121*333d2b36SAndroid Build Coastguard Worker } 122*333d2b36SAndroid Build Coastguard Worker return result 123*333d2b36SAndroid Build Coastguard Worker} 124*333d2b36SAndroid Build Coastguard Worker 125*333d2b36SAndroid Build Coastguard Workertype prebuiltInfoProps struct { 126*333d2b36SAndroid Build Coastguard Worker baseModuleName string 127*333d2b36SAndroid Build Coastguard Worker isPrebuilt bool 128*333d2b36SAndroid Build Coastguard Worker prebuiltInfo *string 129*333d2b36SAndroid Build Coastguard Worker} 130*333d2b36SAndroid Build Coastguard Worker 131*333d2b36SAndroid Build Coastguard Worker// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file 132*333d2b36SAndroid Build Coastguard Worker// with information about whether source or prebuilt of an apex was used during the build. 133*333d2b36SAndroid Build Coastguard Workerfunc providePrebuiltInfo(ctx android.ModuleContext, p prebuiltInfoProps) { 134*333d2b36SAndroid Build Coastguard Worker info := android.PrebuiltInfo{ 135*333d2b36SAndroid Build Coastguard Worker Name: p.baseModuleName, 136*333d2b36SAndroid Build Coastguard Worker Is_prebuilt: p.isPrebuilt, 137*333d2b36SAndroid Build Coastguard Worker } 138*333d2b36SAndroid Build Coastguard Worker // If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json. 139*333d2b36SAndroid Build Coastguard Worker if p.prebuiltInfo != nil { 140*333d2b36SAndroid Build Coastguard Worker prebuiltInfoFile := android.PathForModuleSrc(ctx, *p.prebuiltInfo) 141*333d2b36SAndroid Build Coastguard Worker info.Prebuilt_info_file_path = prebuiltInfoFile.String() 142*333d2b36SAndroid Build Coastguard Worker } 143*333d2b36SAndroid Build Coastguard Worker android.SetProvider(ctx, android.PrebuiltInfoProvider, info) 144*333d2b36SAndroid Build Coastguard Worker} 145*333d2b36SAndroid Build Coastguard Worker 146*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { 147*333d2b36SAndroid Build Coastguard Worker as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip") 148*333d2b36SAndroid Build Coastguard Worker as.primaryOutput = android.PathForModuleOut(ctx, as.BaseModuleName()+".apk") 149*333d2b36SAndroid Build Coastguard Worker as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt") 150*333d2b36SAndroid Build Coastguard Worker // We are assuming here that the install file in the APK 151*333d2b36SAndroid Build Coastguard Worker // set has `.apk` suffix. If it doesn't the build will fail. 152*333d2b36SAndroid Build Coastguard Worker // APK sets containing APEX files are handled elsewhere. 153*333d2b36SAndroid Build Coastguard Worker screenDensities := "all" 154*333d2b36SAndroid Build Coastguard Worker if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 { 155*333d2b36SAndroid Build Coastguard Worker screenDensities = strings.ToUpper(strings.Join(dpis, ",")) 156*333d2b36SAndroid Build Coastguard Worker } 157*333d2b36SAndroid Build Coastguard Worker // TODO(asmundak): handle locales. 158*333d2b36SAndroid Build Coastguard Worker // TODO(asmundak): do we support device features 159*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, 160*333d2b36SAndroid Build Coastguard Worker android.BuildParams{ 161*333d2b36SAndroid Build Coastguard Worker Rule: extractMatchingApks, 162*333d2b36SAndroid Build Coastguard Worker Description: "Extract APKs from APK set", 163*333d2b36SAndroid Build Coastguard Worker Output: as.primaryOutput, 164*333d2b36SAndroid Build Coastguard Worker ImplicitOutputs: android.WritablePaths{as.packedOutput, as.apkcertsFile}, 165*333d2b36SAndroid Build Coastguard Worker Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)}, 166*333d2b36SAndroid Build Coastguard Worker Args: map[string]string{ 167*333d2b36SAndroid Build Coastguard Worker "abis": strings.Join(SupportedAbis(ctx, false), ","), 168*333d2b36SAndroid Build Coastguard Worker "allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)), 169*333d2b36SAndroid Build Coastguard Worker "screen-densities": screenDensities, 170*333d2b36SAndroid Build Coastguard Worker "sdk-version": ctx.Config().PlatformSdkVersion().String(), 171*333d2b36SAndroid Build Coastguard Worker "skip-sdk-check": strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")), 172*333d2b36SAndroid Build Coastguard Worker "stem": as.BaseModuleName(), 173*333d2b36SAndroid Build Coastguard Worker "apkcerts": as.apkcertsFile.String(), 174*333d2b36SAndroid Build Coastguard Worker "partition": as.PartitionTag(ctx.DeviceConfig()), 175*333d2b36SAndroid Build Coastguard Worker "zip": as.packedOutput.String(), 176*333d2b36SAndroid Build Coastguard Worker }, 177*333d2b36SAndroid Build Coastguard Worker }) 178*333d2b36SAndroid Build Coastguard Worker 179*333d2b36SAndroid Build Coastguard Worker var installDir android.InstallPath 180*333d2b36SAndroid Build Coastguard Worker if as.Privileged() { 181*333d2b36SAndroid Build Coastguard Worker installDir = android.PathForModuleInstall(ctx, "priv-app", as.BaseModuleName()) 182*333d2b36SAndroid Build Coastguard Worker } else { 183*333d2b36SAndroid Build Coastguard Worker installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName()) 184*333d2b36SAndroid Build Coastguard Worker } 185*333d2b36SAndroid Build Coastguard Worker ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk", as.primaryOutput, as.packedOutput) 186*333d2b36SAndroid Build Coastguard Worker 187*333d2b36SAndroid Build Coastguard Worker providePrebuiltInfo(ctx, 188*333d2b36SAndroid Build Coastguard Worker prebuiltInfoProps{ 189*333d2b36SAndroid Build Coastguard Worker baseModuleName: as.BaseModuleName(), 190*333d2b36SAndroid Build Coastguard Worker isPrebuilt: true, 191*333d2b36SAndroid Build Coastguard Worker prebuiltInfo: as.properties.Prebuilt_info, 192*333d2b36SAndroid Build Coastguard Worker }, 193*333d2b36SAndroid Build Coastguard Worker ) 194*333d2b36SAndroid Build Coastguard Worker 195*333d2b36SAndroid Build Coastguard Worker} 196*333d2b36SAndroid Build Coastguard Worker 197*333d2b36SAndroid Build Coastguard Workerfunc (as *AndroidAppSet) InstallBypassMake() bool { return true } 198*333d2b36SAndroid Build Coastguard Worker 199*333d2b36SAndroid Build Coastguard Worker// android_app_set extracts a set of APKs based on the target device 200*333d2b36SAndroid Build Coastguard Worker// configuration and installs this set as "split APKs". 201*333d2b36SAndroid Build Coastguard Worker// The extracted set always contains an APK whose name is 202*333d2b36SAndroid Build Coastguard Worker// _module_name_.apk and every split APK matching target device. 203*333d2b36SAndroid Build Coastguard Worker// The extraction of the density-specific splits depends on 204*333d2b36SAndroid Build Coastguard Worker// PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should 205*333d2b36SAndroid Build Coastguard Worker// be a list density names: LDPI, MDPI, HDPI, etc.), only listed 206*333d2b36SAndroid Build Coastguard Worker// splits will be extracted. Otherwise all density-specific splits 207*333d2b36SAndroid Build Coastguard Worker// will be extracted. 208*333d2b36SAndroid Build Coastguard Workerfunc AndroidAppSetFactory() android.Module { 209*333d2b36SAndroid Build Coastguard Worker module := &AndroidAppSet{} 210*333d2b36SAndroid Build Coastguard Worker module.AddProperties(&module.properties) 211*333d2b36SAndroid Build Coastguard Worker InitJavaModule(module, android.DeviceSupported) 212*333d2b36SAndroid Build Coastguard Worker android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set") 213*333d2b36SAndroid Build Coastguard Worker return module 214*333d2b36SAndroid Build Coastguard Worker} 215