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

Commit 54105c48 authored by Jiyong Park's avatar Jiyong Park
Browse files

SdkSpec = Scope + ApiLevel

SdkSpec.Version was an int type. Now it becomes ApiLevel type which
is a better abstraction of the version (or api level).

Bug: 1655587
Test: m

Change-Id: I4d67b9b9eae45f653b6af4f5b73da9e091b3dfab
parent 0774773a
Loading
Loading
Loading
Loading
+43 −76
Original line number Diff line number Diff line
@@ -75,58 +75,15 @@ func (k SdkKind) String() string {
	}
}

// SdkVersion represents a specific version number of an SDK spec of a particular kind
type SdkVersion int

const (
	// special version number for a not-yet-frozen SDK
	SdkVersionCurrent SdkVersion = SdkVersion(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)
)

// IsCurrent checks if the SdkVersion refers to the not-yet-published version of an SdkKind
func (v SdkVersion) IsCurrent() bool {
	return v == SdkVersionCurrent
}

// IsNumbered checks if the SdkVersion refers to the published (a.k.a numbered) version of an SdkKind
func (v SdkVersion) IsNumbered() bool {
	return !v.IsCurrent() && v != SdkVersionNone
}

// String returns the string representation of this SdkVersion.
func (v SdkVersion) String() string {
	if v.IsCurrent() {
		return "current"
	} else if v.IsNumbered() {
		return strconv.Itoa(int(v))
	}
	return "(no version)"
}

