Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/java/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 30 kB image not shown  

Quelle  app_import.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2020 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package java

// This file contains the module implementations for android_app_import and android_test_import.

import (
 "path/filepath"
 "reflect"
 "strings"

 "github.com/google/blueprint"

 "github.com/google/blueprint/proptools"

 "android/soong/android"
 "android/soong/provenance"
)

//go:generate go run ../../blueprint/gobtools/codegen

func init() {
 RegisterAppImportBuildComponents(android.InitRegistrationContext)

 initAndroidAppImportVariantGroupTypes()
}

var (
 uncompressEmbeddedJniLibsRule = pctx.AndroidStaticRule("uncompress-embedded-jni-libs", blueprint.RuleParams{
  Command2: blueprint.NewCommand(
   `if (`, android.ZipInfo, ` $in 'lib/*.so' 2>/dev/null | `,
   android.Grep, ` -v ' stor ' >/dev/null) ; then `,
   android.Zip2zip, ` -i $in -o $out -0 'lib/**/*.so'`,
   `; else `, android.Cp, ` -f $in $out; fi`,
  ),
  Description: "Uncompress embedded JNI libs",
 })

 stripEmbeddedJniLibsUnusedArchRule = pctx.AndroidStaticRule("strip-embedded-jni-libs-from-unused-arch", blueprint.RuleParams{
  Command2: blueprint.NewCommand(
   android.Zip2zip, ` -i $in -o $out -x 'lib/**/*.so' $extraArgs`,
  ),
  Description: "Remove all JNI libs from unused architectures",
 }, "extraArgs")

 uncompressDexRule = pctx.AndroidStaticRule("uncompress-dex", blueprint.RuleParams{
  Command2: blueprint.NewCommand(
   `if (`, android.ZipInfo, ` $in '*.dex' 2>/dev/null | `,
   android.Grep, ` -v ' stor ' >/dev/null) ; then `,
   android.Zip2zip, ` -i $in -o $out -0 'classes*.dex'`,
   `; else `, android.Cp, ` -f $in $out; fi`,
  ),
  Description: "Uncompress dex files",
 })

 checkPresignedApkRule = pctx.AndroidStaticRule("check-presigned-apk", blueprint.RuleParams{
  Command:         "build/soong/scripts/check_prebuilt_presigned_apk.py --aapt2 ${config.Aapt2Cmd} --zipalign ${config.ZipAlign} $extraArgs $in $out",
  CommandDeps:     []string{"build/soong/scripts/check_prebuilt_presigned_apk.py", "${config.Aapt2Cmd}", "${config.ZipAlign}"},
  Description:     "Check presigned apk",
  SandboxDisabled: true,
 }, "extraArgs")

 extractApkRule = pctx.AndroidStaticRule("extract-apk", blueprint.RuleParams{
  Command2: blueprint.NewCommand(
   android.ZipSync, ` -d $out.tmpdir $in && `,
   android.Cp, ` $out.tmpdir/$extract_apk $out && `,
   android.Rm, ` -rf $out.tmpdir`,
  ),
  Description: "Extract specific sub apk",
 }, "extract_apk")

 gzipRule = pctx.AndroidStaticRule("gzip",
  blueprint.RuleParams{
   Command2: blueprint.NewCommand(
    android.Gzip, ` -9 -c $in > $out`,
   ),
   Description: "gzip $out",
  })
)

func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
 ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory)
 ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory)
 ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
  ctx.BottomUp("disable_prebuilts_without_apk", disablePrebuiltsWithoutApkMutator)
 })
}

type AndroidAppImport struct {
 android.ModuleBase
 android.DefaultableModuleBase
 android.ApexModuleBase
 // TODO(b/461815001): remove this and replace usage of WalkDepsProxy with
 //  VisitDirectDepsProxy and DepSets.
 blueprint.ModuleUsesIncrementalWalkDeps
 prebuilt android.Prebuilt

 properties       AndroidAppImportProperties
 dpiVariants      interface{}
 archVariants     interface{}
 arch_dpiVariants interface{}

 outputFile  android.Path
 certificate Certificate

 dexpreopter

 usesLibrary usesLibrary

 installPath android.InstallPath
}

