Merge changes Ia3e93b8a,I964af3cb

* changes:
  Remove ccFixtureFactory
  Remove buildDir from cc package
diff --git a/android/bazel.go b/android/bazel.go
index 5bb3879..a7c6b63 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -129,49 +129,59 @@
 	}
 
 	// Per-module denylist to always opt modules out.
-	bp2buildModuleDoNotConvert = map[string]bool{
-		"libBionicBenchmarksUtils":      true,
-		"libbionic_spawn_benchmark":     true,
-		"libc_jemalloc_wrapper":         true,
-		"libc_bootstrap":                true,
-		"libc_init_static":              true,
-		"libc_init_dynamic":             true,
-		"libc_tzcode":                   true,
-		"libc_freebsd":                  true,
-		"libc_freebsd_large_stack":      true,
-		"libc_netbsd":                   true,
-		"libc_openbsd_ndk":              true,
-		"libc_openbsd_large_stack":      true,
-		"libc_openbsd":                  true,
-		"libc_gdtoa":                    true,
-		"libc_fortify":                  true,
-		"libc_bionic":                   true,
-		"libc_bionic_ndk":               true,
-		"libc_bionic_systrace":          true,
-		"libc_pthread":                  true,
-		"libc_syscalls":                 true,
-		"libc_aeabi":                    true,
-		"libc_ndk":                      true,
-		"libc_nopthread":                true,
-		"libc_common":                   true,
-		"libc_static_dispatch":          true,
-		"libc_dynamic_dispatch":         true,
-		"libc_common_static":            true,
-		"libc_common_shared":            true,
-		"libc_unwind_static":            true,
-		"libc_nomalloc":                 true,
-		"libasync_safe":                 true,
-		"libc_malloc_debug_backtrace":   true,
-		"libsystemproperties":           true,
-		"libdl_static":                  true,
-		"liblinker_main":                true,
-		"liblinker_malloc":              true,
-		"liblinker_debuggerd_stub":      true,
-		"libbionic_tests_headers_posix": true,
-		"libc_dns":                      true,
+
+	bp2buildModuleDoNotConvertList = []string{
+		"libBionicBenchmarksUtils",
+		"libbionic_spawn_benchmark",
+		"libc_jemalloc_wrapper",
+		"libc_bootstrap",
+		"libc_init_static",
+		"libc_init_dynamic",
+		"libc_tzcode",
+		"libc_freebsd",
+		"libc_freebsd_large_stack",
+		"libc_netbsd",
+		"libc_openbsd_ndk",
+		"libc_openbsd_large_stack",
+		"libc_openbsd",
+		"libc_gdtoa",
+		"libc_fortify",
+		"libc_bionic",
+		"libc_bionic_ndk",
+		"libc_bionic_systrace",
+		"libc_pthread",
+		"libc_syscalls",
+		"libc_aeabi",
+		"libc_ndk",
+		"libc_nopthread",
+		"libc_common",
+		"libc_static_dispatch",
+		"libc_dynamic_dispatch",
+		"libc_common_static",
+		"libc_common_shared",
+		"libc_unwind_static",
+		"libc_nomalloc",
+		"libasync_safe",
+		"libc_malloc_debug_backtrace",
+		"libsystemproperties",
+		"libdl_static",
+		"liblinker_main",
+		"liblinker_malloc",
+		"liblinker_debuggerd_stub",
+		"libbionic_tests_headers_posix",
+		"libc_dns",
 	}
+
+	// Used for quicker lookups
+	bp2buildModuleDoNotConvert = map[string]bool{}
 )
 
