Loading android/sdk.go +2 −0 Original line number Diff line number Diff line Loading @@ -375,6 +375,8 @@ type SdkMemberTypeDependencyTag interface { // SdkMemberType returns the SdkMemberType that will be used to automatically add the child module // to the sdk. // // Returning nil will prevent the module being added to the sdk. SdkMemberType(child Module) SdkMemberType // ExportMember determines whether a module added to the sdk through this tag will be exported Loading apex/bootclasspath_fragment_test.go +327 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import ( "android/soong/android" "android/soong/java" "github.com/google/blueprint/proptools" ) // Contains tests for bootclasspath_fragment logic from java/bootclasspath_fragment.go as the ART Loading Loading @@ -868,4 +869,330 @@ func TestBootclasspathFragment_HiddenAPIList(t *testing.T) { android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+quuzTestStubs+":"+fooStubs) } // TestBootclasspathFragment_AndroidNonUpdatable checks to make sure that setting // additional_stubs: ["android-non-updatable"] causes the source android-non-updatable modules to be // added to the hiddenapi list tool. func TestBootclasspathFragment_AndroidNonUpdatable(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, prepareForTestWithArtApex, prepareForTestWithMyapex, // Configure bootclasspath jars to ensure that hidden API encoding is performed on them. java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"), // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding // is disabled. android.FixtureAddTextFile("frameworks/base/Android.bp", ""), java.PrepareForTestWithJavaSdkLibraryFiles, java.FixtureWithLastReleaseApis("foo", "android-non-updatable"), ).RunTestWithBp(t, ` java_sdk_library { name: "android-non-updatable", srcs: ["b.java"], compile_dex: true, public: { enabled: true, }, system: { enabled: true, }, test: { enabled: true, }, module_lib: { enabled: true, }, } apex { name: "com.android.art", key: "com.android.art.key", bootclasspath_fragments: ["art-bootclasspath-fragment"], java_libs: [ "baz", "quuz", ], updatable: false, } apex_key { name: "com.android.art.key", public_key: "com.android.art.avbpubkey", private_key: "com.android.art.pem", } java_library { name: "baz", apex_available: [ "com.android.art", ], srcs: ["b.java"], compile_dex: true, } java_library { name: "quuz", apex_available: [ "com.android.art", ], srcs: ["b.java"], compile_dex: true, } bootclasspath_fragment { name: "art-bootclasspath-fragment", image_name: "art", // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. contents: ["baz", "quuz"], apex_available: [ "com.android.art", ], } apex { name: "myapex", key: "myapex.key", bootclasspath_fragments: [ "mybootclasspathfragment", ], updatable: false, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_sdk_library { name: "foo", srcs: ["b.java"], shared_library: false, public: {enabled: true}, apex_available: [ "myapex", ], } java_library { name: "bar", srcs: ["b.java"], installable: true, apex_available: [ "myapex", ], } bootclasspath_fragment { name: "mybootclasspathfragment", contents: [ "foo", "bar", ], apex_available: [ "myapex", ], additional_stubs: ["android-non-updatable"], fragments: [ { apex: "com.android.art", module: "art-bootclasspath-fragment", }, ], } `) java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{ "android-non-updatable.stubs", "android-non-updatable.stubs.module_lib", "android-non-updatable.stubs.system", "android-non-updatable.stubs.test", "art-bootclasspath-fragment", "bar", "dex2oatd", "foo", }) nonUpdatablePublicStubs := getDexJarPath(result, "android-non-updatable.stubs") nonUpdatableSystemStubs := getDexJarPath(result, "android-non-updatable.stubs.system") nonUpdatableTestStubs := getDexJarPath(result, "android-non-updatable.stubs.test") nonUpdatableModuleLibStubs := getDexJarPath(result, "android-non-updatable.stubs.module_lib") // Make sure that the fragment uses the android-non-updatable modules when generating the hidden // API flags. fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000") rule := fragment.Rule("modularHiddenAPIStubFlagsFile") command := rule.RuleParams.Command android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list") // Make sure that the module_lib non-updatable stubs are available for resolving references from // the implementation boot dex jars provided by this module. android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs) // Make sure that the appropriate non-updatable stubs are available for resolving references from // the different API stubs provided by this module. android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs) android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs) android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs) } // TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks checks to make sure that // setting additional_stubs: ["android-non-updatable"] causes the prebuilt android-non-updatable // modules to be added to the hiddenapi list tool. func TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, java.PrepareForTestWithJavaDefaultModules, prepareForTestWithArtApex, prepareForTestWithMyapex, // Configure bootclasspath jars to ensure that hidden API encoding is performed on them. java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"), // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding // is disabled. android.FixtureAddTextFile("frameworks/base/Android.bp", ""), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true) }), java.PrepareForTestWithJavaSdkLibraryFiles, java.FixtureWithPrebuiltApis(map[string][]string{ "current": {"android-non-updatable"}, "30": {"foo"}, }), ).RunTestWithBp(t, ` apex { name: "com.android.art", key: "com.android.art.key", bootclasspath_fragments: ["art-bootclasspath-fragment"], java_libs: [ "baz", "quuz", ], updatable: false, } apex_key { name: "com.android.art.key", public_key: "com.android.art.avbpubkey", private_key: "com.android.art.pem", } java_library { name: "baz", apex_available: [ "com.android.art", ], srcs: ["b.java"], compile_dex: true, } java_library { name: "quuz", apex_available: [ "com.android.art", ], srcs: ["b.java"], compile_dex: true, } bootclasspath_fragment { name: "art-bootclasspath-fragment", image_name: "art", // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. contents: ["baz", "quuz"], apex_available: [ "com.android.art", ], } apex { name: "myapex", key: "myapex.key", bootclasspath_fragments: [ "mybootclasspathfragment", ], updatable: false, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_sdk_library { name: "foo", srcs: ["b.java"], shared_library: false, public: {enabled: true}, apex_available: [ "myapex", ], } java_library { name: "bar", srcs: ["b.java"], installable: true, apex_available: [ "myapex", ], } bootclasspath_fragment { name: "mybootclasspathfragment", contents: [ "foo", "bar", ], apex_available: [ "myapex", ], additional_stubs: ["android-non-updatable"], fragments: [ { apex: "com.android.art", module: "art-bootclasspath-fragment", }, ], } `) java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{ "art-bootclasspath-fragment", "bar", "dex2oatd", "foo", "prebuilt_sdk_module-lib_current_android-non-updatable", "prebuilt_sdk_public_current_android-non-updatable", "prebuilt_sdk_system_current_android-non-updatable", "prebuilt_sdk_test_current_android-non-updatable", }) nonUpdatablePublicStubs := getDexJarPath(result, "sdk_public_current_android-non-updatable") nonUpdatableSystemStubs := getDexJarPath(result, "sdk_system_current_android-non-updatable") nonUpdatableTestStubs := getDexJarPath(result, "sdk_test_current_android-non-updatable") nonUpdatableModuleLibStubs := getDexJarPath(result, "sdk_module-lib_current_android-non-updatable") // Make sure that the fragment uses the android-non-updatable modules when generating the hidden // API flags. fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000") rule := fragment.Rule("modularHiddenAPIStubFlagsFile") command := rule.RuleParams.Command android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list") // Make sure that the module_lib non-updatable stubs are available for resolving references from // the implementation boot dex jars provided by this module. android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs) // Make sure that the appropriate non-updatable stubs are available for resolving references from // the different API stubs provided by this module. android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs) android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs) android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs) } // TODO(b/177892522) - add test for host apex. java/bootclasspath_fragment.go +20 −2 Original line number Diff line number Diff line Loading @@ -124,6 +124,15 @@ type bootclasspathFragmentProperties struct { // Hidden API related properties. Hidden_api HiddenAPIFlagFileProperties // The list of additional stub libraries which this fragment's contents use but which are not // provided by another bootclasspath_fragment. // // Note, "android-non-updatable" is treated specially. While no such module exists it is treated // as if it was a java_sdk_library. So, when public API stubs are needed then it will be replaced // with "android-non-updatable.stubs", with "androidn-non-updatable.system.stubs" when the system // stubs are needed and so on. Additional_stubs []string // Properties that allow a fragment to depend on other fragments. This is needed for hidden API // processing as it needs access to all the classes used by a fragment including those provided // by other fragments. Loading Loading @@ -381,6 +390,15 @@ func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorCon // bootclasspath fragment. hiddenAPIAddStubLibDependencies(ctx, b.properties.apiScopeToStubLibs()) for _, additionalStubModule := range b.properties.Additional_stubs { for _, apiScope := range hiddenAPISdkLibrarySupportedScopes { // Add a dependency onto a possibly scope specific stub library. scopeSpecificDependency := apiScope.scopeSpecificStubModule(ctx, additionalStubModule) tag := hiddenAPIStubsDependencyTag{apiScope: apiScope, fromAdditionalDependency: true} ctx.AddVariationDependencies(nil, tag, scopeSpecificDependency) } } if SkipDexpreoptBootJars(ctx) { return } Loading Loading @@ -640,8 +658,8 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul // Populate with flag file paths from the properties. input.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api) // Store the stub dex jars from this module's fragment dependencies. input.DependencyStubDexJarsByScope = dependencyHiddenApiInfo.TransitiveStubDexJarsByScope // Add the stub dex jars from this module's fragment dependencies. input.DependencyStubDexJarsByScope.append(dependencyHiddenApiInfo.TransitiveStubDexJarsByScope) return input } Loading java/hiddenapi_modular.go +97 −10 Original line number Diff line number Diff line Loading @@ -37,13 +37,65 @@ type HiddenAPIScope struct { // The option needed to passed to "hiddenapi list". hiddenAPIListOption string // The name sof the source stub library modules that contain the API provided by the platform, // i.e. by modules that are not in an APEX. nonUpdatableSourceModule string // The names of the prebuilt stub library modules that contain the API provided by the platform, // i.e. by modules that are not in an APEX. nonUpdatablePrebuiltModule string } // initHiddenAPIScope initializes the scope. func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope { sdkKind := apiScope.sdkKind // The platform does not provide a core platform API. if sdkKind != android.SdkCorePlatform { kindAsString := sdkKind.String() var insert string if sdkKind == android.SdkPublic { insert = "" } else { insert = "." + strings.ReplaceAll(kindAsString, "-", "_") } nonUpdatableModule := "android-non-updatable" // Construct the name of the android-non-updatable source module for this scope. apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert) prebuiltModuleName := func(name string, kind string) string { return fmt.Sprintf("sdk_%s_current_%s", kind, name) } // Construct the name of the android-non-updatable prebuilt module for this scope. apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString) } return apiScope } // android-non-updatable takes the name of a module and returns a possibly scope specific name of // the module. func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string { // The android-non-updatable is not a java_sdk_library but there are separate stub libraries for // each scope. // TODO(b/192067200): Remove special handling of android-non-updatable. if name == "android-non-updatable" { if ctx.Config().AlwaysUsePrebuiltSdks() { return l.nonUpdatablePrebuiltModule } else { return l.nonUpdatableSourceModule } } else { // Assume that the module is either a java_sdk_library (or equivalent) and so will provide // separate stub jars for each scope or is a java_library (or equivalent) in which case it will // have the same stub jar for each scope. return name } } func (l *HiddenAPIScope) String() string { return fmt.Sprintf("HiddenAPIScope{%s}", l.name) } Loading Loading @@ -122,6 +174,11 @@ type hiddenAPIStubsDependencyTag struct { // The api scope for which this dependency was added. apiScope *HiddenAPIScope // Indicates that the dependency is not for an API provided by the current bootclasspath fragment // but is an additional API provided by a module that is not part of the current bootclasspath // fragment. fromAdditionalDependency bool } func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() { Loading @@ -132,6 +189,11 @@ func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool { } func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType { // Do not add additional dependencies to the sdk. if b.fromAdditionalDependency { return nil } // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs // property, otherwise treat if it was specified in the java_header_libs property. if javaSdkLibrarySdkMemberType.IsInstance(child) { Loading Loading @@ -243,15 +305,10 @@ func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, tempPath := tempPathForRestat(ctx, outputPath) // Find the widest API stubs provided by the fragments on which this depends, if any. var dependencyStubDexJars android.Paths for i := len(hiddenAPIScopes) - 1; i >= 0; i-- { apiScope := hiddenAPIScopes[i] stubsForAPIScope := input.DependencyStubDexJarsByScope[apiScope] if len(stubsForAPIScope) != 0 { dependencyStubDexJars = stubsForAPIScope break } } dependencyStubDexJars := input.DependencyStubDexJarsByScope.stubDexJarsForWidestAPIScope() // Add widest API stubs from the additional dependencies of this, if any. dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.stubDexJarsForWidestAPIScope()...) command := rule.Command(). Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")). Loading @@ -266,6 +323,7 @@ func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, // other fragment's APIs. var paths android.Paths paths = append(paths, input.DependencyStubDexJarsByScope[apiScope]...) paths = append(paths, input.AdditionalStubDexJarsByScope[apiScope]...) paths = append(paths, input.StubDexJarsByScope[apiScope]...) if len(paths) > 0 { option := apiScope.hiddenAPIListOption Loading Loading @@ -514,6 +572,20 @@ func (s StubDexJarsByScope) dedupAndSort() { } } // stubDexJarsForWidestAPIScope returns the stub dex jars for the widest API scope provided by this // map. The relative width of APIs is determined by their order in hiddenAPIScopes. func (s StubDexJarsByScope) stubDexJarsForWidestAPIScope() android.Paths { for i := len(hiddenAPIScopes) - 1; i >= 0; i-- { apiScope := hiddenAPIScopes[i] stubsForAPIScope := s[apiScope] if len(stubsForAPIScope) != 0 { return stubsForAPIScope } } return nil } // HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are // needed for hidden API flag generation. type HiddenAPIFlagInput struct { Loading @@ -530,6 +602,13 @@ type HiddenAPIFlagInput struct { // fragment on which this depends. DependencyStubDexJarsByScope StubDexJarsByScope // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to // the ones that are obtained from fragments on which this depends. // // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope // as there are not propagated transitively to other fragments that depend on this. AdditionalStubDexJarsByScope StubDexJarsByScope // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are // specified in the bootclasspath_fragment's stub_libs and contents properties. RemovedTxtFiles android.Paths Loading @@ -541,6 +620,7 @@ func newHiddenAPIFlagInput() HiddenAPIFlagInput { FlagFilesByCategory: FlagFilesByCategory{}, StubDexJarsByScope: StubDexJarsByScope{}, DependencyStubDexJarsByScope: StubDexJarsByScope{}, AdditionalStubDexJarsByScope: StubDexJarsByScope{}, } return input Loading Loading @@ -614,8 +694,15 @@ func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, conten tag := ctx.OtherModuleDependencyTag(module) if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok { apiScope := hiddenAPIStubsTag.apiScope if hiddenAPIStubsTag.fromAdditionalDependency { dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind) if dexJar != nil { i.AdditionalStubDexJarsByScope[apiScope] = append(i.AdditionalStubDexJarsByScope[apiScope], dexJar) } } else { addFromModule(ctx, module, apiScope) } } }) // Normalize the paths, i.e. remove duplicates and sort. Loading sdk/update.go +5 −0 Original line number Diff line number Diff line Loading @@ -156,6 +156,11 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) { if memberTag, ok := tag.(android.SdkMemberTypeDependencyTag); ok { memberType := memberTag.SdkMemberType(child) // If a nil SdkMemberType was returned then this module should not be added to the sdk. if memberType == nil { return false } // Make sure that the resolved module is allowed in the member list property. if !memberType.IsInstance(child) { ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(child), memberType.SdkPropertyName()) Loading Loading
android/sdk.go +2 −0 Original line number Diff line number Diff line Loading @@ -375,6 +375,8 @@ type SdkMemberTypeDependencyTag interface { // SdkMemberType returns the SdkMemberType that will be used to automatically add the child module // to the sdk. // // Returning nil will prevent the module being added to the sdk. SdkMemberType(child Module) SdkMemberType // ExportMember determines whether a module added to the sdk through this tag will be exported Loading
apex/bootclasspath_fragment_test.go +327 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import ( "android/soong/android" "android/soong/java" "github.com/google/blueprint/proptools" ) // Contains tests for bootclasspath_fragment logic from java/bootclasspath_fragment.go as the ART Loading Loading @@ -868,4 +869,330 @@ func TestBootclasspathFragment_HiddenAPIList(t *testing.T) { android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+quuzTestStubs+":"+fooStubs) } // TestBootclasspathFragment_AndroidNonUpdatable checks to make sure that setting // additional_stubs: ["android-non-updatable"] causes the source android-non-updatable modules to be // added to the hiddenapi list tool. func TestBootclasspathFragment_AndroidNonUpdatable(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, prepareForTestWithArtApex, prepareForTestWithMyapex, // Configure bootclasspath jars to ensure that hidden API encoding is performed on them. java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"), // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding // is disabled. android.FixtureAddTextFile("frameworks/base/Android.bp", ""), java.PrepareForTestWithJavaSdkLibraryFiles, java.FixtureWithLastReleaseApis("foo", "android-non-updatable"), ).RunTestWithBp(t, ` java_sdk_library { name: "android-non-updatable", srcs: ["b.java"], compile_dex: true, public: { enabled: true, }, system: { enabled: true, }, test: { enabled: true, }, module_lib: { enabled: true, }, } apex { name: "com.android.art", key: "com.android.art.key", bootclasspath_fragments: ["art-bootclasspath-fragment"], java_libs: [ "baz", "quuz", ], updatable: false, } apex_key { name: "com.android.art.key", public_key: "com.android.art.avbpubkey", private_key: "com.android.art.pem", } java_library { name: "baz", apex_available: [ "com.android.art", ], srcs: ["b.java"], compile_dex: true, } java_library { name: "quuz", apex_available: [ "com.android.art", ], srcs: ["b.java"], compile_dex: true, } bootclasspath_fragment { name: "art-bootclasspath-fragment", image_name: "art", // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. contents: ["baz", "quuz"], apex_available: [ "com.android.art", ], } apex { name: "myapex", key: "myapex.key", bootclasspath_fragments: [ "mybootclasspathfragment", ], updatable: false, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_sdk_library { name: "foo", srcs: ["b.java"], shared_library: false, public: {enabled: true}, apex_available: [ "myapex", ], } java_library { name: "bar", srcs: ["b.java"], installable: true, apex_available: [ "myapex", ], } bootclasspath_fragment { name: "mybootclasspathfragment", contents: [ "foo", "bar", ], apex_available: [ "myapex", ], additional_stubs: ["android-non-updatable"], fragments: [ { apex: "com.android.art", module: "art-bootclasspath-fragment", }, ], } `) java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{ "android-non-updatable.stubs", "android-non-updatable.stubs.module_lib", "android-non-updatable.stubs.system", "android-non-updatable.stubs.test", "art-bootclasspath-fragment", "bar", "dex2oatd", "foo", }) nonUpdatablePublicStubs := getDexJarPath(result, "android-non-updatable.stubs") nonUpdatableSystemStubs := getDexJarPath(result, "android-non-updatable.stubs.system") nonUpdatableTestStubs := getDexJarPath(result, "android-non-updatable.stubs.test") nonUpdatableModuleLibStubs := getDexJarPath(result, "android-non-updatable.stubs.module_lib") // Make sure that the fragment uses the android-non-updatable modules when generating the hidden // API flags. fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000") rule := fragment.Rule("modularHiddenAPIStubFlagsFile") command := rule.RuleParams.Command android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list") // Make sure that the module_lib non-updatable stubs are available for resolving references from // the implementation boot dex jars provided by this module. android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs) // Make sure that the appropriate non-updatable stubs are available for resolving references from // the different API stubs provided by this module. android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs) android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs) android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs) } // TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks checks to make sure that // setting additional_stubs: ["android-non-updatable"] causes the prebuilt android-non-updatable // modules to be added to the hiddenapi list tool. func TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, java.PrepareForTestWithJavaDefaultModules, prepareForTestWithArtApex, prepareForTestWithMyapex, // Configure bootclasspath jars to ensure that hidden API encoding is performed on them. java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"), // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding // is disabled. android.FixtureAddTextFile("frameworks/base/Android.bp", ""), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true) }), java.PrepareForTestWithJavaSdkLibraryFiles, java.FixtureWithPrebuiltApis(map[string][]string{ "current": {"android-non-updatable"}, "30": {"foo"}, }), ).RunTestWithBp(t, ` apex { name: "com.android.art", key: "com.android.art.key", bootclasspath_fragments: ["art-bootclasspath-fragment"], java_libs: [ "baz", "quuz", ], updatable: false, } apex_key { name: "com.android.art.key", public_key: "com.android.art.avbpubkey", private_key: "com.android.art.pem", } java_library { name: "baz", apex_available: [ "com.android.art", ], srcs: ["b.java"], compile_dex: true, } java_library { name: "quuz", apex_available: [ "com.android.art", ], srcs: ["b.java"], compile_dex: true, } bootclasspath_fragment { name: "art-bootclasspath-fragment", image_name: "art", // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. contents: ["baz", "quuz"], apex_available: [ "com.android.art", ], } apex { name: "myapex", key: "myapex.key", bootclasspath_fragments: [ "mybootclasspathfragment", ], updatable: false, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_sdk_library { name: "foo", srcs: ["b.java"], shared_library: false, public: {enabled: true}, apex_available: [ "myapex", ], } java_library { name: "bar", srcs: ["b.java"], installable: true, apex_available: [ "myapex", ], } bootclasspath_fragment { name: "mybootclasspathfragment", contents: [ "foo", "bar", ], apex_available: [ "myapex", ], additional_stubs: ["android-non-updatable"], fragments: [ { apex: "com.android.art", module: "art-bootclasspath-fragment", }, ], } `) java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{ "art-bootclasspath-fragment", "bar", "dex2oatd", "foo", "prebuilt_sdk_module-lib_current_android-non-updatable", "prebuilt_sdk_public_current_android-non-updatable", "prebuilt_sdk_system_current_android-non-updatable", "prebuilt_sdk_test_current_android-non-updatable", }) nonUpdatablePublicStubs := getDexJarPath(result, "sdk_public_current_android-non-updatable") nonUpdatableSystemStubs := getDexJarPath(result, "sdk_system_current_android-non-updatable") nonUpdatableTestStubs := getDexJarPath(result, "sdk_test_current_android-non-updatable") nonUpdatableModuleLibStubs := getDexJarPath(result, "sdk_module-lib_current_android-non-updatable") // Make sure that the fragment uses the android-non-updatable modules when generating the hidden // API flags. fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000") rule := fragment.Rule("modularHiddenAPIStubFlagsFile") command := rule.RuleParams.Command android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list") // Make sure that the module_lib non-updatable stubs are available for resolving references from // the implementation boot dex jars provided by this module. android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs) // Make sure that the appropriate non-updatable stubs are available for resolving references from // the different API stubs provided by this module. android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs) android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs) android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs) } // TODO(b/177892522) - add test for host apex.
java/bootclasspath_fragment.go +20 −2 Original line number Diff line number Diff line Loading @@ -124,6 +124,15 @@ type bootclasspathFragmentProperties struct { // Hidden API related properties. Hidden_api HiddenAPIFlagFileProperties // The list of additional stub libraries which this fragment's contents use but which are not // provided by another bootclasspath_fragment. // // Note, "android-non-updatable" is treated specially. While no such module exists it is treated // as if it was a java_sdk_library. So, when public API stubs are needed then it will be replaced // with "android-non-updatable.stubs", with "androidn-non-updatable.system.stubs" when the system // stubs are needed and so on. Additional_stubs []string // Properties that allow a fragment to depend on other fragments. This is needed for hidden API // processing as it needs access to all the classes used by a fragment including those provided // by other fragments. Loading Loading @@ -381,6 +390,15 @@ func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorCon // bootclasspath fragment. hiddenAPIAddStubLibDependencies(ctx, b.properties.apiScopeToStubLibs()) for _, additionalStubModule := range b.properties.Additional_stubs { for _, apiScope := range hiddenAPISdkLibrarySupportedScopes { // Add a dependency onto a possibly scope specific stub library. scopeSpecificDependency := apiScope.scopeSpecificStubModule(ctx, additionalStubModule) tag := hiddenAPIStubsDependencyTag{apiScope: apiScope, fromAdditionalDependency: true} ctx.AddVariationDependencies(nil, tag, scopeSpecificDependency) } } if SkipDexpreoptBootJars(ctx) { return } Loading Loading @@ -640,8 +658,8 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul // Populate with flag file paths from the properties. input.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api) // Store the stub dex jars from this module's fragment dependencies. input.DependencyStubDexJarsByScope = dependencyHiddenApiInfo.TransitiveStubDexJarsByScope // Add the stub dex jars from this module's fragment dependencies. input.DependencyStubDexJarsByScope.append(dependencyHiddenApiInfo.TransitiveStubDexJarsByScope) return input } Loading
java/hiddenapi_modular.go +97 −10 Original line number Diff line number Diff line Loading @@ -37,13 +37,65 @@ type HiddenAPIScope struct { // The option needed to passed to "hiddenapi list". hiddenAPIListOption string // The name sof the source stub library modules that contain the API provided by the platform, // i.e. by modules that are not in an APEX. nonUpdatableSourceModule string // The names of the prebuilt stub library modules that contain the API provided by the platform, // i.e. by modules that are not in an APEX. nonUpdatablePrebuiltModule string } // initHiddenAPIScope initializes the scope. func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope { sdkKind := apiScope.sdkKind // The platform does not provide a core platform API. if sdkKind != android.SdkCorePlatform { kindAsString := sdkKind.String() var insert string if sdkKind == android.SdkPublic { insert = "" } else { insert = "." + strings.ReplaceAll(kindAsString, "-", "_") } nonUpdatableModule := "android-non-updatable" // Construct the name of the android-non-updatable source module for this scope. apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert) prebuiltModuleName := func(name string, kind string) string { return fmt.Sprintf("sdk_%s_current_%s", kind, name) } // Construct the name of the android-non-updatable prebuilt module for this scope. apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString) } return apiScope } // android-non-updatable takes the name of a module and returns a possibly scope specific name of // the module. func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string { // The android-non-updatable is not a java_sdk_library but there are separate stub libraries for // each scope. // TODO(b/192067200): Remove special handling of android-non-updatable. if name == "android-non-updatable" { if ctx.Config().AlwaysUsePrebuiltSdks() { return l.nonUpdatablePrebuiltModule } else { return l.nonUpdatableSourceModule } } else { // Assume that the module is either a java_sdk_library (or equivalent) and so will provide // separate stub jars for each scope or is a java_library (or equivalent) in which case it will // have the same stub jar for each scope. return name } } func (l *HiddenAPIScope) String() string { return fmt.Sprintf("HiddenAPIScope{%s}", l.name) } Loading Loading @@ -122,6 +174,11 @@ type hiddenAPIStubsDependencyTag struct { // The api scope for which this dependency was added. apiScope *HiddenAPIScope // Indicates that the dependency is not for an API provided by the current bootclasspath fragment // but is an additional API provided by a module that is not part of the current bootclasspath // fragment. fromAdditionalDependency bool } func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() { Loading @@ -132,6 +189,11 @@ func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool { } func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType { // Do not add additional dependencies to the sdk. if b.fromAdditionalDependency { return nil } // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs // property, otherwise treat if it was specified in the java_header_libs property. if javaSdkLibrarySdkMemberType.IsInstance(child) { Loading Loading @@ -243,15 +305,10 @@ func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, tempPath := tempPathForRestat(ctx, outputPath) // Find the widest API stubs provided by the fragments on which this depends, if any. var dependencyStubDexJars android.Paths for i := len(hiddenAPIScopes) - 1; i >= 0; i-- { apiScope := hiddenAPIScopes[i] stubsForAPIScope := input.DependencyStubDexJarsByScope[apiScope] if len(stubsForAPIScope) != 0 { dependencyStubDexJars = stubsForAPIScope break } } dependencyStubDexJars := input.DependencyStubDexJarsByScope.stubDexJarsForWidestAPIScope() // Add widest API stubs from the additional dependencies of this, if any. dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.stubDexJarsForWidestAPIScope()...) command := rule.Command(). Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")). Loading @@ -266,6 +323,7 @@ func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, // other fragment's APIs. var paths android.Paths paths = append(paths, input.DependencyStubDexJarsByScope[apiScope]...) paths = append(paths, input.AdditionalStubDexJarsByScope[apiScope]...) paths = append(paths, input.StubDexJarsByScope[apiScope]...) if len(paths) > 0 { option := apiScope.hiddenAPIListOption Loading Loading @@ -514,6 +572,20 @@ func (s StubDexJarsByScope) dedupAndSort() { } } // stubDexJarsForWidestAPIScope returns the stub dex jars for the widest API scope provided by this // map. The relative width of APIs is determined by their order in hiddenAPIScopes. func (s StubDexJarsByScope) stubDexJarsForWidestAPIScope() android.Paths { for i := len(hiddenAPIScopes) - 1; i >= 0; i-- { apiScope := hiddenAPIScopes[i] stubsForAPIScope := s[apiScope] if len(stubsForAPIScope) != 0 { return stubsForAPIScope } } return nil } // HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are // needed for hidden API flag generation. type HiddenAPIFlagInput struct { Loading @@ -530,6 +602,13 @@ type HiddenAPIFlagInput struct { // fragment on which this depends. DependencyStubDexJarsByScope StubDexJarsByScope // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to // the ones that are obtained from fragments on which this depends. // // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope // as there are not propagated transitively to other fragments that depend on this. AdditionalStubDexJarsByScope StubDexJarsByScope // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are // specified in the bootclasspath_fragment's stub_libs and contents properties. RemovedTxtFiles android.Paths Loading @@ -541,6 +620,7 @@ func newHiddenAPIFlagInput() HiddenAPIFlagInput { FlagFilesByCategory: FlagFilesByCategory{}, StubDexJarsByScope: StubDexJarsByScope{}, DependencyStubDexJarsByScope: StubDexJarsByScope{}, AdditionalStubDexJarsByScope: StubDexJarsByScope{}, } return input Loading Loading @@ -614,8 +694,15 @@ func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, conten tag := ctx.OtherModuleDependencyTag(module) if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok { apiScope := hiddenAPIStubsTag.apiScope if hiddenAPIStubsTag.fromAdditionalDependency { dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind) if dexJar != nil { i.AdditionalStubDexJarsByScope[apiScope] = append(i.AdditionalStubDexJarsByScope[apiScope], dexJar) } } else { addFromModule(ctx, module, apiScope) } } }) // Normalize the paths, i.e. remove duplicates and sort. Loading
sdk/update.go +5 −0 Original line number Diff line number Diff line Loading @@ -156,6 +156,11 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) { if memberTag, ok := tag.(android.SdkMemberTypeDependencyTag); ok { memberType := memberTag.SdkMemberType(child) // If a nil SdkMemberType was returned then this module should not be added to the sdk. if memberType == nil { return false } // Make sure that the resolved module is allowed in the member list property. if !memberType.IsInstance(child) { ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(child), memberType.SdkPropertyName()) Loading