| // Copyright (C) 2021 The Android Open Source Project | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | package sdk | 
 |  | 
 | import ( | 
 | 	"fmt" | 
 | 	"path/filepath" | 
 | 	"strings" | 
 | 	"testing" | 
 |  | 
 | 	"android/soong/android" | 
 | 	"android/soong/java" | 
 | ) | 
 |  | 
 | // fixtureAddPlatformBootclasspathForBootclasspathFragment adds a platform_bootclasspath module that | 
 | // references the bootclasspath fragment. | 
 | func fixtureAddPlatformBootclasspathForBootclasspathFragment(apex, fragment string) android.FixturePreparer { | 
 | 	return fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra(apex, fragment, "") | 
 | } | 
 |  | 
 | // fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra is the same as above, but also adds extra fragments. | 
 | func fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra(apex, fragment, extraFragments string) android.FixturePreparer { | 
 | 	return android.GroupFixturePreparers( | 
 | 		// Add a platform_bootclasspath module. | 
 | 		android.FixtureAddTextFile("frameworks/base/boot/Android.bp", fmt.Sprintf(` | 
 | 			platform_bootclasspath { | 
 | 				name: "platform-bootclasspath", | 
 | 				fragments: [ | 
 | 					{ | 
 | 						apex: "%s", | 
 | 						module: "%s", | 
 | 					}, | 
 | 					%s | 
 | 				], | 
 | 			} | 
 | 		`, apex, fragment, extraFragments)), | 
 | 		android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil), | 
 | 		android.FixtureAddFile("frameworks/base/config/boot-image-profile.txt", nil), | 
 | 		android.FixtureAddFile("build/soong/scripts/check_boot_jars/package_allowed_list.txt", nil), | 
 | 	) | 
 | } | 
 |  | 
 | // fixtureAddPrebuiltApexForBootclasspathFragment adds a prebuilt_apex that exports the fragment. | 
 | func fixtureAddPrebuiltApexForBootclasspathFragment(apex, fragment string) android.FixturePreparer { | 
 | 	apexFile := fmt.Sprintf("%s.apex", apex) | 
 | 	dir := "prebuilts/apex" | 
 | 	return android.GroupFixturePreparers( | 
 | 		// A preparer to add a prebuilt apex to the test fixture. | 
 | 		android.FixtureAddTextFile(filepath.Join(dir, "Android.bp"), fmt.Sprintf(` | 
 | 			prebuilt_apex { | 
 | 				name: "%s", | 
 | 				src: "%s", | 
 | 				exported_bootclasspath_fragments: [ | 
 | 					"%s", | 
 | 				], | 
 | 			} | 
 | 		`, apex, apexFile, fragment)), | 
 | 		android.FixtureAddFile(filepath.Join(dir, apexFile), nil), | 
 | 	) | 
 | } | 
 |  | 
 | func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { | 
 | 	result := android.GroupFixturePreparers( | 
 | 		prepareForSdkTestWithJava, | 
 | 		java.PrepareForTestWithDexpreopt, | 
 | 		prepareForSdkTestWithApex, | 
 |  | 
 | 		// Some additional files needed for the art apex. | 
 | 		android.FixtureMergeMockFs(android.MockFS{ | 
 | 			"com.android.art.avbpubkey":                          nil, | 
 | 			"com.android.art.pem":                                nil, | 
 | 			"system/sepolicy/apex/com.android.art-file_contexts": nil, | 
 | 		}), | 
 |  | 
 | 		// Add a platform_bootclasspath that depends on the fragment. | 
 | 		fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra( | 
 | 			"com.android.art", "art-bootclasspath-fragment", java.ApexBootJarFragmentsForPlatformBootclasspath), | 
 |  | 
 | 		java.PrepareForBootImageConfigTest, | 
 | 		java.PrepareApexBootJarConfigsAndModules, | 
 | 		android.FixtureWithRootAndroidBp(` | 
 | 			sdk { | 
 | 				name: "mysdk", | 
 | 				bootclasspath_fragments: ["art-bootclasspath-fragment"], | 
 | 			} | 
 |  | 
 | 			apex { | 
 | 				name: "com.android.art", | 
 | 				key: "com.android.art.key", | 
 | 				bootclasspath_fragments: [ | 
 | 					"art-bootclasspath-fragment", | 
 | 				], | 
 | 				updatable: false, | 
 | 			} | 
 |  | 
 | 			bootclasspath_fragment { | 
 | 				name: "art-bootclasspath-fragment", | 
 | 				image_name: "art", | 
 | 				contents: ["core1", "core2"], | 
 | 				apex_available: ["com.android.art"], | 
 | 				hidden_api: { | 
 | 					split_packages: ["*"], | 
 | 				}, | 
 | 			} | 
 |  | 
 | 			apex_key { | 
 | 				name: "com.android.art.key", | 
 | 				public_key: "com.android.art.avbpubkey", | 
 | 				private_key: "com.android.art.pem", | 
 | 			} | 
 |  | 
 | 			java_library { | 
 | 				name: "core1", | 
 | 				srcs: ["Test.java"], | 
 | 				system_modules: "none", | 
 | 				sdk_version: "none", | 
 | 				compile_dex: true, | 
 | 				apex_available: ["com.android.art"], | 
 | 			} | 
 |  | 
 | 			java_library { | 
 | 				name: "core2", | 
 | 				srcs: ["Test.java"], | 
 | 				system_modules: "none", | 
 | 				sdk_version: "none", | 
 | 				compile_dex: true, | 
 | 				apex_available: ["com.android.art"], | 
 | 			} | 
 | `), | 
 | 	).RunTest(t) | 
 |  | 
 | 	// A preparer to update the test fixture used when processing an unpackage snapshot. | 
 | 	preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("com.android.art", "art-bootclasspath-fragment") | 
 |  | 
 | 	// Check that source on its own configures the bootImageConfig correctly. | 
 | 	java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") | 
 | 	java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") | 
 |  | 
 | 	CheckSnapshot(t, result, "mysdk", "", | 
 | 		checkAndroidBpContents(` | 
 | // This is auto-generated. DO NOT EDIT. | 
 |  | 
 | apex_contributions_defaults { | 
 |     name: "mysdk.contributions", | 
 |     contents: [], | 
 | } | 
 |  | 
 | prebuilt_bootclasspath_fragment { | 
 |     name: "art-bootclasspath-fragment", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["com.android.art"], | 
 |     image_name: "art", | 
 |     contents: [ | 
 |         "core1", | 
 |         "core2", | 
 |     ], | 
 |     hidden_api: { | 
 |         annotation_flags: "hiddenapi/annotation-flags.csv", | 
 |         metadata: "hiddenapi/metadata.csv", | 
 |         index: "hiddenapi/index.csv", | 
 |         signature_patterns: "hiddenapi/signature-patterns.csv", | 
 |         filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv", | 
 |         filtered_flags: "hiddenapi/filtered-flags.csv", | 
 |     }, | 
 | } | 
 |  | 
 | java_import { | 
 |     name: "core1", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["com.android.art"], | 
 |     jars: ["java_boot_libs/snapshot/jars/are/invalid/core1.jar"], | 
 | } | 
 |  | 
 | java_import { | 
 |     name: "core2", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["com.android.art"], | 
 |     jars: ["java_boot_libs/snapshot/jars/are/invalid/core2.jar"], | 
 | } | 
 |  | 
 | `), | 
 | 		checkAllCopyRules(` | 
 | .intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv | 
 | .intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv | 
 | .intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv | 
 | .intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv | 
 | .intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv | 
 | .intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv | 
 | .intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core1.jar | 
 | .intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core2.jar | 
 | 		`), | 
 | 		snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot), | 
 |  | 
 | 		// Check the behavior of the snapshot without the source. | 
 | 		snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) { | 
 | 			// Make sure that the boot jars package check rule includes the dex jars retrieved from the prebuilt apex. | 
 | 			checkBootJarsPackageCheckRule(t, result, | 
 | 				append( | 
 | 					[]string{ | 
 | 						"out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core1.jar", | 
 | 						"out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core2.jar", | 
 | 						"out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar", | 
 | 					}, | 
 | 					java.ApexBootJarDexJarPaths..., | 
 | 				)..., | 
 | 			) | 
 | 			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") | 
 | 			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") | 
 | 		}), | 
 |  | 
 | 		snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot), | 
 |  | 
 | 		// Check the behavior of the snapshot when the source is preferred. | 
 | 		snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) { | 
 | 			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") | 
 | 			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") | 
 | 		}), | 
 |  | 
 | 		snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot), | 
 |  | 
 | 		// Check the behavior of the snapshot when it is preferred. | 
 | 		snapshotTestChecker(checkSnapshotPreferredWithSource, func(t *testing.T, result *android.TestResult) { | 
 | 			java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") | 
 | 			java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") | 
 | 		}), | 
 | 	) | 
 |  | 
 | 	// Make sure that the boot jars package check rule includes the dex jars created from the source. | 
 | 	checkBootJarsPackageCheckRule(t, result, | 
 | 		append( | 
 | 			[]string{ | 
 | 				"out/soong/.intermediates/core1/android_common_apex10000/aligned/core1.jar", | 
 | 				"out/soong/.intermediates/core2/android_common_apex10000/aligned/core2.jar", | 
 | 				"out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar", | 
 | 			}, | 
 | 			java.ApexBootJarDexJarPaths..., | 
 | 		)..., | 
 | 	) | 
 | } | 
 |  | 
 | // checkBootJarsPackageCheckRule checks that the supplied module is an input to the boot jars | 
 | // package check rule. | 
 | func checkBootJarsPackageCheckRule(t *testing.T, result *android.TestResult, expectedModules ...string) { | 
 | 	t.Helper() | 
 | 	platformBcp := result.ModuleForTests("platform-bootclasspath", "android_common") | 
 | 	bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check") | 
 | 	command := bootJarsCheckRule.RuleParams.Command | 
 | 	expectedCommandArgs := " build/soong/scripts/check_boot_jars/package_allowed_list.txt " + strings.Join(expectedModules, " ") + " &&" | 
 | 	android.AssertStringDoesContain(t, "boot jars package check", command, expectedCommandArgs) | 
 | } | 
 |  | 
 | func testSnapshotWithBootClasspathFragment_Contents(t *testing.T, sdk string, copyRules string) { | 
 | 	result := android.GroupFixturePreparers( | 
 | 		prepareForSdkTestWithJava, | 
 | 		java.PrepareForTestWithJavaDefaultModules, | 
 | 		java.PrepareForTestWithJavaSdkLibraryFiles, | 
 | 		java.FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"), | 
 | 		java.FixtureConfigureApexBootJars("myapex:mybootlib", "myapex:myothersdklibrary"), | 
 | 		prepareForSdkTestWithApex, | 
 |  | 
 | 		// Add a platform_bootclasspath that depends on the fragment. | 
 | 		fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"), | 
 |  | 
 | 		android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"), | 
 | 		// Make sure that we have atleast one platform library so that we can check the monolithic hiddenapi | 
 | 		// file creation. | 
 | 		java.FixtureConfigureBootJars("platform:foo"), | 
 | 		android.FixtureModifyMockFS(func(fs android.MockFS) { | 
 | 			fs["platform/Android.bp"] = []byte(` | 
 | 		java_library { | 
 | 			name: "foo", | 
 | 			srcs: ["Test.java"], | 
 | 			compile_dex: true, | 
 | 		} | 
 | 		`) | 
 | 			fs["platform/Test.java"] = nil | 
 | 		}), | 
 |  | 
 | 		android.FixtureWithRootAndroidBp(sdk+` | 
 | 			apex { | 
 | 				name: "myapex", | 
 | 				key: "myapex.key", | 
 | 				min_sdk_version: "2", | 
 | 				bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 			} | 
 |  | 
 | 			bootclasspath_fragment { | 
 | 				name: "mybootclasspathfragment", | 
 | 				apex_available: ["myapex"], | 
 | 				contents: [ | 
 | 					// This should be automatically added to the sdk_snapshot as a java_boot_libs module. | 
 | 					"mybootlib", | 
 | 					// This should be automatically added to the sdk_snapshot as a java_sdk_libs module. | 
 | 					"myothersdklibrary", | 
 | 				], | 
 | 				api: { | 
 | 					stub_libs: ["mysdklibrary"], | 
 | 				}, | 
 | 				core_platform_api: { | 
 | 					// This should be automatically added to the sdk_snapshot as a java_sdk_libs module. | 
 | 					stub_libs: ["mycoreplatform"], | 
 | 				}, | 
 | 				hidden_api: { | 
 | 					split_packages: ["*"], | 
 | 				}, | 
 | 			} | 
 |  | 
 | 			java_library { | 
 | 				name: "mybootlib", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				system_modules: "none", | 
 | 				sdk_version: "none", | 
 | 				min_sdk_version: "2", | 
 | 				compile_dex: true, | 
 | 				permitted_packages: ["mybootlib"], | 
 | 			} | 
 |  | 
 | 			java_sdk_library { | 
 | 				name: "mysdklibrary", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				shared_library: false, | 
 | 				public: {enabled: true}, | 
 | 				min_sdk_version: "2", | 
 | 			} | 
 |  | 
 | 			java_sdk_library { | 
 | 				name: "myothersdklibrary", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				compile_dex: true, | 
 | 				public: {enabled: true}, | 
 | 				min_sdk_version: "2", | 
 | 				permitted_packages: ["myothersdklibrary"], | 
 | 			} | 
 |  | 
 | 			java_sdk_library { | 
 | 				name: "mycoreplatform", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				compile_dex: true, | 
 | 				public: {enabled: true}, | 
 | 				min_sdk_version: "2", | 
 | 			} | 
 | 		`), | 
 | 	).RunTest(t) | 
 |  | 
 | 	// A preparer to update the test fixture used when processing an unpackage snapshot. | 
 | 	preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("myapex", "mybootclasspathfragment") | 
 |  | 
 | 	CheckSnapshot(t, result, "mysdk", "", | 
 | 		checkAndroidBpContents(` | 
 | // This is auto-generated. DO NOT EDIT. | 
 |  | 
 | apex_contributions_defaults { | 
 |     name: "mysdk.contributions", | 
 |     contents: [ | 
 |         "prebuilt_myothersdklibrary", | 
 |         "prebuilt_mysdklibrary", | 
 |         "prebuilt_mycoreplatform", | 
 |     ], | 
 | } | 
 |  | 
 | prebuilt_bootclasspath_fragment { | 
 |     name: "mybootclasspathfragment", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     contents: [ | 
 |         "mybootlib", | 
 |         "myothersdklibrary", | 
 |     ], | 
 |     api: { | 
 |         stub_libs: ["mysdklibrary"], | 
 |     }, | 
 |     core_platform_api: { | 
 |         stub_libs: ["mycoreplatform"], | 
 |     }, | 
 |     hidden_api: { | 
 |         annotation_flags: "hiddenapi/annotation-flags.csv", | 
 |         metadata: "hiddenapi/metadata.csv", | 
 |         index: "hiddenapi/index.csv", | 
 |         signature_patterns: "hiddenapi/signature-patterns.csv", | 
 |         filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv", | 
 |         filtered_flags: "hiddenapi/filtered-flags.csv", | 
 |     }, | 
 | } | 
 |  | 
 | java_import { | 
 |     name: "mybootlib", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     jars: ["java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar"], | 
 |     min_sdk_version: "2", | 
 |     permitted_packages: ["mybootlib"], | 
 | } | 
 |  | 
 | java_sdk_library_import { | 
 |     name: "myothersdklibrary", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     shared_library: true, | 
 |     compile_dex: true, | 
 |     permitted_packages: ["myothersdklibrary"], | 
 |     public: { | 
 |         jars: ["sdk_library/public/myothersdklibrary-stubs.jar"], | 
 |         stub_srcs: ["sdk_library/public/myothersdklibrary_stub_sources"], | 
 |         current_api: "sdk_library/public/myothersdklibrary.txt", | 
 |         removed_api: "sdk_library/public/myothersdklibrary-removed.txt", | 
 |         sdk_version: "current", | 
 |     }, | 
 | } | 
 |  | 
 | java_sdk_library_import { | 
 |     name: "mysdklibrary", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     shared_library: false, | 
 |     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_sdk_library_import { | 
 |     name: "mycoreplatform", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     shared_library: true, | 
 |     compile_dex: true, | 
 |     public: { | 
 |         jars: ["sdk_library/public/mycoreplatform-stubs.jar"], | 
 |         stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"], | 
 |         current_api: "sdk_library/public/mycoreplatform.txt", | 
 |         removed_api: "sdk_library/public/mycoreplatform-removed.txt", | 
 |         sdk_version: "current", | 
 |     }, | 
 | } | 
 | 		`), | 
 | 		checkAllCopyRules(copyRules), | 
 | 		snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot), | 
 | 		snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) { | 
 | 			module := result.ModuleForTests("platform-bootclasspath", "android_common") | 
 | 			var rule android.TestingBuildParams | 
 | 			rule = module.Output("out/soong/hiddenapi/hiddenapi-flags.csv") | 
 | 			java.CheckHiddenAPIRuleInputs(t, "monolithic flags", ` | 
 | 				out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/annotation-flags-from-classes.csv | 
 |         out/soong/hiddenapi/hiddenapi-stub-flags.txt | 
 |         snapshot/hiddenapi/annotation-flags.csv | 
 | 			`, rule) | 
 |  | 
 | 			rule = module.Output("out/soong/hiddenapi/hiddenapi-unsupported.csv") | 
 | 			java.CheckHiddenAPIRuleInputs(t, "monolithic metadata", ` | 
 | 				out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/metadata-from-classes.csv | 
 |         snapshot/hiddenapi/metadata.csv | 
 | 			`, rule) | 
 |  | 
 | 			rule = module.Output("out/soong/hiddenapi/hiddenapi-index.csv") | 
 | 			java.CheckHiddenAPIRuleInputs(t, "monolithic index", ` | 
 | 				out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv | 
 |         snapshot/hiddenapi/index.csv | 
 | 			`, rule) | 
 |  | 
 | 			rule = module.Output("out/soong/hiddenapi/hiddenapi-flags.csv.valid") | 
 | 			android.AssertStringDoesContain(t, "verify-overlaps", rule.RuleParams.Command, " snapshot/hiddenapi/filtered-flags.csv:snapshot/hiddenapi/signature-patterns.csv ") | 
 | 		}), | 
 | 		snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot), | 
 | 		snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) { | 
 | 			module := result.ModuleForTests("platform-bootclasspath", "android_common") | 
 | 			rule := module.Output("out/soong/hiddenapi/hiddenapi-flags.csv.valid") | 
 | 			android.AssertStringDoesContain(t, "verify-overlaps", rule.RuleParams.Command, " out/soong/.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv:out/soong/.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv ") | 
 | 		}), | 
 | 		snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot), | 
 | 	) | 
 | } | 
 |  | 
 | func TestSnapshotWithBootClasspathFragment_Contents(t *testing.T) { | 
 | 	t.Run("added-directly", func(t *testing.T) { | 
 | 		testSnapshotWithBootClasspathFragment_Contents(t, ` | 
 | 			sdk { | 
 | 				name: "mysdk", | 
 | 				bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 				java_sdk_libs: [ | 
 | 					// This is not strictly needed as it should be automatically added to the sdk_snapshot as | 
 | 					// a java_sdk_libs module because it is used in the mybootclasspathfragment's | 
 | 					// api.stub_libs property. However, it is specified here to ensure that duplicates are | 
 | 					// correctly deduped. | 
 | 					"mysdklibrary", | 
 | 				], | 
 | 			} | 
 | 		`, ` | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv | 
 | .intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar | 
 | .intermediates/myothersdklibrary.stubs.exportable/android_common/combined/myothersdklibrary.stubs.exportable.jar -> sdk_library/public/myothersdklibrary-stubs.jar | 
 | .intermediates/myothersdklibrary.stubs.source/android_common/exportable/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt | 
 | .intermediates/myothersdklibrary.stubs.source/android_common/exportable/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt | 
 | .intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt | 
 | .intermediates/mycoreplatform.stubs.exportable/android_common/combined/mycoreplatform.stubs.exportable.jar -> sdk_library/public/mycoreplatform-stubs.jar | 
 | .intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt | 
 | .intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt | 
 | `) | 
 | 	}) | 
 |  | 
 | 	copyBootclasspathFragmentFromApexVariantRules := ` | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/index.csv -> hiddenapi/index.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv | 
 | .intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar | 
 | .intermediates/myothersdklibrary.stubs.exportable/android_common/combined/myothersdklibrary.stubs.exportable.jar -> sdk_library/public/myothersdklibrary-stubs.jar | 
 | .intermediates/myothersdklibrary.stubs.source/android_common/exportable/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt | 
 | .intermediates/myothersdklibrary.stubs.source/android_common/exportable/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt | 
 | .intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt | 
 | .intermediates/mycoreplatform.stubs.exportable/android_common/combined/mycoreplatform.stubs.exportable.jar -> sdk_library/public/mycoreplatform-stubs.jar | 
 | .intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt | 
 | .intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt | 
 | ` | 
 | 	t.Run("added-via-apex", func(t *testing.T) { | 
 | 		testSnapshotWithBootClasspathFragment_Contents(t, ` | 
 | 			sdk { | 
 | 				name: "mysdk", | 
 | 				apexes: ["myapex"], | 
 | 			} | 
 | 		`, copyBootclasspathFragmentFromApexVariantRules) | 
 | 	}) | 
 |  | 
 | 	t.Run("added-directly-and-indirectly", func(t *testing.T) { | 
 | 		testSnapshotWithBootClasspathFragment_Contents(t, ` | 
 | 			sdk { | 
 | 				name: "mysdk", | 
 | 				apexes: ["myapex"], | 
 | 				// This is not strictly needed as it should be automatically added to the sdk_snapshot as | 
 | 				// a bootclasspath_fragments module because it is used in the myapex's | 
 | 				// bootclasspath_fragments property. However, it is specified here to ensure that duplicates | 
 | 				// are correctly deduped. | 
 | 				bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 				java_sdk_libs: [ | 
 | 					// This is not strictly needed as it should be automatically added to the sdk_snapshot as | 
 | 					// a java_sdk_libs module because it is used in the mybootclasspathfragment's | 
 | 					// api.stub_libs property. However, it is specified here to ensure that duplicates are | 
 | 					// correctly deduped. | 
 | 					"mysdklibrary", | 
 | 				], | 
 | 			} | 
 | 		`, copyBootclasspathFragmentFromApexVariantRules) | 
 | 	}) | 
 | } | 
 |  | 
 | // TestSnapshotWithBootClasspathFragment_Fragments makes sure that the fragments property of a | 
 | // bootclasspath_fragment is correctly output to the sdk snapshot. | 
 | func TestSnapshotWithBootClasspathFragment_Fragments(t *testing.T) { | 
 | 	result := android.GroupFixturePreparers( | 
 | 		prepareForSdkTestWithJava, | 
 | 		java.PrepareForTestWithJavaDefaultModules, | 
 | 		java.PrepareForTestWithJavaSdkLibraryFiles, | 
 | 		java.FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary"), | 
 | 		java.FixtureConfigureApexBootJars("someapex:mysdklibrary", "myotherapex:myotherlib"), | 
 | 		prepareForSdkTestWithApex, | 
 |  | 
 | 		// Some additional files needed for the myotherapex. | 
 | 		android.FixtureMergeMockFs(android.MockFS{ | 
 | 			"system/sepolicy/apex/myotherapex-file_contexts": nil, | 
 | 			"myotherapex/apex_manifest.json":                 nil, | 
 | 			"myotherapex/Test.java":                          nil, | 
 | 		}), | 
 |  | 
 | 		android.FixtureAddTextFile("myotherapex/Android.bp", ` | 
 | 			apex { | 
 | 				name: "myotherapex", | 
 | 				key: "myapex.key", | 
 | 				min_sdk_version: "2", | 
 | 				bootclasspath_fragments: ["myotherbootclasspathfragment"], | 
 | 			} | 
 |  | 
 | 			bootclasspath_fragment { | 
 | 				name: "myotherbootclasspathfragment", | 
 | 				apex_available: ["myotherapex"], | 
 | 				contents: [ | 
 | 					"myotherlib", | 
 | 				], | 
 | 				hidden_api: { | 
 | 					split_packages: ["*"], | 
 | 				}, | 
 | 			} | 
 |  | 
 | 			java_library { | 
 | 				name: "myotherlib", | 
 | 				apex_available: ["myotherapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				min_sdk_version: "2", | 
 | 				permitted_packages: ["myothersdklibrary"], | 
 | 				compile_dex: true, | 
 | 			} | 
 | 		`), | 
 |  | 
 | 		android.FixtureWithRootAndroidBp(` | 
 | 			sdk { | 
 | 				name: "mysdk", | 
 | 				bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 			} | 
 |  | 
 | 			bootclasspath_fragment { | 
 | 				name: "mybootclasspathfragment", | 
 | 				contents: [ | 
 | 					"mysdklibrary", | 
 | 				], | 
 | 				fragments: [ | 
 | 					{ | 
 | 						apex: "myotherapex", | 
 | 						module: "myotherbootclasspathfragment" | 
 | 					}, | 
 | 				], | 
 | 				hidden_api: { | 
 | 					split_packages: ["*"], | 
 | 				}, | 
 | 			} | 
 |  | 
 | 			java_sdk_library { | 
 | 				name: "mysdklibrary", | 
 | 				srcs: ["Test.java"], | 
 | 				shared_library: false, | 
 | 				public: {enabled: true}, | 
 | 				min_sdk_version: "2", | 
 | 			} | 
 | 		`), | 
 | 	).RunTest(t) | 
 |  | 
 | 	// A preparer to update the test fixture used when processing an unpackage snapshot. | 
 | 	preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("myapex", "mybootclasspathfragment") | 
 |  | 
 | 	CheckSnapshot(t, result, "mysdk", "", | 
 | 		checkAndroidBpContents(` | 
 | // This is auto-generated. DO NOT EDIT. | 
 |  | 
 | apex_contributions_defaults { | 
 |     name: "mysdk.contributions", | 
 |     contents: ["prebuilt_mysdklibrary"], | 
 | } | 
 |  | 
 | prebuilt_bootclasspath_fragment { | 
 |     name: "mybootclasspathfragment", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["//apex_available:platform"], | 
 |     contents: ["mysdklibrary"], | 
 |     fragments: [ | 
 |         { | 
 |             apex: "myotherapex", | 
 |             module: "myotherbootclasspathfragment", | 
 |         }, | 
 |     ], | 
 |     hidden_api: { | 
 |         annotation_flags: "hiddenapi/annotation-flags.csv", | 
 |         metadata: "hiddenapi/metadata.csv", | 
 |         index: "hiddenapi/index.csv", | 
 |         signature_patterns: "hiddenapi/signature-patterns.csv", | 
 |         filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv", | 
 |         filtered_flags: "hiddenapi/filtered-flags.csv", | 
 |     }, | 
 | } | 
 |  | 
 | java_sdk_library_import { | 
 |     name: "mysdklibrary", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["//apex_available:platform"], | 
 |     shared_library: false, | 
 |     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", | 
 |     }, | 
 | } | 
 | 		`), | 
 | 		snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot), | 
 | 		snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot), | 
 | 		snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot), | 
 | 	) | 
 | } | 
 |  | 
 | // Test that bootclasspath_fragment works with sdk. | 
 | func TestBasicSdkWithBootclasspathFragment(t *testing.T) { | 
 | 	android.GroupFixturePreparers( | 
 | 		prepareForSdkTestWithApex, | 
 | 		prepareForSdkTestWithJava, | 
 | 		android.FixtureMergeMockFs(android.MockFS{ | 
 | 			"java/mybootlib.jar":                nil, | 
 | 			"hiddenapi/annotation-flags.csv":    nil, | 
 | 			"hiddenapi/index.csv":               nil, | 
 | 			"hiddenapi/metadata.csv":            nil, | 
 | 			"hiddenapi/signature-patterns.csv":  nil, | 
 | 			"hiddenapi/filtered-stub-flags.csv": nil, | 
 | 			"hiddenapi/filtered-flags.csv":      nil, | 
 | 		}), | 
 | 		android.FixtureWithRootAndroidBp(` | 
 | 		sdk { | 
 | 			name: "mysdk", | 
 | 			bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 		} | 
 |  | 
 | 		bootclasspath_fragment { | 
 | 			name: "mybootclasspathfragment", | 
 | 			image_name: "art", | 
 | 			contents: ["mybootlib"], | 
 | 			apex_available: ["myapex"], | 
 | 			hidden_api: { | 
 | 				split_packages: ["*"], | 
 | 			}, | 
 | 		} | 
 |  | 
 | 		java_library { | 
 | 			name: "mybootlib", | 
 | 			apex_available: ["myapex"], | 
 | 			srcs: ["Test.java"], | 
 | 			system_modules: "none", | 
 | 			sdk_version: "none", | 
 | 			min_sdk_version: "1", | 
 | 			compile_dex: true, | 
 | 		} | 
 |  | 
 | 		prebuilt_bootclasspath_fragment { | 
 | 			name: "mybootclasspathfragment", | 
 | 			prefer: false, | 
 | 			visibility: ["//visibility:public"], | 
 | 			apex_available: [ | 
 | 				"myapex", | 
 | 			], | 
 | 			image_name: "art", | 
 | 			contents: ["mybootlib"], | 
 | 			hidden_api: { | 
 | 				annotation_flags: "hiddenapi/annotation-flags.csv", | 
 | 				metadata: "hiddenapi/metadata.csv", | 
 | 				index: "hiddenapi/index.csv", | 
 | 				signature_patterns: "hiddenapi/signature-patterns.csv", | 
 | 				filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv", | 
 | 				filtered_flags: "hiddenapi/filtered-flags.csv", | 
 | 			}, | 
 | 		} | 
 |  | 
 | 		java_import { | 
 | 			name: "mybootlib", | 
 | 			visibility: ["//visibility:public"], | 
 | 			apex_available: ["com.android.art"], | 
 | 			jars: ["java/mybootlib.jar"], | 
 | 		} | 
 | 	`), | 
 | 	).RunTest(t) | 
 | } | 
 |  | 
 | func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { | 
 | 	result := android.GroupFixturePreparers( | 
 | 		prepareForSdkTestWithJava, | 
 | 		java.PrepareForTestWithJavaDefaultModules, | 
 | 		java.PrepareForTestWithJavaSdkLibraryFiles, | 
 | 		java.FixtureWithLastReleaseApis("mysdklibrary", "mynewlibrary"), | 
 | 		java.FixtureConfigureApexBootJars("myapex:mybootlib", "myapex:mynewlibrary"), | 
 | 		prepareForSdkTestWithApex, | 
 |  | 
 | 		// Add a platform_bootclasspath that depends on the fragment. | 
 | 		fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"), | 
 |  | 
 | 		android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"), | 
 |  | 
 | 		android.MockFS{ | 
 | 			"my-blocked.txt":                   nil, | 
 | 			"my-max-target-o-low-priority.txt": nil, | 
 | 			"my-max-target-p.txt":              nil, | 
 | 			"my-max-target-q.txt":              nil, | 
 | 			"my-max-target-r-low-priority.txt": nil, | 
 | 			"my-removed.txt":                   nil, | 
 | 			"my-unsupported-packages.txt":      nil, | 
 | 			"my-unsupported.txt":               nil, | 
 | 			"my-new-max-target-q.txt":          nil, | 
 | 		}.AddToFixture(), | 
 | 		android.FixtureWithRootAndroidBp(` | 
 | 			sdk { | 
 | 				name: "mysdk", | 
 | 				bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 			} | 
 |  | 
 | 			apex { | 
 | 				name: "myapex", | 
 | 				key: "myapex.key", | 
 | 				min_sdk_version: "1", | 
 | 				bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 			} | 
 |  | 
 | 			bootclasspath_fragment { | 
 | 				name: "mybootclasspathfragment", | 
 | 				apex_available: ["myapex"], | 
 | 				contents: ["mybootlib", "mynewlibrary"], | 
 | 				api: { | 
 | 					stub_libs: ["mysdklibrary"], | 
 | 				}, | 
 | 				hidden_api: { | 
 | 					unsupported: [ | 
 | 							"my-unsupported.txt", | 
 | 					], | 
 | 					removed: [ | 
 | 							"my-removed.txt", | 
 | 					], | 
 | 					max_target_r_low_priority: [ | 
 | 							"my-max-target-r-low-priority.txt", | 
 | 					], | 
 | 					max_target_q: [ | 
 | 							"my-max-target-q.txt", | 
 | 					], | 
 | 					max_target_p: [ | 
 | 							"my-max-target-p.txt", | 
 | 					], | 
 | 					max_target_o_low_priority: [ | 
 | 							"my-max-target-o-low-priority.txt", | 
 | 					], | 
 | 					blocked: [ | 
 | 							"my-blocked.txt", | 
 | 					], | 
 | 					unsupported_packages: [ | 
 | 							"my-unsupported-packages.txt", | 
 | 					], | 
 | 					split_packages: ["sdklibrary"], | 
 | 					package_prefixes: ["sdklibrary.all.mine"], | 
 | 					single_packages: ["sdklibrary.mine"], | 
 | 				}, | 
 | 			} | 
 |  | 
 | 			java_library { | 
 | 				name: "mybootlib", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				system_modules: "none", | 
 | 				sdk_version: "none", | 
 | 				min_sdk_version: "1", | 
 | 				compile_dex: true, | 
 | 				permitted_packages: ["mybootlib"], | 
 | 			} | 
 |  | 
 | 			java_sdk_library { | 
 | 				name: "mysdklibrary", | 
 | 				srcs: ["Test.java"], | 
 | 				compile_dex: true, | 
 | 				public: {enabled: true}, | 
 | 				permitted_packages: ["mysdklibrary"], | 
 | 				min_sdk_version: "current", | 
 | 			} | 
 |  | 
 | 			java_sdk_library { | 
 | 				name: "mynewlibrary", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				min_sdk_version: "10", | 
 | 				compile_dex: true, | 
 | 				public: {enabled: true}, | 
 | 				permitted_packages: ["mysdklibrary"], | 
 | 				hidden_api: { | 
 | 					max_target_q: [ | 
 | 							"my-new-max-target-q.txt", | 
 | 					], | 
 | 					split_packages: ["sdklibrary", "newlibrary"], | 
 | 					package_prefixes: ["newlibrary.all.mine"], | 
 | 					single_packages: ["newlibrary.mine"], | 
 | 				}, | 
 | 			} | 
 | 		`), | 
 | 	).RunTest(t) | 
 |  | 
 | 	// A preparer to update the test fixture used when processing an unpackage snapshot. | 
 | 	preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("myapex", "mybootclasspathfragment") | 
 |  | 
 | 	CheckSnapshot(t, result, "mysdk", "", | 
 | 		checkAndroidBpContents(` | 
 | // This is auto-generated. DO NOT EDIT. | 
 |  | 
 | apex_contributions_defaults { | 
 |     name: "mysdk.contributions", | 
 |     contents: [ | 
 |         "prebuilt_mynewlibrary", | 
 |         "prebuilt_mysdklibrary", | 
 |     ], | 
 | } | 
 |  | 
 | prebuilt_bootclasspath_fragment { | 
 |     name: "mybootclasspathfragment", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     contents: [ | 
 |         "mybootlib", | 
 |         "mynewlibrary", | 
 |     ], | 
 |     api: { | 
 |         stub_libs: ["mysdklibrary"], | 
 |     }, | 
 |     hidden_api: { | 
 |         unsupported: ["hiddenapi/my-unsupported.txt"], | 
 |         removed: ["hiddenapi/my-removed.txt"], | 
 |         max_target_r_low_priority: ["hiddenapi/my-max-target-r-low-priority.txt"], | 
 |         max_target_q: [ | 
 |             "hiddenapi/my-max-target-q.txt", | 
 |             "hiddenapi/my-new-max-target-q.txt", | 
 |         ], | 
 |         max_target_p: ["hiddenapi/my-max-target-p.txt"], | 
 |         max_target_o_low_priority: ["hiddenapi/my-max-target-o-low-priority.txt"], | 
 |         blocked: ["hiddenapi/my-blocked.txt"], | 
 |         unsupported_packages: ["hiddenapi/my-unsupported-packages.txt"], | 
 |         annotation_flags: "hiddenapi/annotation-flags.csv", | 
 |         metadata: "hiddenapi/metadata.csv", | 
 |         index: "hiddenapi/index.csv", | 
 |         signature_patterns: "hiddenapi/signature-patterns.csv", | 
 |         filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv", | 
 |         filtered_flags: "hiddenapi/filtered-flags.csv", | 
 |     }, | 
 | } | 
 |  | 
 | java_import { | 
 |     name: "mybootlib", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     jars: ["java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar"], | 
 |     min_sdk_version: "1", | 
 |     permitted_packages: ["mybootlib"], | 
 | } | 
 |  | 
 | java_sdk_library_import { | 
 |     name: "mynewlibrary", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     shared_library: true, | 
 |     compile_dex: true, | 
 |     permitted_packages: ["mysdklibrary"], | 
 |     public: { | 
 |         jars: ["sdk_library/public/mynewlibrary-stubs.jar"], | 
 |         stub_srcs: ["sdk_library/public/mynewlibrary_stub_sources"], | 
 |         current_api: "sdk_library/public/mynewlibrary.txt", | 
 |         removed_api: "sdk_library/public/mynewlibrary-removed.txt", | 
 |         sdk_version: "current", | 
 |     }, | 
 | } | 
 |  | 
 | java_sdk_library_import { | 
 |     name: "mysdklibrary", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["//apex_available:platform"], | 
 |     shared_library: true, | 
 |     compile_dex: true, | 
 |     permitted_packages: ["mysdklibrary"], | 
 |     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", | 
 |     }, | 
 | } | 
 | `), | 
 | 		checkAllCopyRules(` | 
 | my-unsupported.txt -> hiddenapi/my-unsupported.txt | 
 | my-removed.txt -> hiddenapi/my-removed.txt | 
 | my-max-target-r-low-priority.txt -> hiddenapi/my-max-target-r-low-priority.txt | 
 | my-max-target-q.txt -> hiddenapi/my-max-target-q.txt | 
 | my-new-max-target-q.txt -> hiddenapi/my-new-max-target-q.txt | 
 | my-max-target-p.txt -> hiddenapi/my-max-target-p.txt | 
 | my-max-target-o-low-priority.txt -> hiddenapi/my-max-target-o-low-priority.txt | 
 | my-blocked.txt -> hiddenapi/my-blocked.txt | 
 | my-unsupported-packages.txt -> hiddenapi/my-unsupported-packages.txt | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv | 
 | .intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar | 
 | .intermediates/mynewlibrary.stubs.exportable/android_common/combined/mynewlibrary.stubs.exportable.jar -> sdk_library/public/mynewlibrary-stubs.jar | 
 | .intermediates/mynewlibrary.stubs.source/android_common/exportable/mynewlibrary.stubs.source_api.txt -> sdk_library/public/mynewlibrary.txt | 
 | .intermediates/mynewlibrary.stubs.source/android_common/exportable/mynewlibrary.stubs.source_removed.txt -> sdk_library/public/mynewlibrary-removed.txt | 
 | .intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt | 
 | `), | 
 | 		snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot), | 
 | 		snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot), | 
 | 		snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot), | 
 | 	) | 
 | } | 
 |  | 
 | func testSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T, targetBuildRelease string, | 
 | 	expectedSdkSnapshot string, | 
 | 	expectedCopyRules string, | 
 | 	expectedStubFlagsInputs []string, | 
 | 	suffix string) { | 
 |  | 
 | 	result := android.GroupFixturePreparers( | 
 | 		prepareForSdkTestWithJava, | 
 | 		java.PrepareForTestWithJavaDefaultModules, | 
 | 		java.PrepareForTestWithJavaSdkLibraryFiles, | 
 | 		java.FixtureWithLastReleaseApis("mysdklibrary", "mynewsdklibrary"), | 
 | 		java.FixtureConfigureApexBootJars("myapex:mysdklibrary", "myapex:mynewsdklibrary"), | 
 | 		prepareForSdkTestWithApex, | 
 |  | 
 | 		// Add a platform_bootclasspath that depends on the fragment. | 
 | 		fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"), | 
 |  | 
 | 		android.FixtureMergeEnv(map[string]string{ | 
 | 			"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease, | 
 | 		}), | 
 | 		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { | 
 | 			variables.Platform_version_active_codenames = []string{"VanillaIceCream"} | 
 | 		}), | 
 |  | 
 | 		android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"), | 
 |  | 
 | 		android.FixtureWithRootAndroidBp(` | 
 | 			sdk { | 
 | 				name: "mysdk", | 
 | 				apexes: ["myapex"], | 
 | 			} | 
 |  | 
 | 			apex { | 
 | 				name: "myapex", | 
 | 				key: "myapex.key", | 
 | 				min_sdk_version: "S", | 
 | 				bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 			} | 
 |  | 
 | 			bootclasspath_fragment { | 
 | 				name: "mybootclasspathfragment", | 
 | 				apex_available: ["myapex"], | 
 | 				contents: [ | 
 | 					"mysdklibrary", | 
 | 					"mynewsdklibrary", | 
 | 				], | 
 |  | 
 | 				hidden_api: { | 
 | 					split_packages: [], | 
 | 				}, | 
 | 			} | 
 |  | 
 | 			java_sdk_library { | 
 | 				name: "mysdklibrary", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				shared_library: false, | 
 | 				public: {enabled: true}, | 
 | 				min_sdk_version: "S", | 
 | 			} | 
 |  | 
 | 			java_sdk_library { | 
 | 				name: "mynewsdklibrary", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				compile_dex: true, | 
 | 				public: {enabled: true}, | 
 | 				min_sdk_version: "Tiramisu", | 
 | 				permitted_packages: ["mynewsdklibrary"], | 
 | 			} | 
 | 		`), | 
 | 	).RunTest(t) | 
 |  | 
 | 	bcpf := result.ModuleForTests("mybootclasspathfragment", "android_common") | 
 | 	rule := bcpf.Output("out/soong/.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi" + suffix + "/stub-flags.csv") | 
 | 	android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", android.SortedUniqueStrings(expectedStubFlagsInputs), android.SortedUniquePaths(rule.Implicits)) | 
 |  | 
 | 	CheckSnapshot(t, result, "mysdk", "", | 
 | 		checkAndroidBpContents(expectedSdkSnapshot), | 
 | 		checkAllCopyRules(expectedCopyRules), | 
 | 	) | 
 | } | 
 |  | 
 | func TestSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T) { | 
 | 	t.Run("target S build", func(t *testing.T) { | 
 | 		expectedSnapshot := ` | 
 | // This is auto-generated. DO NOT EDIT. | 
 |  | 
 | prebuilt_bootclasspath_fragment { | 
 |     name: "mybootclasspathfragment", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     contents: ["mysdklibrary"], | 
 |     hidden_api: { | 
 |         annotation_flags: "hiddenapi/annotation-flags.csv", | 
 |         metadata: "hiddenapi/metadata.csv", | 
 |         index: "hiddenapi/index.csv", | 
 |         stub_flags: "hiddenapi/stub-flags.csv", | 
 |         all_flags: "hiddenapi/all-flags.csv", | 
 |     }, | 
 | } | 
 |  | 
 | java_sdk_library_import { | 
 |     name: "mysdklibrary", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     shared_library: false, | 
 |     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", | 
 |     }, | 
 | } | 
 | ` | 
 | 		expectedCopyRules := ` | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/annotation-flags.csv -> hiddenapi/annotation-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/metadata.csv -> hiddenapi/metadata.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/index.csv -> hiddenapi/index.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/stub-flags.csv -> hiddenapi/stub-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/all-flags.csv -> hiddenapi/all-flags.csv | 
 | .intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt | 
 | ` | 
 |  | 
 | 		// On S the stub flags should only be generated from mysdklibrary as mynewsdklibrary is not part | 
 | 		// of the snapshot. | 
 | 		expectedStubFlagsInputs := []string{ | 
 | 			"out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar", | 
 | 			"out/soong/.intermediates/mysdklibrary.impl/android_common/aligned/mysdklibrary.jar", | 
 | 		} | 
 |  | 
 | 		testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "S", | 
 | 			expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "-for-sdk-snapshot") | 
 | 	}) | 
 |  | 
 | 	t.Run("target-Tiramisu-build", func(t *testing.T) { | 
 | 		expectedSnapshot := ` | 
 | // This is auto-generated. DO NOT EDIT. | 
 |  | 
 | prebuilt_bootclasspath_fragment { | 
 |     name: "mybootclasspathfragment", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     contents: [ | 
 |         "mysdklibrary", | 
 |         "mynewsdklibrary", | 
 |     ], | 
 |     hidden_api: { | 
 |         annotation_flags: "hiddenapi/annotation-flags.csv", | 
 |         metadata: "hiddenapi/metadata.csv", | 
 |         index: "hiddenapi/index.csv", | 
 |         signature_patterns: "hiddenapi/signature-patterns.csv", | 
 |         filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv", | 
 |         filtered_flags: "hiddenapi/filtered-flags.csv", | 
 |     }, | 
 | } | 
 |  | 
 | java_sdk_library_import { | 
 |     name: "mysdklibrary", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     shared_library: false, | 
 |     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_sdk_library_import { | 
 |     name: "mynewsdklibrary", | 
 |     prefer: false, | 
 |     visibility: ["//visibility:public"], | 
 |     apex_available: ["myapex"], | 
 |     shared_library: true, | 
 |     compile_dex: true, | 
 |     permitted_packages: ["mynewsdklibrary"], | 
 |     public: { | 
 |         jars: ["sdk_library/public/mynewsdklibrary-stubs.jar"], | 
 |         stub_srcs: ["sdk_library/public/mynewsdklibrary_stub_sources"], | 
 |         current_api: "sdk_library/public/mynewsdklibrary.txt", | 
 |         removed_api: "sdk_library/public/mynewsdklibrary-removed.txt", | 
 |         sdk_version: "current", | 
 |     }, | 
 | } | 
 | ` | 
 | 		expectedCopyRules := ` | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/index.csv -> hiddenapi/index.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv | 
 | .intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv | 
 | .intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt | 
 | .intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt | 
 | .intermediates/mynewsdklibrary.stubs.exportable/android_common/combined/mynewsdklibrary.stubs.exportable.jar -> sdk_library/public/mynewsdklibrary-stubs.jar | 
 | .intermediates/mynewsdklibrary.stubs.source/android_common/exportable/mynewsdklibrary.stubs.source_api.txt -> sdk_library/public/mynewsdklibrary.txt | 
 | .intermediates/mynewsdklibrary.stubs.source/android_common/exportable/mynewsdklibrary.stubs.source_removed.txt -> sdk_library/public/mynewsdklibrary-removed.txt | 
 | ` | 
 |  | 
 | 		// On tiramisu the stub flags should be generated from both mynewsdklibrary and mysdklibrary as | 
 | 		// they are both part of the snapshot. | 
 | 		expectedStubFlagsInputs := []string{ | 
 | 			"out/soong/.intermediates/mynewsdklibrary.stubs.exportable/android_common/dex/mynewsdklibrary.stubs.exportable.jar", | 
 | 			"out/soong/.intermediates/mynewsdklibrary.impl/android_common/aligned/mynewsdklibrary.jar", | 
 | 			"out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar", | 
 | 			"out/soong/.intermediates/mysdklibrary.impl/android_common/aligned/mysdklibrary.jar", | 
 | 		} | 
 |  | 
 | 		testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "Tiramisu", | 
 | 			expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "") | 
 | 	}) | 
 | } | 
 |  | 
 | func TestSnapshotWithEmptyBootClasspathFragment(t *testing.T) { | 
 | 	result := android.GroupFixturePreparers( | 
 | 		prepareForSdkTestWithJava, | 
 | 		java.PrepareForTestWithJavaDefaultModules, | 
 | 		java.PrepareForTestWithJavaSdkLibraryFiles, | 
 | 		java.FixtureWithLastReleaseApis("mysdklibrary", "mynewsdklibrary"), | 
 | 		java.FixtureConfigureApexBootJars("myapex:mysdklibrary", "myapex:mynewsdklibrary"), | 
 | 		prepareForSdkTestWithApex, | 
 | 		// Add a platform_bootclasspath that depends on the fragment. | 
 | 		fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"), | 
 | 		android.FixtureMergeEnv(map[string]string{ | 
 | 			"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S", | 
 | 		}), | 
 | 		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { | 
 | 			variables.Platform_version_active_codenames = []string{"VanillaIceCream"} | 
 | 		}), | 
 | 		android.FixtureWithRootAndroidBp(` | 
 | 			sdk { | 
 | 				name: "mysdk", | 
 | 				apexes: ["myapex"], | 
 | 			} | 
 | 			apex { | 
 | 				name: "myapex", | 
 | 				key: "myapex.key", | 
 | 				min_sdk_version: "S", | 
 | 				bootclasspath_fragments: ["mybootclasspathfragment"], | 
 | 			} | 
 | 			bootclasspath_fragment { | 
 | 				name: "mybootclasspathfragment", | 
 | 				apex_available: ["myapex"], | 
 | 				contents: ["mysdklibrary", "mynewsdklibrary"], | 
 | 				hidden_api: { | 
 | 					split_packages: [], | 
 | 				}, | 
 | 			} | 
 | 			java_sdk_library { | 
 | 				name: "mysdklibrary", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				shared_library: false, | 
 | 				public: {enabled: true}, | 
 | 				min_sdk_version: "Tiramisu", | 
 | 			} | 
 | 			java_sdk_library { | 
 | 				name: "mynewsdklibrary", | 
 | 				apex_available: ["myapex"], | 
 | 				srcs: ["Test.java"], | 
 | 				compile_dex: true, | 
 | 				public: {enabled: true}, | 
 | 				min_sdk_version: "Tiramisu", | 
 | 				permitted_packages: ["mynewsdklibrary"], | 
 | 			} | 
 | 		`), | 
 | 	).RunTest(t) | 
 |  | 
 | 	CheckSnapshot(t, result, "mysdk", "", checkAndroidBpContents(`// This is auto-generated. DO NOT EDIT.`)) | 
 | } |