Merge "Enforce mainline modules to have latest target sdk version by default."

This commit is contained in:
Harshit Mahajan
2022-09-27 17:04:27 +00:00
committed by Gerrit Code Review
5 changed files with 244 additions and 30 deletions

View File

@@ -270,7 +270,7 @@ var extractAssetsRule = pctx.AndroidStaticRule("extractAssets",
func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext,
classLoaderContexts dexpreopt.ClassLoaderContextMap, excludedLibs []string,
extraLinkFlags ...string) {
enforceDefaultTargetSdkVersion bool, extraLinkFlags ...string) {
transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags :=
aaptLibs(ctx, sdkContext, classLoaderContexts)
@@ -292,6 +292,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
UseEmbeddedDex: a.useEmbeddedDex,
HasNoCode: a.hasNoCode,
LoggingParent: a.LoggingParent,
EnforceDefaultTargetSdkVersion: enforceDefaultTargetSdkVersion,
})
// Add additional manifest files to transitive manifests.
@@ -535,7 +536,7 @@ func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.isLibrary = true
a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil)
a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil, false)
a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()

View File

@@ -43,13 +43,12 @@ var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
// targetSdkVersion for manifest_fixer
// When TARGET_BUILD_APPS is not empty, this method returns 10000 for modules targeting an unreleased SDK
// This enables release builds (that run with TARGET_BUILD_APPS=[val...]) to target APIs that have not yet been finalized as part of an SDK
func targetSdkVersionForManifestFixer(ctx android.ModuleContext, sdkContext android.SdkContext) string {
targetSdkVersionSpec := sdkContext.TargetSdkVersion(ctx)
// Return 10000 for modules targeting "current" if either
// 1. The module is built in unbundled mode (TARGET_BUILD_APPS not empty)
// 2. The module is run as part of MTS, and should be testable on stable branches
func targetSdkVersionForManifestFixer(ctx android.ModuleContext, params ManifestFixerParams) string {
targetSdkVersionSpec := params.SdkContext.TargetSdkVersion(ctx)
// Check if we want to return 10000
// TODO(b/240294501): Determine the rules for handling test apexes
if targetSdkVersionSpec.ApiLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module())) {
if shouldReturnFinalOrFutureInt(ctx, targetSdkVersionSpec, params.EnforceDefaultTargetSdkVersion) {
return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt())
}
targetSdkVersion, err := targetSdkVersionSpec.EffectiveVersionString(ctx)
@@ -59,6 +58,17 @@ func targetSdkVersionForManifestFixer(ctx android.ModuleContext, sdkContext andr
return targetSdkVersion
}
// Return true for modules targeting "current" if either
// 1. The module is built in unbundled mode (TARGET_BUILD_APPS not empty)
// 2. The module is run as part of MTS, and should be testable on stable branches
// Do not return 10000 if we are enforcing default targetSdkVersion and sdk has been finalised
func shouldReturnFinalOrFutureInt(ctx android.ModuleContext, targetSdkVersionSpec android.SdkSpec, enforceDefaultTargetSdkVersion bool) bool {
if enforceDefaultTargetSdkVersion && ctx.Config().PlatformSdkFinal() {
return false
}
return targetSdkVersionSpec.ApiLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module()))
}
// Helper function that casts android.Module to java.androidTestApp
// If this type conversion is possible, it queries whether the test app is included in an MTS suite
func includedInMts(module android.Module) bool {
@@ -79,6 +89,7 @@ type ManifestFixerParams struct {
HasNoCode bool
TestOnly bool
LoggingParent string
EnforceDefaultTargetSdkVersion bool
}
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
@@ -137,7 +148,7 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path,
var argsMapper = make(map[string]string)
if params.SdkContext != nil {
targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params.SdkContext)
targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params)
args = append(args, "--targetSdkVersion ", targetSdkVersion)
if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {

View File

@@ -101,6 +101,15 @@ type appProperties struct {
PreventInstall bool `blueprint:"mutated"`
IsCoverageVariant bool `blueprint:"mutated"`
// It can be set to test the behaviour of default target sdk version.
// Only required when updatable: false. It is an error if updatable: true and this is false.
Enforce_default_target_sdk_version *bool
// If set, the targetSdkVersion for the target is set to the latest default API level.
// This would be by default false, unless updatable: true or
// enforce_default_target_sdk_version: true in which case this defaults to true.
EnforceDefaultTargetSdkVersion bool `blueprint:"mutated"`
// Whether this app is considered mainline updatable or not. When set to true, this will enforce
// additional rules to make sure an app can safely be updated. Default is false.
// Prefer using other specific properties if build behaviour must be changed; avoid using this
@@ -296,6 +305,18 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
} else {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
}
if !BoolDefault(a.appProperties.Enforce_default_target_sdk_version, true) {
ctx.PropertyErrorf("enforce_default_target_sdk_version", "Updatable apps must enforce default target sdk version")
}
// TODO(b/227460469) after all the modules removes the target sdk version, throw an error if the target sdk version is explicitly set.
if a.deviceProperties.Target_sdk_version == nil {
a.SetEnforceDefaultTargetSdkVersion(true)
}
}
if Bool(a.appProperties.Enforce_default_target_sdk_version) {
a.SetEnforceDefaultTargetSdkVersion(true)
}
a.checkPlatformAPI(ctx)
@@ -427,7 +448,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
}
a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts,
a.usesLibraryProperties.Exclude_uses_libs, aaptLinkFlags...)
a.usesLibraryProperties.Exclude_uses_libs, a.enforceDefaultTargetSdkVersion(), aaptLinkFlags...)
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
@@ -865,6 +886,14 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) {
a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).String(), depsInfo)
}
func (a *AndroidApp) enforceDefaultTargetSdkVersion() bool {
return a.appProperties.EnforceDefaultTargetSdkVersion
}
func (a *AndroidApp) SetEnforceDefaultTargetSdkVersion(val bool) {
a.appProperties.EnforceDefaultTargetSdkVersion = val
}
func (a *AndroidApp) Updatable() bool {
return Bool(a.appProperties.Updatable)
}

