Merge "Only pass "-Xgc:CMC" when building for Android."
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index 875dbab..2954f8b 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -14,10 +14,6 @@
 
 package genrule
 
-import (
-	"android/soong/android"
-)
-
 var (
 	DepfileAllowList = []string{
 		"depfile_allowed_for_test",
@@ -136,12 +132,3 @@
 		"external/perfetto",
 	}
 )
-var DepfileAllowSet = map[string]bool{}
-var SandboxingDenyModuleSet = map[string]bool{}
-var SandboxingDenyPathSet = map[string]bool{}
-
-func init() {
-	android.AddToStringSet(DepfileAllowSet, DepfileAllowList)
-	android.AddToStringSet(SandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...))
-	android.AddToStringSet(SandboxingDenyPathSet, SandboxingDenyPathList)
-}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index c830fcc..4992625 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -24,6 +24,7 @@
 	"path/filepath"
 	"strconv"
 	"strings"
+	"sync"
 
 	"android/soong/bazel/cquery"
 
@@ -60,6 +61,12 @@
 	PrepareForTestWithGenRuleBuildComponents,
 )
 
+var DepfileAllowSet map[string]bool
+var SandboxingDenyModuleSet map[string]bool
+var SandboxingDenyPathSet map[string]bool
+var SandboxingDenyModuleSetLock sync.Mutex
+var DepfileAllowSetLock sync.Mutex
+
 func RegisterGenruleBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
 
@@ -595,6 +602,12 @@
 	// Allowlist genrule to use depfile until we have a solution to remove it.
 	// TODO(b/235582219): Remove allowlist for genrule
 	if Bool(g.properties.Depfile) {
+		if DepfileAllowSet == nil {
+			DepfileAllowSetLock.Lock()
+			defer DepfileAllowSetLock.Unlock()
+			DepfileAllowSet = map[string]bool{}
+			android.AddToStringSet(DepfileAllowSet, DepfileAllowList)
+		}
 		// TODO(b/283852474): Checking the GenruleSandboxing flag is temporary in
 		// order to pass the presubmit before internal master is updated.
 		if ctx.DeviceConfig().GenruleSandboxing() && !DepfileAllowSet[g.Name()] {
@@ -1024,8 +1037,19 @@
 }
 
 func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder {
-	if !ctx.DeviceConfig().GenruleSandboxing() || SandboxingDenyPathSet[ctx.ModuleDir()] ||
-		SandboxingDenyModuleSet[ctx.ModuleName()] {
+	if !ctx.DeviceConfig().GenruleSandboxing() {
+		return r.SandboxTools()
+	}
+	if SandboxingDenyModuleSet == nil {
+		SandboxingDenyModuleSetLock.Lock()
+		defer SandboxingDenyModuleSetLock.Unlock()
+		SandboxingDenyModuleSet = map[string]bool{}
+		SandboxingDenyPathSet = map[string]bool{}
+		android.AddToStringSet(SandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...))
+		android.AddToStringSet(SandboxingDenyPathSet, SandboxingDenyPathList)
+	}
+
+	if SandboxingDenyPathSet[ctx.ModuleDir()] || SandboxingDenyModuleSet[ctx.ModuleName()] {
 		return r.SandboxTools()
 	}
 	return r.SandboxInputs()
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 8a521aa..d577b22 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -535,6 +535,10 @@
 		// b/223382732
 		FlagWithArg("--hide ", "ChangedDefault")
 
+	// Force metalava to ignore classes on the classpath when an API file contains missing classes.
+	// See b/285140653 for more information.
+	cmd.FlagWithArg("--api-class-resolution ", "api")
+
 	return cmd
 }
 
diff --git a/java/java.go b/java/java.go
index aa9f936..5bc378b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1728,6 +1728,10 @@
 		FlagWithArg("--hide ", "InvalidNullabilityOverride").
 		FlagWithArg("--hide ", "ChangedDefault")
 
+	// Force metalava to ignore classes on the classpath when an API file contains missing classes.
+	// See b/285140653 for more information.
+	cmd.FlagWithArg("--api-class-resolution ", "api")
+
 	return cmd
 }
 
diff --git a/rust/builder.go b/rust/builder.go
index 0aa2225..0dfaef4 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -261,7 +261,7 @@
 	// Disallow experimental features
 	modulePath := android.PathForModuleSrc(ctx).String()
 	if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
-		rustcFlags = append(rustcFlags, "-Zallow-features=\"custom_inner_attributes,mixed_integer_ops\"")
+		rustcFlags = append(rustcFlags, "-Zallow-features=\"\"")
 	}
 
 	// Collect linker flags
diff --git a/rust/config/global.go b/rust/config/global.go
index 748bb3d..60acc6e 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -51,9 +51,6 @@
 		// Use v0 mangling to distinguish from C++ symbols
 		"-C symbol-mangling-version=v0",
 		"--color always",
-		// TODO (b/267698452): Temporary workaround until the "no unstable
-		// features" policy is enforced.
-		"-A stable-features",
 		"-Zdylib-lto",
 	}
 
