Merge "Fix deprecated utcfromtimestamp() usage." into main
diff --git a/core/Makefile b/core/Makefile
index 651b1e0..2051c2c 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -6279,13 +6279,13 @@
   $(foreach device,$(BOARD_SUPER_PARTITION_BLOCK_DEVICES), \
     echo "super_$(device)_device_size=$(BOARD_SUPER_PARTITION_$(call to-upper,$(device))_DEVICE_SIZE)" >> $(1);)
   $(if $(BOARD_SUPER_PARTITION_PARTITION_LIST), \
-    echo "dynamic_partition_list=$(call filter-out-missing-partitions,$(BOARD_SUPER_PARTITION_PARTITION_LIST))" >> $(1))
+    echo "dynamic_partition_list=$(sort $(call filter-out-missing-partitions,$(BOARD_SUPER_PARTITION_PARTITION_LIST)))" >> $(1))
   $(if $(BOARD_SUPER_PARTITION_GROUPS),
     echo "super_partition_groups=$(BOARD_SUPER_PARTITION_GROUPS)" >> $(1))
   $(foreach group,$(BOARD_SUPER_PARTITION_GROUPS), \
     echo "super_$(group)_group_size=$(BOARD_$(call to-upper,$(group))_SIZE)" >> $(1); \
     $(if $(BOARD_$(call to-upper,$(group))_PARTITION_LIST), \
-      echo "super_$(group)_partition_list=$(call filter-out-missing-partitions,$(BOARD_$(call to-upper,$(group))_PARTITION_LIST))" >> $(1);))
+      echo "super_$(group)_partition_list=$(strip $(call filter-out-missing-partitions,$(BOARD_$(call to-upper,$(group))_PARTITION_LIST)))" >> $(1);))
   $(if $(filter true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED)), \
     echo "build_non_sparse_super_partition=true" >> $(1))
   $(if $(filter true,$(TARGET_USERIMAGES_SPARSE_F2FS_DISABLED)), \
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 6aea680..f57ec81 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -108,6 +108,9 @@
 SYSTEMUI_OPTIMIZE_JAVA ?= true
 $(call add_soong_config_var,ANDROID,SYSTEMUI_OPTIMIZE_JAVA)
 
+# Flag to use baseline profile for SystemUI.
+$(call soong_config_set,ANDROID,release_systemui_use_speed_profile,$(RELEASE_SYSTEMUI_USE_SPEED_PROFILE))
+
 # Flag for enabling compose for Launcher.
 $(call soong_config_set,ANDROID,release_enable_compose_in_launcher,$(RELEASE_ENABLE_COMPOSE_IN_LAUNCHER))
 
@@ -216,6 +219,19 @@
 # Required as platform_bootclasspath is using this namespace
 $(call soong_config_set,bootclasspath,release_crashrecovery_module,$(RELEASE_CRASHRECOVERY_MODULE))
 
+
+# Add ondeviceintelligence module build flag to soong
+ifeq (true,$(RELEASE_ONDEVICE_INTELLIGENCE_MODULE))
+    $(call soong_config_set,ANDROID,release_ondevice_intelligence_module,true)
+    # Required as platform_bootclasspath is using this namespace
+    $(call soong_config_set,bootclasspath,release_ondevice_intelligence_module,true)
+
+else
+    $(call soong_config_set,ANDROID,release_ondevice_intelligence_platform,true)
+    $(call soong_config_set,bootclasspath,release_ondevice_intelligence_platform,true)
+
+endif
+
 # Add uprobestats build flag to soong
 $(call soong_config_set,ANDROID,release_uprobestats_module,$(RELEASE_UPROBESTATS_MODULE))
 # Add uprobestats file move flags to soong, for both platform and module
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 9ffe518..604fe06 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -214,6 +214,22 @@
   actual_partition_tag := $(if $(partition_tag),data,system)
 endif
 endif
+
+# if this is a soong module, verify that LOCAL_COMPATIBILITY_SUITE (legacy) matches
+# LOCAL_SOONG_PROVIDER_TEST_SUITES (new, via TestSuiteInfoProvider instead of AndroidMk stuff),
+# modulo "null-sute", "mts", and "mcts". mts/mcts are automatically added if there's a different
+# suite starting with "m(c)ts-". null-suite seems useless and is sometimes automatically added
+# if no other suites are added.
+ifneq (,$(filter $(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK)))
+  a := $(filter-out null-suite mts mcts,$(sort $(LOCAL_COMPATIBILITY_SUITE)))
+  b := $(filter-out null-suite mts mcts,$(sort $(LOCAL_SOONG_PROVIDER_TEST_SUITES)))
+  ifneq ($(a),$(b))
+    $(error $(LOCAL_MODULE): LOCAL_COMPATIBILITY_SUITE did not match LOCAL_SOONG_PROVIDER_TEST_SUITES$(newline)  LOCAL_COMPATIBILITY_SUITE: $(a)$(newline)  LOCAL_SOONG_PROVIDER_TEST_SUITES: $(b)$(newline))
+  endif
+  a :=
+  b :=
+endif
+
 # For test modules that lack a suite tag, set null-suite as the default.
 # We only support adding a default suite to native tests, native benchmarks, and instrumentation tests.
 # This is because they are the only tests we currently auto-generate test configs for.
diff --git a/core/board_config.mk b/core/board_config.mk
index ad89c03..16cf863 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -225,6 +225,7 @@
       $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
       device/generic/goldfish/board/$(TARGET_DEVICE)/BoardConfig.mk \
       device/google/cuttlefish/board/$(TARGET_DEVICE)/BoardConfig.mk \
+      vendor/google/products/cuttlefish/pixel_watch/board/$(TARGET_DEVICE)/BoardConfig.mk \
       $(shell test -d device && find -L device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
       $(shell test -d vendor && find -L vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
     )))
