Merge "Convert testDexpreoptWithApexes to use test fixtures"
diff --git a/android/bazel.go b/android/bazel.go
index a7c6b63..cc02152 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -129,8 +129,8 @@
 	}
 
 	// Per-module denylist to always opt modules out.
-
 	bp2buildModuleDoNotConvertList = []string{
+		"generated_android_ids",
 		"libBionicBenchmarksUtils",
 		"libbionic_spawn_benchmark",
 		"libc_jemalloc_wrapper",
@@ -170,6 +170,8 @@
 		"liblinker_debuggerd_stub",
 		"libbionic_tests_headers_posix",
 		"libc_dns",
+		"note_memtag_heap_async",
+		"note_memtag_heap_sync",
 	}
 
 	// Used for quicker lookups
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 45dfbaa..abc793f 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -27,6 +27,7 @@
 	"sync"
 
 	"android/soong/bazel/cquery"
+
 	"github.com/google/blueprint/bootstrap"
 
 	"android/soong/bazel"
@@ -37,7 +38,6 @@
 
 const (
 	getAllFiles CqueryRequestType = iota
-	getCcObjectFiles
 	getAllFilesAndCcObjectFiles
 )
 
@@ -56,10 +56,6 @@
 	// Returns result files built by building the given bazel target label.
 	GetOutputFiles(label string, archType ArchType) ([]string, bool)
 
-	// Returns object files produced by compiling the given cc-related target.
-	// Retrieves these files from Bazel's CcInfo provider.
-	GetCcObjectFiles(label string, archType ArchType) ([]string, bool)
-
 	// TODO(cparsons): Other cquery-related methods should be added here.
 	// Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order).
 	GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool)
@@ -116,11 +112,6 @@
 	return result, ok
 }
 
-func (m MockBazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
-	result, ok := m.AllFiles[label]
-	return result, ok
-}
-
 func (m MockBazelContext) GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
 	result, ok := m.AllFiles[label]
 	return result, result, ok
@@ -154,16 +145,6 @@
 	return ret, ok
 }
 
-func (bazelCtx *bazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
-	rawString, ok := bazelCtx.cquery(label, cquery.GetCcObjectFiles, archType)
-	var returnResult []string
-	if ok {
-		bazelOutput := strings.TrimSpace(rawString)
-		returnResult = cquery.GetCcObjectFiles.ParseResult(bazelOutput).([]string)
-	}
-	return returnResult, ok
-}
-
 func (bazelCtx *bazelContext) GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
 	var outputFiles []string
 	var ccObjects []string
@@ -183,10 +164,6 @@
 	panic("unimplemented")
 }
 
-func (n noopBazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
-	panic("unimplemented")
-}
-
 func (n noopBazelContext) GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
 	panic("unimplemented")
 }
@@ -332,8 +309,13 @@
     name = "sourceroot",
     path = "%s",
 )