func (v SdkVersion) ApiLevel(ctx EarlyModuleContext) ApiLevel {
	return 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"),
// respectively.
func (v SdkVersion) AsNumberString() string {
	return strconv.Itoa(int(v))
}

// SdkSpec represents the kind and the version of an SDK for a module to build against
type SdkSpec struct {
	Kind     SdkKind
	Version SdkVersion
	ApiLevel ApiLevel
	Raw      string
}

func (s SdkSpec) String() string {
	return fmt.Sprintf("%s_%s", s.Kind, s.Version)
	return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
}

// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
@@ -177,10 +134,10 @@ func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
	}

	if s.Kind == SdkPublic || s.Kind == SdkSystem {
		if s.Version.IsCurrent() {
		if s.ApiLevel.IsCurrent() {
			if i, err := strconv.Atoi(currentSdkVersion); err == nil {
				version := SdkVersion(i)
				return SdkSpec{s.Kind, version, s.Raw}
				apiLevel := uncheckedFinalApiLevel(i)
				return SdkSpec{s.Kind, apiLevel, s.Raw}
			}
			panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
		}
@@ -190,10 +147,10 @@ func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {

// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
	if s.Version.IsCurrent() {
	if s.ApiLevel.IsCurrent() {
		// "current" can be built from source and be from prebuilt SDK
		return ctx.Config().AlwaysUsePrebuiltSdks()
	} else if s.Version.IsNumbered() {
	} else if !s.ApiLevel.IsPreview() {
		// validation check
		if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule {
			panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
@@ -206,50 +163,60 @@ func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
	return false
}

// EffectiveVersion converts an SdkSpec into the concrete SdkVersion that the module
// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
// it returns FutureApiLevel(10000).
func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (SdkVersion, error) {
// EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
// FutureApiLevel(10000).
func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
	if !s.Valid() {
		return s.Version, fmt.Errorf("invalid sdk version %q", s.Raw)
		return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
	}

	if ctx.DeviceSpecific() || ctx.SocSpecific() {
		s = s.ForVendorPartition(ctx)
	}
	if s.Version.IsNumbered() {
		return s.Version, nil
	if !s.ApiLevel.IsPreview() {
		return s.ApiLevel, nil
	}
	return SdkVersion(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt()), nil
	ret := ctx.Config().DefaultAppTargetSdk(ctx)
	if ret.IsPreview() {
		return FutureApiLevel, nil
	}
	return ret, nil
}

// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
// it returns the codename (P, Q, R, etc.)
func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
	ver, err := s.EffectiveVersion(ctx)
	if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt() {
		return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil
	if !s.Valid() {
		return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
	}
	return ver.String(), err

	if ctx.DeviceSpecific() || ctx.SocSpecific() {
		s = s.ForVendorPartition(ctx)
	}
	if !s.ApiLevel.IsPreview() {
		return s.ApiLevel.String(), nil
	}
	return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil
}

func SdkSpecFrom(str string) SdkSpec {
	switch str {
	// special cases first
	case "":
		return SdkSpec{SdkPrivate, SdkVersionNone, str}
		return SdkSpec{SdkPrivate, NoneApiLevel, str}
	case "none":
		return SdkSpec{SdkNone, SdkVersionNone, str}
		return SdkSpec{SdkNone, NoneApiLevel, str}
	case "core_platform":
		return SdkSpec{SdkCorePlatform, SdkVersionNone, str}
		return SdkSpec{SdkCorePlatform, NoneApiLevel, str}
	default:
		// the syntax is [kind_]version
		sep := strings.LastIndex(str, "_")

		var kindString string
		if sep == 0 {
			return SdkSpec{SdkInvalid, SdkVersionNone, str}
			return SdkSpec{SdkInvalid, NoneApiLevel, str}
		} else if sep == -1 {
			kindString = ""
		} else {
@@ -272,19 +239,19 @@ func SdkSpecFrom(str string) SdkSpec {
		case "system_server":
			kind = SdkSystemServer
		default:
			return SdkSpec{SdkInvalid, SdkVersionNone, str}
			return SdkSpec{SdkInvalid, NoneApiLevel, str}
		}

		var version SdkVersion
		var apiLevel ApiLevel
		if versionString == "current" {
			version = SdkVersionCurrent
			apiLevel = FutureApiLevel
		} else if i, err := strconv.Atoi(versionString); err == nil {
			version = SdkVersion(i)
			apiLevel = uncheckedFinalApiLevel(i)
		} else {
			return SdkSpec{SdkInvalid, SdkVersionNone, str}
			return SdkSpec{SdkInvalid, apiLevel, str}
		}

		return SdkSpec{kind, version, str}
		return SdkSpec{kind, apiLevel, str}
	}
}

@@ -292,7 +259,7 @@ func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
	// Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
	// Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
	// sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
	if s.Kind != SdkSystem || !s.Version.IsNumbered() {
	if s.Kind != SdkSystem || s.ApiLevel.IsPreview() {
		return true
	}
	allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
@@ -302,7 +269,7 @@ func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
			allowedVersions = systemSdkVersions
		}
	}
	if len(allowedVersions) > 0 && !InList(s.Version.String(), allowedVersions) {
	if len(allowedVersions) > 0 && !InList(s.ApiLevel.String(), allowedVersions) {
		ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
			s.Raw, allowedVersions)
		return false
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
		if err != nil {
			ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
		}
		if minSdkVersion >= 23 {
		if minSdkVersion.FinalOrFutureInt() >= 23 {
			args = append(args, fmt.Sprintf("--extract-native-libs=%v", !useEmbeddedNativeLibs))
		} else if useEmbeddedNativeLibs {
			ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
+4 −4
Original line number Diff line number Diff line
@@ -288,7 +288,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, minSdkVersion.ApiLevel(ctx))
			android.CheckMinSdkVersion(a, ctx, minSdkVersion)
		} else {
			ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
		}
@@ -304,7 +304,7 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
// because, sdk_version is overridden by min_sdk_version (if set as smaller)
// and sdkLinkType is checked with dependencies so we can be sure that the whole dependency tree
// will meet the requirements.
func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.SdkVersion) {
func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
	// It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType()
	ctx.VisitDirectDeps(func(m android.Module) {
		if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) {
@@ -315,7 +315,7 @@ func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVer
		// We can rely on android.SdkSpec to convert it to <number> so that "current" is
		// handled properly regardless of sdk finalization.
		jniSdkVersion, err := android.SdkSpecFrom(dep.SdkVersion()).EffectiveVersion(ctx)
		if err != nil || minSdkVersion < jniSdkVersion {
		if err != nil || minSdkVersion.LessThan(jniSdkVersion) {
			ctx.OtherModuleErrorf(dep, "sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)",
				dep.SdkVersion(), minSdkVersion, ctx.ModuleName())
			return
@@ -333,7 +333,7 @@ func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
	}

	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
	return (minSdkVersion >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) ||
	return (minSdkVersion.FinalOrFutureInt() >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) ||
		!apexInfo.IsForPlatform()
}

+3 −3
Original line number Diff line number Diff line
@@ -535,7 +535,7 @@ func (j *Module) TargetSdkVersion() android.SdkSpec {
}

func (j *Module) MinSdkVersionString() string {
	return j.MinSdkVersion().Version.String()
	return j.MinSdkVersion().ApiLevel.String()
}

func (j *Module) AvailableFor(what string) bool {
@@ -1255,7 +1255,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {

	if ctx.Device() {
		lintSDKVersionString := func(sdkSpec android.SdkSpec) string {
			if v := sdkSpec.Version; v.IsNumbered() {
			if v := sdkSpec.ApiLevel; !v.IsPreview() {
				return v.String()
			} else {
				return ctx.Config().DefaultAppTargetSdk(ctx).String()
@@ -1482,7 +1482,7 @@ func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
	if err != nil {
		return err
	}
	if ver.ApiLevel(ctx).GreaterThan(sdkVersion) {
	if ver.GreaterThan(sdkVersion) {
		return fmt.Errorf("newer SDK(%v)", ver)
	}
	return nil
+2 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
package java

import (
	"strconv"
	"strings"

	"github.com/google/blueprint"
@@ -179,7 +180,7 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion android.
		ctx.PropertyErrorf("min_sdk_version", "%s", err)
	}

	flags = append(flags, "--min-api "+effectiveVersion.AsNumberString())
	flags = append(flags, "--min-api "+strconv.Itoa(effectiveVersion.FinalOrFutureInt()))
	return flags
}

Loading