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

Commit 8bd50953 authored by Dan Albert's avatar Dan Albert Committed by Gerrit Code Review
Browse files

Merge changes from topics "soong-apilevel", "soong-config-apilevel"

* changes:
  Convert more versions in config to ApiLevel.
  Replace FutureApiLevel with an ApiLevel.
  Replace ApiStrToNum uses with ApiLevel.
parents 2c7ca784 4f378d75
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
+21 −27
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 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\", <number> or <codename>: %q", apiLevel)
}

func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) {
	apiLevelsMap := getApiLevelsMap(ctx.Config())
	apiLevelsJson := GetApiLevelsJson(ctx)
+30 −28
Original line number Diff line number Diff line
@@ -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"
@@ -224,6 +229,8 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string
		productVariables: productVariables{
			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"},
@@ -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 {
func (c *config) DefaultAppTargetSdk(ctx EarlyModuleContext) ApiLevel {
	if Bool(c.productVariables.Platform_sdk_final) {
		return c.PlatformSdkVersionInt()
		return c.PlatformSdkVersion()
	} else {
		return FutureApiLevel
		codename := c.PlatformSdkCodename()
		if codename == "" {
			return NoneApiLevel
		}
		if codename == "REL" {
			panic("Platform_sdk_codename should not be REL when Platform_sdk_final is true")
		}

func (c *config) DefaultAppTargetSdk() string {
	if Bool(c.productVariables.Platform_sdk_final) {
		return c.PlatformSdkVersion()
	} else {
		return c.PlatformSdkCodename()
		return ApiLevelOrPanic(ctx, codename)
	}
}

+12 −16
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
	}
	// 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.FutureApiLevel
	}
	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
+4 −10
Original line number Diff line number Diff line
@@ -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"],
		}
Loading