+
+local_repository(
+    name = "rules_cc",
+    path = "%s/build/bazel/rules_cc",
+)
 `
-	return []byte(fmt.Sprintf(formatString, context.workspaceDir))
+	return []byte(fmt.Sprintf(formatString, context.workspaceDir, context.workspaceDir))
 }
 
 func (context *bazelContext) mainBzlFileContents() []byte {
diff --git a/android/fixture.go b/android/fixture.go
index 8d62958..303c95c 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -455,7 +455,7 @@
 	Extend(preparers ...FixturePreparer) FixturePreparer
 
 	// Create a Fixture.
-	Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
+	Fixture(t *testing.T) Fixture
 
 	// ExtendWithErrorHandler creates a new FixturePreparer that will use the supplied error handler
 	// to check the errors (may be 0) reported by the test.
@@ -466,12 +466,13 @@
 
 	// Run the test, checking any errors reported and returning a TestResult instance.
 	//
-	// Shorthand for Fixture(t, preparers...).RunTest()
-	RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult
+	// Shorthand for Fixture(t).RunTest()
+	RunTest(t *testing.T) *TestResult
 
 	// Run the test with the supplied Android.bp file.
 	//
-	// Shorthand for RunTest(t, android.FixtureWithRootAndroidBp(bp))
+	// preparer.RunTestWithBp(t, bp) is shorthand for
+	// android.GroupFixturePreparers(preparer, android.FixtureWithRootAndroidBp(bp)).RunTest(t)
 	RunTestWithBp(t *testing.T, bp string) *TestResult
 
 	// RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
@@ -705,13 +706,11 @@
 	NinjaDeps []string
 }
 
-func createFixture(t *testing.T, buildDir string, base []*simpleFixturePreparer, extra []FixturePreparer) Fixture {
-	all := dedupAndFlattenPreparers(base, extra)
-
+func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture {
 	config := TestConfig(buildDir, nil, "", nil)
 	ctx := NewTestContext(config)
 	fixture := &fixture{
-		preparers: all,
+		preparers: preparers,
 		t:         t,
 		config:    config,
 		ctx:       ctx,
@@ -720,7 +719,7 @@
 		errorHandler: FixtureExpectsNoErrors,
 	}
 
-	for _, preparer := range all {
+	for _, preparer := range preparers {
 		preparer.function(fixture)
 	}
 
@@ -740,8 +739,8 @@
 	return newFixturePreparer(all)
 }
 
-func (b *baseFixturePreparer) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
-	return createFixture(t, t.TempDir(), b.self.list(), preparers)
+func (b *baseFixturePreparer) Fixture(t *testing.T) Fixture {
+	return createFixture(t, t.TempDir(), b.self.list())
 }
 
 func (b *baseFixturePreparer) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer {
@@ -750,15 +749,15 @@
 	}))
 }
 
-func (b *baseFixturePreparer) RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult {
+func (b *baseFixturePreparer) RunTest(t *testing.T) *TestResult {
 	t.Helper()
-	fixture := b.self.Fixture(t, preparers...)
+	fixture := b.self.Fixture(t)
 	return fixture.RunTest()
 }
 
 func (b *baseFixturePreparer) RunTestWithBp(t *testing.T, bp string) *TestResult {
 	t.Helper()
-	return b.RunTest(t, FixtureWithRootAndroidBp(bp))
+	return GroupFixturePreparers(b.self, FixtureWithRootAndroidBp(bp)).RunTest(t)
 }
 
 func (b *baseFixturePreparer) RunTestWithConfig(t *testing.T, config Config) *TestResult {
@@ -811,16 +810,16 @@
 	return extendedFactory
 }
 
-func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
+func (f *fixtureFactory) Fixture(t *testing.T) Fixture {
 	// If there is no buildDirSupplier then just use the default implementation.
 	if f.buildDirSupplier == nil {
-		return f.baseFixturePreparer.Fixture(t, preparers...)
+		return f.baseFixturePreparer.Fixture(t)
 	}
 
 	// Retrieve the buildDir from the supplier.
 	buildDir := *f.buildDirSupplier
 
-	return createFixture(t, buildDir, f.preparers, preparers)
+	return createFixture(t, buildDir, f.preparers)
 }
 
 type fixture struct {
diff --git a/android/fixture_test.go b/android/fixture_test.go
index 681a034..8f04715 100644
--- a/android/fixture_test.go
+++ b/android/fixture_test.go
@@ -43,43 +43,40 @@
 
 	extension := group.Extend(preparer4, preparer2)
 
-	extension.Fixture(t, preparer1, preparer2, preparer2Then1, preparer3)
+	GroupFixturePreparers(extension, preparer1, preparer2, preparer2Then1, preparer3).Fixture(t)
 
 	AssertDeepEquals(t, "preparers called in wrong order",
 		[]string{"preparer1", "preparer2", "preparer4", "preparer3"}, list)
 }
 
 func TestFixtureValidateMockFS(t *testing.T) {
-	buildDir := "<unused>"
-	factory := NewFixtureFactory(&buildDir)
-
 	t.Run("absolute path", func(t *testing.T) {
 		AssertPanicMessageContains(t, "source path validation failed", "Path is outside directory: /abs/path/Android.bp", func() {
-			factory.Fixture(t, FixtureAddFile("/abs/path/Android.bp", nil))
+			FixtureAddFile("/abs/path/Android.bp", nil).Fixture(t)
 		})
 	})
 	t.Run("not canonical", func(t *testing.T) {
 		AssertPanicMessageContains(t, "source path validation failed", `path "path/with/../in/it/Android.bp" is not a canonical path, use "path/in/it/Android.bp" instead`, func() {
-			factory.Fixture(t, FixtureAddFile("path/with/../in/it/Android.bp", nil))
+			FixtureAddFile("path/with/../in/it/Android.bp", nil).Fixture(t)
 		})
 	})
 	t.Run("FixtureAddFile", func(t *testing.T) {
 		AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
-			factory.Fixture(t, FixtureAddFile("out/Android.bp", nil))
+			FixtureAddFile("out/Android.bp", nil).Fixture(t)
 		})
 	})
 	t.Run("FixtureMergeMockFs", func(t *testing.T) {
 		AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
-			factory.Fixture(t, FixtureMergeMockFs(MockFS{
+			FixtureMergeMockFs(MockFS{
 				"out/Android.bp": nil,
-			}))
+			}).Fixture(t)
 		})
 	})
 	t.Run("FixtureModifyMockFS", func(t *testing.T) {
 		AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
-			factory.Fixture(t, FixtureModifyMockFS(func(fs MockFS) {
+			FixtureModifyMockFS(func(fs MockFS) {
 				fs["out/Android.bp"] = nil
-			}))
+			}).Fixture(t)
 		})
 	})
 }
diff --git a/android/mutator.go b/android/mutator.go
index 3d24c1e..e25e2e8 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -539,7 +539,7 @@
 		Name: &name,
 	}
 
-	b := t.CreateModule(factory, &nameProp, attrs).(BazelTargetModule)
+	b := t.createModuleWithoutInheritance(factory, &nameProp, attrs).(BazelTargetModule)
 	b.SetBazelTargetModuleProperties(bazelProps)
 	return b
 }
@@ -608,6 +608,11 @@
 	return module
 }
 
+func (t *topDownMutatorContext) createModuleWithoutInheritance(factory ModuleFactory, props ...interface{}) Module {
+	module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), props...).(Module)
+	return module
+}
+
 func (b *bottomUpMutatorContext) MutatorName() string {
 	return b.bp.MutatorName()
 }
diff --git a/android/register.go b/android/register.go
index 35469d4..4c8088d 100644
--- a/android/register.go
+++ b/android/register.go
@@ -192,6 +192,15 @@
 		t.register(ctx)
 	}
 
+	if ctx.config.BazelContext.BazelEnabled() {
+		// Hydrate the configuration of bp2build-enabled module types. This is
+		// required as a signal to identify which modules should be deferred to
+		// Bazel in mixed builds, if it is enabled.
+		for t, _ := range bp2buildMutators {
+			ctx.config.bp2buildModuleTypeConfig[t] = true
+		}
+	}
+
 	mutators := collateGloballyRegisteredMutators()
 	mutators.registerAll(ctx)
 
diff --git a/android/variable.go b/android/variable.go
index 2ab51c7..dff48c2 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -448,6 +448,63 @@
 	}
 }
 
+// ProductConfigContext requires the access to the Module to get product config properties.
+type ProductConfigContext interface {
+	Module() Module
+}
+
+// ProductConfigProperty contains the information for a single property (may be a struct) paired
+// with the appropriate ProductConfigVariable.
+type ProductConfigProperty struct {
+	ProductConfigVariable string
+	Property              interface{}
+}
+
+// ProductConfigProperties is a map of property name to a slice of ProductConfigProperty such that
+// all it all product variable-specific versions of a property are easily accessed together
+type ProductConfigProperties map[string][]ProductConfigProperty
+
+// ProductVariableProperties returns a ProductConfigProperties containing only the properties which
+// have been set for the module in the given context.
+func ProductVariableProperties(ctx ProductConfigContext) ProductConfigProperties {
+	module := ctx.Module()
+	moduleBase := module.base()
+
+	productConfigProperties := ProductConfigProperties{}
+
+	if moduleBase.variableProperties == nil {
+		return productConfigProperties
+	}
+
+	variableValues := reflect.ValueOf(moduleBase.variableProperties).Elem().FieldByName("Product_variables")
+	for i := 0; i < variableValues.NumField(); i++ {
+		variableValue := variableValues.Field(i)
+		// Check if any properties were set for the module
+		if variableValue.IsZero() {
+			continue
+		}
+		// e.g. Platform_sdk_version, Unbundled_build, Malloc_not_svelte, etc.
+		productVariableName := variableValues.Type().Field(i).Name
+		for j := 0; j < variableValue.NumField(); j++ {
+			property := variableValue.Field(j)
+			// If the property wasn't set, no need to pass it along
+			if property.IsZero() {
+				continue
+			}
+
+			// e.g. Asflags, Cflags, Enabled, etc.
+			propertyName := variableValue.Type().Field(j).Name
+			productConfigProperties[propertyName] = append(productConfigProperties[propertyName],
+				ProductConfigProperty{
+					ProductConfigVariable: productVariableName,
+					Property:              property.Interface(),
+				})
+		}
+	}
+
+	return productConfigProperties
+}
+
 func VariableMutator(mctx BottomUpMutatorContext) {
 	var module Module
 	var ok bool
diff --git a/bazel/properties.go b/bazel/properties.go
index 25e110a..1763f2d 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"regexp"
 	"sort"
 )
 
@@ -31,6 +32,8 @@
 
 const BazelTargetModuleNamePrefix = "__bp2build__"
 
+var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)")
+
 // Label is used to represent a Bazel compatible Label. Also stores the original bp text to support
 // string replacement.
 type Label struct {
@@ -225,3 +228,23 @@
 		panic(fmt.Errorf("Unknown arch: %s", arch))
 	}
 }
+
+// TryVariableSubstitution, replace string substitution formatting within each string in slice with
+// Starlark string.format compatible tag for productVariable.
+func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
+	ret := make([]string, 0, len(slice))
+	changesMade := false
+	for _, s := range slice {
+		newS, changed := TryVariableSubstitution(s, productVariable)
+		ret = append(ret, newS)
+		changesMade = changesMade || changed
+	}
+	return ret, changesMade
+}
+
+// TryVariableSubstitution, replace string substitution formatting within s with Starlark
+// string.format compatible tag for productVariable.
+func TryVariableSubstitution(s string, productVariable string) (string, bool) {
+	sub := productVariableSubstitutionPattern.ReplaceAllString(s, "{"+productVariable+"}")
+	return sub, s != sub
+}
diff --git a/bloaty/Android.bp b/bloaty/Android.bp
index b1f1e39..96cc1a5 100644
--- a/bloaty/Android.bp
+++ b/bloaty/Android.bp
@@ -1,3 +1,7 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 bootstrap_go_package {
     name: "soong-bloaty",
     pkgPath: "android/soong/bloaty",
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index b007033..9461739 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -209,6 +209,34 @@
 )`,
 			},
 		},
