diff --git a/apex/apex.go b/apex/apex.go index ff38773b8..8a8b19d0a 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1769,7 +1769,7 @@ func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaMod func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile { if dexpreopter, ok := module.(java.DexpreopterInterface); ok { - if profilePathOnHost := dexpreopter.ProfilePathOnHost(); profilePathOnHost != nil { + if profilePathOnHost := dexpreopter.OutputProfilePathOnHost(); profilePathOnHost != nil { dirInApex := "javalib" af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil) af.customStem = module.Stem() + ".jar.prof" diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go index c404a2e37..f94e50f4f 100644 --- a/apex/systemserver_classpath_fragment_test.go +++ b/apex/systemserver_classpath_fragment_test.go @@ -15,10 +15,11 @@ package apex import ( - "android/soong/dexpreopt" + "strings" "testing" "android/soong/android" + "android/soong/dexpreopt" "android/soong/java" ) @@ -31,7 +32,7 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"), + dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar", "myapex:baz"), ).RunTestWithBp(t, ` apex { name: "myapex", @@ -69,11 +70,24 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { ], } + java_library { + name: "baz", + srcs: ["d.java"], + installable: true, + dex_preopt: { + profile_guided: true, // ignored + }, + apex_available: [ + "myapex", + ], + } + systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", contents: [ "foo", "bar", + "baz", ], apex_available: [ "myapex", @@ -81,17 +95,24 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { } `) - ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ + ctx := result.TestContext + + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ "etc/classpaths/systemserverclasspath.pb", "javalib/foo.jar", "javalib/bar.jar", "javalib/bar.jar.prof", + "javalib/baz.jar", }) - java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ + java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex_image", []string{ `myapex.key`, `mysystemserverclasspathfragment`, }) + + assertProfileGuided(t, ctx, "foo", "android_common_apex10000", false) + assertProfileGuided(t, ctx, "bar", "android_common_apex10000", true) + assertProfileGuided(t, ctx, "baz", "android_common_apex10000", false) } func TestSystemserverclasspathFragmentNoGeneratedProto(t *testing.T) { @@ -201,7 +222,7 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"), + dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"), ).RunTestWithBp(t, ` prebuilt_apex { name: "myapex", @@ -224,11 +245,23 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { ], } + java_import { + name: "bar", + jars: ["bar.jar"], + dex_preopt: { + profile_guided: true, + }, + apex_available: [ + "myapex", + ], + } + prebuilt_systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", prefer: true, contents: [ "foo", + "bar", ], apex_available: [ "myapex", @@ -236,22 +269,34 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { } `) - java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{ + ctx := result.TestContext + + java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{ `myapex.apex.selector`, `prebuilt_mysystemserverclasspathfragment`, }) - java.CheckModuleDependencies(t, result.TestContext, "mysystemserverclasspathfragment", "android_common_myapex", []string{ + java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{ `myapex.deapexer`, + `prebuilt_bar`, `prebuilt_foo`, }) + + ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{ + "javalib/foo.jar", + "javalib/bar.jar", + "javalib/bar.jar.prof", + }) + + assertProfileGuided(t, ctx, "foo", "android_common_myapex", false) + assertProfileGuided(t, ctx, "bar", "android_common_myapex", true) } func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"), + dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar", "myapex:baz"), ).RunTestWithBp(t, ` apex { name: "myapex", @@ -289,11 +334,24 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { ], } + java_library { + name: "baz", + srcs: ["d.java"], + dex_preopt: { + profile_guided: true, // ignored + }, + installable: true, + apex_available: [ + "myapex", + ], + } + systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", standalone_contents: [ "foo", "bar", + "baz", ], apex_available: [ "myapex", @@ -301,19 +359,26 @@ func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) { } `) - ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ + ctx := result.TestContext + + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ "etc/classpaths/systemserverclasspath.pb", "javalib/foo.jar", "javalib/bar.jar", "javalib/bar.jar.prof", + "javalib/baz.jar", }) + + assertProfileGuided(t, ctx, "foo", "android_common_apex10000", false) + assertProfileGuided(t, ctx, "bar", "android_common_apex10000", true) + assertProfileGuided(t, ctx, "baz", "android_common_apex10000", false) } func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, - dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo"), + dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"), ).RunTestWithBp(t, ` prebuilt_apex { name: "myapex", @@ -336,11 +401,23 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { ], } + java_import { + name: "bar", + jars: ["bar.jar"], + dex_preopt: { + profile_guided: true, + }, + apex_available: [ + "myapex", + ], + } + prebuilt_systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", prefer: true, standalone_contents: [ "foo", + "bar", ], apex_available: [ "myapex", @@ -348,8 +425,28 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { } `) - java.CheckModuleDependencies(t, result.TestContext, "mysystemserverclasspathfragment", "android_common_myapex", []string{ + ctx := result.TestContext + + java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{ `myapex.deapexer`, + `prebuilt_bar`, `prebuilt_foo`, }) + + ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{ + "javalib/foo.jar", + "javalib/bar.jar", + "javalib/bar.jar.prof", + }) + + assertProfileGuided(t, ctx, "foo", "android_common_myapex", false) + assertProfileGuided(t, ctx, "bar", "android_common_myapex", true) +} + +func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) { + dexpreopt := ctx.ModuleForTests(moduleName, variant).Rule("dexpreopt") + actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=") + if expected != actual { + t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual) + } } diff --git a/java/dexpreopt.go b/java/dexpreopt.go index c4b0af441..e0a062902 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -23,11 +23,24 @@ import ( ) type DexpreopterInterface interface { - IsInstallable() bool // Structs that embed dexpreopter must implement this. + // True if the java module is to be dexed and installed on devices. + // Structs that embed dexpreopter must implement this. + IsInstallable() bool + + // True if dexpreopt is disabled for the java module. dexpreoptDisabled(ctx android.BaseModuleContext) bool + + // If the java module is to be installed into an APEX, this list contains information about the + // dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed + // outside of the APEX. DexpreoptBuiltInstalledForApex() []dexpreopterInstall + + // The Make entries to install the dexpreopt outputs. Derived from + // `DexpreoptBuiltInstalledForApex`. AndroidMkEntriesForApex() []android.AndroidMkEntries - ProfilePathOnHost() android.Path + + // See `dexpreopter.outputProfilePathOnHost`. + OutputProfilePathOnHost() android.Path } type dexpreopterInstall struct { @@ -78,7 +91,8 @@ func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries { } type dexpreopter struct { - dexpreoptProperties DexpreoptProperties + dexpreoptProperties DexpreoptProperties + importDexpreoptProperties ImportDexpreoptProperties installPath android.InstallPath uncompressedDex bool @@ -105,8 +119,13 @@ type dexpreopter struct { // dexpreopt another partition). configPath android.WritablePath - // The path to the profile on host. - profilePathOnHost android.Path + // The path to the profile on host that dexpreopter generates. This is used as the input for + // dex2oat. + outputProfilePathOnHost android.Path + + // The path to the profile that dexpreopter accepts. It must be in the binary format. If this is + // set, it overrides the profile settings in `dexpreoptProperties`. + inputProfilePathOnHost android.Path } type DexpreoptProperties struct { @@ -127,6 +146,18 @@ type DexpreoptProperties struct { // profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found. Profile *string `android:"path"` } + + Dex_preopt_result struct { + // True if profile-guided optimization is actually enabled. + Profile_guided bool + } `blueprint:"mutated"` +} + +type ImportDexpreoptProperties struct { + Dex_preopt struct { + // If true, use the profile in the prebuilt APEX to guide optimization. Defaults to false. + Profile_guided *bool + } } func init() { @@ -295,7 +326,9 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr var profileClassListing android.OptionalPath var profileBootListing android.OptionalPath profileIsTextListing := false - if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) { + if d.inputProfilePathOnHost != nil { + profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost) + } else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) { // If dex_preopt.profile_guided is not set, default it based on the existence of the // dexprepot.profile option or the profile class listing. if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" { @@ -310,6 +343,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr } } + d.dexpreoptProperties.Dex_preopt_result.Profile_guided = profileClassListing.Valid() + // Full dexpreopt config, used to create dexpreopt build rules. dexpreoptConfig := &dexpreopt.ModuleConfig{ Name: moduleName(ctx), @@ -374,7 +409,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr isProfile := strings.HasSuffix(installBase, ".prof") if isProfile { - d.profilePathOnHost = install.From + d.outputProfilePathOnHost = install.From } if isApexSystemServerJar { @@ -416,6 +451,6 @@ func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries { return entries } -func (d *dexpreopter) ProfilePathOnHost() android.Path { - return d.profilePathOnHost +func (d *dexpreopter) OutputProfilePathOnHost() android.Path { + return d.outputProfilePathOnHost } diff --git a/java/java.go b/java/java.go index a003162eb..c2fcccf2f 100644 --- a/java/java.go +++ b/java/java.go @@ -801,6 +801,8 @@ type librarySdkMemberProperties struct { // The value of the min_sdk_version property, translated into a number where possible. MinSdkVersion *string `supported_build_releases:"Tiramisu+"` + + DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"` } func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { @@ -818,6 +820,10 @@ func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberCo canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.ApiLevel.String()) p.MinSdkVersion = proptools.StringPtr(canonical) } + + if j.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided { + p.DexPreoptProfileGuided = proptools.BoolPtr(true) + } } func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { @@ -844,6 +850,11 @@ func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberConte propertySet.AddProperty("permitted_packages", p.PermittedPackages) } + dexPreoptSet := propertySet.AddPropertySet("dex_preopt") + if p.DexPreoptProfileGuided != nil { + dexPreoptSet.AddProperty("profile_guided", proptools.Bool(p.DexPreoptProfileGuided)) + } + // Do not copy anything else to the snapshot. if memberType.onlyCopyJarToSnapshot { return @@ -2014,7 +2025,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { if di == nil { return // An error has been reported by FindDeapexerProviderForModule. } - if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(j.BaseModuleName())); dexOutputPath != nil { + dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(j.BaseModuleName()) + if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil { dexJarFile := makeDexJarPathFromPath(dexOutputPath) j.dexJarFile = dexJarFile installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName())) @@ -2023,6 +2035,11 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath) setUncompressDex(ctx, &j.dexpreopter, &j.dexer) j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex + + if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil { + j.dexpreopter.inputProfilePathOnHost = profilePath + } + j.dexpreopt(ctx, dexOutputPath) // Initialize the hiddenapi structure. @@ -2157,11 +2174,16 @@ func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, // requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or // java_sdk_library_import with the specified base module name requires to be exported from a // prebuilt_apex/apex_set. -func requiredFilesFromPrebuiltApexForImport(name string) []string { +func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []string { + dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(name) // Add the dex implementation jar to the set of exported files. - return []string{ - apexRootRelativePathToJavaLib(name), + files := []string{ + dexJarFileApexRootRelative, } + if BoolDefault(d.importDexpreoptProperties.Dex_preopt.Profile_guided, false) { + files = append(files, dexJarFileApexRootRelative+".prof") + } + return files } // apexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for @@ -2174,7 +2196,7 @@ var _ android.RequiredFilesFromPrebuiltApex = (*Import)(nil) func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []string { name := j.BaseModuleName() - return requiredFilesFromPrebuiltApexForImport(name) + return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter) } // Add compile time check for interface implementation @@ -2215,6 +2237,7 @@ func ImportFactory() android.Module { module.AddProperties( &module.properties, &module.dexer.dexProperties, + &module.importDexpreoptProperties, ) module.initModuleAndImport(module) diff --git a/java/sdk_library.go b/java/sdk_library.go index d50628080..c168c53d4 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -2243,7 +2243,7 @@ func sdkLibraryImportFactory() android.Module { allScopeProperties, scopeToProperties := createPropertiesInstance() module.scopeProperties = scopeToProperties - module.AddProperties(&module.properties, allScopeProperties) + module.AddProperties(&module.properties, allScopeProperties, &module.importDexpreoptProperties) // Initialize information common between source and prebuilt. module.initCommon(module) @@ -2487,18 +2487,24 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo if di == nil { return // An error has been reported by FindDeapexerProviderForModule. } - if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(module.BaseModuleName())); dexOutputPath != nil { + dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(module.BaseModuleName()) + if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil { dexJarFile := makeDexJarPathFromPath(dexOutputPath) module.dexJarFile = dexJarFile installPath := android.PathForModuleInPartitionInstall( - ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(module.BaseModuleName())) + ctx, "apex", ai.ApexVariationName, dexJarFileApexRootRelative) module.installFile = installPath module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil) - // Dexpreopting. module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, installPath) module.dexpreopter.isSDKLibrary = true module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &module.dexpreopter) + + if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil { + module.dexpreopter.inputProfilePathOnHost = profilePath + } + + // Dexpreopting. module.dexpreopt(ctx, dexOutputPath) } else { // This should never happen as a variant for a prebuilt_apex is only created if the @@ -2627,7 +2633,7 @@ var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil) func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string { name := module.BaseModuleName() - return requiredFilesFromPrebuiltApexForImport(name) + return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter) } // java_sdk_library_xml @@ -3036,6 +3042,8 @@ type sdkLibrarySdkMemberProperties struct { // // This means that the device won't recognise this library as installed. Max_device_sdk *string + + DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"` } type scopeProperties struct { @@ -3089,6 +3097,10 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe 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 + + if sdk.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided { + s.DexPreoptProfileGuided = proptools.BoolPtr(true) + } } func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { @@ -3104,6 +3116,10 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo if len(s.Permitted_packages) > 0 { propertySet.AddProperty("permitted_packages", s.Permitted_packages) } + dexPreoptSet := propertySet.AddPropertySet("dex_preopt") + if s.DexPreoptProfileGuided != nil { + dexPreoptSet.AddProperty("profile_guided", proptools.Bool(s.DexPreoptProfileGuided)) + } stem := s.Stem diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index 2ade146b7..3a2ecc00c 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -33,7 +33,8 @@ var prepareForSdkTestWithJava = android.GroupFixturePreparers( // Files needs by most of the tests. android.MockFS{ - "Test.java": nil, + "Test.java": nil, + "art-profile": nil, }.AddToFixture(), ) diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go index 2a17cdc3a..66c44c843 100644 --- a/sdk/systemserverclasspath_fragment_sdk_test.go +++ b/sdk/systemserverclasspath_fragment_sdk_test.go @@ -62,6 +62,9 @@ func testSnapshotWithSystemServerClasspathFragment(t *testing.T, sdk string, tar min_sdk_version: "2", compile_dex: true, permitted_packages: ["mylib"], + dex_preopt: { + profile: "art-profile", + }, } java_sdk_library { @@ -71,6 +74,9 @@ func testSnapshotWithSystemServerClasspathFragment(t *testing.T, sdk string, tar shared_library: false, public: {enabled: true}, min_sdk_version: "2", + dex_preopt: { + profile: "art-profile", + }, } `), ).RunTest(t) @@ -105,6 +111,9 @@ java_sdk_library_import { visibility: ["//visibility:public"], apex_available: ["myapex"], shared_library: false, + dex_preopt: { + profile_guided: true, + }, public: { jars: ["sdk_library/public/mysdklibrary-stubs.jar"], stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"], @@ -122,6 +131,9 @@ java_import { jars: ["java_systemserver_libs/snapshot/jars/are/invalid/mylib.jar"], min_sdk_version: "2", permitted_packages: ["mylib"], + dex_preopt: { + profile_guided: true, + }, } prebuilt_systemserverclasspath_fragment { @@ -186,6 +198,54 @@ java_import { permitted_packages: ["mylib"], } +prebuilt_systemserverclasspath_fragment { + name: "mysystemserverclasspathfragment", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + contents: [ + "mylib", + "mysdklibrary", + ], +} +`) + }) + + t.Run("target-u", func(t *testing.T) { + testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "UpsideDownCake", ` +// This is auto-generated. DO NOT EDIT. + +java_sdk_library_import { + name: "mysdklibrary", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + shared_library: false, + dex_preopt: { + profile_guided: true, + }, + public: { + jars: ["sdk_library/public/mysdklibrary-stubs.jar"], + stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"], + current_api: "sdk_library/public/mysdklibrary.txt", + removed_api: "sdk_library/public/mysdklibrary-removed.txt", + sdk_version: "current", + }, +} + +java_import { + name: "mylib", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + jars: ["java_systemserver_libs/snapshot/jars/are/invalid/mylib.jar"], + min_sdk_version: "2", + permitted_packages: ["mylib"], + dex_preopt: { + profile_guided: true, + }, +} + prebuilt_systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", prefer: false,