+func init() {
+	for _, moduleName := range bp2buildModuleDoNotConvertList {
+		bp2buildModuleDoNotConvert[moduleName] = true
+	}
+}
+
 // ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
 func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionPathContext) bool {
 	if bp2buildModuleDoNotConvert[ctx.Module().Name()] {
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 0595d68..45dfbaa 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -344,73 +344,39 @@
 # This file is generated by soong_build. Do not edit.
 #####################################################
 
-def _x86_64_transition_impl(settings, attr):
+def _config_node_transition_impl(settings, attr):
     return {
-        "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_x86_64",
+        "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_%s" % attr.arch,
     }
 
-def _x86_transition_impl(settings, attr):
-    return {
-        "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_x86",
-    }
-
-def _arm64_transition_impl(settings, attr):
-    return {
-        "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_arm64",
-    }
-
-def _arm_transition_impl(settings, attr):
-    return {
-        "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_arm",
-    }
-
-x86_64_transition = transition(
-    implementation = _x86_64_transition_impl,
+_config_node_transition = transition(
+    implementation = _config_node_transition_impl,
     inputs = [],
     outputs = [
         "//command_line_option:platforms",
     ],
 )
 
-x86_transition = transition(
-    implementation = _x86_transition_impl,
-    inputs = [],
-    outputs = [
-        "//command_line_option:platforms",
-    ],
+def _passthrough_rule_impl(ctx):
+    return [DefaultInfo(files = depset(ctx.files.deps))]
+
+config_node = rule(
+    implementation = _passthrough_rule_impl,
+    attrs = {
+        "arch" : attr.string(mandatory = True),
+        "deps" : attr.label_list(cfg = _config_node_transition),
+        "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
+    },
 )
 
-arm64_transition = transition(
-    implementation = _arm64_transition_impl,
-    inputs = [],
-    outputs = [
-        "//command_line_option:platforms",
-    ],
-)
-
-arm_transition = transition(
-    implementation = _arm_transition_impl,
-    inputs = [],
-    outputs = [
-        "//command_line_option:platforms",
-    ],
-)
-
-def _mixed_build_root_impl(ctx):
-    all_files = ctx.files.deps_x86_64 + ctx.files.deps_x86 + ctx.files.deps_arm64 + ctx.files.deps_arm
-    return [DefaultInfo(files = depset(all_files))]
 
 # Rule representing the root of the build, to depend on all Bazel targets that
 # are required for the build. Building this target will build the entire Bazel
 # build tree.
 mixed_build_root = rule(
-    implementation = _mixed_build_root_impl,
+    implementation = _passthrough_rule_impl,
     attrs = {
-        "deps_x86_64" : attr.label_list(cfg = x86_64_transition),
-        "deps_x86" : attr.label_list(cfg = x86_transition),
-        "deps_arm64" : attr.label_list(cfg = arm64_transition),
-        "deps_arm" : attr.label_list(cfg = arm_transition),
-        "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
+        "deps" : attr.label_list(),
     },
 )
 
@@ -446,44 +412,42 @@
 	// architecture mapping.
 	formatString := `
 # This file is generated by soong_build. Do not edit.
-load(":main.bzl", "mixed_build_root", "phony_root")
+load(":main.bzl", "config_node", "mixed_build_root", "phony_root")
+
+%s
 
 mixed_build_root(name = "buildroot",
-    deps_x86_64 = [%s],
-    deps_x86 = [%s],
-    deps_arm64 = [%s],
-    deps_arm = [%s],
+    deps = [%s],
 )
 
 phony_root(name = "phonyroot",
     deps = [":buildroot"],
 )
 `
-	var deps_x86_64 []string = nil
-	var deps_x86 []string = nil
-	var deps_arm64 []string = nil
-	var deps_arm []string = nil
+	configNodeFormatString := `
+config_node(name = "%s",
+    arch = "%s",
+    deps = [%s],
+)
+`
+
+	configNodesSection := ""
+
+	labelsByArch := map[string][]string{}
 	for val, _ := range context.requests {
 		labelString := fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label))
-		switch getArchString(val) {
-		case "x86_64":
-			deps_x86_64 = append(deps_x86_64, labelString)
-		case "x86":
-			deps_x86 = append(deps_x86, labelString)
-		case "arm64":
-			deps_arm64 = append(deps_arm64, labelString)
-		case "arm":
-			deps_arm = append(deps_arm, labelString)
-		default:
-			panic(fmt.Sprintf("unhandled architecture %s for %v", getArchString(val), val))
-		}
+		archString := getArchString(val)
+		labelsByArch[archString] = append(labelsByArch[archString], labelString)
 	}
 
-	return []byte(fmt.Sprintf(formatString,
-		strings.Join(deps_x86_64, ",\n            "),
-		strings.Join(deps_x86, ",\n            "),
-		strings.Join(deps_arm64, ",\n            "),
-		strings.Join(deps_arm, ",\n            ")))
+	configNodeLabels := []string{}
+	for archString, labels := range labelsByArch {
+		configNodeLabels = append(configNodeLabels, fmt.Sprintf("\":%s\"", archString))
+		labelsString := strings.Join(labels, ",\n            ")
+		configNodesSection += fmt.Sprintf(configNodeFormatString, archString, archString, labelsString)
+	}
+
+	return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(configNodeLabels, ",\n            ")))
 }
 
 func indent(original string) string {
diff --git a/android/paths.go b/android/paths.go
index db9e06a..ba1ab11 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -286,9 +286,9 @@
 	return p.path
 }
 
