Merge "Align boot jar exclusion with apex_contributions" into main
diff --git a/android/makevars.go b/android/makevars.go
index f57ac45..f92f458 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -513,6 +513,7 @@
 		fmt.Fprintln(buf)
 	}
 	fmt.Fprintf(buf, ".KATI_READONLY := EXTRA_INSTALL_ZIPS\n")
+	fmt.Fprintf(buf, "$(KATI_visibility_prefix EXTRA_INSTALL_ZIPS,build/make/core/Makefile)\n")
 
 	for _, symlink := range symlinks {
 		fmt.Fprintf(buf, "%s:", symlink.to.String())
diff --git a/android/module_context.go b/android/module_context.go
index 3c1e30a..18adb30 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -497,6 +497,7 @@
 		partition:             fullInstallPath.partition,
 		skipInstall:           m.skipInstall(),
 		aconfigPaths:          m.getAconfigPaths(),
+		archType:              m.target.Arch.ArchType,
 	}
 	m.packagingSpecs = append(m.packagingSpecs, spec)
 	return spec
@@ -622,6 +623,7 @@
 		partition:        fullInstallPath.partition,
 		skipInstall:      m.skipInstall(),
 		aconfigPaths:     m.getAconfigPaths(),
+		archType:         m.target.Arch.ArchType,
 	})
 
 	return fullInstallPath
@@ -665,6 +667,7 @@
 		partition:        fullInstallPath.partition,
 		skipInstall:      m.skipInstall(),
 		aconfigPaths:     m.getAconfigPaths(),
+		archType:         m.target.Arch.ArchType,
 	})
 
 	return fullInstallPath
diff --git a/android/packaging.go b/android/packaging.go
index a7260a6..383f828 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -51,6 +51,9 @@
 
 	// Paths of aconfig files for the built artifact
 	aconfigPaths *Paths
+
+	// ArchType of the module which produced this packaging spec
+	archType ArchType
 }
 
 func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
@@ -260,11 +263,31 @@
 
 func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
 	m := make(map[string]PackagingSpec)
