Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8060536 authored by Dan Albert's avatar Dan Albert
Browse files

Replace ApiStrToNum uses with ApiLevel.

Test: treehugger
Bug: http://b/154667674
Change-Id: I2954bb21c1cfdeb305f25cfb6c8711c930f6ed50
parent af6073f7
Loading
Loading
Loading
Loading
+30 −17
Original line number Diff line number Diff line
@@ -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
	// 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
+19 −18
Original line number Diff line number Diff line
@@ -49,6 +49,14 @@ type ApiLevel struct {
	isPreview bool
}

func (this ApiLevel) FinalOrFutureInt() int {
	if this.IsPreview() {
		return FutureApiLevel
	} 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".
@@ -261,6 +269,17 @@ 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()
		}
@@ -300,24 +319,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\", <number> or <codename>: %q", apiLevel)
}

func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) {
	apiLevelsMap := getApiLevelsMap(ctx.Config())
	apiLevelsJson := GetApiLevelsJson(ctx)
+13 −17
Original line number Diff line number Diff line
@@ -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
		return android.CurrentApiLevel
	}
	// 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
	}
	if apiLevel.IsPreview() {
		// All codenames should build against "current".
		return android.CurrentApiLevel
	}
	return intVer
	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
+3 −9
Original line number Diff line number Diff line
@@ -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"],
		}
+9 −7
Original line number Diff line number Diff line
@@ -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 {
@@ -536,8 +537,9 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
		// TODO(b/157078772): propagate min_sdk_version to apexer.
		minSdkVersion := ctx.Config().DefaultAppTargetSdk()

		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())
		}
Loading