Merge "Sandbox LTP genrules" into main
diff --git a/android/paths.go b/android/paths.go
index 8dd1966..a6cda38 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1915,7 +1915,9 @@
 // validatePathInternal ensures that a path does not leave its component, and
 // optionally doesn't contain Ninja variables.
 func validatePathInternal(allowNinjaVariables bool, pathComponents ...string) (string, error) {
-	for _, path := range pathComponents {
+	initialEmpty := 0
+	finalEmpty := 0
+	for i, path := range pathComponents {
 		if !allowNinjaVariables && strings.Contains(path, "$") {
 			return "", fmt.Errorf("Path contains invalid character($): %s", path)
 		}
@@ -1924,11 +1926,25 @@
 		if path == ".." || strings.HasPrefix(path, "../") || strings.HasPrefix(path, "/") {
 			return "", fmt.Errorf("Path is outside directory: %s", path)
 		}
+
+		if i == initialEmpty && pathComponents[i] == "" {
+			initialEmpty++
+		}
+		if i == finalEmpty && pathComponents[len(pathComponents)-1-i] == "" {
+			finalEmpty++
+		}
 	}
+	// Optimization: filepath.Join("foo", "") returns a newly allocated copy
+	// of "foo", while filepath.Join("foo") does not.  Strip out any empty
+	// path components.
+	if initialEmpty == len(pathComponents) {
+		return "", nil
+	}
+	nonEmptyPathComponents := pathComponents[initialEmpty : len(pathComponents)-finalEmpty]
 	// TODO: filepath.Join isn't necessarily correct with embedded ninja
 	// variables. '..' may remove the entire ninja variable, even if it
 	// will be expanded to multiple nested directories.
-	return filepath.Join(pathComponents...), nil
+	return filepath.Join(nonEmptyPathComponents...), nil
 }
 
 // validateSafePath validates a path that we trust (may contain ninja
diff --git a/android/paths_test.go b/android/paths_test.go
index 2f87977..bf46c34 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -37,6 +37,22 @@
 		out: "",
 	},
 	{
+		in:  []string{"", ""},
+		out: "",
+	},
+	{
+		in:  []string{"a", ""},
+		out: "a",
+	},
+	{
+		in:  []string{"", "a"},
+		out: "a",
+	},
+	{
+		in:  []string{"", "a", ""},
+		out: "a",
+	},
+	{
 		in:  []string{"a/b"},
 		out: "a/b",
 	},
diff --git a/apex/apex.go b/apex/apex.go
index adabdee..f2e8a06 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -135,6 +135,11 @@
 	// List of filesystem images that are embedded inside this APEX bundle.
 	Filesystems []string
 
+	// List of module names which we don't want to add as transitive deps. This can be used as
+	// a workaround when the current implementation collects more than necessary. For example,
+	// Rust binaries with prefer_rlib:true add unnecessary dependencies.
+	Unwanted_transitive_deps []string
+
 	// The minimum SDK version that this APEX must support at minimum. This is usually set to
 	// the SDK version that the APEX was first introduced.
 	Min_sdk_version *string
@@ -2003,11 +2008,21 @@
 
 	// if true, raise error on duplicate apexFile
 	checkDuplicate bool