type AndroidAppImportProperties struct {
 // A prebuilt apk to import
 Apk proptools.Configurable[string] `android:"path,replace_instead_of_append"`

 // The name of a certificate in the default certificate directory or an android_app_certificate
 // module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
 Certificate proptools.Configurable[string] `android:"replace_instead_of_append"`

 // Names of extra android_app_certificate modules to sign the apk with in the form ":module".
 Additional_certificates []string

 // Set this flag to true if the prebuilt apk is already signed. The certificate property must not
 // be set for presigned modules.
 Presigned proptools.Configurable[bool] `android:"replace_instead_of_append"`

 // Name of the signing certificate lineage file or filegroup module.
 Lineage *string `android:"path"`

 // For overriding the --rotation-min-sdk-version property of apksig
 RotationMinSdkVersion *string

 // Sign with the default system dev certificate. Must be used judiciously. Most imported apps
 // need to either specify a specific certificate or be presigned.
 Default_dev_cert *bool

 // Specifies that this app should be installed to the priv-app directory,
 // where the system will grant it additional privileges not available to
 // normal apps.
 Privileged *bool

 // Names of modules to be overridden. Listed modules can only be other binaries
 // (in Make or Soong).
 // This does not completely prevent installation of the overridden binaries, but if both
 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
 // from PRODUCT_PACKAGES.
 Overrides []string

 // Optional name for the installed app. If unspecified, it is derived from the module name.
 Filename *string

 // If set, create package-export.apk, which other packages can
 // use to get PRODUCT-agnostic resource data like IDs and type definitions.
 Export_package_resources *bool

 // Optional. Install to a subdirectory of the default install path for the module
 Relative_install_path *string

 // Optional. Control the install path without module name subdirectory.
 Install_path_skip_module_dir *bool

 // Whether the prebuilt apk can be installed without additional processing. Default is false.
 Preprocessed proptools.Configurable[bool] `android:"replace_instead_of_append"`

 // Whether or not to skip checking the preprocessed apk for proper alignment and uncompressed
 // JNI libs and dex files. Default is false
 Skip_preprocessed_apk_checks *bool

 // Name of the source soong module that gets shadowed by this prebuilt
 // If unspecified, follows the naming convention that the source module of
 // the prebuilt is Name() without "prebuilt_" prefix
 Source_module_name *string

 // Whether stripping all libraries from unused architectures.
 Strip_unused_jni_arch *bool

 // Path to the .prebuilt_info file of the prebuilt app.
 // In case of mainline modules, the .prebuilt_info file contains the build_id that was used
 // to generate the prebuilt.
 Prebuilt_info *string `android:"path"`

 // Path of extracted apk which is extracted from prebuilt apk. Use this extracted to import.
 Extract_apk proptools.Configurable[string]

 // Compress the output APK using gzip. Defaults to false.
 Compress_apk proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
}

func (a *AndroidAppImport) IsInstallable() bool {
 return true
}