-// RelativeToPath returns an OptionalPath with the path that was embedded having been replaced by
-// the result of calling Path.RelativeToPath on it.
-func (p OptionalPath) RelativeToPath() OptionalPath {
+// RelativeToTop returns an OptionalPath with the path that was embedded having been replaced by the
+// result of calling Path.RelativeToTop on it.
+func (p OptionalPath) RelativeToTop() OptionalPath {
 	if !p.valid {
 		return p
 	}
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index 9c5ca41..d2a7d8d 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -645,7 +645,7 @@
 		rspFile := "out/soong/.intermediates/foo/rsp"
 		rspFile2 := "out/soong/.intermediates/foo/rsp2"
 		module := result.ModuleForTests("foo", "")
-		check(t, module.Rule("rule").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
+		check(t, module.Rule("rule"), module.Output(rspFile2),
 			"cp bar "+outFile+" @"+rspFile+" @"+rspFile2,
 			outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
 	})
@@ -662,7 +662,7 @@
 		cmd := `rm -rf ` + outDir + `/gen && ` +
 			sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
 		module := result.ModuleForTests("foo_sbox", "")
-		check(t, module.Output("gen/foo_sbox").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
+		check(t, module.Output("gen/foo_sbox"), module.Output(rspFile2),
 			cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
 	})
 	t.Run("sbox_inputs", func(t *testing.T) {
@@ -679,7 +679,7 @@
 			sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
 
 		module := result.ModuleForTests("foo_sbox_inputs", "")
-		check(t, module.Output("gen/foo_sbox_inputs").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
+		check(t, module.Output("gen/foo_sbox_inputs"), module.Output(rspFile2),
 			cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
 	})
 	t.Run("singleton", func(t *testing.T) {
@@ -687,7 +687,7 @@
 		rspFile := filepath.Join("out/soong/singleton/rsp")
 		rspFile2 := filepath.Join("out/soong/singleton/rsp2")
 		singleton := result.SingletonForTests("rule_builder_test")
-		check(t, singleton.Rule("rule").RelativeToTop(), singleton.Output(rspFile2).RelativeToTop(),
+		check(t, singleton.Rule("rule"), singleton.Output(rspFile2),
 			"cp bar "+outFile+" @"+rspFile+" @"+rspFile2,
 			outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
 	})
diff --git a/android/testing.go b/android/testing.go
index f4f5c98..ce27fca 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -551,6 +551,8 @@
 //   * CommandOrderOnly
 //
 // See PathRelativeToTop for more details.
+//
+// deprecated: this is no longer needed as TestingBuildParams are created in this form.
 func (p TestingBuildParams) RelativeToTop() TestingBuildParams {
 	// If this is not a valid params then just return it back. That will make it easy to use with the
 	// Maybe...() methods.
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 11b23c6..407faa1 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -485,7 +485,7 @@
 		}
 	`)
 
-	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule").RelativeToTop()
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
 
 	// Make sure that Android.mk is created
 	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
@@ -2498,7 +2498,7 @@
 
 	vendorVariant := "android_vendor.VER_arm64_armv8-a"
 
-	ldRule := ctx.ModuleForTests("mybin", vendorVariant+"_apex10000").Rule("ld").RelativeToTop()
+	ldRule := ctx.ModuleForTests("mybin", vendorVariant+"_apex10000").Rule("ld")
 	libs := names(ldRule.Args["libFlags"])
 	// VNDK libs(libvndk/libc++) as they are
 	ensureListContains(t, libs, "out/soong/.intermediates/libvndk/"+vendorVariant+"_shared/libvndk.so")
@@ -5066,7 +5066,7 @@
 	}
 	// JNI libraries including transitive deps are
 	for _, jni := range []string{"libjni", "libfoo"} {
-		jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile().RelativeToPath()
+		jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile().RelativeToTop()
 		// ... embedded inside APK (jnilibs.zip)
 		ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
 		// ... and not directly inside the APEX
@@ -6849,7 +6849,7 @@
 	`)
 
 	ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) {
-		ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").RelativeToTop().Args["libFlags"], " ")
+		ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").Args["libFlags"], " ")
 		mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) })
 		android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags)
 	}