+
+	// visitor skips these from this list of module names
+	unwantedTransitiveDeps []string
 }
 
 func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) {
 	encountered := make(map[string]apexFile)
 	for _, f := range vctx.filesInfo {
+		// Skips unwanted transitive deps. This happens, for example, with Rust binaries with prefer_rlib:true.
+		// TODO(b/295593640)
+		// Needs additional verification for the resulting APEX to ensure that skipped artifacts don't make problems.
+		// For example, DT_NEEDED modules should be found within the APEX unless they are marked in `requiredNativeLibs`.
+		if f.transitiveDep && f.module != nil && android.InList(mctx.OtherModuleName(f.module), vctx.unwantedTransitiveDeps) {
+			continue
+		}
 		dest := filepath.Join(f.installDir, f.builtFile.Base())
 		if e, ok := encountered[dest]; !ok {
 			encountered[dest] = f
@@ -2371,10 +2386,6 @@
 	if a.properties.IsCoverageVariant {
 		return false
 	}
-	// TODO(b/263308515) remove this
-	if a.testApex {
-		return false
-	}
 	if ctx.DeviceConfig().DeviceArch() == "" {
 		return false
 	}
@@ -2401,8 +2412,9 @@
 	// TODO(jiyong): do this using WalkPayloadDeps
 	// TODO(jiyong): make this clean!!!
 	vctx := visitorContext{
-		handleSpecialLibs: !android.Bool(a.properties.Ignore_system_library_special_case),
-		checkDuplicate:    a.shouldCheckDuplicate(ctx),
+		handleSpecialLibs:      !android.Bool(a.properties.Ignore_system_library_special_case),
+		checkDuplicate:         a.shouldCheckDuplicate(ctx),
+		unwantedTransitiveDeps: a.properties.Unwanted_transitive_deps,
 	}
 	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
 	vctx.normalizeFileInfo(ctx)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index a95a14d..e6581cf 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7709,6 +7709,42 @@
 		`)
 }
 
+func TestApexUnwantedTransitiveDeps(t *testing.T) {
+	bp := `
+	apex {
+		name: "myapex",
+		key: "myapex.key",
+		native_shared_libs: ["libfoo"],
+		updatable: false,
+		unwanted_transitive_deps: ["libbar"],
+	}
+
+	apex_key {
+		name: "myapex.key",
+		public_key: "testkey.avbpubkey",
+		private_key: "testkey.pem",
+	}
+
+	cc_library {
+		name: "libfoo",
+		srcs: ["foo.cpp"],
+		shared_libs: ["libbar"],
+		apex_available: ["myapex"],
+	}
+
+	cc_library {
+		name: "libbar",
+		srcs: ["bar.cpp"],
+		apex_available: ["myapex"],
+	}`
+	ctx := testApex(t, bp)
+	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
+		"*/libc++.so",
+		"*/libfoo.so",
+		// not libbar.so
+	})
+}
+
 func TestRejectNonInstallableJavaLibrary(t *testing.T) {
 	testApexError(t, `"myjar" is not configured to be compiled into dex`, `
 		apex {
diff --git a/cc/builder.go b/cc/builder.go
index c8fa1e4..3f582fa 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -534,7 +534,7 @@
 		toolingCppflags += " ${config.NoOverride64GlobalCflags}"
 	}
 
-	modulePath := android.PathForModuleSrc(ctx).String()
+	modulePath := ctx.ModuleDir()
 	if android.IsThirdPartyPath(modulePath) {
 		cflags += " ${config.NoOverrideExternalGlobalCflags}"
 		toolingCflags += " ${config.NoOverrideExternalGlobalCflags}"
diff --git a/cc/compiler.go b/cc/compiler.go
index 5bed8a7..490d3cc 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -339,7 +339,7 @@
 // per-target values, module type values, and per-module Blueprints properties
 func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
 	tc := ctx.toolchain()
-	modulePath := android.PathForModuleSrc(ctx).String()
+	modulePath := ctx.ModuleDir()
 
 	compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
 	compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...)
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index 33c3ac3..9cc98f5 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -74,12 +74,6 @@
 		"ScriptGroupTest-rscript",
 		"TracingVMProtoStub_cc",
 		"TracingVMProtoStub_h",
-		"UpdatableSystemFontTest_NotoColorEmojiV0.sig",
-		"UpdatableSystemFontTest_NotoColorEmojiV0.ttf",
-		"UpdatableSystemFontTest_NotoColorEmojiVPlus1.sig",
-		"UpdatableSystemFontTest_NotoColorEmojiVPlus1.ttf",
-		"UpdatableSystemFontTest_NotoColorEmojiVPlus2.sig",
-		"UpdatableSystemFontTest_NotoColorEmojiVPlus2.ttf",
 		"VehicleServerProtoStub_cc",
 		"VehicleServerProtoStub_cc@2.0-grpc-trout",
 		"VehicleServerProtoStub_cc@default-grpc",
@@ -102,12 +96,6 @@
 		"camera-its",
 		"checkIn-service-stub-lite",
 		"chre_atoms_log.h",
-		"com.android.apex.test.bar_stripped",
-		"com.android.apex.test.baz_stripped",
-		"com.android.apex.test.foo_stripped",
-		"com.android.apex.test.pony_stripped",
-		"com.android.apex.test.sharedlibs_generated",
-		"com.android.apex.test.sharedlibs_secondary_generated",
 		"common-profile-text-protos",
 		"core-tests-smali-dex",
 		"cronet_aml_base_android_runtime_jni_headers",
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index d15dbc9..7d8a9f7 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -632,21 +632,6 @@
 	return output
 }
 
-// retrieveLegacyEncodedBootDexFiles attempts to retrieve the legacy encoded boot dex jar files.
-func retrieveLegacyEncodedBootDexFiles(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
-	// If the current bootclasspath_fragment is the active module or a source module then retrieve the
-	// encoded dex files, otherwise return an empty map.
-	//
-	// An inactive (i.e. not preferred) bootclasspath_fragment needs to retrieve the encoded dex jars
-	// as they are still needed by an apex. An inactive prebuilt_bootclasspath_fragment does not need
-	// to do so and may not yet have access to dex boot jars from a prebuilt_apex/apex_set.
-	if isActiveModule(ctx.Module()) || !android.IsModulePrebuilt(ctx.Module()) {
-		return extractEncodedDexJarsFromModules(ctx, contents)
-	} else {
-		return nil
-	}
-}
-
 // createHiddenAPIFlagInput creates a HiddenAPIFlagInput struct and initializes it with information derived
 // from the properties on this module and its dependencies.
 func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) HiddenAPIFlagInput {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 87588f3..f7d7de6 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -303,7 +303,7 @@
 	}
 
 	flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
-	flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
+	flags = append(flags, "-I"+ctx.ModuleDir())
 	if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
 		flags = append(flags, "-I"+src.String())
 	}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index c000ac3..180ba92 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -775,6 +775,11 @@
 			`         m %s-update-current-api\n\n`+
 			`      To submit the revised current.txt to the main Android repository,\n`+
 			`      you will need approval.\n`+
