Merge "Add the new NetworkStack shim libraries to APEX allowed deps."
diff --git a/android/Android.bp b/android/Android.bp
index 00139d8..a8fa53a 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -22,6 +22,7 @@
         "api_levels.go",
         "arch.go",
         "arch_list.go",
+        "bazel.go",
         "bazel_handler.go",
         "config.go",
         "csuite_config.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 5856851..32d7712 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -141,7 +141,20 @@
 	entryOrder []string
 }
 
-type AndroidMkExtraEntriesFunc func(entries *AndroidMkEntries)
+type AndroidMkExtraEntriesContext interface {
+	Provider(provider blueprint.ProviderKey) interface{}
+}
+
+type androidMkExtraEntriesContext struct {
+	ctx fillInEntriesContext
+	mod blueprint.Module
+}
+
+func (a *androidMkExtraEntriesContext) Provider(provider blueprint.ProviderKey) interface{} {
+	return a.ctx.ModuleProvider(a.mod, provider)
+}
+
+type AndroidMkExtraEntriesFunc func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries)
 type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string)
 
 // Utility funcs to manipulate Android.mk variable entries.
@@ -448,7 +461,13 @@
 
 // fillInEntries goes through the common variable processing and calls the extra data funcs to
 // generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
-func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) {
+type fillInEntriesContext interface {
+	ModuleDir(module blueprint.Module) string
+	Config() Config
+	ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
+}
+
+func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
 	a.EntryMap = make(map[string][]string)
 	amod := mod.(Module).base()
 	name := amod.BaseModuleName()
@@ -470,7 +489,7 @@
 	fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)")
 
 	// Collect make variable assignment entries.
-	a.SetString("LOCAL_PATH", filepath.Dir(bpPath))
+	a.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
 	a.SetString("LOCAL_MODULE", name+a.SubName)
 	a.AddStrings("LOCAL_LICENSE_KINDS", amod.commonProperties.Effective_license_kinds...)
 	a.AddStrings("LOCAL_LICENSE_CONDITIONS", amod.commonProperties.Effective_license_conditions...)
@@ -561,17 +580,23 @@
 
 		}
 
-		if amod.Arch().ArchType != config.Targets[amod.Os()][0].Arch.ArchType {
+		if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType {
 			prefix = "2ND_" + prefix
 		}
 	}
+
+	extraCtx := &androidMkExtraEntriesContext{
+		ctx: ctx,
+		mod: mod,
+	}
+
 	for _, extra := range a.ExtraEntries {
-		extra(a)
+		extra(extraCtx, a)
 	}
 
 	// Write to footer.
 	fmt.Fprintln(&a.footer, "include "+a.Include)
-	blueprintDir := filepath.Dir(bpPath)
+	blueprintDir := ctx.ModuleDir(mod)
 	for _, footerFunc := range a.ExtraFooters {
 		footerFunc(&a.footer, name, prefix, blueprintDir)
 	}
@@ -732,7 +757,7 @@
 	return nil
 }
 
-func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprint.Module) {
+func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod blueprint.Module) {
 	// Get the preamble content through AndroidMkEntries logic.
 	data.Entries = AndroidMkEntries{
 		Class:           data.Class,
@@ -745,7 +770,7 @@
 		Host_required:   data.Host_required,
 		Target_required: data.Target_required,
 	}
-	data.Entries.fillInEntries(config, bpPath, mod)
+	data.Entries.fillInEntries(ctx, mod)
 
 	// copy entries back to data since it is used in Custom
 	data.Required = data.Entries.Required
@@ -768,7 +793,7 @@
 		data.Include = "$(BUILD_PREBUILT)"
 	}
 