// Updates properties with variant-specific values.
// This happens as a DefaultableHook instead of a LoadHook because we want to run it after
// soong config variables are applied.
func (a *AndroidAppImport) processVariants(ctx android.DefaultableHookContext) {
 config := ctx.Config()
 dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName(DpiGroupName)

 // Try DPI variant matches in the reverse-priority order so that the highest priority match
 // overwrites everything else.
 // TODO(jungjw): Can we optimize this by making it priority order?
 for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- {
  MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPrebuiltDPI()[i])
 }
 if config.ProductAAPTPreferredConfig() != "" {
  MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPreferredConfig())
 }
 archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName(ArchGroupName)
 archType := ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType
 MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)

 // Process "arch" includes "dpi_variants"
 archStructPtr := reflect.ValueOf(a.arch_dpiVariants).Elem().FieldByName(ArchGroupName)
 if archStruct := archStructPtr.Elem(); archStruct.IsValid() {
  archPartPropsPtr := archStruct.FieldByName(proptools.FieldNameForProperty(archType.Name))
  if archPartProps := archPartPropsPtr.Elem(); archPartProps.IsValid() {
   archDpiPropsPtr := archPartProps.FieldByName(DpiGroupName)
   if archDpiProps := archDpiPropsPtr.Elem(); archDpiProps.IsValid() {
    for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- {
     MergePropertiesFromVariant(ctx, &a.properties, archDpiProps, config.ProductAAPTPrebuiltDPI()[i])
    }
    if config.ProductAAPTPreferredConfig() != "" {
     MergePropertiesFromVariant(ctx, &a.properties, archDpiProps, config.ProductAAPTPreferredConfig())
    }
   }
  }
 }
}

func MergePropertiesFromVariant(ctx android.EarlyModuleContext,
 dst interface{}, variantGroup reflect.Value, variant string) {
 src := variantGroup.FieldByName(proptools.FieldNameForProperty(variant))
 if !src.IsValid() {
  return
 }

 err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, proptools.OrderAppend)
 if err != nil {
  if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
   ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
  } else {
   panic(err)
  }
 }
}

// disablePrebuiltsWithoutApkMutator is a pre-arch mutator that disables AndroidAppImport or
// AndroidTestImport modules that don't have an apk set. We need this separate mutator instead
// of doing it in processVariants because processVariants is a defaultable hook, and configurable
// properties can only be evaluated after the defaults (and eventually, base configurabtion)
// mutators.
func disablePrebuiltsWithoutApkMutator(ctx android.BottomUpMutatorContext) {
 switch a := ctx.Module().(type) {
 case *AndroidAppImport:
  if a.properties.Apk.GetOrDefault(ctx, "") == "" {
   // Disable this module since the apk property is still empty after processing all
   // matching variants. This likely means there is no matching variant, and the default
   // variant doesn't have an apk property value either.
   a.Disable()
  }
 case *AndroidTestImport:
  if a.properties.Apk.GetOrDefault(ctx, "") == "" {
   // Disable this module since the apk property is still empty after processing all
   // matching variants. This likely means there is no matching variant, and the default
   // variant doesn't have an apk property value either.
   a.Disable()
  }
 }
}

func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
 a.dexpreopter.DepsMutator(ctx)

 cert := android.SrcIsModule(a.properties.Certificate.GetOrDefault(ctx, ""))
 if cert != "" {
  ctx.AddDependency(ctx.Module(), certificateTag, cert)
 }

 for _, cert := range a.properties.Additional_certificates {
  cert = android.SrcIsModule(cert)
  if cert != "" {
   ctx.AddDependency(ctx.Module(), certificateTag, cert)
  } else {
   ctx.PropertyErrorf("additional_certificates",
    `must be names of android_app_certificate modules in the form ":module"`)
  }
 }

 a.usesLibrary.deps(ctx, true)
}

func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
 ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) {
 // Test apps don't need their JNI libraries stored uncompressed. As a matter of fact, messing
 // with them may invalidate pre-existing signature data.
 if ctx.InstallInTestcases() && (a.properties.Presigned.GetOrDefault(ctx, false) || a.properties.Preprocessed.GetOrDefault(ctx, false)) {
  ctx.Build(pctx, android.BuildParams{
   Rule:   android.CpRule,
   Output: outputPath,
   Input:  inputPath,
  })
  return
 }

 ctx.Build(pctx, android.BuildParams{
  Rule:   uncompressEmbeddedJniLibsRule,
  Input:  inputPath,
  Output: outputPath,
 })
}

