Merge "cc/linker.go: check min_sdk_version."
diff --git a/android/arch.go b/android/arch.go
index c1b2c33..bb1b613 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1025,7 +1025,7 @@
 }
 
 // Merges the property struct in srcValue into dst.
-func mergePropertyStruct(ctx BaseMutatorContext, dst interface{}, srcValue reflect.Value) {
+func mergePropertyStruct(ctx ArchVariantContext, dst interface{}, srcValue reflect.Value) {
 	src := maybeBlueprintEmbed(srcValue).Interface()
 
 	// order checks the `android:"variant_prepend"` tag to handle properties where the
@@ -1054,7 +1054,7 @@
 
 // Returns the immediate child of the input property struct that corresponds to
 // the sub-property "field".
-func getChildPropertyStruct(ctx BaseMutatorContext,
+func getChildPropertyStruct(ctx ArchVariantContext,
 	src reflect.Value, field, userFriendlyField string) reflect.Value {
 
 	// Step into non-nil pointers to structs in the src value.
@@ -1186,7 +1186,7 @@
 // },
 // This struct will also contain sub-structs containing to the architecture/CPU
 // variants and features that themselves contain properties specific to those.
-func getArchTypeStruct(ctx BaseMutatorContext, archProperties interface{}, archType ArchType) reflect.Value {
+func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) reflect.Value {
 	archPropValues := reflect.ValueOf(archProperties).Elem()
 	archProp := archPropValues.FieldByName("Arch").Elem()
 	prefix := "arch." + archType.Name
@@ -1201,7 +1201,7 @@
 //         key: value,
 //     },
 // },
-func getMultilibStruct(ctx BaseMutatorContext, archProperties interface{}, archType ArchType) reflect.Value {
+func getMultilibStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) reflect.Value {
 	archPropValues := reflect.ValueOf(archProperties).Elem()
 	multilibProp := archPropValues.FieldByName("Multilib").Elem()
 	multilibProperties := getChildPropertyStruct(ctx, multilibProp, archType.Multilib, "multilib."+archType.Multilib)
@@ -1851,6 +1851,12 @@
 	return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
 }
 
+// ArchVariantContext defines the limited context necessary to retrieve arch_variant properties.
+type ArchVariantContext interface {
+	ModuleErrorf(fmt string, args ...interface{})
+	PropertyErrorf(property, fmt string, args ...interface{})
+}
+
 // GetArchProperties returns a map of architectures to the values of the
 // properties of the 'propertySet' struct that are specific to that architecture.
 //
@@ -1863,7 +1869,7 @@
 // For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }`
 // will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given
 // propertyset contains `Foo []string`.
-func (m *ModuleBase) GetArchProperties(ctx BaseMutatorContext, propertySet interface{}) map[ArchType]interface{} {
+func (m *ModuleBase) GetArchProperties(ctx ArchVariantContext, propertySet interface{}) map[ArchType]interface{} {
 	// Return value of the arch types to the prop values for that arch.
 	archToProp := map[ArchType]interface{}{}
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 922e40a..68182a7 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4542,7 +4542,12 @@
 }
 
 func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
-	preparer := java.FixtureConfigureBootJars("myapex:libfoo", "myapex:libbar")
+	preparer := android.GroupFixturePreparers(
+		java.FixtureConfigureBootJars("myapex:libfoo", "myapex:libbar"),
+		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+		// is disabled.
+		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+	)
 
 	checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
 		t.Helper()
@@ -4564,7 +4569,7 @@
 	checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedInputs string) {
 		t.Helper()
 		platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
-		indexRule := platformBootclasspath.Rule("platform-bootclasspath-monolithic-hiddenapi-index")
+		indexRule := platformBootclasspath.Rule("monolithic_hidden_API_index")
 		java.CheckHiddenAPIRuleInputs(t, expectedInputs, indexRule)
 	}
 
@@ -4602,10 +4607,10 @@
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
-		// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
+		// Verify the correct module jars contribute to the hiddenapi index file.
 		checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/libfoo/android_common_myapex/hiddenapi/index.csv
+.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
+.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
 `)
 	})
 
@@ -4636,10 +4641,10 @@
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
-		// Make sure that the dex file from the apex_set contributes to the hiddenapi index file.
+		// Verify the correct module jars contribute to the hiddenapi index file.
 		checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/libfoo/android_common_myapex/hiddenapi/index.csv
+.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
+.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
 `)
 	})
 
@@ -4743,10 +4748,10 @@
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
-		// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
+		// Verify the correct module jars contribute to the hiddenapi index file.
 		checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/prebuilt_libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/prebuilt_libfoo/android_common_myapex/hiddenapi/index.csv
+.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
+.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
 `)
 	})
 
@@ -4810,10 +4815,10 @@
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
 
-		// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
+		// Verify the correct module jars contribute to the hiddenapi index file.
 		checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/libfoo/android_common_apex10000/hiddenapi/index.csv
+.intermediates/libbar/android_common_myapex/javac/libbar.jar
+.intermediates/libfoo/android_common_apex10000/javac/libfoo.jar
 `)
 	})
 
@@ -4879,10 +4884,10 @@
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
-		// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
+		// Verify the correct module jars contribute to the hiddenapi index file.
 		checkHiddenAPIIndexInputs(t, ctx, `
-.intermediates/prebuilt_libbar/android_common_myapex/hiddenapi/index.csv
-.intermediates/prebuilt_libfoo/android_common_myapex/hiddenapi/index.csv
+.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
+.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
 `)
 	})
 }
diff --git a/cc/builder.go b/cc/builder.go
index 29cde9d..51c8a0b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -804,6 +804,7 @@
 		ImplicitOutputs: implicitOutputs,
 		Inputs:          objFiles,
 		Implicits:       deps,
+		OrderOnly:       sharedLibs,
 		Args:            args,
 	})
 }
diff --git a/cc/cc.go b/cc/cc.go
index c5552d6..a0ad0d6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3230,6 +3230,9 @@
 				return false
 			}
 		}
+		if cc.IsLlndk() {
+			return false
+		}
 		if isLibDepTag && c.static() && libDepTag.shared() {
 			// shared_lib dependency from a static lib is considered as crossing
 			// the APEX boundary because the dependency doesn't actually is
diff --git a/cc/library.go b/cc/library.go
index c5ff9b1..1ba3597 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1426,11 +1426,10 @@
 	}
 }
 
-func processLLNDKHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) android.Path {
+func processLLNDKHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) (timestamp android.Path, installPaths android.WritablePaths) {
 	srcDir := android.PathForModuleSrc(ctx, srcHeaderDir)
 	srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil)
 
-	var installPaths []android.WritablePath
 	for _, header := range srcFiles {
 		headerDir := filepath.Dir(header.String())
 		relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir)
@@ -1443,7 +1442,7 @@
 		installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base()))
 	}
 
-	return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths)
+	return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths), installPaths
 }
 
 // link registers actions to link this library, and sets various fields
@@ -1459,7 +1458,9 @@
 
 			var timestampFiles android.Paths
 			for _, dir := range library.Properties.Llndk.Export_preprocessed_headers {
-				timestampFiles = append(timestampFiles, processLLNDKHeaders(ctx, dir, genHeaderOutDir))
+				timestampFile, installPaths := processLLNDKHeaders(ctx, dir, genHeaderOutDir)
+				timestampFiles = append(timestampFiles, timestampFile)
+				library.addExportedGeneratedHeaders(installPaths.Paths()...)
 			}
 
 			if Bool(library.Properties.Llndk.Export_headers_as_system) {
diff --git a/cc/test.go b/cc/test.go
index d4c23d7..047a69e 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -48,12 +48,19 @@
 	Unit_test *bool
 
 	// Add ShippingApiLevelModuleController to auto generated test config. If the device properties
-	// for the shipping api level is less than the test_min_api_level, skip this module.
-	Test_min_api_level *int64
+	// for the shipping api level is less than the min_shipping_api_level, skip this module.
+	Min_shipping_api_level *int64
+
+	// Add ShippingApiLevelModuleController to auto generated test config. If any of the device
+	// shipping api level and vendor api level properties are less than the
+	// vsr_min_shipping_api_level, skip this module.
+	// As this includes the shipping api level check, it is not allowed to define
+	// min_shipping_api_level at the same time with this property.
+	Vsr_min_shipping_api_level *int64
 
 	// Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an
-	// integer value and the value is less than the test_min_vndk_version, skip this module.
-	Test_min_vndk_version *int64
+	// integer value and the value is less than the min_vndk_version, skip this module.
+	Min_vndk_version *int64
 }
 
 type TestBinaryProperties struct {
@@ -97,7 +104,7 @@
 
 	// Add ShippingApiLevelModuleController to auto generated test config. If the device properties
 	// for the shipping api level is less than the test_min_api_level, skip this module.
-	// Deprecated (b/187258404). Use test_options.test_min_api_level instead.
+	// Deprecated (b/187258404). Use test_options.min_shipping_api_level instead.
 	Test_min_api_level *int64
 
 	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
@@ -404,19 +411,30 @@
 	for _, tag := range test.Properties.Test_options.Test_suite_tag {
 		configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag})
 	}
-	if test.Properties.Test_options.Test_min_api_level != nil {
+	if test.Properties.Test_options.Min_shipping_api_level != nil {
+		if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
+			ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
+		}
 		var options []tradefed.Option
-		options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Test_min_api_level), 10)})
+		options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_shipping_api_level), 10)})
 		configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
 	} else if test.Properties.Test_min_api_level != nil {
 		// TODO: (b/187258404) Remove test.Properties.Test_min_api_level
+		if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
+			ctx.PropertyErrorf("test_min_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
+		}
 		var options []tradefed.Option
 		options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)})
 		configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
 	}
-	if test.Properties.Test_options.Test_min_vndk_version != nil {
+	if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
 		var options []tradefed.Option
-		options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Test_min_vndk_version), 10)})
+		options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Vsr_min_shipping_api_level), 10)})
+		configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
+	}
+	if test.Properties.Test_options.Min_vndk_version != nil {
+		var options []tradefed.Option
+		options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_vndk_version), 10)})
 		options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"})
 		configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
 	}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 1844bce..7e73bf7 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -130,9 +130,11 @@
 	ProvidesUsesLibrary            string       // library name (usually the same as module name)
 	ClassLoaderContexts            ClassLoaderContextMap
 
