Merge "Reimplement verify_uses_libraries.sh in manifest_check.py."
diff --git a/apex/apex.go b/apex/apex.go
index e5b5c92..3db20f4 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -102,6 +102,9 @@
 	// List of prebuilt files that are embedded inside this APEX bundle.
 	Prebuilts []string
 
+	// List of platform_compat_config files that are embedded inside this APEX bundle.
+	Compat_configs []string
+
 	// List of BPF programs inside this APEX bundle.
 	Bpfs []string
 
@@ -549,20 +552,21 @@
 }
 
 var (
-	androidAppTag  = dependencyTag{name: "androidApp", payload: true}
-	bpfTag         = dependencyTag{name: "bpf", payload: true}
-	certificateTag = dependencyTag{name: "certificate"}
-	executableTag  = dependencyTag{name: "executable", payload: true}
-	fsTag          = dependencyTag{name: "filesystem", payload: true}
-	bootImageTag   = dependencyTag{name: "bootImage", payload: true}
-	javaLibTag     = dependencyTag{name: "javaLib", payload: true}
-	jniLibTag      = dependencyTag{name: "jniLib", payload: true}
-	keyTag         = dependencyTag{name: "key"}
-	prebuiltTag    = dependencyTag{name: "prebuilt", payload: true}
-	rroTag         = dependencyTag{name: "rro", payload: true}
-	sharedLibTag   = dependencyTag{name: "sharedLib", payload: true}
-	testForTag     = dependencyTag{name: "test for"}
-	testTag        = dependencyTag{name: "test", payload: true}
+	androidAppTag    = dependencyTag{name: "androidApp", payload: true}
+	bpfTag           = dependencyTag{name: "bpf", payload: true}
+	certificateTag   = dependencyTag{name: "certificate"}
+	executableTag    = dependencyTag{name: "executable", payload: true}
+	fsTag            = dependencyTag{name: "filesystem", payload: true}
+	bootImageTag     = dependencyTag{name: "bootImage", payload: true}
+	compatConfigsTag = dependencyTag{name: "compatConfig", payload: true}
+	javaLibTag       = dependencyTag{name: "javaLib", payload: true}
+	jniLibTag        = dependencyTag{name: "jniLib", payload: true}
+	keyTag           = dependencyTag{name: "key"}
+	prebuiltTag      = dependencyTag{name: "prebuilt", payload: true}
+	rroTag           = dependencyTag{name: "rro", payload: true}
+	sharedLibTag     = dependencyTag{name: "sharedLib", payload: true}
+	testForTag       = dependencyTag{name: "test for"}
+	testTag          = dependencyTag{name: "test", payload: true}
 )
 
 // TODO(jiyong): shorten this function signature
@@ -737,6 +741,7 @@
 	ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
 	ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
 	ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