func (a *AndroidAppImport) extractSubApk(
 ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) {
 extractApkPath := a.properties.Extract_apk.GetOrDefault(ctx, "")
 ctx.Build(pctx, android.BuildParams{
  Rule:   extractApkRule,
  Input:  inputPath,
  Output: outputPath,
  Args: map[string]string{
   "extract_apk": extractApkPath,
  },
 })
}

// Returns whether this module should have the dex file stored uncompressed in the APK.
func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
 if ctx.Config().UnbundledBuild() || a.properties.Preprocessed.GetOrDefault(ctx, false) {
  return false
 }

 // Uncompress dex in APKs of priv-apps if and only if DONT_UNCOMPRESS_PRIV_APPS_DEXS is false.
 if a.Privileged() {
  return ctx.Config().UncompressPrivAppDex()
 }

 return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter)
}

func (a *AndroidAppImport) stripEmbeddedJniLibsUnusedArch(
 ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) {
 var wantedJniLibSlice []string
 for _, target := range ctx.MultiTargets() {
  supported_abis := target.Arch.Abi
  for _, arch := range supported_abis {
   wantedJniLibSlice = append(wantedJniLibSlice, " -X 'lib/"+arch+"/*.so'")
  }
 }
 wantedJniLibString := strings.Join(wantedJniLibSlice, " ")
 ctx.Build(pctx, android.BuildParams{
  Rule:   stripEmbeddedJniLibsUnusedArchRule,
  Input:  inputPath,
  Output: outputPath,
  Args: map[string]string{
   "extraArgs": wantedJniLibString,
  },
 })
}

func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 a.generateAndroidBuildActions(ctx)

 moduleInfoJSON := ctx.ModuleInfoJSON()
 moduleInfoJSON.Class = []string{"APPS"}
 moduleInfoJSON.SystemSharedLibs = []string{"none"}

 appInfo := &AppInfo{
  Prebuilt: true,
 }
 setCommonAppInfo(appInfo, a)
 android.SetProvider(ctx, AppInfoProvider, appInfo)
 android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
  Certificate: appInfo.Certificate,
  Name:        appInfo.InstallApkName + ".apk",
 })
}

func (a *AndroidAppImport) InstallApkName() string {
 return a.BaseModuleName()
}

func (a *AndroidAppImport) BaseModuleName() string {
 return proptools.StringDefault(a.properties.Source_module_name, a.ModuleBase.Name())
}

