Merge changes I5645ddb9,Ib3d50f15,Ib4c5815a,If3b63706 into main

* changes:
  Revert "Revert^2 "Always embed jni libs and store uncompressed""
  Revert "Revert "Revert "Collect transitve deps of jni libs only for bund...""
  Revert "Add SkipToTransitiveDepsTag interface for dependency tags"
  Revert "Install transitive deps of jni libs, but not the jni libs themselves"
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index 7317587..ee9891d 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -130,6 +130,7 @@
 			AconfigFiles: mergedAconfigFiles,
 			ModeInfos:    mergedModeInfos,
 		})
+		ctx.Module().base().aconfigFilePaths = getAconfigFilePaths(ctx.Module().base(), mergedAconfigFiles)
 	}
 }
 
diff --git a/android/makevars.go b/android/makevars.go
index b6bc14e..f57ac45 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -507,7 +507,7 @@
 		if extraFiles := install.extraFiles; extraFiles != nil {
 			fmt.Fprintf(buf, "\t( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} ) || \\\n", extraFiles.dir.String(), extraFiles.zip.String())
 			fmt.Fprintf(buf, "\t  ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )\n")
-			fmt.Fprintf(buf, "EXTRA_INSTALL_ZIPS += %s:%s\n", extraFiles.dir.String(), extraFiles.zip.String())
+			fmt.Fprintf(buf, "EXTRA_INSTALL_ZIPS += %s:%s:%s\n", install.to.String(), extraFiles.dir.String(), extraFiles.zip.String())
 		}
 
 		fmt.Fprintln(buf)
diff --git a/android/module.go b/android/module.go
index 738f543..d4e4c2d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -902,6 +902,9 @@
 	installedInitRcPaths         InstallPaths
 	installedVintfFragmentsPaths InstallPaths
 
+	// Merged Aconfig files for all transitive deps.
+	aconfigFilePaths Paths
+
 	// set of dependency module:location mappings used to populate the license metadata for
 	// apex containers.
 	licenseInstallMap []string
@@ -1066,7 +1069,8 @@
 		// TODO(jiyong): the Make-side does this only when the required module is a shared
 		// library or a native test.
 		bothInAndroid := ctx.Device() && target.Os.Class == Device
-		nativeArch := InList(ctx.Arch().ArchType.Multilib, []string{"lib32", "lib64"})
+		nativeArch := InList(ctx.Arch().ArchType.Multilib, []string{"lib32", "lib64"}) &&
+			InList(target.Arch.ArchType.Multilib, []string{"lib32", "lib64"})
 		sameBitness := ctx.Arch().ArchType.Multilib == target.Arch.ArchType.Multilib
 		if bothInAndroid && nativeArch && !sameBitness {
 			return
diff --git a/android/module_context.go b/android/module_context.go
index 605d3ba..3c1e30a 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -482,6 +482,10 @@
 	return m.packageFile(fullInstallPath, srcPath, false)
 }
 
+func (m *moduleContext) getAconfigPaths() *Paths {
+	return &m.module.base().aconfigFilePaths
+}
+
 func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
 	licenseFiles := m.Module().EffectiveLicenseFiles()
 	spec := PackagingSpec{
@@ -492,6 +496,7 @@
 		effectiveLicenseFiles: &licenseFiles,
 		partition:             fullInstallPath.partition,
 		skipInstall:           m.skipInstall(),
+		aconfigPaths:          m.getAconfigPaths(),
 	}
 	m.packagingSpecs = append(m.packagingSpecs, spec)
 	return spec
@@ -616,6 +621,7 @@
 		executable:       false,
 		partition:        fullInstallPath.partition,
 		skipInstall:      m.skipInstall(),
+		aconfigPaths:     m.getAconfigPaths(),
 	})
 
 	return fullInstallPath
@@ -658,6 +664,7 @@
 		executable:       false,
 		partition:        fullInstallPath.partition,
 		skipInstall:      m.skipInstall(),
+		aconfigPaths:     m.getAconfigPaths(),
 	})
 
 	return fullInstallPath
diff --git a/android/packaging.go b/android/packaging.go
index fe61da1..a7260a6 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -48,6 +48,9 @@
 	// is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via
 	// PackageFile).
 	skipInstall bool
+
+	// Paths of aconfig files for the built artifact
+	aconfigPaths *Paths
 }
 
 func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
@@ -102,6 +105,11 @@
 	return p.skipInstall
 }
 
+// Paths of aconfig files for the built artifact
+func (p *PackagingSpec) GetAconfigPaths() Paths {
+	return *p.aconfigPaths
+}
+
 type PackageModule interface {
 	Module
 	packagingBase() *PackagingBase
diff --git a/cc/library.go b/cc/library.go
index 12ecc13..895b199 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1490,6 +1490,11 @@
 					fileName, nameExt, isLlndk)
 			}
 		}