+	ctx.AddFarVariationDependencies(commonVariation, compatConfigsTag, a.properties.Compat_configs...)
 
 	if a.artApex {
 		// With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
@@ -1735,10 +1740,14 @@
 			case prebuiltTag:
 				if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
 					filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
-				} else if prebuilt, ok := child.(java.PlatformCompatConfigIntf); ok {
-					filesInfo = append(filesInfo, apexFileForCompatConfig(ctx, prebuilt, depName))
 				} else {
-					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc and not a platform_compat_config module", depName)
+					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
+				}
+			case compatConfigsTag:
+				if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok {
+					filesInfo = append(filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName))
+				} else {
+					ctx.PropertyErrorf("compat_configs", "%q is not a platform_compat_config module", depName)
 				}
 			case testTag:
 				if ccTest, ok := child.(*cc.Module); ok {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index dd290d3..21cf5df 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -5989,11 +5989,13 @@
 }
 
 func TestCompatConfig(t *testing.T) {
-	ctx := testApex(t, `
+	result := apexFixtureFactory.
+		Extend(java.PrepareForTestWithPlatformCompatConfig).
+		RunTestWithBp(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
-			prebuilts: ["myjar-platform-compat-config"],
+			compat_configs: ["myjar-platform-compat-config"],
 			java_libs: ["myjar"],
 			updatable: false,
 		}
@@ -6017,6 +6019,7 @@
 			apex_available: [ "myapex" ],
 		}
 	`)
+	ctx := result.TestContext
 	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
 		"etc/compatconfig/myjar-platform-compat-config.xml",
 		"javalib/myjar.jar",
diff --git a/bazel/Android.bp b/bazel/Android.bp
index 117fd46..b7c185a 100644
--- a/bazel/Android.bp
+++ b/bazel/Android.bp
@@ -12,6 +12,7 @@
     ],
     testSrcs: [
         "aquery_test.go",
+        "properties_test.go",
     ],
     pluginFor: [
         "soong_build",
diff --git a/bazel/properties.go b/bazel/properties.go
index a5ffa55..cb47758 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -14,7 +14,10 @@
 
 package bazel
 
-import "fmt"
+import (
+	"fmt"
+	"sort"
+)
 
 type bazelModuleProperties struct {
 	// The label of the Bazel target replacing this Soong module.
@@ -66,6 +69,28 @@
 	}
 }
 
+func UniqueBazelLabels(originalLabels []Label) []Label {
+	uniqueLabelsSet := make(map[Label]bool)
+	for _, l := range originalLabels {
+		uniqueLabelsSet[l] = true
+	}
+	var uniqueLabels []Label
+	for l, _ := range uniqueLabelsSet {
+		uniqueLabels = append(uniqueLabels, l)
+	}
+	sort.SliceStable(uniqueLabels, func(i, j int) bool {
+		return uniqueLabels[i].Label < uniqueLabels[j].Label
+	})
+	return uniqueLabels
+}
+
+func UniqueBazelLabelList(originalLabelList LabelList) LabelList {
+	var uniqueLabelList LabelList
+	uniqueLabelList.Includes = UniqueBazelLabels(originalLabelList.Includes)
+	uniqueLabelList.Excludes = UniqueBazelLabels(originalLabelList.Excludes)
+	return uniqueLabelList
+}
+
 // StringListAttribute corresponds to the string_list Bazel attribute type with
 // support for additional metadata, like configurations.
 type StringListAttribute struct {
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
new file mode 100644
index 0000000..0fcb904
--- /dev/null
+++ b/bazel/properties_test.go
@@ -0,0 +1,89 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// 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 bazel
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestUniqueBazelLabels(t *testing.T) {
+	testCases := []struct {
+		originalLabels       []Label
+		expectedUniqueLabels []Label
+	}{
+		{
+			originalLabels: []Label{
+				{Label: "a"},
+				{Label: "b"},
+				{Label: "a"},
+				{Label: "c"},
+			},
+			expectedUniqueLabels: []Label{
+				{Label: "a"},
+				{Label: "b"},
+				{Label: "c"},
+			},
+		},
+	}
+	for _, tc := range testCases {
+		actualUniqueLabels := UniqueBazelLabels(tc.originalLabels)
+		if !reflect.DeepEqual(tc.expectedUniqueLabels, actualUniqueLabels) {
+			t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabels, actualUniqueLabels)
+		}
+	}
+}
+
+func TestUniqueBazelLabelList(t *testing.T) {
+	testCases := []struct {
+		originalLabelList       LabelList
+		expectedUniqueLabelList LabelList
+	}{
+		{
+			originalLabelList: LabelList{
+				Includes: []Label{
+					{Label: "a"},
+					{Label: "b"},
+					{Label: "a"},
+					{Label: "c"},
+				},
+				Excludes: []Label{
+					{Label: "x"},
+					{Label: "x"},
+					{Label: "y"},
+					{Label: "z"},
+				},
+			},
+			expectedUniqueLabelList: LabelList{
+				Includes: []Label{
+					{Label: "a"},
+					{Label: "b"},
+					{Label: "c"},
+				},
+				Excludes: []Label{
+					{Label: "x"},
+					{Label: "y"},
+					{Label: "z"},
+				},
+			},
+		},
+	}
+	for _, tc := range testCases {
+		actualUniqueLabelList := UniqueBazelLabelList(tc.originalLabelList)
+		if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
+			t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
+		}
+	}
+}
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 876e189..372a610 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -62,6 +62,10 @@
 	// Optional kernel commandline
 	Cmdline *string
 