-	data.fillInData(ctx.Config(), ctx.BlueprintFile(mod), mod)
+	data.fillInData(ctx, mod)
 
 	prefix := ""
 	if amod.ArchSpecific() {
@@ -795,7 +820,7 @@
 	if data.Custom != nil {
 		// List of module types allowed to use .Custom(...)
 		// Additions to the list require careful review for proper license handling.
-		switch reflect.TypeOf(mod).String() {  // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type
+		switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type
 		case "*aidl.aidlApi": // writes non-custom before adding .phony
 		case "*aidl.aidlMapping": // writes non-custom before adding .phony
 		case "*android.customModule": // appears in tests only
@@ -850,7 +875,7 @@
 
 	// Any new or special cases here need review to verify correct propagation of license information.
 	for _, entries := range provider.AndroidMkEntries() {
-		entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
+		entries.fillInEntries(ctx, mod)
 		entries.write(w)
 	}
 
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
index 347b92e..2f568fb 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -137,9 +137,9 @@
 	return module
 }
 
-// buildConfigAndCustomModuleFoo creates a config object, processes the supplied
+// buildContextAndCustomModuleFoo creates a config object, processes the supplied
 // bp module and then returns the config and the custom module called "foo".
-func buildConfigAndCustomModuleFoo(t *testing.T, bp string) (Config, *customModule) {
+func buildContextAndCustomModuleFoo(t *testing.T, bp string) (*TestContext, *customModule) {
 	t.Helper()
 	config := TestConfig(buildDir, nil, bp, nil)
 	config.katiEnabled = true // Enable androidmk Singleton
@@ -155,7 +155,7 @@
 	FailIfErrored(t, errs)
 
 	module := ctx.ModuleForTests("foo", "").Module().(*customModule)
-	return config, module
+	return ctx, module
 }
 
 func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testing.T) {
@@ -168,7 +168,7 @@
 	}
 	`
 
-	_, m := buildConfigAndCustomModuleFoo(t, bp)
+	_, m := buildContextAndCustomModuleFoo(t, bp)
 
 	assertEqual := func(expected interface{}, actual interface{}) {
 		if !reflect.DeepEqual(expected, actual) {
@@ -253,8 +253,8 @@
 		"$(call dist-for-goals,my_goal my_other_goal,three/four.out:four.out)\n",
 	}
 
-	config, module := buildConfigAndCustomModuleFoo(t, bp)
-	entries := AndroidMkEntriesForTest(t, config, "", module)
+	ctx, module := buildContextAndCustomModuleFoo(t, bp)
+	entries := AndroidMkEntriesForTest(t, ctx, module)
 	if len(entries) != 1 {
 		t.Errorf("Expected a single AndroidMk entry, got %d", len(entries))
 	}
@@ -343,8 +343,8 @@
 		t.Run(name, func(t *testing.T) {
 			t.Helper()
 
-			config, module := buildConfigAndCustomModuleFoo(t, bp)
-			entries := AndroidMkEntriesForTest(t, config, "", module)
+			ctx, module := buildContextAndCustomModuleFoo(t, bp)
+			entries := AndroidMkEntriesForTest(t, ctx, module)
 			if len(entries) != 1 {
 				t.Errorf("Expected a single AndroidMk entry, got %d", len(entries))
 			}
diff --git a/android/apex.go b/android/apex.go
index 4637942..81f8c86 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -739,6 +739,8 @@
 
 	d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath
 	WriteFileRule(ctx, d.flatListPath, flatContent.String())
+
+	ctx.Phony(fmt.Sprintf("%s-depsinfo", ctx.ModuleName()), d.fullListPath, d.flatListPath)
 }
 
 // TODO(b/158059172): remove minSdkVersion allowlist
diff --git a/android/bazel.go b/android/bazel.go
new file mode 100644
index 0000000..9939bd5
--- /dev/null
+++ b/android/bazel.go
@@ -0,0 +1,57 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import "android/soong/bazel"
+
+// BazelModuleBase contains the property structs with metadata for modules which can be converted to
+// Bazel.
+type BazelModuleBase struct {
+	bazelProperties bazel.Properties
+}
+
+// Bazelable is specifies the interface for modules that can be converted to Bazel.
+type Bazelable interface {
+	bazelProps() *bazel.Properties
+	GetBazelLabel() string
+	ConvertWithBp2build() bool
+}
+
+// BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules.
+type BazelModule interface {
+	Module
+	Bazelable
+}
+
+// InitBazelModule is a wrapper function that decorates a BazelModule with Bazel-conversion
+// properties.
+func InitBazelModule(module BazelModule) {
+	module.AddProperties(module.bazelProps())
+}
+
+// bazelProps returns the Bazel properties for the given BazelModuleBase.
+func (b *BazelModuleBase) bazelProps() *bazel.Properties {
+	return &b.bazelProperties
+}
+
+// GetBazelLabel returns the Bazel label for the given BazelModuleBase.
+func (b *BazelModuleBase) GetBazelLabel() string {
+	return b.bazelProperties.Bazel_module.Label
+}
+
+// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
+func (b *BazelModuleBase) ConvertWithBp2build() bool {
+	return b.bazelProperties.Bazel_module.Bp2build_available
+}
diff --git a/android/config.go b/android/config.go
index 095b1e4..f0bba81 100644
--- a/android/config.go
+++ b/android/config.go
@@ -913,6 +913,25 @@
 	return "json"
 }
 
+// XrefCuJavaSourceMax returns the maximum number of the Java source files
+// in a single compilation unit
+const xrefJavaSourceFileMaxDefault = "1000"
+
+func (c Config) XrefCuJavaSourceMax() string {
+	v := c.Getenv("KYTHE_JAVA_SOURCE_BATCH_SIZE")
+	if v == "" {
+		return xrefJavaSourceFileMaxDefault
+	}
+	if _, err := strconv.ParseUint(v, 0, 0); err != nil {
+		fmt.Fprintf(os.Stderr,
+			"bad KYTHE_JAVA_SOURCE_BATCH_SIZE value: %s, will use %s",
+			err, xrefJavaSourceFileMaxDefault)
+		return xrefJavaSourceFileMaxDefault
+	}
+	return v
+
+}
+
 func (c *config) EmitXrefRules() bool {
 	return c.XrefCorpusName() != ""
 }
diff --git a/android/csuite_config.go b/android/csuite_config.go
index bf24d98..56d2408 100644
--- a/android/csuite_config.go
+++ b/android/csuite_config.go
@@ -40,7 +40,7 @@
 		OutputFile: OptionalPathForPath(me.OutputFilePath),
 	}
 	androidMkEntries.ExtraEntries = []AndroidMkExtraEntriesFunc{
-		func(entries *AndroidMkEntries) {
+		func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
 			if me.properties.Test_config != nil {
 				entries.SetString("LOCAL_TEST_CONFIG", *me.properties.Test_config)
 			}
diff --git a/android/filegroup.go b/android/filegroup.go
index 674a196..593e470 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -49,7 +49,7 @@
 
 func FilegroupBp2Build(ctx TopDownMutatorContext) {
 	fg, ok := ctx.Module().(*fileGroup)
-	if !ok || !fg.properties.Bazel_module.Bp2build_available {
+	if !ok || !fg.ConvertWithBp2build() {
 		return
 	}
 
@@ -57,9 +57,9 @@
 		Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs),
 	}
 
-	props := bazel.NewBazelTargetModuleProperties(fg.Name(), "filegroup", "")
+	props := bazel.BazelTargetModuleProperties{Rule_class: "filegroup"}
 
-	ctx.CreateBazelTargetModule(BazelFileGroupFactory, props, attrs)
+	ctx.CreateBazelTargetModule(BazelFileGroupFactory, fg.Name(), props, attrs)
 }
 
 type fileGroupProperties struct {
@@ -77,13 +77,11 @@
 	// Create a make variable with the specified name that contains the list of files in the
 	// filegroup, relative to the root of the source tree.
 	Export_to_make_var *string
-
-	// Properties for Bazel migration purposes.
-	bazel.Properties
 }
 
 type fileGroup struct {
 	ModuleBase
+	BazelModuleBase
 	properties fileGroupProperties
 	srcs       Paths
 }
@@ -97,6 +95,7 @@
 	module := &fileGroup{}
 	module.AddProperties(&module.properties)
 	InitAndroidModule(module)
+	InitBazelModule(module)
 	return module
 }
 
diff --git a/android/module.go b/android/module.go
index bf74cad..58675d4 100644
--- a/android/module.go
+++ b/android/module.go
@@ -507,13 +507,17 @@
 type BazelTargetModule interface {
 	Module
 
-	BazelTargetModuleProperties() *bazel.BazelTargetModuleProperties
+	bazelTargetModuleProperties() *bazel.BazelTargetModuleProperties
+	SetBazelTargetModuleProperties(props bazel.BazelTargetModuleProperties)
+
+	RuleClass() string
+	BzlLoadLocation() string
 }
 
 // InitBazelTargetModule is a wrapper function that decorates BazelTargetModule
 // with property structs containing metadata for bp2build conversion.
 func InitBazelTargetModule(module BazelTargetModule) {
-	module.AddProperties(module.BazelTargetModuleProperties())
+	module.AddProperties(module.bazelTargetModuleProperties())
 	InitAndroidModule(module)
 }
 
@@ -524,11 +528,26 @@
 	Properties bazel.BazelTargetModuleProperties
 }
 
-// BazelTargetModuleProperties getter.
-func (btmb *BazelTargetModuleBase) BazelTargetModuleProperties() *bazel.BazelTargetModuleProperties {
+// bazelTargetModuleProperties getter.
+func (btmb *BazelTargetModuleBase) bazelTargetModuleProperties() *bazel.BazelTargetModuleProperties {
 	return &btmb.Properties
 }
 
+// SetBazelTargetModuleProperties setter for BazelTargetModuleProperties
+func (btmb *BazelTargetModuleBase) SetBazelTargetModuleProperties(props bazel.BazelTargetModuleProperties) {
+	btmb.Properties = props
+}
+
+// RuleClass returns the rule class for this Bazel target
+func (b *BazelTargetModuleBase) RuleClass() string {
+	return b.bazelTargetModuleProperties().Rule_class
+}
+
+// BzlLoadLocation returns the rule class for this Bazel target
+func (b *BazelTargetModuleBase) BzlLoadLocation() string {
+	return b.bazelTargetModuleProperties().Bzl_load_location
+}
+
 // Qualified id for a module
 type qualifiedModuleName struct {
 	// The package (i.e. directory) in which the module is defined, without trailing /
diff --git a/android/mutator.go b/android/mutator.go
index c387193..b023001 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -283,7 +283,7 @@
 	// factory method, just like in CreateModule, but also requires
 	// BazelTargetModuleProperties containing additional metadata for the
 	// bp2build codegenerator.
-	CreateBazelTargetModule(ModuleFactory, bazel.BazelTargetModuleProperties, interface{}) BazelTargetModule
+	CreateBazelTargetModule(ModuleFactory, string, bazel.BazelTargetModuleProperties, interface{}) BazelTargetModule
 }
 
 type topDownMutatorContext struct {
@@ -513,17 +513,25 @@
 
 func (t *topDownMutatorContext) CreateBazelTargetModule(
 	factory ModuleFactory,
+	name string,
 	bazelProps bazel.BazelTargetModuleProperties,
 	attrs interface{}) BazelTargetModule {
-	if !strings.HasPrefix(*bazelProps.Name, bazel.BazelTargetModuleNamePrefix) {
+	if strings.HasPrefix(name, bazel.BazelTargetModuleNamePrefix) {
 		panic(fmt.Errorf(
-			"bp2build error: the bazel target module name must start with '%s': %s",
+			"The %s name prefix is added automatically, do not set it manually: %s",
 			bazel.BazelTargetModuleNamePrefix,
-			*bazelProps.Name,
-		))
+			name))
+	}
+	name = bazel.BazelTargetModuleNamePrefix + name
+	nameProp := struct {
+		Name *string
+	}{
+		Name: &name,
 	}
 
-	return t.CreateModule(factory, &bazelProps, attrs).(BazelTargetModule)
+	b := t.CreateModule(factory, &nameProp, attrs).(BazelTargetModule)
+	b.SetBazelTargetModuleProperties(bazelProps)
+	return b
 }
 
 func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
diff --git a/android/path_properties.go b/android/path_properties.go
index 4bb706a..853e5a9 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -76,52 +76,73 @@
 	var ret []string
 
 	for _, i := range pathPropertyIndexes {
-		// Turn an index into a field.
-		sv := fieldByIndex(v, i)
-		if !sv.IsValid() {
-			// Skip properties inside a nil pointer.
-			continue
-		}
-
-		// If the field is a non-nil pointer step into it.
-		if sv.Kind() == reflect.Ptr {
-			if sv.IsNil() {
+		var values []reflect.Value
+		fieldsByIndex(v, i, &values)
+		for _, sv := range values {
+			if !sv.IsValid() {
+				// Skip properties inside a nil pointer.
 				continue
 			}
-			sv = sv.Elem()
-		}
 
-		// Collect paths from all strings and slices of strings.
-		switch sv.Kind() {
-		case reflect.String:
-			ret = append(ret, sv.String())
-		case reflect.Slice:
-			ret = append(ret, sv.Interface().([]string)...)
-		default:
-			panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`,
-				v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
+			// If the field is a non-nil pointer step into it.
+			if sv.Kind() == reflect.Ptr {
+				if sv.IsNil() {
+					continue
+				}
+				sv = sv.Elem()
+			}
+
+			// Collect paths from all strings and slices of strings.
+			switch sv.Kind() {
+			case reflect.String:
+				ret = append(ret, sv.String())
+			case reflect.Slice:
+				ret = append(ret, sv.Interface().([]string)...)
+			default:
+				panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`,
+					v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
+			}
 		}
 	}
 
 	return ret
 }
 
-// fieldByIndex is like reflect.Value.FieldByIndex, but returns an invalid reflect.Value when
-// traversing a nil pointer to a struct.
-func fieldByIndex(v reflect.Value, index []int) reflect.Value {
+// fieldsByIndex is similar to reflect.Value.FieldByIndex, but is more robust: it doesn't track
+// nil pointers and it returns multiple values when there's slice of struct.
+func fieldsByIndex(v reflect.Value, index []int, values *[]reflect.Value) {
+	// leaf case
 	if len(index) == 1 {
-		return v.Field(index[0])
-	}
-	for _, x := range index {
-		if v.Kind() == reflect.Ptr {
-			if v.IsNil() {
-				return reflect.Value{}
+		if isSliceOfStruct(v) {
+			for i := 0; i < v.Len(); i++ {
+				*values = append(*values, v.Index(i).Field(index[0]))
 			}
-			v = v.Elem()
+		} else {
+			*values = append(*values, v.Field(index[0]))
 		}
-		v = v.Field(x)
+		return
 	}
-	return v
+
+	// recursion
+	if v.Kind() == reflect.Ptr {
+		// don't track nil pointer
+		if v.IsNil() {
+			return
+		}
+		v = v.Elem()
+	} else if isSliceOfStruct(v) {
+		// do the recursion for all elements
+		for i := 0; i < v.Len(); i++ {
+			fieldsByIndex(v.Index(i).Field(index[0]), index[1:], values)
+		}
+		return
+	}
+	fieldsByIndex(v.Field(index[0]), index[1:], values)
+	return
+}
+
+func isSliceOfStruct(v reflect.Value) bool {
+	return v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Struct
 }
 
 var pathPropertyIndexesCache OncePer
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index f964d9f..2aab748 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -33,12 +33,21 @@
 		Foo string `android:"path"`
 	}
 
+	// nested slices of struct
+	props3 struct {
+		X []struct {
+			Y []struct {
+				Z []string `android:"path"`
+			}
+		}
+	}
+
 	sourceDeps []string
 }
 
 func pathDepsMutatorTestModuleFactory() Module {
 	module := &pathDepsMutatorTestModule{}
-	module.AddProperties(&module.props, &module.props2)
+	module.AddProperties(&module.props, &module.props2, &module.props3)
 	InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
 	return module
 }
@@ -73,8 +82,20 @@
 				bar: [":b"],
 				baz: ":c{.bar}",
 				qux: ":d",
+				x: [
+					{
+						y: [
+							{
+								z: [":x", ":y"],
+							},
+							{
+								z: [":z"],
+							},
+						],
+					},
+				],
 			}`,
-			deps: []string{"a", "b", "c"},
+			deps: []string{"a", "b", "c", "x", "y", "z"},
 		},
 		{
 			name: "arch variant",
@@ -113,6 +134,18 @@
 				filegroup {
 					name: "d",
 				}
+
+				filegroup {
+					name: "x",
+				}
+
+				filegroup {
+					name: "y",
+				}
+
+				filegroup {
+					name: "z",
+				}
 			`
 
 			config := TestArchConfig(buildDir, nil, bp, nil)
diff --git a/android/testing.go b/android/testing.go
index de338bf..7852b60 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -201,6 +201,10 @@
 		"\nall singletons: %v", name, allSingletonNames))
 }
 
+func (ctx *TestContext) Config() Config {
+	return ctx.config
+}
+
 type testBuildProvider interface {
 	BuildParamsForTests() []BuildParams
 	RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
@@ -461,7 +465,7 @@
 	config.katiEnabled = true
 }
 
-func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) []AndroidMkEntries {
+func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) []AndroidMkEntries {
 	var p AndroidMkEntriesProvider
 	var ok bool
 	if p, ok = mod.(AndroidMkEntriesProvider); !ok {
@@ -470,19 +474,19 @@
 
 	entriesList := p.AndroidMkEntries()
 	for i, _ := range entriesList {
-		entriesList[i].fillInEntries(config, bpPath, mod)
+		entriesList[i].fillInEntries(ctx, mod)
 	}
 	return entriesList
 }
 
-func AndroidMkDataForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) AndroidMkData {
+func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) AndroidMkData {
 	var p AndroidMkDataProvider
 	var ok bool
 	if p, ok = mod.(AndroidMkDataProvider); !ok {
 		t.Errorf("module does not implement AndroidMkDataProvider: " + mod.Name())
 	}
 	data := p.AndroidMk()
-	data.fillInData(config, bpPath, mod)
+	data.fillInData(ctx, mod)
 	return data
 }
 
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index b0e3f20..47ea239 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -202,6 +202,7 @@
 InProcessTethering(minSdkVersion:current)
 ipmemorystore-aidl-interfaces-java(minSdkVersion:29)
 ipmemorystore-aidl-interfaces-unstable-java(minSdkVersion:29)
+ipmemorystore-aidl-interfaces-V10-java(minSdkVersion:29)
 ipmemorystore-aidl-interfaces-V11-java(minSdkVersion:29)
 jni_headers(minSdkVersion:29)
 jsr305(minSdkVersion:14)
@@ -477,6 +478,7 @@
 mediaswcodec(minSdkVersion:29)
 metrics-constants-protos(minSdkVersion:29)
 modules-utils-build(minSdkVersion:29)
+modules-utils-build_system(minSdkVersion:29)
 modules-utils-os(minSdkVersion:30)
 ndk_crtbegin_so.19(minSdkVersion:(no version))
 ndk_crtbegin_so.21(minSdkVersion:(no version))
@@ -493,7 +495,9 @@
 net-utils-framework-common(minSdkVersion:current)
 netd-client(minSdkVersion:29)
 netd_aidl_interface-java(minSdkVersion:29)
+netd_aidl_interface-lateststable-java(minSdkVersion:29)
 netd_aidl_interface-unstable-java(minSdkVersion:29)
+netd_aidl_interface-V5-java(minSdkVersion:29)
 netd_aidl_interface-V6-java(minSdkVersion:29)
 netd_event_listener_interface-java(minSdkVersion:29)
 netd_event_listener_interface-ndk_platform(minSdkVersion:29)
diff --git a/apex/apex.go b/apex/apex.go
index e06a967..662bbbd 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2847,14 +2847,6 @@
 	//
 	// Module separator
 	//
-	m["com.android.sdkext"] = []string{
-		"fmtlib_ndk",
-		"libbase_ndk",
-		"libprotobuf-cpp-lite-ndk",
-	}
-	//
-	// Module separator
-	//
 	m["com.android.os.statsd"] = []string{
 		"libstatssocket",
 	}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index bbc4b93..3f56047 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -354,7 +354,7 @@
 
 // Minimal test
 func TestBasicApex(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex_defaults {
 			name: "myapex-defaults",
 			manifest: ":myapex.manifest",
@@ -562,7 +562,7 @@
 
 	// Make sure that Android.mk is created
 	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", ab)
+	data := android.AndroidMkDataForTest(t, ctx, ab)
 	var builder strings.Builder
 	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
 
@@ -2508,7 +2508,7 @@
 }
 
 func TestVendorApex(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2539,7 +2539,7 @@
 	})
 
 	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	name := apexBundle.BaseModuleName()
 	prefix := "TARGET_"
 	var builder strings.Builder
@@ -2643,7 +2643,7 @@
 }
 
 func TestAndroidMk_UseVendorRequired(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2667,7 +2667,7 @@
 	})
 
 	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	name := apexBundle.BaseModuleName()
 	prefix := "TARGET_"
 	var builder strings.Builder
@@ -2677,7 +2677,7 @@
 }
 
 func TestAndroidMk_VendorApexRequired(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2698,7 +2698,7 @@
 	`)
 
 	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	name := apexBundle.BaseModuleName()
 	prefix := "TARGET_"
 	var builder strings.Builder
@@ -2708,7 +2708,7 @@
 }
 
 func TestAndroidMkWritesCommonProperties(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -2726,7 +2726,7 @@
 	`)
 
 	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	name := apexBundle.BaseModuleName()
 	prefix := "TARGET_"
 	var builder strings.Builder
@@ -3799,7 +3799,7 @@
 }
 
 func TestApexName(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -3832,7 +3832,7 @@
 	ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
 
 	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	name := apexBundle.BaseModuleName()
 	prefix := "TARGET_"
 	var builder strings.Builder
@@ -4336,7 +4336,7 @@
 }
 
 func TestPrebuiltOverrides(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		prebuilt_apex {
 			name: "myapex.prebuilt",
 			src: "myapex-arm.apex",
@@ -4349,7 +4349,7 @@
 	p := ctx.ModuleForTests("myapex.prebuilt", "android_common").Module().(*Prebuilt)
 
 	expected := []string{"myapex"}
-	actual := android.AndroidMkEntriesForTest(t, config, "", p)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
+	actual := android.AndroidMkEntriesForTest(t, ctx, p)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
 	if !reflect.DeepEqual(actual, expected) {
 		t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES value '%s', expected '%s'", actual, expected)
 	}
@@ -4708,7 +4708,7 @@
 }
 
 func TestApexWithTests(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex_test {
 			name: "myapex",
 			key: "myapex.key",
@@ -4796,7 +4796,7 @@
 
 	// Ensure the module is correctly translated.
 	bundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", bundle)
+	data := android.AndroidMkDataForTest(t, ctx, bundle)
 	name := bundle.BaseModuleName()
 	prefix := "TARGET_"
 	var builder strings.Builder
@@ -4811,7 +4811,7 @@
 	ensureContains(t, androidMk, "LOCAL_MODULE := myapex\n")
 
 	flatBundle := ctx.ModuleForTests("myapex", "android_common_myapex_flattened").Module().(*apexBundle)
-	data = android.AndroidMkDataForTest(t, config, "", flatBundle)
+	data = android.AndroidMkDataForTest(t, ctx, flatBundle)
 	data.Custom(&builder, name, prefix, "", data)
 	flatAndroidMk := builder.String()
 	ensureContainsOnce(t, flatAndroidMk, "LOCAL_TEST_DATA := :baz :bar/baz\n")
@@ -4819,7 +4819,7 @@
 }
 
 func TestInstallExtraFlattenedApexes(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -4834,7 +4834,7 @@
 	})
 	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
 	ensureListContains(t, ab.requiredDeps, "myapex.flattened")
-	mk := android.AndroidMkDataForTest(t, config, "", ab)
+	mk := android.AndroidMkDataForTest(t, ctx, ab)
 	var builder strings.Builder
 	mk.Custom(&builder, ab.Name(), "TARGET_", "", mk)
 	androidMk := builder.String()
@@ -5382,7 +5382,7 @@
 }
 
 func TestOverrideApex(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5450,7 +5450,7 @@
 	optFlags := apexRule.Args["opt_flags"]
 	ensureContains(t, optFlags, "--override_apk_package_name test.overridden.package")
 
-	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	var builder strings.Builder
 	data.Custom(&builder, name, "TARGET_", "", data)
 	androidMk := builder.String()
@@ -5838,7 +5838,7 @@
 }
 
 func TestCarryRequiredModuleNames(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -5864,7 +5864,7 @@
 	`)
 
 	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	name := apexBundle.BaseModuleName()
 	prefix := "TARGET_"
 	var builder strings.Builder
@@ -6005,7 +6005,7 @@
 }
 
 func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6043,7 +6043,7 @@
 	`)
 
 	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	var builder strings.Builder
 	data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
 	androidMk := builder.String()
@@ -6728,7 +6728,7 @@
 }
 
 func TestApexSet(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex_set {
 			name: "myapex",
 			set: "myapex.apks",
@@ -6760,7 +6760,7 @@
 
 	a := m.Module().(*ApexSet)
 	expectedOverrides := []string{"foo"}
-	actualOverrides := android.AndroidMkEntriesForTest(t, config, "", a)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
+	actualOverrides := android.AndroidMkEntriesForTest(t, ctx, a)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
 	if !reflect.DeepEqual(actualOverrides, expectedOverrides) {
 		t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES - expected %q vs actual %q", expectedOverrides, actualOverrides)
 	}
@@ -6933,7 +6933,7 @@
 }
 
 func TestCompressedApex(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -6959,7 +6959,7 @@
 	ensureContains(t, ab.outputFile.String(), "myapex.capex")
 
 	// Verify android.mk rules
-	data := android.AndroidMkDataForTest(t, config, "", ab)
+	data := android.AndroidMkDataForTest(t, ctx, ab)
 	var builder strings.Builder
 	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
 	androidMk := builder.String()
@@ -6967,7 +6967,7 @@
 }
 
 func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
-	ctx, config := testApex(t, `
+	ctx, _ := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
@@ -7007,7 +7007,7 @@
 	`)
 
 	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
-	data := android.AndroidMkDataForTest(t, config, "", ab)
+	data := android.AndroidMkDataForTest(t, ctx, ab)
 	var builder strings.Builder
 	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
 	androidMk := builder.String()
@@ -7159,7 +7159,7 @@
 		t.Run(test.name, func(t *testing.T) {
 			for _, otherApexEnabled := range test.otherApexEnabled {
 				t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) {
-					ctx, config := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
+					ctx, _ := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
 
 					type modAndMkEntries struct {
 						mod       *cc.Module
@@ -7177,7 +7177,7 @@
 							if !mod.Enabled() || mod.IsHideFromMake() {
 								continue
 							}
-							for _, ent := range android.AndroidMkEntriesForTest(t, config, "", mod) {
+							for _, ent := range android.AndroidMkEntriesForTest(t, ctx, mod) {
 								if ent.Disabled {
 									continue
 								}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 041afb3..ec7f253 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -414,7 +414,7 @@
 		OutputFile: android.OptionalPathForPath(p.inputApex),
 		Include:    "$(BUILD_PREBUILT)",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_PATH", p.installDir.ToMakePath().String())
 				entries.SetString("LOCAL_MODULE_STEM", p.installFilename)
 				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
@@ -609,7 +609,7 @@
 		Include:       "$(BUILD_PREBUILT)",
 		Host_required: a.hostRequired,
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_PATH", a.installDir.ToMakePath().String())
 				entries.SetString("LOCAL_MODULE_STEM", a.installFilename)
 				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !a.installable())
diff --git a/bazel/properties.go b/bazel/properties.go
index 8055306..a4df4bc 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -14,11 +14,6 @@
 
 package bazel
 
-import (
-	"fmt"
-	"strings"
-)
-
 type bazelModuleProperties struct {
 	// The label of the Bazel target replacing this Soong module.
 	Label string
@@ -37,32 +32,15 @@
 // BazelTargetModuleProperties contain properties and metadata used for
 // Blueprint to BUILD file conversion.
 type BazelTargetModuleProperties struct {
-	Name *string
-
 	// The Bazel rule class for this target.
-	Rule_class string
+	Rule_class string `blueprint:"mutated"`
 
 	// The target label for the bzl file containing the definition of the rule class.
-	Bzl_load_location string
+	Bzl_load_location string `blueprint:"mutated"`
 }
 
 const BazelTargetModuleNamePrefix = "__bp2build__"
 
-func NewBazelTargetModuleProperties(name string, ruleClass string, bzlLoadLocation string) BazelTargetModuleProperties {
-	if strings.HasPrefix(name, BazelTargetModuleNamePrefix) {
-		panic(fmt.Errorf(
-			"The %s name prefix is added automatically, do not set it manually: %s",
-			BazelTargetModuleNamePrefix,
-			name))
-	}
-	name = BazelTargetModuleNamePrefix + name
-	return BazelTargetModuleProperties{
-		Name:              &name,
-		Rule_class:        ruleClass,
-		Bzl_load_location: bzlLoadLocation,
-	}
-}
-
 // Label is used to represent a Bazel compatible Label. Also stores the original bp text to support
 // string replacement.
 type Label struct {
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index fcad686..a4c4a0d 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -19,7 +19,6 @@
 	"android/soong/bazel"
 	"fmt"
 	"reflect"
-	"strconv"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -178,13 +177,14 @@
 
 		switch ctx.Mode() {
 		case Bp2Build:
-			if _, ok := m.(android.BazelTargetModule); !ok {
+			if b, ok := m.(android.BazelTargetModule); !ok {
 				// Only include regular Soong modules (non-BazelTargetModules) into the total count.
 				totalModuleCount += 1
 				return
+			} else {
+				t = generateBazelTarget(bpCtx, m, b)
+				ruleClassCount[t.ruleClass] += 1
 			}
-			t = generateBazelTarget(bpCtx, m)
-			ruleClassCount[t.ruleClass] += 1
 		case QueryView:
 			// Blocklist certain module types from being generated.
 			if canonicalizeModuleType(bpCtx.ModuleType(m)) == "package" {
@@ -208,42 +208,13 @@
 	return buildFileToTargets, metrics
 }
 
-// Helper method for tests to easily access the targets in a dir.
-func GenerateBazelTargetsForDir(codegenCtx CodegenContext, dir string) BazelTargets {
-	bazelTargetsMap, _ := GenerateBazelTargets(codegenCtx)
-	return bazelTargetsMap[dir]
-}
+func generateBazelTarget(ctx bpToBuildContext, m blueprint.Module, b android.BazelTargetModule) BazelTarget {
+	ruleClass := b.RuleClass()
+	bzlLoadLocation := b.BzlLoadLocation()
 
-// Helper method to trim quotes around strings.
-func trimQuotes(s string) string {
-	if s == "" {
-		// strconv.Unquote would error out on empty strings, but this method
-		// allows them, so return the empty string directly.
-		return ""
-	}
-	ret, err := strconv.Unquote(s)
-	if err != nil {
-		// Panic the error immediately.
-		panic(fmt.Errorf("Trying to unquote '%s', but got error: %s", s, err))
-	}
-	return ret
-}
-
-func generateBazelTarget(ctx bpToBuildContext, m blueprint.Module) BazelTarget {
 	// extract the bazel attributes from the module.
 	props := getBuildProperties(ctx, m)
 
-	// extract the rule class name from the attributes. Since the string value
-	// will be string-quoted, remove the quotes here.
-	ruleClass := trimQuotes(props.Attrs["rule_class"])
-	// Delete it from being generated in the BUILD file.
-	delete(props.Attrs, "rule_class")
-
-	// extract the bzl_load_location, and also remove the quotes around it here.
-	bzlLoadLocation := trimQuotes(props.Attrs["bzl_load_location"])
-	// Delete it from being generated in the BUILD file.
-	delete(props.Attrs, "bzl_load_location")
-
 	delete(props.Attrs, "bp2build_available")
 
 	// Return the Bazel target with rule class and attributes, ready to be
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index fce6433..aa4fc1d 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -204,7 +204,7 @@
 		android.FailIfErrored(t, errs)
 
 		codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, dir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
 		if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
 			t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
 		}
@@ -262,7 +262,7 @@
 		}
 
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, dir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
 
 		if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
 			t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
@@ -421,7 +421,7 @@
 		android.FailIfErrored(t, errs)
 
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, dir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
 		if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
 			t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount)
 		}
@@ -912,7 +912,7 @@
 		}
 
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, checkDir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
 		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
 			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
 		} else {
@@ -1127,7 +1127,7 @@
 		android.FailIfErrored(t, errs)
 
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, dir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
 		if actualCount := len(bazelTargets); actualCount != 1 {
 			t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
 		}
@@ -1215,7 +1215,7 @@
 		android.FailIfErrored(t, errs)
 
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, dir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
 		if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
 			t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount)
 		}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index b2d8941..5bf5c80 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -203,7 +203,7 @@
 			checkDir = testCase.dir
 		}
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, checkDir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
 		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
 			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
 		} else {
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index 816edb8..f094102 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -167,7 +167,7 @@
 		}
 
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, dir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
 		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
 			fmt.Println(bazelTargets)
 			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
diff --git a/bp2build/sh_conversion_test.go b/bp2build/sh_conversion_test.go
index 3e15dfc..2aa373c 100644
--- a/bp2build/sh_conversion_test.go
+++ b/bp2build/sh_conversion_test.go
@@ -116,7 +116,7 @@
 			checkDir = testCase.dir
 		}
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := GenerateBazelTargetsForDir(codegenCtx, checkDir)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
 		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
 			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
 		} else {
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 2e59999..bd75a8f 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -25,10 +25,9 @@
 
 type customModule struct {
 	android.ModuleBase
+	android.BazelModuleBase
 
 	props customProps
-
-	bazelProps bazel.Properties
 }
 
 // OutputFiles is needed because some instances of this module use dist with a
@@ -44,7 +43,7 @@
 func customModuleFactoryBase() android.Module {
 	module := &customModule{}
 	module.AddProperties(&module.props)
-	module.AddProperties(&module.bazelProps)
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -127,7 +126,7 @@
 
 func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
 	if m, ok := ctx.Module().(*customModule); ok {
-		if !m.bazelProps.Bazel_module.Bp2build_available {
+		if !m.ConvertWithBp2build() {
 			return
 		}
 
@@ -136,9 +135,11 @@
 			String_list_prop: m.props.String_list_prop,
 		}
 
-		props := bazel.NewBazelTargetModuleProperties(m.Name(), "custom", "")
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class: "custom",
+		}
 
-		ctx.CreateBazelTargetModule(customBazelModuleFactory, props, attrs)
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, m.Name(), props, attrs)
 	}
 }
 
@@ -146,32 +147,35 @@
 // module to target.
 func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
 	if m, ok := ctx.Module().(*customModule); ok {
-		if !m.bazelProps.Bazel_module.Bp2build_available {
+		if !m.ConvertWithBp2build() {
 			return
 		}
 
 		baseName := m.Name()
 		attrs := &customBazelModuleAttributes{}
 
-		myLibraryProps := bazel.NewBazelTargetModuleProperties(
-			baseName,
-			"my_library",
-			"//build/bazel/rules:rules.bzl",
-		)
-		ctx.CreateBazelTargetModule(customBazelModuleFactory, myLibraryProps, attrs)
+		myLibraryProps := bazel.BazelTargetModuleProperties{
+			Rule_class:        "my_library",
+			Bzl_load_location: "//build/bazel/rules:rules.bzl",
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName, myLibraryProps, attrs)
 
-		protoLibraryProps := bazel.NewBazelTargetModuleProperties(
-			baseName+"_proto_library_deps",
-			"proto_library",
-			"//build/bazel/rules:proto.bzl",
-		)
-		ctx.CreateBazelTargetModule(customBazelModuleFactory, protoLibraryProps, attrs)
+		protoLibraryProps := bazel.BazelTargetModuleProperties{
+			Rule_class:        "proto_library",
+			Bzl_load_location: "//build/bazel/rules:proto.bzl",
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName+"_proto_library_deps", protoLibraryProps, attrs)
 
-		myProtoLibraryProps := bazel.NewBazelTargetModuleProperties(
-			baseName+"_my_proto_library_deps",
-			"my_proto_library",
-			"//build/bazel/rules:proto.bzl",
-		)
-		ctx.CreateBazelTargetModule(customBazelModuleFactory, myProtoLibraryProps, attrs)
+		myProtoLibraryProps := bazel.BazelTargetModuleProperties{
+			Rule_class:        "my_proto_library",
+			Bzl_load_location: "//build/bazel/rules:proto.bzl",
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName+"_my_proto_library_deps", myProtoLibraryProps, attrs)
 	}
 }
+
+// Helper method for tests to easily access the targets in a dir.
+func generateBazelTargetsForDir(codegenCtx CodegenContext, dir string) BazelTargets {
+	buildFileToTargets, _ := GenerateBazelTargets(codegenCtx)
+	return buildFileToTargets[dir]
+}
diff --git a/build_kzip.bash b/build_kzip.bash
index 0018ea9..9564723 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -7,14 +7,16 @@
 #   BUILD_NUMBER          build number, used to generate unique ID (will use UUID if not set)
 #   DIST_DIR              where the resulting all.kzip will be placed
 #   KYTHE_KZIP_ENCODING   proto or json (proto is default)
+#   KYTHE_JAVA_SOURCE_BATCH_SIZE maximum number of the Java source files in a compilation unit
 #   OUT_DIR               output directory (out if not specified})
 #   TARGET_BUILD_VARIANT  variant, e.g., `userdebug`
 #   TARGET_PRODUCT        target device name, e.g., 'aosp_blueline'
 #   XREF_CORPUS           source code repository URI, e.g., 'android.googlesource.com/platform/superproject'
 
 : ${BUILD_NUMBER:=$(uuidgen)}
+: ${KYTHE_JAVA_SOURCE_BATCH_SIZE:=500}
 : ${KYTHE_KZIP_ENCODING:=proto}
-export KYTHE_KZIP_ENCODING
+export KYTHE_JAVA_SOURCE_BATCH_SIZE KYTHE_KZIP_ENCODING
 
 # The extraction might fail for some source files, so run with -k and then check that
 # sufficiently many files were generated.
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 8652c10..536efa4 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -83,7 +83,7 @@
 		Include:  "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
 
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				if len(c.Properties.Logtags) > 0 {
 					entries.AddStrings("LOCAL_LOGTAGS_FILES", c.Properties.Logtags...)
 				}
@@ -162,16 +162,17 @@
 
 func androidMkWriteExtraTestConfigs(extraTestConfigs android.Paths, entries *android.AndroidMkEntries) {
 	if len(extraTestConfigs) > 0 {
-		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
-			entries.AddStrings("LOCAL_EXTRA_FULL_TEST_CONFIGS", extraTestConfigs.Strings()...)
-		})
+		entries.ExtraEntries = append(entries.ExtraEntries,
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+				entries.AddStrings("LOCAL_EXTRA_FULL_TEST_CONFIGS", extraTestConfigs.Strings()...)
+			})
 	}
 }
 
 func AndroidMkWriteTestData(data []android.DataPath, entries *android.AndroidMkEntries) {
 	testFiles := android.AndroidMkDataPaths(data)
 	if len(testFiles) > 0 {
-		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+		entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 			entries.AddStrings("LOCAL_TEST_DATA", testFiles...)
 		})
 	}
@@ -224,7 +225,7 @@
 		entries.Class = "STATIC_LIBRARIES"
 	} else if library.shared() {
 		entries.Class = "SHARED_LIBRARIES"
-		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+		entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 			entries.SetString("LOCAL_SOONG_TOC", library.toc().String())
 			if !library.buildStubs() {
 				entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", library.unstrippedOutputFile.String())
@@ -244,7 +245,7 @@
 		entries.DistFiles = android.MakeDefaultDistFiles(library.distFile)
 	}
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		library.androidMkWriteExportedFlags(entries)
 		library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries)
 
@@ -272,7 +273,7 @@
 		if library.buildStubs() && library.stubsVersion() != "" {
 			entries.SubName = "." + library.stubsVersion()
 		}
-		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+		entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 			// library.makeUninstallable() depends on this to bypass HideFromMake() for
 			// static libraries.
 			entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
@@ -315,7 +316,7 @@
 
 	entries.Class = "EXECUTABLES"
 	entries.DistFiles = binary.distFiles
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", binary.unstrippedOutputFile.String())
 		if len(binary.symlinks) > 0 {
 			entries.AddStrings("LOCAL_MODULE_SYMLINKS", binary.symlinks...)
@@ -337,7 +338,7 @@
 func (benchmark *benchmarkDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
 	ctx.subAndroidMk(entries, benchmark.binaryDecorator)
 	entries.Class = "NATIVE_TESTS"
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		if len(benchmark.Properties.Test_suites) > 0 {
 			entries.AddCompatibilityTestSuites(benchmark.Properties.Test_suites...)
 		}
@@ -362,7 +363,7 @@
 	if Bool(test.Properties.Test_per_src) {
 		entries.SubName = "_" + String(test.binaryDecorator.Properties.Stem)
 	}
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		if len(test.Properties.Test_suites) > 0 {
 			entries.AddCompatibilityTestSuites(test.Properties.Test_suites...)
 		}
@@ -406,7 +407,7 @@
 			filepath.Dir(fuzz.config.String())+":config.json")
 	}
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
 		if len(fuzzFiles) > 0 {
 			entries.AddStrings("LOCAL_TEST_DATA", fuzzFiles...)
@@ -423,7 +424,7 @@
 
 func (library *toolchainLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
 	entries.Class = "STATIC_LIBRARIES"
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		_, suffix, _ := android.SplitFileExt(entries.OutputFile.Path().Base())
 		entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
 	})
@@ -439,7 +440,7 @@
 		entries.OutputFile = android.OptionalPathForPath(installer.path)
 	}
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		path, file := filepath.Split(installer.path.ToMakePath().String())
 		stem, suffix, _ := android.SplitFileExt(file)
 		entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
@@ -457,7 +458,7 @@
 		return
 	}
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		path, file := filepath.Split(c.installPath.String())
 		stem, suffix, _ := android.SplitFileExt(file)
 		entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
@@ -481,7 +482,7 @@
 
 	entries.SubName = c.androidMkSuffix
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		c.libraryDecorator.androidMkWriteExportedFlags(entries)
 
 		// Specifying stem is to pass check_elf_files when vendor modules link against vndk prebuilt.
@@ -521,7 +522,7 @@
 
 	entries.SubName += c.baseProperties.Androidmk_suffix
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		c.libraryDecorator.androidMkWriteExportedFlags(entries)
 
 		if c.shared() || c.static() {
@@ -548,7 +549,7 @@
 	entries.Class = "EXECUTABLES"
 	entries.SubName = c.baseProperties.Androidmk_suffix
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		entries.AddStrings("LOCAL_MODULE_SYMLINKS", c.Properties.Symlinks...)
 	})
 }
@@ -575,7 +576,7 @@
 	entries.Class = "SHARED_LIBRARIES"
 	entries.SubName = vendorPublicLibrarySuffix
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		c.libraryDecorator.androidMkWriteExportedFlags(entries)
 		_, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
 
@@ -586,7 +587,7 @@
 }
 
 func (p *prebuiltLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		if p.properties.Check_elf_files != nil {
 			entries.SetBool("LOCAL_CHECK_ELF_FILES", *p.properties.Check_elf_files)
 		} else {
@@ -616,7 +617,7 @@
 func androidMkWriteAllowUndefinedSymbols(linker *baseLinker, entries *android.AndroidMkEntries) {
 	allow := linker.Properties.Allow_undefined_symbols
 	if allow != nil {
-		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+		entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 			entries.SetBool("LOCAL_ALLOW_UNDEFINED_SYMBOLS", *allow)
 		})
 	}
diff --git a/cc/cc.go b/cc/cc.go
index 6c1469f..11d8718 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -28,7 +28,6 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
-	"android/soong/bazel"
 	"android/soong/cc/config"
 	"android/soong/genrule"
 )
@@ -365,8 +364,6 @@
 	// can depend on libraries that are not exported by the APEXes and use private symbols
 	// from the exported libraries.
 	Test_for []string
-
-	bazel.Properties
 }
 
 type VendorProperties struct {
@@ -765,6 +762,7 @@
 	android.DefaultableModuleBase
 	android.ApexModuleBase
 	android.SdkBase
+	android.BazelModuleBase
 
 	Properties       BaseProperties
 	VendorProperties VendorProperties
@@ -1054,6 +1052,7 @@
 	}
 
 	android.InitAndroidArchModule(c, c.hod, c.multilib)
+	android.InitBazelModule(c)
 	android.InitApexModule(c)
 	android.InitSdkAwareModule(c)
 	android.InitDefaultableModule(c)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index b1c1b2e..e640f12 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -20,6 +20,7 @@
 	"os"
 	"path/filepath"
 	"reflect"
+	"regexp"
 	"strings"
 	"testing"
 
@@ -566,7 +567,7 @@
 	ctx := testCcWithConfig(t, config)
 
 	module := ctx.ModuleForTests("llndk.libraries.txt", "")
-	entries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, module.Module())[0]
 	assertArrayString(t, entries.EntryMap["LOCAL_MODULE_STEM"], []string{"llndk.libraries.VER.txt"})
 }
 
@@ -712,7 +713,7 @@
 	if !strings.HasSuffix(outputPath, "/main_test") {
 		t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
 	}
-	entries := android.AndroidMkEntriesForTest(t, config, "", module)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, module)[0]
 	if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][0], ":test_lib.so:foo/bar/baz") {
 		t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+
 			" but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][0])
@@ -3104,7 +3105,7 @@
 	if !strings.HasSuffix(outputPath, "/main_test") {
 		t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
 	}
-	entries := android.AndroidMkEntriesForTest(t, config, "", module)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, module)[0]
 	if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][0], ":test_lib.so:foo/bar/baz") {
 		t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+
 			" but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][0])
@@ -3910,3 +3911,274 @@
 	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_nodiag", variant), Async)
 	checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_diag", variant), Sync)
 }
+
+func TestIncludeDirsExporting(t *testing.T) {
+
+	// Trim spaces from the beginning, end and immediately after any newline characters. Leaves
+	// embedded newline characters alone.
+	trimIndentingSpaces := func(s string) string {
+		return strings.TrimSpace(regexp.MustCompile("(^|\n)\\s+").ReplaceAllString(s, "$1"))
+	}
+
+	checkPaths := func(t *testing.T, message string, expected string, paths android.Paths) {
+		t.Helper()
+		expected = trimIndentingSpaces(expected)
+		actual := trimIndentingSpaces(strings.Join(android.FirstUniqueStrings(android.NormalizePathsForTesting(paths)), "\n"))
+		if expected != actual {
+			t.Errorf("%s: expected:\n%s\n actual:\n%s\n", message, expected, actual)
+		}
+	}
+
+	type exportedChecker func(t *testing.T, name string, exported FlagExporterInfo)
+
+	checkIncludeDirs := func(t *testing.T, ctx *android.TestContext, module android.Module, checkers ...exportedChecker) {
+		t.Helper()
+		exported := ctx.ModuleProvider(module, FlagExporterInfoProvider).(FlagExporterInfo)
+		name := module.Name()
+
+		for _, checker := range checkers {
+			checker(t, name, exported)
+		}
+	}
+
+	expectedIncludeDirs := func(expectedPaths string) exportedChecker {
+		return func(t *testing.T, name string, exported FlagExporterInfo) {
+			t.Helper()
+			checkPaths(t, fmt.Sprintf("%s: include dirs", name), expectedPaths, exported.IncludeDirs)
+		}
+	}
+
+	expectedSystemIncludeDirs := func(expectedPaths string) exportedChecker {
+		return func(t *testing.T, name string, exported FlagExporterInfo) {
+			t.Helper()
+			checkPaths(t, fmt.Sprintf("%s: system include dirs", name), expectedPaths, exported.SystemIncludeDirs)
+		}
+	}
+
+	expectedGeneratedHeaders := func(expectedPaths string) exportedChecker {
+		return func(t *testing.T, name string, exported FlagExporterInfo) {
+			t.Helper()
+			checkPaths(t, fmt.Sprintf("%s: generated headers", name), expectedPaths, exported.GeneratedHeaders)
+		}
+	}
+
+	expectedOrderOnlyDeps := func(expectedPaths string) exportedChecker {
+		return func(t *testing.T, name string, exported FlagExporterInfo) {
+			t.Helper()
+			checkPaths(t, fmt.Sprintf("%s: order only deps", name), expectedPaths, exported.Deps)
+		}
+	}
+
+	genRuleModules := `
+		genrule {
+			name: "genrule_foo",
+			cmd: "generate-foo",
+			out: [
+				"generated_headers/foo/generated_header.h",
+			],
+			export_include_dirs: [
+				"generated_headers",
+			],
+		}
+
+		genrule {
+			name: "genrule_bar",
+			cmd: "generate-bar",
+			out: [
+				"generated_headers/bar/generated_header.h",
+			],
+			export_include_dirs: [
+				"generated_headers",
+			],
+		}
+	`
+
+	t.Run("ensure exported include dirs are not automatically re-exported from shared_libs", func(t *testing.T) {
+		ctx := testCc(t, genRuleModules+`
+		cc_library {
+			name: "libfoo",
+			srcs: ["foo.c"],
+			export_include_dirs: ["foo/standard"],
+			export_system_include_dirs: ["foo/system"],
+			generated_headers: ["genrule_foo"],
+			export_generated_headers: ["genrule_foo"],
+		}
+
+		cc_library {
+			name: "libbar",
+			srcs: ["bar.c"],
+			shared_libs: ["libfoo"],
+			export_include_dirs: ["bar/standard"],
+			export_system_include_dirs: ["bar/system"],
+			generated_headers: ["genrule_bar"],
+			export_generated_headers: ["genrule_bar"],
+		}
+		`)
+		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+		checkIncludeDirs(t, ctx, foo,
+			expectedIncludeDirs(`
+				foo/standard
+				.intermediates/genrule_foo/gen/generated_headers
+			`),
+			expectedSystemIncludeDirs(`foo/system`),
+			expectedGeneratedHeaders(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
+			expectedOrderOnlyDeps(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
+		)
+
+		bar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
+		checkIncludeDirs(t, ctx, bar,
+			expectedIncludeDirs(`
+				bar/standard
+				.intermediates/genrule_bar/gen/generated_headers
+			`),
+			expectedSystemIncludeDirs(`bar/system`),
+			expectedGeneratedHeaders(`.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h`),
+			expectedOrderOnlyDeps(`.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h`),
+		)
+	})
+
+	t.Run("ensure exported include dirs are automatically re-exported from whole_static_libs", func(t *testing.T) {
+		ctx := testCc(t, genRuleModules+`
+		cc_library {
+			name: "libfoo",
+			srcs: ["foo.c"],
+			export_include_dirs: ["foo/standard"],
+			export_system_include_dirs: ["foo/system"],
+			generated_headers: ["genrule_foo"],
+			export_generated_headers: ["genrule_foo"],
+		}
+
+		cc_library {
+			name: "libbar",
+			srcs: ["bar.c"],
+			whole_static_libs: ["libfoo"],
+			export_include_dirs: ["bar/standard"],
+			export_system_include_dirs: ["bar/system"],
+			generated_headers: ["genrule_bar"],
+			export_generated_headers: ["genrule_bar"],
+		}
+		`)
+		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+		checkIncludeDirs(t, ctx, foo,
+			expectedIncludeDirs(`
+				foo/standard
+				.intermediates/genrule_foo/gen/generated_headers
+			`),
+			expectedSystemIncludeDirs(`foo/system`),
+			expectedGeneratedHeaders(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
+			expectedOrderOnlyDeps(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
+		)
+
+		bar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
+		checkIncludeDirs(t, ctx, bar,
+			expectedIncludeDirs(`
+				bar/standard
+				foo/standard
+				.intermediates/genrule_foo/gen/generated_headers
+				.intermediates/genrule_bar/gen/generated_headers
+			`),
+			expectedSystemIncludeDirs(`
+				bar/system
+				foo/system
+			`),
+			expectedGeneratedHeaders(`
+				.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h
+				.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h
+			`),
+			expectedOrderOnlyDeps(`
+				.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h
+				.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h
+			`),
+		)
+	})
+
+	t.Run("ensure only aidl headers are exported", func(t *testing.T) {
+		ctx := testCc(t, genRuleModules+`
+		cc_library_shared {
+			name: "libfoo",
+			srcs: [
+				"foo.c",
+				"b.aidl",
+				"a.proto",
+			],
+			aidl: {
+				export_aidl_headers: true,
+			}
+		}
+		`)
+		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+		checkIncludeDirs(t, ctx, foo,
+			expectedIncludeDirs(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl
+			`),
+			expectedSystemIncludeDirs(``),
+			expectedGeneratedHeaders(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+			`),
+			expectedOrderOnlyDeps(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+			`),
+		)
+	})
+
+	t.Run("ensure only proto headers are exported", func(t *testing.T) {
+		ctx := testCc(t, genRuleModules+`
+		cc_library_shared {
+			name: "libfoo",
+			srcs: [
+				"foo.c",
+				"b.aidl",
+				"a.proto",
+			],
+			proto: {
+				export_proto_headers: true,
+			}
+		}
+		`)
+		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+		checkIncludeDirs(t, ctx, foo,
+			expectedIncludeDirs(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto
+			`),
+			expectedSystemIncludeDirs(``),
+			expectedGeneratedHeaders(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto/a.pb.h
+			`),
+			expectedOrderOnlyDeps(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto/a.pb.h
+			`),
+		)
+	})
+
+	t.Run("ensure only sysprop headers are exported", func(t *testing.T) {
+		ctx := testCc(t, genRuleModules+`
+		cc_library_shared {
+			name: "libfoo",
+			srcs: [
+				"foo.c",
+				"a.sysprop",
+				"b.aidl",
+				"a.proto",
+			],
+		}
+		`)
+		foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+		checkIncludeDirs(t, ctx, foo,
+			expectedIncludeDirs(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include
+			`),
+			expectedSystemIncludeDirs(``),
+			expectedGeneratedHeaders(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/a.sysprop.h
+			`),
+			expectedOrderOnlyDeps(`
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/a.sysprop.h
+				.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/public/include/a.sysprop.h
+			`),
+		)
+	})
+}
diff --git a/cc/compiler.go b/cc/compiler.go
index 5f30d3d..e96295c 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -230,6 +230,8 @@
 	// other modules and filegroups. May include source files that have not yet been translated to
 	// C/C++ (.aidl, .proto, etc.)
 	srcsBeforeGen android.Paths
+
+	generatedSourceInfo
 }
 
 var _ compiler = (*baseCompiler)(nil)
@@ -634,10 +636,11 @@
 
 	srcs := append(android.Paths(nil), compiler.srcsBeforeGen...)
 
-	srcs, genDeps := genSources(ctx, srcs, buildFlags)
+	srcs, genDeps, info := genSources(ctx, srcs, buildFlags)
 	pathDeps = append(pathDeps, genDeps...)
 
 	compiler.pathDeps = pathDeps
+	compiler.generatedSourceInfo = info
 	compiler.cFlagsDeps = flags.CFlagsDeps
 
 	// Save src, buildFlags and context
diff --git a/cc/gen.go b/cc/gen.go
index 75b9e49..83c019c 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -220,8 +220,35 @@
 	return rcFile, headerFile
 }
 
+// Used to communicate information from the genSources method back to the library code that uses
+// it.
+type generatedSourceInfo struct {
+	// The headers created from .proto files
+	protoHeaders android.Paths
+
+	// The files that can be used as order only dependencies in order to ensure that the proto header
+	// files are up to date.
+	protoOrderOnlyDeps android.Paths
+
+	// The headers created from .aidl files
+	aidlHeaders android.Paths
+
+	// The files that can be used as order only dependencies in order to ensure that the aidl header
+	// files are up to date.
+	aidlOrderOnlyDeps android.Paths
+
+	// The headers created from .sysprop files
+	syspropHeaders android.Paths
+
+	// The files that can be used as order only dependencies in order to ensure that the sysprop
+	// header files are up to date.
+	syspropOrderOnlyDeps android.Paths
+}
+
 func genSources(ctx android.ModuleContext, srcFiles android.Paths,
-	buildFlags builderFlags) (android.Paths, android.Paths) {
+	buildFlags builderFlags) (android.Paths, android.Paths, generatedSourceInfo) {
+
+	var info generatedSourceInfo
 
 	var deps android.Paths
 	var rsFiles android.Paths
@@ -258,7 +285,9 @@
 		case ".proto":
 			ccFile, headerFile := genProto(ctx, srcFile, buildFlags)
 			srcFiles[i] = ccFile
-			deps = append(deps, headerFile)
+			info.protoHeaders = append(info.protoHeaders, headerFile)
+			// Use the generated header as an order only dep to ensure that it is up to date when needed.
+			info.protoOrderOnlyDeps = append(info.protoOrderOnlyDeps, headerFile)
 		case ".aidl":
 			if aidlRule == nil {
 				aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
@@ -267,7 +296,12 @@
 			cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp")
 			depFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp.d")
 			srcFiles[i] = cppFile
-			deps = append(deps, genAidl(ctx, aidlRule, srcFile, cppFile, depFile, buildFlags.aidlFlags)...)
+			aidlHeaders := genAidl(ctx, aidlRule, srcFile, cppFile, depFile, buildFlags.aidlFlags)
+			info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
+			// Use the generated headers as order only deps to ensure that they are up to date when
+			// needed.
+			// TODO: Reduce the size of the ninja file by using one order only dep for the whole rule
+			info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...)
 		case ".rscript", ".fs":
 			cppFile := rsGeneratedCppFile(ctx, srcFile)
 			rsFiles = append(rsFiles, srcFiles[i])
@@ -279,7 +313,10 @@
 		case ".sysprop":
 			cppFile, headerFiles := genSysprop(ctx, srcFile)
 			srcFiles[i] = cppFile
-			deps = append(deps, headerFiles...)
+			info.syspropHeaders = append(info.syspropHeaders, headerFiles...)
+			// Use the generated headers as order only deps to ensure that they are up to date when
+			// needed.
+			info.syspropOrderOnlyDeps = append(info.syspropOrderOnlyDeps, headerFiles...)
 		}
 	}
 
@@ -291,9 +328,13 @@
 		yaccRule_.Build("yacc", "gen yacc")
 	}
 
+	deps = append(deps, info.protoOrderOnlyDeps...)
+	deps = append(deps, info.aidlOrderOnlyDeps...)
+	deps = append(deps, info.syspropOrderOnlyDeps...)
+
 	if len(rsFiles) > 0 {
 		deps = append(deps, rsGenerateCpp(ctx, rsFiles, buildFlags.rsFlags)...)
 	}
 
-	return srcFiles, deps
+	return srcFiles, deps, info
 }
diff --git a/cc/library.go b/cc/library.go
index 65533bc..0e6e107 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1313,9 +1313,8 @@
 			dir := android.PathForModuleGen(ctx, "aidl")
 			library.reexportDirs(dir)
 
-			// TODO: restrict to aidl deps
-			library.reexportDeps(library.baseCompiler.pathDeps...)
-			library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
+			library.reexportDeps(library.baseCompiler.aidlOrderOnlyDeps...)
+			library.addExportedGeneratedHeaders(library.baseCompiler.aidlHeaders...)
 		}
 	}
 
@@ -1329,9 +1328,8 @@
 			includes = append(includes, flags.proto.Dir)
 			library.reexportDirs(includes...)
 
-			// TODO: restrict to proto deps
-			library.reexportDeps(library.baseCompiler.pathDeps...)
-			library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
+			library.reexportDeps(library.baseCompiler.protoOrderOnlyDeps...)
+			library.addExportedGeneratedHeaders(library.baseCompiler.protoHeaders...)
 		}
 	}
 
@@ -1350,10 +1348,16 @@
 			}
 		}
 
+		// Make sure to only export headers which are within the include directory.
+		_, headers := android.FilterPathListPredicate(library.baseCompiler.syspropHeaders, func(path android.Path) bool {
+			_, isRel := android.MaybeRel(ctx, dir.String(), path.String())
+			return isRel
+		})
+
 		// Add sysprop-related directories to the exported directories of this library.
 		library.reexportDirs(dir)
-		library.reexportDeps(library.baseCompiler.pathDeps...)
-		library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
+		library.reexportDeps(library.baseCompiler.syspropOrderOnlyDeps...)
+		library.addExportedGeneratedHeaders(headers...)
 	}
 
 	// Add stub-related flags if this library is a stub library.
diff --git a/cc/library_headers.go b/cc/library_headers.go
index e5a5557..dc851a5 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -86,7 +86,7 @@
 		return
 	}
 
-	if !module.Properties.Bazel_module.Bp2build_available {
+	if !module.ConvertWithBp2build() {
 		return
 	}
 
@@ -129,13 +129,12 @@
 		Deps:     headerLibLabels,
 	}
 
-	props := bazel.NewBazelTargetModuleProperties(
-		module.Name(),
-		"cc_library_headers",
-		"//build/bazel/rules:cc_library_headers.bzl",
-	)
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_library_headers",
+		Bzl_load_location: "//build/bazel/rules:cc_library_headers.bzl",
+	}
 
-	ctx.CreateBazelTargetModule(BazelCcLibraryHeadersFactory, props, attrs)
+	ctx.CreateBazelTargetModule(BazelCcLibraryHeadersFactory, module.Name(), props, attrs)
 }
 
 func (m *bazelCcLibraryHeaders) Name() string {
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 1402991..d5f2adf 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -206,22 +206,22 @@
 		dirs:         true,
 	},
 	{
-		// exportedGeneratedIncludeDirs lists directories that contains some header files
-		// that are explicitly listed in the exportedGeneratedHeaders property. So, the contents
+		// ExportedGeneratedIncludeDirs lists directories that contains some header files
+		// that are explicitly listed in the ExportedGeneratedHeaders property. So, the contents
 		// of these directories do not need to be copied, but these directories do need adding to
 		// the export_include_dirs property in the prebuilt module in the snapshot.
-		pathsGetter:  func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedIncludeDirs },
+		pathsGetter:  func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedGeneratedIncludeDirs },
 		propertyName: "export_include_dirs",
 		snapshotDir:  nativeGeneratedIncludeDir,
 		copy:         false,
 		dirs:         true,
 	},
 	{
-		// exportedGeneratedHeaders lists header files that are in one of the directories
-		// specified in exportedGeneratedIncludeDirs must be copied into the snapshot.
-		// As they are in a directory in exportedGeneratedIncludeDirs they do not need adding to a
+		// ExportedGeneratedHeaders lists header files that are in one of the directories
+		// specified in ExportedGeneratedIncludeDirs must be copied into the snapshot.
+		// As they are in a directory in ExportedGeneratedIncludeDirs they do not need adding to a
 		// property in the prebuilt module in the snapshot.
-		pathsGetter:  func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedHeaders },
+		pathsGetter:  func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedGeneratedHeaders },
 		propertyName: "",
 		snapshotDir:  nativeGeneratedIncludeDir,
 		copy:         true,
@@ -258,42 +258,52 @@
 	// values where necessary.
 	for _, propertyInfo := range includeDirProperties {
 		// Calculate the base directory in the snapshot into which the files will be copied.
-		// lib.ArchType is "" for common properties.
+		// lib.archType is "" for common properties.
 		targetDir := filepath.Join(libInfo.OsPrefix(), libInfo.archType, propertyInfo.snapshotDir)
 
 		propertyName := propertyInfo.propertyName
 
 		// Iterate over each path in one of the include directory properties.
 		for _, path := range propertyInfo.pathsGetter(libInfo) {
+			inputPath := path.String()
+
+			// Map the input path to a snapshot relative path. The mapping is independent of the module
+			// that references them so that if multiple modules within the same snapshot export the same
+			// header files they end up in the same place in the snapshot and so do not get duplicated.
+			targetRelativePath := inputPath
+			if isGeneratedHeaderDirectory(path) {
+				// Remove everything up to the .intermediates/ from the generated output directory to
+				// leave a module relative path.
+				base := android.PathForIntermediates(sdkModuleContext, "")
+				targetRelativePath = android.Rel(sdkModuleContext, base.String(), inputPath)
+			}
+
+			snapshotRelativePath := filepath.Join(targetDir, targetRelativePath)
 
 			// Copy the files/directories when necessary.
 			if propertyInfo.copy {
 				if propertyInfo.dirs {
 					// When copying a directory glob and copy all the headers within it.
 					// TODO(jiyong) copy headers having other suffixes
-					headers, _ := sdkModuleContext.GlobWithDeps(path.String()+"/**/*.h", nil)
+					headers, _ := sdkModuleContext.GlobWithDeps(inputPath+"/**/*.h", nil)
 					for _, file := range headers {
 						src := android.PathForSource(sdkModuleContext, file)
-						dest := filepath.Join(targetDir, file)
+
+						// The destination path in the snapshot is constructed from the snapshot relative path
+						// of the input directory and the input directory relative path of the header file.
+						inputRelativePath := android.Rel(sdkModuleContext, inputPath, file)
+						dest := filepath.Join(snapshotRelativePath, inputRelativePath)
 						builder.CopyToSnapshot(src, dest)
 					}
 				} else {
-					// Otherwise, just copy the files.
-					dest := filepath.Join(targetDir, libInfo.name, path.Rel())
-					builder.CopyToSnapshot(path, dest)
+					// Otherwise, just copy the file to its snapshot relative path.
+					builder.CopyToSnapshot(path, snapshotRelativePath)
 				}
 			}
 
 			// Only directories are added to a property.
 			if propertyInfo.dirs {
-				var snapshotPath string
-				if isGeneratedHeaderDirectory(path) {
-					snapshotPath = filepath.Join(targetDir, libInfo.name)
-				} else {
-					snapshotPath = filepath.Join(targetDir, path.String())
-				}
-
-				includeDirs[propertyName] = append(includeDirs[propertyName], snapshotPath)
+				includeDirs[propertyName] = append(includeDirs[propertyName], snapshotRelativePath)
 			}
 		}
 	}
@@ -330,9 +340,6 @@
 
 	memberType *librarySdkMemberType
 
-	// The name of the library, is not exported as this must not be changed during optimization.
-	name string
-
 	// archType is not exported as if set (to a non default value) it is always arch specific.
 	// This is "" for common properties.
 	archType string
@@ -344,13 +351,13 @@
 
 	// The list of arch specific exported generated include dirs.
 	//
-	// This field is not exported as its contents are always arch specific.
-	exportedGeneratedIncludeDirs android.Paths
+	// This field is exported as its contents may not be arch specific, e.g. protos.
+	ExportedGeneratedIncludeDirs android.Paths `android:"arch_variant"`
 
 	// The list of arch specific exported generated header files.
 	//
-	// This field is not exported as its contents are is always arch specific.
-	exportedGeneratedHeaders android.Paths
+	// This field is exported as its contents may not be arch specific, e.g. protos.
+	ExportedGeneratedHeaders android.Paths `android:"arch_variant"`
 
 	// The list of possibly common exported system include dirs.
 	//
@@ -419,12 +426,11 @@
 	exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
 		exportedInfo.IncludeDirs, isGeneratedHeaderDirectory)
 
-	p.name = variant.Name()
 	p.archType = ccModule.Target().Arch.ArchType.String()
 
 	// Make sure that the include directories are unique.
 	p.ExportedIncludeDirs = android.FirstUniquePaths(exportedIncludeDirs)
-	p.exportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
+	p.ExportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
 
 	// Take a copy before filtering out duplicates to avoid changing the slice owned by the
 	// ccModule.
@@ -450,7 +456,7 @@
 		}
 		p.SystemSharedLibs = specifiedDeps.systemSharedLibs
 	}
-	p.exportedGeneratedHeaders = exportedInfo.GeneratedHeaders
+	p.ExportedGeneratedHeaders = exportedInfo.GeneratedHeaders
 
 	if !p.memberType.noOutputFiles && addOutputFile {
 		p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
diff --git a/cc/object.go b/cc/object.go
index d92e110..b108c1c 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -118,7 +118,7 @@
 // Bazel equivalent target, plus any necessary include deps for the cc_object.
 func ObjectBp2Build(ctx android.TopDownMutatorContext) {
 	m, ok := ctx.Module().(*Module)
-	if !ok || !m.Properties.Bazel_module.Bp2build_available {
+	if !ok || !m.ConvertWithBp2build() {
 		return
 	}
 
@@ -150,13 +150,12 @@
 		Local_include_dirs: localIncludeDirs,
 	}
 
-	props := bazel.NewBazelTargetModuleProperties(
-		m.Name(),
-		"cc_object",
-		"//build/bazel/rules:cc_object.bzl",
-	)
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_object",
+		Bzl_load_location: "//build/bazel/rules:cc_object.bzl",
+	}
 
-	ctx.CreateBazelTargetModule(BazelObjectFactory, props, attrs)
+	ctx.CreateBazelTargetModule(BazelObjectFactory, m.Name(), props, attrs)
 }
 
 func (object *objectLinker) appendLdflags(flags []string) {
diff --git a/cc/vndk.go b/cc/vndk.go
index ff38db5..85028d0 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -561,7 +561,7 @@
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(txt.outputFile),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base())
 			},
 		},
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index d55204b..36a5e2a 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -84,6 +84,15 @@
 	BootFlags         string        // extra flags to pass to dex2oat for the boot image
 	Dex2oatImageXmx   string        // max heap size for dex2oat for the boot image
 	Dex2oatImageXms   string        // initial heap size for dex2oat for the boot image
+
+	// If true, downgrade the compiler filter of dexpreopt to "extract" when verify_uses_libraries
+	// check fails, instead of failing the build. This will disable any AOT-compilation.
+	//
+	// The intended use case for this flag is to have a smoother migration path for the Java
+	// modules that need to add <uses-library> information in their build files. The flag allows to
+	// quickly silence build errors. This flag should be used with caution and only as a temporary
+	// measure, as it masks real errors and affects performance.
+	RelaxUsesLibraryCheck bool
 }
 
 // GlobalSoongConfig contains the global config that is generated from Soong,
@@ -113,9 +122,10 @@
 	ProfileIsTextListing bool
 	ProfileBootListing   android.OptionalPath
 
-	EnforceUsesLibraries bool
-	ProvidesUsesLibrary  string // the name of the <uses-library> (usually the same as its module)
-	ClassLoaderContexts  ClassLoaderContextMap
+	EnforceUsesLibraries           bool         // turn on build-time verify_uses_libraries check
+	EnforceUsesLibrariesStatusFile android.Path // a file with verify_uses_libraries errors (if any)
+	ProvidesUsesLibrary            string       // library name (usually the same as module name)
+	ClassLoaderContexts            ClassLoaderContextMap
 
 	Archs                   []android.ArchType
 	DexPreoptImages         []android.Path
@@ -258,14 +268,15 @@
 
 		// Copies of entries in ModuleConfig that are not constructable without extra parameters.  They will be
 		// used to construct the real value manually below.
-		BuildPath                   string
-		DexPath                     string
-		ManifestPath                string
-		ProfileClassListing         string
-		ClassLoaderContexts         jsonClassLoaderContextMap
-		DexPreoptImages             []string
-		DexPreoptImageLocations     []string
-		PreoptBootClassPathDexFiles []string
+		BuildPath                      string
+		DexPath                        string
+		ManifestPath                   string
+		ProfileClassListing            string
+		EnforceUsesLibrariesStatusFile string
+		ClassLoaderContexts            jsonClassLoaderContextMap
+		DexPreoptImages                []string
+		DexPreoptImageLocations        []string
+		PreoptBootClassPathDexFiles    []string
 	}
 
 	config := ModuleJSONConfig{}
@@ -280,6 +291,7 @@
 	config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
 	config.ModuleConfig.ManifestPath = constructPath(ctx, config.ManifestPath)
 	config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
+	config.ModuleConfig.EnforceUsesLibrariesStatusFile = constructPath(ctx, config.EnforceUsesLibrariesStatusFile)
 	config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts)
 	config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
 	config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index b0a684e..6e0fe01 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -279,11 +279,12 @@
 
 		// Generate command that saves host and target class loader context in shell variables.
 		clc, paths := ComputeClassLoaderContext(module.ClassLoaderContexts)
-		cmd := rule.Command().
-			Text(`eval "$(`).Tool(globalSoong.ConstructContext).
+		rule.Command().
+			Text("if ! test -s ").Input(module.EnforceUsesLibrariesStatusFile).
+			Text(` ; then eval "$(`).Tool(globalSoong.ConstructContext).
 			Text(` --target-sdk-version ${target_sdk_version}`).
-			Text(clc).Implicits(paths)
-		cmd.Text(`)"`)
+			Text(clc).Implicits(paths).
+			Text(`)" ; fi`)
 
 	} else {
 		// Other libraries or APKs for which the exact <uses-library> list is unknown.
@@ -366,7 +367,16 @@
 		} else {
 			compilerFilter = "quicken"
 		}
-		cmd.FlagWithArg("--compiler-filter=", compilerFilter)
+		if module.EnforceUsesLibraries {
+			// If the verify_uses_libraries check failed (in this case status file contains a
+			// non-empty error message), then use "extract" compiler filter to avoid compiling any
+			// code (it would be rejected on device because of a class loader context mismatch).
+			cmd.Text("--compiler-filter=$(if test -s ").
+				Input(module.EnforceUsesLibrariesStatusFile).
+				Text(" ; then echo extract ; else echo " + compilerFilter + " ; fi)")
+		} else {
+			cmd.FlagWithArg("--compiler-filter=", compilerFilter)
+		}
 	}
 
 	if generateDM {
@@ -542,6 +552,12 @@
 	}
 }
 
+// Returns path to a file containing the reult of verify_uses_libraries check (empty if the check
+// has succeeded, or an error message if it failed).
+func UsesLibrariesStatusFile(ctx android.ModuleContext) android.WritablePath {
+	return android.PathForModuleOut(ctx, "enforce_uses_libraries.status")
+}
+
 func contains(l []string, s string) bool {
 	for _, e := range l {
 		if e == s {
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index af73d0c..12df36b 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -43,6 +43,7 @@
 		PreoptFlags:                     nil,
 		ProfileClassListing:             android.OptionalPath{},
 		ProfileIsTextListing:            false,
+		EnforceUsesLibrariesStatusFile:  android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)),
 		EnforceUsesLibraries:            false,
 		ClassLoaderContexts:             nil,
 		Archs:                           []android.ArchType{android.Arm},
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index e15324b..b07ad91 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -309,7 +309,7 @@
 		SubName:    nameSuffix,
 		OutputFile: android.OptionalPathForPath(p.outputFilePath),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_TAGS", "optional")
 				entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.ToMakePath().String())
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index 6c4c0b6..585760d 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -175,7 +175,7 @@
 }
 
 func TestPrebuiltEtcAndroidMk(t *testing.T) {
-	ctx, config := testPrebuiltEtc(t, `
+	ctx, _ := testPrebuiltEtc(t, `
 		prebuilt_etc {
 			name: "foo",
 			src: "foo.conf",
@@ -198,7 +198,7 @@
 	}
 
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 	for k, expectedValue := range expected {
 		if value, ok := entries.EntryMap[k]; ok {
 			if !reflect.DeepEqual(value, expectedValue) {
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index 42a4c88..dcdbdcf 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -13,6 +13,7 @@
     srcs: [
         "bootimg.go",
         "filesystem.go",
+        "logical_partition.go",
     ],
     testSrcs: [
     ],
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index c90929a..764f045 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -107,14 +107,8 @@
 }
 
 func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	var unsignedOutput android.OutputPath
-	if proptools.Bool(b.properties.Vendor_boot) {
-		unsignedOutput = b.buildVendorBootImage(ctx)
-	} else {
-		// TODO(jiyong): fix this
-		ctx.PropertyErrorf("vendor_boot", "only vendor_boot:true is supported")
-		return
-	}
+	vendor := proptools.Bool(b.properties.Vendor_boot)
+	unsignedOutput := b.buildBootImage(ctx, vendor)
 
 	if proptools.Bool(b.properties.Use_avb) {
 		b.output = b.signImage(ctx, unsignedOutput)
@@ -126,17 +120,24 @@
 	ctx.InstallFile(b.installDir, b.installFileName(), b.output)
 }
 
-func (b *bootimg) buildVendorBootImage(ctx android.ModuleContext) android.OutputPath {
+func (b *bootimg) buildBootImage(ctx android.ModuleContext, vendor bool) android.OutputPath {
 	output := android.PathForModuleOut(ctx, "unsigned", b.installFileName()).OutputPath
 
 	builder := android.NewRuleBuilder(pctx, ctx)
 	cmd := builder.Command().BuiltTool("mkbootimg")
 
-	kernel := android.OptionalPathForModuleSrc(ctx, b.properties.Kernel_prebuilt)
-	if kernel.Valid() {
+	kernel := proptools.String(b.properties.Kernel_prebuilt)
+	if vendor && kernel != "" {
 		ctx.PropertyErrorf("kernel_prebuilt", "vendor_boot partition can't have kernel")
 		return output
 	}
+	if !vendor && kernel == "" {
+		ctx.PropertyErrorf("kernel_prebuilt", "boot partition must have kernel")
+		return output
+	}
+	if kernel != "" {
+		cmd.FlagWithInput("--kernel ", android.PathForModuleSrc(ctx, kernel))
+	}
 
 	dtbName := proptools.String(b.properties.Dtb_prebuilt)
 	if dtbName == "" {
@@ -148,7 +149,11 @@
 
 	cmdline := proptools.String(b.properties.Cmdline)
 	if cmdline != "" {
-		cmd.FlagWithArg("--vendor_cmdline ", "\""+cmdline+"\"")
+		flag := "--cmdline "
+		if vendor {
+			flag = "--vendor_cmdline "
+		}
+		cmd.FlagWithArg(flag, "\""+proptools.ShellEscape(cmdline)+"\"")
 	}
 
 	headerVersion := proptools.String(b.properties.Header_version)
@@ -174,15 +179,23 @@
 	}
 	ramdisk := ctx.GetDirectDepWithTag(ramdiskName, bootimgRamdiskDep)
 	if filesystem, ok := ramdisk.(*filesystem); ok {
-		cmd.FlagWithInput("--vendor_ramdisk ", filesystem.OutputPath())
+		flag := "--ramdisk "
+		if vendor {
+			flag = "--vendor_ramdisk "
+		}
+		cmd.FlagWithInput(flag, filesystem.OutputPath())
 	} else {
 		ctx.PropertyErrorf("ramdisk", "%q is not android_filesystem module", ramdisk.Name())
 		return output
 	}
 
-	cmd.FlagWithOutput("--vendor_boot ", output)
+	flag := "--output "
+	if vendor {
+		flag = "--vendor_boot "
+	}
+	cmd.FlagWithOutput(flag, output)
 
-	builder.Build("build_vendor_bootimg", fmt.Sprintf("Creating %s", b.BaseModuleName()))
+	builder.Build("build_bootimg", fmt.Sprintf("Creating %s", b.BaseModuleName()))
 	return output
 }
 
@@ -211,7 +224,7 @@
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(b.output),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_PATH", b.installDir.ToMakePath().String())
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", b.installFileName())
 			},
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 3bccde9..3b0a7ae 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -358,7 +358,7 @@
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(f.output),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_PATH", f.installDir.ToMakePath().String())
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", f.installFileName())
 			},
diff --git a/filesystem/logical_partition.go b/filesystem/logical_partition.go
new file mode 100644
index 0000000..e547203
--- /dev/null
+++ b/filesystem/logical_partition.go
@@ -0,0 +1,210 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package filesystem
+
+import (
+	"fmt"
+	"strconv"
+
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+)
+
+func init() {
+	android.RegisterModuleType("logical_partition", logicalPartitionFactory)
+}
+
+type logicalPartition struct {
+	android.ModuleBase
+
+	properties logicalPartitionProperties
+
+	output     android.OutputPath
+	installDir android.InstallPath
+}
+
+type logicalPartitionProperties struct {
+	// Set the name of the output. Defaults to <module_name>.img.
+	Stem *string
+
+	// Total size of the logical partition
+	Size *string
+
+	// List of groups. A group defines a fixed sized region. It can host one or more logical
+	// partitions and their total size is limited by the size of the group they are in.
+	Groups []groupProperties
+
+	// Whether the output is a sparse image or not. Default is false.
+	Sparse *bool
+}
+
+type groupProperties struct {
+	// Name of the partition group
+	Name *string
+
+	// Size of the partition group
+	Size *string
+
+	// List of logical partitions in this group
+	Partitions []partitionProperties
+}
+
+type partitionProperties struct {
+	// Name of the partition
+	Name *string
+
+	// Filesystem that is placed on the partition
+	Filesystem *string `android:"path"`
+}
+
+// logical_partition is a partition image which has one or more logical partitions in it.
+func logicalPartitionFactory() android.Module {
+	module := &logicalPartition{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	return module
+}
+
+func (l *logicalPartition) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// do nothing
+}
+
+func (l *logicalPartition) installFileName() string {
+	return proptools.StringDefault(l.properties.Stem, l.BaseModuleName()+".img")
+}
+
+func (l *logicalPartition) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	builder := android.NewRuleBuilder(pctx, ctx)
+
+	// Sparse the filesystem images and calculate their sizes
+	sparseImages := make(map[string]android.OutputPath)
+	sparseImageSizes := make(map[string]android.OutputPath)
+	for _, group := range l.properties.Groups {
+		for _, part := range group.Partitions {
+			sparseImg, sizeTxt := sparseFilesystem(ctx, part, builder)
+			pName := proptools.String(part.Name)
+			sparseImages[pName] = sparseImg
+			sparseImageSizes[pName] = sizeTxt
+		}
+	}
+
+	cmd := builder.Command().BuiltTool("lpmake")
+
+	size := proptools.String(l.properties.Size)
+	if size == "" {
+		ctx.PropertyErrorf("size", "must be set")
+	}
+	if _, err := strconv.Atoi(size); err != nil {
+		ctx.PropertyErrorf("size", "must be a number")
+	}
+	cmd.FlagWithArg("--device-size=", size)
+
+	// TODO(jiyong): consider supporting A/B devices. Then we need to adjust num of slots.
+	cmd.FlagWithArg("--metadata-slots=", "2")
+	cmd.FlagWithArg("--metadata-size=", "65536")
+
+	if proptools.Bool(l.properties.Sparse) {
+		cmd.Flag("--sparse")
+	}
+
+	groupNames := make(map[string]bool)
+	partitionNames := make(map[string]bool)
+
+	for _, group := range l.properties.Groups {
+		gName := proptools.String(group.Name)
+		if gName == "" {
+			ctx.PropertyErrorf("groups.name", "must be set")
+		}
+		if _, ok := groupNames[gName]; ok {
+			ctx.PropertyErrorf("group.name", "already exists")
+		} else {
+			groupNames[gName] = true
+		}
+		gSize := proptools.String(group.Size)
+		if gSize == "" {
+			ctx.PropertyErrorf("groups.size", "must be set")
+		}
+		if _, err := strconv.Atoi(gSize); err != nil {
+			ctx.PropertyErrorf("groups.size", "must be a number")
+		}
+		cmd.FlagWithArg("--group=", gName+":"+gSize)
+
+		for _, part := range group.Partitions {
+			pName := proptools.String(part.Name)
+			if pName == "" {
+				ctx.PropertyErrorf("groups.partitions.name", "must be set")
+			}
+			if _, ok := partitionNames[pName]; ok {
+				ctx.PropertyErrorf("groups.partitions.name", "already exists")
+			} else {
+				partitionNames[pName] = true
+			}
+			// Get size of the partition by reading the -size.txt file
+			pSize := fmt.Sprintf("$(cat %s)", sparseImageSizes[pName])
+			cmd.FlagWithArg("--partition=", fmt.Sprintf("%s:readonly:%s:%s", pName, pSize, gName))
+			cmd.FlagWithInput("--image="+pName+"=", sparseImages[pName])
+		}
+	}
+
+	l.output = android.PathForModuleOut(ctx, l.installFileName()).OutputPath
+	cmd.FlagWithOutput("--output=", l.output)
+
+	builder.Build("build_logical_partition", fmt.Sprintf("Creating %s", l.BaseModuleName()))
+
+	l.installDir = android.PathForModuleInstall(ctx, "etc")
+	ctx.InstallFile(l.installDir, l.installFileName(), l.output)
+}
+
+// Add a rule that converts the filesystem for the given partition to the given rule builder. The
+// path to the sparse file and the text file having the size of the partition are returned.
+func sparseFilesystem(ctx android.ModuleContext, p partitionProperties, builder *android.RuleBuilder) (sparseImg android.OutputPath, sizeTxt android.OutputPath) {
+	img := android.PathForModuleSrc(ctx, proptools.String(p.Filesystem))
+	name := proptools.String(p.Name)
+	sparseImg = android.PathForModuleOut(ctx, name+".img").OutputPath
+
+	builder.Temporary(sparseImg)
+	builder.Command().BuiltTool("img2simg").Input(img).Output(sparseImg)
+
+	sizeTxt = android.PathForModuleOut(ctx, name+"-size.txt").OutputPath
+	builder.Temporary(sizeTxt)
+	builder.Command().BuiltTool("sparse_img").Flag("--get_partition_size").Input(sparseImg).
+		Text("| ").Text("tr").FlagWithArg("-d ", "'\n'").
+		Text("> ").Output(sizeTxt)
+
+	return sparseImg, sizeTxt
+}
+
+var _ android.AndroidMkEntriesProvider = (*logicalPartition)(nil)
+
+// Implements android.AndroidMkEntriesProvider
+func (l *logicalPartition) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(l.output),
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+				entries.SetString("LOCAL_MODULE_PATH", l.installDir.ToMakePath().String())
+				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", l.installFileName())
+			},
+		},
+	}}
+}
+
+var _ Filesystem = (*logicalPartition)(nil)
+
+func (l *logicalPartition) OutputPath() android.Path {
+	return l.output
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 9fa6c48..b4303a6 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -124,14 +124,12 @@
 
 	// input files to exclude
 	Exclude_srcs []string `android:"path,arch_variant"`
-
-	// Properties for Bazel migration purposes.
-	bazel.Properties
 }
 
 type Module struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.BazelModuleBase
 	android.ApexModuleBase
 
 	// For other packages to make their own genrules with extra