-	Archs                         []android.ArchType
-	DexPreoptImagesDeps           []android.OutputPaths
-	DexPreoptImageLocationsOnHost []string // boot image location on host (file path without the arch subdirectory)
+	Archs               []android.ArchType
+	DexPreoptImagesDeps []android.OutputPaths
+
+	DexPreoptImageLocationsOnHost   []string // boot image location on host (file path without the arch subdirectory)
+	DexPreoptImageLocationsOnDevice []string // boot image location on device (file path without the arch subdirectory)
 
 	PreoptBootClassPathDexFiles     android.Paths // file paths of boot class path files
 	PreoptBootClassPathDexLocations []string      // virtual locations of boot class path files
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 9d9234f..da015a3 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -499,11 +499,16 @@
 
 // PathToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art
 func PathToLocation(path android.Path, arch android.ArchType) string {
-	pathArch := filepath.Base(filepath.Dir(path.String()))
+	return PathStringToLocation(path.String(), arch)
+}
+
+// PathStringToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art
+func PathStringToLocation(path string, arch android.ArchType) string {
+	pathArch := filepath.Base(filepath.Dir(path))
 	if pathArch != arch.String() {
 		panic(fmt.Errorf("last directory in %q must be %q", path, arch.String()))
 	}
-	return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
+	return filepath.Join(filepath.Dir(filepath.Dir(path)), filepath.Base(path))
 }
 
 func makefileMatch(pattern, s string) bool {
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index 32c4f84..7dbe74c 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -37,6 +37,12 @@
 	globalConfigPath      = flag.String("global", "", "path to global configuration file")
 	moduleConfigPath      = flag.String("module", "", "path to module configuration file")
 	outDir                = flag.String("out_dir", "", "path to output directory")
+	// If uses_target_files is true, dexpreopt_gen will be running on extracted target_files.zip files.
+	// In this case, the tool replace output file path with $(basePath)/$(on-device file path).
+	// The flag is useful when running dex2oat on system image and vendor image which are built separately.
+	usesTargetFiles = flag.Bool("uses_target_files", false, "whether or not dexpreopt is running on target_files")
+	// basePath indicates the path where target_files.zip is extracted.
+	basePath = flag.String("base_path", ".", "base path where images and tools are extracted")
 )
 
 type builderContext struct {
@@ -134,32 +140,28 @@
 			}
 		}
 	}()
-
+	if *usesTargetFiles {
+		moduleConfig.ManifestPath = android.OptionalPath{}
+		prefix := "dex2oat_result"
+		moduleConfig.BuildPath = android.PathForOutput(ctx, filepath.Join(prefix, moduleConfig.DexLocation))
+		for i, location := range moduleConfig.PreoptBootClassPathDexLocations {
+			moduleConfig.PreoptBootClassPathDexFiles[i] = android.PathForSource(ctx, *basePath+location)
+		}
+		for i := range moduleConfig.ClassLoaderContexts {
+			for _, v := range moduleConfig.ClassLoaderContexts[i] {
+				v.Host = android.PathForSource(ctx, *basePath+v.Device)
+			}
+		}
+		moduleConfig.EnforceUsesLibraries = false
+		for i, location := range moduleConfig.DexPreoptImageLocationsOnDevice {
+			moduleConfig.DexPreoptImageLocationsOnHost[i] = *basePath + location
+		}
+	}
 	writeScripts(ctx, globalSoongConfig, globalConfig, moduleConfig, *dexpreoptScriptPath)
 }
 
 func writeScripts(ctx android.BuilderContext, globalSoong *dexpreopt.GlobalSoongConfig,
 	global *dexpreopt.GlobalConfig, module *dexpreopt.ModuleConfig, dexpreoptScriptPath string) {
-	dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, module)
-	if err != nil {
-		panic(err)
-	}
-
-	installDir := module.BuildPath.InSameDir(ctx, "dexpreopt_install")
-
-	dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir.String())
-	dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir.String())
-
-	for _, install := range dexpreoptRule.Installs() {
-		installPath := installDir.Join(ctx, strings.TrimPrefix(install.To, "/"))
-		dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String()))
-		dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
-	}
-	dexpreoptRule.Command().Tool(globalSoong.SoongZip).
-		FlagWithArg("-o ", "$2").
-		FlagWithArg("-C ", installDir.String()).
-		FlagWithArg("-D ", installDir.String())
-
 	write := func(rule *android.RuleBuilder, file string) {
 		script := &bytes.Buffer{}
 		script.WriteString(scriptHeader)
@@ -195,6 +197,30 @@
 			panic(err)
 		}
 	}
+	dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, module)
+	if err != nil {
+		panic(err)
+	}
+	// When usesTargetFiles is true, only odex/vdex files are necessary.
+	// So skip redunant processes(such as copying the result to the artifact path, and zipping, and so on.)
+	if *usesTargetFiles {
+		write(dexpreoptRule, dexpreoptScriptPath)
+		return
+	}
+	installDir := module.BuildPath.InSameDir(ctx, "dexpreopt_install")
+
+	dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir.String())
+	dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir.String())
+
+	for _, install := range dexpreoptRule.Installs() {
+		installPath := installDir.Join(ctx, strings.TrimPrefix(install.To, "/"))
+		dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String()))
+		dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
+	}
+	dexpreoptRule.Command().Tool(globalSoong.SoongZip).
+		FlagWithArg("-o ", "$2").
+		FlagWithArg("-C ", installDir.String()).
+		FlagWithArg("-D ", installDir.String())
 
 	// The written scripts will assume the input is $1 and the output is $2
 	if module.DexPath.String() != "$1" {
diff --git a/java/base.go b/java/base.go
index 19c85cd..03652be 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1177,8 +1177,14 @@
 		j.properties.Instrument = true
 	}
 
+	// enforce syntax check to jacoco filters for any build (http://b/183622051)
+	specs := j.jacocoModuleToZipCommand(ctx)
+	if ctx.Failed() {
+		return
+	}
+
 	if j.shouldInstrument(ctx) {
-		outputFile = j.instrument(ctx, flags, outputFile, jarName)
+		outputFile = j.instrument(ctx, flags, outputFile, jarName, specs)
 	}
 
 	// merge implementation jar with resources if necessary
@@ -1217,9 +1223,11 @@
 				return
 			}
 
-			// Hidden API CSV generation and dex encoding
-			dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
-				proptools.Bool(j.dexProperties.Uncompress_dex))
+			// Update hidden API paths.
+			j.hiddenAPIUpdatePaths(ctx, dexOutputFile, j.implementationJarFile)
+
+			// Encode hidden API flags in dex file.
+			dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile, proptools.Bool(j.dexProperties.Uncompress_dex))
 
 			// merge dex jar with resources if necessary
 			if j.resourceJar != nil {
@@ -1390,9 +1398,7 @@
 }
 
 func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
-	classesJar android.Path, jarName string) android.OutputPath {
-
-	specs := j.jacocoModuleToZipCommand(ctx)
+	classesJar android.Path, jarName string, specs string) android.OutputPath {
 
 	jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
 	instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName).OutputPath
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 20421de..16aa5e2 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -61,8 +61,14 @@
 }
 
 // SdkMemberType causes dependencies added with this tag to be automatically added to the sdk as if
-// they were specified using java_boot_libs.
-func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType {
+// they were specified using java_boot_libs or java_sdk_libs.
+func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+	// If the module is a java_sdk_library then treat it as if it was specified in the java_sdk_libs
+	// property, otherwise treat if it was specified in the java_boot_libs property.
+	if javaSdkLibrarySdkMemberType.IsInstance(child) {
+		return javaSdkLibrarySdkMemberType
+	}
+
 	return javaBootLibsSdkMemberType
 }
 
@@ -85,6 +91,9 @@
 type BootclasspathFragmentCoverageAffectedProperties struct {
 	// The contents of this bootclasspath_fragment, could be either java_library, or java_sdk_library.
 	//
+	// A java_sdk_library specified here will also be treated as if it was specified on the stub_libs
+	// property.
+	//
 	// The order of this list matters as it is the order that is used in the bootclasspath.
 	Contents []string
 
@@ -114,6 +123,15 @@
 	properties bootclasspathFragmentProperties
 }
 
+// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
+// bootclasspath fragment modules.
+type commonBootclasspathFragment interface {
+	// produceHiddenAPIAllFlagsFile produces the all-flags.csv and intermediate files.
+	//
+	// Updates the supplied flagFileInfo with the paths to the generated files set.
+	produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo)
+}
+
 func bootclasspathFragmentFactory() android.Module {
 	m := &BootclasspathFragmentModule{}
 	m.AddProperties(&m.properties)
@@ -371,7 +389,7 @@
 	})
 
 	// Perform hidden API processing.
-	b.generateHiddenAPIBuildActions(ctx)
+	b.generateHiddenAPIBuildActions(ctx, contents)
 
 	// Construct the boot image info from the config.
 	info := BootclasspathFragmentApexContentInfo{
@@ -431,19 +449,43 @@
 }
 
 // generateHiddenAPIBuildActions generates all the hidden API related build rules.
-func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) {
-	// Resolve the properties to paths.
-	flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
-
-	// Store the information for use by platform_bootclasspath.
-	ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
+func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module) {
 
 	// Convert the kind specific lists of modules into kind specific lists of jars.
-	stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx)
+	stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx, contents)
 
 	// Store the information for use by other modules.
 	bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: stubJarsByKind}
 	ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo)
+
+	// Resolve the properties to paths.
+	flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
+
+	hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, contents)
+
+	// Delegate the production of the hidden API all flags file to a module type specific method.
+	common := ctx.Module().(commonBootclasspathFragment)
+	common.produceHiddenAPIAllFlagsFile(ctx, hiddenAPIModules, stubJarsByKind, &flagFileInfo)
+
+	// Store the information for use by platform_bootclasspath.
+	ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
+}
+
+// produceHiddenAPIAllFlagsFile produces the hidden API all-flags.csv file (and supporting files)
+// for the fragment.
+func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
+	// If no stubs have been provided then don't perform hidden API processing. This is a temporary
+	// workaround to avoid existing bootclasspath_fragments that do not provide stubs breaking the
+	// build.
+	// TODO(b/179354495): Remove this workaround.
+	if len(stubJarsByKind) == 0 {
+		// Nothing to do.
+		return
+	}
+
+	// Generate the rules to create the hidden API flags and update the supplied flagFileInfo with the
+	// paths to the created files.
+	hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, stubJarsByKind, flagFileInfo)
 }
 
 // generateBootImageBuildActions generates ninja rules to create the boot image if required for this
@@ -524,6 +566,32 @@
 
 	// Flag files by *hiddenAPIFlagFileCategory
 	Flag_files_by_category map[*hiddenAPIFlagFileCategory]android.Paths