+		// Ensure that a module tagged with only platformLsdumpTag has ref_dump_dirs.
+		// Android.bp in vendor projects should be cleaned up before this is enforced for vendorLsdumpTag and productLsdumpTag.
+		if len(headerAbiChecker.Ref_dump_dirs) == 0 && len(tags) == 1 && tags[0] == platformLsdumpTag {
+			ctx.ModuleErrorf("header_abi_checker is explicitly enabled, but no ref_dump_dirs are specified.")
+		}
 		// Check against the opt-in reference dumps.
 		for i, optInDumpDir := range headerAbiChecker.Ref_dump_dirs {
 			optInDumpDirPath := android.PathForModuleSrc(ctx, optInDumpDir)
diff --git a/cc/sabi.go b/cc/sabi.go
index edd9cfe..64eab41 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -43,8 +43,6 @@
 		return "platform"
 	case llndkLsdumpTag:
 		return "vndk"
-	case platformLsdumpTag:
-		return "platform"
 	default:
 		return ""
 	}
@@ -134,10 +132,10 @@
 		if m.isImplementationForLLNDKPublic() {
 			result = append(result, llndkLsdumpTag)
 		}
-		// APEX and opt-in platform dumps are placed in the same directory.
 		if m.library.hasStubsVariants() {
 			result = append(result, apexLsdumpTag)
-		} else if headerAbiChecker.enabled() {
+		}
+		if headerAbiChecker.enabled() {
 			result = append(result, platformLsdumpTag)
 		}
 	} else if headerAbiChecker.enabled() {
diff --git a/cc/test.go b/cc/test.go
index 3a1a3af..a96af31 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -359,6 +359,12 @@
 func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
 	flags = test.binaryDecorator.linkerFlags(ctx, flags)
 	flags = test.testDecorator.linkerFlags(ctx, flags)
+
+	// Add a default rpath to allow tests to dlopen libraries specified in data_libs.
+	// Host modules already get an rpath specified in linker.go.
+	if !ctx.Host() {
+		flags.Global.LdFlags = append(flags.Global.LdFlags, `-Wl,-rpath,\$$ORIGIN`)
+	}
 	return flags
 }
 
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index d64010e..4490dd2 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -108,7 +108,7 @@
 	case "always":
 		return true
 	case "depend":
-		if _, err := os.Stat(filepath.Join(ctx.Config().OutDir(), ".ninja_log")); errors.Is(err, os.ErrNotExist) {
+		if _, err := os.Stat(filepath.Join(topDir, ctx.Config().OutDir(), ".ninja_log")); errors.Is(err, os.ErrNotExist) {
 			return true
 		}
 	}
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index 854a366..a08f7cf 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -15,6 +15,7 @@
         "soong-phony", // for testing
     ],
     srcs: [
+        "aconfig_files.go",
         "avb_add_hash_footer.go",
         "avb_gen_vbmeta_image.go",
         "bootimg.go",
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
new file mode 100644
index 0000000..44de202
--- /dev/null
+++ b/filesystem/aconfig_files.go
@@ -0,0 +1,58 @@
+// Copyright (C) 2024 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.
+
+package filesystem
+
+import (
+	"android/soong/android"
+	"path/filepath"
+	"strings"
+
+	"github.com/google/blueprint/proptools"
+)
+
+func (f *filesystem) buildAconfigFlagsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, dir android.Path) {
+	if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) {
+		return
+	}
+
+	aconfigFlagsBuilderPath := android.PathForModuleOut(ctx, "aconfig_flags_builder.sh")
+	aconfigToolPath := ctx.Config().HostToolPath(ctx, "aconfig")
+	cmd := builder.Command().Tool(aconfigFlagsBuilderPath).Implicit(aconfigToolPath)
+
+	installAconfigFlags := filepath.Join(dir.String(), "etc", "aconfig_flags_"+f.partitionName()+".pb")
+
+	var sb strings.Builder
+	sb.WriteString("set -e\n")
+	sb.WriteString(aconfigToolPath.String())
+	sb.WriteString(" dump-cache --dedup --format protobuf --out ")
+	sb.WriteString(installAconfigFlags)
+	sb.WriteString(" \\\n")
+
+	var caches []string
+	for _, ps := range specs {
+		cmd.Implicits(ps.GetAconfigPaths())
+		caches = append(caches, ps.GetAconfigPaths().Strings()...)
+	}
+	caches = android.SortedUniqueStrings(caches)
+
+	for _, cache := range caches {
+		sb.WriteString("  --cache ")
+		sb.WriteString(cache)
+		sb.WriteString(" \\\n")
+	}
+	sb.WriteRune('\n')
+
+	android.WriteExecutableFileRuleVerbatim(ctx, aconfigFlagsBuilderPath, sb.String())
+}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index b342ae9..d8a00e2 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -131,6 +131,9 @@
 	// Default is false
 	Build_logtags *bool
 
+	// Install aconfig_flags.pb file for the modules installed in this partition.
+	Gen_aconfig_flags_pb *bool
+
 	Fsverity fsverityProperties
 }
 