+	// File that contains bootconfig parameters. This can be set only when `vendor_boot` is true
+	// and `header_version` is greater than or equal to 4.
+	Bootconfig *string `android:"arch_variant,path"`
+
 	// When set to true, sign the image with avbtool. Default is false.
 	Use_avb *bool
 
@@ -189,6 +193,19 @@
 		return output
 	}
 
+	bootconfig := proptools.String(b.properties.Bootconfig)
+	if bootconfig != "" {
+		if !vendor {
+			ctx.PropertyErrorf("bootconfig", "requires vendor_boot: true")
+			return output
+		}
+		if verNum < 4 {
+			ctx.PropertyErrorf("bootconfig", "requires header_version: 4 or later")
+			return output
+		}
+		cmd.FlagWithInput("--vendor_bootconfig ", android.PathForModuleSrc(ctx, bootconfig))
+	}
+
 	flag := "--output "
 	if vendor {
 		flag = "--vendor_boot "
diff --git a/java/app_test.go b/java/app_test.go
index 040ca19..c189ee5 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -28,70 +28,68 @@
 	"android/soong/cc"
 )
 
-var (
-	resourceFiles = []string{
+// testAppConfig is a legacy way of creating a test Config for testing java app modules.
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
+func testAppConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
+	return testConfig(env, bp, fs)
+}
+
+// testApp runs tests using the javaFixtureFactory
+//
+// See testJava for an explanation as to how to stop using this deprecated method.
+//
+// deprecated
+func testApp(t *testing.T, bp string) *android.TestContext {
+	t.Helper()
+	result := javaFixtureFactory.RunTestWithBp(t, bp)
+	return result.TestContext
+}
+
+func TestApp(t *testing.T) {
+	resourceFiles := []string{
 		"res/layout/layout.xml",
 		"res/values/strings.xml",
 		"res/values-en-rUS/strings.xml",
 	}
 
-	compiledResourceFiles = []string{
+	compiledResourceFiles := []string{
 		"aapt2/res/layout_layout.xml.flat",
 		"aapt2/res/values_strings.arsc.flat",
 		"aapt2/res/values-en-rUS_strings.arsc.flat",
 	}
-)
 
-func testAppConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
-	appFS := map[string][]byte{}
-	for k, v := range fs {
-		appFS[k] = v
-	}
-
-	for _, file := range resourceFiles {
-		appFS[file] = nil
-	}
-
-	return testConfig(env, bp, appFS)
-}
-
-func testApp(t *testing.T, bp string) *android.TestContext {
-	config := testAppConfig(nil, bp, nil)
-
-	ctx := testContext(config)
-
-	run(t, ctx, config)
-
-	return ctx
-}
-
-func TestApp(t *testing.T) {
 	for _, moduleType := range []string{"android_app", "android_library"} {
 		t.Run(moduleType, func(t *testing.T) {
-			ctx := testApp(t, moduleType+` {
+			result := javaFixtureFactory.Extend(
+				android.FixtureModifyMockFS(func(fs android.MockFS) {
+					for _, file := range resourceFiles {
+						fs[file] = nil
+					}
+				}),
+			).RunTestWithBp(t, moduleType+` {
 					name: "foo",
 					srcs: ["a.java"],
 					sdk_version: "current"
 				}
 			`)
 
-			foo := ctx.ModuleForTests("foo", "android_common")
+			foo := result.ModuleForTests("foo", "android_common")
 
 			var expectedLinkImplicits []string
 
 			manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
 			expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
 
-			frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
+			frameworkRes := result.ModuleForTests("framework-res", "android_common")
 			expectedLinkImplicits = append(expectedLinkImplicits,
 				frameworkRes.Output("package-res.apk").Output.String())
 
 			// Test the mapping from input files to compiled output file names
 			compile := foo.Output(compiledResourceFiles[0])
-			if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
-				t.Errorf("expected aapt2 compile inputs expected:\n  %#v\n got:\n  %#v",
-					resourceFiles, compile.Inputs.Strings())
-			}
+			android.AssertDeepEquals(t, "aapt2 compile inputs", resourceFiles, compile.Inputs.Strings())
 
 			compiledResourceOutputs := compile.Outputs.Strings()
 			sort.Strings(compiledResourceOutputs)
@@ -102,11 +100,8 @@
 			expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
 
 			// Check that the link rule uses
-			res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
-			if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
-				t.Errorf("expected aapt2 link implicits expected:\n  %#v\n got:\n  %#v",
-					expectedLinkImplicits, res.Implicits.Strings())
-			}
+			res := result.ModuleForTests("foo", "android_common").Output("package-res.apk")
+			android.AssertDeepEquals(t, "aapt2 link implicits", expectedLinkImplicits, res.Implicits.Strings())
 		})
 	}
 }
diff --git a/java/java_test.go b/java/java_test.go
index 670eefc..9ef23e9 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -65,6 +65,7 @@
 		ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
 	}),
 	javaMockFS().AddToFixture(),
+	PrepareForTestWithJavaSdkLibraryFiles,
 	dexpreopt.PrepareForTestWithDexpreopt,
 )
 
@@ -147,7 +148,11 @@
 // deprecated
 func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) {
 	t.Helper()
-	return testJavaErrorWithConfig(t, pattern, testConfig(nil, bp, nil))
+	result := javaFixtureFactory.
+		Extend(dexpreopt.PrepareForTestWithDexpreopt).
+		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
+		RunTestWithBp(t, bp)
+	return result.TestContext, result.Config
 }
 
 // testJavaErrorWithConfig is a legacy way of running tests of java modules that expect errors.
@@ -895,7 +900,7 @@
 		allowList                  []string
 	}
 
-	createTestConfig := func(info testConfigInfo) android.Config {
+	createPreparer := func(info testConfigInfo) android.FixturePreparer {
 		bpFileTemplate := `
 			java_library {
 				name: "foo",
@@ -918,58 +923,68 @@
 			info.libraryType,
 			partitionToBpOption(info.toPartition))
 
-		config := testConfig(nil, bpFile, nil)
-		configVariables := config.TestProductVariables
+		return android.GroupFixturePreparers(
+			android.FixtureWithRootAndroidBp(bpFile),
+			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+				variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
+				if info.enforceVendorInterface {
+					variables.DeviceVndkVersion = proptools.StringPtr("current")
+				}
+				variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
+				variables.InterPartitionJavaLibraryAllowList = info.allowList
+			}),
+		)
+	}
 
-		configVariables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
-		if info.enforceVendorInterface {
-			configVariables.DeviceVndkVersion = proptools.StringPtr("current")
-		}
-		configVariables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
-		configVariables.InterPartitionJavaLibraryAllowList = info.allowList
-
-		return config
+	runTest := func(t *testing.T, info testConfigInfo, expectedErrorPattern string) {
+		t.Run(fmt.Sprintf("%#v", info), func(t *testing.T) {
+			errorHandler := android.FixtureExpectsNoErrors
+			if expectedErrorPattern != "" {
+				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorPattern)
+			}
+			javaFixtureFactory.ExtendWithErrorHandler(errorHandler).RunTest(t, createPreparer(info))
+		})
 	}
 
 	errorMessage := "is not allowed across the partitions"
 
-	testJavaWithConfig(t, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_library",
 		fromPartition:              "product",
 		toPartition:                "system",
 		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: false,
-	}))
+	}, "")
 
