app_set.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright 2020 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. package java
  15. // This file contains the module implementation for android_app_set.
  16. import (
  17. "strconv"
  18. "strings"
  19. "github.com/google/blueprint/proptools"
  20. "android/soong/android"
  21. )
  22. func init() {
  23. RegisterAppSetBuildComponents(android.InitRegistrationContext)
  24. }
  25. func RegisterAppSetBuildComponents(ctx android.RegistrationContext) {
  26. ctx.RegisterModuleType("android_app_set", AndroidAppSetFactory)
  27. }
  28. type AndroidAppSetProperties struct {
  29. // APK Set path
  30. Set *string
  31. // Specifies that this app should be installed to the priv-app directory,
  32. // where the system will grant it additional privileges not available to
  33. // normal apps.
  34. Privileged *bool
  35. // APKs in this set use prerelease SDK version
  36. Prerelease *bool
  37. // Names of modules to be overridden. Listed modules can only be other apps
  38. // (in Make or Soong).
  39. Overrides []string
  40. }
  41. type AndroidAppSet struct {
  42. android.ModuleBase
  43. android.DefaultableModuleBase
  44. prebuilt android.Prebuilt
  45. properties AndroidAppSetProperties
  46. packedOutput android.WritablePath
  47. primaryOutput android.WritablePath
  48. apkcertsFile android.ModuleOutPath
  49. }
  50. func (as *AndroidAppSet) Name() string {
  51. return as.prebuilt.Name(as.ModuleBase.Name())
  52. }
  53. func (as *AndroidAppSet) IsInstallable() bool {
  54. return true
  55. }
  56. func (as *AndroidAppSet) Prebuilt() *android.Prebuilt {
  57. return &as.prebuilt
  58. }
  59. func (as *AndroidAppSet) Privileged() bool {
  60. return Bool(as.properties.Privileged)
  61. }
  62. func (as *AndroidAppSet) OutputFile() android.Path {
  63. return as.primaryOutput
  64. }
  65. func (as *AndroidAppSet) PackedAdditionalOutputs() android.Path {
  66. return as.packedOutput
  67. }
  68. func (as *AndroidAppSet) APKCertsFile() android.Path {
  69. return as.apkcertsFile
  70. }
  71. var TargetCpuAbi = map[string]string{
  72. "arm": "ARMEABI_V7A",
  73. "arm64": "ARM64_V8A",
  74. // TODO: use "RISCV64" when that is supported in bundles
  75. "riscv64": "ARM64_V8A",
  76. "x86": "X86",
  77. "x86_64": "X86_64",
  78. }
  79. func SupportedAbis(ctx android.ModuleContext, excludeNativeBridgeAbis bool) []string {
  80. abiName := func(targetIdx int, deviceArch string) string {
  81. if abi, found := TargetCpuAbi[deviceArch]; found {
  82. return abi
  83. }
  84. ctx.ModuleErrorf("Target %d has invalid Arch: %s", targetIdx, deviceArch)
  85. return "BAD_ABI"
  86. }
  87. var result []string
  88. for i, target := range ctx.Config().Targets[android.Android] {
  89. if target.NativeBridge == android.NativeBridgeEnabled && excludeNativeBridgeAbis {
  90. continue
  91. }
  92. result = append(result, abiName(i, target.Arch.ArchType.String()))
  93. }
  94. return result
  95. }
  96. func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  97. as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
  98. as.primaryOutput = android.PathForModuleOut(ctx, as.BaseModuleName()+".apk")
  99. as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
  100. // We are assuming here that the install file in the APK
  101. // set has `.apk` suffix. If it doesn't the build will fail.
  102. // APK sets containing APEX files are handled elsewhere.
  103. screenDensities := "all"
  104. if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 {
  105. screenDensities = strings.ToUpper(strings.Join(dpis, ","))
  106. }
  107. // TODO(asmundak): handle locales.
  108. // TODO(asmundak): do we support device features
  109. ctx.Build(pctx,
  110. android.BuildParams{
  111. Rule: extractMatchingApks,
  112. Description: "Extract APKs from APK set",
  113. Output: as.primaryOutput,
  114. ImplicitOutputs: android.WritablePaths{as.packedOutput, as.apkcertsFile},
  115. Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)},
  116. Args: map[string]string{
  117. "abis": strings.Join(SupportedAbis(ctx, false), ","),
  118. "allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
  119. "screen-densities": screenDensities,
  120. "sdk-version": ctx.Config().PlatformSdkVersion().String(),
  121. "skip-sdk-check": strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")),
  122. "stem": as.BaseModuleName(),
  123. "apkcerts": as.apkcertsFile.String(),
  124. "partition": as.PartitionTag(ctx.DeviceConfig()),
  125. "zip": as.packedOutput.String(),
  126. },
  127. })
  128. var installDir android.InstallPath
  129. if as.Privileged() {
  130. installDir = android.PathForModuleInstall(ctx, "priv-app", as.BaseModuleName())
  131. } else {
  132. installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName())
  133. }
  134. ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk", as.primaryOutput, as.packedOutput)
  135. }
  136. func (as *AndroidAppSet) InstallBypassMake() bool { return true }
  137. // android_app_set extracts a set of APKs based on the target device
  138. // configuration and installs this set as "split APKs".
  139. // The extracted set always contains an APK whose name is
  140. // _module_name_.apk and every split APK matching target device.
  141. // The extraction of the density-specific splits depends on
  142. // PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should
  143. // be a list density names: LDPI, MDPI, HDPI, etc.), only listed
  144. // splits will be extracted. Otherwise all density-specific splits
  145. // will be extracted.
  146. func AndroidAppSetFactory() android.Module {
  147. module := &AndroidAppSet{}
  148. module.AddProperties(&module.properties)
  149. InitJavaModule(module, android.DeviceSupported)
  150. android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set")
  151. return module
  152. }