Merge changes from topics "presubmit-am-0a046d9514b34cc1a3b2b3584e857f6c", "presubmit-am-22410ea0b46e4a3d961d51518c65514d", "presubmit-am-2646dd78e751450296e76a7e6fac60eb", "presubmit-am-2762d254a366481180c66eefcb7b8c53", "presubmit-am-36ef44194069468da39e59065e3b9d39", "presubmit-am-6e59a6b21a5047bd940a9bff59c79228", "presubmit-am-855c4e732f2645568065c3c870ecd0da", "presubmit-am-dae9703bfd65425b8b44605c42e9d5b9" into sc-mainline-prod

* changes:
  Allow java_sdk_library in an APEX to have higher min_sdk_version.
  Perform CheckMinSdkVersion for java_sdk_library.
  Add MinSdkVersion(ctx) method to ModuleWithMinSdkVersionCheck interface.
  Add ModuleWithMinSdkVersionCheck type.
  Use textproto format for classpaths.proto generation.
  Propagate min and max sdk versions to classpaths.proto configs.
  Introduce max_sdk_version device property.
  Test SdkSpecForm.
This commit is contained in:
TreeHugger Robot
2021-12-09 15:54:26 +00:00
committed by Android (Google) Code Review
16 changed files with 493 additions and 47 deletions

View File