@@ -6907,7 +6907,7 @@
 	`)
 
 	ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) {
-		ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").RelativeToTop().Args["libFlags"], " ")
+		ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").Args["libFlags"], " ")
 		mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) })
 		android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags)
 	}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index d48d975..e93b3dc 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -568,6 +568,13 @@
 
 func escapeString(s string) string {
 	s = strings.ReplaceAll(s, "\\", "\\\\")
+
+	// b/184026959: Reverse the application of some common control sequences.
+	// These must be generated literally in the BUILD file.
+	s = strings.ReplaceAll(s, "\t", "\\t")
+	s = strings.ReplaceAll(s, "\n", "\\n")
+	s = strings.ReplaceAll(s, "\r", "\\r")
+
 	return strings.ReplaceAll(s, "\"", "\\\"")
 }
 
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index ad88e97..49897b3 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -241,6 +241,22 @@
     string_prop = "a",
 )`,
 		},
+		{
+			bp: `custom {
+	name: "control_characters",
+    string_list_prop: ["\t", "\n"],
+    string_prop: "a\t\n\r",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTarget: `custom(
+    name = "control_characters",
+    string_list_prop = [
+        "\t",
+        "\n",
+    ],
+    string_prop = "a\t\n\r",
+)`,
+		},
 	}
 
 	dir := "."
diff --git a/cc/library.go b/cc/library.go
index 28e4f61..f459e80 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -504,12 +504,11 @@
 			return
 		}
 		isLibcxx := strings.HasPrefix(dir, "external/libcxx/include")
-		j := 0
-		for i, header := range glob {
+		for _, header := range glob {
 			if isLibcxx {
 				// Glob all files under this special directory, because of C++ headers with no
 				// extension.
-				if !strings.HasSuffix(header, "/") {
+				if strings.HasSuffix(header, "/") {
 					continue
 				}
 			} else {
@@ -525,12 +524,8 @@
 					continue
 				}
 			}
-			if i != j {
-				glob[j] = glob[i]
-			}
-			j++
+			ret = append(ret, android.PathForSource(ctx, header))
 		}
-		glob = glob[:j]
 	}
 
 	// Collect generated headers
diff --git a/cc/proto_test.go b/cc/proto_test.go
index 3d636fb..b9c89c7 100644
--- a/cc/proto_test.go
+++ b/cc/proto_test.go
@@ -61,7 +61,7 @@
 			t.Errorf("expected %q in %q", w, cmd)
 		}
 
-		foobarPath := foobar.Module().(android.HostToolProvider).HostToolPath().RelativeToPath().String()
+		foobarPath := foobar.Module().(android.HostToolProvider).HostToolPath().RelativeToTop().String()
 
 		if w := "--plugin=protoc-gen-foobar=" + foobarPath; !strings.Contains(cmd, w) {
 			t.Errorf("expected %q in %q", w, cmd)
diff --git a/java/app_test.go b/java/app_test.go
index 825ad20..a99ac62 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -652,7 +652,7 @@
 			} else {
 				aapt2link = m.Output("package-res.apk")
 			}
-			aapt2link = aapt2link.RelativeToTop()
+			aapt2link = aapt2link
 			aapt2Flags := aapt2link.Args["flags"]
 			if test.assetFlag != "" {
 				android.AssertStringDoesContain(t, "asset flag", aapt2Flags, test.assetFlag)
@@ -1993,14 +1993,14 @@
 		`)
 
 	// Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