+
+	var arches []ArchType
+	for _, target := range p.getSupportedTargets(ctx) {
+		arches = append(arches, target.Arch.ArchType)
+	}
+
+	// filter out packaging specs for unsupported architecture
+	filterArch := func(ps PackagingSpec) bool {
+		for _, arch := range arches {
+			if arch == ps.archType {
+				return true
+			}
+		}
+		return false
+	}
+
 	ctx.VisitDirectDeps(func(child Module) {
 		if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
 			return
 		}
 		for _, ps := range child.TransitivePackagingSpecs() {
+			if !filterArch(ps) {
+				continue
+			}
+
 			if filter != nil {
 				if !filter(ps) {
 					continue
diff --git a/apex/apex.go b/apex/apex.go
index 9a80ec6..8029910 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1636,7 +1636,8 @@
 
 func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile {
 	dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
-	return newApexFile(ctx, outputFile, outputFile.Base(), dirInApex, etc, prebuilt)
+	makeModuleName := strings.ReplaceAll(filepath.Join(dirInApex, outputFile.Base()), "/", "_")
+	return newApexFile(ctx, outputFile, makeModuleName, dirInApex, etc, prebuilt)
 }
 
 func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 9a5c2b4..74b2eec 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -11531,3 +11531,42 @@
 		"depend on java_aconfig_library not passed as an input",
 		aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "quux"))
 }
+
+func TestMultiplePrebuiltsWithSameBase(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			prebuilts: ["myetc", "myetc2"],
+			min_sdk_version: "29",
+		}
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		prebuilt_etc {
+			name: "myetc",
+			src: "myprebuilt",
+			filename: "myfilename",
+		}
+		prebuilt_etc {
+			name: "myetc2",
+			sub_dir: "mysubdir",
+			src: "myprebuilt",
+			filename: "myfilename",
+		}
+	`, withFiles(android.MockFS{
+		"packages/modules/common/build/allowed_deps.txt": nil,
+	}))
+
+	ab := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, ab)
+	var builder strings.Builder
+	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
+	androidMk := builder.String()
+
+	android.AssertStringDoesContain(t, "not found", androidMk, "LOCAL_MODULE := etc_myfilename.myapex")
+	android.AssertStringDoesContain(t, "not found", androidMk, "LOCAL_MODULE := etc_mysubdir_myfilename.myapex")
+}
diff --git a/bin/aninja b/bin/aninja
new file mode 100755
index 0000000..cceb794
--- /dev/null
+++ b/bin/aninja
@@ -0,0 +1,25 @@
+#!/bin/bash -e
+
+# Copyright (C) 2022 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.
+
+# Common script utilities
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+require_lunch
+
+cd $(gettop)
+prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-${TARGET_PRODUCT}.ninja "$@"
+
diff --git a/bin/overrideflags b/bin/overrideflags
new file mode 100755
index 0000000..e16537b
--- /dev/null
+++ b/bin/overrideflags
@@ -0,0 +1,100 @@
+#!/bin/bash -e
+# 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.
+
+
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+
+function print_help() {
+    echo -e "overrideflags is used to set default value for local build."
+    echo -e "\nOptions:"
+    echo -e "\t--release-config  \tPath to release configuration directory. Required"
+    echo -e "\t--no-edit         \tIf present, skip editing flag value file."
+    echo -e "\t-h/--help         \tShow this help."
+}
+
+function main() {
+    while (($# > 0)); do
+        case $1 in
+        --release-config)
+            if [[ $# -le 1 ]]; then
+                echo "--release-config requires a path"
+                return 1
+            fi
+            local release_config_dir="$2"
+            shift 2
+            ;;
+        --no-edit)
+            local no_edit="true"
+            shift 1
+            ;;
+        -h|--help)
+            print_help
+            return
+            ;;
+        *)
+            echo "$1 is unrecognized"
+            print_help
+            return 1
+            ;;
+        esac
+    done
+
+
+
+    case $(uname -s) in
+        Darwin)
+            local host_arch=darwin-x86
+            ;;
+        Linux)
+            local host_arch=linux-x86
+            ;;
+        *)
+            >&2 echo Unknown host $(uname -s)
+            return
+            ;;
+    esac
+
+    if [[ -z "${release_config_dir}" ]]; then
+        echo "Please provide release configuration path by --release-config"
+        exit 1
+    elif [ ! -d "${release_config_dir}" ]; then
+        echo "${release_config_dir} is an invalid directory"
+        exit 1
+    fi
+    local T="$(gettop)"
+    local aconfig_dir="${T}"/build/make/tools/aconfig/
+    local overrideflag_py="${aconfig_dir}"/overrideflags/overrideflags.py
+    local overridefile="${release_config_dir}/aconfig/override_values.textproto"
+
+    # Edit override file
+    if [[ -z "${no_edit}" ]]; then
+        editor="${EDITOR:-$(which vim)}"
+
+        eval "${editor} ${overridefile}"
+        if [ $? -ne 0 ]; then
+            echo "Fail to set override values"
+            return 1
+        fi
+    fi
+
+    ${T}/prebuilts/build-tools/${host_arch}/bin/py3-cmd -u "${overrideflag_py}" \
+        --overrides "${overridefile}" \
+        --out "${release_config_dir}/aconfig"
+}
+
+
+main "$@"
diff --git a/cc/cmake_ext_add_aidl_library.txt b/cc/cmake_ext_add_aidl_library.txt
index dcf805a..af5bdf6 100644
--- a/cc/cmake_ext_add_aidl_library.txt
+++ b/cc/cmake_ext_add_aidl_library.txt
@@ -1,35 +1,51 @@
-function(add_aidl_library NAME LANG SOURCES AIDLFLAGS)
+function(add_aidl_library NAME LANG AIDLROOT SOURCES AIDLFLAGS)
     if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.20")
         cmake_policy(SET CMP0116 NEW)
     endif()
 
+    # Strip trailing slash
+    get_filename_component(AIDLROOT_TRAILING "${AIDLROOT}" NAME)
+    if ("${AIDLROOT_TRAILING}" STREQUAL "")
+        get_filename_component(AIDLROOT "${AIDLROOT}foo" DIRECTORY)
+    endif()
+
     set(GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/.intermediates/${NAME}-source")
     set(GEN_SOURCES)
-    foreach(SOURCE ${SOURCES})
-        get_filename_component(SOURCE_WE ${SOURCE} NAME_WE)
-        get_filename_component(SOURCE_ABSOLUTE ${SOURCE} ABSOLUTE)
-        get_filename_component(SOURCE_DIR ${SOURCE_ABSOLUTE} DIRECTORY)
-        set(GEN_SOURCE "${GEN_DIR}/${SOURCE_WE}.cpp")
+    foreach (SOURCE ${SOURCES})
+        set(SOURCE_FULL ${AIDLROOT}/${SOURCE})
+        get_filename_component(SOURCE_WLE ${SOURCE} NAME_WLE)
+        get_filename_component(SOURCE_SUBDIR ${SOURCE} DIRECTORY)
+        set(GEN_SOURCE "${GEN_DIR}/${SOURCE_SUBDIR}/${SOURCE_WLE}.cpp")
+
+        file(READ "${SOURCE}" SOURCE_CONTENTS)
+        string(FIND "${SOURCE_CONTENTS}" "@VintfStability" VINTF_MATCH)
+        set(STABILITY_FLAG)
+        if (${VINTF_MATCH} GREATER_EQUAL 0)
+            set(STABILITY_FLAG --stability vintf)
+        endif()
+
         set(DEPFILE_ARG)
         if (NOT ${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
             set(DEPFILE_ARG DEPFILE "${GEN_SOURCE}.d")
         endif()
+
         add_custom_command(
             OUTPUT "${GEN_SOURCE}"
-            MAIN_DEPENDENCY "${SOURCE_ABSOLUTE}"
+            MAIN_DEPENDENCY "${SOURCE_FULL}"
             ${DEPFILE_ARG}
             COMMAND "${AIDL_BIN}"
             ARGS
             --lang=${LANG}
-            --include="${SOURCE_DIR}"
+            --include="${AIDLROOT}"
             --dep="${GEN_SOURCE}.d"
             --out="${GEN_DIR}"
             --header_out="${GEN_DIR}/include"
             --ninja
             --structured
             --min_sdk_version=current
+            ${STABILITY_FLAG}
             ${AIDLFLAGS}
-            "${SOURCE_ABSOLUTE}"
+            "${SOURCE_FULL}"
         )
         list(APPEND GEN_SOURCES "${GEN_SOURCE}")
     endforeach()
@@ -39,9 +55,14 @@
     target_include_directories(${NAME}
         PUBLIC
         "${GEN_DIR}/include"
-        "${ANDROID_BUILD_TOP}/frameworks/native/libs/binder/ndk/include_${LANG}"
     )
+
+    if (${LANG} MATCHES "ndk")
+        set(BINDER_LIB_NAME "libbinder_ndk_sdk")
+    else()
+        set(BINDER_LIB_NAME "libbinder_sdk")
+    endif()
     target_link_libraries(${NAME}
-        libbinder_sdk
+        ${BINDER_LIB_NAME}
     )
 endfunction()
diff --git a/cc/cmake_module_aidl.txt b/cc/cmake_module_aidl.txt
index 4509a88..84755a3 100644
--- a/cc/cmake_module_aidl.txt
+++ b/cc/cmake_module_aidl.txt
@@ -1,8 +1,11 @@
 # <<.M.Name>>
 
-<<setList .M.Name "_SRCS" "${ANDROID_BUILD_TOP}/" (getCompilerProperties .M).AidlInterface.Sources>>
+<<setList .M.Name "_SRCS" "" (getAidlSources .M)>>
 
 <<setList .M.Name "_AIDLFLAGS" "" (getCompilerProperties .M).AidlInterface.Flags>>
 
-add_aidl_library(<<.M.Name>> <<(getCompilerProperties .M).AidlInterface.Lang>> "${<<.M.Name>>_SRCS}" "${<<.M.Name>>_AIDLFLAGS}")
+add_aidl_library(<<.M.Name>> <<(getCompilerProperties .M).AidlInterface.Lang>>
+    "${ANDROID_BUILD_TOP}/<<.Ctx.OtherModuleDir .M>>/<<(getCompilerProperties .M).AidlInterface.AidlRoot>>"
+    "${<<.M.Name>>_SRCS}"
+    "${<<.M.Name>>_AIDLFLAGS}")
 add_library(android::<<.M.Name>> ALIAS <<.M.Name>>)
diff --git a/cc/cmake_module_cc.txt b/cc/cmake_module_cc.txt
index 571f27c..488e5e1 100644
--- a/cc/cmake_module_cc.txt
+++ b/cc/cmake_module_cc.txt
@@ -1,7 +1,7 @@
 <<$srcs := getSources .M>>
 <<$includeDirs := getIncludeDirs .Ctx .M>>
 <<$cflags := (getCompilerProperties .M).Cflags>>
-<<$deps := mapLibraries (concat5
+<<$deps := mapLibraries .Ctx .M (concat5
 (getLinkerProperties .M).Whole_static_libs
 (getLinkerProperties .M).Static_libs
 (getLinkerProperties .M).Shared_libs
diff --git a/cc/cmake_snapshot.go b/cc/cmake_snapshot.go
index 0635a29..c21a46f 100644
--- a/cc/cmake_snapshot.go
+++ b/cc/cmake_snapshot.go
@@ -192,13 +192,16 @@
 		},
 		"getExtraLibs":   getExtraLibs,
 		"getIncludeDirs": getIncludeDirs,
-		"mapLibraries": func(libs []string, mapping map[string]LibraryMappingProperty) []string {
+		"mapLibraries": func(ctx android.ModuleContext, m *Module, libs []string, mapping map[string]LibraryMappingProperty) []string {
 			var mappedLibs []string
 			for _, lib := range libs {
 				mappedLib, exists := mapping[lib]
 				if exists {
 					lib = mappedLib.Mapped_name
 				} else {
+					if !ctx.OtherModuleExists(lib) {
+						ctx.OtherModuleErrorf(m, "Dependency %s doesn't exist", lib)
+					}
 					lib = "android::" + lib
 				}
 				if lib == "" {
@@ -210,6 +213,21 @@
 			mappedLibs = slices.Compact(mappedLibs)
 			return mappedLibs
 		},
+		"getAidlSources": func(m *Module) []string {
+			aidlInterface := m.compiler.baseCompilerProps().AidlInterface
+			aidlRoot := aidlInterface.AidlRoot + string(filepath.Separator)
+			if aidlInterface.AidlRoot == "" {
+				aidlRoot = ""
+			}
+			var sources []string
+			for _, src := range aidlInterface.Sources {
+				if !strings.HasPrefix(src, aidlRoot) {
+					panic(fmt.Sprintf("Aidl source '%v' doesn't start with '%v'", src, aidlRoot))
+				}
+				sources = append(sources, src[len(aidlRoot):])
+			}
+			return sources
+		},
 	}
 
 	return template.Must(template.New("").Delims("<<", ">>").Funcs(funcMap).Parse(templateContents))
@@ -282,14 +300,14 @@
 	var pregeneratedModules []*Module
 	ctx.WalkDeps(func(dep_a android.Module, parent android.Module) bool {
 		moduleName := ctx.OtherModuleName(dep_a)
-		dep, ok := dep_a.(*Module)
-		if !ok {
-			return false // not a cc module
-		}
 		if visited := visitedModules[moduleName]; visited {
 			return false // visit only once
 		}
 		visitedModules[moduleName] = true
+		dep, ok := dep_a.(*Module)
+		if !ok {
+			return false // not a cc module
+		}
 		if mapping, ok := pprop.LibraryMapping[moduleName]; ok {
 			if mapping.Package_pregenerated != "" {
 				pregeneratedModules = append(pregeneratedModules, dep)
diff --git a/cc/compiler.go b/cc/compiler.go
index aee584d..9187b9b 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -147,6 +147,9 @@
 		// list of aidl_interface sources
 		Sources []string `blueprint:"mutated"`
 
+		// root directory of AIDL sources
+		AidlRoot string `blueprint:"mutated"`
+
 		// AIDL backend language (e.g. "cpp", "ndk")
 		Lang string `blueprint:"mutated"`
 
diff --git a/cc/config/global.go b/cc/config/global.go
index 16b5e09..ffd6d7e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -295,6 +295,9 @@
 		// New warnings to be fixed after clang-r475365
 		"-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
 		"-Wno-error=enum-constexpr-conversion",               // http://b/243964282
+		// New warnings to be fixed after clang-r522817
+		"-Wno-error=invalid-offsetof",
+		"-Wno-error=thread-safety-reference-return",
 
 		// Irrelevant on Android because _we_ don't use exceptions, but causes
 		// lots of build noise because libcxx/libcxxabi do. This can probably
@@ -302,6 +305,9 @@
 		// until then because it causes warnings in the _callers_, not the
 		// project itself.
 		"-Wno-deprecated-dynamic-exception-spec",
+
+		// Allow using VLA CXX extension.
+		"-Wno-vla-cxx-extension",
 	}
 
 	noOverride64GlobalCflags = []string{}
@@ -386,7 +392,7 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r510928"
+	ClangDefaultVersion      = "clang-r522817"
 	ClangDefaultShortVersion = "18"
 
 	// Directories with warnings from Android.bp files.
diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go
index 5432806..67b57cc 100644
--- a/cmd/release_config/release_config/main.go
+++ b/cmd/release_config/release_config/main.go
@@ -51,7 +51,7 @@
 	flag.BoolVar(&textproto, "textproto", true, "write artifacts as text protobuf")
 	flag.BoolVar(&json, "json", true, "write artifacts as json")
 	flag.BoolVar(&pb, "pb", true, "write artifacts as binary protobuf")
-	flag.BoolVar(&allMake, "all_make", true, "write makefiles for all release configs")
+	flag.BoolVar(&allMake, "all_make", false, "write makefiles for all release configs")
 	flag.BoolVar(&useBuildVar, "use_get_build_var", false, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS")
 	flag.BoolVar(&guard, "guard", true, "whether to guard with RELEASE_BUILD_FLAGS_IN_PROTOBUF")
 
@@ -92,10 +92,10 @@
 	}
 	if allMake {
 		// Write one makefile per release config, using the canonical release name.
-		for k, _ := range configs.ReleaseConfigs {
-			if k != targetRelease {
-				makefilePath = filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, k))
-				err = configs.WriteMakefile(makefilePath, k)
+		for _, c := range configs.GetSortedReleaseConfigs() {
+			if c.Name != targetRelease {
+				makefilePath = filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, c.Name))
+				err = configs.WriteMakefile(makefilePath, c.Name)
 				if err != nil {
 					panic(err)
 				}
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index 8204822..93410a6 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -91,7 +91,8 @@
 			return fmt.Errorf("Could not inherit flag %s from %s", name, iConfig.Name)
 		}
 		if name == "RELEASE_ACONFIG_VALUE_SETS" {
-			if len(fa.Traces) > 0 {
+			// If there is a value assigned, add the trace.
+			if len(fa.Value.GetStringValue()) > 0 {
 				myFa.Traces = append(myFa.Traces, fa.Traces...)
 				myFa.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{
 					myFa.Value.GetStringValue() + " " + fa.Value.GetStringValue()}}
diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go
index 2487f2e..461ee10 100644
--- a/cmd/release_config/release_config_lib/release_configs.go
+++ b/cmd/release_config/release_config_lib/release_configs.go
@@ -120,6 +120,16 @@
 	return &configs
 }
 
+func (configs *ReleaseConfigs) GetSortedReleaseConfigs() (ret []*ReleaseConfig) {
+	for _, config := range configs.ReleaseConfigs {
+		ret = append(ret, config)
+	}
+	slices.SortFunc(ret, func(a, b *ReleaseConfig) int {
+		return cmp.Compare(a.Name, b.Name)
+	})
+	return ret
+}
+
 func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap) {
 	m = &ReleaseConfigMap{
 		path:                       protoPath,
@@ -283,9 +293,7 @@
 	return nil, fmt.Errorf("Missing config %s.  Trace=%v", name, trace)
 }
 
-// Write the makefile for this targetRelease.
-func (configs *ReleaseConfigs) WriteMakefile(outFile, targetRelease string) error {
-	makeVars := make(map[string]string)
+func (configs *ReleaseConfigs) GetAllReleaseNames() []string {
 	var allReleaseNames []string
 	for _, v := range configs.ReleaseConfigs {
 		allReleaseNames = append(allReleaseNames, v.Name)
@@ -294,6 +302,12 @@
 	slices.SortFunc(allReleaseNames, func(a, b string) int {
 		return cmp.Compare(a, b)
 	})
+	return allReleaseNames
+}
+
+// Write the makefile for this targetRelease.
+func (configs *ReleaseConfigs) WriteMakefile(outFile, targetRelease string) error {
+	makeVars := make(map[string]string)
 	config, err := configs.GetReleaseConfig(targetRelease)
 	if err != nil {
 		return err
@@ -356,7 +370,7 @@
 		data += fmt.Sprintf("# User specified TARGET_RELEASE=%s\n", targetRelease)
 	}
 	// The variable _all_release_configs will get deleted during processing, so do not mark it read-only.
-	data += fmt.Sprintf("_all_release_configs := %s\n", strings.Join(allReleaseNames, " "))
+	data += fmt.Sprintf("_all_release_configs := %s\n", strings.Join(configs.GetAllReleaseNames(), " "))
 	data += fmt.Sprintf("_ALL_RELEASE_FLAGS :=$= %s\n", strings.Join(names, " "))
 	for _, pName := range pNames {
 		data += fmt.Sprintf("_ALL_RELEASE_FLAGS.PARTITIONS.%s :=$= %s\n", pName, strings.Join(partitions[pName], " "))
@@ -388,8 +402,9 @@
 		configs.ReleaseConfigs[name].OtherNames = aliases
 	}
 
-	for _, config := range configs.ReleaseConfigs {
-		err := config.GenerateReleaseConfig(configs)
+	sortedReleaseConfigs := configs.GetSortedReleaseConfigs()
+	for _, c := range sortedReleaseConfigs {
+		err := c.GenerateReleaseConfig(configs)
 		if err != nil {
 			return err
 		}
@@ -399,17 +414,16 @@
 	if err != nil {
 		return err
 	}
+	orc := []*rc_proto.ReleaseConfigArtifact{}
+	for _, c := range sortedReleaseConfigs {
+		if c.Name != releaseConfig.Name {
+			orc = append(orc, c.ReleaseConfigArtifact)
+		}
+	}
+
 	configs.Artifact = rc_proto.ReleaseConfigsArtifact{
-		ReleaseConfig: releaseConfig.ReleaseConfigArtifact,
-		OtherReleaseConfigs: func() []*rc_proto.ReleaseConfigArtifact {
-			orc := []*rc_proto.ReleaseConfigArtifact{}
-			for name, config := range configs.ReleaseConfigs {
-				if name != releaseConfig.Name {
-					orc = append(orc, config.ReleaseConfigArtifact)
-				}
-			}
-			return orc
-		}(),
+		ReleaseConfig:       releaseConfig.ReleaseConfigArtifact,
+		OtherReleaseConfigs: orc,
 		ReleaseConfigMapsMap: func() map[string]*rc_proto.ReleaseConfigMap {
 			ret := make(map[string]*rc_proto.ReleaseConfigMap)
 			for k, v := range configs.releaseConfigMapsMap {
@@ -439,7 +453,8 @@
 
 	configs := ReleaseConfigsFactory()
 	mapsRead := make(map[string]bool)
-	for idx, releaseConfigMapPath := range releaseConfigMapPaths {
+	var idx int
+	for _, releaseConfigMapPath := range releaseConfigMapPaths {
 		// Maintain an ordered list of release config directories.
 		configDir := filepath.Dir(releaseConfigMapPath)
 		if mapsRead[configDir] {
@@ -454,6 +469,7 @@
 		if err != nil {
 			return nil, err
 		}
+		idx += 1
 	}
 
 	// Now that we have all of the release config maps, can meld them and generate the artifacts.
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index 44de202..8daee85 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -22,7 +22,7 @@
 	"github.com/google/blueprint/proptools"
 )
 
-func (f *filesystem) buildAconfigFlagsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, dir android.Path) {
+func (f *filesystem) buildAconfigFlagsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, dir android.OutputPath) {
 	if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) {
 		return
 	}
@@ -31,15 +31,6 @@
 	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())
@@ -47,12 +38,45 @@
 	}
 	caches = android.SortedUniqueStrings(caches)
 
+	var sbCaches strings.Builder
 	for _, cache := range caches {
-		sb.WriteString("  --cache ")
-		sb.WriteString(cache)
-		sb.WriteString(" \\\n")
+		sbCaches.WriteString("  --cache ")
+		sbCaches.WriteString(cache)
+		sbCaches.WriteString(" \\\n")
 	}
+	sbCaches.WriteRune('\n')
+
+	var sb strings.Builder
+	sb.WriteString("set -e\n")
+
+	installAconfigFlagsPath := dir.Join(ctx, "etc", "aconfig_flags.pb")
+	sb.WriteString(aconfigToolPath.String())
+	sb.WriteString(" dump-cache --dedup --format protobuf --out ")
+	sb.WriteString(installAconfigFlagsPath.String())
+	sb.WriteString(" \\\n")
+	sb.WriteString(sbCaches.String())
+	cmd.ImplicitOutput(installAconfigFlagsPath)
+
+	installAconfigStorageDir := dir.Join(ctx, "etc", "aconfig")
+	sb.WriteString("mkdir -p ")
+	sb.WriteString(installAconfigStorageDir.String())
 	sb.WriteRune('\n')
 
+	generatePartitionAconfigStorageFile := func(fileType, fileName string) {
+		sb.WriteString(aconfigToolPath.String())
+		sb.WriteString(" create-storage --container ")
+		sb.WriteString(f.PartitionType())
+		sb.WriteString(" --file ")
+		sb.WriteString(fileType)
+		sb.WriteString(" --out ")
+		sb.WriteString(filepath.Join(installAconfigStorageDir.String(), fileName))
+		sb.WriteString(" \\\n")
+		sb.WriteString(sbCaches.String())
+		cmd.ImplicitOutput(installAconfigStorageDir.Join(ctx, fileName))
+	}
+	generatePartitionAconfigStorageFile("package_map", "package.map")
+	generatePartitionAconfigStorageFile("flag_map", "flag.map")
+	generatePartitionAconfigStorageFile("flag_val", "flag.val")
+
 	android.WriteExecutableFileRuleVerbatim(ctx, aconfigFlagsBuilderPath, sb.String())
 }
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 861918f..015d39a 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -497,3 +497,70 @@
 		android.AssertStringListContains(t, "missing entry", fs.entries, e)
 	}
 }
+
+func TestFilterOutUnsupportedArches(t *testing.T) {
+	result := fixture.RunTestWithBp(t, `
+		android_filesystem {
+			name: "fs_64_only",
+			deps: ["foo"],
+		}
+
+		android_filesystem {
+			name: "fs_64_32",
+			compile_multilib: "both",
+			multilib: {
+				first: {
+					deps: ["foo"],
+				},
+			},
+		}
+
+		cc_binary {
+			name: "foo",
+			required: ["phony"],
+		}
+
+		phony {
+			name: "phony",
+			required: [
+				"libbar",
+				"app",
+			],
+		}
+
+		cc_library {
+			name: "libbar",
+		}
+
+		android_app {
+			name: "app",
+			srcs: ["a.java"],
+			platform_apis: true,
+		}
+	`)
+	testcases := []struct {
+		fsName     string
+		expected   []string
+		unexpected []string
+	}{
+		{
+			fsName:     "fs_64_only",
+			expected:   []string{"app/app/app.apk", "bin/foo", "lib64/libbar.so"},
+			unexpected: []string{"lib/libbar.so"},
+		},
+		{
+			fsName:     "fs_64_32",
+			expected:   []string{"app/app/app.apk", "bin/foo", "lib64/libbar.so", "lib/libbar.so"},
+			unexpected: []string{},
+		},
+	}
+	for _, c := range testcases {
+		fs := result.ModuleForTests(c.fsName, "android_common").Module().(*filesystem)
+		for _, e := range c.expected {
+			android.AssertStringListContains(t, "missing entry", fs.entries, e)
+		}
+		for _, e := range c.unexpected {
+			android.AssertStringListDoesNotContain(t, "unexpected entry", fs.entries, e)
+		}
+	}
+}