@@ -289,6 +290,7 @@
     $(error Valid values of $(var) are "true", "false", and "". Not "$($(var))")))
 
 include $(BUILD_SYSTEM)/board_config_wifi.mk
+include $(BUILD_SYSTEM)/board_config_wpa_supplicant.mk
 
 # Set up soong config for "soong_config_value_variable".
 -include hardware/interfaces/configstore/1.1/default/surfaceflinger.mk
diff --git a/core/board_config_wpa_supplicant.mk b/core/board_config_wpa_supplicant.mk
new file mode 100644
index 0000000..9ef438e
--- /dev/null
+++ b/core/board_config_wpa_supplicant.mk
@@ -0,0 +1,88 @@
+#
+# 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.
+#
+
+# ###############################################################
+# This file adds wpa_supplicant_8 variables into soong config namespace (`wpa_supplicant_8`)
+# ###############################################################
+
+ifdef BOARD_HOSTAPD_DRIVER
+$(call soong_config_set_bool,wpa_supplicant_8,wpa_build_hostapd,true)
+ifneq ($(BOARD_HOSTAPD_DRIVER),NL80211)
+    $(error BOARD_HOSTAPD_DRIVER set to $(BOARD_HOSTAPD_DRIVER) but current soong expected it should be NL80211 only!)
+endif
+endif
+
+ifdef BOARD_WPA_SUPPLICANT_DRIVER
+ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),NL80211)
+    $(error BOARD_WPA_SUPPLICANT_DRIVER set to $(BOARD_WPA_SUPPLICANT_DRIVER) but current soong expected it should be NL80211 only!)
+endif
+endif
+
+# This is for CONFIG_DRIVER_NL80211_BRCM, CONFIG_DRIVER_NL80211_SYNA, CONFIG_DRIVER_NL80211_QCA
+# And it is only used for a cflags setting in driver.
+$(call soong_config_set,wpa_supplicant_8,board_wlan_device,$(BOARD_WLAN_DEVICE))
+
+# Belong to CONFIG_IEEE80211AX definition
+ifeq ($(WIFI_FEATURE_HOSTAPD_11AX),true)
+$(call soong_config_set_bool,wpa_supplicant_8,hostapd_11ax,true)
+endif
+
+# Belong to CONFIG_IEEE80211BE definition
+ifeq ($(WIFI_FEATURE_HOSTAPD_11BE),true)
+$(call soong_config_set_bool,wpa_supplicant_8,hostapd_11be,true)
+endif
+
+# PLATFORM_VERSION
+$(call soong_config_set,wpa_supplicant_8,platform_version,$(PLATFORM_VERSION))
+
+# BOARD_HOSTAPD_PRIVATE_LIB
+ifeq ($(BOARD_HOSTAPD_PRIVATE_LIB),)
+$(call soong_config_set_bool,wpa_supplicant_8,hostapd_use_stub_lib,true)
+else
+$(call soong_config_set,wpa_supplicant_8,board_hostapd_private_lib,$(BOARD_HOSTAPD_PRIVATE_LIB))
+endif
+
+ifeq ($(BOARD_HOSTAPD_CONFIG_80211W_MFP_OPTIONAL),true)
+$(call soong_config_set_bool,wpa_supplicant_8,board_hostapd_config_80211w_mfp_optional,true)
+endif
+
+ifneq ($(BOARD_HOSTAPD_PRIVATE_LIB_EVENT),)
+$(call soong_config_set_bool,wpa_supplicant_8,board_hostapd_private_lib_event,true)
+endif
+
+# BOARD_WPA_SUPPLICANT_PRIVATE_LIB
+ifeq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB),)
+$(call soong_config_set_bool,wpa_supplicant_8,wpa_supplicant_use_stub_lib,true)
+else
+$(call soong_config_set,wpa_supplicant_8,board_wpa_supplicant_private_lib,$(BOARD_WPA_SUPPLICANT_PRIVATE_LIB))
+endif
+
+ifneq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB_EVENT),)
+$(call soong_config_set_bool,wpa_supplicant_8,board_wpa_supplicant_private_lib_event,true)
+endif
+
+ifeq ($(WIFI_PRIV_CMD_UPDATE_MBO_CELL_STATUS), enabled)
+$(call soong_config_set_bool,wpa_supplicant_8,wifi_priv_cmd_update_mbo_cell_status,true)
+endif
+
+ifeq ($(WIFI_HIDL_UNIFIED_SUPPLICANT_SERVICE_RC_ENTRY), true)
+$(call soong_config_set_bool,wpa_supplicant_8,wifi_hidl_unified_supplicant_service_rc_entry,true)
+endif
+
+# New added in internal main
+ifeq ($(WIFI_BRCM_OPEN_SOURCE_MULTI_AKM), enabled)
+$(call soong_config_set_bool,wpa_supplicant_8,wifi_brcm_open_source_multi_akm,true)
+endif
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 2e67aff..8a98c13 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -271,6 +271,7 @@
 LOCAL_SOONG_MODULE_TYPE :=
 LOCAL_SOONG_PROGUARD_DICT :=
 LOCAL_SOONG_PROGUARD_USAGE_ZIP :=