-	javac := ctx.ModuleForTests("baz", "android_common").Rule("javac").RelativeToTop()
+	javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
 	fooTurbine := "out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar"
 	if !strings.Contains(javac.Args["classpath"], fooTurbine) {
 		t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
 	}
 
 	// Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
-	javac = ctx.ModuleForTests("qux", "android_common").Rule("javac").RelativeToTop()
+	javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
 	barTurbine := "out/soong/.intermediates/foo/android_common_bar/turbine-combined/foo.jar"
 	if !strings.Contains(javac.Args["classpath"], barTurbine) {
 		t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
@@ -2077,7 +2077,7 @@
 		}
 
 		// Check if javac classpath has the correct jar file path. This checks instrumentation_for overrides.
-		javac := variant.Rule("javac").RelativeToTop()
+		javac := variant.Rule("javac")
 		turbine := filepath.Join("out", "soong", ".intermediates", "foo", expected.targetVariant, "turbine-combined", "foo.jar")
 		if !strings.Contains(javac.Args["classpath"], turbine) {
 			t.Errorf("classpath %q does not contain %q", javac.Args["classpath"], turbine)
@@ -2151,7 +2151,7 @@
 
 	for _, test := range testCases {
 		variant := ctx.ModuleForTests(test.moduleName, test.variantName)
-		params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml").RelativeToTop()
+		params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml")
 
 		if len(test.expectedFlags) > 0 {
 			if params.Rule == nil {
@@ -2647,14 +2647,14 @@
 		t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs)
 	}
 	// aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets.
-	res := foo.Output("package-res.apk").RelativeToTop()
+	res := foo.Output("package-res.apk")
 	aapt2Flags := res.Args["flags"]
 	e := "-A out/soong/.intermediates/foo/android_common/NOTICE"
 	android.AssertStringDoesContain(t, "expected.apkPath", aapt2Flags, e)
 
 	// bar has NOTICE files to process, but embed_notices is not set.
 	bar := result.ModuleForTests("bar", "android_common")
-	res = bar.Output("package-res.apk").RelativeToTop()
+	res = bar.Output("package-res.apk")
 	aapt2Flags = res.Args["flags"]
 	e = "-A out/soong/.intermediates/bar/android_common/NOTICE"
 	android.AssertStringDoesNotContain(t, "bar shouldn't have the asset dir flag for NOTICE", aapt2Flags, e)
diff --git a/java/droiddoc.go b/java/droiddoc.go
index a8e2b0e..f7595b1 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -226,11 +226,8 @@
 	srcJars     android.Paths
 	srcFiles    android.Paths
 	sourcepaths android.Paths
-	argFiles    android.Paths
 	implicits   android.Paths
 
-	args []string
-
 	docZip      android.WritablePath
 	stubsSrcJar android.WritablePath
 }
@@ -480,15 +477,20 @@
 		j.sourcepaths = android.PathsForModuleSrc(ctx, []string{"."})
 	}
 
