Merge "apex: Make android_library support APEX variants" into rvc-dev
diff --git a/apex/builder.go b/apex/builder.go
index 06c10eb..cebd86a 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -445,11 +445,11 @@
 		}
 
 		targetSdkVersion := ctx.Config().DefaultAppTargetSdk()
+		// TODO(b/157078772): propagate min_sdk_version to apexer.
 		minSdkVersion := ctx.Config().DefaultAppTargetSdk()
 
 		if a.minSdkVersion(ctx) == android.SdkVersion_Android10 {
 			minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx))
-			targetSdkVersion = strconv.Itoa(a.minSdkVersion(ctx))
 		}
 
 		if java.UseApiFingerprint(ctx) {
diff --git a/cc/builder.go b/cc/builder.go
index d8e90b6..37fbf4e 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -65,7 +65,7 @@
 
 	ld, ldRE = remoteexec.StaticRules(pctx, "ld",
 		blueprint.RuleParams{
-			Command: "$ldCmd ${crtBegin} @${out}.rsp " +
+			Command: "$reTemplate$ldCmd ${crtBegin} @${out}.rsp " +
 				"${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${extraLibFlags}",
 			CommandDeps:    []string{"$ldCmd"},
 			Rspfile:        "${out}.rsp",
@@ -73,28 +73,30 @@
 			// clang -Wl,--out-implib doesn't update its output file if it hasn't changed.
 			Restat: true,
 		},
-		&remoteexec.REParams{Labels: map[string]string{"type": "link", "tool": "clang"},
+		&remoteexec.REParams{
+			Labels:          map[string]string{"type": "link", "tool": "clang"},
 			ExecStrategy:    "${config.RECXXLinksExecStrategy}",
 			Inputs:          []string{"${out}.rsp"},
 			RSPFile:         "${out}.rsp",
-			OutputFiles:     []string{"${out}"},
+			OutputFiles:     []string{"${out}", "$implicitOutputs"},
 			ToolchainInputs: []string{"$ldCmd"},
 			Platform:        map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
-		}, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, nil)
+		}, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, []string{"implicitOutputs"})
 
 	partialLd, partialLdRE = remoteexec.StaticRules(pctx, "partialLd",
 		blueprint.RuleParams{
 			// Without -no-pie, clang 7.0 adds -pie to link Android files,
 			// but -r and -pie cannot be used together.
-			Command:     "$ldCmd -fuse-ld=lld -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
+			Command:     "$reTemplate$ldCmd -fuse-ld=lld -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
 			CommandDeps: []string{"$ldCmd"},
 		}, &remoteexec.REParams{
-			Labels:       map[string]string{"type": "link", "tool": "clang"},
-			ExecStrategy: "${config.RECXXLinksExecStrategy}", Inputs: []string{"$inCommaList"},
-			OutputFiles:     []string{"${out}"},
+			Labels:          map[string]string{"type": "link", "tool": "clang"},
+			ExecStrategy:    "${config.RECXXLinksExecStrategy}",
+			Inputs:          []string{"$inCommaList"},
+			OutputFiles:     []string{"${out}", "$implicitOutputs"},
 			ToolchainInputs: []string{"$ldCmd"},
 			Platform:        map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
-		}, []string{"ldCmd", "ldFlags"}, []string{"inCommaList"})
+		}, []string{"ldCmd", "ldFlags"}, []string{"inCommaList", "implicitOutputs"})
 
 	ar = pctx.AndroidStaticRule("ar",
 		blueprint.RuleParams{
@@ -199,12 +201,18 @@
 	_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
 
 	// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
-	sAbiDump = pctx.AndroidStaticRule("sAbiDump",
+	sAbiDump, sAbiDumpRE = remoteexec.StaticRules(pctx, "sAbiDump",
 		blueprint.RuleParams{
-			Command:     "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
+			Command:     "rm -f $out && $reTemplate$sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
 			CommandDeps: []string{"$sAbiDumper"},
-		},
-		"cFlags", "exportDirs")
+		}, &remoteexec.REParams{
+			Labels:       map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"},
+			ExecStrategy: "${config.REAbiDumperExecStrategy}",
+			Platform: map[string]string{
+				remoteexec.PoolKey:      "${config.RECXXPool}",
+				"InputRootAbsolutePath": android.AbsSrcDirForExistingUseCases(),
+			},
+		}, []string{"cFlags", "exportDirs"}, nil)
 
 	_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
 
@@ -567,8 +575,12 @@
 			sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump")
 			sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile)
 