+
+	// The path to the generated stub-flags.csv file.
+	Stub_flags_path android.OptionalPath
+
+	// The path to the generated annotation-flags.csv file.
+	Annotation_flags_path android.OptionalPath
+
+	// The path to the generated metadata.csv file.
+	Metadata_path android.OptionalPath
+
+	// The path to the generated index.csv file.
+	Index_path android.OptionalPath
+
+	// The path to the generated all-flags.csv file.
+	All_flags_path android.OptionalPath
+}
+
+func pathsToOptionalPath(paths android.Paths) android.OptionalPath {
+	switch len(paths) {
+	case 0:
+		return android.OptionalPath{}
+	case 1:
+		return android.OptionalPathForPath(paths[0])
+	default:
+		panic(fmt.Errorf("expected 0 or 1 paths, found %q", paths))
+	}
 }
 
 func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
@@ -537,6 +605,13 @@
 	flagFileInfo := mctx.OtherModuleProvider(module, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo)
 	b.Flag_files_by_category = flagFileInfo.categoryToPaths
 
+	// Copy all the generated file paths.
+	b.Stub_flags_path = pathsToOptionalPath(flagFileInfo.StubFlagsPaths)
+	b.Annotation_flags_path = pathsToOptionalPath(flagFileInfo.AnnotationFlagsPaths)
+	b.Metadata_path = pathsToOptionalPath(flagFileInfo.MetadataPaths)
+	b.Index_path = pathsToOptionalPath(flagFileInfo.IndexPaths)
+	b.All_flags_path = pathsToOptionalPath(flagFileInfo.AllFlagsPaths)
+
 	// Copy stub_libs properties.
 	b.Stub_libs = module.properties.Api.Stub_libs
 	b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs
@@ -563,14 +638,17 @@
 		corePlatformApiPropertySet.AddPropertyWithTag("stub_libs", b.Core_platform_stub_libs, requiredMemberDependency)
 	}
 
+	hiddenAPISet := propertySet.AddPropertySet("hidden_api")
+	hiddenAPIDir := "hiddenapi"
+
+	// Copy manually curated flag files specified on the bootclasspath_fragment.
 	if b.Flag_files_by_category != nil {
-		hiddenAPISet := propertySet.AddPropertySet("hidden_api")
 		for _, category := range hiddenAPIFlagFileCategories {
 			paths := b.Flag_files_by_category[category]
 			if len(paths) > 0 {
 				dests := []string{}
 				for _, p := range paths {
-					dest := filepath.Join("hiddenapi", p.Base())
+					dest := filepath.Join(hiddenAPIDir, p.Base())
 					builder.CopyToSnapshot(p, dest)
 					dests = append(dests, dest)
 				}
@@ -578,10 +656,47 @@
 			}
 		}
 	}
+
+	copyOptionalPath := func(path android.OptionalPath, property string) {
+		if path.Valid() {
+			p := path.Path()
+			dest := filepath.Join(hiddenAPIDir, p.Base())
+			builder.CopyToSnapshot(p, dest)
+			hiddenAPISet.AddProperty(property, dest)
+		}
+	}
+
+	// Copy all the generated files, if available.
+	copyOptionalPath(b.Stub_flags_path, "stub_flags")
+	copyOptionalPath(b.Annotation_flags_path, "annotation_flags")
+	copyOptionalPath(b.Metadata_path, "metadata")
+	copyOptionalPath(b.Index_path, "index")
+	copyOptionalPath(b.All_flags_path, "all_flags")
 }
 
 var _ android.SdkMemberType = (*bootclasspathFragmentMemberType)(nil)
 
+// prebuiltBootclasspathFragmentProperties contains additional prebuilt_bootclasspath_fragment
+// specific properties.
+type prebuiltBootclasspathFragmentProperties struct {
+	Hidden_api struct {
+		// The path to the stub-flags.csv file created by the bootclasspath_fragment.
+		Stub_flags *string `android:"path"`
+
+		// The path to the annotation-flags.csv file created by the bootclasspath_fragment.
+		Annotation_flags *string `android:"path"`
+
+		// The path to the metadata.csv file created by the bootclasspath_fragment.
+		Metadata *string `android:"path"`
+
+		// The path to the index.csv file created by the bootclasspath_fragment.
+		Index *string `android:"path"`
+
+		// The path to the all-flags.csv file created by the bootclasspath_fragment.
+		All_flags *string `android:"path"`
+	}
+}
+
 // A prebuilt version of the bootclasspath_fragment module.
 //
 // At the moment this is basically just a bootclasspath_fragment module that can be used as a
@@ -590,6 +705,9 @@
 type prebuiltBootclasspathFragmentModule struct {
 	BootclasspathFragmentModule
 	prebuilt android.Prebuilt
+
+	// Additional prebuilt specific properties.
+	prebuiltProperties prebuiltBootclasspathFragmentProperties
 }
 
 func (module *prebuiltBootclasspathFragmentModule) Prebuilt() *android.Prebuilt {
@@ -600,9 +718,29 @@
 	return module.prebuilt.Name(module.ModuleBase.Name())
 }
 
+// produceHiddenAPIAllFlagsFile returns a path to the prebuilt all-flags.csv or nil if none is
+// specified.
+func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
+	pathsForOptionalSrc := func(src *string) android.Paths {
+		if src == nil {
+			// TODO(b/179354495): Fail if this is not provided once prebuilts have been updated.
+			return nil
+		}
+		return android.Paths{android.PathForModuleSrc(ctx, *src)}
+	}
+
+	flagFileInfo.StubFlagsPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags)
+	flagFileInfo.AnnotationFlagsPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.Annotation_flags)
+	flagFileInfo.MetadataPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.Metadata)
+	flagFileInfo.IndexPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.Index)
+	flagFileInfo.AllFlagsPaths = pathsForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags)
+}
+
+var _ commonBootclasspathFragment = (*prebuiltBootclasspathFragmentModule)(nil)
+
 func prebuiltBootclasspathFragmentFactory() android.Module {
 	m := &prebuiltBootclasspathFragmentModule{}
-	m.AddProperties(&m.properties)
+	m.AddProperties(&m.properties, &m.prebuiltProperties)
 	// This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
 	// array.
 	android.InitPrebuiltModule(m, &[]string{"placeholder"})
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 32ed7ea..db284c9 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -204,7 +204,7 @@
 	result := android.GroupFixturePreparers(
 		prepareForTestWithBootclasspathFragment,
 		PrepareForTestWithJavaSdkLibraryFiles,
-		FixtureWithLastReleaseApis("mysdklibrary", "mycoreplatform"),
+		FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
 	).RunTestWithBp(t, `
 		bootclasspath_fragment {
 			name: "myfragment",
@@ -212,7 +212,7 @@
 			api: {
 				stub_libs: [
 					"mystublib",
-					"mysdklibrary",
+					"myothersdklibrary",
 				],
 			},
 			core_platform_api: {
@@ -231,15 +231,22 @@
 		java_sdk_library {
 			name: "mysdklibrary",
 			srcs: ["a.java"],
-			compile_dex: true,
+			shared_library: false,
 			public: {enabled: true},
 			system: {enabled: true},
 		}
 
 		java_sdk_library {
+			name: "myothersdklibrary",
+			srcs: ["a.java"],
+			shared_library: false,
+			public: {enabled: true},
+		}
+
+		java_sdk_library {
 			name: "mycoreplatform",
 			srcs: ["a.java"],
-			compile_dex: true,
+			shared_library: false,
 			public: {enabled: true},
 		}
 	`)
@@ -249,16 +256,23 @@
 
 	stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
 
-	// Check that SdkPublic uses public stubs.
+	// Stubs jars for mysdklibrary
 	publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar"
-	android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{stubsJar, publicStubsJar}, info.stubJarsByKind[android.SdkPublic])
-
-	// Check that SdkSystem uses system stubs.
 	systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.system/android_common/dex/mysdklibrary.stubs.system.jar"
-	android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{stubsJar, systemStubsJar}, info.stubJarsByKind[android.SdkSystem])
 
-	// Check that SdkTest also uses system stubs as the mysdklibrary does not provide test stubs.
-	android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{stubsJar, systemStubsJar}, info.stubJarsByKind[android.SdkTest])
+	// Stubs jars for myothersdklibrary
+	otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs/android_common/dex/myothersdklibrary.stubs.jar"
+
+	// Check that SdkPublic uses public stubs for all sdk libraries.
+	android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.stubJarsByKind[android.SdkPublic])
+
+	// Check that SdkSystem uses system stubs for mysdklibrary and public stubs for myothersdklibrary
+	// as it does not provide system stubs.
+	android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.stubJarsByKind[android.SdkSystem])
+
+	// Check that SdkTest also uses system stubs for mysdklibrary as it does not provide test stubs
+	// and public stubs for myothersdklibrary as it does not provide test stubs either.
+	android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.stubJarsByKind[android.SdkTest])
 
 	// Check that SdkCorePlatform uses public stubs from the mycoreplatform library.
 	corePlatformStubsJar := "out/soong/.intermediates/mycoreplatform.stubs/android_common/dex/mycoreplatform.stubs.jar"
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 8d23ad6..2e46d74 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -184,7 +184,7 @@
 		imagesDeps = append(imagesDeps, variant.imagesDeps)
 	}
 	// The image locations for all Android variants are identical.
-	hostImageLocations := bootImage.getAnyAndroidVariant().imageLocations()
+	hostImageLocations, deviceImageLocations := bootImage.getAnyAndroidVariant().imageLocations()
 
 	var profileClassListing android.OptionalPath
 	var profileBootListing android.OptionalPath
@@ -224,9 +224,10 @@
 		ProvidesUsesLibrary:            providesUsesLib,
 		ClassLoaderContexts:            d.classLoaderContexts,
 
-		Archs:                         archs,
-		DexPreoptImagesDeps:           imagesDeps,
-		DexPreoptImageLocationsOnHost: hostImageLocations,
+		Archs:                           archs,
+		DexPreoptImagesDeps:             imagesDeps,
+		DexPreoptImageLocationsOnHost:   hostImageLocations,
+		DexPreoptImageLocationsOnDevice: deviceImageLocations,
 
 		PreoptBootClassPathDexFiles:     dexFiles.Paths(),
 		PreoptBootClassPathDexLocations: dexLocations,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 07715ab..be202c0 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -244,6 +244,9 @@
 	// Subdirectory where the image files are installed.
 	installDirOnHost string
 
+	// Subdirectory where the image files on device are installed.
+	installDirOnDevice string
+
 	// A list of (location, jar) pairs for the Java modules in this image.
 	modules android.ConfiguredJarList
 
