Merge "Fix prebuilt selection logic for cc_prebuilt_library_headers."
diff --git a/android/bazel.go b/android/bazel.go
index e97acff..72aad60 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -226,7 +226,8 @@
// Configure modules in these directories to enable bp2build_available: true or false by default.
bp2buildDefaultConfig = Bp2BuildConfig{
- "bionic": Bp2BuildDefaultTrueRecursively,
+ "bionic": Bp2BuildDefaultTrueRecursively,
+ "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
"build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively,
"build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
"development/sdk": Bp2BuildDefaultTrueRecursively,
diff --git a/android/config.go b/android/config.go
index 5ee28e7..ed63ddf 100644
--- a/android/config.go
+++ b/android/config.go
@@ -324,7 +324,7 @@
DeviceName: stringPtr("test_device"),
Platform_sdk_version: intPtr(30),
Platform_sdk_codename: stringPtr("S"),
- Platform_version_active_codenames: []string{"S"},
+ Platform_version_active_codenames: []string{"S", "Tiramisu"},
DeviceSystemSdkVersions: []string{"14", "15"},
Platform_systemsdk_versions: []string{"29", "30"},
AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
@@ -856,7 +856,7 @@
// Returns true if building apps that aren't bundled with the platform.
// UnbundledBuild() is always true when this is true.
func (c *config) UnbundledBuildApps() bool {
- return Bool(c.productVariables.Unbundled_build_apps)
+ return len(c.productVariables.Unbundled_build_apps) > 0
}
// Returns true if building image that aren't bundled with the platform.
diff --git a/android/hooks.go b/android/hooks.go
index 85fc081..9eaa1ac 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -65,10 +65,10 @@
return l.bp.ModuleFactories()
}
-func (l *loadHookContext) AppendProperties(props ...interface{}) {
+func (l *loadHookContext) appendPrependHelper(props []interface{},
+ extendFn func([]interface{}, interface{}, proptools.ExtendPropertyFilterFunc) error) {
for _, p := range props {
- err := proptools.AppendMatchingProperties(l.Module().base().customizableProperties,
- p, nil)
+ err := extendFn(l.Module().base().customizableProperties, p, nil)
if err != nil {
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
l.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
@@ -78,19 +78,12 @@
}
}
}
+func (l *loadHookContext) AppendProperties(props ...interface{}) {
+ l.appendPrependHelper(props, proptools.AppendMatchingProperties)
+}
func (l *loadHookContext) PrependProperties(props ...interface{}) {
- for _, p := range props {
- err := proptools.PrependMatchingProperties(l.Module().base().customizableProperties,
- p, nil)
- if err != nil {
- if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
- l.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
- } else {
- panic(err)
- }
- }
- }
+ l.appendPrependHelper(props, proptools.PrependMatchingProperties)
}
func (l *loadHookContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
diff --git a/android/module.go b/android/module.go
index e100330..4a388b5 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1148,7 +1148,7 @@
// }
// }
//
-// func NewMyModule() android.Module) {
+// func NewMyModule() android.Module {
// m := &myModule{}
// m.AddProperties(&m.properties)
// android.InitAndroidModule(m)
diff --git a/android/mutator.go b/android/mutator.go
index 4b37377..461cb17 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -529,10 +529,10 @@
mod.base().addBp2buildInfo(info)
}
-func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
+func (t *topDownMutatorContext) appendPrependHelper(props []interface{},
+ extendFn func([]interface{}, interface{}, proptools.ExtendPropertyFilterFunc) error) {
for _, p := range props {
- err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
- p, nil)
+ err := extendFn(t.Module().base().customizableProperties, p, nil)
if err != nil {
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
t.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
@@ -543,18 +543,12 @@
}
}
+func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
+ t.appendPrependHelper(props, proptools.AppendMatchingProperties)
+}
+
func (t *topDownMutatorContext) PrependProperties(props ...interface{}) {
- for _, p := range props {
- err := proptools.PrependMatchingProperties(t.Module().base().customizableProperties,
- p, nil)
- if err != nil {
- if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
- t.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
- } else {
- panic(err)
- }
- }
- }
+ t.appendPrependHelper(props, proptools.PrependMatchingProperties)
}
// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 3a93f47..09a5057 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -20,6 +20,7 @@
"reflect"
"sort"
"strings"
+ "sync"
"github.com/google/blueprint"
"github.com/google/blueprint/parser"
@@ -239,10 +240,18 @@
ValueVars map[string]bool
}
+var bp2buildSoongConfigVarsLock sync.Mutex
+
// SoongConfigVariablesForBp2build extracts information from a
// SoongConfigDefinition that bp2build needs to generate constraint settings and
// values for, in order to migrate soong_config_module_type usages to Bazel.
func (defs *Bp2BuildSoongConfigDefinitions) AddVars(mtDef SoongConfigDefinition) {
+ // In bp2build mode, this method is called concurrently in goroutines from
+ // loadhooks while parsing soong_config_module_type, so add a mutex to
+ // prevent concurrent map writes. See b/207572723
+ bp2buildSoongConfigVarsLock.Lock()
+ defer bp2buildSoongConfigVarsLock.Unlock()
+
if defs.StringVars == nil {
defs.StringVars = make(map[string]map[string]bool)
}
diff --git a/android/variable.go b/android/variable.go
index fe828d3..a29c6f8 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -15,13 +15,14 @@
package android
import (
- "android/soong/android/soongconfig"
- "android/soong/bazel"
"fmt"
"reflect"
"runtime"
"strings"
+ "android/soong/android/soongconfig"
+ "android/soong/bazel"
+
"github.com/google/blueprint/proptools"
)
@@ -245,30 +246,30 @@
AppsDefaultVersionName *string `json:",omitempty"`
- Allow_missing_dependencies *bool `json:",omitempty"`
- Unbundled_build *bool `json:",omitempty"`
- Unbundled_build_apps *bool `json:",omitempty"`
- Unbundled_build_image *bool `json:",omitempty"`
- Always_use_prebuilt_sdks *bool `json:",omitempty"`
- Skip_boot_jars_check *bool `json:",omitempty"`
- Malloc_not_svelte *bool `json:",omitempty"`
- Malloc_zero_contents *bool `json:",omitempty"`
- Malloc_pattern_fill_contents *bool `json:",omitempty"`
- Safestack *bool `json:",omitempty"`
- HostStaticBinaries *bool `json:",omitempty"`
- Binder32bit *bool `json:",omitempty"`
- UseGoma *bool `json:",omitempty"`
- UseRBE *bool `json:",omitempty"`
- UseRBEJAVAC *bool `json:",omitempty"`
- UseRBER8 *bool `json:",omitempty"`
- UseRBED8 *bool `json:",omitempty"`
- Debuggable *bool `json:",omitempty"`
- Eng *bool `json:",omitempty"`
- Treble_linker_namespaces *bool `json:",omitempty"`
- Enforce_vintf_manifest *bool `json:",omitempty"`
- Uml *bool `json:",omitempty"`
- Arc *bool `json:",omitempty"`
- MinimizeJavaDebugInfo *bool `json:",omitempty"`
+ Allow_missing_dependencies *bool `json:",omitempty"`
+ Unbundled_build *bool `json:",omitempty"`
+ Unbundled_build_apps []string `json:",omitempty"`
+ Unbundled_build_image *bool `json:",omitempty"`
+ Always_use_prebuilt_sdks *bool `json:",omitempty"`
+ Skip_boot_jars_check *bool `json:",omitempty"`
+ Malloc_not_svelte *bool `json:",omitempty"`
+ Malloc_zero_contents *bool `json:",omitempty"`
+ Malloc_pattern_fill_contents *bool `json:",omitempty"`
+ Safestack *bool `json:",omitempty"`
+ HostStaticBinaries *bool `json:",omitempty"`
+ Binder32bit *bool `json:",omitempty"`
+ UseGoma *bool `json:",omitempty"`
+ UseRBE *bool `json:",omitempty"`
+ UseRBEJAVAC *bool `json:",omitempty"`
+ UseRBER8 *bool `json:",omitempty"`
+ UseRBED8 *bool `json:",omitempty"`
+ Debuggable *bool `json:",omitempty"`
+ Eng *bool `json:",omitempty"`
+ Treble_linker_namespaces *bool `json:",omitempty"`
+ Enforce_vintf_manifest *bool `json:",omitempty"`
+ Uml *bool `json:",omitempty"`
+ Arc *bool `json:",omitempty"`
+ MinimizeJavaDebugInfo *bool `json:",omitempty"`
Check_elf_files *bool `json:",omitempty"`
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 59ea206..130581c 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -215,7 +215,9 @@
variables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
variables.Platform_sdk_codename = proptools.StringPtr("Q")
variables.Platform_sdk_final = proptools.BoolPtr(false)
- variables.Platform_version_active_codenames = []string{"Q"}
+ // "Tiramisu" needs to be in the next line for compatibility with soong code,
+ // not because of these tests specifically (it's not used by the tests)
+ variables.Platform_version_active_codenames = []string{"Q", "Tiramisu"}
variables.Platform_vndk_version = proptools.StringPtr("29")
}),
)
@@ -6204,7 +6206,7 @@
})
// Permission XML should point to the activated path of impl jar of java_sdk_library
sdkLibrary := ctx.ModuleForTests("foo.xml", "android_common_myapex").Rule("java_sdk_xml")
- ensureContains(t, sdkLibrary.RuleParams.Command, `<library name=\"foo\" file=\"/apex/myapex/javalib/foo.jar\"`)
+ ensureMatches(t, sdkLibrary.RuleParams.Command, `<library\\n\s+name=\\\"foo\\\"\\n\s+file=\\\"/apex/myapex/javalib/foo.jar\\\"`)
}
func TestJavaSDKLibrary_WithinApex(t *testing.T) {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 5b070c6..84bdcdd 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -257,8 +257,8 @@
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_PATH", p.installDir.ToMakePath().String())
- entries.SetString("LOCAL_SOONG_INSTALLED_MODULE :=", filepath.Join(p.installDir.String(), fi.stem()))
- entries.SetString("LOCAL_SOONG_INSTALL_PAIRS :=",
+ entries.SetString("LOCAL_SOONG_INSTALLED_MODULE", filepath.Join(p.installDir.String(), fi.stem()))
+ entries.SetString("LOCAL_SOONG_INSTALL_PAIRS",
fi.builtFile.String()+":"+filepath.Join(p.installDir.String(), fi.stem()))
// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 284a19a..a722946 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -625,7 +625,6 @@
Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatImageXmx)
if profile != nil {
- cmd.FlagWithArg("--compiler-filter=", "speed-profile")
cmd.FlagWithInput("--profile-file=", profile)
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index d7f14d6..3065d57 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -21,6 +21,7 @@
"reflect"
"regexp"
"sort"
+ "strconv"
"strings"
"sync"
@@ -32,25 +33,7 @@
)
const (
- sdkXmlFileSuffix = ".xml"
- permissionsTemplate = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n` +
- `<!-- Copyright (C) 2018 The Android Open Source Project\n` +
- `\n` +
- ` Licensed under the Apache License, Version 2.0 (the \"License\");\n` +
- ` you may not use this file except in compliance with the License.\n` +
- ` You may obtain a copy of the License at\n` +
- `\n` +
- ` http://www.apache.org/licenses/LICENSE-2.0\n` +
- `\n` +
- ` Unless required by applicable law or agreed to in writing, software\n` +
- ` distributed under the License is distributed on an \"AS IS\" BASIS,\n` +
- ` WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n` +
- ` See the License for the specific language governing permissions and\n` +
- ` limitations under the License.\n` +
- `-->\n` +
- `<permissions>\n` +
- ` <library name=\"%s\" file=\"%s\"/>\n` +
- `</permissions>\n`
+ sdkXmlFileSuffix = ".xml"
)
// A tag to associated a dependency with a specific api scope.
@@ -637,6 +620,33 @@
// Files containing information about supported java doc tags.
Doctag_files []string `android:"path"`
+
+ // Signals that this shared library is part of the bootclasspath starting
+ // on the version indicated in this attribute.
+ //
+ // This will make platforms at this level and above to ignore
+ // <uses-library> tags with this library name because the library is already
+ // available
+ On_bootclasspath_since *string
+
+ // Signals that this shared library was part of the bootclasspath before
+ // (but not including) the version indicated in this attribute.
+ //
+ // The system will automatically add a <uses-library> tag with this library to
+ // apps that target any SDK less than the version indicated in this attribute.
+ On_bootclasspath_before *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is below the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Min_device_sdk *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is above the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Max_device_sdk *string
}
// commonSdkLibraryAndImportModule defines the interface that must be provided by a module that
@@ -1580,14 +1590,29 @@
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
+ moduleMinApiLevel := module.Library.MinSdkVersion(mctx).ApiLevel
+ var moduleMinApiLevelStr = moduleMinApiLevel.String()
+ if moduleMinApiLevel == android.NoneApiLevel {
+ moduleMinApiLevelStr = "current"
+ }
props := struct {
- Name *string
- Lib_name *string
- Apex_available []string
+ Name *string
+ Lib_name *string
+ Apex_available []string
+ On_bootclasspath_since *string
+ On_bootclasspath_before *string
+ Min_device_sdk *string
+ Max_device_sdk *string
+ Sdk_library_min_api_level *string
}{
- Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
- Lib_name: proptools.StringPtr(module.BaseModuleName()),
- Apex_available: module.ApexProperties.Apex_available,
+ Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
+ Lib_name: proptools.StringPtr(module.BaseModuleName()),
+ Apex_available: module.ApexProperties.Apex_available,
+ On_bootclasspath_since: module.commonSdkLibraryProperties.On_bootclasspath_since,
+ On_bootclasspath_before: module.commonSdkLibraryProperties.On_bootclasspath_before,
+ Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
+ Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
+ Sdk_library_min_api_level: &moduleMinApiLevelStr,
}
mctx.CreateModule(sdkLibraryXmlFactory, &props)
@@ -2383,6 +2408,38 @@
type sdkLibraryXmlProperties struct {
// canonical name of the lib
Lib_name *string
+
+ // Signals that this shared library is part of the bootclasspath starting
+ // on the version indicated in this attribute.
+ //
+ // This will make platforms at this level and above to ignore
+ // <uses-library> tags with this library name because the library is already
+ // available
+ On_bootclasspath_since *string
+
+ // Signals that this shared library was part of the bootclasspath before
+ // (but not including) the version indicated in this attribute.
+ //
+ // The system will automatically add a <uses-library> tag with this library to
+ // apps that target any SDK less than the version indicated in this attribute.
+ On_bootclasspath_before *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is below the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Min_device_sdk *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is above the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Max_device_sdk *string
+
+ // The SdkLibrary's min api level as a string
+ //
+ // This value comes from the ApiLevel of the MinSdkVersion property.
+ Sdk_library_min_api_level *string
}
// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
@@ -2459,11 +2516,81 @@
return "/" + partition + "/framework/" + implName + ".jar"
}
+func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string {
+ if value == nil {
+ return ""
+ }
+ apiLevel, err := android.ApiLevelFromUser(ctx, *value)
+ if err != nil {
+ // attributes in bp files have underscores but in the xml have dashes.
+ ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
+ return ""
+ }
+ intStr := strconv.Itoa(apiLevel.FinalOrPreviewInt())
+ return formattedOptionalAttribute(attrName, &intStr)
+}
+
+// formats an attribute for the xml permissions file if the value is not null
+// returns empty string otherwise
+func formattedOptionalAttribute(attrName string, value *string) string {
+ if value == nil {
+ return ""
+ }
+ return fmt.Sprintf(` %s=\"%s\"\n`, attrName, *value)
+}
+
+func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
+ libName := proptools.String(module.properties.Lib_name)
+ libNameAttr := formattedOptionalAttribute("name", &libName)
+ filePath := module.implPath(ctx)
+ filePathAttr := formattedOptionalAttribute("file", &filePath)
+ implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since)
+ implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
+ minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
+ maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
+ // <library> is understood in all android versions whereas <updatable-library> is only understood from API T (and ignored before that).
+ // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the updatable-library to make sure this library is not loaded before T
+ var libraryTag string
+ if module.properties.Min_device_sdk != nil {
+ libraryTag = ` <updatable-library\n`
+ } else {
+ libraryTag = ` <library\n`
+ }
+
+ return strings.Join([]string{
+ `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n`,
+ `<!-- Copyright (C) 2018 The Android Open Source Project\n`,
+ `\n`,
+ ` Licensed under the Apache License, Version 2.0 (the \"License\");\n`,
+ ` you may not use this file except in compliance with the License.\n`,
+ ` You may obtain a copy of the License at\n`,
+ `\n`,
+ ` http://www.apache.org/licenses/LICENSE-2.0\n`,
+ `\n`,
+ ` Unless required by applicable law or agreed to in writing, software\n`,
+ ` distributed under the License is distributed on an \"AS IS\" BASIS,\n`,
+ ` WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n`,
+ ` See the License for the specific language governing permissions and\n`,
+ ` limitations under the License.\n`,
+ `-->\n`,
+ `<permissions>\n`,
+ libraryTag,
+ libNameAttr,
+ filePathAttr,
+ implicitFromAttr,
+ implicitUntilAttr,
+ minSdkAttr,
+ maxSdkAttr,
+ ` />\n`,
+ `</permissions>\n`}, "")
+}
+
func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
module.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
libName := proptools.String(module.properties.Lib_name)
- xmlContent := fmt.Sprintf(permissionsTemplate, libName, module.implPath(ctx))
+ module.selfValidate(ctx)
+ xmlContent := module.permissionsContents(ctx)
module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
rule := android.NewRuleBuilder(pctx, ctx)
@@ -2496,6 +2623,81 @@
}}
}
+func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) {
+ module.validateAtLeastTAttributes(ctx)
+ module.validateMinAndMaxDeviceSdk(ctx)
+ module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx)
+ module.validateOnBootclasspathBeforeRequirements(ctx)
+}
+
+func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) {
+ t := android.ApiLevelOrPanic(ctx, "Tiramisu")
+ module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk")
+ module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk")
+ module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before")
+ module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since")
+}
+
+func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) {
+ if attr != nil {
+ if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil {
+ // we will inform the user of invalid inputs when we try to write the
+ // permissions xml file so we don't need to do it here
+ if t.GreaterThan(level) {
+ ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T")
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) {
+ if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil {
+ min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
+ max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
+ if minErr == nil && maxErr == nil {
+ // we will inform the user of invalid inputs when we try to write the
+ // permissions xml file so we don't need to do it here
+ if min.GreaterThan(max) {
+ ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk")
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) {
+ moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
+ if module.properties.Min_device_sdk != nil {
+ api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
+ if err == nil {
+ if moduleMinApi.GreaterThan(api) {
+ ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
+ }
+ }
+ }
+ if module.properties.Max_device_sdk != nil {
+ api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
+ if err == nil {
+ if moduleMinApi.GreaterThan(api) {
+ ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) {
+ moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
+ if module.properties.On_bootclasspath_before != nil {
+ t := android.ApiLevelOrPanic(ctx, "Tiramisu")
+ // if we use the attribute, then we need to do this validation
+ if moduleMinApi.LessThan(t) {
+ // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+)
+ if module.properties.Min_device_sdk == nil {
+ ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T")
+ }
+ }
+ }
+}
+
type sdkLibrarySdkMemberType struct {
android.SdkMemberTypeBase
}
@@ -2547,6 +2749,33 @@
Doctag_paths android.Paths
Permitted_packages []string
+
+ // Signals that this shared library is part of the bootclasspath starting
+ // on the version indicated in this attribute.
+ //
+ // This will make platforms at this level and above to ignore
+ // <uses-library> tags with this library name because the library is already
+ // available
+ On_bootclasspath_since *string
+
+ // Signals that this shared library was part of the bootclasspath before
+ // (but not including) the version indicated in this attribute.
+ //
+ // The system will automatically add a <uses-library> tag with this library to
+ // apps that target any SDK less than the version indicated in this attribute.
+ On_bootclasspath_before *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is below the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Min_device_sdk *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is above the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Max_device_sdk *string
}
type scopeProperties struct {
@@ -2593,6 +2822,10 @@
s.Compile_dex = sdk.dexProperties.Compile_dex
s.Doctag_paths = sdk.doctagPaths
s.Permitted_packages = sdk.PermittedPackagesForUpdatableBootJars()
+ s.On_bootclasspath_since = sdk.commonSdkLibraryProperties.On_bootclasspath_since
+ s.On_bootclasspath_before = sdk.commonSdkLibraryProperties.On_bootclasspath_before
+ s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk
+ s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk
}
func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index be23536..2271573 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -15,12 +15,13 @@
package java
import (
- "android/soong/android"
"fmt"
"path/filepath"
"regexp"
"testing"
+ "android/soong/android"
+
"github.com/google/blueprint/proptools"
)
@@ -107,7 +108,7 @@
libs: ["foo"],
sdk_version: "module_30",
}
- `)
+ `)
// check the existence of the internal modules
foo := result.ModuleForTests("foo", "android_common")
@@ -162,6 +163,185 @@
}
}
+func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ "29": {"foo"},
+ "30": {"foo", "fooUpdatable", "fooUpdatableErr"},
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"Tiramisu", "U", "V", "W"}
+ }),
+ ).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "fooUpdatable",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ on_bootclasspath_since: "U",
+ on_bootclasspath_before: "V",
+ min_device_sdk: "W",
+ max_device_sdk: "current",
+ min_sdk_version: "S",
+ }
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ }
+`)
+ // test that updatability attributes are passed on correctly
+ fooUpdatable := result.ModuleForTests("fooUpdatable.xml", "android_common").Rule("java_sdk_xml")
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-since=\"9001\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-before=\"9002\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `min-device-sdk=\"9003\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `max-device-sdk=\"10000\"`)
+
+ // double check that updatability attributes are not written if they don't exist in the bp file
+ // the permissions file for the foo library defined above
+ fooPermissions := result.ModuleForTests("foo.xml", "android_common").Rule("java_sdk_xml")
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `on-bootclasspath-since`)
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `on-bootclasspath-before`)
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `min-device-sdk`)
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `max-device-sdk`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_Validation_ValidVersion(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "30": {"fooUpdatable", "fooUpdatableErr"},
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ `on_bootclasspath_since: "aaa" could not be parsed as an integer and is not a recognized codename`,
+ `on_bootclasspath_before: "bbc" could not be parsed as an integer and is not a recognized codename`,
+ `min_device_sdk: "ccc" could not be parsed as an integer and is not a recognized codename`,
+ `max_device_sdk: "ddd" could not be parsed as an integer and is not a recognized codename`,
+ })).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "fooUpdatableErr",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ on_bootclasspath_since: "aaa",
+ on_bootclasspath_before: "bbc",
+ min_device_sdk: "ccc",
+ max_device_sdk: "ddd",
+ }
+`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_Validation_AtLeastTAttributes(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ "on_bootclasspath_since: Attribute value needs to be at least T",
+ "on_bootclasspath_before: Attribute value needs to be at least T",
+ "min_device_sdk: Attribute value needs to be at least T",
+ "max_device_sdk: Attribute value needs to be at least T",
+ },
+ )).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ on_bootclasspath_since: "S",
+ on_bootclasspath_before: "S",
+ min_device_sdk: "S",
+ max_device_sdk: "S",
+ min_sdk_version: "S",
+ }
+`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdk(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"Tiramisu", "U", "V"}
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ "min_device_sdk can't be greater than max_device_sdk",
+ },
+ )).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ min_device_sdk: "V",
+ max_device_sdk: "U",
+ min_sdk_version: "S",
+ }
+`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdkAndModuleMinSdk(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"Tiramisu", "U", "V"}
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ regexp.QuoteMeta("min_device_sdk: Can't be less than module's min sdk (V)"),
+ regexp.QuoteMeta("max_device_sdk: Can't be less than module's min sdk (V)"),
+ },
+ )).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ min_device_sdk: "U",
+ max_device_sdk: "U",
+ min_sdk_version: "V",
+ }
+`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_usesNewTag(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "30": {"foo"},
+ }),
+ ).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ min_device_sdk: "Tiramisu",
+ min_sdk_version: "S",
+ }
+`)
+ // test that updatability attributes are passed on correctly
+ fooUpdatable := result.ModuleForTests("foo.xml", "android_common").Rule("java_sdk_xml")
+ android.AssertStringDoesContain(t, "foo.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `<updatable-library`)
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `<library`)
+}
+
func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index a376e06..b19949a 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -7,4 +7,4 @@
"$TOP/build/soong/tests/mixed_mode_test.sh"
"$TOP/build/soong/tests/bp2build_bazel_test.sh"
"$TOP/build/soong/tests/soong_test.sh"
-"$TOP/build/bazel/ci/rbc_product_config.sh" aosp_arm64-userdebug
+"$TOP/build/bazel/ci/rbc_regression_test.sh" aosp_arm64-userdebug