Merge "Rename stubsjar to stubsSrcjar for droiddoc"
diff --git a/android/config.go b/android/config.go
index b158e05..db833ec 100644
--- a/android/config.go
+++ b/android/config.go
@@ -649,6 +649,14 @@
 	return arches
 }
 
+func (c *deviceConfig) BinderBitness() string {
+	is32BitBinder := c.config.ProductVariables.Binder32bit
+	if is32BitBinder != nil && *is32BitBinder {
+		return "32"
+	}
+	return "64"
+}
+
 func (c *deviceConfig) VendorPath() string {
 	if c.config.ProductVariables.VendorPath != nil {
 		return *c.config.ProductVariables.VendorPath
diff --git a/android/paths.go b/android/paths.go
index cf5544d..3605dcf 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -800,8 +800,8 @@
 	if len(arches) == 0 {
 		panic("device build with no primary arch")
 	}
-	primary_arch := arches[0].ArchType.String()
-	refDumpFileStr := "prebuilts/abi-dumps/" + vndkOrNdkDir + "/" + version + "/" + primary_arch + "/" +
+	binderBitness := ctx.DeviceConfig().BinderBitness()
+	refDumpFileStr := "prebuilts/abi-dumps/" + vndkOrNdkDir + "/" + version + "/" + binderBitness + "/" +
 		archNameAndVariant + "/" + sourceOrBinaryDir + "/" + fileName + ext
 	return ExistentPathForSource(ctx, refDumpFileStr)
 }
diff --git a/android/util.go b/android/util.go
index 854d782..e9b9764 100644
--- a/android/util.go
+++ b/android/util.go
@@ -101,11 +101,18 @@
 
 func RemoveFromList(s string, list []string) (bool, []string) {
 	i := IndexList(s, list)
-	if i != -1 {
-		return true, append(list[:i], list[i+1:]...)
-	} else {
+	if i == -1 {
 		return false, list
 	}
+
+	result := make([]string, 0, len(list)-1)
+	result = append(result, list[:i]...)
+	for _, l := range list[i+1:] {
+		if l != s {
+			result = append(result, l)
+		}
+	}
+	return true, result
 }
 
 // FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
diff --git a/android/util_test.go b/android/util_test.go
index 32f92b4..1c791b2 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -118,3 +118,244 @@
 		}
 	}
 }