@@ -273,8 +276,9 @@
 	dexLocationsDeps []string // for the dependency images and in this image
 
 	// Paths to image files.
-	imagePathOnHost android.OutputPath  // first image file
-	imagesDeps      android.OutputPaths // all files
+	imagePathOnHost   android.OutputPath  // first image file path on host
+	imagePathOnDevice string              // first image file path on device
+	imagesDeps        android.OutputPaths // all files
 
 	// Only for extensions, paths to the primary boot images.
 	primaryImages android.OutputPath
@@ -361,11 +365,12 @@
 // The location is passed as an argument to the ART tools like dex2oat instead of the real path.
 // ART tools will then reconstruct the architecture-specific real path.
 //
-func (image *bootImageVariant) imageLocations() (imageLocations []string) {
+func (image *bootImageVariant) imageLocations() (imageLocationsOnHost []string, imageLocationsOnDevice []string) {
 	if image.extends != nil {
-		imageLocations = image.extends.getVariant(image.target).imageLocations()
+		imageLocationsOnHost, imageLocationsOnDevice = image.extends.getVariant(image.target).imageLocations()
 	}
-	return append(imageLocations, dexpreopt.PathToLocation(image.imagePathOnHost, image.target.Arch.ArchType))
+	return append(imageLocationsOnHost, dexpreopt.PathToLocation(image.imagePathOnHost, image.target.Arch.ArchType)),
+		append(imageLocationsOnDevice, dexpreopt.PathStringToLocation(image.imagePathOnDevice, image.target.Arch.ArchType))
 }
 
 func dexpreoptBootJarsFactory() android.SingletonModule {
@@ -796,12 +801,13 @@
 		// Create a rule to call oatdump.
 		output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
 		rule := android.NewRuleBuilder(pctx, ctx)
+		imageLocationsOnHost, _ := image.imageLocations()
 		rule.Command().
 			// TODO: for now, use the debug version for better error reporting
 			BuiltTool("oatdumpd").
 			FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
 			FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
-			FlagWithArg("--image=", strings.Join(image.imageLocations(), ":")).Implicits(image.imagesDeps.Paths()).
+			FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()).
 			FlagWithOutput("--output=", output).
 			FlagWithArg("--instruction-set=", arch.String())
 		rule.Build("dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
@@ -871,8 +877,8 @@
 				ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String())
 				ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String())
 			}
-			imageLocations := current.getAnyAndroidVariant().imageLocations()
-			ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocations, ":"))
+			imageLocationsOnHost, _ := current.getAnyAndroidVariant().imageLocations()
+			ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocationsOnHost, ":"))
 			ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
 		}
 		ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 7fb0444..3724860 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -84,25 +84,28 @@
 		frameworkModules := global.BootJars.RemoveList(artModules)
 
 		artDirOnHost := "apex/art_boot_images/javalib"
+		artDirOnDevice := "apex/com.android.art/javalib"
 		frameworkSubdir := "system/framework"
 
 		// ART config for the primary boot image in the ART apex.
 		// It includes the Core Libraries.
 		artCfg := bootImageConfig{
-			name:             artBootImageName,
-			stem:             "boot",
-			installDirOnHost: artDirOnHost,
-			modules:          artModules,
+			name:               artBootImageName,
+			stem:               "boot",
+			installDirOnHost:   artDirOnHost,
+			installDirOnDevice: artDirOnDevice,
+			modules:            artModules,
 		}
 
 		// Framework config for the boot image extension.
 		// It includes framework libraries and depends on the ART config.
 		frameworkCfg := bootImageConfig{
-			extends:          &artCfg,
-			name:             frameworkBootImageName,
-			stem:             "boot",
-			installDirOnHost: frameworkSubdir,
-			modules:          frameworkModules,
+			extends:            &artCfg,
+			name:               frameworkBootImageName,
+			stem:               "boot",
+			installDirOnHost:   frameworkSubdir,
+			installDirOnDevice: frameworkSubdir,
+			modules:            frameworkModules,
 		}
 
 		configs := map[string]*bootImageConfig{
@@ -131,11 +134,12 @@
 				arch := target.Arch.ArchType
 				imageDir := c.dir.Join(ctx, target.Os.String(), c.installDirOnHost, arch.String())
 				variant := &bootImageVariant{
-					bootImageConfig: c,
-					target:          target,
-					imagePathOnHost: imageDir.Join(ctx, imageName),
-					imagesDeps:      c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
-					dexLocations:    c.modules.DevicePaths(ctx.Config(), target.Os),
+					bootImageConfig:   c,
+					target:            target,
+					imagePathOnHost:   imageDir.Join(ctx, imageName),
+					imagePathOnDevice: filepath.Join("/", c.installDirOnDevice, arch.String(), imageName),
+					imagesDeps:        c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
+					dexLocations:      c.modules.DevicePaths(ctx.Config(), target.Os),
 				}
 				variant.dexLocationsDeps = variant.dexLocations
 				c.variants = append(c.variants, variant)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index a34044f..829c473 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -56,66 +56,28 @@
 	// this file so using the encoded dex jar here would result in a cycle in the ninja rules.
 	bootDexJarPath android.Path
 
-	// The path to the CSV file that contains mappings from Java signature to various flags derived
-	// from annotations in the source, e.g. whether it is public or the sdk version above which it
-	// can no longer be used.
-	//
-	// It is created by the Class2NonSdkList tool which processes the .class files in the class
-	// implementation jar looking for UnsupportedAppUsage and CovariantReturnType annotations. The
-	// tool also consumes the hiddenAPISingletonPathsStruct.stubFlags file in order to perform
-	// consistency checks on the information in the annotations and to filter out bridge methods
-	// that are already part of the public API.
-	flagsCSVPath android.Path
-
-	// The path to the CSV file that contains mappings from Java signature to the value of properties
-	// specified on UnsupportedAppUsage annotations in the source.
-	//
-	// Like the flagsCSVPath file this is also created by the Class2NonSdkList in the same way.
-	// Although the two files could potentially be created in a single invocation of the
-	// Class2NonSdkList at the moment they are created using their own invocation, with the behavior
-	// being determined by the property that is used.
-	metadataCSVPath android.Path
-
-	// The path to the CSV file that contains mappings from Java signature to source location
-	// information.
-	//
-	// It is created by the merge_csv tool which processes the class implementation jar, extracting
-	// all the files ending in .uau (which are CSV files) and merges them together. The .uau files are
-	// created by the unsupported app usage annotation processor during compilation of the class
-	// implementation jar.
-	indexCSVPath android.Path
-
 	// The paths to the classes jars that contain classes and class members annotated with
 	// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
 	// processing.
 	classesJarPaths android.Paths
 }
 
-func (h *hiddenAPI) flagsCSV() android.Path {
-	return h.flagsCSVPath
-}
-
-func (h *hiddenAPI) metadataCSV() android.Path {
-	return h.metadataCSVPath
-}
-
 func (h *hiddenAPI) bootDexJar() android.Path {
 	return h.bootDexJarPath
 }
 
-func (h *hiddenAPI) indexCSV() android.Path {
-	return h.indexCSVPath
-}
-
 func (h *hiddenAPI) classesJars() android.Paths {
 	return h.classesJarPaths
 }
 
+// hiddenAPIModule is the interface a module that embeds the hiddenAPI structure must implement.
+type hiddenAPIModule interface {
+	android.Module
+	hiddenAPIIntf
+}
+
 type hiddenAPIIntf interface {
 	bootDexJar() android.Path
-	flagsCSV() android.Path
-	indexCSV() android.Path
-	metadataCSV() android.Path
 	classesJars() android.Paths
 }
 
@@ -130,6 +92,12 @@
 
 	h.configurationName = configurationName
 
+	// If the frameworks/base directories does not exist and no prebuilt hidden API flag files have
+	// been configured then it is not possible to do hidden API encoding.
+	if !ctx.Config().FrameworksBaseDirExists(ctx) && ctx.Config().PrebuiltHiddenApiDir(ctx) == "" {
+		return
+	}
+
 	// It is important that hiddenapi information is only gathered for/from modules that are actually
 	// on the boot jars list because the runtime only enforces access to the hidden API for the
 	// bootclassloader. If information is gathered for modules not on the list then that will cause
@@ -191,29 +159,19 @@
 	return active
 }
 
-// hiddenAPIExtractAndEncode is called by any module that could contribute to the hiddenapi
-// processing.
+// hiddenAPIEncodeDex is called by any module that needs to encode dex files.
 //
 // It ignores any module that has not had initHiddenApi() called on it and which is not in the boot
-// jar list.
+// jar list. In that case it simply returns the supplied dex jar path.
 //
-// Otherwise, it generates ninja rules to do the following:
-// 1. Extract information needed for hiddenapi processing from the module and output it into CSV
-//    files.
-// 2. Conditionally adds the supplied dex file to the list of files used to generate the
-//    hiddenAPISingletonPathsStruct.stubsFlag file.
-// 3. Conditionally creates a copy of the supplied dex file into which it has encoded the hiddenapi
-//    flags and returns this instead of the supplied dex jar, otherwise simply returns the supplied
-//    dex jar.
-func (h *hiddenAPI) hiddenAPIExtractAndEncode(ctx android.ModuleContext, dexJar android.OutputPath,
-	implementationJar android.Path, uncompressDex bool) android.OutputPath {
+// Otherwise, it creates a copy of the supplied dex file into which it has encoded the hiddenapi
+// flags and returns this instead of the supplied dex jar.
+func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android.OutputPath, uncompressDex bool) android.OutputPath {
 
 	if !h.active {
 		return dexJar
 	}
 
-	h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar)
-
 	hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
 
 	// Create a copy of the dex jar which has been encoded with hiddenapi flags.
@@ -225,23 +183,15 @@
 	return dexJar
 }
 
-// hiddenAPIExtractInformation generates ninja rules to extract the information from the classes
+// hiddenAPIUpdatePaths generates ninja rules to extract the information from the classes
 // jar, and outputs it to the appropriate module specific CSV file.
 //
 // It also makes the dex jar available for use when generating the
 // hiddenAPISingletonPathsStruct.stubFlags.
-func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJar, classesJar android.Path) {
-	if !h.active {
-		return
-	}
+func (h *hiddenAPI) hiddenAPIUpdatePaths(ctx android.ModuleContext, dexJar, classesJar android.Path) {
 
-	// More than one library with the same classes may need to be encoded but only one should be
-	// used as a source of information for hidden API processing otherwise it will result in
-	// duplicate entries in the files.
-	if !h.primary {
-		return
-	}
-
+	// Save the classes jars even if this is not active as they may be used by modular hidden API
+	// processing.
 	classesJars := android.Paths{classesJar}
 	ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
 		javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
@@ -249,26 +199,51 @@
 	})
 	h.classesJarPaths = classesJars
 