-	testJavaWithConfig(t, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_library",
 		fromPartition:              "product",
 		toPartition:                "system",
 		enforceVendorInterface:     true,
 		enforceProductInterface:    false,
 		enforceJavaSdkLibraryCheck: true,
-	}))
+	}, "")
 
-	testJavaErrorWithConfig(t, errorMessage, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_library",
 		fromPartition:              "product",
 		toPartition:                "system",
 		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
-	}))
+	}, errorMessage)
 
-	testJavaErrorWithConfig(t, errorMessage, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_library",
 		fromPartition:              "vendor",
 		toPartition:                "system",
 		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
-	}))
+	}, errorMessage)
 
-	testJavaWithConfig(t, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_library",
 		fromPartition:              "vendor",
 		toPartition:                "system",
@@ -977,43 +992,43 @@
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
 		allowList:                  []string{"bar"},
-	}))
+	}, "")
 
-	testJavaErrorWithConfig(t, errorMessage, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_library",
 		fromPartition:              "vendor",
 		toPartition:                "product",
 		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
-	}))
+	}, errorMessage)
 
-	testJavaWithConfig(t, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_sdk_library",
 		fromPartition:              "product",
 		toPartition:                "system",
 		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
-	}))
+	}, "")
 
-	testJavaWithConfig(t, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_sdk_library",
 		fromPartition:              "vendor",
 		toPartition:                "system",
 		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
-	}))
+	}, "")
 