func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext) {
 if a.Name() == "prebuilt_framework-res" {
  ctx.ModuleErrorf("prebuilt_framework-res found. This used to have special handling in soong, but was removed due to prebuilt_framework-res no longer existing. This check is to ensure it doesn't come back without readding the special handling.")
 }

 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
 if !apexInfo.IsForPlatform() {
  // The non-platform variant is placed inside APEX. No reason to
  // make it available to Make.
  a.HideFromMake()
 }

 if a.properties.Preprocessed.GetOrDefault(ctx, false) {
  if !a.properties.Presigned.GetOrDefault(ctx, true) {
   ctx.ModuleErrorf("Setting preprocessed: true implies presigned: true, so you cannot set presigned to false")
  }
  a.properties.Presigned.AppendSimpleValue(true)
 }

 numCertPropsSet := 0
 if a.properties.Certificate.GetOrDefault(ctx, "") != "" {
  numCertPropsSet++
 }
 if a.properties.Presigned.GetOrDefault(ctx, false) {
  numCertPropsSet++
 }
 if Bool(a.properties.Default_dev_cert) {
  numCertPropsSet++
 }
 if numCertPropsSet != 1 {
  ctx.ModuleErrorf("One and only one of certficate, presigned (implied by preprocessed), and default_dev_cert properties must be set")
 }

 // TODO: LOCAL_PACKAGE_SPLITS

 srcApk := a.prebuilt.SingleSourcePath(ctx)
 if a.properties.Extract_apk.GetOrDefault(ctx, "") != "" {
  extract_apk := android.PathForModuleOut(ctx, "extract-apk", ctx.ModuleName()+".apk")
  a.extractSubApk(ctx, srcApk, extract_apk)
  srcApk = extract_apk
 }

 // TODO: Install or embed JNI libraries

 // Uncompress JNI libraries in the apk
 jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk")
 a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed)

 // Strip all embedded JNI libs and include only required ones accordingly to the module's compile_multilib
 if Bool(a.properties.Strip_unused_jni_arch) {
  jnisStripped := android.PathForModuleOut(ctx, "jnis-stripped", ctx.ModuleName()+".apk")
  a.stripEmbeddedJniLibsUnusedArch(ctx, jnisUncompressed, jnisStripped)
  jnisUncompressed = jnisStripped
 }

 var pathFragments []string
 relInstallPath := String(a.properties.Relative_install_path)
 if !proptools.Bool(a.properties.Install_path_skip_module_dir) {
  // Default add module name folder into install path.
  relInstallPath = filepath.Join(relInstallPath, a.BaseModuleName())
 }

 if Bool(a.properties.Privileged) {
  pathFragments = append([]string{"priv-app"}, relInstallPath)
 } else if ctx.InstallInTestcases() {
  pathFragments = []string{relInstallPath, ctx.DeviceConfig().DeviceArch()}
 } else {
  pathFragments = []string{"app", relInstallPath}
 }

 installDir := android.PathForModuleInstall(ctx, pathFragments...)
 a.dexpreopter.isApp = true
 a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
 a.dexpreopter.isPresignedPrebuilt = a.properties.Presigned.GetOrDefault(ctx, false)
 a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)

 a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries(ctx)
 a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)

 // Disable Dexpreopt if Compress_apk is true. It follows the build/make/core/app_prebuilt_internal.mk
 if a.usesLibrary.shouldDisableDexpreopt || a.properties.Compress_apk.GetOrDefault(ctx, false) {
  a.dexpreopter.disableDexpreopt()
 }

 if a.usesLibrary.enforceUsesLibraries(ctx) {
  a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk, &a.dexpreopter.classLoaderContexts)
 }

 a.dexpreopter.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), jnisUncompressed)
 if a.dexpreopter.uncompressedDex {
  dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
  ctx.Build(pctx, android.BuildParams{
   Rule:   uncompressDexRule,
   Input:  jnisUncompressed,
   Output: dexUncompressed,
  })
  jnisUncompressed = dexUncompressed
 }

 defaultApkFilename := a.BaseModuleName()
 if a.properties.Compress_apk.GetOrDefault(ctx, false) {
  defaultApkFilename += ".apk.gz"
 } else {
  defaultApkFilename += ".apk"
 }
 apkFilename := proptools.StringDefault(a.properties.Filename, defaultApkFilename)

 // TODO: Handle EXTERNAL

 // Sign or align the package if package has not been preprocessed

 if a.properties.Preprocessed.GetOrDefault(ctx, false) {
  validationStamp := a.validatePresignedApk(ctx, srcApk)
  output := android.PathForModuleOut(ctx, apkFilename)
  ctx.Build(pctx, android.BuildParams{
   Rule:       android.CpRule,
   Input:      srcApk,
   Output:     output,
   Validation: validationStamp,
  })
  a.outputFile = output
  a.certificate = PresignedCertificate
 } else if !a.properties.Presigned.GetOrDefault(ctx, false) {
  // If the certificate property is empty at this point, default_dev_cert must be set to true.
  // Which makes processMainCert's behavior for the empty cert string WAI.
  _, _, certificates := collectAppDeps(ctx, a, false, false)
  a.certificate, certificates = processMainCert(a.ModuleBase, a.properties.Certificate.GetOrDefault(ctx, ""), certificates, ctx)
  signed := android.PathForModuleOut(ctx, "signed", apkFilename)
  var lineageFile android.Path
  if lineage := String(a.properties.Lineage); lineage != "" {
   lineageFile = android.PathForModuleSrc(ctx, lineage)
  }

  rotationMinSdkVersion := String(a.properties.RotationMinSdkVersion)

  SignAppPackage(ctx, signed, jnisUncompressed, certificates, nil, lineageFile,
   rotationMinSdkVersion, a.MinSdkVersion(ctx))
  a.outputFile = signed
 } else {
  validationStamp := a.validatePresignedApk(ctx, srcApk)
  alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
  TransformZipAlign(ctx, alignedApk, jnisUncompressed, []android.Path{validationStamp})
  a.outputFile = alignedApk
  a.certificate = PresignedCertificate
 }

 if a.properties.Compress_apk.GetOrDefault(ctx, false) {
  outputFile := android.PathForModuleOut(ctx, "compressed_apk", apkFilename)
  ctx.Build(pctx, android.BuildParams{
   Rule:        gzipRule,
   Input:       a.outputFile,
   Output:      outputFile,
   Description: "Compressing " + a.outputFile.Base(),
  })
  a.outputFile = outputFile
 }

 if apexInfo.IsForPlatform() {
  a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
  artifactPath := android.PathForModuleSrc(ctx, a.properties.Apk.GetOrDefault(ctx, ""))
  provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
 }

 providePrebuiltInfo(ctx,
  prebuiltInfoProps{
   baseModuleName: a.BaseModuleName(),
   isPrebuilt:     true,
   prebuiltInfo:   a.properties.Prebuilt_info,
  },
 )

 ctx.SetOutputFiles([]android.Path{a.outputFile}, "")

 buildComplianceMetadata(ctx)
 src := a.prebuilt.SingleSource(ctx)
 ctx.ComplianceMetadataInfo().SetPrebuiltSrc(ctx, src)

 // TODO: androidmk converter jni libs
}