@@ -519,7 +517,7 @@
 
 	g.outputFiles = outputFiles.Paths()
 
-	bazelModuleLabel := g.properties.Bazel_module.Label
+	bazelModuleLabel := g.GetBazelLabel()
 	bazelActionsUsed := false
 	if ctx.Config().BazelContext.BazelEnabled() && len(bazelModuleLabel) > 0 {
 		bazelActionsUsed = g.generateBazelBuildActions(ctx, bazelModuleLabel)
@@ -771,6 +769,7 @@
 	m := NewGenRule()
 	android.InitAndroidModule(m)
 	android.InitDefaultableModule(m)
+	android.InitBazelModule(m)
 	return m
 }
 
@@ -800,7 +799,7 @@
 
 func GenruleBp2Build(ctx android.TopDownMutatorContext) {
 	m, ok := ctx.Module().(*Module)
-	if !ok || !m.properties.Bazel_module.Bp2build_available {
+	if !ok || !m.ConvertWithBp2build() {
 		return
 	}
 
@@ -853,10 +852,12 @@
 		Tools: tools,
 	}
 
-	props := bazel.NewBazelTargetModuleProperties(m.Name(), "genrule", "")
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class: "genrule",
+	}
 
 	// Create the BazelTargetModule.
-	ctx.CreateBazelTargetModule(BazelGenruleFactory, props, attrs)
+	ctx.CreateBazelTargetModule(BazelGenruleFactory, m.Name(), props, attrs)
 }
 
 func (m *bazelGenrule) Name() string {
diff --git a/java/androidmk.go b/java/androidmk.go
index 6e7c437..9bdb70c 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -41,7 +41,7 @@
 			Required:   library.deviceProperties.Target.Hostdex.Required,
 			Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-				func(entries *android.AndroidMkEntries) {
+				func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 					entries.SetBool("LOCAL_IS_HOST_MODULE", true)
 					entries.SetPath("LOCAL_PREBUILT_MODULE_FILE", output)
 					if library.dexJarFile != nil {
@@ -74,7 +74,7 @@
 				OutputFile: android.OptionalPathForPath(checkedModulePaths[0]),
 				Include:    "$(BUILD_PHONY_PACKAGE)",
 				ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-					func(entries *android.AndroidMkEntries) {
+					func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 						entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", checkedModulePaths.Strings()...)
 					},
 				},
@@ -88,7 +88,7 @@
 			OutputFile: android.OptionalPathForPath(library.outputFile),
 			Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-				func(entries *android.AndroidMkEntries) {
+				func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 					if len(library.logtagsSrcs) > 0 {
 						var logtags []string
 						for _, l := range library.logtagsSrcs {
@@ -152,7 +152,7 @@
 func (j *Test) AndroidMkEntries() []android.AndroidMkEntries {
 	entriesList := j.Library.AndroidMkEntries()
 	entries := &entriesList[0]
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, j.testProperties.Test_suites)
 		if j.testConfig != nil {
 			entries.SetPath("LOCAL_FULL_TEST_CONFIG", j.testConfig)
@@ -180,7 +180,7 @@
 func (j *TestHelperLibrary) AndroidMkEntries() []android.AndroidMkEntries {
 	entriesList := j.Library.AndroidMkEntries()
 	entries := &entriesList[0]
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, j.testHelperLibraryProperties.Test_suites)
 	})
 
@@ -198,7 +198,7 @@
 		OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
 		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
 				if prebuilt.dexJarFile != nil {
 					entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile)
@@ -223,7 +223,7 @@
 		OutputFile: android.OptionalPathForPath(prebuilt.maybeStrippedDexJarFile),
 		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				if prebuilt.dexJarFile != nil {
 					entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile)
 				}
@@ -247,7 +247,7 @@
 		OutputFile: android.OptionalPathForPath(prebuilt.classpathFile),
 		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
 				entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile)
 				entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile)
@@ -269,7 +269,7 @@
 			OutputFile: android.OptionalPathForPath(binary.outputFile),
 			Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-				func(entries *android.AndroidMkEntries) {
+				func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 					entries.SetPath("LOCAL_SOONG_HEADER_JAR", binary.headerJarFile)
 					entries.SetPath("LOCAL_SOONG_CLASSES_JAR", binary.implementationAndResourcesJar)
 					if binary.dexJarFile != nil {
@@ -287,11 +287,18 @@
 			},
 		}}
 	} else {
+		outputFile := binary.wrapperFile
+		// Have Make installation trigger Soong installation by using Soong's install path as
+		// the output file.
+		if binary.Host() {
+			outputFile = binary.binaryFile
+		}
+
 		return []android.AndroidMkEntries{android.AndroidMkEntries{
 			Class:      "EXECUTABLES",
-			OutputFile: android.OptionalPathForPath(binary.wrapperFile),
+			OutputFile: android.OptionalPathForPath(outputFile),
 			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-				func(entries *android.AndroidMkEntries) {
+				func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 					entries.SetBool("LOCAL_STRIP_MODULE", false)
 				},
 			},
@@ -317,7 +324,7 @@
 		OutputFile: android.OptionalPathForPath(app.outputFile),
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				// App module names can be overridden.
 				entries.SetString("LOCAL_MODULE", app.installApkName)
 				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", app.appProperties.PreventInstall)
@@ -432,7 +439,7 @@
 func (a *AndroidTest) AndroidMkEntries() []android.AndroidMkEntries {
 	entriesList := a.AndroidApp.AndroidMkEntries()
 	entries := &entriesList[0]
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, a.testProperties.Test_suites)
 		if a.testConfig != nil {
 			entries.SetPath("LOCAL_FULL_TEST_CONFIG", a.testConfig)
@@ -448,7 +455,7 @@
 func (a *AndroidTestHelperApp) AndroidMkEntries() []android.AndroidMkEntries {
 	entriesList := a.AndroidApp.AndroidMkEntries()
 	entries := &entriesList[0]
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, a.appTestHelperAppProperties.Test_suites)
 	})
 
@@ -464,7 +471,7 @@
 	entriesList := a.Library.AndroidMkEntries()
 	entries := &entriesList[0]
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		if a.aarFile != nil {
 			entries.SetPath("LOCAL_SOONG_AAR", a.aarFile)
 		}
@@ -492,7 +499,7 @@
 		OutputFile: android.OptionalPathForPath(jd.stubsSrcJar),
 		Include:    "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				if BoolDefault(jd.properties.Installable, true) {
 					entries.SetPath("LOCAL_DROIDDOC_DOC_ZIP", jd.docZip)
 				}
