Merge "Enable Soong's tradefed_binary to support multi-arch" into main
diff --git a/cc/compiler.go b/cc/compiler.go
index bb7885b..c9de1b0 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -479,7 +479,7 @@
 			target += strconv.Itoa(android.FutureApiLevelInt)
 		} else {
 			apiLevel := nativeApiLevelOrPanic(ctx, version)
-			target += apiLevel.String()
+			target += strconv.Itoa(apiLevel.FinalOrFutureInt())
 		}
 	}
 
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 3364f50..e69a930 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -22,6 +22,7 @@
 	"flag"
 	"fmt"
 	"io"
+	"io/fs"
 	"io/ioutil"
 	"os"
 	"os/exec"
@@ -478,7 +479,8 @@
 // copyOneFile copies a file and its permissions.  If forceExecutable is true it adds u+x to the
 // permissions.  If exists is allowFromNotExists it returns nil if the from path doesn't exist.
 // If write is onlyWriteIfChanged then the output file is compared to the input file and not written to
-// if it is the same, avoiding updating the timestamp.
+// if it is the same, avoiding updating the timestamp. If from is a symlink, the symlink itself
+// will be copied, instead of what it points to.
 func copyOneFile(from string, to string, forceExecutable bool, exists existsType,
 	write writeType) error {
 	err := os.MkdirAll(filepath.Dir(to), 0777)
@@ -486,7 +488,7 @@
 		return err
 	}
 
-	stat, err := os.Stat(from)
+	stat, err := os.Lstat(from)
 	if err != nil {
 		if os.IsNotExist(err) && exists == allowFromNotExists {
 			return nil
@@ -494,6 +496,25 @@
 		return err
 	}
 
+	if stat.Mode()&fs.ModeSymlink != 0 {
+		linkTarget, err := os.Readlink(from)
+		if err != nil {
+			return err
+		}
+		if write == onlyWriteIfChanged {
+			toLinkTarget, err := os.Readlink(to)
+			if err == nil && toLinkTarget == linkTarget {
+				return nil
+			}
+		}
+		err = os.Remove(to)
+		if err != nil && !os.IsNotExist(err) {
+			return err
+		}
+
+		return os.Symlink(linkTarget, to)
+	}
+
 	perm := stat.Mode()
 	if forceExecutable {
 		perm = perm | 0100 // u+x
diff --git a/genrule/genrule.go b/genrule/genrule.go
index ffdd890..0512c15 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -581,17 +581,15 @@
 
 func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	// Allowlist genrule to use depfile until we have a solution to remove it.
-	// TODO(b/235582219): Remove allowlist for genrule
+	// TODO(b/307824623): Remove depfile property
 	if Bool(g.properties.Depfile) {
 		sandboxingAllowlistSets := getSandboxingAllowlistSets(ctx)
-		// TODO(b/283852474): Checking the GenruleSandboxing flag is temporary in
-		// order to pass the presubmit before internal master is updated.
 		if ctx.DeviceConfig().GenruleSandboxing() && !sandboxingAllowlistSets.depfileAllowSet[g.Name()] {
 			ctx.PropertyErrorf(
 				"depfile",
-				"Deprecated to ensure the module type is convertible to Bazel. "+
-					"Try specifying the dependencies explicitly so that there is no need to use depfile. "+
-					"If not possible, the escape hatch is to add the module to allowlists.go to bypass the error.")
+				"Deprecated because with genrule sandboxing, dependencies must be known before the action is run "+
+					"in order to add them to the sandbox. "+
+					"Please specify the dependencies explicitly so that there is no need to use depfile.")
 		}
 	}
 
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index d13e976..fa0ee17 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -708,7 +708,7 @@
 				depfile: true,
 				cmd: "cat $(in) > $(out) && cat $(depfile)",
 			`,
-			err: "depfile: Deprecated to ensure the module type is convertible to Bazel",
+			err: "depfile: Deprecated because with genrule sandboxing, dependencies must be known before the action is run in order to add them to the sandbox",
 		},
 		{
 			name: `no error when module is allowlisted`,