func (a *AndroidAppImport) validatePresignedApk(ctx android.ModuleContext, srcApk android.Path) android.Path {
 stamp := android.PathForModuleOut(ctx, "validated-prebuilt", "check.stamp")
 var extraArgs []string
 if a.Privileged() {
  extraArgs = append(extraArgs, "--privileged")
  if ctx.Config().UncompressPrivAppDex() {
   extraArgs = append(extraArgs, "--uncompress-priv-app-dex")
  }
 }
 if proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
  extraArgs = append(extraArgs, "--skip-preprocessed-apk-checks")
 }
 if a.properties.Preprocessed.GetOrDefault(ctx, false) {
  extraArgs = append(extraArgs, "--preprocessed")
 }

 ctx.Build(pctx, android.BuildParams{
  Rule:   checkPresignedApkRule,
  Input:  srcApk,
  Output: stamp,
  Args: map[string]string{
   "extraArgs": strings.Join(extraArgs, " "),
  },
 })
 return stamp
}

func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
 return &a.prebuilt
}

func (a *AndroidAppImport) Name() string {
 return a.prebuilt.Name(a.ModuleBase.Name())
}

func (a *AndroidAppImport) OutputFile() android.Path {
 return a.outputFile
}

func (a *AndroidAppImport) JacocoInfo() JacocoInfo {
 return JacocoInfo{}
}

func (a *AndroidAppImport) Certificate() Certificate {
 return a.certificate
}

func (a *AndroidAppImport) PrivAppAllowlist() android.OptionalPath {
 return android.OptionalPath{}
}

func (a *AndroidAppImport) PreinstallAllowlist() android.OptionalPath {
 return android.OptionalPath{}
}

const (
 ArchGroupName = "Arch"
 DpiGroupName  = "Dpi_variants"
)

var dpiVariantGroupType reflect.Type
var archVariantGroupType reflect.Type
var archdpiVariantGroupType reflect.Type
var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}

func initAndroidAppImportVariantGroupTypes() {
 dpiVariantGroupType = createVariantGroupType(supportedDpis, DpiGroupName)

 archNames := make([]string, len(android.ArchTypeList()))
 for i, archType := range android.ArchTypeList() {
  archNames[i] = archType.Name
 }
 archVariantGroupType = createVariantGroupType(archNames, ArchGroupName)
 archdpiVariantGroupType = createArchDpiVariantGroupType(archNames, supportedDpis)
}