@@ -510,7 +517,7 @@
 		OutputFile: android.OptionalPathForPath(ddoc.Javadoc.docZip),
 		Include:    "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				if ddoc.Javadoc.docZip != nil {
 					entries.SetPath("LOCAL_DROIDDOC_DOC_ZIP", ddoc.Javadoc.docZip)
 				}
@@ -539,7 +546,7 @@
 		OutputFile: outputFile,
 		Include:    "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				if dstubs.Javadoc.stubsSrcJar != nil {
 					entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", dstubs.Javadoc.stubsSrcJar)
 				}
@@ -638,7 +645,7 @@
 		OutputFile: android.OptionalPathForPath(a.outputFile),
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", a.Privileged())
 				entries.SetString("LOCAL_CERTIFICATE", a.certificate.AndroidMkString())
 				entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", a.properties.Overrides...)
@@ -657,7 +664,7 @@
 func (a *AndroidTestImport) AndroidMkEntries() []android.AndroidMkEntries {
 	entriesList := a.AndroidAppImport.AndroidMkEntries()
 	entries := &entriesList[0]
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+	entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, a.testProperties.Test_suites)
 		androidMkWriteTestData(a.data, entries)
 	})
@@ -678,7 +685,7 @@
 		OutputFile: android.OptionalPathForPath(r.outputFile),
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_CERTIFICATE", r.certificate.AndroidMkString())
 				entries.SetPath("LOCAL_MODULE_PATH", r.installDir.ToMakePath())
 				entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", r.properties.Overrides...)