+LOCAL_SOONG_PROVIDER_TEST_SUITES :=
 LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=
 LOCAL_SOONG_TRANSITIVE_RES_PACKAGES :=
 LOCAL_SOONG_DEVICE_RRO_DIRS :=
diff --git a/core/layoutlib_data.mk b/core/layoutlib_data.mk
index dabcfb2..f228ef6 100644
--- a/core/layoutlib_data.mk
+++ b/core/layoutlib_data.mk
@@ -3,11 +3,10 @@
 FONT_TEMP := $(call intermediates-dir-for,PACKAGING,fonts,HOST,COMMON)
 
 # The font configuration files - system_fonts.xml, fallback_fonts.xml etc.
-font_config := $(sort $(wildcard frameworks/base/data/fonts/*.xml))
+font_config := $(filter $(TARGET_OUT)/etc/font%.xml, $(INTERNAL_SYSTEMIMAGE_FILES))
 font_config := $(addprefix $(FONT_TEMP)/, $(notdir $(font_config)))
 
-$(font_config): $(FONT_TEMP)/%.xml: \
-			frameworks/base/data/fonts/%.xml
+$(font_config): $(FONT_TEMP)/%: $(TARGET_OUT)/etc/%
 	$(hide) mkdir -p $(dir $@)
 	$(hide) cp -vf $< $@
 
diff --git a/core/soong_config.mk b/core/soong_config.mk
index c3cbaf3..f5c5238 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -467,6 +467,7 @@
   $(call add_json_bool, ProductUseDynamicPartitions, $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITIONS)))
   $(call add_json_bool, ProductRetrofitDynamicPartitions, $(filter true,$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS)))
   $(call add_json_bool, ProductBuildSuperPartition, $(filter true,$(PRODUCT_BUILD_SUPER_PARTITION)))
+  $(call add_json_bool, BuildingSuperEmptyImage, $(filter true,$(BUILDING_SUPER_EMPTY_IMAGE)))
   $(call add_json_str, BoardSuperPartitionSize, $(BOARD_SUPER_PARTITION_SIZE))
   $(call add_json_str, BoardSuperPartitionMetadataDevice, $(BOARD_SUPER_PARTITION_METADATA_DEVICE))
   $(call add_json_list, BoardSuperPartitionBlockDevices, $(BOARD_SUPER_PARTITION_BLOCK_DEVICES))
diff --git a/core/sysprop.mk b/core/sysprop.mk
index 9a9f509..5485a3a 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -79,6 +79,7 @@
     echo "ro.$(1).build.version.release=$(PLATFORM_VERSION_LAST_STABLE)" >> $(2);\
     echo "ro.$(1).build.version.release_or_codename=$(PLATFORM_VERSION)" >> $(2);\
     echo "ro.$(1).build.version.sdk=$(PLATFORM_SDK_VERSION)" >> $(2);\
+    echo "ro.$(1).build.version.sdk_minor=$(PLATFORM_SDK_MINOR_VERSION)" >> $(2);\
 
 endef
 
diff --git a/core/version_util.mk b/core/version_util.mk
index 2bf41ec..ddcbda2 100644
--- a/core/version_util.mk
+++ b/core/version_util.mk
@@ -62,6 +62,12 @@
 PLATFORM_SDK_VERSION := $(RELEASE_PLATFORM_SDK_VERSION)
 .KATI_READONLY := PLATFORM_SDK_VERSION
 
+ifdef PLATFORM_SDK_MINOR_VERSION
+  $(error Do not set PLATFORM_SDK_MINOR_VERSION directly. Use RELEASE_PLATFORM_SDK_MINOR_VERSION. value: $(PLATFORM_SDK_MINOR_VERSION))
+endif
+PLATFORM_SDK_MINOR_VERSION := $(RELEASE_PLATFORM_SDK_MINOR_VERSION)
+.KATI_READONLY := PLATFORM_SDK_MINOR_VERSION
+
 ifdef PLATFORM_SDK_EXTENSION_VERSION
   $(error Do not set PLATFORM_SDK_EXTENSION_VERSION directly. Use RELEASE_PLATFORM_SDK_EXTENSION_VERSION. value: $(PLATFORM_SDK_EXTENSION_VERSION))
 endif
diff --git a/shell_utils.sh b/shell_utils.sh
index 3124db5..61b0ebc 100644
--- a/shell_utils.sh
+++ b/shell_utils.sh
@@ -97,8 +97,11 @@
   local out_dir=$(getoutdir)
   local top=$(gettop)
 
-  # return early if out dir is already a symlink
+  # return early if out dir is already a symlink.
   if [[ -L "$out_dir" ]]; then
+    destination=$(readlink "$out_dir")
+    # ensure the destination exists.
+    mkdir -p "$destination"
     return 0
   fi
 
diff --git a/target/product/app_function_extensions.mk b/target/product/app_function_extensions.mk
index a61afdc..e601fd7 100644
--- a/target/product/app_function_extensions.mk
+++ b/target/product/app_function_extensions.mk
@@ -18,5 +18,5 @@
 
 # /system_ext packages
 PRODUCT_PACKAGES += \
-    com.google.android.appfunctions.sidecar \
-    appfunctions.sidecar.xml
+    com.android.extensions.appfunctions \
+    appfunctions.extension.xml
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index ef70fce..3fe97ba 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -205,7 +205,6 @@
     libstdc++ \
     libsysutils \
     libui \
-    libuprobestats_client \
     libusbhost \
     libutils \
     libvintf_jni \
@@ -310,8 +309,20 @@
   PRODUCT_PACKAGES += \
         com.android.crashrecovery \
 
+else
+  PRODUCT_PACKAGES += \
+    framework-platformcrashrecovery \
+
 endif
 
+# When we release ondeviceintelligence in neuralnetworks module
+ifneq ($(RELEASE_ONDEVICE_INTELLIGENCE_MODULE),true)
+  PRODUCT_PACKAGES += \
+        framework-ondeviceintelligence-platform
+
+endif
+
+
 # When we release uprobestats module
 ifeq ($(RELEASE_UPROBESTATS_MODULE),true)
     PRODUCT_PACKAGES += \
@@ -320,6 +331,7 @@
 else
     PRODUCT_PACKAGES += \
         uprobestats \
+        libuprobestats_client \
 
 endif
 
@@ -350,8 +362,7 @@
 # Check if the build supports Profiling module
 ifeq ($(RELEASE_PACKAGE_PROFILING_MODULE),true)
     PRODUCT_PACKAGES += \
-       com.android.profiling \
-       trace_redactor
+       com.android.profiling
 endif
 
 ifeq ($(RELEASE_USE_WEBVIEW_BOOTSTRAP_MODULE),true)
@@ -374,6 +385,9 @@
 ifeq ($(RELEASE_MEMORY_MANAGEMENT_DAEMON),true)
   PRODUCT_PACKAGES += \
         mm_daemon
+else
+  PRODUCT_PACKAGES += \
+        init-mmd-prop.rc
 endif
 
 # VINTF data for system image
diff --git a/target/product/base_system_ext.mk b/target/product/base_system_ext.mk
index febe537..6767b9a 100644
--- a/target/product/base_system_ext.mk
+++ b/target/product/base_system_ext.mk
@@ -30,3 +30,8 @@
 PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
     hwservicemanager \
     android.hidl.allocator@1.0-service \
+
+# AppFunction Extensions
+ifneq (,$(RELEASE_APPFUNCTION_SIDECAR))
+    $(call inherit-product, $(SRC_TARGET_DIR)/product/app_function_extensions.mk)
+endif
\ No newline at end of file
diff --git a/target/product/build_variables.mk b/target/product/build_variables.mk
index 8e1de8f..562e5b7 100644
--- a/target/product/build_variables.mk
+++ b/target/product/build_variables.mk
@@ -32,5 +32,8 @@
 # Use the configured MessageQueue implementation
 $(call soong_config_set, messagequeue, release_package_messagequeue_implementation, $(RELEASE_PACKAGE_MESSAGEQUEUE_IMPLEMENTATION))
 
+# Use the configured version of WebView
+$(call soong_config_set, webview, release_package_webview_version, $(RELEASE_PACKAGE_WEBVIEW_VERSION))
+
 # Use the configured version of Cronet
 $(call soong_config_set,cronet,enable_cronet_tot,$(RELEASE_ENABLE_TOT_CRONET))
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index e543ccf..f91cb07 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -90,11 +90,27 @@
     com.android.virt:framework-virtualization \
     com.android.wifi:framework-wifi \
 
-# When we release crashrecovery module
+# When crashrecovery module is ready use apex jar
+# else put the platform jar in system
 ifeq ($(RELEASE_CRASHRECOVERY_MODULE),true)
-  PRODUCT_APEX_BOOT_JARS += \
+    PRODUCT_APEX_BOOT_JARS += \
         com.android.crashrecovery:framework-crashrecovery \
 
+else
+    PRODUCT_BOOT_JARS += \
+        framework-platformcrashrecovery \
+
+endif
+
+# When we release ondeviceintelligence in NeuralNetworks module
+ifeq ($(RELEASE_ONDEVICE_INTELLIGENCE_MODULE),true)
+    PRODUCT_APEX_BOOT_JARS += \
+    com.android.neuralnetworks:framework-ondeviceintelligence \
+
+else
+    PRODUCT_BOOT_JARS += \
+        framework-ondeviceintelligence-platform \
+
 endif
 
 # Check if the build supports NFC apex or not
@@ -153,6 +169,13 @@
 
 endif
 
+# When we release ondeviceintelligence in NeuralNetworks module
+ifeq ($(RELEASE_ONDEVICE_INTELLIGENCE_MODULE),true)
+    PRODUCT_APEX_SYSTEM_SERVER_JARS += \
+        com.android.neuralnetworks:service-ondeviceintelligence
+
+endif
+
 ifeq ($(RELEASE_AVF_ENABLE_LLPVM_CHANGES),true)
   PRODUCT_APEX_SYSTEM_SERVER_JARS += com.android.virt:service-virtualization
 endif
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index 38fa688..c90c61c 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -393,8 +393,8 @@
         "charger",
     ] + select(release_flag("RELEASE_APPFUNCTION_SIDECAR"), {
         true: [
-            "com.google.android.appfunctions.sidecar",
-            "appfunctions.sidecar.xml",
+            "com.android.extensions.appfunctions",
+            "appfunctions.extension.xml",
         ],
         default: [],
     }),
@@ -694,16 +694,13 @@
         default: [
             "android.software.preview_sdk.prebuilt.xml", // media_system
         ],
-    }) + select(soong_config_variable("ANDROID", "release_package_profiling_module"), {
-        "true": [
-            "trace_redactor", // base_system (RELEASE_PACKAGE_PROFILING_MODULE)
-        ],
-        default: [],
     }) + select(release_flag("RELEASE_MEMORY_MANAGEMENT_DAEMON"), {
         true: [
             "mm_daemon", // base_system (RELEASE_MEMORY_MANAGEMENT_DAEMON)
         ],
-        default: [],
+        default: [
+            "init-mmd-prop.rc", // base_system
+        ],
     }) + select(product_variable("debuggable"), {
         true: [
             "alloctop",
@@ -868,7 +865,16 @@
                 "true": [
                     "com.android.crashrecovery", // base_system (RELEASE_CRASHRECOVERY_MODULE)
                 ],
-                default: [],
+                default: [
+                    "framework-platformcrashrecovery", // base_system
+                ],
+            }) + select(release_flag("RELEASE_ONDEVICE_INTELLIGENCE_MODULE"), {
+                true: [
+                    "com.android.neuralnetworks", // base_system (RELEASE_ONDEVICE_INTELLIGENCE_MODULE)
+                ],
+                default: [
+                    "framework-ondeviceintelligence-platform", // base_system
+                ],
             }) + select(soong_config_variable("ANDROID", "release_package_profiling_module"), {
                 "true": [
                     "com.android.profiling", // base_system (RELEASE_PACKAGE_PROFILING_MODULE)
diff --git a/target/product/media_system_ext.mk b/target/product/media_system_ext.mk
index 1179966..e79a7eb 100644
--- a/target/product/media_system_ext.mk
+++ b/target/product/media_system_ext.mk
@@ -22,8 +22,3 @@
 
 # Window Extensions
 $(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions_base.mk)
-
-# AppFunction Extensions
-ifneq (,$(RELEASE_APPFUNCTION_SIDECAR))
-    $(call inherit-product, $(SRC_TARGET_DIR)/product/app_function_extensions.mk)
-endif
diff --git a/tools/aconfig/Cargo.toml b/tools/aconfig/Cargo.toml
index a031b7f..cb8377e 100644
--- a/tools/aconfig/Cargo.toml
+++ b/tools/aconfig/Cargo.toml
@@ -8,8 +8,8 @@
     "aconfig_storage_read_api",
     "aconfig_storage_write_api",
     "aflags",
-    "printflags",
-    "convert_finalized_flags"
+    "convert_finalized_flags",
+    "exported_flag_check",
 ]
 
 resolver = "2"
diff --git a/tools/aconfig/OWNERS b/tools/aconfig/OWNERS
index c92fc7c..0c31938 100644
--- a/tools/aconfig/OWNERS
+++ b/tools/aconfig/OWNERS
@@ -1,6 +1,5 @@
 dzshen@google.com
 opg@google.com
-tedbauer@google.com
 zhidou@google.com
 
 amhk@google.com  #{LAST_RESORT_SUGGESTION}
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 61802f2..d74e87a 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -59,7 +59,8 @@
     let runtime_lookup_required =
         flag_elements.iter().any(|elem| elem.is_read_write) || library_exported;
     let container = (flag_elements.first().expect("zero template flags").container).to_string();
-    let is_platform_container = matches!(container.as_str(), "system" | "product" | "vendor");
+    let is_platform_container =
+        matches!(container.as_str(), "system" | "system_ext" | "product" | "vendor");
     let context = Context {
         flag_elements,
         namespace_flags,
diff --git a/tools/aconfig/exported_flag_check/Android.bp b/tools/aconfig/exported_flag_check/Android.bp
new file mode 100644
index 0000000..184149a
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/Android.bp
@@ -0,0 +1,28 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+    name: "exported-flag-check-defaults",
+    edition: "2021",
+    clippy_lints: "android",
+    lints: "android",
+    srcs: ["src/main.rs"],
+    rustlibs: [
+        "libaconfig_protos",
+        "libanyhow",
+        "libclap",
+        "libregex",
+    ],
+}
+
+rust_binary_host {
+    name: "exported-flag-check",
+    defaults: ["record-finalized-flags-defaults"],
+}
+
+rust_test_host {
+    name: "exported-flag-check-test",
+    defaults: ["record-finalized-flags-defaults"],
+    test_suites: ["general-tests"],
+}
diff --git a/tools/aconfig/exported_flag_check/Cargo.toml b/tools/aconfig/exported_flag_check/Cargo.toml
new file mode 100644
index 0000000..6bc07c5
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "exported-flag-check"
+version = "0.1.0"
+edition = "2021"
+
+[features]
+default = ["cargo"]
+cargo = []
+
+[dependencies]
+aconfig_protos = { path = "../aconfig_protos" }
+anyhow = "1.0.69"
+clap = { version = "4.1.8", features = ["derive"] }
+regex = "1.11.1"
diff --git a/tools/aconfig/exported_flag_check/allow_list.txt b/tools/aconfig/exported_flag_check/allow_list.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/allow_list.txt
diff --git a/tools/aconfig/exported_flag_check/src/main.rs b/tools/aconfig/exported_flag_check/src/main.rs
new file mode 100644
index 0000000..866a700
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/src/main.rs
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+//! `exported-flag-check` is a tool to ensures that exported flags are used as intended
+use anyhow::{ensure, Result};
+use clap::Parser;
+use std::{collections::HashSet, fs::File, path::PathBuf};
+
+mod utils;
+
+use utils::{
+    check_all_exported_flags, extract_flagged_api_flags, get_exported_flags_from_binary_proto,
+    read_finalized_flags,
+};
+
+const ABOUT: &str = "CCheck Exported Flags
+
+This tool ensures that exported flags are used as intended. Exported flags, marked with
+`is_exported: true` in their declaration, are designed to control access to specific API
+features. This tool identifies and reports any exported flags that are not currently
+associated with an API feature, preventing unnecessary flag proliferation and maintaining
+a clear API design.
+
+This tool works as follows:
+
+  - Read API signature files from source tree (*current.txt files) [--api-signature-file]
+  - Read the current aconfig flag values from source tree [--parsed-flags-file]
+  - Read the previous finalized-flags.txt files from prebuilts/sdk [--finalized-flags-file]
+  - Extract the flags slated for API by scanning through the API signature files
+  - Merge the found flags with the recorded flags from previous API finalizations
+  - Error if exported flags are not in the set
+";
+
+#[derive(Parser, Debug)]
+#[clap(about=ABOUT)]
+struct Cli {
+    #[arg(long)]
+    parsed_flags_file: PathBuf,
+
+    #[arg(long)]
+    api_signature_file: Vec<PathBuf>,
+
+    #[arg(long)]
+    finalized_flags_file: PathBuf,
+}
+
+fn main() -> Result<()> {
+    let args = Cli::parse();
+
+    let mut flags_used_with_flaggedapi_annotation = HashSet::new();
+    for path in &args.api_signature_file {
+        let file = File::open(path)?;
+        let flags = extract_flagged_api_flags(file)?;
+        flags_used_with_flaggedapi_annotation.extend(flags);
+    }
+
+    let file = File::open(args.parsed_flags_file)?;
+    let all_flags = get_exported_flags_from_binary_proto(file)?;
+
+    let file = File::open(args.finalized_flags_file)?;
+    let already_finalized_flags = read_finalized_flags(file)?;
+
+    let exported_flags = check_all_exported_flags(
+        &flags_used_with_flaggedapi_annotation,
+        &all_flags,
+        &already_finalized_flags,
+    )?;
+
+    println!("{}", exported_flags.join("\n"));
+
+    ensure!(
+        exported_flags.is_empty(),
+        "Flags {} are exported but not used to guard any API. \
+    Exported flag should be used to guard API",
+        exported_flags.join(",")
+    );
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test() {
+        let input = include_bytes!("../tests/api-signature-file.txt");
+        let flags_used_with_flaggedapi_annotation = extract_flagged_api_flags(&input[..]).unwrap();
+
+        let input = include_bytes!("../tests/flags.protobuf");
+        let all_flags_to_be_finalized = get_exported_flags_from_binary_proto(&input[..]).unwrap();
+
+        let input = include_bytes!("../tests/finalized-flags.txt");
+        let already_finalized_flags = read_finalized_flags(&input[..]).unwrap();
+
+        let exported_flags = check_all_exported_flags(
+            &flags_used_with_flaggedapi_annotation,
+            &all_flags_to_be_finalized,
+            &already_finalized_flags,
+        )
+        .unwrap();
+
+        assert_eq!(1, exported_flags.len());
+    }
+}
diff --git a/tools/aconfig/exported_flag_check/src/utils.rs b/tools/aconfig/exported_flag_check/src/utils.rs
new file mode 100644
index 0000000..2c30424
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/src/utils.rs
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+use aconfig_protos::ParsedFlagExt;
+use anyhow::{anyhow, Context, Result};
+use regex::Regex;
+use std::{
+    collections::HashSet,
+    io::{BufRead, BufReader, Read},
+};
+
+pub(crate) type FlagId = String;
+
+/// Grep for all flags used with @FlaggedApi annotations in an API signature file (*current.txt
+/// file).
+pub(crate) fn extract_flagged_api_flags<R: Read>(mut reader: R) -> Result<HashSet<FlagId>> {
+    let mut haystack = String::new();
+    reader.read_to_string(&mut haystack)?;
+    let regex = Regex::new(r#"(?ms)@FlaggedApi\("(.*?)"\)"#).unwrap();
+    let iter = regex.captures_iter(&haystack).map(|cap| cap[1].to_owned());
+    Ok(HashSet::from_iter(iter))
+}
+
+/// Read a list of flag names. The input is expected to be plain text, with each line containing
+/// the name of a single flag.
+pub(crate) fn read_finalized_flags<R: Read>(reader: R) -> Result<HashSet<FlagId>> {
+    BufReader::new(reader)
+        .lines()
+        .map(|line_result| line_result.context("Failed to read line from finalized flags file"))
+        .collect()
+}
+
+/// Parse a ProtoParsedFlags binary protobuf blob and return the fully qualified names of flags
+/// have is_exported as true.
+pub(crate) fn get_exported_flags_from_binary_proto<R: Read>(
+    mut reader: R,
+) -> Result<HashSet<FlagId>> {
+    let mut buffer = Vec::new();
+    reader.read_to_end(&mut buffer)?;
+    let parsed_flags = aconfig_protos::parsed_flags::try_from_binary_proto(&buffer)
+        .map_err(|_| anyhow!("failed to parse binary proto"))?;
+    let iter = parsed_flags
+        .parsed_flag
+        .into_iter()
+        .filter(|flag| flag.is_exported())
+        .map(|flag| flag.fully_qualified_name());
+    Ok(HashSet::from_iter(iter))
+}
+
+fn get_allow_list() -> Result<HashSet<FlagId>> {
+    let allow_list: HashSet<FlagId> =
+        include_str!("../allow_list.txt").lines().map(|x| x.into()).collect();
+    Ok(allow_list)
+}
+
+/// Filter out the flags have is_exported as true but not used with @FlaggedApi annotations
+/// in the source tree, or in the previously finalized flags set.
+pub(crate) fn check_all_exported_flags(
+    flags_used_with_flaggedapi_annotation: &HashSet<FlagId>,
+    all_flags: &HashSet<FlagId>,
+    already_finalized_flags: &HashSet<FlagId>,
+) -> Result<Vec<FlagId>> {
+    let allow_list = get_allow_list()?;
+    let new_flags: Vec<FlagId> = all_flags
+        .difference(flags_used_with_flaggedapi_annotation)
+        .cloned()
+        .collect::<HashSet<_>>()
+        .difference(already_finalized_flags)
+        .cloned()
+        .collect::<HashSet<_>>()
+        .difference(&allow_list)
+        .cloned()
+        .collect();
+
+    Ok(new_flags.into_iter().collect())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_extract_flagged_api_flags() {
+        let api_signature_file = include_bytes!("../tests/api-signature-file.txt");
+        let flags = extract_flagged_api_flags(&api_signature_file[..]).unwrap();
+        assert_eq!(
+            flags,
+            HashSet::from_iter(vec![
+                "record_finalized_flags.test.foo".to_string(),
+                "this.flag.is.not.used".to_string(),
+            ])
+        );
+    }
+
+    #[test]
+    fn test_read_finalized_flags() {
+        let input = include_bytes!("../tests/finalized-flags.txt");
+        let flags = read_finalized_flags(&input[..]).unwrap();
+        assert_eq!(
+            flags,
+            HashSet::from_iter(vec![
+                "record_finalized_flags.test.bar".to_string(),
+                "record_finalized_flags.test.baz".to_string(),
+            ])
+        );
+    }
+
+    #[test]
+    fn test_disabled_or_read_write_flags_are_ignored() {
+        let bytes = include_bytes!("../tests/flags.protobuf");
+        let flags = get_exported_flags_from_binary_proto(&bytes[..]).unwrap();
+        assert_eq!(
+            flags,
+            HashSet::from_iter(vec![
+                "record_finalized_flags.test.foo".to_string(),
+                "record_finalized_flags.test.not_enabled".to_string()
+            ])
+        );
+    }
+}
diff --git a/tools/aconfig/exported_flag_check/tests/api-signature-file.txt b/tools/aconfig/exported_flag_check/tests/api-signature-file.txt
new file mode 100644
index 0000000..2ad559f
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/tests/api-signature-file.txt
@@ -0,0 +1,15 @@
+// Signature format: 2.0
+package android {
+
+  public final class C {
+    ctor public C();
+  }
+
+  public static final class C.inner {
+    ctor public C.inner();
+    field @FlaggedApi("record_finalized_flags.test.foo") public static final String FOO = "foo";
+    field @FlaggedApi("this.flag.is.not.used") public static final String BAR = "bar";
+  }
+
+}
+
diff --git a/tools/aconfig/exported_flag_check/tests/finalized-flags.txt b/tools/aconfig/exported_flag_check/tests/finalized-flags.txt
new file mode 100644
index 0000000..7fbcb3d
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/tests/finalized-flags.txt
@@ -0,0 +1,2 @@
+record_finalized_flags.test.bar
+record_finalized_flags.test.baz
diff --git a/tools/aconfig/exported_flag_check/tests/flags.declarations b/tools/aconfig/exported_flag_check/tests/flags.declarations
new file mode 100644
index 0000000..f86dbfa
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/tests/flags.declarations
@@ -0,0 +1,18 @@
+package: "record_finalized_flags.test"
+container: "system"
+
+flag {
+    name: "foo"
+    namespace: "test"
+    description: "FIXME"
+    bug: ""
+    is_exported:true
+}
+
+flag {
+    name: "not_enabled"
+    namespace: "test"
+    description: "FIXME"
+    bug: ""
+    is_exported:true
+}
diff --git a/tools/aconfig/exported_flag_check/tests/flags.protobuf b/tools/aconfig/exported_flag_check/tests/flags.protobuf
new file mode 100644
index 0000000..be64ef9
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/tests/flags.protobuf
Binary files differ
diff --git a/tools/aconfig/exported_flag_check/tests/flags.values b/tools/aconfig/exported_flag_check/tests/flags.values
new file mode 100644
index 0000000..ff6225d
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/tests/flags.values
@@ -0,0 +1,13 @@
+flag_value {
+    package: "record_finalized_flags.test"
+    name: "foo"
+    state: ENABLED
+    permission: READ_ONLY
+}
+
+flag_value {
+    package: "record_finalized_flags.test"
+    name: "not_enabled"
+    state: DISABLED
+    permission: READ_ONLY
+}
diff --git a/tools/aconfig/exported_flag_check/tests/generate-flags-protobuf.sh b/tools/aconfig/exported_flag_check/tests/generate-flags-protobuf.sh
new file mode 100755
index 0000000..701189c
--- /dev/null
+++ b/tools/aconfig/exported_flag_check/tests/generate-flags-protobuf.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+aconfig create-cache \
+    --package record_finalized_flags.test \
+    --container system \
+    --declarations flags.declarations \
+    --values flags.values \
+    --cache flags.protobuf
diff --git a/tools/aconfig/fake_device_config/src/android/os/Build.java b/tools/aconfig/fake_device_config/src/android/os/Build.java
index 8ec72fb..790ff82 100644
--- a/tools/aconfig/fake_device_config/src/android/os/Build.java
+++ b/tools/aconfig/fake_device_config/src/android/os/Build.java
@@ -18,6 +18,9 @@
 
 public class Build {
     public static class VERSION {
-        public static final int SDK_INT = 0;
+        public static final int SDK_INT = placeholder();
+        private static int placeholder() {
+            throw new UnsupportedOperationException("Stub!");
+        }
     }
 }
diff --git a/tools/finalization/environment.sh b/tools/finalization/environment.sh
index 0d3a9e1..c76980d 100755
--- a/tools/finalization/environment.sh
+++ b/tools/finalization/environment.sh
@@ -34,3 +34,4 @@
 export FINAL_CORRESPONDING_PLATFORM_VERSION='16'
 export FINAL_NEXT_BOARD_API_LEVEL='202604'
 export FINAL_NEXT_CORRESPONDING_VERSION_LETTER='C'
+export FINAL_NEXT_CORRESPONDING_SDK_VERSION='37'
diff --git a/tools/finalization/finalize-vintf-resources.sh b/tools/finalization/finalize-vintf-resources.sh
index 6f1a6f6..45efc10 100755
--- a/tools/finalization/finalize-vintf-resources.sh
+++ b/tools/finalization/finalize-vintf-resources.sh
@@ -16,6 +16,13 @@
     export TARGET_RELEASE=fina_0
     export TARGET_PRODUCT=aosp_arm64
 
+    # build/soong
+    local vendor_api_level_map="case ${FINAL_NEXT_BOARD_API_LEVEL}:"
+    if ! grep -q "$vendor_api_level_map" "$top/build/soong/android/vendor_api_levels.go" ; then
+        sed -i -e "/case ${FINAL_BOARD_API_LEVEL}:/{N;a \\\t$vendor_api_level_map\n\t\tsdkVersion = ${FINAL_NEXT_CORRESPONDING_SDK_VERSION}
+        }" "$top/build/soong/android/vendor_api_levels.go"
+    fi
+
     # system/sepolicy
     "$top/system/sepolicy/tools/finalize-vintf-resources.sh" "$top" "$FINAL_BOARD_API_LEVEL"
 
diff --git a/tools/otatools_package/Android.bp b/tools/otatools_package/Android.bp
new file mode 100644
index 0000000..5c7bfc7
--- /dev/null
+++ b/tools/otatools_package/Android.bp
@@ -0,0 +1,65 @@
+// Copyright (C) 2025 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_genrule_host {
+    name: "otatools_package_dep_jars",
+    tools: ["soong_zip"],
+    compile_multilib: "first",
+    cmd: "mkdir -p $(genDir)/framework && " +
+        "cp $(in) $(genDir)/framework && " +
+        "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)/framework",
+    srcs: [
+        ":apksigner",
+        ":boot_signer",
+        ":signapk",
+        ":verity_signer",
+    ],
+    out: ["otatools_package_dep_jars.zip"],
+}
+
+genrule {
+    name: "otatools_package_cert_files",
+    tools: ["soong_zip"],
+    cmd: "mkdir -p $(genDir)/tmp/ && " +
+        "echo $(in) > $(genDir)/tmp/zip_files.list && " +
+        "$(location soong_zip) -o $(out) -l $(genDir)/tmp/zip_files.list ",
+    srcs: [
+        ":soong_generated_otatools_package_filegroup",
+    ],
+    out: ["otatools_package_cert_files.zip"],
+}
+
+java_genrule_host {
+    name: "otatools_package",
+    tools: ["merge_zips"],
+    compile_multilib: "first",
+    cmd: "$(location merge_zips) $(out) $(in)",
+    srcs: [
+        ":otatools_package_cert_files",
+        ":otatools_package_dep_jars",
+        ":otatools_package_releasetools",
+    ],
+    // TODO: Rename as "otatools.zip" when the rest files are ready.
+    out: ["otatools_temp.zip"],
+    dist: {
+        targets: [
+            "otatools-package-temp",
+        ],
+    },
+}
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index 3467152..2232385 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -650,3 +650,12 @@
         unit_test: true,
     },
 }
+
+genrule {
+    name: "otatools_package_releasetools",
+    tools: ["soong_zip"],
+    srcs: ["**/*"],
+    cmd: "find build/make/tools/releasetools -name '*.pyc' -prune -o \\( -type f -o -type l \\) -print | sort > $(genDir)/files.txt && " +
+        "$(location soong_zip) -o $(out) -C build/make/tools -l $(genDir)/files.txt",
+    out: ["otatools_package_releasetools.zip"],
+}