+			dumpRule := sAbiDump
+			if ctx.Config().IsEnvTrue("RBE_ABI_DUMPER") {
+				dumpRule = sAbiDumpRE
+			}
 			ctx.Build(pctx, android.BuildParams{
-				Rule:        sAbiDump,
+				Rule:        dumpRule,
 				Description: "header-abi-dumper " + srcFile.Rel(),
 				Output:      sAbiDumpFile,
 				Input:       srcFile,
@@ -672,8 +684,17 @@
 	}
 
 	rule := ld
+	args := map[string]string{
+		"ldCmd":         ldCmd,
+		"crtBegin":      crtBegin.String(),
+		"libFlags":      strings.Join(libFlagsList, " "),
+		"extraLibFlags": flags.extraLibFlags,
+		"ldFlags":       flags.globalLdFlags + " " + flags.localLdFlags,
+		"crtEnd":        crtEnd.String(),
+	}
 	if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
 		rule = ldRE
+		args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",")
 	}
 
 	ctx.Build(pctx, android.BuildParams{
@@ -683,14 +704,7 @@
 		ImplicitOutputs: implicitOutputs,
 		Inputs:          objFiles,
 		Implicits:       deps,
-		Args: map[string]string{
-			"ldCmd":         ldCmd,
-			"crtBegin":      crtBegin.String(),
-			"libFlags":      strings.Join(libFlagsList, " "),
-			"extraLibFlags": flags.extraLibFlags,
-			"ldFlags":       flags.globalLdFlags + " " + flags.localLdFlags,
-			"crtEnd":        crtEnd.String(),
-		},
+		Args:            args,
 	})
 }
 
diff --git a/cc/config/global.go b/cc/config/global.go
index ae32d91..f4d188e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -257,8 +257,10 @@
 		return ""
 	})
 
