diff --git a/android/apex.go b/android/apex.go index f857ec692..3cc663bab 100644 --- a/android/apex.go +++ b/android/apex.go @@ -24,29 +24,36 @@ import ( "github.com/google/blueprint" ) -const ( - SdkVersion_Android10 = 29 +var ( + SdkVersion_Android10 = uncheckedFinalApiLevel(29) ) type ApexInfo struct { // Name of the apex variation that this module is mutated into ApexVariationName string - MinSdkVersion int - Updatable bool - RequiredSdks SdkRefs + // Serialized ApiLevel. Use via MinSdkVersion() method. Cannot be stored in + // its struct form because this is cloned into properties structs, and + // ApiLevel has private members. + MinSdkVersionStr string + Updatable bool + RequiredSdks SdkRefs InApexes []string } -func (i ApexInfo) mergedName() string { - name := "apex" + strconv.Itoa(i.MinSdkVersion) +func (i ApexInfo) mergedName(ctx EarlyModuleContext) string { + name := "apex" + strconv.Itoa(i.MinSdkVersion(ctx).FinalOrFutureInt()) for _, sdk := range i.RequiredSdks { name += "_" + sdk.Name + "_" + sdk.Version } return name } +func (this *ApexInfo) MinSdkVersion(ctx EarlyModuleContext) ApiLevel { + return ApiLevelOrPanic(ctx, this.MinSdkVersionStr) +} + // Extracted from ApexModule to make it easier to define custom subsets of the // ApexModule interface and improve code navigation within the IDE. type DepIsInSameApex interface { @@ -141,7 +148,7 @@ type ApexModule interface { // Returns nil if this module supports sdkVersion // Otherwise, returns error with reason - ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion int) error + ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion ApiLevel) error // Returns true if this module needs a unique variation per apex, for example if // use_apex_name_macro is set. @@ -347,18 +354,18 @@ func (a byApexName) Less(i, j int) bool { return a[i].ApexVariationName < a[j].A // mergeApexVariations deduplicates APEX variations that would build identically into a common // variation. It returns the reduced list of variations and a list of aliases from the original // variation names to the new variation names. -func mergeApexVariations(apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]string) { +func mergeApexVariations(ctx EarlyModuleContext, apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]string) { sort.Sort(byApexName(apexVariations)) seen := make(map[string]int) for _, apexInfo := range apexVariations { apexName := apexInfo.ApexVariationName - mergedName := apexInfo.mergedName() + mergedName := apexInfo.mergedName(ctx) if index, exists := seen[mergedName]; exists { merged[index].InApexes = append(merged[index].InApexes, apexName) merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable } else { seen[mergedName] = len(merged) - apexInfo.ApexVariationName = apexInfo.mergedName() + apexInfo.ApexVariationName = apexInfo.mergedName(ctx) apexInfo.InApexes = CopyOf(apexInfo.InApexes) merged = append(merged, apexInfo) } @@ -374,7 +381,7 @@ func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Mod var apexVariations []ApexInfo var aliases [][2]string if !mctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps { - apexVariations, aliases = mergeApexVariations(m.apexVariations) + apexVariations, aliases = mergeApexVariations(mctx, m.apexVariations) } else { apexVariations = m.apexVariations } @@ -603,7 +610,13 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion } // TODO(b/158059172): remove minSdkVersion allowlist -var minSdkVersionAllowlist = map[string]int{ +var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel { + list := make(map[string]ApiLevel, len(apiMap)) + for name, finalApiInt := range apiMap { + list[name] = uncheckedFinalApiLevel(finalApiInt) + } + return list +}(map[string]int{ "adbd": 30, "android.net.ipsec.ike": 30, "androidx-constraintlayout_constraintlayout-solver": 30, @@ -672,7 +685,7 @@ var minSdkVersionAllowlist = map[string]int{ "statsd": 30, "tensorflow_headers": 30, "xz-java": 29, -} +}) // Function called while walking an APEX's payload dependencies. // @@ -686,7 +699,7 @@ type UpdatableModule interface { } // CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version accordingly -func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) { +func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiLevel) { // do not enforce min_sdk_version for host if ctx.Host() { return @@ -699,7 +712,7 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) // do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version or // min_sdk_version is not finalized (e.g. current or codenames) - if minSdkVersion == FutureApiLevel { + if minSdkVersion.IsCurrent() { return } @@ -714,7 +727,7 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) } if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil { toName := ctx.OtherModuleName(to) - if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver > minSdkVersion { + if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) { ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s", minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false)) return false diff --git a/android/api_levels.go b/android/api_levels.go index ddcdbb7e4..97683404e 100644 --- a/android/api_levels.go +++ b/android/api_levels.go @@ -49,6 +49,14 @@ type ApiLevel struct { isPreview bool } +func (this ApiLevel) FinalOrFutureInt() int { + if this.IsPreview() { + return FutureApiLevelInt + } else { + return this.number + } +} + // Returns the canonical name for this API level. For a finalized API level // this will be the API number as a string. For a preview API level this // will be the codename, or "current". @@ -119,13 +127,6 @@ func uncheckedFinalApiLevel(num int) ApiLevel { } } -// TODO: Merge with FutureApiLevel -var CurrentApiLevel = ApiLevel{ - value: "current", - number: 10000, - isPreview: true, -} - var NoneApiLevel = ApiLevel{ value: "(no version)", // Not 0 because we don't want this to compare equal with the first preview. @@ -180,7 +181,7 @@ func ApiLevelFromUser(ctx EarlyModuleContext, raw string) (ApiLevel, error) { } if raw == "current" { - return CurrentApiLevel, nil + return FutureApiLevel, nil } for _, preview := range ctx.Config().PreviewApiLevels() { @@ -261,8 +262,19 @@ func getFinalCodenamesMap(config Config) map[string]int { "R": 30, } + // TODO: Differentiate "current" and "future". + // The code base calls it FutureApiLevel, but the spelling is "current", + // and these are really two different things. When defining APIs it + // means the API has not yet been added to a specific release. When + // choosing an API level to build for it means that the future API level + // should be used, except in the case where the build is finalized in + // which case the platform version should be used. This is *weird*, + // because in the circumstance where API foo was added in R and bar was + // added in S, both of these are usable when building for "current" when + // neither R nor S are final, but the S APIs stop being available in a + // final R build. if Bool(config.productVariables.Platform_sdk_final) { - apiLevelsMap["current"] = config.PlatformSdkVersionInt() + apiLevelsMap["current"] = config.PlatformSdkVersion().FinalOrFutureInt() } return apiLevelsMap @@ -300,24 +312,6 @@ func getApiLevelsMap(config Config) map[string]int { }).(map[string]int) } -// Converts an API level string into its numeric form. -// * Codenames are decoded. -// * Numeric API levels are simply converted. -// * "current" is mapped to FutureApiLevel(10000) -// * "minimum" is NDK specific and not handled with this. (refer normalizeNdkApiLevel in cc.go) -func ApiStrToNum(ctx BaseModuleContext, apiLevel string) (int, error) { - if apiLevel == "current" { - return FutureApiLevel, nil - } - if num, ok := getApiLevelsMap(ctx.Config())[apiLevel]; ok { - return num, nil - } - if num, err := strconv.Atoi(apiLevel); err == nil { - return num, nil - } - return 0, fmt.Errorf("SDK version should be one of \"current\", or : %q", apiLevel) -} - func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) { apiLevelsMap := getApiLevelsMap(ctx.Config()) apiLevelsJson := GetApiLevelsJson(ctx) diff --git a/android/config.go b/android/config.go index 1c06e8c55..f5deeee57 100644 --- a/android/config.go +++ b/android/config.go @@ -21,7 +21,6 @@ import ( "os" "path/filepath" "runtime" - "strconv" "strings" "sync" @@ -37,7 +36,13 @@ var Bool = proptools.Bool var String = proptools.String var StringDefault = proptools.StringDefault -const FutureApiLevel = 10000 +const FutureApiLevelInt = 10000 + +var FutureApiLevel = ApiLevel{ + value: "current", + number: FutureApiLevelInt, + isPreview: true, +} // The configuration file name const configFileName = "soong.config" @@ -222,15 +227,17 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string config := &config{ productVariables: productVariables{ - DeviceName: stringPtr("test_device"), - Platform_sdk_version: intPtr(30), - DeviceSystemSdkVersions: []string{"14", "15"}, - Platform_systemsdk_versions: []string{"29", "30"}, - AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}, - AAPTPreferredConfig: stringPtr("xhdpi"), - AAPTCharacteristics: stringPtr("nosdcard"), - AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"}, - UncompressPrivAppDex: boolPtr(true), + DeviceName: stringPtr("test_device"), + Platform_sdk_version: intPtr(30), + Platform_sdk_codename: stringPtr("S"), + Platform_version_active_codenames: []string{"S"}, + DeviceSystemSdkVersions: []string{"14", "15"}, + Platform_systemsdk_versions: []string{"29", "30"}, + AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}, + AAPTPreferredConfig: stringPtr("xhdpi"), + AAPTCharacteristics: stringPtr("nosdcard"), + AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"}, + UncompressPrivAppDex: boolPtr(true), }, buildDir: buildDir, @@ -614,12 +621,8 @@ func (c *config) PlatformVersionName() string { return String(c.productVariables.Platform_version_name) } -func (c *config) PlatformSdkVersionInt() int { - return *c.productVariables.Platform_sdk_version -} - -func (c *config) PlatformSdkVersion() string { - return strconv.Itoa(c.PlatformSdkVersionInt()) +func (c *config) PlatformSdkVersion() ApiLevel { + return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version) } func (c *config) PlatformSdkCodename() string { @@ -648,7 +651,7 @@ func (c *config) MinSupportedSdkVersion() ApiLevel { func (c *config) FinalApiLevels() []ApiLevel { var levels []ApiLevel - for i := 1; i <= c.PlatformSdkVersionInt(); i++ { + for i := 1; i <= c.PlatformSdkVersion().FinalOrFutureInt(); i++ { levels = append(levels, uncheckedFinalApiLevel(i)) } return levels @@ -672,19 +675,18 @@ func (c *config) AllSupportedApiLevels() []ApiLevel { return append(levels, c.PreviewApiLevels()...) } -func (c *config) DefaultAppTargetSdkInt() int { - if Bool(c.productVariables.Platform_sdk_final) { - return c.PlatformSdkVersionInt() - } else { - return FutureApiLevel - } -} - -func (c *config) DefaultAppTargetSdk() string { +func (c *config) DefaultAppTargetSdk(ctx EarlyModuleContext) ApiLevel { if Bool(c.productVariables.Platform_sdk_final) { return c.PlatformSdkVersion() } else { - return c.PlatformSdkCodename() + codename := c.PlatformSdkCodename() + if codename == "" { + return NoneApiLevel + } + if codename == "REL" { + panic("Platform_sdk_codename should not be REL when Platform_sdk_final is true") + } + return ApiLevelOrPanic(ctx, codename) } } diff --git a/apex/apex.go b/apex/apex.go index 8e35e07c0..e8294a8f6 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -795,7 +795,7 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { } apexInfo := android.ApexInfo{ ApexVariationName: mctx.ModuleName(), - MinSdkVersion: a.minSdkVersion(mctx), + MinSdkVersionStr: a.minSdkVersion(mctx).String(), RequiredSdks: a.RequiredSdks(), Updatable: a.Updatable(), InApexes: []string{mctx.ModuleName()}, @@ -1952,27 +1952,21 @@ func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.Paylo }) } -func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int { +func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel { ver := proptools.String(a.properties.Min_sdk_version) if ver == "" { return android.FutureApiLevel } - // Treat the current codenames as "current", which means future API version (10000) - // Otherwise, ApiStrToNum converts codename(non-finalized) to a value from [9000...] - // and would fail to build against "current". - if android.InList(ver, ctx.Config().PlatformVersionActiveCodenames()) { - return android.FutureApiLevel - } - // In "REL" branch, "current" is mapped to finalized sdk version - if ctx.Config().PlatformSdkCodename() == "REL" && ver == "current" { - return ctx.Config().PlatformSdkVersionInt() - } - // Finalized codenames are OKAY and will be converted to int - intVer, err := android.ApiStrToNum(ctx, ver) + apiLevel, err := android.ApiLevelFromUser(ctx, ver) if err != nil { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) + return android.NoneApiLevel } - return intVer + if apiLevel.IsPreview() { + // All codenames should build against "current". + return android.FutureApiLevel + } + return apiLevel } func (a *apexBundle) Updatable() bool { @@ -2046,7 +2040,9 @@ func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) { if proptools.Bool(a.properties.Use_vendor) && ctx.DeviceConfig().VndkVersion() == "" { return } - android.CheckMinSdkVersion(a, ctx, a.minSdkVersion(ctx)) + // apexBundle::minSdkVersion reports its own errors. + minSdkVersion := a.minSdkVersion(ctx) + android.CheckMinSdkVersion(a, ctx, minSdkVersion) } // Ensures that a lib providing stub isn't statically linked diff --git a/apex/apex_test.go b/apex/apex_test.go index 5c49667e5..02689a0b7 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -207,7 +207,7 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"} config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q") config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false) - config.TestProductVariables.Platform_version_active_codenames = []string{"R"} + config.TestProductVariables.Platform_version_active_codenames = []string{"Q"} config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER") for _, handler := range handlers { @@ -1425,13 +1425,7 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) { ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"] ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so") } - // 9000 is quite a magic number. - // Finalized SDK codenames are mapped as P(28), Q(29), ... - // And, codenames which are not finalized yet(active_codenames + future_codenames) are numbered from 9000, 9001, ... - // to distinguish them from finalized and future_api(10000) - // In this test, "R" is assumed not finalized yet( listed in Platform_version_active_codenames) and translated into 9000 - // (refer android/api_levels.go) - expectLink("libx", "shared_apex10000", "libz", "shared_9000") + expectLink("libx", "shared_apex10000", "libz", "shared_R") expectNoLink("libx", "shared_apex10000", "libz", "shared_29") expectNoLink("libx", "shared_apex10000", "libz", "shared") } @@ -6130,7 +6124,7 @@ func TestNonPreferredPrebuiltDependency(t *testing.T) { name: "mylib", srcs: ["mylib.cpp"], stubs: { - versions: ["10000"], + versions: ["current"], }, apex_available: ["myapex"], } @@ -6140,7 +6134,7 @@ func TestNonPreferredPrebuiltDependency(t *testing.T) { prefer: false, srcs: ["prebuilt.so"], stubs: { - versions: ["10000"], + versions: ["current"], }, apex_available: ["myapex"], } diff --git a/apex/builder.go b/apex/builder.go index c5680ad2d..b0f0c8212 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -21,7 +21,6 @@ import ( "path/filepath" "runtime" "sort" - "strconv" "strings" "android/soong/android" @@ -214,7 +213,8 @@ func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs, }, }) - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { + minSdkVersion := a.minSdkVersion(ctx) + if minSdkVersion.EqualTo(android.SdkVersion_Android10) { // b/143654022 Q apexd can't understand newly added keys in apex_manifest.json // prepare stripped-down version so that APEX modules built from R+ can be installed to Q a.manifestJsonOut = android.PathForModuleOut(ctx, "apex_manifest.json") @@ -426,7 +426,8 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { var emitCommands []string imageContentFile := android.PathForModuleOut(ctx, "content.txt") emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String()) - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { + minSdkVersion := a.minSdkVersion(ctx) + if minSdkVersion.EqualTo(android.SdkVersion_Android10) { emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String()) } for _, fi := range a.filesInfo { @@ -532,12 +533,13 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String()) } - targetSdkVersion := ctx.Config().DefaultAppTargetSdk() + targetSdkVersion := ctx.Config().DefaultAppTargetSdk(ctx).String() // TODO(b/157078772): propagate min_sdk_version to apexer. - minSdkVersion := ctx.Config().DefaultAppTargetSdk() + minSdkVersion := ctx.Config().DefaultAppTargetSdk(ctx).String() - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { - minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx)) + moduleMinSdkVersion := a.minSdkVersion(ctx) + if moduleMinSdkVersion.EqualTo(android.SdkVersion_Android10) { + minSdkVersion = moduleMinSdkVersion.String() } if java.UseApiFingerprint(ctx) { @@ -566,7 +568,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { ctx.PropertyErrorf("test_only_no_hashtree", "not available") return } - if a.minSdkVersion(ctx) > android.SdkVersion_Android10 || a.testOnlyShouldSkipHashtreeGeneration() { + if moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) || a.testOnlyShouldSkipHashtreeGeneration() { // Apexes which are supposed to be installed in builtin dirs(/system, etc) // don't need hashtree for activation. Therefore, by removing hashtree from // apex bundle (filesystem image in it, to be specific), we can save storage. @@ -583,7 +585,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { optFlags = append(optFlags, "--do_not_check_keyname") } - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { + if moduleMinSdkVersion == android.SdkVersion_Android10 { implicitInputs = append(implicitInputs, a.manifestJsonOut) optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String()) } diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 37457e921..9f6c8ada9 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -326,7 +326,7 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { Args: map[string]string{ "abis": strings.Join(java.SupportedAbis(ctx), ","), "allow-prereleased": strconv.FormatBool(proptools.Bool(a.properties.Prerelease)), - "sdk-version": ctx.Config().PlatformSdkVersion(), + "sdk-version": ctx.Config().PlatformSdkVersion().String(), }, }) diff --git a/apex/vndk.go b/apex/vndk.go index 5cc0e2a43..93265c4ac 100644 --- a/apex/vndk.go +++ b/apex/vndk.go @@ -16,7 +16,6 @@ package apex import ( "path/filepath" - "strconv" "strings" "sync" @@ -124,10 +123,10 @@ func makeCompatSymlinks(name string, ctx android.ModuleContext) (symlinks []stri // Since prebuilt vndk libs still depend on system/lib/vndk path if strings.HasPrefix(name, vndkApexNamePrefix) { vndkVersion := strings.TrimPrefix(name, vndkApexNamePrefix) - if numVer, err := strconv.Atoi(vndkVersion); err != nil { + if ver, err := android.ApiLevelFromUser(ctx, vndkVersion); err != nil { ctx.ModuleErrorf("apex_vndk should be named as %v: %s", vndkApexNamePrefix, name) return - } else if numVer > android.SdkVersion_Android10 { + } else if ver.GreaterThan(android.SdkVersion_Android10) { return } // the name of vndk apex is formatted "com.android.vndk.v" + version diff --git a/cc/cc.go b/cc/cc.go index 6584380aa..9877cc6c7 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -354,7 +354,7 @@ type ModuleContextIntf interface { useClangLld(actx ModuleContext) bool isForPlatform() bool apexVariationName() string - apexSdkVersion() int + apexSdkVersion() android.ApiLevel hasStubsVariants() bool isStubs() bool bootstrap() bool @@ -615,7 +615,7 @@ type Module struct { kytheFiles android.Paths // For apex variants, this is set as apex.min_sdk_version - apexSdkVersion int + apexSdkVersion android.ApiLevel } func (c *Module) Toc() android.OptionalPath { @@ -1328,7 +1328,7 @@ func (ctx *moduleContextImpl) apexVariationName() string { return ctx.mod.ApexVariationName() } -func (ctx *moduleContextImpl) apexSdkVersion() int { +func (ctx *moduleContextImpl) apexSdkVersion() android.ApiLevel { return ctx.mod.apexSdkVersion } @@ -2317,7 +2317,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // For the dependency from platform to apex, use the latest stubs c.apexSdkVersion = android.FutureApiLevel if !c.IsForPlatform() { - c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion + c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion(ctx) } if android.InList("hwaddress", ctx.Config().SanitizeDevice()) { @@ -2421,7 +2421,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { if libDepTag, ok := depTag.(libraryDependencyTag); ok { // Only use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859) - if libDepTag.staticUnwinder && c.apexSdkVersion > android.SdkVersion_Android10 { + if libDepTag.staticUnwinder && c.apexSdkVersion.GreaterThan(android.SdkVersion_Android10) { return } @@ -2465,7 +2465,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // when to use (unspecified) stubs, check min_sdk_version and choose the right one if useThisDep && depIsStubs && !libDepTag.explicitlyVersioned { - versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion) + versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion.FinalOrFutureInt()) if err != nil { ctx.OtherModuleErrorf(dep, err.Error()) return @@ -2488,7 +2488,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // if this is for use_vendor apex && dep has stubsVersions // apply the same rule of apex sdk enforcement to choose right version var err error - versionToUse, err = c.ChooseSdkVersion(versions, c.apexSdkVersion) + versionToUse, err = c.ChooseSdkVersion(versions, c.apexSdkVersion.FinalOrFutureInt()) if err != nil { ctx.OtherModuleErrorf(dep, err.Error()) return @@ -3012,21 +3012,8 @@ func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return true } -// b/154667674: refactor this to handle "current" in a consistent way -func decodeSdkVersionString(ctx android.BaseModuleContext, versionString string) (int, error) { - if versionString == "" { - return 0, fmt.Errorf("not specified") - } - if versionString == "current" { - if ctx.Config().PlatformSdkCodename() == "REL" { - return ctx.Config().PlatformSdkVersionInt(), nil - } - return android.FutureApiLevel, nil - } - return android.ApiStrToNum(ctx, versionString) -} - -func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // We ignore libclang_rt.* prebuilt libs since they declare sdk_version: 14(b/121358700) if strings.HasPrefix(ctx.OtherModuleName(c), "libclang_rt") { return nil @@ -3050,11 +3037,17 @@ func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersi // non-SDK variant resets sdk_version, which works too. minSdkVersion = c.SdkVersion() } - ver, err := decodeSdkVersionString(ctx, minSdkVersion) + if minSdkVersion == "" { + return fmt.Errorf("neither min_sdk_version nor sdk_version specificed") + } + // Not using nativeApiLevelFromUser because the context here is not + // necessarily a native context. + ver, err := android.ApiLevelFromUser(ctx, minSdkVersion) if err != nil { return err } - if ver > sdkVersion { + + if ver.GreaterThan(sdkVersion) { return fmt.Errorf("newer SDK(%v)", ver) } return nil diff --git a/cc/compiler.go b/cc/compiler.go index f74582004..bb5c7bf2a 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -354,7 +354,9 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_NAME__='\""+ctx.apexVariationName()+"\"'") } if ctx.Device() { - flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_SDK_VERSION__="+strconv.Itoa(ctx.apexSdkVersion())) + flags.Global.CommonFlags = append(flags.Global.CommonFlags, + fmt.Sprintf("-D__ANDROID_SDK_VERSION__=%d", + ctx.apexSdkVersion().FinalOrFutureInt())) } } @@ -390,7 +392,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps if ctx.Os().Class == android.Device { version := ctx.sdkVersion() if version == "" || version == "current" { - target += strconv.Itoa(android.FutureApiLevel) + target += strconv.Itoa(android.FutureApiLevelInt) } else { target += version } diff --git a/cc/library.go b/cc/library.go index 7b09b1145..8048f0002 100644 --- a/cc/library.go +++ b/cc/library.go @@ -19,8 +19,6 @@ import ( "io" "path/filepath" "regexp" - "sort" - "strconv" "strings" "sync" @@ -1520,20 +1518,18 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) { } func normalizeVersions(ctx android.BaseModuleContext, versions []string) { - numVersions := make([]int, len(versions)) + var previous android.ApiLevel for i, v := range versions { - numVer, err := android.ApiStrToNum(ctx, v) + ver, err := android.ApiLevelFromUser(ctx, v) if err != nil { ctx.PropertyErrorf("versions", "%s", err.Error()) return } - numVersions[i] = numVer - } - if !sort.IsSorted(sort.IntSlice(numVersions)) { - ctx.PropertyErrorf("versions", "not sorted: %v", versions) - } - for i, v := range numVersions { - versions[i] = strconv.Itoa(v) + if i > 0 && ver.LessThanOrEqualTo(previous) { + ctx.PropertyErrorf("versions", "not sorted: %v", versions) + } + versions[i] = ver.String() + previous = ver } } diff --git a/cc/library_test.go b/cc/library_test.go index cb167252d..49838b48e 100644 --- a/cc/library_test.go +++ b/cc/library_test.go @@ -195,7 +195,7 @@ func TestStubsVersions(t *testing.T) { name: "libfoo", srcs: ["foo.c"], stubs: { - versions: ["29", "R", "10000"], + versions: ["29", "R", "current"], }, } ` @@ -204,7 +204,7 @@ func TestStubsVersions(t *testing.T) { ctx := testCcWithConfig(t, config) variants := ctx.ModuleVariantsForTests("libfoo") - for _, expectedVer := range []string{"29", "9000", "10000"} { + for _, expectedVer := range []string{"29", "R", "current"} { expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer if !inList(expectedVariant, variants) { t.Errorf("missing expected variant: %q", expectedVariant) @@ -218,7 +218,7 @@ func TestStubsVersions_NotSorted(t *testing.T) { name: "libfoo", srcs: ["foo.c"], stubs: { - versions: ["29", "10000", "R"], + versions: ["29", "current", "R"], }, } ` @@ -233,10 +233,10 @@ func TestStubsVersions_ParseError(t *testing.T) { name: "libfoo", srcs: ["foo.c"], stubs: { - versions: ["29", "10000", "X"], + versions: ["29", "current", "X"], }, } ` - testCcError(t, `"libfoo" .*: versions: SDK version should be`, bp) + testCcError(t, `"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`, bp) } diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 4c6d98c52..5682d1c6b 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -118,8 +118,8 @@ func generatePerApiVariants(ctx android.BottomUpMutatorContext, m *Module, versionStrs = append(versionStrs, version.String()) } } - versions = append(versions, android.CurrentApiLevel) - versionStrs = append(versionStrs, android.CurrentApiLevel.String()) + versions = append(versions, android.FutureApiLevel) + versionStrs = append(versionStrs, android.FutureApiLevel.String()) modules := ctx.CreateVariations(versionStrs...) for i, module := range modules { diff --git a/genrule/genrule.go b/genrule/genrule.go index 1cec2893a..4a2f81073 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -555,7 +555,8 @@ func (g *Module) AndroidMk() android.AndroidMkData { } } -func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // Because generated outputs are checked by client modules(e.g. cc_library, ...) // we can safely ignore the check here. return nil diff --git a/java/aar.go b/java/aar.go index 667dd9de4..9cab0bdca 100644 --- a/java/aar.go +++ b/java/aar.go @@ -189,7 +189,7 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, // Version code if !hasVersionCode { - linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion()) + linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion().String()) } if !hasVersionName { @@ -774,7 +774,8 @@ func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.M return a.depIsInSameApex(ctx, dep) } -func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { return nil } diff --git a/java/app.go b/java/app.go index ae7373fc7..2377c911b 100755 --- a/java/app.go +++ b/java/app.go @@ -157,7 +157,7 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) "abis": strings.Join(SupportedAbis(ctx), ","), "allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)), "screen-densities": screenDensities, - "sdk-version": ctx.Config().PlatformSdkVersion(), + "sdk-version": ctx.Config().PlatformSdkVersion().String(), "stem": as.BaseModuleName(), "apkcerts": as.apkcertsFile.String(), "partition": as.PartitionTag(ctx.DeviceConfig()), @@ -436,7 +436,7 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil { a.checkJniLibsSdkVersion(ctx, minSdkVersion) - android.CheckMinSdkVersion(a, ctx, int(minSdkVersion)) + android.CheckMinSdkVersion(a, ctx, minSdkVersion.ApiLevel(ctx)) } else { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) } @@ -1637,7 +1637,8 @@ func (a *AndroidAppImport) minSdkVersion() sdkSpec { return sdkSpecFrom("") } -func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +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 } diff --git a/java/app_test.go b/java/app_test.go index 536797119..4347db8b1 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -1078,6 +1078,7 @@ func TestAppSdkVersion(t *testing.T) { platformSdkFinal bool expectedMinSdkVersion string platformApis bool + activeCodenames []string }{ { name: "current final SDK", @@ -1094,6 +1095,7 @@ func TestAppSdkVersion(t *testing.T) { platformSdkCodename: "OMR1", platformSdkFinal: false, expectedMinSdkVersion: "OMR1", + activeCodenames: []string{"OMR1"}, }, { name: "default final SDK", @@ -1112,11 +1114,14 @@ func TestAppSdkVersion(t *testing.T) { platformSdkCodename: "OMR1", platformSdkFinal: false, expectedMinSdkVersion: "OMR1", + activeCodenames: []string{"OMR1"}, }, { name: "14", sdkVersion: "14", expectedMinSdkVersion: "14", + platformSdkCodename: "S", + activeCodenames: []string{"S"}, }, } @@ -1137,6 +1142,7 @@ func TestAppSdkVersion(t *testing.T) { config := testAppConfig(nil, bp, nil) config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename + config.TestProductVariables.Platform_version_active_codenames = test.activeCodenames config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal checkSdkVersion(t, config, test.expectedMinSdkVersion) @@ -1173,15 +1179,6 @@ func TestVendorAppSdkVersion(t *testing.T) { deviceCurrentApiLevelForVendorModules: "28", expectedMinSdkVersion: "28", }, - { - name: "current final SDK", - sdkVersion: "current", - platformSdkInt: 29, - platformSdkCodename: "Q", - platformSdkFinal: false, - deviceCurrentApiLevelForVendorModules: "current", - expectedMinSdkVersion: "Q", - }, { name: "current final SDK", sdkVersion: "current", diff --git a/java/droiddoc.go b/java/droiddoc.go index 85a61dd98..55bc04173 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -1228,7 +1228,7 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml) cmd.FlagWithInput("--apply-api-levels ", d.apiVersionsXml) - cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion()) + cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String()) cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename()) filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar") diff --git a/java/java.go b/java/java.go index d67e9e098..1d7eaa771 100644 --- a/java/java.go +++ b/java/java.go @@ -1658,7 +1658,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { if v := sdkSpec.version; v.isNumbered() { return v.String() } else { - return ctx.Config().DefaultAppTargetSdk() + return ctx.Config().DefaultAppTargetSdk(ctx).String() } } @@ -1876,7 +1876,8 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return j.depIsInSameApex(ctx, dep) } -func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { sdkSpec := j.minSdkVersion() if !sdkSpec.specified() { return fmt.Errorf("min_sdk_version is not specified") @@ -1888,7 +1889,7 @@ func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersi if err != nil { return err } - if int(ver) > sdkVersion { + if ver.ApiLevel(ctx).GreaterThan(sdkVersion) { return fmt.Errorf("newer SDK(%v)", ver) } return nil @@ -2753,7 +2754,8 @@ func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return j.depIsInSameApex(ctx, dep) } -func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // Do not check for prebuilts against the min_sdk_version of enclosing APEX return nil } @@ -2936,7 +2938,8 @@ func (j *DexImport) DexJarBuildPath() android.Path { return j.dexJarFile } -func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // we don't check prebuilt modules for sdk_version return nil } diff --git a/java/sdk.go b/java/sdk.go index 56fa12b3e..f59926502 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -107,7 +107,7 @@ type sdkVersion int const ( // special version number for a not-yet-frozen SDK - sdkVersionCurrent sdkVersion = sdkVersion(android.FutureApiLevel) + sdkVersionCurrent sdkVersion = sdkVersion(android.FutureApiLevelInt) // special version number to be used for SDK specs where version number doesn't // make sense, e.g. "none", "", etc. sdkVersionNone sdkVersion = sdkVersion(0) @@ -133,6 +133,10 @@ func (v sdkVersion) String() string { return "(no version)" } +func (v sdkVersion) ApiLevel(ctx android.EarlyModuleContext) android.ApiLevel { + return android.ApiLevelOrPanic(ctx, v.String()) +} + // asNumberString directly converts the numeric value of this sdk version as a string. // When isNumbered() is true, this method is the same as String(). However, for sdkVersionCurrent // and sdkVersionNone, this returns 10000 and 0 while String() returns "current" and "(no version"), @@ -243,7 +247,7 @@ func (s sdkSpec) effectiveVersion(ctx android.EarlyModuleContext) (sdkVersion, e if s.version.isNumbered() { return s.version, nil } - return sdkVersion(ctx.Config().DefaultAppTargetSdkInt()), nil + return sdkVersion(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt()), nil } // effectiveVersionString converts an sdkSpec into the concrete version string that the module @@ -251,8 +255,8 @@ func (s sdkSpec) effectiveVersion(ctx android.EarlyModuleContext) (sdkVersion, e // it returns the codename (P, Q, R, etc.) func (s sdkSpec) effectiveVersionString(ctx android.EarlyModuleContext) (string, error) { ver, err := s.effectiveVersion(ctx) - if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdkInt() { - return ctx.Config().DefaultAppTargetSdk(), nil + if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt() { + return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil } return ver.String(), err } diff --git a/java/sdk_library.go b/java/sdk_library.go index 1a5ef544c..a7b92b3a8 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1878,7 +1878,8 @@ func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, return false } -func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // we don't check prebuilt modules for sdk_version return nil } @@ -2078,7 +2079,8 @@ func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) { // do nothing } -func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked return nil } diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go index 768c8e5b0..480f9b797 100644 --- a/sysprop/sysprop_library.go +++ b/sysprop/sysprop_library.go @@ -310,7 +310,8 @@ func (m *syspropLibrary) AndroidMk() android.AndroidMkData { }} } -func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { +func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, + sdkVersion android.ApiLevel) error { return fmt.Errorf("sysprop_library is not supposed to be part of apex modules") }