From 826863c8e0844b2172fde38ccdcc0d83aa2ae7e5 Mon Sep 17 00:00:00 2001 From: Pedro Loureiro Date: Tue, 7 Sep 2021 17:21:59 +0000 Subject: [PATCH] Add support for new permissions library tag attributes We are expanding PackageManager's supported attributes and this change enables the developer to define them in the .bp file. Test: m nothing Bug: 191978330 Change-Id: I01d579190fb585662086a7fc456f3b33cb89fb57 --- apex/apex_test.go | 2 +- java/sdk_library.go | 188 +++++++++++++++++++++++++++++++++------ java/sdk_library_test.go | 71 ++++++++++++++- 3 files changed, 233 insertions(+), 28 deletions(-) diff --git a/apex/apex_test.go b/apex/apex_test.go index 9d6753ef9..8cd05841a 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -6180,7 +6180,7 @@ func TestJavaSDKLibrary(t *testing.T) { }) // 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, `\n` + - `\n` + - `\n` + - ` \n` + - `\n` + sdkXmlFileSuffix = ".xml" ) // A tag to associated a dependency with a specific api scope. @@ -629,6 +612,33 @@ type commonToSdkLibraryAndImportProperties struct { // 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 + // 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 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 @@ -1567,13 +1577,21 @@ func (module *SdkLibrary) UniqueApexVariations() bool { // Creates the xml file that publicizes the runtime library func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) { 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 }{ - 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, } mctx.CreateModule(sdkLibraryXmlFactory, &props) @@ -2354,6 +2372,33 @@ type sdkLibraryXml struct { 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 + // 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 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 } // java_sdk_library_xml builds the permission xml file for a java_sdk_library. @@ -2430,11 +2475,71 @@ func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string { 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 { + ctx.PropertyErrorf(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) + + return strings.Join([]string{ + `\n`, + `\n`, + `\n`, + ` \n`, + `\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)) + xmlContent := module.permissionsContents(ctx) module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath rule := android.NewRuleBuilder(pctx, ctx) @@ -2518,6 +2623,33 @@ type sdkLibrarySdkMemberProperties struct { 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 + // 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 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 { @@ -2559,6 +2691,10 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe 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 938bb2895..bcd837c04 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -107,7 +107,7 @@ func TestJavaSdkLibrary(t *testing.T) { libs: ["foo"], sdk_version: "module_30", } - `) + `) // check the existence of the internal modules foo := result.ModuleForTests("foo", "android_common") @@ -162,6 +162,75 @@ func TestJavaSdkLibrary(t *testing.T) { } } +func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithPrebuiltApis(map[string][]string{ + "28": {"foo"}, + "29": {"foo"}, + "30": {"foo", "fooUpdatable", "fooUpdatableErr"}, + }), + ).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", + } + 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=\"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, `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(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_StubOrImplOnlyLibs(t *testing.T) { result := android.GroupFixturePreparers( prepareForJavaTest,