diff options
| author | 2021-09-28 15:40:23 +0000 | |
|---|---|---|
| committer | 2021-11-24 17:09:19 +0000 | |
| commit | c362142438b5b883f62d57f980fdee2f02a26b7c (patch) | |
| tree | 6e9597e73c2cb2d453f0d43dbfd584d459b12996 | |
| parent | 9956e5e281973c810ac182646f18649a35182bb5 (diff) | |
Perform validation of shared library attributes
Perform consistency checks as per http://go/updatable-shared-libraries
These include:
* no attribute can specified can be less than T
* max-device-sdk can't be less than min-device-sdk
* min and max-device-sdk need to be at least the module's
min_sdk_version
* using on-bootclasspath-before implies that the module's
min_sdk_version is at least T or the library has min-device-sdk of at
least T
Test: m nothing
Bug: 191978330
Change-Id: Iaca5cf23fb0bc7e65effb3529c8e829560894c2e
Merged-In: Iaca5cf23fb0bc7e65effb3529c8e829560894c2e
(cherry picked from commit f9e584dd20068334f7ab44c8a989fc1b177e3886)
| -rw-r--r-- | android/config.go | 2 | ||||
| -rw-r--r-- | apex/apex_test.go | 4 | ||||
| -rw-r--r-- | java/sdk_library.go | 126 | ||||
| -rw-r--r-- | java/sdk_library_test.go | 137 |
4 files changed, 239 insertions, 30 deletions
diff --git a/android/config.go b/android/config.go index 5ee28e735..6f7499499 100644 --- a/android/config.go +++ b/android/config.go @@ -324,7 +324,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string 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"}, diff --git a/apex/apex_test.go b/apex/apex_test.go index 7f4a5cb87..130581ca4 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -215,7 +215,9 @@ var prepareForApexTest = android.GroupFixturePreparers( 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") }), ) diff --git a/java/sdk_library.go b/java/sdk_library.go index 32f9e4712..522452219 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1590,22 +1590,29 @@ func (module *SdkLibrary) UniqueApexVariations() bool { // 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 - On_bootclasspath_since *string - On_bootclasspath_before *string - Min_device_sdk *string - Max_device_sdk *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, - 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, + 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) @@ -2428,6 +2435,11 @@ type sdkLibraryXmlProperties struct { // // 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. @@ -2535,6 +2547,14 @@ func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) stri 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`, @@ -2553,7 +2573,7 @@ func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) stri ` limitations under the License.\n`, `-->\n`, `<permissions>\n`, - ` <library\n`, + libraryTag, libNameAttr, filePathAttr, implicitFromAttr, @@ -2568,6 +2588,7 @@ func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleConte module.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() libName := proptools.String(module.properties.Lib_name) + module.selfValidate(ctx) xmlContent := module.permissionsContents(ctx) module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath @@ -2601,6 +2622,81 @@ func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries { }} } +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 } diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index e22118b0b..9506c8aee 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" ) @@ -171,16 +172,20 @@ func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { "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: "29", - on_bootclasspath_before: "30", - min_device_sdk: "R", - max_device_sdk: "current", + 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", @@ -190,9 +195,9 @@ func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { `) // 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=\"29\"`) - android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on_bootclasspath_before=\"30\"`) - android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `min_device_sdk=\"30\"`) + 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 @@ -204,7 +209,7 @@ func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `max_device_sdk`) } -func TestJavaSdkLibrary_UpdatableLibrary_Validation(t *testing.T) { +func TestJavaSdkLibrary_UpdatableLibrary_Validation_ValidVersion(t *testing.T) { android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -223,14 +228,120 @@ func TestJavaSdkLibrary_UpdatableLibrary_Validation(t *testing.T) { 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", + 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, |