-	stubFlagsCSV := hiddenAPISingletonPaths(ctx).stubFlags
+	// Save the unencoded dex jar so it can be used when generating the
+	// hiddenAPISingletonPathsStruct.stubFlags file.
+	h.bootDexJarPath = dexJar
+}
 
-	flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv")
+// buildRuleToGenerateAnnotationFlags builds a ninja rule to generate the annotation-flags.csv file
+// from the classes jars and stub-flags.csv files.
+//
+// The annotation-flags.csv file contains mappings from Java signature to various flags derived from
+// annotations in the source, e.g. whether it is public or the sdk version above which it can no
+// longer be used.
+//
+// It is created by the Class2NonSdkList tool which processes the .class files in the class
+// implementation jar looking for UnsupportedAppUsage and CovariantReturnType annotations. The
+// tool also consumes the hiddenAPISingletonPathsStruct.stubFlags file in order to perform
+// consistency checks on the information in the annotations and to filter out bridge methods
+// that are already part of the public API.
+func buildRuleToGenerateAnnotationFlags(ctx android.ModuleContext, desc string, classesJars android.Paths, stubFlagsCSV android.Path, outputPath android.WritablePath) {
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        hiddenAPIGenerateCSVRule,
-		Description: "hiddenapi flags",
+		Description: desc,
 		Inputs:      classesJars,
-		Output:      flagsCSV,
+		Output:      outputPath,
 		Implicit:    stubFlagsCSV,
 		Args: map[string]string{
 			"outFlag":      "--write-flags-csv",
 			"stubAPIFlags": stubFlagsCSV.String(),
 		},
 	})
-	h.flagsCSVPath = flagsCSV
+}
 
-	metadataCSV := android.PathForModuleOut(ctx, "hiddenapi", "metadata.csv")
+// buildRuleToGenerateMetadata builds a ninja rule to generate the metadata.csv file from
+// the classes jars and stub-flags.csv files.
+//
+// The metadata.csv file contains mappings from Java signature to the value of properties specified
+// on UnsupportedAppUsage annotations in the source.
+//
+// Like the annotation-flags.csv file this is also created by the Class2NonSdkList in the same way.
+// Although the two files could potentially be created in a single invocation of the
+// Class2NonSdkList at the moment they are created using their own invocation, with the behavior
+// being determined by the property that is used.
+func buildRuleToGenerateMetadata(ctx android.ModuleContext, desc string, classesJars android.Paths, stubFlagsCSV android.Path, metadataCSV android.WritablePath) {
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        hiddenAPIGenerateCSVRule,
-		Description: "hiddenapi metadata",
+		Description: desc,
 		Inputs:      classesJars,
 		Output:      metadataCSV,
 		Implicit:    stubFlagsCSV,
@@ -277,22 +252,27 @@
 			"stubAPIFlags": stubFlagsCSV.String(),
 		},
 	})
-	h.metadataCSVPath = metadataCSV
+}
 
-	indexCSV := android.PathForModuleOut(ctx, "hiddenapi", "index.csv")
+// buildRuleToGenerateIndex builds a ninja rule to generate the index.csv file from the classes
+// jars.
+//
+// The index.csv file contains mappings from Java signature to source location information.
+//
+// It is created by the merge_csv tool which processes the class implementation jar, extracting
+// all the files ending in .uau (which are CSV files) and merges them together. The .uau files are
+// created by the unsupported app usage annotation processor during compilation of the class
+// implementation jar.
+func buildRuleToGenerateIndex(ctx android.ModuleContext, desc string, classesJars android.Paths, indexCSV android.WritablePath) {
 	rule := android.NewRuleBuilder(pctx, ctx)
 	rule.Command().
 		BuiltTool("merge_csv").
 		Flag("--zip_input").
 		Flag("--key_field signature").
+		FlagWithArg("--header=", "signature,file,startline,startcol,endline,endcol,properties").
 		FlagWithOutput("--output=", indexCSV).
 		Inputs(classesJars)
-	rule.Build("merged-hiddenapi-index", "Merged Hidden API index")
-	h.indexCSVPath = indexCSV
-
-	// Save the unencoded dex jar so it can be used when generating the
-	// hiddenAPISingletonPathsStruct.stubFlags file.
-	h.bootDexJarPath = dexJar
+	rule.Build(desc, desc)
 }
 
 var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", blueprint.RuleParams{
@@ -329,11 +309,7 @@
 	}
 
 	enforceHiddenApiFlagsToAllMembers := true
-	// If frameworks/base doesn't exist we must be building with the 'master-art' manifest.
-	// Disable assertion that all methods/fields have hidden API flags assigned.
-	if !ctx.Config().FrameworksBaseDirExists(ctx) {
-		enforceHiddenApiFlagsToAllMembers = false
-	}
+
 	// b/149353192: when a module is instrumented, jacoco adds synthetic members
 	// $jacocoData and $jacocoInit. Since they don't exist when building the hidden API flags,
 	// don't complain when we don't find hidden API flags for the synthetic members.
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 335f5b8..2dceb65 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -15,6 +15,8 @@
 package java
 
 import (
+	"strings"
+
 	"android/soong/android"
 	"github.com/google/blueprint"
 )
@@ -97,7 +99,12 @@
 	systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
 	testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
 	if config.IsEnvTrue("EMMA_INSTRUMENT") {
+		// Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
+		// allows everyone access but it is needed to ensure consistent flags between the
+		// bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
 		publicStubModules = append(publicStubModules, "jacoco-stubs")
+		systemStubModules = append(systemStubModules, "jacoco-stubs")
+		testStubModules = append(testStubModules, "jacoco-stubs")
 	}
 
 	m := map[android.SdkKind][]string{}
@@ -121,8 +128,21 @@
 
 // hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
 // in hiddenAPIAddStubLibDependencies.
-func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext) map[android.SdkKind]android.Paths {
+func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext, contents []android.Module) map[android.SdkKind]android.Paths {
 	m := map[android.SdkKind]android.Paths{}
+
+	// If the contents includes any java_sdk_library modules then add them to the stubs.
+	for _, module := range contents {
+		if _, ok := module.(SdkLibraryDependency); ok {
+			for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
+				dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
+				if dexJar != nil {
+					m[kind] = append(m[kind], dexJar)
+				}
+			}
+		}
+	}
+
 	ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
 		tag := ctx.OtherModuleDependencyTag(module)
 		if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
@@ -133,6 +153,12 @@
 			}
 		}
 	})
+
+	// Normalize the paths, i.e. remove duplicates and sort.
+	for k, v := range m {
+		m[k] = android.SortedUniquePaths(v)
+	}
+
 	return m
 }
 
@@ -166,7 +192,7 @@
 //
 // The rule is initialized but not built so that the caller can modify it and select an appropriate
 // name.
-func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.OutputPath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
+func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
 	// Singleton rule which applies hiddenapi on all boot class path dex files.
 	rule := android.NewRuleBuilder(pctx, ctx)
 
@@ -338,57 +364,105 @@
 	},
 }
 
-// hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties
+// hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties and also generated
+// by hidden API processing.
+//
+// This is used both for an individual bootclasspath_fragment to provide it to other modules and
+// for a module to collate the files from the fragments it depends upon. That is why the fields are
+// all Paths even though they are initialized with a single path.
 type hiddenAPIFlagFileInfo struct {
 	// categoryToPaths maps from the flag file category to the paths containing information for that
 	// category.
 	categoryToPaths map[*hiddenAPIFlagFileCategory]android.Paths
+
+	// The paths to the generated stub-flags.csv files.
+	StubFlagsPaths android.Paths
+
+	// The paths to the generated annotation-flags.csv files.
+	AnnotationFlagsPaths android.Paths
+
+	// The paths to the generated metadata.csv files.
+	MetadataPaths android.Paths
+
+	// The paths to the generated index.csv files.
+	IndexPaths android.Paths
+
+	// The paths to the generated all-flags.csv files.
+	AllFlagsPaths android.Paths
 }
 
 func (i *hiddenAPIFlagFileInfo) append(other hiddenAPIFlagFileInfo) {
 	for _, category := range hiddenAPIFlagFileCategories {
 		i.categoryToPaths[category] = append(i.categoryToPaths[category], other.categoryToPaths[category]...)
 	}
+	i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPaths...)
+	i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPaths...)
+	i.MetadataPaths = append(i.MetadataPaths, other.MetadataPaths...)
+	i.IndexPaths = append(i.IndexPaths, other.IndexPaths...)
+	i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPaths...)
 }
 
 var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})
 
-// ruleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from the
-// flags from all the modules, the stub flags, augmented with some additional configuration files.
+// pathForValidation creates a path of the same type as the supplied type but with a name of
+// <path>.valid.
+//
+// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
+// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
+func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
+	extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
+	return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
+}
+
+// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
+// the flags from all the modules, the stub flags, augmented with some additional configuration
+// files.
 //
 // baseFlagsPath is the path to the flags file containing all the information from the stubs plus
 // an entry for every single member in the dex implementation jars of the individual modules. Every
 // signature in any of the other files MUST be included in this file.
 //
-// moduleSpecificFlagsPaths are the paths to the flags files generated by each module using
-// information from the baseFlagsPath as well as from annotations within the source.
+// annotationFlags is the path to the annotation flags file generated from annotation information
+// in each module.
 //