-	j.argFiles = android.PathsForModuleSrc(ctx, j.properties.Arg_files)
+	return deps
+}
+
+func (j *Javadoc) expandArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
+	var argFiles android.Paths
 	argFilesMap := map[string]string{}
 	argFileLabels := []string{}
 
 	for _, label := range j.properties.Arg_files {
 		var paths = android.PathsForModuleSrc(ctx, []string{label})
 		if _, exists := argFilesMap[label]; !exists {
-			argFilesMap[label] = strings.Join(paths.Strings(), " ")
+			argFilesMap[label] = strings.Join(cmd.PathsForInputs(paths), " ")
 			argFileLabels = append(argFileLabels, label)
+			argFiles = append(argFiles, paths...)
 		} else {
 			ctx.ModuleErrorf("multiple arg_files for %q, %q and %q",
 				label, argFilesMap[label], paths)
@@ -508,7 +510,7 @@
 	}
 
 	for _, flag := range flags {
-		args, err := android.Expand(flag, func(name string) (string, error) {
+		expanded, err := android.Expand(flag, func(name string) (string, error) {
 			if strings.HasPrefix(name, "location ") {
 				label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
 				if paths, ok := argFilesMap[label]; ok {
@@ -526,10 +528,10 @@
 		if err != nil {
 			ctx.PropertyErrorf(argsPropertyName, "%s", err.Error())
 		}
-		j.args = append(j.args, args)
+		cmd.Flag(expanded)
 	}
 
-	return deps
+	cmd.Implicits(argFiles)
 }
 
 func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -563,6 +565,8 @@
 		Flag("-XDignore.symbol.file").
 		Flag("-Xdoclint:none")
 
+	j.expandArgs(ctx, cmd)
+
 	rule.Command().
 		BuiltTool("soong_zip").
 		Flag("-write_if_changed").
@@ -821,7 +825,7 @@
 			deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
 	}
 
-	cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles)
+	d.expandArgs(ctx, cmd)
 
 	if d.properties.Compat_config != nil {
 		compatConfig := android.PathForModuleSrc(ctx, String(d.properties.Compat_config))
diff --git a/java/droiddoc_test.go b/java/droiddoc_test.go
index 2b324ae..8d1f591 100644
--- a/java/droiddoc_test.go
+++ b/java/droiddoc_test.go
@@ -80,7 +80,7 @@
 
 	barStubsOutput := barStubsOutputs[0]
 	barDoc := ctx.ModuleForTests("bar-doc", "android_common")
-	javaDoc := barDoc.Rule("javadoc").RelativeToTop()
+	javaDoc := barDoc.Rule("javadoc")
 	if g, w := android.PathsRelativeToTop(javaDoc.Implicits), android.PathRelativeToTop(barStubsOutput); !inList(w, g) {
 		t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g)
 	}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index e453e62..d7a0668 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -284,7 +284,7 @@
 		cmd.Flag("--include-annotations")
 
 		validatingNullability :=
-			android.InList("--validate-nullability-from-merged-stubs", d.Javadoc.args) ||
+			strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
 				String(d.properties.Validate_nullability_from_list) != ""
 
 		migratingNullability := String(d.properties.Previous_api) != ""
@@ -360,7 +360,16 @@
 	ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
 		if t, ok := m.(*ExportedDroiddocDir); ok {
 			for _, dep := range t.deps {
-				if strings.HasSuffix(dep.String(), filename) {
+				if dep.Base() == filename {
+					cmd.Implicit(dep)
+				}
+				if filename != "android.jar" && dep.Base() == "android.jar" {
+					// Metalava implicitly searches these patterns:
+					//  prebuilts/tools/common/api-versions/android-%/android.jar
+					//  prebuilts/sdk/%/public/android.jar
+					// Add android.jar files from the api_levels_annotations_dirs directories to try
+					// to satisfy these patterns.  If Metalava can't find a match for an API level
+					// between 1 and 28 in at least one pattern it will fail.
 					cmd.Implicit(dep)
 				}
 			}
@@ -473,7 +482,7 @@
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 
-	sandbox := proptools.Bool(d.Javadoc.properties.Sandbox)
+	sandbox := proptools.BoolDefault(d.Javadoc.properties.Sandbox, true)
 	if sandbox {
 		rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
 			android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
@@ -509,14 +518,8 @@
 	d.inclusionAnnotationsFlags(ctx, cmd)
 	d.apiLevelsAnnotationsFlags(ctx, cmd)
 
-	if android.InList("--generate-documentation", d.Javadoc.args) {
-		// Currently Metalava have the ability to invoke Javadoc in a separate process.
-		// Pass "-nodocs" to suppress the Javadoc invocation when Metalava receives
-		// "--generate-documentation" arg. This is not needed when Metalava removes this feature.
-		d.Javadoc.args = append(d.Javadoc.args, "-nodocs")
-	}
+	d.expandArgs(ctx, cmd)
 
-	cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles)
 	for _, o := range d.Javadoc.properties.Out {
 		cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
 	}
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index c6db979..f8125fb 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -34,6 +34,7 @@
 			srcs: ["bar-doc/a.java"],
 			api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
 			api_levels_annotations_enabled: true,
+			sandbox: false,
 		}
 
 		droidstubs {
@@ -43,6 +44,7 @@
 			api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
 			api_levels_annotations_enabled: true,
 			api_levels_jar_filename: "android.other.jar",
+			sandbox: false,
 		}
 		`,
 		map[string][]byte{
@@ -81,10 +83,19 @@
 
 func TestDroidstubsSandbox(t *testing.T) {
 	ctx, _ := testJavaWithFS(t, `
+		genrule {
+			name: "foo",
+			out: ["foo.txt"],
+			cmd: "touch $(out)",
+		}
+
 		droidstubs {
 			name: "bar-stubs",
 			srcs: ["bar-doc/a.java"],
 			sandbox: true,
+
+			args: "--reference $(location :foo)",
+			arg_files: [":foo"],
 		}
 		`,
 		map[string][]byte{
@@ -96,6 +107,11 @@
 	if g, w := metalava.Inputs.Strings(), []string{"bar-doc/a.java"}; !reflect.DeepEqual(w, g) {
 		t.Errorf("Expected inputs %q, got %q", w, g)
 	}
+
+	manifest := android.RuleBuilderSboxProtoForTests(t, m.Output("metalava.sbox.textproto"))
+	if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
+		t.Errorf("Expected command to contain %q, got %q", w, g)
+	}
 }
 
 func TestDroidstubsWithSystemModules(t *testing.T) {
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index d6c6a2d..dc4e8aa 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -50,7 +50,7 @@
 	`)
 
 	hiddenAPI := result.SingletonForTests("hiddenapi")
-	hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
 	want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
 	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
 }
@@ -145,7 +145,7 @@
 	`)
 
 	hiddenAPI := result.SingletonForTests("hiddenapi")
-	hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
 	want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
 	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
 }
@@ -169,7 +169,7 @@
 	`)
 
 	hiddenAPI := result.SingletonForTests("hiddenapi")
-	hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
 	fromSourceJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
 	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, fromSourceJarArg)
 
@@ -196,7 +196,7 @@
 	`)
 
 	hiddenAPI := result.SingletonForTests("hiddenapi")
-	hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
 	prebuiltJarArg := "--boot-dex=out/soong/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
 	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, prebuiltJarArg)
 
@@ -244,7 +244,7 @@
 			).RunTest(t)
 
 			hiddenAPI := result.SingletonForTests("hiddenapi")
-			hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+			hiddenapiRule := hiddenAPI.Rule("hiddenapi")
 			wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild)
 			android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantPublicStubs)
 
@@ -307,7 +307,7 @@
 	cpRule := hiddenAPI.Rule("Cp")
 	actualCpInput := cpRule.BuildParams.Input
 	actualCpOutput := cpRule.BuildParams.Output
-	encodeDexRule := foo.Rule("hiddenAPIEncodeDex").RelativeToTop()
+	encodeDexRule := foo.Rule("hiddenAPIEncodeDex")
 	actualFlagsCsv := encodeDexRule.BuildParams.Args["flagsCsv"]
 
 	android.AssertPathRelativeToTopEquals(t, "hiddenapi cp rule input", expectedCpInput, actualCpInput)
diff --git a/java/java_test.go b/java/java_test.go
index 1d1a796..d1d26ba 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -250,7 +250,7 @@
 		}
 	`)
 