diff --git a/tests/genrule_sandbox_test.sh b/tests/genrule_sandbox_test.sh
new file mode 100755
index 0000000..21b476b
--- /dev/null
+++ b/tests/genrule_sandbox_test.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+
+# Copyright (C) 2023 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.
+
+set -e
+
+# Build the given genrule modules with GENRULE_SANDBOXING enabled and disabled,
+# then compare the output of the modules and report result.
+
+function die() { format=$1; shift; printf >&2 "$format\n" $@; exit 1; }
+
+function usage() {
+  die "usage: ${0##*/} <-t lunch_target> [module]..."
+}
+
+if [ ! -e "build/make/core/Makefile" ]; then
+  die "$0 must be run from the top of the Android source tree."
+fi
+
+declare TARGET=
+while getopts "t:" opt; do
+  case $opt in
+    t)
+      TARGET=$OPTARG ;;
+    *) usage ;;
+  esac
+done
+
+shift $((OPTIND-1))
+MODULES="$@"
+
+source build/envsetup.sh
+
+if [[ -n $TARGET ]]; then
+  lunch $TARGET
+fi
+
+if [[ -z ${OUT_DIR+x} ]]; then
+  OUT_DIR="out"
+fi
+
+OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)"
+PASS=true
+
+function cleanup {
+  if [ $PASS = true ]; then
+    rm -rf "${OUTPUT_DIR}"
+  fi
+}
+trap cleanup EXIT
+
+declare -A GEN_PATH_MAP
+
+function find_gen_paths() {
+  for module in $MODULES; do
+    module_path=$(pathmod "$module")
+    package_path=${module_path#$ANDROID_BUILD_TOP}
+    gen_path=$OUT_DIR/soong/.intermediates$package_path/$module
+    GEN_PATH_MAP[$module]=$gen_path
+  done
+}
+
+function store_outputs() {
+  local dir=$1; shift
+
+  for module in $MODULES; do
+    dest_dir=$dir/${module}
+    mkdir -p $dest_dir
+    gen_path=${GEN_PATH_MAP[$module]}
+    cp -r $gen_path $dest_dir
+  done
+}
+
+function cmp_outputs() {
+  local dir1=$1; shift
+  local dir2=$1; shift
+
+  for module in $MODULES; do
+    if ! diff -rq --exclude=genrule.sbox.textproto $dir1/$module $dir2/$module; then
+      PASS=false
+      echo "$module differ"
+    fi
+  done
+  if [ $PASS = true ]; then
+    echo "Test passed"
+  fi
+}
+
+if [ ! -f "$ANDROID_PRODUCT_OUT/module-info.json" ]; then
+  refreshmod
+fi
+
+find_gen_paths
+m --skip-soong-tests GENRULE_SANDBOXING=true "${MODULES[@]}"
+store_outputs "$OUTPUT_DIR/sandbox"
+m --skip-soong-tests GENRULE_SANDBOXING=false "${MODULES[@]}"
+store_outputs "$OUTPUT_DIR/non_sandbox"
+
+cmp_outputs "$OUTPUT_DIR/non_sandbox" "$OUTPUT_DIR/sandbox"
diff --git a/ui/build/config.go b/ui/build/config.go
index bfbf85d..0df1374 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -231,8 +231,9 @@
 
 func NewConfig(ctx Context, args ...string) Config {
 	ret := &configImpl{
-		environ:       OsEnvironment(),
-		sandboxConfig: &SandboxConfig{},
+		environ:               OsEnvironment(),
+		sandboxConfig:         &SandboxConfig{},
+		ninjaWeightListSource: NINJA_LOG,
 	}
 
 	// Default matching ninja
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 5d56531..61aaad8 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -35,48 +35,6 @@
 	ninjaWeightListFileName = ".ninja_weight_list"
 )
 
-func useNinjaBuildLog(ctx Context, config Config, cmd *Cmd) {
-	ninjaLogFile := filepath.Join(config.OutDir(), ninjaLogFileName)
-	data, err := os.ReadFile(ninjaLogFile)
-	var outputBuilder strings.Builder
-	if err == nil {
-		lines := strings.Split(strings.TrimSpace(string(data)), "\n")
-		// ninja log: <start>	<end>	<restat>	<name>	<cmdhash>
-		// ninja weight list: <name>,<end-start+1>
-		for _, line := range lines {
-			if strings.HasPrefix(line, "#") {
-				continue
-			}
-			fields := strings.Split(line, "\t")
-			path := fields[3]
-			start, err := strconv.Atoi(fields[0])
-			if err != nil {
-				continue
-			}
-			end, err := strconv.Atoi(fields[1])
-			if err != nil {
-				continue
-			}
-			outputBuilder.WriteString(path)
-			outputBuilder.WriteString(",")
-			outputBuilder.WriteString(strconv.Itoa(end-start+1) + "\n")
-		}
-	} else {
-		// If there is no ninja log file, just pass empty ninja weight list.
-		// Because it is still efficient with critical path calculation logic even without weight.
-		ctx.Verbosef("There is an error during reading ninja log, so ninja will use empty weight list: %s", err)
-	}
-
-	weightListFile := filepath.Join(config.OutDir(), ninjaWeightListFileName)
-
-	err = os.WriteFile(weightListFile, []byte(outputBuilder.String()), 0644)
-	if err == nil {
-		cmd.Args = append(cmd.Args, "-o", "usesweightlist="+weightListFile)
-	} else {
-		ctx.Panicf("Could not write ninja weight list file %s", err)
-	}
-}
-
 // Constructs and runs the Ninja command line with a restricted set of
 // environment variables. It's important to restrict the environment Ninja runs
 // for hermeticity reasons, and to avoid spurious rebuilds.
@@ -131,7 +89,7 @@
 
 	switch config.NinjaWeightListSource() {
 	case NINJA_LOG:
-		useNinjaBuildLog(ctx, config, cmd)
+		cmd.Args = append(cmd.Args, "-o", "usesninjalogasweightlist=yes")
 	case EVENLY_DISTRIBUTED:
 		// pass empty weight list means ninja considers every tasks's weight as 1(default value).
 		cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null")