+			`If your build failed due to stub validation, you can resolve the errors with\n`+
+			`either of the two choices above and try re-building the target.\n`+
+			`If the mismatch between the stubs and the current.txt is intended,\n`+
+			`you can try re-building the target by executing the following command:\n`+
+			`m DISABLE_STUB_VALIDATION=true <your build target>\n`+
 			`******************************\n`, ctx.ModuleName())
 
 		rule.Command().
diff --git a/rust/builder.go b/rust/builder.go
index 72e5be1..162d1aa 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -288,7 +288,7 @@
 	}
 
 	// Disallow experimental features
-	modulePath := android.PathForModuleSrc(ctx).String()
+	modulePath := ctx.ModuleDir()
 	if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
 		rustcFlags = append(rustcFlags, "-Zallow-features=\"\"")
 	}
@@ -436,7 +436,7 @@
 	docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
 
 	// Silence warnings about renamed lints for third-party crates
-	modulePath := android.PathForModuleSrc(ctx).String()
+	modulePath := ctx.ModuleDir()
 	if android.IsThirdPartyPath(modulePath) {
 		rustdocFlags = append(rustdocFlags, " -A warnings")
 	}
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index dad2b47..47eae07 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -44,6 +44,7 @@
 java\.util\.jar
 java\.util\.logging
 java\.util\.prefs
+java\.util\.random
 java\.util\.regex
 java\.util\.spi
 java\.util\.stream
@@ -79,8 +80,10 @@
 jdk\.internal\.reflect
 jdk\.internal\.util
 jdk\.internal\.util\.jar
+jdk\.internal\.util\.random
 jdk\.internal\.vm\.annotation
 jdk\.net
+jdk\.random
 org\.w3c\.dom
 org\.w3c\.dom\.ls
 org\.w3c\.dom\.traversal