// Populates all variant struct properties at creation time.
func (a *AndroidAppImport) populateAllVariantStructs() {
 a.dpiVariants = reflect.New(dpiVariantGroupType).Interface()
 a.AddProperties(a.dpiVariants)

 a.archVariants = reflect.New(archVariantGroupType).Interface()
 a.AddProperties(a.archVariants)

 a.arch_dpiVariants = reflect.New(archdpiVariantGroupType).Interface()
 a.AddProperties(a.arch_dpiVariants)
}

func (a *AndroidAppImport) Privileged() bool {
 return Bool(a.properties.Privileged)
}

func (m *AndroidAppImport) GetDepInSameApexChecker() android.DepInSameApexChecker {
 return AppImportDepInSameApexChecker{}
}

// @auto-generate: gob
type AppImportDepInSameApexChecker struct {
 android.BaseDepInSameApexChecker
}

func (m AppImportDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
 // android_app_import might have extra dependencies via uses_libs property.
 // Don't track the dependency as we don't automatically add those libraries
 // to the classpath. It should be explicitly added to java_libs property of APEX
 return false
}

func (a *AndroidAppImport) SdkVersion(ctx android.ConfigContext) android.SdkSpec {
 return android.SdkSpecPrivate
}

func (a *AndroidAppImport) MinSdkVersion(ctx android.MinSdkVersionFromValueContext) android.ApiLevel {
 return android.SdkSpecPrivate.ApiLevel
}

var _ android.ApexModule = (*AndroidAppImport)(nil)

// Implements android.ApexModule
func (m *AndroidAppImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
 return android.MinApiLevel
}

func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
 props := reflect.TypeOf((*AndroidAppImportProperties)(nil))

 variantFields := make([]reflect.StructField, len(variants))
 for i, variant := range variants {
  variantFields[i] = reflect.StructField{
   Name: proptools.FieldNameForProperty(variant),
   Type: props,
  }
 }

 variantGroupStruct := reflect.StructOf(variantFields)
 return reflect.StructOf([]reflect.StructField{
  {
   Name: variantGroupName,
   Type: variantGroupStruct,
  },
 })
}

func createArchDpiVariantGroupType(archNames []string, dpiNames []string) reflect.Type {
 props := reflect.TypeOf((*AndroidAppImportProperties)(nil))

 dpiVariantFields := make([]reflect.StructField, len(dpiNames))
 for i, variant_dpi := range dpiNames {
  dpiVariantFields[i] = reflect.StructField{
   Name: proptools.FieldNameForProperty(variant_dpi),
   Type: props,
  }
 }
 dpiVariantGroupStruct := reflect.StructOf(dpiVariantFields)
 dpi_struct := reflect.StructOf([]reflect.StructField{
  {
   Name: DpiGroupName,
   Type: reflect.PointerTo(dpiVariantGroupStruct),
  },
 })

 archVariantFields := make([]reflect.StructField, len(archNames))
 for i, variant_arch := range archNames {
  archVariantFields[i] = reflect.StructField{
   Name: proptools.FieldNameForProperty(variant_arch),
   Type: reflect.PointerTo(dpi_struct),
  }
 }
 archVariantGroupStruct := reflect.StructOf(archVariantFields)

 return_struct := reflect.StructOf([]reflect.StructField{
  {
   Name: ArchGroupName,
   Type: reflect.PointerTo(archVariantGroupStruct),
  },
 })
 return return_struct
}

func (a *AndroidAppImport) UsesLibrary() *usesLibrary {
 return &a.usesLibrary
}

var _ ModuleWithUsesLibrary = (*AndroidAppImport)(nil)

// android_app_import imports a prebuilt apk with additional processing specified in the module.
// DPI-specific apk source files can be specified using dpi_variants. Example:
//
// android_app_import {
//     name: "example_import",
//     apk: "prebuilts/example.apk",
//     dpi_variants: {
//         mdpi: {
//             apk: "prebuilts/example_mdpi.apk",
//         },
//         xhdpi: {
//             apk: "prebuilts/example_xhdpi.apk",
//         },
//     },
//     presigned: true,
// }
func AndroidAppImportFactory() android.Module {
 module := &AndroidAppImport{}
 module.AddProperties(&module.properties)
 module.AddProperties(&module.dexpreoptProperties)
 module.AddProperties(&module.usesLibrary.usesLibraryProperties)
 module.populateAllVariantStructs()
 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
  module.processVariants(ctx)
 })

 android.InitApexModule(module)
 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 android.InitDefaultableModule(module)
 android.InitConfigurablePrebuiltModuleString(module, &module.properties.Apk, "Apk")

 module.usesLibrary.enforce = true

 return module
}

type AndroidTestImport struct {
 AndroidAppImport

 testProperties struct {
  // list of compatibility suites (for example "cts", "vts") that the module should be
  // installed into.
  Test_suites []string `android:"arch_variant"`

  // list of files or filegroup modules that provide data that should be installed alongside
  // the test
  Data []string `android:"path"`

  // Install the test into a folder named for the module in all test suites.
  Per_testcase_directory *bool
 }

 data android.Paths
}

func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 a.generateAndroidBuildActions(ctx)

 a.updateModuleInfoJSON(ctx)

 a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)

 var data []android.DataPath
 for _, d := range a.data {
  data = append(data, android.DataPath{SrcPath: d})
 }

 ctx.SetTestSuiteInfo(android.TestSuiteInfo{
  TestSuites:                a.testProperties.Test_suites,
  MainFile:                  a.outputFile,
  MainFileStem:              a.outputFile.Base(),
  NeedsArchFolder:           true,
  Data:                      data,
  CompatibilitySupportFiles: a.data,
 })

 android.SetProvider(ctx, ApkCertInfoProvider, ApkCertInfo{
  Certificate: a.Certificate(),
  Name:        a.InstallApkName() + ".apk",
  Test:        true,
 })
}

func (a *AndroidTestImport) updateModuleInfoJSON(ctx android.ModuleContext) {
 moduleInfoJSON := ctx.ModuleInfoJSON()
 moduleInfoJSON.Class = []string{"APPS"}
 moduleInfoJSON.CompatibilitySuites = []string{"null-suite"}
 if len(a.testProperties.Test_suites) > 0 {
  moduleInfoJSON.CompatibilitySuites = a.testProperties.Test_suites
 }
 moduleInfoJSON.SystemSharedLibs = []string{"none"}
 moduleInfoJSON.Tags = []string{"tests"}
 moduleInfoJSON.RegisterNameOverride = a.BaseModuleName()
 testConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml")
 if testConfig.Valid() {
  moduleInfoJSON.TestConfig = []string{testConfig.String()}
 }
}

func (a *AndroidTestImport) InstallInTestcases() bool {
 return true
}

// android_test_import imports a prebuilt test apk with additional processing specified in the
// module. DPI or arch variant configurations can be made as with android_app_import.
func AndroidTestImportFactory() android.Module {
 module := &AndroidTestImport{}
 module.AddProperties(&module.properties)
 module.AddProperties(&module.dexpreoptProperties)
 module.AddProperties(&module.testProperties)
 module.populateAllVariantStructs()
 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
  module.processVariants(ctx)
 })

 module.dexpreopter.isTest = true

 android.InitApexModule(module)
 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 android.InitDefaultableModule(module)
 android.InitConfigurablePrebuiltModuleString(module, &module.properties.Apk, "Apk")

 return module
}

[Dauer der Verarbeitung: 0.26 Sekunden, vorverarbeitet 2026-06-28]