-// augmentationInfo is a struct containing paths to files that augment the information provided by
-// the moduleSpecificFlagsPaths.
-// ruleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from the
-// flags from all the modules, the stub flags, augmented with some additional configuration files.
-//
-// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
-// an entry for every single member in the dex implementation jars of the individual modules. Every
-// signature in any of the other files MUST be included in this file.
-//
-// moduleSpecificFlagsPaths are the paths to the flags files generated by each module using
-// information from the baseFlagsPath as well as from annotations within the source.
-//
-// augmentationInfo is a struct containing paths to files that augment the information provided by
-// the moduleSpecificFlagsPaths.
-func ruleToGenerateHiddenApiFlags(ctx android.BuilderContext, outputPath android.WritablePath, baseFlagsPath android.Path, moduleSpecificFlagsPaths android.Paths, augmentationInfo hiddenAPIFlagFileInfo) {
+// flagFileInfo is a struct containing paths to files that augment the information provided by
+// the annotationFlags.
+func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlags android.Path, flagFileInfo *hiddenAPIFlagFileInfo) {
+
+	// The file which is used to record that the flags file is valid.
+	var validFile android.WritablePath
+
+	// If there are flag files that have been generated by fragments on which this depends then use
+	// them to validate the flag file generated by the rules created by this method.
+	if allFlagsPaths := flagFileInfo.AllFlagsPaths; len(allFlagsPaths) > 0 {
+		// The flags file generated by the rule created by this method needs to be validated to ensure
+		// that it is consistent with the flag files generated by the individual fragments.
+
+		validFile = pathForValidation(ctx, outputPath)
+
+		// Create a rule to validate the output from the following rule.
+		rule := android.NewRuleBuilder(pctx, ctx)
+		rule.Command().
+			BuiltTool("verify_overlaps").
+			Input(outputPath).
+			Inputs(allFlagsPaths).
+			// If validation passes then update the file that records that.
+			Text("&& touch").Output(validFile)
+		rule.Build(name+"Validation", desc+" validation")
+	}
+
+	// Create the rule that will generate the flag files.
 	tempPath := tempPathForRestat(ctx, outputPath)
 	rule := android.NewRuleBuilder(pctx, ctx)
 	command := rule.Command().
 		BuiltTool("generate_hiddenapi_lists").
 		FlagWithInput("--csv ", baseFlagsPath).
-		Inputs(moduleSpecificFlagsPaths).
+		Input(annotationFlags).
 		FlagWithOutput("--output ", tempPath)
 
 	// Add the options for the different categories of flag files.
 	for _, category := range hiddenAPIFlagFileCategories {
-		paths := augmentationInfo.categoryToPaths[category]
+		paths := flagFileInfo.categoryToPaths[category]
 		for _, path := range paths {
 			category.commandMutator(command, path)
 		}
@@ -396,5 +470,109 @@
 
 	commitChangeForRestat(rule, tempPath, outputPath)
 
-	rule.Build("hiddenAPIFlagsFile", "hiddenapi flags")
+	if validFile != nil {
+		// Add the file that indicates that the file generated by this is valid.
+		//
+		// This will cause the validation rule above to be run any time that the output of this rule
+		// changes but the validation will run in parallel with other rules that depend on this file.
+		command.Validation(validFile)
+	}
+
+	rule.Build(name, desc)
+}
+
+// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment
+// of the bootclasspath.
+//
+// It takes:
+// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
+// * The list of modules that are the contents of the fragment.
+// * The additional manually curated flag files to use.
+//
+// It generates:
+// * stub-flags.csv
+// * annotation-flags.csv
+// * metadata.csv
+// * index.csv
+// * all-flags.csv
+func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
+	hiddenApiSubDir := "modular-hiddenapi"
+
+	// Generate the stub-flags.csv.
+	bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents)
+	stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
+	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, stubJarsByKind)
+	rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
+
+	// Extract the classes jars from the contents.
+	classesJars := extractClassJarsFromHiddenAPIModules(ctx, contents)
+
+	// Generate the set of flags from the annotations in the source code.
+	annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
+	buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
+
+	// Generate the metadata from the annotations in the source code.
+	metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
+	buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
+
+	// Generate the index file from the CSV files in the classes jars.
+	indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
+	buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
+
+	// Removed APIs need to be marked and in order to do that the flagFileInfo needs to specify files
+	// containing dex signatures of all the removed APIs. In the monolithic files that is done by
+	// manually combining all the removed.txt files for each API and then converting them to dex
+	// signatures, see the combined-removed-dex module. That will all be done automatically in future.
+	// For now removed APIs are ignored.
+	// TODO(b/179354495): handle removed apis automatically.
+
+	// Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
+	// files.
+	outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
+	buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, flagFileInfo)
+
+	// Store the paths in the info for use by other modules and sdk snapshot generation.
+	flagFileInfo.StubFlagsPaths = android.Paths{stubFlagsCSV}
+	flagFileInfo.AnnotationFlagsPaths = android.Paths{annotationFlagsCSV}
+	flagFileInfo.MetadataPaths = android.Paths{metadataCSV}
+	flagFileInfo.IndexPaths = android.Paths{indexCSV}
+	flagFileInfo.AllFlagsPaths = android.Paths{outputPath}
+}
+
+// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents.
+func gatherHiddenAPIModuleFromContents(ctx android.ModuleContext, contents []android.Module) []hiddenAPIModule {
+	hiddenAPIModules := []hiddenAPIModule{}
+	for _, module := range contents {
+		if hiddenAPI, ok := module.(hiddenAPIModule); ok {
+			hiddenAPIModules = append(hiddenAPIModules, hiddenAPI)
+		} else if _, ok := module.(*DexImport); ok {
+			// Ignore this for the purposes of hidden API processing
+		} else {
+			ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
+		}
+	}
+	return hiddenAPIModules
+}
+
+// extractBootDexJarsFromHiddenAPIModules extracts the boot dex jars from the supplied modules.
+func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
+	bootDexJars := android.Paths{}
+	for _, module := range contents {
+		bootDexJar := module.bootDexJar()
+		if bootDexJar == nil {
+			ctx.ModuleErrorf("module %s does not provide a dex jar", module)
+		} else {
+			bootDexJars = append(bootDexJars, bootDexJar)
+		}
+	}
+	return bootDexJars
+}
+
+// extractClassJarsFromHiddenAPIModules extracts the class jars from the supplied modules.
+func extractClassJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
+	classesJars := android.Paths{}
+	for _, module := range contents {
+		classesJars = append(classesJars, module.classesJars()...)
+	}
+	return classesJars
 }
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 676a0e7..848aa59 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -117,7 +117,6 @@
 }
 
 type hiddenAPISingleton struct {
-	flags android.Path
 }
 
 // hiddenAPI singleton rules
@@ -136,17 +135,10 @@
 	// consistency.
 
 	if ctx.Config().PrebuiltHiddenApiDir(ctx) != "" {
-		h.flags = prebuiltFlagsRule(ctx)
+		prebuiltFlagsRule(ctx)
 		prebuiltIndexRule(ctx)
 		return
 	}
-
-	// These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them.
-	if ctx.Config().FrameworksBaseDirExists(ctx) {
-		h.flags = flagsRule(ctx)
-	} else {
-		h.flags = emptyFlagsRule(ctx)
-	}
 }
 
 // Checks to see whether the supplied module variant is in the list of boot jars.
@@ -187,7 +179,7 @@
 	return true
 }
 
-func prebuiltFlagsRule(ctx android.SingletonContext) android.Path {
+func prebuiltFlagsRule(ctx android.SingletonContext) {
 	outputPath := hiddenAPISingletonPaths(ctx).flags
 	inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-flags.csv")
 
@@ -196,8 +188,6 @@
 		Output: outputPath,
 		Input:  inputPath,
 	})
-
-	return outputPath
 }
 
 func prebuiltIndexRule(ctx android.SingletonContext) {
@@ -211,28 +201,6 @@
 	})
 }
 
-// flagsRule is a placeholder that simply returns the location of the file, the generation of the
-// ninja rules is done in generateHiddenAPIBuildActions.
-func flagsRule(ctx android.SingletonContext) android.Path {
-	outputPath := hiddenAPISingletonPaths(ctx).flags
-	return outputPath
-}
-
-// emptyFlagsRule creates a rule to build an empty hiddenapi-flags.csv, which is needed by master-art-host builds that
-// have a partial manifest without frameworks/base but still need to build a boot image.
-func emptyFlagsRule(ctx android.SingletonContext) android.Path {
-	rule := android.NewRuleBuilder(pctx, ctx)
-
-	outputPath := hiddenAPISingletonPaths(ctx).flags
-
-	rule.Command().Text("rm").Flag("-f").Output(outputPath)
-	rule.Command().Text("touch").Output(outputPath)
-
-	rule.Build("emptyHiddenAPIFlagsFile", "empty hiddenapi flags")
-
-	return outputPath
-}
-
 // tempPathForRestat creates a path of the same type as the supplied type but with a name of
 // <path>.tmp.
 //
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 3ab2277..e6b45ac 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -60,10 +60,7 @@
 }
 
 func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) {
-	expectedErrorMessage :=
-		"hiddenapi has determined that the source module \"foo\" should be ignored as it has been" +
-			" replaced by the prebuilt module \"prebuilt_foo\" but unfortunately it does not provide a" +
-			" suitable boot dex jar"
+	expectedErrorMessage := "module prebuilt_foo{os:android,arch:common} does not provide a dex jar"
 
 	android.GroupFixturePreparers(
 		hiddenApiFixtureFactory,
diff --git a/java/java.go b/java/java.go
index 9a5fbfc..f85de3d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1315,7 +1315,7 @@
 			di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
 			if dexOutputPath := di.PrebuiltExportPath(j.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
 				j.dexJarFile = dexOutputPath
-				j.hiddenAPIExtractInformation(ctx, dexOutputPath, outputFile)
+				j.hiddenAPIUpdatePaths(ctx, dexOutputPath, outputFile)
 			} else {
 				// This should never happen as a variant for a prebuilt_apex is only created if the
 				// prebuilt_apex has been configured to export the java library dex file.
@@ -1346,9 +1346,11 @@
 				return
 			}
 
-			// Hidden API CSV generation and dex encoding
-			dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, outputFile,
-				proptools.Bool(j.dexProperties.Uncompress_dex))
+			// Update hidden API paths.
+			j.hiddenAPIUpdatePaths(ctx, dexOutputFile, outputFile)
+
+			// Encode hidden API flags in dex file.
+			dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile, proptools.Bool(j.dexProperties.Uncompress_dex))
 
 			j.dexJarFile = dexOutputFile
 		}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 1feed3d..c8fafed 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -257,17 +257,6 @@
 	return defaultBootImageConfig(ctx)
 }
 
-// hiddenAPISupportingModule encapsulates the information provided by any module that contributes to
-// the hidden API processing.
-type hiddenAPISupportingModule struct {
-	module android.Module
-
-	bootDexJar  android.Path
-	flagsCSV    android.Path
-	indexCSV    android.Path
-	metadataCSV android.Path
-}
-
 // generateHiddenAPIBuildActions generates all the hidden API related build rules.
 func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) {
 
@@ -290,67 +279,6 @@
 		return
 	}
 