+
+func TestJoinWithPrefix(t *testing.T) {
+	testcases := []struct {
+		name     string
+		input    []string
+		expected string
+	}{
+		{
+			name:     "zero_inputs",
+			input:    []string{},
+			expected: "",
+		},
+		{
+			name:     "one_input",
+			input:    []string{"a"},
+			expected: "prefix:a",
+		},
+		{
+			name:     "two_inputs",
+			input:    []string{"a", "b"},
+			expected: "prefix:a prefix:b",
+		},
+	}
+
+	prefix := "prefix:"
+
+	for _, testCase := range testcases {
+		t.Run(testCase.name, func(t *testing.T) {
+			out := JoinWithPrefix(testCase.input, prefix)
+			if out != testCase.expected {
+				t.Errorf("incorrect output:")
+				t.Errorf("     input: %#v", testCase.input)
+				t.Errorf("    prefix: %#v", prefix)
+				t.Errorf("  expected: %#v", testCase.expected)
+				t.Errorf("       got: %#v", out)
+			}
+		})
+	}
+}
+
+func TestIndexList(t *testing.T) {
+	input := []string{"a", "b", "c"}
+
+	testcases := []struct {
+		key      string
+		expected int
+	}{
+		{
+			key:      "a",
+			expected: 0,
+		},
+		{
+			key:      "b",
+			expected: 1,
+		},
+		{
+			key:      "c",
+			expected: 2,
+		},
+		{
+			key:      "X",
+			expected: -1,
+		},
+	}
+
+	for _, testCase := range testcases {
+		t.Run(testCase.key, func(t *testing.T) {
+			out := IndexList(testCase.key, input)
+			if out != testCase.expected {
+				t.Errorf("incorrect output:")
+				t.Errorf("       key: %#v", testCase.key)
+				t.Errorf("     input: %#v", input)
+				t.Errorf("  expected: %#v", testCase.expected)
+				t.Errorf("       got: %#v", out)
+			}
+		})
+	}
+}
+
+func TestInList(t *testing.T) {
+	input := []string{"a"}
+
+	testcases := []struct {
+		key      string
+		expected bool
+	}{
+		{
+			key:      "a",
+			expected: true,
+		},
+		{
+			key:      "X",
+			expected: false,
+		},
+	}
+
+	for _, testCase := range testcases {
+		t.Run(testCase.key, func(t *testing.T) {
+			out := InList(testCase.key, input)
+			if out != testCase.expected {
+				t.Errorf("incorrect output:")
+				t.Errorf("       key: %#v", testCase.key)
+				t.Errorf("     input: %#v", input)
+				t.Errorf("  expected: %#v", testCase.expected)
+				t.Errorf("       got: %#v", out)
+			}
+		})
+	}
+}
+
+func TestPrefixInList(t *testing.T) {
+	prefixes := []string{"a", "b"}
+
+	testcases := []struct {
+		str      string
+		expected bool
+	}{
+		{
+			str:      "a-example",
+			expected: true,
+		},
+		{
+			str:      "b-example",
+			expected: true,
+		},
+		{
+			str:      "X-example",
+			expected: false,
+		},
+	}
+
+	for _, testCase := range testcases {
+		t.Run(testCase.str, func(t *testing.T) {
+			out := PrefixInList(testCase.str, prefixes)
+			if out != testCase.expected {
+				t.Errorf("incorrect output:")
+				t.Errorf("       str: %#v", testCase.str)
+				t.Errorf("  prefixes: %#v", prefixes)
+				t.Errorf("  expected: %#v", testCase.expected)
+				t.Errorf("       got: %#v", out)
+			}
+		})
+	}
+}
+
+func TestFilterList(t *testing.T) {
+	input := []string{"a", "b", "c", "c", "b", "d", "a"}
+	filter := []string{"a", "c"}
+	remainder, filtered := FilterList(input, filter)
+
+	expected := []string{"b", "b", "d"}
+	if !reflect.DeepEqual(remainder, expected) {
+		t.Errorf("incorrect remainder output:")
+		t.Errorf("     input: %#v", input)
+		t.Errorf("    filter: %#v", filter)
+		t.Errorf("  expected: %#v", expected)
+		t.Errorf("       got: %#v", remainder)
+	}
+
+	expected = []string{"a", "c", "c", "a"}
+	if !reflect.DeepEqual(filtered, expected) {
+		t.Errorf("incorrect filtered output:")
+		t.Errorf("     input: %#v", input)
+		t.Errorf("    filter: %#v", filter)
+		t.Errorf("  expected: %#v", expected)
+		t.Errorf("       got: %#v", filtered)
+	}
+}
+
+func TestRemoveListFromList(t *testing.T) {
+	input := []string{"a", "b", "c", "d", "a", "c", "d"}
+	filter := []string{"a", "c"}
+	expected := []string{"b", "d", "d"}
+	out := RemoveListFromList(input, filter)
+	if !reflect.DeepEqual(out, expected) {
+		t.Errorf("incorrect output:")
+		t.Errorf("     input: %#v", input)
+		t.Errorf("    filter: %#v", filter)
+		t.Errorf("  expected: %#v", expected)
+		t.Errorf("       got: %#v", out)
+	}
+}
+
+func TestRemoveFromList(t *testing.T) {
+	testcases := []struct {
+		name          string
+		key           string
+		input         []string
+		expectedFound bool
+		expectedOut   []string
+	}{
+		{
+			name:          "remove_one_match",
+			key:           "a",
+			input:         []string{"a", "b", "c"},
+			expectedFound: true,
+			expectedOut:   []string{"b", "c"},
+		},
+		{
+			name:          "remove_three_matches",
+			key:           "a",
+			input:         []string{"a", "b", "a", "c", "a"},
+			expectedFound: true,
+			expectedOut:   []string{"b", "c"},
+		},
+		{
+			name:          "remove_zero_matches",
+			key:           "X",
+			input:         []string{"a", "b", "a", "c", "a"},
+			expectedFound: false,
+			expectedOut:   []string{"a", "b", "a", "c", "a"},
+		},
+		{
+			name:          "remove_all_matches",
+			key:           "a",
+			input:         []string{"a", "a", "a", "a"},
+			expectedFound: true,
+			expectedOut:   []string{},
+		},
+	}
+
+	for _, testCase := range testcases {
+		t.Run(testCase.name, func(t *testing.T) {
+			found, out := RemoveFromList(testCase.key, testCase.input)
+			if found != testCase.expectedFound {
+				t.Errorf("incorrect output:")
+				t.Errorf("       key: %#v", testCase.key)
+				t.Errorf("     input: %#v", testCase.input)
+				t.Errorf("  expected: %#v", testCase.expectedFound)
+				t.Errorf("       got: %#v", found)
+			}
+			if !reflect.DeepEqual(out, testCase.expectedOut) {
+				t.Errorf("incorrect output:")
+				t.Errorf("       key: %#v", testCase.key)
+				t.Errorf("     input: %#v", testCase.input)
+				t.Errorf("  expected: %#v", testCase.expectedOut)
+				t.Errorf("       got: %#v", out)
+			}
+		})
+	}
+}
diff --git a/cc/cc.go b/cc/cc.go
index ebc98ac..4d26e84 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1423,6 +1423,7 @@
 		&VndkProperties{},
 		&LTOProperties{},
 		&PgoProperties{},