@@ -694,7 +701,7 @@
 			OutputFile: android.OptionalPathForPath(apkSet.packedOutput),
 			Include:    "$(BUILD_SYSTEM)/soong_android_app_set.mk",
 			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-				func(entries *android.AndroidMkEntries) {
+				func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 					entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", apkSet.Privileged())
 					entries.SetString("LOCAL_APK_SET_INSTALL_FILE", apkSet.InstallFile())
 					entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile)
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index e2647cf..e758a92 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -22,7 +22,7 @@
 )
 
 func TestRequired(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
 			srcs: ["a.java"],
@@ -31,7 +31,7 @@
 	`)
 
 	mod := ctx.ModuleForTests("foo", "android_common").Module()
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 
 	expected := []string{"libfoo"}
 	actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
@@ -41,7 +41,7 @@
 }
 
 func TestHostdex(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
 			srcs: ["a.java"],
@@ -50,7 +50,7 @@
 	`)
 
 	mod := ctx.ModuleForTests("foo", "android_common").Module()
-	entriesList := android.AndroidMkEntriesForTest(t, config, "", mod)
+	entriesList := android.AndroidMkEntriesForTest(t, ctx, mod)
 	if len(entriesList) != 2 {
 		t.Errorf("two entries are expected, but got %d", len(entriesList))
 	}
@@ -71,7 +71,7 @@
 }
 
 func TestHostdexRequired(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
 			srcs: ["a.java"],
@@ -81,7 +81,7 @@
 	`)
 
 	mod := ctx.ModuleForTests("foo", "android_common").Module()
-	entriesList := android.AndroidMkEntriesForTest(t, config, "", mod)
+	entriesList := android.AndroidMkEntriesForTest(t, ctx, mod)
 	if len(entriesList) != 2 {
 		t.Errorf("two entries are expected, but got %d", len(entriesList))
 	}
@@ -102,7 +102,7 @@
 }
 
 func TestHostdexSpecificRequired(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		java_library {
 			name: "foo",
 			srcs: ["a.java"],
@@ -116,7 +116,7 @@
 	`)
 
 	mod := ctx.ModuleForTests("foo", "android_common").Module()
-	entriesList := android.AndroidMkEntriesForTest(t, config, "", mod)
+	entriesList := android.AndroidMkEntriesForTest(t, ctx, mod)
 	if len(entriesList) != 2 {
 		t.Errorf("two entries are expected, but got %d", len(entriesList))
 	}
@@ -135,7 +135,7 @@
 }
 
 func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		java_sdk_library {
 			name: "foo-shared_library",
 			srcs: ["a.java"],
@@ -159,7 +159,7 @@
 	}
 	for _, tc := range testCases {
 		mod := ctx.ModuleForTests(tc.moduleName, "android_common").Module()
-		entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+		entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 		actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
 		if !reflect.DeepEqual(tc.expected, actual) {
 			t.Errorf("Unexpected required modules - expected: %q, actual: %q", tc.expected, actual)
@@ -168,7 +168,7 @@
 }
 
 func TestImportSoongDexJar(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		java_import {
 			name: "my-java-import",
 			jars: ["a.jar"],
@@ -178,7 +178,7 @@
 	`)
 
 	mod := ctx.ModuleForTests("my-java-import", "android_common").Module()
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 	expectedSoongDexJar := buildDir + "/.intermediates/my-java-import/android_common/dex/my-java-import.jar"
 	actualSoongDexJar := entries.EntryMap["LOCAL_SOONG_DEX_JAR"]
 
diff --git a/java/app.go b/java/app.go
index ce89e9b..5181207 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1260,13 +1260,19 @@
 // in the uses_libs and optional_uses_libs properties.  It returns the path to a copy of the manifest.
 func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
 	outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
+	statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 	cmd := rule.Command().BuiltTool("manifest_check").
 		Flag("--enforce-uses-libraries").
 		Input(manifest).
+		FlagWithOutput("--enforce-uses-libraries-status ", statusFile).
 		FlagWithOutput("-o ", outputFile)
 
+	if dexpreopt.GetGlobalConfig(ctx).RelaxUsesLibraryCheck {
+		cmd.Flag("--enforce-uses-libraries-relax")
+	}
+
 	for _, lib := range u.usesLibraryProperties.Uses_libs {
 		cmd.FlagWithArg("--uses-library ", lib)
 	}
@@ -1284,6 +1290,7 @@
 // in the uses_libs and optional_uses_libs properties.  It returns the path to a copy of the APK.
 func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) android.Path {
 	outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
+	statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 	aapt := ctx.Config().HostToolPath(ctx, "aapt")
@@ -1291,7 +1298,8 @@
 		Textf("aapt_binary=%s", aapt.String()).Implicit(aapt).
 		Textf(`uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Uses_libs, " ")).
 		Textf(`optional_uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Optional_uses_libs, " ")).
-		Tool(android.PathForSource(ctx, "build/make/core/verify_uses_libraries.sh")).Input(apk)
+		Textf(`relax_check="%b"`, dexpreopt.GetGlobalConfig(ctx).RelaxUsesLibraryCheck).
+		Tool(android.PathForSource(ctx, "build/make/core/verify_uses_libraries.sh")).Input(apk).Output(statusFile)
 	rule.Command().Text("cp -f").Input(apk).Output(outputFile)
 
 	rule.Build("verify_uses_libraries", "verify <uses-library>")
diff --git a/java/app_import_test.go b/java/app_import_test.go
index d7f69eb..dc31d07 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -232,7 +232,7 @@
 }
 
 func TestAndroidAppImport_Filename(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		android_app_import {
 			name: "foo",
 			apk: "prebuilts/apk/app.apk",
@@ -269,8 +269,7 @@
 
 		a := variant.Module().(*AndroidAppImport)
 		expectedValues := []string{test.expected}
-		actualValues := android.AndroidMkEntriesForTest(
-			t, config, "", a)[0].EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
+		actualValues := android.AndroidMkEntriesForTest(t, ctx, a)[0].EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
 		if !reflect.DeepEqual(actualValues, expectedValues) {
 			t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
 				actualValues, expectedValues)
@@ -394,7 +393,7 @@
 }
 
 func TestAndroidAppImport_frameworkRes(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		android_app_import {
 			name: "framework-res",
 			certificate: "platform",
@@ -424,7 +423,7 @@
 
 	}
 
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 
 	expectedPath := "."
 	// From apk property above, in the root of the source tree.
@@ -457,7 +456,7 @@
 }
 
 func TestAndroidTestImport(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		android_test_import {
 			name: "foo",
 			apk: "prebuilts/apk/app.apk",
@@ -471,7 +470,7 @@
 	test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport)
 
 	// Check android mks.
-	entries := android.AndroidMkEntriesForTest(t, config, "", test)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, test)[0]
 	expected := []string{"tests"}
 	actual := entries.EntryMap["LOCAL_MODULE_TAGS"]
 	if !reflect.DeepEqual(expected, actual) {
diff --git a/java/app_set_test.go b/java/app_set_test.go
index d31900d..ab55758 100644
--- a/java/app_set_test.go
+++ b/java/app_set_test.go
@@ -22,7 +22,7 @@
 )
 
 func TestAndroidAppSet(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		android_app_set {
 			name: "foo",
 			set: "prebuilts/apks/app.apks",
@@ -40,7 +40,7 @@
 	if s := params.Args["partition"]; s != "system" {
 		t.Errorf("wrong partition value: '%s', expected 'system'", s)
 	}
-	mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
+	mkEntries := android.AndroidMkEntriesForTest(t, ctx, module.Module())[0]
 	actualInstallFile := mkEntries.EntryMap["LOCAL_APK_SET_INSTALL_FILE"]
 	expectedInstallFile := []string{"foo.apk"}
 	if !reflect.DeepEqual(actualInstallFile, expectedInstallFile) {
diff --git a/java/builder.go b/java/builder.go
index 22a891a..33206ce 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -80,6 +80,8 @@
 		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
 	_ = pctx.VariableFunc("kytheCuEncoding",
 		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
+	_ = pctx.VariableFunc("kytheCuJavaSourceMax",
+		func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuJavaSourceMax() })
 	_ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
 	// Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about
 	// "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ...
@@ -93,6 +95,7 @@
 				`KYTHE_CORPUS=${kytheCorpus} ` +
 				`KYTHE_VNAMES=${kytheVnames} ` +
 				`KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
+				`KYTHE_JAVA_SOURCE_BATCH_SIZE=${kytheCuJavaSourceMax} ` +
 				`${config.SoongJavacWrapper} ${config.JavaCmd} ` +
 				`--add-opens=java.base/java.nio=ALL-UNNAMED ` +
 				`-jar ${config.JavaKytheExtractorJar} ` +
diff --git a/java/dex.go b/java/dex.go
index e52fdb5..b2a998f 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -260,6 +260,9 @@
 		r8Flags = append(r8Flags, "--debug")
 	}
 
+	// TODO(b/180878971): missing classes should be added to the relevant builds.
+	r8Flags = append(r8Flags, "-ignorewarnings")
+
 	return r8Flags, r8Deps
 }
 
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 29c73c1..a2961c2 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -35,6 +35,7 @@
 	isPresignedPrebuilt bool
 
 	manifestFile        android.Path
+	statusFile          android.WritablePath
 	enforceUsesLibs     bool
 	classLoaderContexts dexpreopt.ClassLoaderContextMap
 
@@ -226,9 +227,10 @@
 		ProfileIsTextListing: profileIsTextListing,
 		ProfileBootListing:   profileBootListing,
 
-		EnforceUsesLibraries: d.enforceUsesLibs,
-		ProvidesUsesLibrary:  providesUsesLib,
-		ClassLoaderContexts:  d.classLoaderContexts,
+		EnforceUsesLibrariesStatusFile: dexpreopt.UsesLibrariesStatusFile(ctx),
+		EnforceUsesLibraries:           d.enforceUsesLibs,
+		ProvidesUsesLibrary:            providesUsesLib,
+		ClassLoaderContexts:            d.classLoaderContexts,
 
 		Archs:                   archs,
 		DexPreoptImages:         images,
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index f8e41c4..da2c48f 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -15,8 +15,6 @@
 package java
 
 import (
-	"strings"
-
 	"github.com/google/blueprint"
 
 	"android/soong/android"
@@ -29,8 +27,8 @@
 
 type hiddenAPI struct {
 	// The name of the module as it would be used in the boot jars configuration, e.g. without any
-	// prebuilt_ prefix (if it is a prebuilt), without any "-hiddenapi" suffix if it just provides
-	// annotations and without any ".impl" suffix if it is a java_sdk_library implementation library.
+	// prebuilt_ prefix (if it is a prebuilt) and without any ".impl" suffix if it is a
+	// java_sdk_library implementation library.
 	configurationName string
 
 	// True if the module containing this structure contributes to the hiddenapi information or has
@@ -49,11 +47,6 @@
 	// annotation information.
 	primary bool
 
-	// True if the module only contains additional annotations and so does not require hiddenapi
-	// information to be encoded in its dex file and should not be used to generate the
-	// hiddenAPISingletonPathsStruct.stubFlags file.
-	annotationsOnly bool
-
 	// The path to the dex jar that is in the boot class path. If this is nil then the associated
 	// module is not a boot jar, but could be one of the <x>-hiddenapi modules that provide additional
 	// annotations for the <x> boot dex jar but which do not actually provide a boot dex jar
@@ -119,48 +112,40 @@
 var _ hiddenAPIIntf = (*hiddenAPI)(nil)
 
 // Initialize the hiddenapi structure
-func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, name string) {
+func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, configurationName string) {
 	// If hiddenapi processing is disabled treat this as inactive.
 	if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
 		return
 	}
 
-	// Modules whose names are of the format <x>-hiddenapi provide hiddenapi information for the boot
-	// jar module <x>. Otherwise, the module provides information for itself. Either way extract the
-	// configurationName of the boot jar module.
-	configurationName := strings.TrimSuffix(name, "-hiddenapi")
 	h.configurationName = configurationName
 
 	// 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
 	// failures in the CtsHiddenApiBlocklist... tests.
-	h.active = inList(configurationName, ctx.Config().BootJars())
+	module := ctx.Module()
+	h.active = isModuleInBootClassPath(ctx, module)
 	if !h.active {
 		// The rest of the properties will be ignored if active is false.
 		return
 	}
 
-	// If this module has a suffix of -hiddenapi then it only provides additional annotation
-	// information for a module on the boot jars list.
-	h.annotationsOnly = strings.HasSuffix(name, "-hiddenapi")
-
 	// Determine whether this module is the primary module or not.
 	primary := true
 
 	// A prebuilt module is only primary if it is preferred and conversely a source module is only
 	// primary if it has not been replaced by a prebuilt module.
-	module := ctx.Module()
 	if pi, ok := module.(android.PrebuiltInterface); ok {
 		if p := pi.Prebuilt(); p != nil {
 			primary = p.UsePrebuilt()
 		}
 	} else {
-		// The only module that will pass a different name to its module name to this method is the
-		// implementation library of a java_sdk_library. It has a configuration name of <x> the same
-		// as its parent java_sdk_library but a module name of <x>.impl. It is not the primary module,
-		// the java_sdk_library with the name of <x> is.
-		primary = name == ctx.ModuleName()
+		// The only module that will pass a different configurationName to its module name to this
+		// method is the implementation library of a java_sdk_library. It has a configuration name of
+		// <x> the same as its parent java_sdk_library but a module name of <x>.impl. It is not the
+		// primary module, the java_sdk_library with the name of <x> is.
+		primary = configurationName == ctx.ModuleName()
 
 		// A source module that has been replaced by a prebuilt can never be the primary module.
 		primary = primary && !module.IsReplacedByPrebuilt()
@@ -168,6 +153,15 @@
 	h.primary = primary
 }
 
+func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool {
+	// Get the configured non-updatable and updatable boot jars.
+	nonUpdatableBootJars := ctx.Config().NonUpdatableBootJars()
+	updatableBootJars := ctx.Config().UpdatableBootJars()
+	active := isModuleInConfiguredList(ctx, module, nonUpdatableBootJars) ||
+		isModuleInConfiguredList(ctx, module, updatableBootJars)
+	return active
+}
+
 // hiddenAPIExtractAndEncode is called by any module that could contribute to the hiddenapi
 // processing.
 //
@@ -191,15 +185,13 @@
 
 	h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar)
 