View File

@@ -3057,6 +3057,179 @@ func TestTargetSdkVersionManifestFixer(t *testing.T) {
}
}
func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) {
platform_sdk_codename := "Tiramisu"
platform_sdk_version := 33
testCases := []struct {
name string
platform_sdk_final bool
targetSdkVersionInBp *string
targetSdkVersionExpected *string
updatable bool
}{
{
name: "Non-Updatable Module: Android.bp has older targetSdkVersion",
targetSdkVersionInBp: proptools.StringPtr("29"),
targetSdkVersionExpected: proptools.StringPtr("29"),
updatable: false,
},
{
name: "Updatable Module: Android.bp has older targetSdkVersion",
targetSdkVersionInBp: proptools.StringPtr("30"),
targetSdkVersionExpected: proptools.StringPtr("30"),
updatable: true,
},
{
name: "Updatable Module: Android.bp has no targetSdkVersion",
targetSdkVersionExpected: proptools.StringPtr("10000"),
updatable: true,
},
{
name: "[SDK finalised] Non-Updatable Module: Android.bp has older targetSdkVersion",
platform_sdk_final: true,
targetSdkVersionInBp: proptools.StringPtr("30"),
targetSdkVersionExpected: proptools.StringPtr("30"),
updatable: false,
},
{
name: "[SDK finalised] Updatable Module: Android.bp has older targetSdkVersion",
platform_sdk_final: true,
targetSdkVersionInBp: proptools.StringPtr("30"),
targetSdkVersionExpected: proptools.StringPtr("30"),
updatable: true,
},
{
name: "[SDK finalised] Updatable Module: Android.bp has targetSdkVersion as platform sdk codename",
platform_sdk_final: true,
targetSdkVersionInBp: proptools.StringPtr(platform_sdk_codename),
targetSdkVersionExpected: proptools.StringPtr("33"),
updatable: true,
},
{
name: "[SDK finalised] Updatable Module: Android.bp has no targetSdkVersion",
platform_sdk_final: true,
targetSdkVersionExpected: proptools.StringPtr("33"),
updatable: true,
},
}
for _, testCase := range testCases {
bp := fmt.Sprintf(`
android_app {
name: "foo",
sdk_version: "current",
min_sdk_version: "29",
target_sdk_version: "%v",
updatable: %t,
enforce_default_target_sdk_version: %t
}
`, proptools.String(testCase.targetSdkVersionInBp), testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable
fixture := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.PrepareForTestWithAllowMissingDependencies,
android.PrepareForTestWithAndroidMk,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
// explicitly set following platform variables to make the test deterministic
variables.Platform_sdk_final = &testCase.platform_sdk_final
variables.Platform_sdk_version = &platform_sdk_version
variables.Platform_sdk_codename = &platform_sdk_codename
variables.Platform_version_active_codenames = []string{platform_sdk_codename}
variables.Unbundled_build_apps = []string{"sampleModule"}
}),
)
result := fixture.RunTestWithBp(t, bp)
foo := result.ModuleForTests("foo", "android_common")
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+*testCase.targetSdkVersionExpected)
}
}
func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) {
platform_sdk_codename := "Tiramisu"
platform_sdk_version := 33
testCases := []struct {
name string
enforceDefaultTargetSdkVersion bool
expectedError string
platform_sdk_final bool
targetSdkVersionInBp string
targetSdkVersionExpected string
updatable bool
}{
{
name: "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion",
enforceDefaultTargetSdkVersion: false,
targetSdkVersionInBp: "29",
targetSdkVersionExpected: "29",
updatable: false,
},
{
name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
enforceDefaultTargetSdkVersion: true,
platform_sdk_final: true,
targetSdkVersionInBp: "current",
targetSdkVersionExpected: "33",
updatable: true,
},
{
name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
enforceDefaultTargetSdkVersion: true,
platform_sdk_final: false,
targetSdkVersionInBp: "current",
targetSdkVersionExpected: "10000",
updatable: false,
},
{
name: "Not enforcing Target SDK Version for Updatable app",
enforceDefaultTargetSdkVersion: false,
expectedError: "Updatable apps must enforce default target sdk version",
targetSdkVersionInBp: "29",
targetSdkVersionExpected: "29",
updatable: true,
},
}
for _, testCase := range testCases {
errExpected := testCase.expectedError != ""
bp := fmt.Sprintf(`
android_app {
name: "foo",
enforce_default_target_sdk_version: %t,
sdk_version: "current",
min_sdk_version: "29",
target_sdk_version: "%v",
updatable: %t
}
`, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp, testCase.updatable)
fixture := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.PrepareForTestWithAllowMissingDependencies,
android.PrepareForTestWithAndroidMk,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
// explicitly set following platform variables to make the test deterministic
variables.Platform_sdk_final = &testCase.platform_sdk_final
variables.Platform_sdk_version = &platform_sdk_version
variables.Platform_sdk_codename = &platform_sdk_codename
variables.Unbundled_build_apps = []string{"sampleModule"}
}),
)
errorHandler := android.FixtureExpectsNoErrors
if errExpected {
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
}
result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
if !errExpected {
foo := result.ModuleForTests("foo", "android_common")
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
}
}
}
func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,

View File

@@ -142,7 +142,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC
aaptLinkFlags = append(aaptLinkFlags,
"--rename-overlay-target-package "+*r.overridableProperties.Target_package_name)
}
r.aapt.buildActions(ctx, r, nil, nil, aaptLinkFlags...)
r.aapt.buildActions(ctx, r, nil, nil, false, aaptLinkFlags...)
// Sign the built package
_, _, certificates := collectAppDeps(ctx, r, false, false)