+		&android.ProtoProperties{},
 	)
 
 	android.InitDefaultsModule(module)
diff --git a/java/builder.go b/java/builder.go
index b8f8351..6d894a3 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -104,10 +104,9 @@
 
 	turbine = pctx.AndroidStaticRule("turbine",
 		blueprint.RuleParams{
-			Command: `rm -rf "$outDir" "$srcJarDir" && mkdir -p "$outDir" "$srcJarDir" && ` +
-				`${config.ExtractSrcJarsCmd} $srcJarDir $srcJarDir/list $srcJars && ` +
+			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
 				`${config.JavaCmd} -jar ${config.TurbineJar} --output $out.tmp ` +
-				`--temp_dir "$outDir" --sources @$out.rsp @$srcJarDir/list ` +
+				`--temp_dir "$outDir" --sources @$out.rsp  --source_jars $srcJars ` +
 				`--javacopts ${config.CommonJdkFlags} ` +
 				`$javacFlags -source $javaVersion -target $javaVersion $bootClasspath $classpath && ` +
 				`${config.Ziptime} $out.tmp && ` +
@@ -116,14 +115,12 @@
 				"${config.TurbineJar}",
 				"${config.JavaCmd}",
 				"${config.Ziptime}",
-				"${config.ExtractSrcJarsCmd}",
 			},
 			Rspfile:        "$out.rsp",
 			RspfileContent: "$in",
 			Restat:         true,
 		},
-		"javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir",
-		"outDir", "javaVersion")
+		"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion")
 
 	jar = pctx.AndroidStaticRule("jar",
 		blueprint.RuleParams{
@@ -258,7 +255,6 @@
 			"javacFlags":    flags.javacFlags,
 			"bootClasspath": bootClasspath,
 			"srcJars":       strings.Join(srcJars.Strings(), " "),
-			"srcJarDir":     android.PathForModuleOut(ctx, "turbine", "srcjars").String(),
 			"classpath":     flags.classpath.FormJavaClassPath("--classpath"),
 			"outDir":        android.PathForModuleOut(ctx, "turbine", "classes").String(),
 			"javaVersion":   flags.javaVersion,
diff --git a/java/java.go b/java/java.go
index c4c07f7..92170e6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1280,6 +1280,7 @@
 	module.AddProperties(
 		&CompilerProperties{},
 		&CompilerDeviceProperties{},
+		&android.ProtoProperties{},
 	)
 
 	android.InitDefaultsModule(module)
diff --git a/ui/build/config.go b/ui/build/config.go
index 27ed8e9..a1b5bd4 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -115,6 +115,8 @@
 	// Tell python not to spam the source tree with .pyc files.
 	ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
 
+	ret.environ.Set("TMPDIR", absPath(ctx, ret.TempDir()))
+
 	// Precondition: the current directory is the top of the source tree
 	if _, err := os.Stat(srcDirFileCheck); err != nil {
 		if os.IsNotExist(err) {