-	if !h.annotationsOnly {
-		hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
+	hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
 
-		// Create a copy of the dex jar which has been encoded with hiddenapi flags.
-		hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
+	// Create a copy of the dex jar which has been encoded with hiddenapi flags.
+	hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
 
-		// Use the encoded dex jar from here onwards.
-		dexJar = hiddenAPIJar
-	}
+	// Use the encoded dex jar from here onwards.
+	dexJar = hiddenAPIJar
 
 	return dexJar
 }
@@ -262,6 +254,7 @@
 	rule.Command().
 		BuiltTool("merge_csv").
 		Flag("--zip_input").
+		Flag("--key_field signature").
 		FlagWithOutput("--output=", indexCSV).
 		Inputs(classesJars)
 	rule.Build("merged-hiddenapi-index", "Merged Hidden API index")
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 6341a34..82e8b3f 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -217,10 +217,6 @@
 
 	var bootDexJars android.Paths
 
-	// Get the configured non-updatable and updatable boot jars.
-	nonUpdatableBootJars := ctx.Config().NonUpdatableBootJars()
-	updatableBootJars := ctx.Config().UpdatableBootJars()
-
 	ctx.VisitAllModules(func(module android.Module) {
 		// Collect dex jar paths for the modules listed above.
 		if j, ok := module.(UsesLibraryDependency); ok {
@@ -235,11 +231,6 @@
 		// Collect dex jar paths for modules that had hiddenapi encode called on them.
 		if h, ok := module.(hiddenAPIIntf); ok {
 			if jar := h.bootDexJar(); jar != nil {
-				if !isModuleInConfiguredList(ctx, module, nonUpdatableBootJars) &&
-					!isModuleInConfiguredList(ctx, module, updatableBootJars) {
-					return
-				}
-
 				bootDexJars = append(bootDexJars, jar)
 			}
 		}
@@ -291,8 +282,8 @@
 // there too.
 //
 // TODO(b/179354495): Avoid having to perform this type of check or if necessary dedup it.
-func isModuleInConfiguredList(ctx android.SingletonContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool {
-	name := ctx.ModuleName(module)
+func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool {
+	name := ctx.OtherModuleName(module)
 
 	// Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed.
 	name = android.RemoveOptionalPrebuiltPrefix(name)
@@ -305,11 +296,11 @@
 
 	// It is an error if the module is not an ApexModule.
 	if _, ok := module.(android.ApexModule); !ok {
-		ctx.Errorf("module %q configured in boot jars does not support being added to an apex", module)
+		ctx.ModuleErrorf("is configured in boot jars but does not support being added to an apex")
 		return false
 	}
 
-	apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+	apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
 
 	// Now match the apex part of the boot image configuration.
 	requiredApex := configuredBootJars.Apex(index)
@@ -433,6 +424,7 @@
 
 	rule.Command().
 		BuiltTool("merge_csv").
+		Flag("--key_field signature").
 		FlagWithOutput("--output=", outputPath).
 		Inputs(metadataCSV)
 
@@ -544,6 +536,7 @@
 	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)
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 4670d03..c0f0e38 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -89,12 +89,6 @@
 		}
 
 		java_library {
-			name: "foo-hiddenapi",
-			srcs: ["a.java"],
-			compile_dex: true,
-		}
-
-		java_library {
 			name: "foo-hiddenapi-annotations",
 			srcs: ["a.java"],
 			compile_dex: true,
@@ -118,7 +112,6 @@
 	indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index")
 	CheckHiddenAPIRuleInputs(t, `
 .intermediates/bar/android_common/hiddenapi/index.csv
-.intermediates/foo-hiddenapi/android_common/hiddenapi/index.csv
 .intermediates/foo/android_common/hiddenapi/index.csv
 `,
 		indexRule)
diff --git a/java/java.go b/java/java.go
index dbfad02..78cd362 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1038,7 +1038,7 @@
 	case javaPlatform:
 		return "private API"
 	default:
-		panic(fmt.Errorf("unrecognized linktype: %v", lt))
+		panic(fmt.Errorf("unrecognized linktype: %d", lt))
 	}
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 0ef4db6..11f6a7c 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2509,7 +2509,7 @@
 }
 
 func TestDataNativeBinaries(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		java_test_host {
 			name: "foo",
 			srcs: ["a.java"],
@@ -2525,7 +2525,7 @@
 	buildOS := android.BuildOs.String()
 
 	test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
-	entries := android.AndroidMkEntriesForTest(t, config, "", test)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, test)[0]
 	expected := []string{buildDir + "/.intermediates/bin/" + buildOS + "_x86_64_PY3/bin:bin"}
 	actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
 	if !reflect.DeepEqual(expected, actual) {
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 9bc821d..2c47b0a 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -131,7 +131,7 @@
 		OutputFile: android.OptionalPathForPath(p.configFile),
 		Include:    "$(BUILD_PREBUILT)",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.ToMakePath().String())
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.configFile.Base())
 			},
diff --git a/java/rro_test.go b/java/rro_test.go
index 0a2f848..edbf170 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -96,7 +96,7 @@
 	if expected != signingFlag {
 		t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
 	}
-	androidMkEntries := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0]
+	androidMkEntries := android.AndroidMkEntriesForTest(t, ctx, m.Module())[0]
 	path := androidMkEntries.EntryMap["LOCAL_CERTIFICATE"]
 	expectedPath := []string{"build/make/target/product/security/platform.x509.pem"}
 	if !reflect.DeepEqual(path, expectedPath) {
@@ -112,7 +112,7 @@
 
 	// A themed module has a different device location
 	m = ctx.ModuleForTests("foo_themed", "android_common")
-	androidMkEntries = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0]
+	androidMkEntries = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0]
 	path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
 	expectedPath = []string{"/tmp/target/product/test_device/product/overlay/faza"}
 	if !reflect.DeepEqual(path, expectedPath) {
@@ -127,7 +127,7 @@
 }
 
 func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
-	ctx, config := testJava(t, `
+	ctx, _ := testJava(t, `
 		java_defaults {
 			name: "rro_defaults",
 			theme: "default_theme",
@@ -159,7 +159,7 @@
 	}
 
 	// Check device location.
-	path := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
+	path := android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
 	expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"}
 	if !reflect.DeepEqual(path, expectedPath) {
 		t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath)
@@ -178,7 +178,7 @@
 	}
 
 	// Check device location.
-	path = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
+	path = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
 	expectedPath = []string{"/tmp/target/product/test_device/system/overlay"}
 	if !reflect.DeepEqual(path, expectedPath) {
 		t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
@@ -345,7 +345,7 @@
 			modules := []string{"foo", "bar"}
 			for _, moduleName := range modules {
 				module := ctx.ModuleForTests(moduleName, "android_common")
-				mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
+				mkEntries := android.AndroidMkEntriesForTest(t, ctx, module.Module())[0]
 				actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"]
 				if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) {
 					t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q",
diff --git a/java/sdk_library.go b/java/sdk_library.go
index aa96e0d..90823a0 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2238,7 +2238,7 @@
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(module.outputFilePath),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_TAGS", "optional")
 				entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.ToMakePath().String())
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index d538ce4..ff548e5 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -98,7 +98,7 @@
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(l.outputFilePath),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_PATH", l.installDirPath.ToMakePath().String())
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", l.outputFilePath.Base())
 				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !installable)
diff --git a/linkerconfig/linkerconfig_test.go b/linkerconfig/linkerconfig_test.go
index 01f4657..8eed4b5 100644
--- a/linkerconfig/linkerconfig_test.go
+++ b/linkerconfig/linkerconfig_test.go
@@ -47,7 +47,7 @@
 	os.Exit(run())
 }
 
-func testContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
+func testContext(t *testing.T, bp string) *android.TestContext {
 	t.Helper()
 
 	fs := map[string][]byte{
@@ -65,11 +65,11 @@
 	_, errs = ctx.PrepareBuildActions(config)
 	android.FailIfErrored(t, errs)
 
-	return ctx, config
+	return ctx
 }
 
 func TestBaseLinkerConfig(t *testing.T) {
-	ctx, config := testContext(t, `
+	ctx := testContext(t, `
 	linker_config {
 		name: "linker-config-base",
 		src: "linker.config.json",
@@ -88,7 +88,7 @@
 		t.Errorf("expected linker.config.pb, got %q", p.outputFilePath.Base())
 	}
 
-	entries := android.AndroidMkEntriesForTest(t, config, "", p)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, p)[0]
 	for k, expectedValue := range expected {
 		if value, ok := entries.EntryMap[k]; ok {
 			if !reflect.DeepEqual(value, expectedValue) {
@@ -105,7 +105,7 @@
 }
 
 func TestUninstallableLinkerConfig(t *testing.T) {
-	ctx, config := testContext(t, `
+	ctx := testContext(t, `
 	linker_config {
 		name: "linker-config-base",
 		src: "linker.config.json",
@@ -116,7 +116,7 @@
 	expected := []string{"true"}
 
 	p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
-	entries := android.AndroidMkEntriesForTest(t, config, "", p)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, p)[0]
 	if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok {
 		if !reflect.DeepEqual(value, expected) {
 			t.Errorf("LOCAL_UNINSTALLABLE_MODULE is expected to be true but %s", value)
diff --git a/python/androidmk.go b/python/androidmk.go
index 60637d3..13b4172 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -48,27 +48,29 @@
 func (p *binaryDecorator) AndroidMk(base *Module, entries *android.AndroidMkEntries) {
 	entries.Class = "EXECUTABLES"
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
-		entries.AddCompatibilityTestSuites(p.binaryProperties.Test_suites...)
-	})
+	entries.ExtraEntries = append(entries.ExtraEntries,
+		func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+			entries.AddCompatibilityTestSuites(p.binaryProperties.Test_suites...)
+		})
 	base.subAndroidMk(entries, p.pythonInstaller)
 }
 
 func (p *testDecorator) AndroidMk(base *Module, entries *android.AndroidMkEntries) {
 	entries.Class = "NATIVE_TESTS"
 
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
-		entries.AddCompatibilityTestSuites(p.binaryDecorator.binaryProperties.Test_suites...)
-		if p.testConfig != nil {
-			entries.SetString("LOCAL_FULL_TEST_CONFIG", p.testConfig.String())
-		}
+	entries.ExtraEntries = append(entries.ExtraEntries,
+		func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+			entries.AddCompatibilityTestSuites(p.binaryDecorator.binaryProperties.Test_suites...)
+			if p.testConfig != nil {
+				entries.SetString("LOCAL_FULL_TEST_CONFIG", p.testConfig.String())
+			}
 
-		entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true))
+			entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true))
 
-		entries.AddStrings("LOCAL_TEST_DATA", android.AndroidMkDataPaths(p.data)...)
+			entries.AddStrings("LOCAL_TEST_DATA", android.AndroidMkDataPaths(p.data)...)
 
-		entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(p.testProperties.Test_options.Unit_test))
-	})
+			entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(p.testProperties.Test_options.Unit_test))
+		})
 	base.subAndroidMk(entries, p.binaryDecorator.pythonInstaller)
 }
 
@@ -80,14 +82,15 @@
 	}
 
 	entries.Required = append(entries.Required, "libc++")
-	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
-		path, file := filepath.Split(installer.path.ToMakePath().String())
-		stem := strings.TrimSuffix(file, filepath.Ext(file))
+	entries.ExtraEntries = append(entries.ExtraEntries,
+		func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+			path, file := filepath.Split(installer.path.ToMakePath().String())
+			stem := strings.TrimSuffix(file, filepath.Ext(file))
 
-		entries.SetString("LOCAL_MODULE_SUFFIX", filepath.Ext(file))
-		entries.SetString("LOCAL_MODULE_PATH", path)
-		entries.SetString("LOCAL_MODULE_STEM", stem)
-		entries.AddStrings("LOCAL_SHARED_LIBRARIES", installer.androidMkSharedLibs...)
-		entries.SetBool("LOCAL_CHECK_ELF_FILES", false)
-	})
+			entries.SetString("LOCAL_MODULE_SUFFIX", filepath.Ext(file))
+			entries.SetString("LOCAL_MODULE_PATH", path)
+			entries.SetString("LOCAL_MODULE_STEM", stem)
+			entries.AddStrings("LOCAL_SHARED_LIBRARIES", installer.androidMkSharedLibs...)
+			entries.SetBool("LOCAL_CHECK_ELF_FILES", false)
+		})
 }
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 1a286f7..0f9a17d 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -53,7 +53,7 @@
 		OutputFile: mod.outputFile,
 		Include:    "$(BUILD_SYSTEM)/soong_rust_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				entries.AddStrings("LOCAL_RLIB_LIBRARIES", mod.Properties.AndroidMkRlibs...)
 				entries.AddStrings("LOCAL_DYLIB_LIBRARIES", mod.Properties.AndroidMkDylibs...)
 				entries.AddStrings("LOCAL_PROC_MACRO_LIBRARIES", mod.Properties.AndroidMkProcMacroLibs...)
@@ -89,14 +89,15 @@
 	ctx.SubAndroidMk(ret, test.binaryDecorator)
 
 	ret.Class = "NATIVE_TESTS"
-	ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) {
-		entries.AddCompatibilityTestSuites(test.Properties.Test_suites...)
-		if test.testConfig != nil {
-			entries.SetString("LOCAL_FULL_TEST_CONFIG", test.testConfig.String())
-		}
-		entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(test.Properties.Auto_gen_config, true))
-		entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(test.Properties.Test_options.Unit_test))
-	})
+	ret.ExtraEntries = append(ret.ExtraEntries,
+		func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+			entries.AddCompatibilityTestSuites(test.Properties.Test_suites...)
+			if test.testConfig != nil {
+				entries.SetString("LOCAL_FULL_TEST_CONFIG", test.testConfig.String())
+			}
+			entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(test.Properties.Auto_gen_config, true))
+			entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(test.Properties.Test_options.Unit_test))
+		})
 
 	cc.AndroidMkWriteTestData(test.data, ret)
 }
@@ -134,13 +135,14 @@
 	ret.Class = "ETC"
 	ret.OutputFile = android.OptionalPathForPath(outFile)
 	ret.SubName += sourceProvider.subName
-	ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) {
-		_, file := filepath.Split(outFile.String())
-		stem, suffix, _ := android.SplitFileExt(file)
-		entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
-		entries.SetString("LOCAL_MODULE_STEM", stem)
-		entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
-	})
+	ret.ExtraEntries = append(ret.ExtraEntries,
+		func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+			_, file := filepath.Split(outFile.String())
+			stem, suffix, _ := android.SplitFileExt(file)
+			entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
+			entries.SetString("LOCAL_MODULE_STEM", stem)
+			entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+		})
 }
 
 func (bindgen *bindgenDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
@@ -165,12 +167,13 @@
 		unstrippedOutputFile = ret.OutputFile
 		ret.OutputFile = compiler.strippedOutputFile
 	}
-	ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) {
-		entries.SetOptionalPath("LOCAL_SOONG_UNSTRIPPED_BINARY", unstrippedOutputFile)
-		path, file := filepath.Split(compiler.path.ToMakePath().String())
-		stem, suffix, _ := android.SplitFileExt(file)
-		entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
-		entries.SetString("LOCAL_MODULE_PATH", path)
-		entries.SetString("LOCAL_MODULE_STEM", stem)
-	})
+	ret.ExtraEntries = append(ret.ExtraEntries,
+		func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+			entries.SetOptionalPath("LOCAL_SOONG_UNSTRIPPED_BINARY", unstrippedOutputFile)
+			path, file := filepath.Split(compiler.path.ToMakePath().String())
+			stem, suffix, _ := android.SplitFileExt(file)
+			entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
+			entries.SetString("LOCAL_MODULE_PATH", path)
+			entries.SetString("LOCAL_MODULE_STEM", stem)
+		})
 }
diff --git a/rust/builder.go b/rust/builder.go
index 547d705..6326124 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -230,6 +230,8 @@
 		envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
 	}
 
+	envVars = append(envVars, "ANDROID_RUST_VERSION="+config.RustDefaultVersion)
+
 	if flags.Clippy {
 		clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
 		ctx.Build(pctx, android.BuildParams{
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index b93c883..0813f1a 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -29,6 +29,7 @@
   runtime-module-sdk
   stats-log-api-gen-exports
   statsd-module-sdk
+  statsd-module-sdk-for-art
   tzdata-module-test-exports
 )
 
diff --git a/scripts/hiddenapi/merge_csv.py b/scripts/hiddenapi/merge_csv.py
index 5ad61b2..b047aab 100755
--- a/scripts/hiddenapi/merge_csv.py
+++ b/scripts/hiddenapi/merge_csv.py
@@ -20,6 +20,9 @@
 import argparse
 import csv
 import io
+import heapq
+import itertools
+import operator
 
 from zipfile import ZipFile
 
@@ -28,6 +31,10 @@
                                           'if missing determines the header from input files.')
 args_parser.add_argument('--zip_input', help='Treat files as ZIP archives containing CSV files to merge.',
                          action="store_true")
+args_parser.add_argument('--key_field', help='The name of the field by which the rows should be sorted. '
+                                             'Must be in the field names. '
+                                             'Will be the first field in the output. '
+                                             'All input files must be sorted by that field.')
 args_parser.add_argument('--output', help='Output file for merged CSV.',
                          default='-', type=argparse.FileType('w'))
 args_parser.add_argument('files', nargs=argparse.REMAINDER)
@@ -57,10 +64,29 @@
         headers = headers.union(reader.fieldnames)
     fieldnames = sorted(headers)
 
-# Concatenate all files to output:
+# By default chain the csv readers together so that the resulting output is
+# the concatenation of the rows from each of them:
+all_rows = itertools.chain.from_iterable(csv_readers)
+
+if len(csv_readers) > 0:
+    keyField = args.key_field
+    if keyField:
+        assert keyField in fieldnames, (
+            "--key_field {} not found, must be one of {}\n").format(
+            keyField, ",".join(fieldnames))
+        # Make the key field the first field in the output
+        keyFieldIndex = fieldnames.index(args.key_field)
+        fieldnames.insert(0, fieldnames.pop(keyFieldIndex))
+        # Create an iterable that performs a lazy merge sort on the csv readers
+        # sorting the rows by the key field.
+        all_rows = heapq.merge(*csv_readers, key=operator.itemgetter(keyField))
+
+# Write all rows from the input files to the output:
 writer = csv.DictWriter(args.output, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL,
                         dialect='unix', fieldnames=fieldnames)
 writer.writeheader()
-for reader in csv_readers:
-    for row in reader:
-        writer.writerow(row)
+
+# Read all the rows from the input and write them to the output in the correct
+# order:
+for row in all_rows:
+  writer.writerow(row)
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 9122da1..0eb1b76 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -48,6 +48,13 @@
                       dest='enforce_uses_libraries',
                       action='store_true',
                       help='check the uses-library entries known to the build system against the manifest')
+  parser.add_argument('--enforce-uses-libraries-relax',
+                      dest='enforce_uses_libraries_relax',
+                      action='store_true',
+                      help='do not fail immediately, just save the error message to file')
+  parser.add_argument('--enforce-uses-libraries-status',
+                      dest='enforce_uses_libraries_status',
+                      help='output file to store check status (error message)')
   parser.add_argument('--extract-target-sdk-version',
                       dest='extract_target_sdk_version',
                       action='store_true',
@@ -57,7 +64,7 @@
   return parser.parse_args()
 
 
-def enforce_uses_libraries(doc, uses_libraries, optional_uses_libraries):
+def enforce_uses_libraries(doc, uses_libraries, optional_uses_libraries, relax):
   """Verify that the <uses-library> tags in the manifest match those provided by the build system.
 
   Args:
@@ -80,10 +87,10 @@
       raise ManifestMismatchError('no <application> tag found')
     return
 
-  verify_uses_library(application, uses_libraries, optional_uses_libraries)
+  return verify_uses_library(application, uses_libraries, optional_uses_libraries, relax)
 
 
-def verify_uses_library(application, uses_libraries, optional_uses_libraries):
+def verify_uses_library(application, uses_libraries, optional_uses_libraries, relax):
   """Verify that the uses-library values known to the build system match the manifest.
 
   Args:
@@ -112,8 +119,12 @@
                (', '.join(optional_uses_libraries), ', '.join(manifest_optional_uses_libraries)))
 
   if err:
-    raise ManifestMismatchError('\n'.join(err))
+    errmsg = '\n'.join(err)
+    if not relax:
+      raise ManifestMismatchError(errmsg)
+    return errmsg
 
+  return None
 
 def parse_uses_library(application):
   """Extract uses-library tags from the manifest.
@@ -195,9 +206,19 @@
     doc = minidom.parse(args.input)
 
     if args.enforce_uses_libraries:
-      enforce_uses_libraries(doc,
-                             args.uses_libraries,
-                             args.optional_uses_libraries)
+      # Check if the <uses-library> lists in the build system agree with those
+      # in the manifest. Raise an exception on mismatch, unless the script was
+      # passed a special parameter to suppress exceptions.
+      errmsg = enforce_uses_libraries(doc, args.uses_libraries,
+        args.optional_uses_libraries, args.enforce_uses_libraries_relax)
+
+      # Create a status file that is empty on success, or contains an error
+      # message on failure. When exceptions are suppressed, dexpreopt command
+      # command will check file size to determine if the check has failed.
+      if args.enforce_uses_libraries_status:
+        with open(args.enforce_uses_libraries_status, 'w') as f:
+          if not errmsg == None:
+            f.write("%s\n" % errmsg)
 
     if args.extract_target_sdk_version:
       print(extract_target_sdk_version(doc))
diff --git a/scripts/manifest_check_test.py b/scripts/manifest_check_test.py
index 7baad5d..56c2d9e 100755
--- a/scripts/manifest_check_test.py
+++ b/scripts/manifest_check_test.py
@@ -39,7 +39,9 @@
   def run_test(self, input_manifest, uses_libraries=None, optional_uses_libraries=None):
     doc = minidom.parseString(input_manifest)
     try:
-      manifest_check.enforce_uses_libraries(doc, uses_libraries, optional_uses_libraries)
+      relax = False
+      manifest_check.enforce_uses_libraries(doc, uses_libraries,
+        optional_uses_libraries, relax)
       return True
     except manifest_check.ManifestMismatchError:
       return False
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 40f0184..5b7a6da 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -89,7 +89,7 @@
         "${CROSS_COMPILE}objcopy" --rename-section .debug_frame=saved_debug_frame "${outfile}.debug" "${outfile}.mini_debuginfo"
         "${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo"
         "${CROSS_COMPILE}objcopy" --rename-section saved_debug_frame=.debug_frame "${outfile}.mini_debuginfo"
-        "${XZ}" "${outfile}.mini_debuginfo"
+        "${XZ}" --block-size=64k --threads=0 "${outfile}.mini_debuginfo"
 
         "${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
         rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index b1eebe9..997d2f6 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -22,14 +22,14 @@
 )
 
 var ccTestFs = map[string][]byte{
-	"Test.cpp":                      nil,
-	"include/Test.h":                nil,
-	"include-android/AndroidTest.h": nil,
-	"include-host/HostTest.h":       nil,
-	"arm64/include/Arm64Test.h":     nil,
-	"libfoo.so":                     nil,
-	"aidl/foo/bar/Test.aidl":        nil,
-	"some/where/stubslib.map.txt":   nil,
+	"Test.cpp":                        nil,
+	"myinclude/Test.h":                nil,
+	"myinclude-android/AndroidTest.h": nil,
+	"myinclude-host/HostTest.h":       nil,
+	"arm64/include/Arm64Test.h":       nil,
+	"libfoo.so":                       nil,
+	"aidl/foo/bar/Test.aidl":          nil,
+	"some/where/stubslib.map.txt":     nil,
 }
 
 func testSdkWithCc(t *testing.T, bp string) *testSdkResult {
@@ -102,16 +102,15 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_sdkmember@current",
-    sdk_member_name: "sdkmember",
+    name: "sdkmember",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     host_supported: true,
-    installable: false,
     stl: "none",
     compile_multilib: "64",
     target: {
@@ -127,13 +126,17 @@
         },
     },
 }
+`),
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "sdkmember",
-    prefer: false,
+    name: "mysdk_sdkmember@current",
+    sdk_member_name: "sdkmember",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     host_supported: true,
+    installable: false,
     stl: "none",
     compile_multilib: "64",
     target: {
@@ -348,12 +351,12 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_object {
-    name: "mysdk_crtobj@current",
-    sdk_member_name: "crtobj",
+    name: "crtobj",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     stl: "none",
@@ -370,10 +373,14 @@
         },
     },
 }
+`),
+		// Make sure that the generated sdk_snapshot uses the native_objects property.
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_object {
-    name: "crtobj",
-    prefer: false,
+    name: "mysdk_crtobj@current",
+    sdk_member_name: "crtobj",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     stl: "none",
@@ -416,7 +423,7 @@
 			srcs: [
 				"Test.cpp",
 			],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			stl: "none",
 		}
 
@@ -425,14 +432,14 @@
 			srcs: [
 				"Test.cpp",
 			],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			stl: "none",
 		}
 	`)
 
 	result.CheckSnapshot("mysdk", "",
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib1/android_arm64_armv8-a_shared/mynativelib1.so -> arm64/lib/mynativelib1.so
 .intermediates/mynativelib1/android_arm_armv7-a-neon_shared/mynativelib1.so -> arm/lib/mynativelib1.so
 .intermediates/mynativelib2/android_arm64_armv8-a_shared/mynativelib2.so -> arm64/lib/mynativelib2.so
@@ -441,6 +448,76 @@
 	)
 }
 
+func TestSnapshotWithCcExportGeneratedHeaders(t *testing.T) {
+	result := testSdkWithCc(t, `
+		sdk {
+			name: "mysdk",
+			native_shared_libs: ["mynativelib"],
+		}
+
+		cc_library_shared {
+			name: "mynativelib",
+			srcs: [
+				"Test.cpp",
+			],
+			generated_headers: [
+				"generated_foo",
+			],
+			export_generated_headers: [
+				"generated_foo",
+			],
+			export_include_dirs: ["myinclude"],
+			stl: "none",
+		}
+
+		genrule {
+			name: "generated_foo",
+			cmd: "generate-foo",
+			out: [
+				"generated_foo/protos/foo/bar.h",
+			],
+			export_include_dirs: [
+				".",
+				"protos",
+			],
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "",
+		checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+    name: "mynativelib",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    stl: "none",
+    compile_multilib: "both",
+    export_include_dirs: [
+        "include/myinclude",
+        "include_gen/generated_foo/gen",
+        "include_gen/generated_foo/gen/protos",
+    ],
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/mynativelib.so"],
+        },
+        arm: {
+            srcs: ["arm/lib/mynativelib.so"],
+        },
+    },
+}
+`),
+		checkAllCopyRules(`
+myinclude/Test.h -> include/myinclude/Test.h
+.intermediates/generated_foo/gen/generated_foo/protos/foo/bar.h -> include_gen/generated_foo/gen/generated_foo/protos/foo/bar.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
+`),
+	)
+}
+
 // Verify that when the shared library has some common and some arch specific
 // properties that the generated snapshot is optimized properly. Substruct
 // handling is tested with the sanitize clauses (but note there's a lot of
@@ -458,7 +535,7 @@
 				"Test.cpp",
 				"aidl/foo/bar/Test.aidl",
 			],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			sanitize: {
 				fuzzer: false,
 				integer_overflow: true,
@@ -477,49 +554,17 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_mynativelib@current",
-    sdk_member_name: "mynativelib",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    stl: "none",
-    compile_multilib: "both",
-    export_include_dirs: ["include/include"],
-    sanitize: {
-        fuzzer: false,
-        diag: {
-            undefined: false,
-        },
-    },
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/mynativelib.so"],
-            export_system_include_dirs: ["arm64/include/arm64/include"],
-            sanitize: {
-                integer_overflow: false,
-            },
-        },
-        arm: {
-            srcs: ["arm/lib/mynativelib.so"],
-            sanitize: {
-                integer_overflow: true,
-            },
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     sanitize: {
         fuzzer: false,
         diag: {
@@ -542,15 +587,9 @@
         },
     },
 }
-
-sdk_snapshot {
-    name: "mysdk@current",
-    visibility: ["//visibility:public"],
-    native_shared_libs: ["mysdk_mynativelib@current"],
-}
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
 arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h
 .intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
@@ -574,15 +613,14 @@
 	`)
 
 	result.CheckSnapshot("mymodule_exports", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_binary {
-    name: "mymodule_exports_mynativebinary@current",
-    sdk_member_name: "mynativebinary",
+    name: "mynativebinary",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
-    installable: false,
     compile_multilib: "both",
     arch: {
         arm64: {
@@ -593,12 +631,17 @@
         },
     },
 }
+`),
+		// Make sure that the generated sdk_snapshot uses the native_binaries property.
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_binary {
-    name: "mynativebinary",
-    prefer: false,
+    name: "mymodule_exports_mynativebinary@current",
+    sdk_member_name: "mynativebinary",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
+    installable: false,
     compile_multilib: "both",
     arch: {
         arm64: {
@@ -655,17 +698,16 @@
 	`)
 
 	result.CheckSnapshot("myexports", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_binary {
-    name: "myexports_mynativebinary@current",
-    sdk_member_name: "mynativebinary",
+    name: "mynativebinary",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     device_supported: false,
     host_supported: true,
-    installable: false,
     stl: "none",
     target: {
         host: {
@@ -691,14 +733,18 @@
         },
     },
 }
+`),
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_binary {
-    name: "mynativebinary",
-    prefer: false,
+    name: "myexports_mynativebinary@current",
+    sdk_member_name: "mynativebinary",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     device_supported: false,
     host_supported: true,
+    installable: false,
     stl: "none",
     target: {
         host: {
@@ -805,7 +851,50 @@
 	result := runTests(t, ctx, config)
 
 	result.CheckSnapshot("myexports", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_binary {
+    name: "mynativebinary",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    device_supported: false,
+    host_supported: true,
+    stl: "none",
+    compile_multilib: "64",
+    target: {
+        host: {
+            enabled: false,
+        },
+        linux_bionic_x86_64: {
+            enabled: true,
+            srcs: ["x86_64/bin/mynativebinary"],
+        },
+    },
+}
+
+cc_prebuilt_library_shared {
+    name: "mynativelib",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    device_supported: false,
+    host_supported: true,
+    stl: "none",
+    compile_multilib: "64",
+    target: {
+        host: {
+            enabled: false,
+        },
+        linux_bionic_x86_64: {
+            enabled: true,
+            srcs: ["x86_64/lib/mynativelib.so"],
+        },
+    },
+}
+`),
+		checkVersionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_binary {
@@ -829,26 +918,6 @@
     },
 }
 
-cc_prebuilt_binary {
-    name: "mynativebinary",
-    prefer: false,
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    device_supported: false,
-    host_supported: true,
-    stl: "none",
-    compile_multilib: "64",
-    target: {
-        host: {
-            enabled: false,
-        },
-        linux_bionic_x86_64: {
-            enabled: true,
-            srcs: ["x86_64/bin/mynativebinary"],
-        },
-    },
-}
-
 cc_prebuilt_library_shared {
     name: "myexports_mynativelib@current",
     sdk_member_name: "mynativelib",
@@ -870,26 +939,6 @@
     },
 }
 
-cc_prebuilt_library_shared {
-    name: "mynativelib",
-    prefer: false,
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    device_supported: false,
-    host_supported: true,
-    stl: "none",
-    compile_multilib: "64",
-    target: {
-        host: {
-            enabled: false,
-        },
-        linux_bionic_x86_64: {
-            enabled: true,
-            srcs: ["x86_64/lib/mynativelib.so"],
-        },
-    },
-}
-
 module_exports_snapshot {
     name: "myexports@current",
     visibility: ["//visibility:public"],
@@ -940,17 +989,16 @@
 	`)
 
 	result.CheckSnapshot("mymodule_exports", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_binary {
-    name: "mymodule_exports_linker@current",
-    sdk_member_name: "linker",
+    name: "linker",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     device_supported: false,
     host_supported: true,
-    installable: false,
     stl: "none",
     compile_multilib: "both",
     static_executable: true,
@@ -969,14 +1017,18 @@
         },
     },
 }
+`),
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_binary {
-    name: "linker",
-    prefer: false,
+    name: "mymodule_exports_linker@current",
+    sdk_member_name: "linker",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     device_supported: false,
     host_supported: true,
+    installable: false,
     stl: "none",
     compile_multilib: "both",
     static_executable: true,
@@ -1036,7 +1088,7 @@
 				"aidl/foo/bar/Test.aidl",
 			],
 			apex_available: ["apex1", "apex2"],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			aidl: {
 				export_aidl_headers: true,
 			},
@@ -1045,34 +1097,10 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_mynativelib@current",
-    sdk_member_name: "mynativelib",
-    visibility: ["//visibility:public"],
-    apex_available: [
-        "apex1",
-        "apex2",
-    ],
-    installable: false,
-    stl: "none",
-    compile_multilib: "both",
-    export_include_dirs: ["include/include"],
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/mynativelib.so"],
-            export_include_dirs: ["arm64/include_gen/mynativelib"],
-        },
-        arm: {
-            srcs: ["arm/lib/mynativelib.so"],
-            export_include_dirs: ["arm/include_gen/mynativelib"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
     visibility: ["//visibility:public"],
@@ -1082,35 +1110,29 @@
     ],
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     arch: {
         arm64: {
             srcs: ["arm64/lib/mynativelib.so"],
-            export_include_dirs: ["arm64/include_gen/mynativelib"],
+            export_include_dirs: ["arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl"],
         },
         arm: {
             srcs: ["arm/lib/mynativelib.so"],
-            export_include_dirs: ["arm/include_gen/mynativelib"],
+            export_include_dirs: ["arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl"],
         },
     },
 }
-
-sdk_snapshot {
-    name: "mysdk@current",
-    visibility: ["//visibility:public"],
-    native_shared_libs: ["mysdk_mynativelib@current"],
-}
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1176,32 +1198,10 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_mynativelib@current",
-    sdk_member_name: "mynativelib",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    stl: "none",
-    compile_multilib: "both",
-    shared_libs: [
-        "mysdk_myothernativelib@current",
-        "libc",
-    ],
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/mynativelib.so"],
-        },
-        arm: {
-            srcs: ["arm/lib/mynativelib.so"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
     visibility: ["//visibility:public"],
@@ -1223,25 +1223,6 @@
 }
 
 cc_prebuilt_library_shared {
-    name: "mysdk_myothernativelib@current",
-    sdk_member_name: "myothernativelib",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    stl: "none",
-    compile_multilib: "both",
-    system_shared_libs: ["libm"],
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/myothernativelib.so"],
-        },
-        arm: {
-            srcs: ["arm/lib/myothernativelib.so"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "myothernativelib",
     prefer: false,
     visibility: ["//visibility:public"],
@@ -1260,24 +1241,6 @@
 }
 
 cc_prebuilt_library_shared {
-    name: "mysdk_mysystemnativelib@current",
-    sdk_member_name: "mysystemnativelib",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    stl: "none",
-    compile_multilib: "both",
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/mysystemnativelib.so"],
-        },
-        arm: {
-            srcs: ["arm/lib/mysystemnativelib.so"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "mysystemnativelib",
     prefer: false,
     visibility: ["//visibility:public"],
@@ -1293,16 +1256,6 @@
         },
     },
 }
-
-sdk_snapshot {
-    name: "mysdk@current",
-    visibility: ["//visibility:public"],
-    native_shared_libs: [
-        "mysdk_mynativelib@current",
-        "mysdk_myothernativelib@current",
-        "mysdk_mysystemnativelib@current",
-    ],
-}
 `),
 		checkAllCopyRules(`
 .intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
@@ -1332,7 +1285,7 @@
 				"Test.cpp",
 				"aidl/foo/bar/Test.aidl",
 			],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			aidl: {
 				export_aidl_headers: true,
 			},
@@ -1342,7 +1295,38 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+    name: "mynativelib",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    device_supported: false,
+    host_supported: true,
+    sdk_version: "minimum",
+    stl: "none",
+    compile_multilib: "both",
+    export_include_dirs: ["include/myinclude"],
+    target: {
+        host: {
+            enabled: false,
+        },
+        linux_glibc_x86_64: {
+            enabled: true,
+            srcs: ["x86_64/lib/mynativelib.so"],
+            export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl"],
+        },
+        linux_glibc_x86: {
+            enabled: true,
+            srcs: ["x86/lib/mynativelib.so"],
+            export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl"],
+        },
+    },
+}
+`),
+		checkVersionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
@@ -1356,7 +1340,7 @@
     sdk_version: "minimum",
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     target: {
         host: {
             enabled: false,
@@ -1364,40 +1348,12 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.so"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
+            export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl"],
         },
         linux_glibc_x86: {
             enabled: true,
             srcs: ["x86/lib/mynativelib.so"],
-            export_include_dirs: ["x86/include_gen/mynativelib"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
-    name: "mynativelib",
-    prefer: false,
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    device_supported: false,
-    host_supported: true,
-    sdk_version: "minimum",
-    stl: "none",
-    compile_multilib: "both",
-    export_include_dirs: ["include/include"],
-    target: {
-        host: {
-            enabled: false,
-        },
-        linux_glibc_x86_64: {
-            enabled: true,
-            srcs: ["x86_64/lib/mynativelib.so"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
-        },
-        linux_glibc_x86: {
-            enabled: true,
-            srcs: ["x86/lib/mynativelib.so"],
-            export_include_dirs: ["x86/include_gen/mynativelib"],
+            export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl"],
         },
     },
 }
@@ -1422,15 +1378,15 @@
 }
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/linux_glibc_x86_64_shared/mynativelib.so -> x86_64/lib/mynativelib.so
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/linux_glibc_x86_shared/mynativelib.so -> x86/lib/mynativelib.so
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1466,17 +1422,16 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_mynativelib@current",
-    sdk_member_name: "mynativelib",
+    name: "mynativelib",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     device_supported: false,
     host_supported: true,
-    installable: false,
     stl: "none",
     target: {
         host: {
@@ -1502,14 +1457,18 @@
         },
     },
 }
+`),
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mynativelib",
-    prefer: false,
+    name: "mysdk_mynativelib@current",
+    sdk_member_name: "mynativelib",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     device_supported: false,
     host_supported: true,
+    installable: false,
     stl: "none",
     target: {
         host: {
@@ -1582,7 +1541,7 @@
 				"Test.cpp",
 				"aidl/foo/bar/Test.aidl",
 			],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			aidl: {
 				export_aidl_headers: true,
 			},
@@ -1591,66 +1550,39 @@
 	`)
 
 	result.CheckSnapshot("myexports", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_static {
-    name: "myexports_mynativelib@current",
-    sdk_member_name: "mynativelib",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    stl: "none",
-    compile_multilib: "both",
-    export_include_dirs: ["include/include"],
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/mynativelib.a"],
-            export_include_dirs: ["arm64/include_gen/mynativelib"],
-        },
-        arm: {
-            srcs: ["arm/lib/mynativelib.a"],
-            export_include_dirs: ["arm/include_gen/mynativelib"],
-        },
-    },
-}
-
-cc_prebuilt_library_static {
     name: "mynativelib",
     prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     arch: {
         arm64: {
             srcs: ["arm64/lib/mynativelib.a"],
-            export_include_dirs: ["arm64/include_gen/mynativelib"],
+            export_include_dirs: ["arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl"],
         },
         arm: {
             srcs: ["arm/lib/mynativelib.a"],
-            export_include_dirs: ["arm/include_gen/mynativelib"],
+            export_include_dirs: ["arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl"],
         },
     },
 }
-
-module_exports_snapshot {
-    name: "myexports@current",
-    visibility: ["//visibility:public"],
-    native_static_libs: ["myexports_mynativelib@current"],
-}
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/android_arm64_armv8-a_static/mynativelib.a -> arm64/lib/mynativelib.a
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1672,7 +1604,7 @@
 				"Test.cpp",
 				"aidl/foo/bar/Test.aidl",
 			],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			aidl: {
 				export_aidl_headers: true,
 			},
@@ -1681,7 +1613,37 @@
 	`)
 
 	result.CheckSnapshot("myexports", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_static {
+    name: "mynativelib",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    device_supported: false,
+    host_supported: true,
+    stl: "none",
+    compile_multilib: "both",
+    export_include_dirs: ["include/myinclude"],
+    target: {
+        host: {
+            enabled: false,
+        },
+        linux_glibc_x86_64: {
+            enabled: true,
+            srcs: ["x86_64/lib/mynativelib.a"],
+            export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl"],
+        },
+        linux_glibc_x86: {
+            enabled: true,
+            srcs: ["x86/lib/mynativelib.a"],
+            export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl"],
+        },
+    },
+}
+`),
+		checkVersionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_static {
@@ -1694,7 +1656,7 @@
     installable: false,
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     target: {
         host: {
             enabled: false,
@@ -1702,39 +1664,12 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.a"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
+            export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl"],
         },
         linux_glibc_x86: {
             enabled: true,
             srcs: ["x86/lib/mynativelib.a"],
-            export_include_dirs: ["x86/include_gen/mynativelib"],
-        },
-    },
-}
-
-cc_prebuilt_library_static {
-    name: "mynativelib",
-    prefer: false,
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    device_supported: false,
-    host_supported: true,
-    stl: "none",
-    compile_multilib: "both",
-    export_include_dirs: ["include/include"],
-    target: {
-        host: {
-            enabled: false,
-        },
-        linux_glibc_x86_64: {
-            enabled: true,
-            srcs: ["x86_64/lib/mynativelib.a"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
-        },
-        linux_glibc_x86: {
-            enabled: true,
-            srcs: ["x86/lib/mynativelib.a"],
-            export_include_dirs: ["x86/include_gen/mynativelib"],
+            export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl"],
         },
     },
 }
@@ -1759,15 +1694,15 @@
 }
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/linux_glibc_x86_64_static/mynativelib.a -> x86_64/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/linux_glibc_x86_static/mynativelib.a -> x86/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1784,7 +1719,7 @@
 			srcs: [
 				"Test.cpp",
 			],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			stl: "none",
 			recovery_available: true,
 			vendor_available: true,
@@ -1792,20 +1727,19 @@
 	`)
 
 	result.CheckSnapshot("myexports", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library {
-    name: "myexports_mynativelib@current",
-    sdk_member_name: "mynativelib",
+    name: "mynativelib",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
-    installable: false,
     recovery_available: true,
     vendor_available: true,
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     arch: {
         arm64: {
             static: {
@@ -1825,17 +1759,22 @@
         },
     },
 }
+`),
+		// Make sure that the generated sdk_snapshot uses the native_libs property.
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library {
-    name: "mynativelib",
-    prefer: false,
+    name: "myexports_mynativelib@current",
+    sdk_member_name: "mynativelib",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
+    installable: false,
     recovery_available: true,
     vendor_available: true,
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     arch: {
         arm64: {
             static: {
@@ -1863,7 +1802,7 @@
 }
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/android_arm64_armv8-a_static/mynativelib.a -> arm64/lib/mynativelib.a
 .intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
 .intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
@@ -1893,7 +1832,7 @@
 				"Test.cpp",
 				"aidl/foo/bar/Test.aidl",
 			],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			aidl: {
 				export_aidl_headers: true,
 			},
@@ -1902,7 +1841,34 @@
 	`)
 
 	result.CheckSnapshot("myexports", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_static {
+    name: "mynativelib",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    device_supported: false,
+    host_supported: true,
+    stl: "none",
+    compile_multilib: "64",
+    export_include_dirs: [
+        "include/myinclude",
+        "include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl",
+    ],
+    target: {
+        host: {
+            enabled: false,
+        },
+        linux_glibc_x86_64: {
+            enabled: true,
+            srcs: ["x86_64/lib/mynativelib.a"],
+        },
+    },
+}
+`),
+		checkVersionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_static {
@@ -1915,7 +1881,10 @@
     installable: false,
     stl: "none",
     compile_multilib: "64",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: [
+        "include/myinclude",
+        "include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl",
+    ],
     target: {
         host: {
             enabled: false,
@@ -1923,29 +1892,6 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.a"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
-        },
-    },
-}
-
-cc_prebuilt_library_static {
-    name: "mynativelib",
-    prefer: false,
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    device_supported: false,
-    host_supported: true,
-    stl: "none",
-    compile_multilib: "64",
-    export_include_dirs: ["include/include"],
-    target: {
-        host: {
-            enabled: false,
-        },
-        linux_glibc_x86_64: {
-            enabled: true,
-            srcs: ["x86_64/lib/mynativelib.a"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
         },
     },
 }
@@ -1965,13 +1911,14 @@
             enabled: true,
         },
     },
-}`),
+}
+`),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/linux_glibc_x86_64_static/mynativelib.a -> x86_64/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1985,43 +1932,27 @@
 
 		cc_library_headers {
 			name: "mynativeheaders",
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			stl: "none",
 		}
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_headers {
-    name: "mysdk_mynativeheaders@current",
-    sdk_member_name: "mynativeheaders",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    stl: "none",
-    compile_multilib: "both",
-    export_include_dirs: ["include/include"],
-}
-
-cc_prebuilt_library_headers {
     name: "mynativeheaders",
     prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
-}
-
-sdk_snapshot {
-    name: "mysdk@current",
-    visibility: ["//visibility:public"],
-    native_header_libs: ["mysdk_mynativeheaders@current"],
+    export_include_dirs: ["include/myinclude"],
 }
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 `),
 	)
 }
@@ -2039,25 +1970,25 @@
 			name: "mynativeheaders",
 			device_supported: false,
 			host_supported: true,
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			stl: "none",
 		}
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_headers {
-    name: "mysdk_mynativeheaders@current",
-    sdk_member_name: "mynativeheaders",
+    name: "mynativeheaders",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     device_supported: false,
     host_supported: true,
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     target: {
         host: {
             enabled: false,
@@ -2070,17 +2001,20 @@
         },
     },
 }
+`),
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_headers {
-    name: "mynativeheaders",
-    prefer: false,
+    name: "mysdk_mynativeheaders@current",
+    sdk_member_name: "mynativeheaders",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     device_supported: false,
     host_supported: true,
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     target: {
         host: {
             enabled: false,
@@ -2114,7 +2048,7 @@
 }
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 `),
 	)
 }
@@ -2131,20 +2065,52 @@
 			name: "mynativeheaders",
 			host_supported: true,
 			stl: "none",
-			export_system_include_dirs: ["include"],
+			export_system_include_dirs: ["myinclude"],
 			target: {
 				android: {
-					export_include_dirs: ["include-android"],
+					export_include_dirs: ["myinclude-android"],
 				},
 				host: {
-					export_include_dirs: ["include-host"],
+					export_include_dirs: ["myinclude-host"],
 				},
 			},
 		}
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_headers {
+    name: "mynativeheaders",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    host_supported: true,
+    stl: "none",
+    compile_multilib: "both",
+    export_system_include_dirs: ["common_os/include/myinclude"],
+    target: {
+        host: {
+            enabled: false,
+        },
+        android: {
+            export_include_dirs: ["android/include/myinclude-android"],
+        },
+        linux_glibc: {
+            export_include_dirs: ["linux_glibc/include/myinclude-host"],
+        },
+        linux_glibc_x86_64: {
+            enabled: true,
+        },
+        linux_glibc_x86: {
+            enabled: true,
+        },
+    },
+}
+`),
+		// Verifi
+		checkVersionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_headers {
@@ -2155,44 +2121,16 @@
     host_supported: true,
     stl: "none",
     compile_multilib: "both",
-    export_system_include_dirs: ["common_os/include/include"],
+    export_system_include_dirs: ["common_os/include/myinclude"],
     target: {
         host: {
             enabled: false,
         },
         android: {
-            export_include_dirs: ["android/include/include-android"],
+            export_include_dirs: ["android/include/myinclude-android"],
         },
         linux_glibc: {
-            export_include_dirs: ["linux_glibc/include/include-host"],
-        },
-        linux_glibc_x86_64: {
-            enabled: true,
-        },
-        linux_glibc_x86: {
-            enabled: true,
-        },
-    },
-}
-
-cc_prebuilt_library_headers {
-    name: "mynativeheaders",
-    prefer: false,
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    host_supported: true,
-    stl: "none",
-    compile_multilib: "both",
-    export_system_include_dirs: ["common_os/include/include"],
-    target: {
-        host: {
-            enabled: false,
-        },
-        android: {
-            export_include_dirs: ["android/include/include-android"],
-        },
-        linux_glibc: {
-            export_include_dirs: ["linux_glibc/include/include-host"],
+            export_include_dirs: ["linux_glibc/include/myinclude-host"],
         },
         linux_glibc_x86_64: {
             enabled: true,
@@ -2222,9 +2160,9 @@
 }
 `),
 		checkAllCopyRules(`
-include/Test.h -> common_os/include/include/Test.h
-include-android/AndroidTest.h -> android/include/include-android/AndroidTest.h
-include-host/HostTest.h -> linux_glibc/include/include-host/HostTest.h
+myinclude/Test.h -> common_os/include/myinclude/Test.h
+myinclude-android/AndroidTest.h -> android/include/myinclude-android/AndroidTest.h
+myinclude-host/HostTest.h -> linux_glibc/include/myinclude-host/HostTest.h
 `),
 	)
 }
@@ -2253,27 +2191,10 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_sslnil@current",
-    sdk_member_name: "sslnil",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    compile_multilib: "both",
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/sslnil.so"],
-        },
-        arm: {
-            srcs: ["arm/lib/sslnil.so"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "sslnil",
     prefer: false,
     visibility: ["//visibility:public"],
@@ -2290,24 +2211,6 @@
 }
 
 cc_prebuilt_library_shared {
-    name: "mysdk_sslempty@current",
-    sdk_member_name: "sslempty",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    compile_multilib: "both",
-    system_shared_libs: [],
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/sslempty.so"],
-        },
-        arm: {
-            srcs: ["arm/lib/sslempty.so"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "sslempty",
     prefer: false,
     visibility: ["//visibility:public"],
@@ -2325,24 +2228,6 @@
 }
 
 cc_prebuilt_library_shared {
-    name: "mysdk_sslnonempty@current",
-    sdk_member_name: "sslnonempty",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    compile_multilib: "both",
-    system_shared_libs: ["mysdk_sslnil@current"],
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/sslnonempty.so"],
-        },
-        arm: {
-            srcs: ["arm/lib/sslnonempty.so"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "sslnonempty",
     prefer: false,
     visibility: ["//visibility:public"],
@@ -2358,16 +2243,6 @@
         },
     },
 }
-
-sdk_snapshot {
-    name: "mysdk@current",
-    visibility: ["//visibility:public"],
-    native_shared_libs: [
-        "mysdk_sslnil@current",
-        "mysdk_sslempty@current",
-        "mysdk_sslnonempty@current",
-    ],
-}
 `))
 
 	result = testSdkWithCc(t, `
@@ -2389,16 +2264,15 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_sslvariants@current",
-    sdk_member_name: "sslvariants",
+    name: "sslvariants",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     host_supported: true,
-    installable: false,
     compile_multilib: "both",
     target: {
         host: {
@@ -2423,13 +2297,17 @@
         },
     },
 }
+`),
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "sslvariants",
-    prefer: false,
+    name: "mysdk_sslvariants@current",
+    sdk_member_name: "sslvariants",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     host_supported: true,
+    installable: false,
     compile_multilib: "both",
     target: {
         host: {
@@ -2497,34 +2375,10 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_stubslib@current",
-    sdk_member_name: "stubslib",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    compile_multilib: "both",
-    stubs: {
-        versions: [
-            "1",
-            "2",
-            "3",
-        ],
-    },
-    arch: {
-        arm64: {
-            srcs: ["arm64/lib/stubslib.so"],
-        },
-        arm: {
-            srcs: ["arm/lib/stubslib.so"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "stubslib",
     prefer: false,
     visibility: ["//visibility:public"],
@@ -2546,12 +2400,6 @@
         },
     },
 }
-
-sdk_snapshot {
-    name: "mysdk@current",
-    visibility: ["//visibility:public"],
-    native_shared_libs: ["mysdk_stubslib@current"],
-}
 `))
 }
 
@@ -2580,16 +2428,15 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_stubslib@current",
-    sdk_member_name: "stubslib",
+    name: "stubslib",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     host_supported: true,
-    installable: false,
     compile_multilib: "both",
     stubs: {
         versions: [
@@ -2618,13 +2465,17 @@
         },
     },
 }
+`),
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "stubslib",
-    prefer: false,
+    name: "mysdk_stubslib@current",
+    sdk_member_name: "stubslib",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     host_supported: true,
+    installable: false,
     compile_multilib: "both",
     stubs: {
         versions: [
@@ -2690,16 +2541,15 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_mylib@current",
-    sdk_member_name: "mylib",
+    name: "mylib",
+    prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     host_supported: true,
-    installable: false,
     unique_host_soname: true,
     compile_multilib: "both",
     target: {
@@ -2722,13 +2572,17 @@
         },
     },
 }
+`),
+		checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mylib",
-    prefer: false,
+    name: "mysdk_mylib@current",
+    sdk_member_name: "mylib",
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     host_supported: true,
+    installable: false,
     unique_host_soname: true,
     compile_multilib: "both",
     target: {
@@ -2789,7 +2643,7 @@
 		cc_library_shared {
 			name: "mynativelib",
 			srcs: ["Test.cpp"],
-			export_include_dirs: ["include"],
+			export_include_dirs: ["myinclude"],
 			arch: {
 				arm64: {
 					export_system_include_dirs: ["arm64/include"],
@@ -2802,34 +2656,16 @@
 	`)
 
 	result.CheckSnapshot("mysdk", "",
-		checkAndroidBpContents(`
+		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
 cc_prebuilt_library_shared {
-    name: "mysdk_mynativelib@current",
-    sdk_member_name: "mynativelib",
-    visibility: ["//visibility:public"],
-    apex_available: ["//apex_available:platform"],
-    installable: false,
-    compile_multilib: "both",
-    export_include_dirs: ["include/include"],
-    arch: {
-        arm64: {
-            export_system_include_dirs: ["arm64/include/arm64/include"],
-        },
-        arm: {
-            srcs: ["arm/lib/mynativelib.so"],
-        },
-    },
-}
-
-cc_prebuilt_library_shared {
     name: "mynativelib",
     prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     compile_multilib: "both",
-    export_include_dirs: ["include/include"],
+    export_include_dirs: ["include/myinclude"],
     arch: {
         arm64: {
             export_system_include_dirs: ["arm64/include/arm64/include"],
@@ -2839,15 +2675,9 @@
         },
     },
 }
-
-sdk_snapshot {
-    name: "mysdk@current",
-    visibility: ["//visibility:public"],
-    native_shared_libs: ["mysdk_mynativelib@current"],
-}
 `),
 		checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
 arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h
 .intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
 	)
diff --git a/sdk/testing.go b/sdk/testing.go
index 1ac873b..0bbf7f4 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -204,7 +204,11 @@
 
 func (h *TestHelper) AssertTrimmedStringEquals(message string, expected string, actual string) {
 	h.t.Helper()
-	h.AssertStringEquals(message, strings.TrimSpace(expected), strings.TrimSpace(actual))
+	expected = strings.TrimSpace(expected)
+	actual = strings.TrimSpace(actual)
+	if actual != expected {
+		h.t.Errorf("%s: expected:\n%s\nactual:\n%s\n", message, expected, actual)
+	}
 }
 
 func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {
@@ -243,11 +247,11 @@
 // e.g. find the src/dest pairs from each cp command, the various zip files
 // generated, etc.
 func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo {
-	androidBpContents := sdk.GetAndroidBpContentsForTests()
-
 	info := &snapshotBuildInfo{
-		r:                 r,
-		androidBpContents: androidBpContents,
+		r:                            r,
+		androidBpContents:            sdk.GetAndroidBpContentsForTests(),
+		androidUnversionedBpContents: sdk.GetUnversionedAndroidBpContentsForTests(),
+		androidVersionedBpContents:   sdk.GetVersionedAndroidBpContentsForTests(),
 	}
 
 	buildParams := sdk.BuildParamsForTests()
@@ -365,6 +369,33 @@
 	}
 }
 
+// Check that the snapshot's unversioned generated Android.bp is correct.
+//
+// This func should be used to check the general snapshot generation code.
+//
+// Both the expected and actual string are both trimmed before comparing.
+func checkUnversionedAndroidBpContents(expected string) snapshotBuildInfoChecker {
+	return func(info *snapshotBuildInfo) {
+		info.r.t.Helper()
+		info.r.AssertTrimmedStringEquals("unversioned Android.bp contents do not match", expected, info.androidUnversionedBpContents)
+	}
+}
+
+// Check that the snapshot's versioned generated Android.bp is correct.
+//
+// This func should only be used to check the version specific snapshot generation code,
+// i.e. the encoding of version into module names and the generation of the _snapshot module. The
+// general snapshot generation code should be checked using the checkUnversionedAndroidBpContents()
+// func.
+//
+// Both the expected and actual string are both trimmed before comparing.
+func checkVersionedAndroidBpContents(expected string) snapshotBuildInfoChecker {
+	return func(info *snapshotBuildInfo) {
+		info.r.t.Helper()
+		info.r.AssertTrimmedStringEquals("versioned Android.bp contents do not match", expected, info.androidVersionedBpContents)
+	}
+}
+
 // Check that the snapshot's copy rules are correct.
 //
 // The copy rules are formatted as <src> -> <dest>, one per line and then compared
@@ -407,6 +438,12 @@
 	// The contents of the generated Android.bp file
 	androidBpContents string
 
+	// The contents of the unversioned Android.bp file
+	androidUnversionedBpContents string
+
+	// The contents of the versioned Android.bp file
+	androidVersionedBpContents string
+
 	// The paths, relative to the snapshot root, of all files and directories copied into the
 	// snapshot.
 	snapshotContents []string
diff --git a/sdk/update.go b/sdk/update.go
index 377aaae..828c7b6 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -572,12 +572,20 @@
 }
 
 func generateBpContents(contents *generatedContents, bpFile *bpFile) {
+	generateFilteredBpContents(contents, bpFile, func(*bpModule) bool {
+		return true
+	})
+}
+
+func generateFilteredBpContents(contents *generatedContents, bpFile *bpFile, moduleFilter func(module *bpModule) bool) {
 	contents.Printfln("// This is auto-generated. DO NOT EDIT.")
 	for _, bpModule := range bpFile.order {
-		contents.Printfln("")
-		contents.Printfln("%s {", bpModule.moduleType)
-		outputPropertySet(contents, bpModule.bpPropertySet)
-		contents.Printfln("}")
+		if moduleFilter(bpModule) {
+			contents.Printfln("")
+			contents.Printfln("%s {", bpModule.moduleType)
+			outputPropertySet(contents, bpModule.bpPropertySet)
+			contents.Printfln("}")
+		}
 	}
 }
 
@@ -639,6 +647,22 @@
 	return contents.content.String()
 }
 
+func (s *sdk) GetUnversionedAndroidBpContentsForTests() string {
+	contents := &generatedContents{}
+	generateFilteredBpContents(contents, s.builderForTests.bpFile, func(module *bpModule) bool {
+		return !strings.Contains(module.properties["name"].(string), "@")
+	})
+	return contents.content.String()
+}
+
+func (s *sdk) GetVersionedAndroidBpContentsForTests() string {
+	contents := &generatedContents{}
+	generateFilteredBpContents(contents, s.builderForTests.bpFile, func(module *bpModule) bool {
+		return strings.Contains(module.properties["name"].(string), "@")
+	})
+	return contents.content.String()
+}
+
 type snapshotBuilder struct {
 	ctx         android.ModuleContext
 	sdk         *sdk
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 54dfc24..031cd47 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -84,9 +84,6 @@
 
 	// Make this module available when building for recovery.
 	Recovery_available *bool
-
-	// Properties for Bazel migration purposes.
-	bazel.Properties
 }
 
 type TestProperties struct {
@@ -132,6 +129,7 @@
 
 type ShBinary struct {
 	android.ModuleBase
+	android.BazelModuleBase
 
 	properties shBinaryProperties
 
@@ -246,7 +244,7 @@
 		OutputFile: android.OptionalPathForPath(s.outputFilePath),
 		Include:    "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				s.customAndroidMkEntries(entries)
 				entries.SetString("LOCAL_MODULE_RELATIVE_PATH", proptools.String(s.properties.Sub_dir))
 			},
@@ -395,7 +393,7 @@
 		OutputFile: android.OptionalPathForPath(s.outputFilePath),
 		Include:    "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
 				s.customAndroidMkEntries(entries)
 				entries.SetPath("LOCAL_MODULE_PATH", s.installDir.ToMakePath())
 				entries.AddCompatibilityTestSuites(s.testProperties.Test_suites...)
@@ -427,6 +425,7 @@
 
 func InitShBinaryModule(s *ShBinary) {
 	s.AddProperties(&s.properties)
+	android.InitBazelModule(s)
 }
 
 // sh_binary is for a shell script or batch file to be installed as an
@@ -504,7 +503,7 @@
 
 func ShBinaryBp2Build(ctx android.TopDownMutatorContext) {
 	m, ok := ctx.Module().(*ShBinary)
-	if !ok || !m.properties.Bazel_module.Bp2build_available {
+	if !ok || !m.ConvertWithBp2build() {
 		return
 	}
 
@@ -514,9 +513,11 @@
 		Srcs: srcs,
 	}
 
-	props := bazel.NewBazelTargetModuleProperties(m.Name(), "sh_binary", "")
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class: "sh_binary",
+	}
 
-	ctx.CreateBazelTargetModule(BazelShBinaryFactory, props, attrs)
+	ctx.CreateBazelTargetModule(BazelShBinaryFactory, m.Name(), props, attrs)
 }
 
 func (m *bazelShBinary) Name() string {
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index c664461..fb7ab13 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -61,7 +61,7 @@
 }
 
 func TestShTestSubDir(t *testing.T) {
-	ctx, config := testShBinary(t, `
+	ctx, _ := testShBinary(t, `
 		sh_test {
 			name: "foo",
 			src: "test.sh",
@@ -71,7 +71,7 @@
 
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
 
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 
 	expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo_test"
 	actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
@@ -81,7 +81,7 @@
 }
 
 func TestShTest(t *testing.T) {
-	ctx, config := testShBinary(t, `
+	ctx, _ := testShBinary(t, `
 		sh_test {
 			name: "foo",
 			src: "test.sh",
@@ -95,7 +95,7 @@
 
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
 
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 
 	expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo"
 	actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
@@ -111,7 +111,7 @@
 }
 
 func TestShTest_dataModules(t *testing.T) {
-	ctx, config := testShBinary(t, `
+	ctx, _ := testShBinary(t, `
 		sh_test {
 			name: "foo",
 			src: "test.sh",
@@ -157,7 +157,7 @@
 		}
 
 		mod := variant.Module().(*ShTest)
-		entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+		entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 		expectedData := []string{
 			filepath.Join(buildDir, ".intermediates/bar", arch, ":bar"),
 			filepath.Join(buildDir, ".intermediates/foo", arch, "relocated/:lib64/libbar"+libExt),
@@ -190,7 +190,7 @@
 }
 
 func TestShTestHost_dataDeviceModules(t *testing.T) {
-	ctx, config := testShBinary(t, `
+	ctx, _ := testShBinary(t, `
 		sh_test_host {
 			name: "foo",
 			src: "test.sh",
@@ -227,7 +227,7 @@
 	}
 
 	mod := variant.Module().(*ShTest)
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
 	expectedData := []string{
 		filepath.Join(buildDir, ".intermediates/bar/android_arm64_armv8-a/:bar"),
 		// libbar has been relocated, and so has a variant that matches the host arch.