+		{
+			description:                        "cc_object with product variable",
+			moduleTypeUnderTest:                "cc_object",
+			moduleTypeUnderTestFactory:         cc.ObjectFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+			blueprint: `cc_object {
+    name: "foo",
+    include_build_directory: false,
+    product_variables: {
+        platform_sdk_version: {
+            asflags: ["-DPLATFORM_SDK_VERSION=%d"],
+        },
+    },
+
+    bazel_module: { bp2build_available: true },
+}
+`,
+			expectedBazelTargets: []string{`cc_object(
+    name = "foo",
+    asflags = [
+        "-DPLATFORM_SDK_VERSION={Platform_sdk_version}",
+    ],
+    copts = [
+        "-fno-addrsig",
+    ],
+)`,
+			},
+		},
 	}
 
 	dir := "."
diff --git a/cc/object.go b/cc/object.go
index abc3e83..ea8d7d3 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -53,8 +53,17 @@
 }
 
 func (handler *objectBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
-	// TODO(b/181794963): restore mixed builds once cc_object incompatibility resolved
-	return false
+	bazelCtx := ctx.Config().BazelContext
+	objPaths, ok := bazelCtx.GetOutputFiles(label, ctx.Arch().ArchType)
+	if ok {
+		if len(objPaths) != 1 {
+			ctx.ModuleErrorf("expected exactly one object file for '%s', but got %s", label, objPaths)
+			return false
+		}
+
+		handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0]))
+	}
+	return ok
 }
 
 type ObjectLinkerProperties struct {
@@ -106,6 +115,7 @@
 	Srcs               bazel.LabelListAttribute
 	Deps               bazel.LabelListAttribute
 	Copts              bazel.StringListAttribute
+	Asflags            []string
 	Local_include_dirs []string
 }
 