+	pctx.VariableFunc("RECXXPool", envOverrideFunc("RBE_CXX_POOL", remoteexec.DefaultPool))
 	pctx.VariableFunc("RECXXLinksPool", envOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool))
 	pctx.VariableFunc("RECXXLinksExecStrategy", envOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+	pctx.VariableFunc("REAbiDumperExecStrategy", envOverrideFunc("RBE_ABI_DUMPER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
 }
 
 var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index a638db2..e9a850e 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -374,6 +374,10 @@
 			regexp.MustCompile(`^.*/` + selected.moduleName + `(-.*\.apk)$`),
 			config.stem + `$1`,
 		},
+		{
+			regexp.MustCompile(`^universal\.apk$`),
+			config.stem + ".apk",
+		},
 	}
 	renamer := func(path string) (string, bool) {
 		for _, rr := range renameRules {
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index bc4d377..bdd4bec 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -24,19 +24,19 @@
 	"android/soong/third_party/zip"
 )
 
-type TestConfigDesc struct {
+type testConfigDesc struct {
 	name         string
 	targetConfig TargetConfig
 	expected     SelectionResult
 }
 
-type TestDesc struct {
+type testDesc struct {
 	protoText string
-	configs   []TestConfigDesc
+	configs   []testConfigDesc
 }
 
 func TestSelectApks_ApkSet(t *testing.T) {
-	testCases := []TestDesc{
+	testCases := []testDesc{
 		{
 			protoText: `
 variant {
@@ -117,7 +117,7 @@
   version: "0.10.3" }
 
 `,
-			configs: []TestConfigDesc{
+			configs: []testConfigDesc{
 				{
 					name: "one",
 					targetConfig: TargetConfig{
@@ -209,7 +209,7 @@
           value { min { value: 21 } } } }
       path: "splits/base-master.apk"
       split_apk_metadata { is_master_split: true } } } }`,
-			configs: []TestConfigDesc{
+			configs: []testConfigDesc{
 				{
 					name: "Prerelease",
 					targetConfig: TargetConfig{
@@ -225,6 +225,30 @@
 				},
 			},
 		},
+		{
+			protoText: `
+variant {
+  targeting {
+    sdk_version_targeting {
+      value { min { value: 29 } } } }
+  apk_set {
+    module_metadata {
+      name: "base" targeting {} delivery_type: INSTALL_TIME }
+    apk_description {
+      targeting {}
+      path: "universal.apk"
+      standalone_apk_metadata { fused_module_name: "base" } } } }`,
+			configs: []testConfigDesc{
+				{
+					name:         "Universal",
+					targetConfig: TargetConfig{sdkVersion: 30},
+					expected: SelectionResult{
+						"base",
+						[]string{"universal.apk"},
+					},
+				},
+			},
+		},
 	}
 	for _, testCase := range testCases {
 		var toc bp.BuildApksResult
@@ -241,7 +265,7 @@
 }
 
 func TestSelectApks_ApexSet(t *testing.T) {
-	testCases := []TestDesc{
+	testCases := []testDesc{
 		{
 			protoText: `
 variant {
@@ -300,7 +324,7 @@
   version: "0.10.3" }
 
 `,
-			configs: []TestConfigDesc{
+			configs: []testConfigDesc{
 				{
 					name: "order matches priorities",
 					targetConfig: TargetConfig{
@@ -406,24 +430,48 @@
 	return nil
 }
 
-func TestWriteZip(t *testing.T) {
+type testCaseWriteZip struct {
+	name       string
+	moduleName string
+	stem       string
 	// what we write from what
-	expected := map[string]string{
-		"Foo.apk":       "splits/mybase-master.apk",
-		"Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
+	expected map[string]string
+}
+
+func TestWriteZip(t *testing.T) {
+	testCases := []testCaseWriteZip{
+		{
+			name:       "splits",
+			moduleName: "mybase",
+			stem:       "Foo",
+			expected: map[string]string{
+				"Foo.apk":       "splits/mybase-master.apk",
+				"Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
+			},
+		},
+		{
+			name:       "universal",
+			moduleName: "base",
+			stem:       "Bar",
+			expected: map[string]string{
+				"Bar.apk": "universal.apk",
+			},
+		},
 	}
-	apkSet := ApkSet{entries: make(map[string]*zip.File)}
-	sel := SelectionResult{moduleName: "mybase"}
-	for _, in := range expected {
-		apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
-		sel.entries = append(sel.entries, in)
-	}
-	writer := testZip2ZipWriter{make(map[string]string)}
-	config := TargetConfig{stem: "Foo"}
-	if err := apkSet.writeApks(sel, config, writer); err != nil {
-		t.Error(err)
-	}
-	if !reflect.DeepEqual(expected, writer.entries) {
-		t.Errorf("expected %v, got %v", expected, writer.entries)
+	for _, testCase := range testCases {
+		apkSet := ApkSet{entries: make(map[string]*zip.File)}
+		sel := SelectionResult{moduleName: testCase.moduleName}
+		for _, in := range testCase.expected {
+			apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
+			sel.entries = append(sel.entries, in)
+		}
+		writer := testZip2ZipWriter{make(map[string]string)}
+		config := TargetConfig{stem: testCase.stem}
+		if err := apkSet.writeApks(sel, config, writer); err != nil {
+			t.Error(err)
+		}
+		if !reflect.DeepEqual(testCase.expected, writer.entries) {
+			t.Errorf("expected %v, got %v", testCase.expected, writer.entries)
+		}
 	}
 }
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 884a757..ce624bf 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -180,7 +180,9 @@
 	// b/149353192: when a module is instrumented, jacoco adds synthetic members
 	// $jacocoData and $jacocoInit. Since they don't exist when building the hidden API flags,
 	// don't complain when we don't find hidden API flags for the synthetic members.
-	if j, ok := ctx.Module().(*Library); ok && j.shouldInstrument(ctx) {
+	if j, ok := ctx.Module().(interface {
+		shouldInstrument(android.BaseModuleContext) bool
+	}); ok && j.shouldInstrument(ctx) {
 		enforceHiddenApiFlagsToAllMembers = false
 	}
 
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index d43dc6c..f511922 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -148,7 +148,8 @@
 // locally executable rule and the second rule is a remotely executable rule.
 func StaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams *REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
 	ruleParamsRE := ruleParams
-	ruleParamsRE.Command = reParams.Template() + ruleParamsRE.Command
+	ruleParams.Command = strings.ReplaceAll(ruleParams.Command, "$reTemplate", "")
+	ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, "$reTemplate", reParams.Template())
 
 	return ctx.AndroidStaticRule(name, ruleParams, commonArgs...),
 		ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)