-	// nilPathHandler will check the supplied path and if it is nil then it will either immediately
-	// report an error, or it will defer the error reporting until it is actually used, depending
-	// whether missing dependencies are allowed.
-	var nilPathHandler func(path android.Path, name string, module android.Module) android.Path
-	if ctx.Config().AllowMissingDependencies() {
-		nilPathHandler = func(path android.Path, name string, module android.Module) android.Path {
-			if path == nil {
-				outputPath := android.PathForModuleOut(ctx, "missing", module.Name(), name)
-				path = outputPath
-
-				// Create an error rule that pretends to create the output file but will actually fail if it
-				// is run.
-				ctx.Build(pctx, android.BuildParams{
-					Rule:   android.ErrorRule,
-					Output: outputPath,
-					Args: map[string]string{
-						"error": fmt.Sprintf("missing hidden API file: %s for %s", name, module),
-					},
-				})
-			}
-			return path
-		}
-	} else {
-		nilPathHandler = func(path android.Path, name string, module android.Module) android.Path {
-			if path == nil {
-				ctx.ModuleErrorf("module %s does not provide a %s file", module, name)
-			}
-			return path
-		}
-	}
-
-	hiddenAPISupportingModules := []hiddenAPISupportingModule{}
-	for _, module := range modules {
-		if h, ok := module.(hiddenAPIIntf); ok {
-			hiddenAPISupportingModule := hiddenAPISupportingModule{
-				module:      module,
-				bootDexJar:  nilPathHandler(h.bootDexJar(), "bootDexJar", module),
-				flagsCSV:    nilPathHandler(h.flagsCSV(), "flagsCSV", module),
-				indexCSV:    nilPathHandler(h.indexCSV(), "indexCSV", module),
-				metadataCSV: nilPathHandler(h.metadataCSV(), "metadataCSV", module),
-			}
-
-			// If any errors were reported when trying to populate the hiddenAPISupportingModule struct
-			// then don't add it to the list.
-			if ctx.Failed() {
-				continue
-			}
-
-			hiddenAPISupportingModules = append(hiddenAPISupportingModules, hiddenAPISupportingModule)
-		} else if _, ok := module.(*DexImport); ok {
-			// Ignore this for the purposes of hidden API processing
-		} else {
-			ctx.ModuleErrorf("module %s of type %s does not support hidden API processing", module, ctx.OtherModuleType(module))
-		}
-	}
-
-	moduleSpecificFlagsPaths := android.Paths{}
-	for _, module := range hiddenAPISupportingModules {
-		moduleSpecificFlagsPaths = append(moduleSpecificFlagsPaths, module.flagsCSV)
-	}
-
 	flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
 	for _, fragment := range fragments {
 		if ctx.OtherModuleHasProvider(fragment, hiddenAPIFlagFileInfoProvider) {
@@ -362,61 +290,53 @@
 	// Store the information for testing.
 	ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
 
-	outputPath := hiddenAPISingletonPaths(ctx).flags
-	baseFlagsPath := hiddenAPISingletonPaths(ctx).stubFlags
-	ruleToGenerateHiddenApiFlags(ctx, outputPath, baseFlagsPath, moduleSpecificFlagsPaths, flagFileInfo)
+	hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, modules)
 
-	b.generateHiddenAPIStubFlagsRules(ctx, hiddenAPISupportingModules)
-	b.generateHiddenAPIIndexRules(ctx, hiddenAPISupportingModules)
-	b.generatedHiddenAPIMetadataRules(ctx, hiddenAPISupportingModules)
-}
+	sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx, nil)
 
-func (b *platformBootclasspathModule) generateHiddenAPIStubFlagsRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
-	bootDexJars := android.Paths{}
-	for _, module := range modules {
-		bootDexJars = append(bootDexJars, module.bootDexJar)
-	}
-
-	sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx)
-
-	outputPath := hiddenAPISingletonPaths(ctx).stubFlags
-	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, outputPath, bootDexJars, sdkKindToStubPaths)
+	// Generate the monolithic stub-flags.csv file.
+	bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, hiddenAPIModules)
+	stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
+	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, sdkKindToStubPaths)
 	rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
+
+	// Extract the classes jars from the contents.
+	classesJars := extractClassJarsFromHiddenAPIModules(ctx, hiddenAPIModules)
+
+	// Generate the annotation-flags.csv file from all the module annotations.
+	annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags.csv")
+	buildRuleToGenerateAnnotationFlags(ctx, "monolithic hiddenapi flags", classesJars, stubFlags, annotationFlags)
+
+	// Generate the monotlithic hiddenapi-flags.csv file.
+	allFlags := hiddenAPISingletonPaths(ctx).flags
+	buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "hiddenapi flags", allFlags, stubFlags, annotationFlags, &flagFileInfo)
+
+	// Generate an intermediate monolithic hiddenapi-metadata.csv file directly from the annotations
+	// in the source code.
+	intermediateMetadataCSV := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "intermediate-metadata.csv")
+	buildRuleToGenerateMetadata(ctx, "monolithic hidden API metadata", classesJars, stubFlags, intermediateMetadataCSV)
+
+	// Reformat the intermediate file to add | quotes just in case that is important for the tools
+	// that consume the metadata file.
+	// TODO(b/179354495): Investigate whether it is possible to remove this reformatting step.
+	metadataCSV := hiddenAPISingletonPaths(ctx).metadata
+	b.buildRuleMergeCSV(ctx, "reformat monolithic hidden API metadata", android.Paths{intermediateMetadataCSV}, metadataCSV)
+
+	// Generate the monolithic hiddenapi-index.csv file directly from the CSV files in the classes
+	// jars.
+	indexCSV := hiddenAPISingletonPaths(ctx).index
+	buildRuleToGenerateIndex(ctx, "monolithic hidden API index", classesJars, indexCSV)
 }
 
-func (b *platformBootclasspathModule) generateHiddenAPIIndexRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
-	indexes := android.Paths{}
-	for _, module := range modules {
-		indexes = append(indexes, module.indexCSV)
-	}
-
+func (b *platformBootclasspathModule) buildRuleMergeCSV(ctx android.ModuleContext, desc string, inputPaths android.Paths, outputPath android.WritablePath) {
 	rule := android.NewRuleBuilder(pctx, ctx)
 	rule.Command().
 		BuiltTool("merge_csv").
 		Flag("--key_field signature").
-		FlagWithArg("--header=", "signature,file,startline,startcol,endline,endcol,properties").
-		FlagWithOutput("--output=", hiddenAPISingletonPaths(ctx).index).
-		Inputs(indexes)
-	rule.Build("platform-bootclasspath-monolithic-hiddenapi-index", "monolithic hidden API index")
-}
-
-func (b *platformBootclasspathModule) generatedHiddenAPIMetadataRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
-	metadataCSVFiles := android.Paths{}
-	for _, module := range modules {
-		metadataCSVFiles = append(metadataCSVFiles, module.metadataCSV)
-	}
-
-	rule := android.NewRuleBuilder(pctx, ctx)
-
-	outputPath := hiddenAPISingletonPaths(ctx).metadata
-
-	rule.Command().
-		BuiltTool("merge_csv").
-		Flag("--key_field signature").
 		FlagWithOutput("--output=", outputPath).
-		Inputs(metadataCSVFiles)
+		Inputs(inputPaths)
 
-	rule.Build("platform-bootclasspath-monolithic-hiddenapi-metadata", "monolithic hidden API metadata")
+	rule.Build(desc, desc)
 }
 
 // generateHiddenApiMakeVars generates make variables needed by hidden API related make rules, e.g.
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index 98d4614..efcbc80 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -155,6 +155,8 @@
 func TestPlatformBootclasspath_Fragments(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		prepareForTestWithPlatformBootclasspath,
+		PrepareForTestWithJavaSdkLibraryFiles,
+		FixtureWithLastReleaseApis("foo"),
 		android.FixtureWithRootAndroidBp(`
 			platform_bootclasspath {
 				name: "platform-bootclasspath",
@@ -192,6 +194,9 @@
 			bootclasspath_fragment {
 				name: "bar-fragment",
 				contents: ["bar"],
+				api: {
+					stub_libs: ["foo"],
+				},
 				hidden_api: {
 					unsupported: [
 							"bar-unsupported.txt",
@@ -227,6 +232,15 @@
 				sdk_version: "none",
 				compile_dex: true,
 			}
+
+			java_sdk_library {
+				name: "foo",
+				srcs: ["a.java"],
+				public: {
+					enabled: true,
+				},
+				compile_dex: true,
+			}
 		`),
 	).RunTest(t)
 
@@ -240,6 +254,12 @@
 		expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
 		android.AssertPathsRelativeToTopEquals(t, message, expected, info.categoryToPaths[category])
 	}
+
+	android.AssertPathsRelativeToTopEquals(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/stub-flags.csv"}, info.StubFlagsPaths)
+	android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
+	android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
+	android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/index.csv"}, info.IndexPaths)
+	android.AssertPathsRelativeToTopEquals(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/all-flags.csv"}, info.AllFlagsPaths)
 }
 
 func TestPlatformBootclasspathVariant(t *testing.T) {
@@ -407,20 +427,14 @@
 		}
 	`)
 
-	platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common")
-	indexRule := platformBootclasspath.Rule("platform-bootclasspath-monolithic-hiddenapi-index")
-	CheckHiddenAPIRuleInputs(t, `
-.intermediates/bar/android_common/hiddenapi/index.csv
-.intermediates/foo/android_common/hiddenapi/index.csv
-`,
-		indexRule)
-
 	// Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that
 	// creates the index.csv file.
-	foo := result.ModuleForTests("foo", "android_common")
-	indexParams := foo.Output("hiddenapi/index.csv")
+	platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common")
+	indexRule := platformBootclasspath.Rule("monolithic_hidden_API_index")
 	CheckHiddenAPIRuleInputs(t, `
+.intermediates/bar/android_common/javac/bar.jar
 .intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar
 .intermediates/foo/android_common/javac/foo.jar
-`, indexParams)
+`,
+		indexRule)
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 7804512..f04f837 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -900,11 +900,17 @@
 	return componentProps
 }
 
-// Check if this can be used as a shared library.
 func (c *commonToSdkLibraryAndImport) sharedLibrary() bool {
 	return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true)
 }
 