-	testJavaWithConfig(t, createTestConfig(testConfigInfo{
+	runTest(t, testConfigInfo{
 		libraryType:                "java_sdk_library",
 		fromPartition:              "vendor",
 		toPartition:                "product",
 		enforceVendorInterface:     true,
 		enforceProductInterface:    true,
 		enforceJavaSdkLibraryCheck: true,
-	}))
+	}, "")
 }
 
 func TestDefaults(t *testing.T) {
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 2c47b0a..4bfd4e2 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -20,11 +20,17 @@
 )
 
 func init() {
-	android.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
-	android.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory)
-	android.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
+	registerPlatformCompatConfigBuildComponents(android.InitRegistrationContext)
 }
 
+func registerPlatformCompatConfigBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
+	ctx.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory)
+	ctx.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
+}
+
+var PrepareForTestWithPlatformCompatConfig = android.FixtureRegisterWithContext(registerPlatformCompatConfigBuildComponents)
+
 func platformCompatConfigPath(ctx android.PathContext) android.OutputPath {
 	return android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml")
 }
@@ -146,7 +152,7 @@
 func PlatformCompatConfigFactory() android.Module {
 	module := &platformCompatConfig{}
 	module.AddProperties(&module.properties)
-	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	return module
 }
 
diff --git a/java/testing.go b/java/testing.go
index 4e1997e..896bcf8 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -61,27 +61,95 @@
 	PrepareForTestWithJavaDefaultModules,
 )
 