@@ -110,6 +110,7 @@ bootstrap_go_package {
"paths_test.go",
"prebuilt_test.go",
"rule_builder_test.go",
"sdk_version_test.go",
"singleton_module_test.go",
"soong_config_modules_test.go",
"util_test.go",

View File

@@ -903,16 +903,18 @@ var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel {
//
// Return true if the `to` module should be visited, false otherwise.
type PayloadDepsCallback func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
type WalkPayloadDepsFunc func(ctx ModuleContext, do PayloadDepsCallback)
// UpdatableModule represents updatable APEX/APK
type UpdatableModule interface {
// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
type ModuleWithMinSdkVersionCheck interface {
Module
WalkPayloadDeps(ctx ModuleContext, do PayloadDepsCallback)
MinSdkVersion(ctx EarlyModuleContext) SdkSpec
CheckMinSdkVersion(ctx ModuleContext)
}
// CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version
// accordingly
func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiLevel) {
func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayloadDepsFunc) {
// do not enforce min_sdk_version for host
if ctx.Host() {
return
@@ -928,7 +930,7 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiL
return
}
m.WalkPayloadDeps(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
walk(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
if externalDep {
// external deps are outside the payload boundary, which is "stable"
// interface. We don't have to check min_sdk_version for external
@@ -938,6 +940,14 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiL
if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
return false
}
if m, ok := to.(ModuleWithMinSdkVersionCheck); ok {
// This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version
// to trigger the check.
if !m.MinSdkVersion(ctx).Specified() {
ctx.OtherModuleErrorf(m, "must set min_sdk_version")
}
return false
}
if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
toName := ctx.OtherModuleName(to)
if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {

View File

@@ -188,8 +188,8 @@ var FirstNonLibAndroidSupportVersion = uncheckedFinalApiLevel(21)
// * "30" -> "30"
// * "R" -> "30"
// * "S" -> "S"
func ReplaceFinalizedCodenames(ctx PathContext, raw string) string {
num, ok := getFinalCodenamesMap(ctx.Config())[raw]
func ReplaceFinalizedCodenames(config Config, raw string) string {
num, ok := getFinalCodenamesMap(config)[raw]
if !ok {
return raw
}
@@ -197,7 +197,7 @@ func ReplaceFinalizedCodenames(ctx PathContext, raw string) string {
return strconv.Itoa(num)
}
// Converts the given string `raw` to an ApiLevel, possibly returning an error.
// ApiLevelFromUser converts the given string `raw` to an ApiLevel, possibly returning an error.
//
// `raw` must be non-empty. Passing an empty string results in a panic.
//
@@ -212,6 +212,12 @@ func ReplaceFinalizedCodenames(ctx PathContext, raw string) string {
// Inputs that are not "current", known previews, or convertible to an integer
// will return an error.
func ApiLevelFromUser(ctx PathContext, raw string) (ApiLevel, error) {
return ApiLevelFromUserWithConfig(ctx.Config(), raw)
}
// ApiLevelFromUserWithConfig implements ApiLevelFromUser, see comments for
// ApiLevelFromUser for more details.
func ApiLevelFromUserWithConfig(config Config, raw string) (ApiLevel, error) {
if raw == "" {
panic("API level string must be non-empty")
}
@@ -220,13 +226,13 @@ func ApiLevelFromUser(ctx PathContext, raw string) (ApiLevel, error) {
return FutureApiLevel, nil
}
for _, preview := range ctx.Config().PreviewApiLevels() {
for _, preview := range config.PreviewApiLevels() {
if raw == preview.String() {
return preview, nil
}
}
canonical := ReplaceFinalizedCodenames(ctx, raw)
canonical := ReplaceFinalizedCodenames(config, raw)
asInt, err := strconv.Atoi(canonical)
if err != nil {
return NoneApiLevel, fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", canonical)

View File

@@ -698,6 +698,16 @@ func (c *config) PreviewApiLevels() []ApiLevel {
return levels
}
func (c *config) LatestPreviewApiLevel() ApiLevel {
level := NoneApiLevel
for _, l := range c.PreviewApiLevels() {
if l.GreaterThan(level) {
level = l
}
}
return level
}
func (c *config) AllSupportedApiLevels() []ApiLevel {
var levels []ApiLevel
levels = append(levels, c.FinalApiLevels()...)

View File

@@ -117,7 +117,7 @@ func (s SdkSpec) Stable() bool {
return false
}
// PrebuiltSdkAvailableForUnbundledBuilt tells whether this SdkSpec can have a prebuilt SDK
// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
// that can be used for unbundled builds.
func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
// "", "none", and "core_platform" are not available for unbundled build
@@ -212,6 +212,10 @@ var (
)
func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
return SdkSpecFromWithConfig(ctx.Config(), str)
}
func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
switch str {
// special cases first
case "":
@@ -252,7 +256,7 @@ func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
return SdkSpec{SdkInvalid, NoneApiLevel, str}
}
apiLevel, err := ApiLevelFromUser(ctx, versionString)
apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
if err != nil {
return SdkSpec{SdkInvalid, apiLevel, str}
}

View File

@@ -0,0 +1,89 @@
// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package android
import (
"testing"
)
func TestSdkSpecFrom(t *testing.T) {
testCases := []struct {
input string
expected string
}{
{
input: "",
expected: "private_current",
},
{
input: "none",
expected: "none_(no version)",
},
{
input: "core_platform",
expected: "core_platform_current",
},
{
input: "_",
expected: "invalid_(no version)",
},
{
input: "_31",
expected: "invalid_(no version)",
},
{
input: "system_R",
expected: "system_30",
},
{
input: "test_31",
expected: "test_31",
},
{
input: "module_current",
expected: "module-lib_current",
},
{
input: "31",
expected: "public_31",
},
{
input: "S",
expected: "public_31",
},
{
input: "current",
expected: "public_current",
},
{
input: "Tiramisu",
expected: "public_Tiramisu",
},
}
config := NullConfig("")
config.productVariables = productVariables{
Platform_sdk_version: intPtr(31),
Platform_sdk_codename: stringPtr("Tiramisu"),
Platform_version_active_codenames: []string{"Tiramisu"},
}
for _, tc := range testCases {
if got := SdkSpecFromWithConfig(config, tc.input).String(); tc.expected != got {
t.Errorf("Expected %v, got %v", tc.expected, got)
}
}
}

View File

@@ -1632,7 +1632,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// 1) do some validity checks such as apex_available, min_sdk_version, etc.
a.checkApexAvailability(ctx)
a.checkUpdatable(ctx)
a.checkMinSdkVersion(ctx)
a.CheckMinSdkVersion(ctx)
a.checkStaticLinkingToStubLibraries(ctx)
if len(a.properties.Tests) > 0 && !a.testApex {
ctx.PropertyErrorf("tests", "property allowed only in apex_test module type")
@@ -2246,18 +2246,28 @@ func overrideApexFactory() android.Module {
//
// TODO(jiyong): move these checks to a separate go file.
var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil)
// Entures that min_sdk_version of the included modules are equal or less than the min_sdk_version
// of this apexBundle.
func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) {
func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) {
if a.testApex || a.vndkApex {
return
}
// apexBundle::minSdkVersion reports its own errors.
minSdkVersion := a.minSdkVersion(ctx)
android.CheckMinSdkVersion(a, ctx, minSdkVersion)
android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
}
func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel {
func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return android.SdkSpec{
Kind: android.SdkNone,
ApiLevel: a.minSdkVersion(ctx),
Raw: String(a.properties.Min_sdk_version),
}
}
func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
ver := proptools.String(a.properties.Min_sdk_version)
if ver == "" {
return android.NoneApiLevel

View File

@@ -7742,6 +7742,184 @@ func TestApexJavaCoverage(t *testing.T) {
}
}
func TestSdkLibraryCanHaveHigherMinSdkVersion(t *testing.T) {
preparer := android.GroupFixturePreparers(
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.PrepareForTestWithJavaDefaultModules,
android.PrepareForTestWithAndroidBuildComponents,
dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"),
dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"),
)
// Test java_sdk_library in bootclasspath_fragment may define higher min_sdk_version than the apex
t.Run("bootclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) {
preparer.RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
bootclasspath_fragments: ["mybootclasspathfragment"],
min_sdk_version: "30",
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
bootclasspath_fragment {
name: "mybootclasspathfragment",
contents: ["mybootclasspathlib"],
apex_available: ["myapex"],
}
java_sdk_library {
name: "mybootclasspathlib",
srcs: ["mybootclasspathlib.java"],
apex_available: ["myapex"],
compile_dex: true,
unsafe_ignore_missing_latest_api: true,
min_sdk_version: "31",
static_libs: ["util"],
}
java_library {
name: "util",
srcs: ["a.java"],
apex_available: ["myapex"],
min_sdk_version: "31",
static_libs: ["another_util"],
}
java_library {
name: "another_util",
srcs: ["a.java"],
min_sdk_version: "31",
apex_available: ["myapex"],
}
`)
})
// Test java_sdk_library in systemserverclasspath_fragment may define higher min_sdk_version than the apex
t.Run("systemserverclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) {
preparer.RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
min_sdk_version: "30",
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
contents: ["mysystemserverclasspathlib"],
apex_available: ["myapex"],
}
java_sdk_library {
name: "mysystemserverclasspathlib",
srcs: ["mysystemserverclasspathlib.java"],
apex_available: ["myapex"],
compile_dex: true,
min_sdk_version: "32",
unsafe_ignore_missing_latest_api: true,
static_libs: ["util"],
}
java_library {
name: "util",
srcs: ["a.java"],
apex_available: ["myapex"],
min_sdk_version: "31",
static_libs: ["another_util"],
}
java_library {
name: "another_util",
srcs: ["a.java"],
min_sdk_version: "31",
apex_available: ["myapex"],
}
`)
})
t.Run("bootclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mybootclasspathlib".*must set min_sdk_version`)).
RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
bootclasspath_fragments: ["mybootclasspathfragment"],
min_sdk_version: "30",
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
bootclasspath_fragment {
name: "mybootclasspathfragment",
contents: ["mybootclasspathlib"],
apex_available: ["myapex"],
}
java_sdk_library {
name: "mybootclasspathlib",
srcs: ["mybootclasspathlib.java"],
apex_available: ["myapex"],
compile_dex: true,
unsafe_ignore_missing_latest_api: true,
}
`)
})
t.Run("systemserverclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mysystemserverclasspathlib".*must set min_sdk_version`)).
RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
min_sdk_version: "30",
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
contents: ["mysystemserverclasspathlib"],
apex_available: ["myapex"],
}
java_sdk_library {
name: "mysystemserverclasspathlib",
srcs: ["mysystemserverclasspathlib.java"],
apex_available: ["myapex"],
compile_dex: true,
unsafe_ignore_missing_latest_api: true,
}
`)
})
}
func TestMain(m *testing.M) {
os.Exit(m.Run())
}

View File

@@ -122,6 +122,14 @@ func FixtureSetBootJars(bootJars ...string) android.FixturePreparer {
func FixtureSetApexBootJars(bootJars ...string) android.FixturePreparer {
return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.ApexBootJars = android.CreateTestConfiguredJarList(bootJars)
})
}
// FixtureSetApexSystemServerJars sets the ApexSystemServerJars property in the global config.
func FixtureSetApexSystemServerJars(jars ...string) android.FixturePreparer {
return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.ApexSystemServerJars = android.CreateTestConfiguredJarList(jars)
})
}

View File

@@ -288,7 +288,7 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
if minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx); err == nil {
a.checkJniLibsSdkVersion(ctx, minSdkVersion)
android.CheckMinSdkVersion(a, ctx, minSdkVersion)
android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
} else {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
}

View File

@@ -185,6 +185,10 @@ type DeviceProperties struct {
// Defaults to sdk_version if not set.
Min_sdk_version *string
// if not blank, set the maximum version of the sdk that the compiled artifacts will run against.
// Defaults to empty string "". See sdk_version for possible values.
Max_sdk_version *string
// if not blank, set the targetSdkVersion in the AndroidManifest.xml.
// Defaults to sdk_version if not set.
Target_sdk_version *string
@@ -367,6 +371,7 @@ type Module struct {
sdkVersion android.SdkSpec
minSdkVersion android.SdkSpec
maxSdkVersion android.SdkSpec
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -524,6 +529,13 @@ func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return j.SdkVersion(ctx)
}
func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
maxSdkVersion := proptools.StringDefault(j.deviceProperties.Max_sdk_version, "")
// SdkSpecFrom returns SdkSpecPrivate for this, which may be confusing.
// TODO(b/208456999): ideally MaxSdkVersion should be an ApiLevel and not SdkSpec.
return android.SdkSpecFrom(ctx, maxSdkVersion)
}
func (j *Module) MinSdkVersionString() string {
return j.minSdkVersion.Raw
}
@@ -1488,8 +1500,7 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu
}
// Implements android.ApexModule
func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
sdkVersion android.ApiLevel) error {
func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
sdkSpec := j.MinSdkVersion(ctx)
if !sdkSpec.Specified() {
return fmt.Errorf("min_sdk_version is not specified")

View File

@@ -84,11 +84,10 @@ func initClasspathFragment(c classpathFragment, classpathType classpathType) {
// Matches definition of Jar in packages/modules/SdkExtensions/proto/classpaths.proto
type classpathJar struct {
path string
classpath classpathType
// TODO(satayev): propagate min/max sdk versions for the jars
minSdkVersion int32
maxSdkVersion int32
path string
classpath classpathType
minSdkVersion string
maxSdkVersion string
}
// gatherPossibleApexModuleNamesAndStems returns a set of module and stem names from the
@@ -120,10 +119,32 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars
jars := make([]classpathJar, 0, len(paths)*len(classpaths))
for i := 0; i < len(paths); i++ {
for _, classpathType := range classpaths {
jars = append(jars, classpathJar{
jar := classpathJar{
classpath: classpathType,
path: paths[i],
}
ctx.VisitDirectDepsIf(func(m android.Module) bool {
return m.Name() == configuredJars.Jar(i)
}, func(m android.Module) {
if s, ok := m.(*SdkLibrary); ok {
// TODO(208456999): instead of mapping "current" to latest, min_sdk_version should never be set to "current"
if s.minSdkVersion.Specified() {
if s.minSdkVersion.ApiLevel.IsCurrent() {
jar.minSdkVersion = ctx.Config().LatestPreviewApiLevel().String()
} else {
jar.minSdkVersion = s.minSdkVersion.ApiLevel.String()
}
}
if s.maxSdkVersion.Specified() {
if s.maxSdkVersion.ApiLevel.IsCurrent() {
jar.maxSdkVersion = ctx.Config().LatestPreviewApiLevel().String()
} else {
jar.maxSdkVersion = s.maxSdkVersion.ApiLevel.String()
}
}
}
})
jars = append(jars, jar)
}
}
return jars
@@ -136,15 +157,15 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M
c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
generatedJson := android.PathForModuleOut(ctx, outputFilename+".json")
writeClasspathsJson(ctx, generatedJson, jars)
generatedTextproto := android.PathForModuleOut(ctx, outputFilename+".textproto")
writeClasspathsTextproto(ctx, generatedTextproto, jars)
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
BuiltTool("conv_classpaths_proto").
Flag("encode").
Flag("--format=json").
FlagWithInput("--input=", generatedJson).
Flag("--format=textproto").
FlagWithInput("--input=", generatedTextproto).
FlagWithOutput("--output=", c.outputFilepath)
rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String())
@@ -159,24 +180,18 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M
ctx.SetProvider(ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
}
func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
var content strings.Builder
fmt.Fprintf(&content, "{\n")
fmt.Fprintf(&content, "\"jars\": [\n")
for idx, jar := range jars {
fmt.Fprintf(&content, "{\n")
fmt.Fprintf(&content, "\"path\": \"%s\",\n", jar.path)
fmt.Fprintf(&content, "\"classpath\": \"%s\"\n", jar.classpath)
if idx < len(jars)-1 {
fmt.Fprintf(&content, "},\n")
} else {
fmt.Fprintf(&content, "}\n")
}
for _, jar := range jars {
fmt.Fprintf(&content, "jars {\n")
fmt.Fprintf(&content, "path: \"%s\"\n", jar.path)
fmt.Fprintf(&content, "classpath: %s\n", jar.classpath)
fmt.Fprintf(&content, "min_sdk_version: \"%s\"\n", jar.minSdkVersion)
fmt.Fprintf(&content, "max_sdk_version: \"%s\"\n", jar.maxSdkVersion)
fmt.Fprintf(&content, "}\n")
}
fmt.Fprintf(&content, "]\n")
fmt.Fprintf(&content, "}\n")
android.WriteFileRule(ctx, output, content.String())
}

View File

@@ -487,6 +487,7 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
j.maxSdkVersion = j.MaxSdkVersion(ctx)
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if !apexInfo.IsForPlatform() {

View File

@@ -68,7 +68,6 @@ type platformBootclasspathProperties struct {
func platformBootclasspathFactory() android.SingletonModule {
m := &platformBootclasspathModule{}
m.AddProperties(&m.properties)
// TODO(satayev): split apex jars into separate configs.
initClasspathFragment(m, BOOTCLASSPATH)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m

View File

@@ -1122,6 +1122,22 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext)
return generatedScopes
}
var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil)
func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) {
android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx).ApiLevel, func(c android.ModuleContext, do android.PayloadDepsCallback) {
ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
isExternal := !module.depIsInSameApex(ctx, child)
if am, ok := child.(android.ApexModule); ok {
if !do(ctx, parent, am, isExternal) {
return false
}
}
return !isExternal
})
})
}
type sdkLibraryComponentTag struct {
blueprint.BaseDependencyTag
name string
@@ -1207,6 +1223,10 @@ func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if proptools.String(module.deviceProperties.Min_sdk_version) != "" {
module.CheckMinSdkVersion(ctx)
}
module.generateCommonBuildActions(ctx)
// Only build an implementation library if required.
@@ -2466,12 +2486,12 @@ func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleConte
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
if module.hideApexVariantFromMake {
return []android.AndroidMkEntries{android.AndroidMkEntries{
return []android.AndroidMkEntries{{
Disabled: true,
}}
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
return []android.AndroidMkEntries{{
Class: "ETC",
OutputFile: android.OptionalPathForPath(module.outputFilePath),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{

View File

@@ -958,3 +958,87 @@ func TestJavaSdkLibraryDist(t *testing.T) {
})
}
}
func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) {
preparer := android.GroupFixturePreparers(
PrepareForTestWithJavaBuildComponents,
PrepareForTestWithJavaDefaultModules,
PrepareForTestWithJavaSdkLibraryFiles,
)
preparer.RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
srcs: ["a.java"],
static_libs: ["util"],
min_sdk_version: "30",
unsafe_ignore_missing_latest_api: true,
}
java_library {
name: "util",
srcs: ["a.java"],
min_sdk_version: "30",
}
`)
preparer.
RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
srcs: ["a.java"],
libs: ["util"],
impl_only_libs: ["util"],
stub_only_libs: ["util"],
stub_only_static_libs: ["util"],
min_sdk_version: "30",
unsafe_ignore_missing_latest_api: true,
}
java_library {
name: "util",
srcs: ["a.java"],
}
`)
preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "util".*should support min_sdk_version\(30\)`)).
RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
srcs: ["a.java"],
static_libs: ["util"],
min_sdk_version: "30",
unsafe_ignore_missing_latest_api: true,
}
java_library {
name: "util",
srcs: ["a.java"],
min_sdk_version: "31",
}
`)
preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "another_util".*should support min_sdk_version\(30\)`)).
RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
srcs: ["a.java"],
static_libs: ["util"],
min_sdk_version: "30",
unsafe_ignore_missing_latest_api: true,
}
java_library {
name: "util",
srcs: ["a.java"],
static_libs: ["another_util"],
min_sdk_version: "30",
}
java_library {
name: "another_util",
srcs: ["a.java"],
min_sdk_version: "31",
}
`)
}