@@ -149,6 +159,7 @@
 	var copts bazel.StringListAttribute
 	var srcs bazel.LabelListAttribute
 	var localIncludeDirs []string
+	var asFlags []string
 	for _, props := range m.compiler.compilerProps() {
 		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
 			copts.Value = baseCompilerProps.Cflags
@@ -174,6 +185,23 @@
 		}
 	}
 
+	productVariableProps := android.ProductVariableProperties(ctx)
+	if props, exists := productVariableProps["Asflags"]; exists {
+		// TODO(b/183595873): consider deduplicating handling of product variable properties
+		for _, prop := range props {
+			flags, ok := prop.Property.([]string)
+			if !ok {
+				ctx.ModuleErrorf("Could not convert product variable asflag property")
+				return
+			}
+			// TODO(b/183595873) handle other product variable usages -- as selects?
+			if newFlags, subbed := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable); subbed {
+				asFlags = append(asFlags, newFlags...)
+			}
+		}
+	}
+	// TODO(b/183595872) warn/error if we're not handling product variables
+
 	for arch, p := range m.GetArchProperties(&BaseCompilerProperties{}) {
 		if cProps, ok := p.(*BaseCompilerProperties); ok {
 			srcs.SetValueForArch(arch.Name, android.BazelLabelForModuleSrcExcludes(ctx, cProps.Srcs, cProps.Exclude_srcs))
@@ -185,6 +213,7 @@
 		Srcs:               srcs,
 		Deps:               deps,
 		Copts:              copts,
+		Asflags:            asFlags,
 		Local_include_dirs: localIncludeDirs,
 	}
 
diff --git a/java/java_test.go b/java/java_test.go
index d1d26ba..3aafdda 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -845,7 +845,12 @@
 			if expectedErrorPattern != "" {
 				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorPattern)
 			}
