diff --git a/android/config.go b/android/config.go index d5ed883fa..32131fc74 100644 --- a/android/config.go +++ b/android/config.go @@ -1498,6 +1498,10 @@ func (c *config) ApexCompressionEnabled() bool { return Bool(c.productVariables.CompressedApex) && !c.UnbundledBuildApps() } +func (c *config) ApexTrimEnabled() bool { + return Bool(c.productVariables.TrimmedApex) +} + func (c *config) EnforceSystemCertificate() bool { return Bool(c.productVariables.EnforceSystemCertificate) } diff --git a/android/variable.go b/android/variable.go index 97258955a..27c5ef110 100644 --- a/android/variable.go +++ b/android/variable.go @@ -380,6 +380,7 @@ type productVariables struct { Ndk_abis *bool `json:",omitempty"` + TrimmedApex *bool `json:",omitempty"` Flatten_apex *bool `json:",omitempty"` ForceApexSymlinkOptimization *bool `json:",omitempty"` CompressedApex *bool `json:",omitempty"` @@ -502,6 +503,7 @@ func (v *productVariables) SetDefaultConfig() { Malloc_zero_contents: boolPtr(true), Malloc_pattern_fill_contents: boolPtr(false), Safestack: boolPtr(false), + TrimmedApex: boolPtr(false), BootJars: ConfiguredJarList{apexes: []string{}, jars: []string{}}, ApexBootJars: ConfiguredJarList{apexes: []string{}, jars: []string{}}, diff --git a/apex/apex.go b/apex/apex.go index b9a3c8f4f..2e2c2cbf8 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -80,6 +80,7 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { ctx.BottomUp("apex", apexMutator).Parallel() ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel() ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel() + ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel() // Register after apex_info mutator so that it can use ApexVariationName ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel() } @@ -389,6 +390,9 @@ type overridableProperties struct { // conditions, e.g., target device needs to support APEX compression, are also fulfilled. // Default: false. Compressible *bool + + // Trim against a specific Dynamic Common Lib APEX + Trim_against *string } type apexBundle struct { @@ -675,6 +679,7 @@ var ( androidAppTag = &dependencyTag{name: "androidApp", payload: true} bpfTag = &dependencyTag{name: "bpf", payload: true} certificateTag = &dependencyTag{name: "certificate"} + dclaTag = &dependencyTag{name: "dcla"} executableTag = &dependencyTag{name: "executable", payload: true} fsTag = &dependencyTag{name: "filesystem", payload: true} bcpfTag = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true, memberType: java.BootclasspathFragmentSdkMemberType} @@ -908,6 +913,33 @@ func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutato } } +func apexDCLADepsMutator(mctx android.BottomUpMutatorContext) { + if !mctx.Config().ApexTrimEnabled() { + return + } + if a, ok := mctx.Module().(*apexBundle); ok && a.overridableProperties.Trim_against != nil { + commonVariation := mctx.Config().AndroidCommonTarget.Variations() + mctx.AddFarVariationDependencies(commonVariation, dclaTag, String(a.overridableProperties.Trim_against)) + } else if o, ok := mctx.Module().(*OverrideApex); ok { + for _, p := range o.GetProperties() { + properties, ok := p.(*overridableProperties) + if !ok { + continue + } + if properties.Trim_against != nil { + commonVariation := mctx.Config().AndroidCommonTarget.Variations() + mctx.AddFarVariationDependencies(commonVariation, dclaTag, String(properties.Trim_against)) + } + } + } +} + +type DCLAInfo struct { + ProvidedLibs []string +} + +var DCLAInfoProvider = blueprint.NewMutatorProvider(DCLAInfo{}, "apex_info") + type ApexBundleInfo struct { Contents *android.ApexContents } @@ -1035,6 +1067,12 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { child.(android.ApexModule).BuildForApex(apexInfo) // leave a mark! return true }) + + if a.dynamic_common_lib_apex() { + mctx.SetProvider(DCLAInfoProvider, DCLAInfo{ + ProvidedLibs: a.properties.Native_shared_libs, + }) + } } type ApexInfoMutator interface { @@ -1531,6 +1569,19 @@ func (a *apexBundle) dynamic_common_lib_apex() bool { return proptools.BoolDefault(a.properties.Dynamic_common_lib_apex, false) } +// See the list of libs to trim +func (a *apexBundle) libs_to_trim(ctx android.ModuleContext) []string { + dclaModules := ctx.GetDirectDepsWithTag(dclaTag) + if len(dclaModules) > 1 { + panic(fmt.Errorf("expected exactly at most one dcla dependency, got %d", len(dclaModules))) + } + if len(dclaModules) > 0 { + DCLAInfo := ctx.OtherModuleProvider(dclaModules[0], DCLAInfoProvider).(DCLAInfo) + return DCLAInfo.ProvidedLibs + } + return []string{} +} + // These functions are interfacing with cc/sanitizer.go. The entire APEX (along with all of its // members) can be sanitized, either forcibly, or by the global configuration. For some of the // sanitizers, extra dependencies can be forcibly added as well. @@ -2473,7 +2524,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { } //////////////////////////////////////////////////////////////////////////////////////////// // 2) traverse the dependency tree to collect apexFile structs from them. - // Collect the module directory for IDE info in java/jdeps.go. a.modulePaths = append(a.modulePaths, ctx.ModuleDir()) diff --git a/apex/builder.go b/apex/builder.go index 3b9cac069..984e7f052 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -40,6 +40,8 @@ func init() { pctx.Import("android/soong/java") pctx.HostBinToolVariable("apexer", "apexer") pctx.HostBinToolVariable("apexer_with_DCLA_preprocessing", "apexer_with_DCLA_preprocessing") + pctx.HostBinToolVariable("apexer_with_trim_preprocessing", "apexer_with_trim_preprocessing") + // ART minimal builds (using the master-art manifest) do not have the "frameworks/base" // projects, and hence cannot build 'aapt2'. Use the SDK prebuilt instead. hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) { @@ -146,6 +148,34 @@ var ( }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "is_DCLA") + TrimmedApexRule = pctx.StaticRule("TrimmedApexRule", blueprint.RuleParams{ + Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + + `(. ${out}.copy_commands) && ` + + `APEXER_TOOL_PATH=${tool_path} ` + + `${apexer_with_trim_preprocessing} ` + + `--apexer ${apexer} ` + + `--canned_fs_config ${canned_fs_config} ` + + `--manifest ${manifest} ` + + `--libs_to_trim ${libs_to_trim} ` + + `${image_dir} ` + + `${out} ` + + `-- ` + + `--include_build_info ` + + `--force ` + + `--payload_type image ` + + `--key ${key} ` + + `--file_contexts ${file_contexts} ` + + `${opt_flags} `, + CommandDeps: []string{"${apexer_with_trim_preprocessing}", "${apexer}", "${avbtool}", "${e2fsdroid}", + "${merge_zips}", "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", + "${sload_f2fs}", "${make_erofs}", "${soong_zip}", "${zipalign}", "${aapt2}", + "prebuilts/sdk/current/public/android.jar"}, + Rspfile: "${out}.copy_commands", + RspfileContent: "${copy_commands}", + Description: "APEX ${image_dir} => ${out}", + }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", + "opt_flags", "manifest", "libs_to_trim") + zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{ Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + `(. ${out}.copy_commands) && ` + @@ -706,6 +736,24 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { "opt_flags": strings.Join(optFlags, " "), }, }) + } else if ctx.Config().ApexTrimEnabled() && len(a.libs_to_trim(ctx)) > 0 { + ctx.Build(pctx, android.BuildParams{ + Rule: TrimmedApexRule, + Implicits: implicitInputs, + Output: unsignedOutputFile, + Description: "apex (" + apexType.name() + ")", + Args: map[string]string{ + "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, + "image_dir": imageDir.String(), + "copy_commands": strings.Join(copyCommands, " && "), + "manifest": a.manifestPbOut.String(), + "file_contexts": fileContexts.String(), + "canned_fs_config": cannedFsConfig.String(), + "key": a.privateKeyFile.String(), + "opt_flags": strings.Join(optFlags, " "), + "libs_to_trim": strings.Join(a.libs_to_trim(ctx), ","), + }, + }) } else { ctx.Build(pctx, android.BuildParams{ Rule: apexRule,