-	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac").RelativeToTop()
+	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
 	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
 
 	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
@@ -976,7 +976,7 @@
 		}
 		`)
 
-	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac").RelativeToTop()
+	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
 	combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
 
 	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
@@ -1336,11 +1336,11 @@
 		}
 		`)
 
-	fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine").RelativeToTop()
-	barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine").RelativeToTop()
-	barJavac := result.ModuleForTests("bar", "android_common").Rule("javac").RelativeToTop()
-	barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine").RelativeToTop()
-	bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac").RelativeToTop()
+	fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine")
+	barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine")
+	barJavac := result.ModuleForTests("bar", "android_common").Rule("javac")
+	barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine")
+	bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
 
 	android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs)
 
@@ -1363,7 +1363,7 @@
 
 	barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
 	for i := 0; i < 3; i++ {
-		barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i)).RelativeToTop()
+		barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i))
 		if !strings.Contains(barJavac.Args["classpath"], barHeaderJar) {
 			t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], barHeaderJar)
 		}
diff --git a/java/rro_test.go b/java/rro_test.go
index 0a10d93..bad60bc 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -68,7 +68,7 @@
 	m := result.ModuleForTests("foo", "android_common")
 
 	// Check AAPT2 link flags.