+// Check if the stub libraries should be compiled for dex
+func (c *commonToSdkLibraryAndImport) stubLibrariesCompiledForDex() bool {
+	// Always compile the dex file files for the stub libraries if they will be used on the
+	// bootclasspath.
+	return !c.sharedLibrary()
+}
+
 // Properties related to the use of a module as an component of a java_sdk_library.
 type SdkLibraryComponentProperties struct {
 
@@ -978,6 +984,9 @@
 	// SdkApiStubDexJar returns the dex jar for the stubs. It is needed by the hiddenapi processing
 	// tool which processes dex files.
 	SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path
+
+	// sharedLibrary returns true if this can be used as a shared library.
+	sharedLibrary() bool
 }
 
 type SdkLibrary struct {
@@ -1309,9 +1318,13 @@
 	// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
 	// interop with older developer tools that don't support 1.9.
 	props.Java_version = proptools.StringPtr("1.8")
-	if module.dexProperties.Compile_dex != nil {
-		props.Compile_dex = module.dexProperties.Compile_dex
+
+	// The imports need to be compiled to dex if the java_sdk_library requests it.
+	compileDex := module.dexProperties.Compile_dex
+	if module.stubLibrariesCompiledForDex() {
+		compileDex = proptools.BoolPtr(true)
 	}
+	props.Compile_dex = compileDex
 
 	// Dist the class jar artifact for sdk builds.
 	if !Bool(module.sdkLibraryProperties.No_dist) {
@@ -1969,7 +1982,11 @@
 	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
 
 	// The imports need to be compiled to dex if the java_sdk_library_import requests it.
-	props.Compile_dex = module.properties.Compile_dex
+	compileDex := module.properties.Compile_dex
+	if module.stubLibrariesCompiledForDex() {
+		compileDex = proptools.BoolPtr(true)
+	}
+	props.Compile_dex = compileDex
 
 	mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
 }
@@ -2111,7 +2128,7 @@
 			if dexOutputPath := di.PrebuiltExportPath(module.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
 				module.dexJarFile = dexOutputPath
 				module.initHiddenAPI(ctx, module.configurationName)
-				module.hiddenAPIExtractInformation(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0])
+				module.hiddenAPIUpdatePaths(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0])
 			} else {
 				// This should never happen as a variant for a prebuilt_apex is only created if the
 				// prebuilt_apex has been configured to export the java library dex file.
diff --git a/scripts/build-rustdocs.sh b/scripts/build-rustdocs.sh
new file mode 100755
index 0000000..ad8ba16
--- /dev/null
+++ b/scripts/build-rustdocs.sh
@@ -0,0 +1,31 @@
+#!/bin/bash -ex
+
+# 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.
+
+# Builds the platform rustdocs and copies them to the dist directory to provide
+# online docs for each build.
+
+if [ -z "${OUT_DIR}" ]; then
+    echo Must set OUT_DIR
+    exit 1
+fi
+
+source build/envsetup.sh
+m rustdoc
+
+if [ -n "${DIST_DIR}" ]; then
+    mkdir -p ${DIST_DIR}
+    cp -r ${OUT_DIR}/soong/rustdoc $DIST_DIR/rustdoc
+fi
diff --git a/scripts/hiddenapi/Android.bp b/scripts/hiddenapi/Android.bp
index af7e7fe..7472f52 100644
--- a/scripts/hiddenapi/Android.bp
+++ b/scripts/hiddenapi/Android.bp
@@ -47,3 +47,18 @@
         },
     },
 }
+
+python_binary_host {
+    name: "verify_overlaps",
+    main: "verify_overlaps.py",
+    srcs: ["verify_overlaps.py"],
+    version: {
+        py2: {
+            enabled: false,
+        },
+        py3: {
+            enabled: true,
+            embedded_launcher: true,
+        },
+    },
+}
diff --git a/scripts/hiddenapi/verify_overlaps.py b/scripts/hiddenapi/verify_overlaps.py
new file mode 100755
index 0000000..c8e3879
--- /dev/null
+++ b/scripts/hiddenapi/verify_overlaps.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 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.
+"""
+Verify that one set of hidden API flags is a subset of another.
+"""
+
+import argparse
+import csv
+
+args_parser = argparse.ArgumentParser(description='Verify that one set of hidden API flags is a subset of another.')
+args_parser.add_argument('all', help='All the flags')
+args_parser.add_argument('subsets', nargs=argparse.REMAINDER, help='Subsets of the flags')
+args = args_parser.parse_args()
+
+
+def dict_reader(input):
+    return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature'])
+
+# Read in all the flags into a dict indexed by signature
+allFlagsBySignature = {}
+with open(args.all, 'r') as allFlagsFile:
+    allFlagsReader = dict_reader(allFlagsFile)
+    for row in allFlagsReader:
+        signature = row['signature']
+        allFlagsBySignature[signature]=row
+
+failed = False
+for subsetPath in args.subsets:
+    mismatchingSignatures = []
+    with open(subsetPath, 'r') as subsetFlagsFile:
+        subsetReader = dict_reader(subsetFlagsFile)
+        for row in subsetReader:
+            signature = row['signature']
+            if signature in allFlagsBySignature:
+                allFlags = allFlagsBySignature.get(signature)
+                if allFlags != row:
+                    mismatchingSignatures.append((signature, row[None], allFlags[None]))
+            else:
+                mismatchingSignatures.append((signature, row[None], []))
+
+
+    if mismatchingSignatures:
+        failed = True
+        print("ERROR: Hidden API flags are inconsistent:")
+        print("< " + subsetPath)
+        print("> " + args.all)
+        for mismatch in mismatchingSignatures:
+            print()
+            print("< " + mismatch[0] + "," + ",".join(mismatch[1]))
+            if mismatch[2] != None:
+                print("> " + mismatch[0] + "," + ",".join(mismatch[2]))
+            else:
+                print("> " + mismatch[0] + " - missing")
+
+if failed:
+    sys.exit(1)
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index f18e697..bd69f06 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -165,21 +165,33 @@
 		prepareForSdkTestWithJava,
 		java.PrepareForTestWithJavaDefaultModules,
 		java.PrepareForTestWithJavaSdkLibraryFiles,
-		java.FixtureWithLastReleaseApis("mysdklibrary", "mycoreplatform"),
+		java.FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
 		android.FixtureWithRootAndroidBp(`
 			sdk {
 				name: "mysdk",
 				bootclasspath_fragments: ["mybootclasspathfragment"],
-				java_sdk_libs: ["mysdklibrary", "mycoreplatform"],
+				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",
+				],
 			}
 
 			bootclasspath_fragment {
 				name: "mybootclasspathfragment",
-				contents: ["mybootlib"],
+				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"],
 				},
 			}
@@ -195,14 +207,21 @@
 			java_sdk_library {
 				name: "mysdklibrary",
 				srcs: ["Test.java"],
-				compile_dex: true,
+				shared_library: false,
+				public: {enabled: true},
+			}
+
+			java_sdk_library {
+				name: "myothersdklibrary",
+				srcs: ["Test.java"],
+				shared_library: false,
 				public: {enabled: true},
 			}
 
 			java_sdk_library {
 				name: "mycoreplatform",
 				srcs: ["Test.java"],
-				compile_dex: true,
+				shared_library: false,
 				public: {enabled: true},
 			}
 		`),
@@ -217,13 +236,23 @@
     prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
-    contents: ["mybootlib"],
+    contents: [
+        "mybootlib",
+        "myothersdklibrary",
+    ],
     api: {
         stub_libs: ["mysdklibrary"],
     },
     core_platform_api: {
         stub_libs: ["mycoreplatform"],
     },
+    hidden_api: {
+        stub_flags: "hiddenapi/stub-flags.csv",
+        annotation_flags: "hiddenapi/annotation-flags.csv",
+        metadata: "hiddenapi/metadata.csv",
+        index: "hiddenapi/index.csv",
+        all_flags: "hiddenapi/all-flags.csv",
+    },
 }
 
 java_import {
@@ -235,12 +264,26 @@
 }
 
 java_sdk_library_import {
+    name: "myothersdklibrary",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    shared_library: false,
+    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: ["//apex_available:platform"],
-    shared_library: true,
-    compile_dex: true,
+    shared_library: false,
     public: {
         jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
         stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
@@ -255,8 +298,7 @@
     prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
-    shared_library: true,
-    compile_dex: true,
+    shared_library: false,
     public: {
         jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
         stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
@@ -265,7 +307,7 @@
         sdk_version: "current",
     },
 }
-`),
+		`),
 		checkVersionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -274,13 +316,23 @@
     sdk_member_name: "mybootclasspathfragment",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
-    contents: ["mysdk_mybootlib@current"],
+    contents: [
+        "mysdk_mybootlib@current",
+        "mysdk_myothersdklibrary@current",
+    ],
     api: {
         stub_libs: ["mysdk_mysdklibrary@current"],
     },
     core_platform_api: {
         stub_libs: ["mysdk_mycoreplatform@current"],
     },
+    hidden_api: {
+        stub_flags: "hiddenapi/stub-flags.csv",
+        annotation_flags: "hiddenapi/annotation-flags.csv",
+        metadata: "hiddenapi/metadata.csv",
+        index: "hiddenapi/index.csv",
+        all_flags: "hiddenapi/all-flags.csv",
+    },
 }
 
 java_import {
@@ -292,12 +344,26 @@
 }
 
 java_sdk_library_import {
+    name: "mysdk_myothersdklibrary@current",
+    sdk_member_name: "myothersdklibrary",
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    shared_library: false,
+    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: "mysdk_mysdklibrary@current",
     sdk_member_name: "mysdklibrary",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
-    shared_library: true,
-    compile_dex: true,
+    shared_library: false,
     public: {
         jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
         stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
@@ -312,8 +378,7 @@
     sdk_member_name: "mycoreplatform",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
-    shared_library: true,
-    compile_dex: true,
+    shared_library: false,
     public: {
         jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
         stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
@@ -329,13 +394,22 @@
     bootclasspath_fragments: ["mysdk_mybootclasspathfragment@current"],
     java_boot_libs: ["mysdk_mybootlib@current"],
     java_sdk_libs: [
+        "mysdk_myothersdklibrary@current",
         "mysdk_mysdklibrary@current",
         "mysdk_mycoreplatform@current",
     ],
 }
-`),
+		`),
 		checkAllCopyRules(`
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
+.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/all-flags.csv -> hiddenapi/all-flags.csv
 .intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
+.intermediates/myothersdklibrary.stubs/android_common/javac/myothersdklibrary.stubs.jar -> sdk_library/public/myothersdklibrary-stubs.jar
+.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
+.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
 .intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
 .intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
 .intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
@@ -487,6 +561,11 @@
         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"],
+        stub_flags: "hiddenapi/stub-flags.csv",
+        annotation_flags: "hiddenapi/annotation-flags.csv",
+        metadata: "hiddenapi/metadata.csv",
+        index: "hiddenapi/index.csv",
+        all_flags: "hiddenapi/all-flags.csv",
     },
 }
 
@@ -523,6 +602,11 @@
 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/stub-flags.csv -> hiddenapi/stub-flags.csv
+.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/all-flags.csv -> hiddenapi/all-flags.csv
 .intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
 .intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
 .intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt