2020-12-21 21:29:12 +01:00
// 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 (
2023-07-07 20:32:32 +02:00
"fmt"
2020-12-21 21:29:12 +01:00
"reflect"
2023-09-07 01:11:44 +02:00
"strings"
2020-12-21 21:29:12 +01:00
2023-04-14 00:43:53 +02:00
"github.com/google/blueprint"
2020-12-21 21:29:12 +01:00
"github.com/google/blueprint/proptools"
"android/soong/android"
2022-03-19 01:33:24 +01:00
"android/soong/provenance"
2020-12-21 21:29:12 +01:00
)
func init ( ) {
RegisterAppImportBuildComponents ( android . InitRegistrationContext )
initAndroidAppImportVariantGroupTypes ( )
}
2023-01-13 21:03:38 +01:00
var (
uncompressEmbeddedJniLibsRule = pctx . AndroidStaticRule ( "uncompress-embedded-jni-libs" , blueprint . RuleParams {
Command : ` if (zipinfo $in 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then ` +
` $ { config.Zip2ZipCmd} -i $in -o $out -0 'lib/**/*.so' ` +
` ; else cp -f $in $out; fi ` ,
CommandDeps : [ ] string { "${config.Zip2ZipCmd}" } ,
Description : "Uncompress embedded JNI libs" ,
} )
uncompressDexRule = pctx . AndroidStaticRule ( "uncompress-dex" , blueprint . RuleParams {
Command : ` if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then ` +
` $ { config.Zip2ZipCmd} -i $in -o $out -0 'classes*.dex' ` +
` ; else cp -f $in $out; fi ` ,
CommandDeps : [ ] string { "${config.Zip2ZipCmd}" } ,
Description : "Uncompress dex files" ,
} )
2023-04-18 00:06:56 +02:00
2023-09-07 01:11:44 +02:00
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" ,
} , "extraArgs" )
2023-01-13 21:03:38 +01:00
)
2020-12-21 21:29:12 +01:00
func RegisterAppImportBuildComponents ( ctx android . RegistrationContext ) {
ctx . RegisterModuleType ( "android_app_import" , AndroidAppImportFactory )
ctx . RegisterModuleType ( "android_test_import" , AndroidTestImportFactory )
}
type AndroidAppImport struct {
android . ModuleBase
android . DefaultableModuleBase
android . ApexModuleBase
prebuilt android . Prebuilt
2024-01-29 06:57:51 +01:00
properties AndroidAppImportProperties
dpiVariants interface { }
archVariants interface { }
arch_dpiVariants interface { }
2020-12-21 21:29:12 +01:00
outputFile android . Path
certificate Certificate
dexpreopter
usesLibrary usesLibrary
installPath android . InstallPath
hideApexVariantFromMake bool
2022-03-19 01:33:24 +01:00
provenanceMetaDataFile android . OutputPath
2024-01-09 23:47:39 +01:00
// Single aconfig "cache file" merged from this module and all dependencies.
mergedAconfigFiles map [ string ] android . Paths
2020-12-21 21:29:12 +01:00
}
type AndroidAppImportProperties struct {
// A prebuilt apk to import
2021-06-28 14:48:51 +02:00
Apk * string ` android:"path" `
2020-12-21 21:29:12 +01:00
// 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 * string
2021-03-09 02:37:46 +01:00
// Names of extra android_app_certificate modules to sign the apk with in the form ":module".
Additional_certificates [ ] string
2020-12-21 21:29:12 +01:00
// Set this flag to true if the prebuilt apk is already signed. The certificate property must not
// be set for presigned modules.
Presigned * bool
2021-03-10 00:02:31 +01:00
// Name of the signing certificate lineage file or filegroup module.
Lineage * string ` android:"path" `
2020-12-21 21:29:12 +01:00
2021-11-03 15:39:39 +01:00
// For overriding the --rotation-min-sdk-version property of apksig
RotationMinSdkVersion * string
2020-12-21 21:29:12 +01:00
// 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
2021-01-09 01:09:09 +01:00
// 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
2021-05-18 19:01:41 +02:00
// Optional. Install to a subdirectory of the default install path for the module
Relative_install_path * string
2023-04-18 00:06:56 +02:00
// Whether the prebuilt apk can be installed without additional processing. Default is false.
Preprocessed * bool
// 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
2024-02-27 19:19:16 +01:00
// 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
2024-03-11 22:37:25 +01:00
// 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" `
2020-12-21 21:29:12 +01:00
}
func ( a * AndroidAppImport ) IsInstallable ( ) bool {
return true
}
// Updates properties with variant-specific values.
2024-01-12 23:02:47 +01:00
// 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 ) {
2020-12-21 21:29:12 +01:00
config := ctx . Config ( )
2024-01-29 06:57:51 +01:00
dpiProps := reflect . ValueOf ( a . dpiVariants ) . Elem ( ) . FieldByName ( DpiGroupName )
2020-12-21 21:29:12 +01:00
// 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 ( ) )
}
2024-01-29 06:57:51 +01:00
archProps := reflect . ValueOf ( a . archVariants ) . Elem ( ) . FieldByName ( ArchGroupName )
2020-12-21 21:29:12 +01:00
archType := ctx . Config ( ) . AndroidFirstDeviceTarget . Arch . ArchType
MergePropertiesFromVariant ( ctx , & a . properties , archProps , archType . Name )
2024-01-29 06:57:51 +01:00
// 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 ( ) )
}
}
}
}
2020-12-21 21:29:12 +01:00
if String ( a . properties . Apk ) == "" {
// 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 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 )
}
}
}
func ( a * AndroidAppImport ) DepsMutator ( ctx android . BottomUpMutatorContext ) {
cert := android . SrcIsModule ( String ( a . properties . Certificate ) )
if cert != "" {
ctx . AddDependency ( ctx . Module ( ) , certificateTag , cert )
}
2021-03-09 02:37:46 +01:00
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" ` )
}
}
2023-04-14 00:43:53 +02:00
a . usesLibrary . deps ( ctx , true )
2020-12-21 21:29:12 +01:00
}
func ( a * AndroidAppImport ) uncompressEmbeddedJniLibs (
ctx android . ModuleContext , inputPath android . Path , outputPath android . OutputPath ) {
// Test apps don't need their JNI libraries stored uncompressed. As a matter of fact, messing
// with them may invalidate pre-existing signature data.
2023-04-18 00:06:56 +02:00
if ctx . InstallInTestcases ( ) && ( Bool ( a . properties . Presigned ) || Bool ( a . properties . Preprocessed ) ) {
2020-12-21 21:29:12 +01:00
ctx . Build ( pctx , android . BuildParams {
Rule : android . Cp ,
Output : outputPath ,
Input : inputPath ,
} )
return
}
2023-01-13 21:03:38 +01:00
ctx . Build ( pctx , android . BuildParams {
Rule : uncompressEmbeddedJniLibsRule ,
Input : inputPath ,
Output : outputPath ,
} )
2020-12-21 21:29:12 +01:00
}
// Returns whether this module should have the dex file stored uncompressed in the APK.
func ( a * AndroidAppImport ) shouldUncompressDex ( ctx android . ModuleContext ) bool {
2023-04-18 00:06:56 +02:00
if ctx . Config ( ) . UnbundledBuild ( ) || proptools . Bool ( a . properties . Preprocessed ) {
2020-12-21 21:29:12 +01:00
return false
}
2021-09-01 16:40:38 +02:00
// 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 ( )
2020-12-21 21:29:12 +01:00
}
2024-01-24 00:56:29 +01:00
return shouldUncompressDex ( ctx , android . RemoveOptionalPrebuiltPrefix ( ctx . ModuleName ( ) ) , & a . dexpreopter )
2020-12-21 21:29:12 +01:00
}
func ( a * AndroidAppImport ) GenerateAndroidBuildActions ( ctx android . ModuleContext ) {
a . generateAndroidBuildActions ( ctx )
}
func ( a * AndroidAppImport ) InstallApkName ( ) string {
return a . BaseModuleName ( )
}
2024-02-27 19:19:16 +01:00
func ( a * AndroidAppImport ) BaseModuleName ( ) string {
return proptools . StringDefault ( a . properties . Source_module_name , a . ModuleBase . Name ( ) )
}
2020-12-21 21:29:12 +01:00
func ( a * AndroidAppImport ) generateAndroidBuildActions ( ctx android . ModuleContext ) {
2023-04-14 00:43:53 +02:00
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." )
}
2023-12-14 00:54:49 +01:00
apexInfo , _ := android . ModuleProvider ( ctx , android . ApexInfoProvider )
2020-12-21 21:29:12 +01:00
if ! apexInfo . IsForPlatform ( ) {
a . hideApexVariantFromMake = true
}
2023-07-15 01:23:39 +02:00
if Bool ( a . properties . Preprocessed ) {
if a . properties . Presigned != nil && ! * a . properties . Presigned {
ctx . ModuleErrorf ( "Setting preprocessed: true implies presigned: true, so you cannot set presigned to false" )
}
t := true
a . properties . Presigned = & t
}
2020-12-21 21:29:12 +01:00
numCertPropsSet := 0
if String ( a . properties . Certificate ) != "" {
numCertPropsSet ++
}
if Bool ( a . properties . Presigned ) {
numCertPropsSet ++
}
if Bool ( a . properties . Default_dev_cert ) {
numCertPropsSet ++
}
if numCertPropsSet != 1 {
2023-07-15 01:23:39 +02:00
ctx . ModuleErrorf ( "One and only one of certficate, presigned (implied by preprocessed), and default_dev_cert properties must be set" )
2020-12-21 21:29:12 +01:00
}
// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
// TODO: LOCAL_PACKAGE_SPLITS
srcApk := a . prebuilt . SingleSourcePath ( ctx )
// 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 . OutputPath )
2021-05-18 19:01:41 +02:00
var pathFragments [ ] string
relInstallPath := String ( a . properties . Relative_install_path )
2021-01-09 01:09:09 +01:00
2023-04-14 00:43:53 +02:00
if Bool ( a . properties . Privileged ) {
2021-05-18 19:01:41 +02:00
pathFragments = [ ] string { "priv-app" , relInstallPath , a . BaseModuleName ( ) }
2020-12-21 21:29:12 +01:00
} else if ctx . InstallInTestcases ( ) {
2021-05-18 19:01:41 +02:00
pathFragments = [ ] string { relInstallPath , a . BaseModuleName ( ) , ctx . DeviceConfig ( ) . DeviceArch ( ) }
2020-12-21 21:29:12 +01:00
} else {
2021-05-18 19:01:41 +02:00
pathFragments = [ ] string { "app" , relInstallPath , a . BaseModuleName ( ) }
2020-12-21 21:29:12 +01:00
}
2021-05-18 19:01:41 +02:00
installDir := android . PathForModuleInstall ( ctx , pathFragments ... )
2021-01-14 18:52:43 +01:00
a . dexpreopter . isApp = true
2020-12-21 21:29:12 +01:00
a . dexpreopter . installPath = installDir . Join ( ctx , a . BaseModuleName ( ) + ".apk" )
a . dexpreopter . isPresignedPrebuilt = Bool ( a . properties . Presigned )
a . dexpreopter . uncompressedDex = a . shouldUncompressDex ( ctx )
a . dexpreopter . enforceUsesLibs = a . usesLibrary . enforceUsesLibraries ( )
a . dexpreopter . classLoaderContexts = a . usesLibrary . classLoaderContextForUsesLibDeps ( ctx )
2024-02-13 17:37:43 +01:00
if a . usesLibrary . shouldDisableDexpreopt {
a . dexpreopter . disableDexpreopt ( )
}
2020-12-21 21:29:12 +01:00
2021-02-26 15:36:48 +01:00
if a . usesLibrary . enforceUsesLibraries ( ) {
Refactor the contruction of the manifest check inputs.
This is a no-op change for a majority of cases.
Before this change, the contruction of the manifest check inputs is
confusing. It mutates uses_libs properties in place just for the
manifest check, by replacing module names with library names for
direct dependencies and merging library names from CLC for both direct
denpendencies and transitive denpendencies, and then constructs manifest
check inputs from those mutated uses_libs properties. This is
error-prone and leads to insistency: the goal is to check that the CLC
matches the manifest, but the inputs to the check don't reflect the CLC.
After this change, we no longer mutate uses_libs properties in place.
Instead, we maintain a separate list of missing denpendencies, and then
construct manifest check inputs directly from the CLC for all existing
libraries, no matter they are direct or transtive, and from the separate
list of missing libraries. This change makes the logic more
consistent and straightforward, and it also allows us to easily do the
next change, which is to propagate transtive missing denpendencies.
In fact, this change revealed several bugs around library optionality
and order in CLC construction, and fixed them.
Bug: 331528424
Test: m --no-skip-soong-tests
Ignore-AOSP-First: Depends on internal changes. Will cherry-pick once merged.
Merged-In: I0de82e76c47995b54aba9efd41538d950256a95f
Change-Id: I0de82e76c47995b54aba9efd41538d950256a95f
2024-04-15 13:15:41 +02:00
a . usesLibrary . verifyUsesLibrariesAPK ( ctx , srcApk , & a . dexpreopter . classLoaderContexts )
2021-02-26 15:36:48 +01:00
}
2024-01-24 00:56:29 +01:00
a . dexpreopter . dexpreopt ( ctx , android . RemoveOptionalPrebuiltPrefix ( ctx . ModuleName ( ) ) , jnisUncompressed )
2020-12-21 21:29:12 +01:00
if a . dexpreopter . uncompressedDex {
dexUncompressed := android . PathForModuleOut ( ctx , "dex-uncompressed" , ctx . ModuleName ( ) + ".apk" )
2023-01-13 21:03:38 +01:00
ctx . Build ( pctx , android . BuildParams {
Rule : uncompressDexRule ,
Input : jnisUncompressed ,
Output : dexUncompressed ,
} )
2020-12-21 21:29:12 +01:00
jnisUncompressed = dexUncompressed
}
apkFilename := proptools . StringDefault ( a . properties . Filename , a . BaseModuleName ( ) + ".apk" )
// TODO: Handle EXTERNAL
// Sign or align the package if package has not been preprocessed
2021-01-09 01:09:09 +01:00
2023-04-18 00:06:56 +02:00
if proptools . Bool ( a . properties . Preprocessed ) {
2023-09-07 01:11:44 +02:00
validationStamp := a . validatePresignedApk ( ctx , srcApk )
output := android . PathForModuleOut ( ctx , apkFilename )
ctx . Build ( pctx , android . BuildParams {
Rule : android . Cp ,
Input : srcApk ,
Output : output ,
Validation : validationStamp ,
} )
2023-04-18 00:06:56 +02:00
a . outputFile = output
2020-12-21 21:29:12 +01:00
a . certificate = PresignedCertificate
} else if ! Bool ( a . properties . Presigned ) {
// 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.
2023-07-15 01:23:39 +02:00
_ , _ , certificates := collectAppDeps ( ctx , a , false , false )
2022-09-14 21:45:42 +02:00
a . certificate , certificates = processMainCert ( a . ModuleBase , String ( a . properties . Certificate ) , certificates , ctx )
2020-12-21 21:29:12 +01:00
signed := android . PathForModuleOut ( ctx , "signed" , apkFilename )
var lineageFile android . Path
if lineage := String ( a . properties . Lineage ) ; lineage != "" {
lineageFile = android . PathForModuleSrc ( ctx , lineage )
}
2021-11-03 15:39:39 +01:00
rotationMinSdkVersion := String ( a . properties . RotationMinSdkVersion )
SignAppPackage ( ctx , signed , jnisUncompressed , certificates , nil , lineageFile , rotationMinSdkVersion )
2020-12-21 21:29:12 +01:00
a . outputFile = signed
} else {
2023-09-07 01:11:44 +02:00
validationStamp := a . validatePresignedApk ( ctx , srcApk )
2020-12-21 21:29:12 +01:00
alignedApk := android . PathForModuleOut ( ctx , "zip-aligned" , apkFilename )
2023-09-07 01:11:44 +02:00
TransformZipAlign ( ctx , alignedApk , jnisUncompressed , [ ] android . Path { validationStamp } )
2020-12-21 21:29:12 +01:00
a . outputFile = alignedApk
a . certificate = PresignedCertificate
}
// TODO: Optionally compress the output apk.
if apexInfo . IsForPlatform ( ) {
a . installPath = ctx . InstallFile ( installDir , apkFilename , a . outputFile )
2022-03-19 01:33:24 +01:00
artifactPath := android . PathForModuleSrc ( ctx , * a . properties . Apk )
a . provenanceMetaDataFile = provenance . GenerateArtifactProvenanceMetaData ( ctx , artifactPath , a . installPath )
2020-12-21 21:29:12 +01:00
}
2024-01-09 23:47:39 +01:00
android . CollectDependencyAconfigFiles ( ctx , & a . mergedAconfigFiles )
2020-12-21 21:29:12 +01:00
2024-03-11 22:37:25 +01:00
providePrebuiltInfo ( ctx ,
prebuiltInfoProps {
baseModuleName : a . BaseModuleName ( ) ,
isPrebuilt : true ,
prebuiltInfo : a . properties . Prebuilt_info ,
} ,
)
2020-12-21 21:29:12 +01:00
// TODO: androidmk converter jni libs
}
2023-09-07 01:11:44 +02:00
func ( a * AndroidAppImport ) validatePresignedApk ( ctx android . ModuleContext , srcApk android . Path ) android . Path {
stamp := android . PathForModuleOut ( ctx , "validated-prebuilt" , "check.stamp" )
var extraArgs [ ] string
2023-07-21 02:31:16 +02:00
if a . Privileged ( ) {
2023-09-07 01:11:44 +02:00
extraArgs = append ( extraArgs , "--privileged" )
}
if proptools . Bool ( a . properties . Skip_preprocessed_apk_checks ) {
extraArgs = append ( extraArgs , "--skip-preprocessed-apk-checks" )
}
if proptools . Bool ( a . properties . Preprocessed ) {
extraArgs = append ( extraArgs , "--preprocessed" )
2023-07-21 02:31:16 +02:00
}
2023-04-18 00:06:56 +02:00
ctx . Build ( pctx , android . BuildParams {
2023-09-07 01:11:44 +02:00
Rule : checkPresignedApkRule ,
2023-07-15 01:23:39 +02:00
Input : srcApk ,
2023-09-07 01:11:44 +02:00
Output : stamp ,
Args : map [ string ] string {
"extraArgs" : strings . Join ( extraArgs , " " ) ,
} ,
2023-07-15 01:23:39 +02:00
} )
2023-09-07 01:11:44 +02:00
return stamp
2023-07-15 01:23:39 +02:00
}
2020-12-21 21:29:12 +01:00
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
}
2023-07-07 20:32:32 +02:00
func ( a * AndroidAppImport ) OutputFiles ( tag string ) ( android . Paths , error ) {
switch tag {
case "" :
return [ ] android . Path { a . outputFile } , nil
default :
return nil , fmt . Errorf ( "unsupported module reference tag %q" , tag )
}
}
2020-12-21 21:29:12 +01:00
func ( a * AndroidAppImport ) JacocoReportClassesFile ( ) android . Path {
return nil
}
func ( a * AndroidAppImport ) Certificate ( ) Certificate {
return a . certificate
}
2022-03-19 01:33:24 +01:00
func ( a * AndroidAppImport ) ProvenanceMetaDataFile ( ) android . OutputPath {
return a . provenanceMetaDataFile
}
2022-08-17 18:53:46 +02:00
func ( a * AndroidAppImport ) PrivAppAllowlist ( ) android . OptionalPath {
return android . OptionalPath { }
}
2024-01-29 06:57:51 +01:00
const (
ArchGroupName = "Arch"
DpiGroupName = "Dpi_variants"
)
2020-12-21 21:29:12 +01:00
var dpiVariantGroupType reflect . Type
var archVariantGroupType reflect . Type
2024-01-29 06:57:51 +01:00
var archdpiVariantGroupType reflect . Type
2020-12-21 21:29:12 +01:00
var supportedDpis = [ ] string { "ldpi" , "mdpi" , "hdpi" , "xhdpi" , "xxhdpi" , "xxxhdpi" }
func initAndroidAppImportVariantGroupTypes ( ) {
2024-01-29 06:57:51 +01:00
dpiVariantGroupType = createVariantGroupType ( supportedDpis , DpiGroupName )
2020-12-21 21:29:12 +01:00
archNames := make ( [ ] string , len ( android . ArchTypeList ( ) ) )
for i , archType := range android . ArchTypeList ( ) {
archNames [ i ] = archType . Name
}
2024-01-29 06:57:51 +01:00
archVariantGroupType = createVariantGroupType ( archNames , ArchGroupName )
archdpiVariantGroupType = createArchDpiVariantGroupType ( archNames , supportedDpis )
2020-12-21 21:29:12 +01:00
}
// 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 )
2024-01-29 06:57:51 +01:00
a . arch_dpiVariants = reflect . New ( archdpiVariantGroupType ) . Interface ( )
a . AddProperties ( a . arch_dpiVariants )
2020-12-21 21:29:12 +01:00
}
func ( a * AndroidAppImport ) Privileged ( ) bool {
return Bool ( a . properties . Privileged )
}
func ( a * AndroidAppImport ) DepIsInSameApex ( _ android . BaseModuleContext , _ android . Module ) 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
}
2021-04-02 01:45:46 +02:00
func ( a * AndroidAppImport ) SdkVersion ( ctx android . EarlyModuleContext ) android . SdkSpec {
return android . SdkSpecPrivate
2020-12-21 21:29:12 +01:00
}
2023-03-03 22:20:36 +01:00
func ( a * AndroidAppImport ) MinSdkVersion ( ctx android . EarlyModuleContext ) android . ApiLevel {
return android . SdkSpecPrivate . ApiLevel
2020-12-21 21:29:12 +01:00
}
2021-08-11 04:24:07 +02:00
func ( a * AndroidAppImport ) LintDepSets ( ) LintDepSets {
return LintDepSets { }
}
2020-12-21 21:29:12 +01:00
var _ android . ApexModule = ( * AndroidAppImport ) ( nil )
// Implements android.ApexModule
func ( j * AndroidAppImport ) ShouldSupportSdkVersion ( ctx android . BaseModuleContext ,
sdkVersion android . ApiLevel ) error {
// Do not check for prebuilts against the min_sdk_version of enclosing APEX
return nil
}
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 ,
} ,
} )
}
2024-01-29 06:57:51 +01:00
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
}
Refactor the contruction of the manifest check inputs.
This is a no-op change for a majority of cases.
Before this change, the contruction of the manifest check inputs is
confusing. It mutates uses_libs properties in place just for the
manifest check, by replacing module names with library names for
direct dependencies and merging library names from CLC for both direct
denpendencies and transitive denpendencies, and then constructs manifest
check inputs from those mutated uses_libs properties. This is
error-prone and leads to insistency: the goal is to check that the CLC
matches the manifest, but the inputs to the check don't reflect the CLC.
After this change, we no longer mutate uses_libs properties in place.
Instead, we maintain a separate list of missing denpendencies, and then
construct manifest check inputs directly from the CLC for all existing
libraries, no matter they are direct or transtive, and from the separate
list of missing libraries. This change makes the logic more
consistent and straightforward, and it also allows us to easily do the
next change, which is to propagate transtive missing denpendencies.
In fact, this change revealed several bugs around library optionality
and order in CLC construction, and fixed them.
Bug: 331528424
Test: m --no-skip-soong-tests
Ignore-AOSP-First: Depends on internal changes. Will cherry-pick once merged.
Merged-In: I0de82e76c47995b54aba9efd41538d950256a95f
Change-Id: I0de82e76c47995b54aba9efd41538d950256a95f
2024-04-15 13:15:41 +02:00
func ( a * AndroidAppImport ) UsesLibrary ( ) * usesLibrary {
return & a . usesLibrary
}
var _ ModuleWithUsesLibrary = ( * AndroidAppImport ) ( nil )
2020-12-21 21:29:12 +01:00
// 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:
//
2022-08-16 19:27:33 +02:00
// 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,
// }
2020-12-21 21:29:12 +01:00
func AndroidAppImportFactory ( ) android . Module {
module := & AndroidAppImport { }
module . AddProperties ( & module . properties )
module . AddProperties ( & module . dexpreoptProperties )
module . AddProperties ( & module . usesLibrary . usesLibraryProperties )
module . populateAllVariantStructs ( )
2024-01-12 23:02:47 +01:00
module . SetDefaultableHook ( func ( ctx android . DefaultableHookContext ) {
2020-12-21 21:29:12 +01:00
module . processVariants ( ctx )
} )
android . InitApexModule ( module )
android . InitAndroidMultiTargetsArchModule ( module , android . DeviceSupported , android . MultilibCommon )
android . InitDefaultableModule ( module )
android . InitSingleSourcePrebuiltModule ( module , & module . properties , "Apk" )
2021-01-05 13:04:17 +01:00
module . usesLibrary . enforce = true
2020-12-21 21:29:12 +01:00
return module
}
type AndroidTestImport struct {
AndroidAppImport
2022-10-20 13:18:35 +02:00
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
}
2020-12-21 21:29:12 +01:00
data android . Paths
}
func ( a * AndroidTestImport ) GenerateAndroidBuildActions ( ctx android . ModuleContext ) {
a . generateAndroidBuildActions ( ctx )
a . data = android . PathsForModuleSrc ( ctx , a . testProperties . Data )
}
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 ( )
2024-01-12 23:02:47 +01:00
module . SetDefaultableHook ( func ( ctx android . DefaultableHookContext ) {
2020-12-21 21:29:12 +01:00
module . processVariants ( ctx )
} )
module . dexpreopter . isTest = true
android . InitApexModule ( module )
android . InitAndroidMultiTargetsArchModule ( module , android . DeviceSupported , android . MultilibCommon )
android . InitDefaultableModule ( module )
android . InitSingleSourcePrebuiltModule ( module , & module . properties , "Apk" )
return module
}