+// Prepare a fixture with the standard files required by a java_sdk_library module.
+var PrepareForTestWithJavaSdkLibraryFiles = android.FixtureMergeMockFs(javaSdkLibraryFiles)
+
+var javaSdkLibraryFiles = android.MockFS{
+	"api/current.txt":               nil,
+	"api/removed.txt":               nil,
+	"api/system-current.txt":        nil,
+	"api/system-removed.txt":        nil,
+	"api/test-current.txt":          nil,
+	"api/test-removed.txt":          nil,
+	"api/module-lib-current.txt":    nil,
+	"api/module-lib-removed.txt":    nil,
+	"api/system-server-current.txt": nil,
+	"api/system-server-removed.txt": nil,
+}
+
+// FixtureWithLastReleaseApis creates a preparer that creates prebuilt versions of the specified
+// modules for the `last` API release. By `last` it just means last in the list of supplied versions
+// and as this only provides one version it can be any value.
+//
+// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this.
+func FixtureWithLastReleaseApis(moduleNames ...string) android.FixturePreparer {
+	return FixtureWithPrebuiltApis(map[string][]string{
+		"30": moduleNames,
+	})
+}
+
+// PrepareForTestWithPrebuiltsOfCurrentApi is a preparer that creates prebuilt versions of the
+// standard modules for the current version.
+//
+// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this.
+var PrepareForTestWithPrebuiltsOfCurrentApi = FixtureWithPrebuiltApis(map[string][]string{
+	"current": {},
+	// Can't have current on its own as it adds a prebuilt_apis module but doesn't add any
+	// .txt files which causes the prebuilt_apis module to fail.
+	"30": {},
+})
+
+// FixtureWithPrebuiltApis creates a preparer that will define prebuilt api modules for the
+// specified releases and modules.
+//
+// The supplied map keys are the releases, e.g. current, 29, 30, etc. The values are a list of
+// modules for that release. Due to limitations in the prebuilt_apis module which this preparer
+// uses the set of releases must include at least one numbered release, i.e. it cannot just include
+// "current".
+//
+// This defines a file in the mock file system in a predefined location (prebuilts/sdk/Android.bp)
+// and so only one instance of this can be used in each fixture.
+func FixtureWithPrebuiltApis(release2Modules map[string][]string) android.FixturePreparer {
+	mockFS := android.MockFS{}
+	path := "prebuilts/sdk/Android.bp"
+
+	bp := fmt.Sprintf(`
+			prebuilt_apis {
+				name: "sdk",
+				api_dirs: ["%s"],
+				imports_sdk_version: "none",
+				imports_compile_dex: true,
+			}
+		`, strings.Join(android.SortedStringKeys(release2Modules), `", "`))
+
+	for release, modules := range release2Modules {
+		libs := append([]string{"android", "core-for-system-modules"}, modules...)
+		mockFS.Merge(prebuiltApisFilesForLibs([]string{release}, libs))
+	}
+	return android.GroupFixturePreparers(
+		// A temporary measure to discard the definitions provided by default by javaMockFS() to allow
+		// the changes that use this preparer to fix tests to be separated from the change to remove
+		// javaMockFS().
+		android.FixtureModifyMockFS(func(fs android.MockFS) {
+			for k, _ := range fs {
+				if strings.HasPrefix(k, "prebuilts/sdk/") {
+					delete(fs, k)
+				}
+			}
+		}),
+		android.FixtureAddTextFile(path, bp),
+		android.FixtureMergeMockFs(mockFS),
+	)
+}
+
 func javaMockFS() android.MockFS {
 	mockFS := android.MockFS{
-		"api/current.txt":        nil,
-		"api/removed.txt":        nil,
-		"api/system-current.txt": nil,
-		"api/system-removed.txt": nil,
-		"api/test-current.txt":   nil,
-		"api/test-removed.txt":   nil,
-
 		"prebuilts/sdk/tools/core-lambda-stubs.jar": nil,
 		"prebuilts/sdk/Android.bp":                  []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"], imports_sdk_version: "none", imports_compile_dex:true,}`),
 
 		"bin.py": nil,
 		python.StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
 		MAIN_FILE = '%main%'`),
-
-		// For java_sdk_library
-		"api/module-lib-current.txt":    nil,
-		"api/module-lib-removed.txt":    nil,
-		"api/system-server-current.txt": nil,
-		"api/system-server-removed.txt": nil,
 	}
 
 	levels := []string{"14", "28", "29", "30", "current"}
@@ -101,6 +169,7 @@
 	bp += GatherRequiredDepsForTest()
 
 	mockFS := javaMockFS()
+	mockFS.Merge(javaSdkLibraryFiles)
 
 	cc.GatherRequiredFilesForTest(mockFS)