-	aapt2Flags := m.Output("package-res.apk").RelativeToTop().Args["flags"]
+	aapt2Flags := m.Output("package-res.apk").Args["flags"]
 	expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
 	absentFlags := android.RemoveListFromList(expectedFlags, strings.Split(aapt2Flags, " "))
 	if len(absentFlags) > 0 {
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 028c4fe..e1ec41b 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -313,10 +313,10 @@
 
 			checkClasspath := func(t *testing.T, result *android.TestResult, isJava8 bool) {
 				foo := result.ModuleForTests("foo", variant)
-				javac := foo.Rule("javac").RelativeToTop()
+				javac := foo.Rule("javac")
 				var deps []string
 
-				aidl := foo.MaybeRule("aidl").RelativeToTop()
+				aidl := foo.MaybeRule("aidl")
 				if aidl.Rule != nil {
 					deps = append(deps, android.PathRelativeToTop(aidl.Output))
 				}
@@ -376,7 +376,7 @@
 				checkClasspath(t, result, true /* isJava8 */)
 
 				if testcase.host != android.Host {
-					aidl := result.ModuleForTests("foo", variant).Rule("aidl").RelativeToTop()
+					aidl := result.ModuleForTests("foo", variant).Rule("aidl")
 
 					android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.")
 				}
@@ -389,7 +389,7 @@
 				checkClasspath(t, result, false /* isJava8 */)
 
 				if testcase.host != android.Host {
-					aidl := result.ModuleForTests("foo", variant).Rule("aidl").RelativeToTop()
+					aidl := result.ModuleForTests("foo", variant).Rule("aidl")
 
 					android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.")
 				}