-			prepareForJavaTest.ExtendWithErrorHandler(errorHandler).RunTest(t, createPreparer(info))
+			android.GroupFixturePreparers(
+				prepareForJavaTest,
+				createPreparer(info),
+			).
+				ExtendWithErrorHandler(errorHandler).
+				RunTest(t)
 		})
 	}
 
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
index 120bbf7..7b5a386 100644
--- a/java/system_modules_test.go
+++ b/java/system_modules_test.go
@@ -50,7 +50,7 @@
 `)
 
 func TestJavaSystemModules(t *testing.T) {
-	result := prepareForJavaTest.RunTest(t, addSourceSystemModules)
+	result := android.GroupFixturePreparers(prepareForJavaTest, addSourceSystemModules).RunTest(t)
 
 	// check the existence of the source module
 	sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
@@ -77,7 +77,7 @@
 `)
 
 func TestJavaSystemModulesImport(t *testing.T) {
-	result := prepareForJavaTest.RunTest(t, addPrebuiltSystemModules)
+	result := android.GroupFixturePreparers(prepareForJavaTest, addPrebuiltSystemModules).RunTest(t)
 
 	// check the existence of the renamed prebuilt module
 	prebuiltSystemModules := result.ModuleForTests("system-modules", "android_common")
@@ -89,10 +89,11 @@
 }
 
 func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) {
-	result := prepareForJavaTest.RunTest(t,
+	result := android.GroupFixturePreparers(
+		prepareForJavaTest,
 		addSourceSystemModules,
 		addPrebuiltSystemModules,
-	)
+	).RunTest(t)
 
 	// check the existence of the source module
 	sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 18174a4..30cb937 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -27,7 +27,6 @@
   platform-mainline-test-exports
   runtime-module-host-exports
   runtime-module-sdk
-  stats-log-api-gen-exports
   statsd-module-sdk
   statsd-module-sdk-for-art
   tzdata-module-test-exports
diff --git a/sdk/testing.go b/sdk/testing.go
index 44970f7..9465e13 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -95,7 +95,10 @@
 
 func testSdkWithFs(t *testing.T, bp string, fs android.MockFS) *android.TestResult {
 	t.Helper()
-	return prepareForSdkTest.RunTest(t, fs.AddToFixture(), android.FixtureWithRootAndroidBp(bp))
+	return android.GroupFixturePreparers(
+		prepareForSdkTest,
+		fs.AddToFixture(),
+	).RunTestWithBp(t, bp)
 }
 
 func testSdkError(t *testing.T, pattern, bp string) {