@@ -300,6 +303,7 @@
 	f.addMakeBuiltFiles(ctx, builder, rootDir)
 	f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
 	f.buildEventLogtagsFile(ctx, builder, rebasedDir)
+	f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
 
 	// run host_init_verifier
 	// Ideally we should have a concept of pluggable linters that verify the generated image.
@@ -441,6 +445,7 @@
 	f.buildNonDepsFiles(ctx, builder, rootDir)
 	f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
 	f.buildEventLogtagsFile(ctx, builder, rebasedDir)
+	f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
 
 	output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath
 	cmd := builder.Command().
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index acd4813..861918f 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -465,3 +465,35 @@
 		}
 	`)
 }
+
+func TestTrackPhonyAsRequiredDep(t *testing.T) {
+	result := fixture.RunTestWithBp(t, `
+		android_filesystem {
+			name: "fs",
+			deps: ["foo"],
+		}
+
+		cc_binary {
+			name: "foo",
+			required: ["phony"],
+		}
+
+		phony {
+			name: "phony",
+			required: ["libbar"],
+		}
+
+		cc_library {
+			name: "libbar",
+		}
+	`)
+
+	fs := result.ModuleForTests("fs", "android_common").Module().(*filesystem)
+	expected := []string{
+		"bin/foo",
+		"lib64/libbar.so",
+	}
+	for _, e := range expected {
+		android.AssertStringListContains(t, "missing entry", fs.entries, e)
+	}
+}
diff --git a/java/app.go b/java/app.go
index 50d1a2f..f05b8a7 100644
--- a/java/app.go
+++ b/java/app.go
@@ -521,7 +521,7 @@
 	}
 
 	// Use non final ids if we are doing optimized shrinking and are using R8.
-	nonFinalIds := Bool(a.dexProperties.Optimize.Optimized_shrink_resources) && a.dexer.effectiveOptimizeEnabled()
+	nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled()
 	a.aapt.buildActions(ctx,
 		aaptBuildActionOptions{
 			sdkContext:                     android.SdkContext(a),
@@ -552,7 +552,7 @@
 	staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
 
 	a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...)
-	if !Bool(a.dexProperties.Optimize.Optimized_shrink_resources) {
+	if !(a.dexProperties.optimizedResourceShrinkingEnabled(ctx)) {
 		// When using the optimized shrinking the R8 enqueuer will traverse the xml files that become
 		// live for code references and (transitively) mark these as live.
 		// In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now
@@ -591,7 +591,7 @@
 	var packageResources = a.exportPackage
 
 	if ctx.ModuleName() != "framework-res" {
-		if a.dexProperties.resourceShrinkingEnabled() {
+		if a.dexProperties.resourceShrinkingEnabled(ctx) {
 			protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
 			aapt2Convert(ctx, protoFile, packageResources, "proto")
 			a.dexer.resourcesInput = android.OptionalPathForPath(protoFile)
@@ -614,7 +614,7 @@
 		}
 
 		a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
-		if a.dexProperties.resourceShrinkingEnabled() {
+		if a.dexProperties.resourceShrinkingEnabled(ctx) {
 			binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
 			aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
 			packageResources = binaryResources
diff --git a/java/dex.go b/java/dex.go
index 6caaa7f..8cfffaf 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -111,8 +111,12 @@
 	return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
 }
 
-func (d *DexProperties) resourceShrinkingEnabled() bool {
-	return BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
+func (d *DexProperties) resourceShrinkingEnabled(ctx android.ModuleContext) bool {
+	return !ctx.Config().Eng() && BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
+}
+
+func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleContext) bool {
+	return d.resourceShrinkingEnabled(ctx) && Bool(d.Optimize.Optimized_shrink_resources)
 }
 
 var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
diff --git a/scripts/extra_install_zips_file_list.py b/scripts/extra_install_zips_file_list.py
index 8ea2a4b..148d6cc 100755
--- a/scripts/extra_install_zips_file_list.py
+++ b/scripts/extra_install_zips_file_list.py
@@ -18,13 +18,16 @@
     parser.add_argument('staging_dir',
         help='Path to the partition staging directory')
     parser.add_argument('extra_install_zips', nargs='*',
-        help='The value of EXTRA_INSTALL_ZIPS from make. It should be a list of extraction_dir:zip_file pairs.')
+        help='The value of EXTRA_INSTALL_ZIPS from make. '
+        'It should be a list of primary_file:extraction_dir:zip_file trios. '
+        'The primary file will be ignored by this script, you should ensure that '
+        'the list of trios given to this script is already filtered by relevant primary files.')
     args = parser.parse_args()
 
     staging_dir = args.staging_dir.removesuffix('/') + '/'
 
-    for zip_pair in args.extra_install_zips:
-        d, z = zip_pair.split(':')
+    for zip_trio in args.extra_install_zips:
+        _, d, z = zip_trio.split(':')
         d = d.removesuffix('/') + '/'
 
         if d.startswith(staging_dir):