Merge "Add kernel lifetimes and approved OGKI builds configs to GSI" into main
diff --git a/core/base_rules.mk b/core/base_rules.mk
index a9d6494..ca553f6 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -728,6 +728,14 @@
 
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 
+ifeq ($(EXCLUDE_MCTS),true)
+  ifneq (,$(test_config))
+    ifneq (,$(filter mcts-%,$(LOCAL_COMPATIBILITY_SUITE)))
+      LOCAL_COMPATIBILITY_SUITE := $(filter-out cts,$(LOCAL_COMPATIBILITY_SUITE))
+    endif
+  endif
+endif
+
 # If we are building a native test or benchmark and its stem variants are not defined,
 # separate the multiple architectures into subdirectories of the testcase folder.
 arch_dir :=
diff --git a/core/ravenwood_test_config_template.xml b/core/ravenwood_test_config_template.xml
index 16a22c0..088a55a 100644
--- a/core/ravenwood_test_config_template.xml
+++ b/core/ravenwood_test_config_template.xml
@@ -18,7 +18,7 @@
     <option name="test-suite-tag" value="ravenwood" />
     <option name="test-suite-tag" value="ravenwood-tests" />
 
-    <option name="java-folder" value="prebuilts/jdk/jdk17/linux-x86/" />
+    <option name="java-folder" value="prebuilts/jdk/jdk21/linux-x86/" />
     <option name="use-ravenwood-resources" value="true" />
     <option name="exclude-paths" value="java" />
     <option name="socket-timeout" value="10000" />
diff --git a/core/release_config.mk b/core/release_config.mk
index 2898868..fe2170e 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -131,6 +131,9 @@
         _args += --guard=false
     endif
     _args += --allow-missing=true
+    ifneq (,$(TARGET_PRODUCT))
+        _args += --product $(TARGET_PRODUCT)
+    endif
     _flags_dir:=$(OUT_DIR)/soong/release-config
     _flags_file:=$(_flags_dir)/release_config-$(TARGET_PRODUCT)-$(TARGET_RELEASE).vars
     # release-config generates $(_flags_varmk)
diff --git a/core/robolectric_test_config_template.xml b/core/robolectric_test_config_template.xml
index 56d2312..b1d0c2f 100644
--- a/core/robolectric_test_config_template.xml
+++ b/core/robolectric_test_config_template.xml
@@ -18,7 +18,7 @@
     <option name="test-suite-tag" value="robolectric" />
     <option name="test-suite-tag" value="robolectric-tests" />
 
-    <option name="java-folder" value="prebuilts/jdk/jdk17/linux-x86/" />
+    <option name="java-folder" value="prebuilts/jdk/jdk21/linux-x86/" />
     <option name="exclude-paths" value="java" />
     <option name="use-robolectric-resources" value="true" />
 
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 12b4135..9be3340 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -361,6 +361,12 @@
 
 $(call add_json_list, OemProperties, $(PRODUCT_OEM_PROPERTIES))
 
+# Do not set ArtTargetIncludeDebugBuild into any value if PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD is not set,
+# to have the same behavior from runtime_libart.mk.
+ifneq ($(PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD),)
+$(call add_json_bool, ArtTargetIncludeDebugBuild, $(PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD))
+endif
+
 $(call json_end)
 
 $(file >$(SOONG_VARIABLES).tmp,$(json_contents))
diff --git a/target/board/Android.mk b/target/board/Android.mk
index decc345..8133af9 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -67,7 +67,6 @@
 $(GEN): $(DEVICE_MANIFEST_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
 	BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
 	PRODUCT_ENFORCE_VINTF_MANIFEST=$(PRODUCT_ENFORCE_VINTF_MANIFEST) \
-	PRODUCT_SHIPPING_API_LEVEL=$(PRODUCT_SHIPPING_API_LEVEL) \
 	$(HOST_OUT_EXECUTABLES)/assemble_vintf -o $@ \
 		-i $(call normalize-path-list,$(PRIVATE_DEVICE_MANIFEST_FILE))
 
@@ -99,7 +98,6 @@
 $$(GEN): $$(my_fragment_files) $$(HOST_OUT_EXECUTABLES)/assemble_vintf
 	BOARD_SEPOLICY_VERS=$$(BOARD_SEPOLICY_VERS) \
 	PRODUCT_ENFORCE_VINTF_MANIFEST=$$(PRODUCT_ENFORCE_VINTF_MANIFEST) \
-	PRODUCT_SHIPPING_API_LEVEL=$$(PRODUCT_SHIPPING_API_LEVEL) \
 	$$(HOST_OUT_EXECUTABLES)/assemble_vintf -o $$@ \
 		-i $$(call normalize-path-list,$$(PRIVATE_SRC_FILES))
 
diff --git a/target/product/build_variables.mk b/target/product/build_variables.mk
index 5fe5333..9fc9ff9 100644
--- a/target/product/build_variables.mk
+++ b/target/product/build_variables.mk
@@ -17,5 +17,8 @@
 # This file contains the trunk-stable flags that should be exported to all
 # Android targets.
 
+# Control libbinder client caching
+$(call soong_config_set, libbinder, release_libbinder_client_cache, $(RELEASE_LIBBINDER_CLIENT_CACHE))
+
 # Use the configured release of sqlite
 $(call soong_config_set, libsqlite3, release_package_libsqlite3, $(RELEASE_PACKAGE_LIBSQLITE3))
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index 5218f29..fd4047a 100644
--- a/target/product/go_defaults_common.mk
+++ b/target/product/go_defaults_common.mk
@@ -37,9 +37,9 @@
 # leave less information available via JDWP.
 PRODUCT_MINIMIZE_JAVA_DEBUG_INFO := true
 
-# Disable Scudo outside of eng builds to save RAM.
+# Use the low memory allocator outside of eng builds to save RSS.
 ifneq (,$(filter eng, $(TARGET_BUILD_VARIANT)))
-  PRODUCT_DISABLE_SCUDO := true
+  MALLOC_LOW_MEMORY := true
 endif
 
 # Add the system properties.
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index ec22ebc..3523b50 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -677,7 +677,7 @@
             modified_parsed_flags.into_iter(),
             mode,
             flag_ids,
-            false,
+            true,
         )
         .unwrap();
 
@@ -870,7 +870,7 @@
             modified_parsed_flags.into_iter(),
             mode,
             flag_ids,
-            false,
+            true,
         )
         .unwrap();
 
@@ -991,7 +991,7 @@
             modified_parsed_flags.into_iter(),
             mode,
             flag_ids,
-            false,
+            true,
         )
         .unwrap();
         let expect_featureflags_content = r#"
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index cd2e3db..a6e1cf3 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -10,12 +10,14 @@
 import android.provider.DeviceConfig.Properties;
 
 
+{{ -if not library_exported }}
 {{ -if allow_instrumentation }}
 import android.aconfig.storage.StorageInternalReader;
 import android.util.Log;
 
 import java.io.File;
 {{ -endif }}
+{{ -endif }}
 
 {{ -endif }}
 /** @hide */
@@ -30,6 +32,7 @@
     private static boolean {flag.method_name} = {flag.default_value};
 {{ -endif }}
 {{ -endfor }}
+{{ -if not library_exported }}
 {{ -if allow_instrumentation }}
     StorageInternalReader reader;
     boolean readFromNewStorage;
@@ -40,23 +43,31 @@
         File file = new File("/metadata/aconfig_test_missions/mission_1");
         if (file.exists()) \{
             readFromNewStorage = true;
-            reader = new StorageInternalReader("{container}", "{package_name}");
+            try \{
+                reader = new StorageInternalReader("{container}", "{package_name}");
+            } catch(Exception e) \{
+                reader = null;
+            }
         }
     }
 {{ -endif }}
+{{ -endif }}
 {{ for namespace_with_flags in namespace_flags }}
     private void load_overrides_{namespace_with_flags.namespace}() \{
         try \{
+{{ -if not library_exported }}
 {{ -if allow_instrumentation }}
             boolean val;
 {{ -endif }}
+{{ -endif }}
             Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}");
 {{ -for flag in namespace_with_flags.flags }}
 {{ -if flag.is_read_write }}
             {flag.method_name} =
                 properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value});
+{{ -if not library_exported }}
 {{ -if allow_instrumentation }}
-            if (readFromNewStorage) \{
+            if (readFromNewStorage && reader != null) \{
                 try \{
                     val = reader.getBooleanFlagValue({flag.flag_offset});
                     if (val == {flag.method_name}) \{
@@ -67,11 +78,12 @@
                             val, {flag.method_name}));
                     }
                 } catch (Exception e) \{
-                    Log.e(TAG,"error: failed to read flag value of {flag.method_name}");
+                    Log.e(TAG,"error: failed to read flag value of {flag.method_name}", e);
                 }
             }
 {{ -endif }}
 {{ -endif }}
+{{ -endif }}
 {{ -endfor }}
         } catch (NullPointerException e) \{
             throw new RuntimeException(
diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp
index 3859194..70171ed 100644
--- a/tools/aconfig/aconfig_storage_file/Android.bp
+++ b/tools/aconfig/aconfig_storage_file/Android.bp
@@ -145,4 +145,10 @@
         "srcs/**/*.java",
     ],
     sdk_version: "core_current",
+    min_sdk_version: "29",
+    host_supported: true,
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
 }
\ No newline at end of file
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index c2f4c18..b4bb06f 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -175,4 +175,10 @@
         "aconfig_storage_file_java",
     ],
     sdk_version: "core_current",
+    host_supported: true,
+    min_sdk_version: "29",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
 }
diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs
index 04140c7..0dfb956 100644
--- a/tools/aconfig/aflags/src/aconfig_storage_source.rs
+++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs
@@ -1,14 +1,93 @@
 use crate::{Flag, FlagPermission, FlagSource, FlagValue, ValuePickedFrom};
 use anyhow::{anyhow, Result};
 
+use std::collections::HashMap;
 use std::fs::File;
 use std::io::Read;
 
 pub struct AconfigStorageSource {}
 
+use aconfig_storage_file::protos::ProtoStorageFileInfo;
 use aconfig_storage_file::protos::ProtoStorageFiles;
+use aconfig_storage_file::FlagValueAndInfoSummary;
 
-static STORAGE_INFO_FILE_PATH: &str = "/metadata/aconfig/persistent_storage_file_records.pb";
+static STORAGE_INFO_FILE_PATH: &str = "/metadata/aconfig/storage_records.pb";
+
+fn read_default_values(file_info: ProtoStorageFileInfo) -> Result<HashMap<String, FlagValue>> {
+    let package_map =
+        file_info.package_map.ok_or(anyhow!("storage file is missing package map"))?;
+    let flag_map = file_info.flag_map.ok_or(anyhow!("storage file is missing flag map"))?;
+    let flag_val = file_info.flag_val.ok_or(anyhow!("storage file is missing flag val"))?;
+
+    let mut result = HashMap::new();
+    for listed_flag in aconfig_storage_file::list_flags(&package_map, &flag_map, &flag_val)? {
+        let value = FlagValue::try_from(listed_flag.flag_value.as_str())?;
+        result.insert(listed_flag.package_name + &listed_flag.flag_name, value);
+    }
+    Ok(result)
+}
+
+fn read_next_boot_values(
+    listed_flags: &[FlagValueAndInfoSummary],
+) -> Result<HashMap<String, FlagValue>> {
+    let mut result = HashMap::new();
+    for flag in listed_flags {
+        result.insert(
+            flag.package_name.clone() + &flag.flag_name,
+            FlagValue::try_from(flag.flag_value.as_str())?,
+        );
+    }
+    Ok(result)
+}
+
+fn reconcile(
+    default_values: HashMap<String, FlagValue>,
+    next_boot_values: HashMap<String, FlagValue>,
+    flags_current_boot: &[FlagValueAndInfoSummary],
+    container: &str,
+) -> Result<Vec<Flag>> {
+    let mut result = Vec::new();
+    for listed_flag in flags_current_boot {
+        let default_value = default_values
+            .get(&(listed_flag.package_name.clone() + &listed_flag.flag_name))
+            .copied();
+
+        let name = listed_flag.flag_name.clone();
+        let package = listed_flag.package_name.clone();
+        let value = FlagValue::try_from(listed_flag.flag_value.as_str())?;
+        let container = container.to_string();
+        let staged_value = next_boot_values
+            .get(&(listed_flag.package_name.clone() + &listed_flag.flag_name))
+            .filter(|&v| value != *v)
+            .copied();
+        let permission = if listed_flag.is_readwrite {
+            FlagPermission::ReadWrite
+        } else {
+            FlagPermission::ReadOnly
+        };
+        let value_picked_from = if listed_flag.has_local_override {
+            ValuePickedFrom::Local
+        } else if Some(value) == default_value {
+            ValuePickedFrom::Default
+        } else {
+            ValuePickedFrom::Server
+        };
+
+        result.push(Flag {
+            name,
+            package,
+            value,
+            container,
+            staged_value,
+            permission,
+            value_picked_from,
+
+            // TODO(b/324436145): delete namespace field once DeviceConfig isn't in CLI.
+            namespace: "-".to_string(),
+        });
+    }
+    Ok(result)
+}
 
 impl FlagSource for AconfigStorageSource {
     fn list_flags() -> Result<Vec<Flag>> {
@@ -20,30 +99,35 @@
         let storage_file_info: ProtoStorageFiles = protobuf::Message::parse_from_bytes(&bytes)?;
 
         for file_info in storage_file_info.files {
-            let package_map =
-                file_info.package_map.ok_or(anyhow!("storage file is missing package map"))?;
-            let flag_map = file_info.flag_map.ok_or(anyhow!("storage file is missing flag map"))?;
-            let flag_val = file_info.flag_val.ok_or(anyhow!("storage file is missing flag val"))?;
+            let default_values = read_default_values(file_info.clone())?;
+
             let container =
                 file_info.container.ok_or(anyhow!("storage file is missing container"))?;
+            let package_map = format!("/metadata/aconfig/maps/{container}.package.map");
+            let flag_map = format!("/metadata/aconfig/maps/{container}.flag.map");
+            let flag_info = format!("/metadata/aconfig/boot/{container}.info");
 
-            for listed_flag in aconfig_storage_file::list_flags(&package_map, &flag_map, &flag_val)?
-            {
-                result.push(Flag {
-                    name: listed_flag.flag_name,
-                    package: listed_flag.package_name,
-                    value: FlagValue::try_from(listed_flag.flag_value.as_str())?,
-                    container: container.to_string(),
+            let flag_val_current_boot = format!("/metadata/aconfig/boot/{container}.val");
+            let flag_val_next_boot = format!("/metadata/aconfig/flags/{container}.val");
 
-                    // TODO(b/324436145): delete namespace field once DeviceConfig isn't in CLI.
-                    namespace: "-".to_string(),
+            let flags_next_boot = aconfig_storage_file::list_flags_with_info(
+                &package_map,
+                &flag_map,
+                &flag_val_next_boot,
+                &flag_info,
+            )?;
+            let flags_current_boot = aconfig_storage_file::list_flags_with_info(
+                &package_map,
+                &flag_map,
+                &flag_val_current_boot,
+                &flag_info,
+            )?;
 
-                    // TODO(b/324436145): Populate with real values once API is available.
-                    staged_value: None,
-                    permission: FlagPermission::ReadOnly,
-                    value_picked_from: ValuePickedFrom::Default,
-                });
-            }
+            let next_boot_values = read_next_boot_values(&flags_next_boot)?;
+            let processed_flags =
+                reconcile(default_values, next_boot_values, &flags_current_boot, &container)?;
+
+            result.extend(processed_flags);
         }
 
         Ok(result)
diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs
index 810f2e3..0a5c989 100644
--- a/tools/aconfig/aflags/src/main.rs
+++ b/tools/aconfig/aflags/src/main.rs
@@ -50,6 +50,7 @@
 enum ValuePickedFrom {
     Default,
     Server,
+    Local,
 }
 
 impl std::fmt::Display for ValuePickedFrom {
@@ -60,6 +61,7 @@
             match &self {
                 Self::Default => "default",
                 Self::Server => "server",
+                Self::Local => "local",
             }
         )
     }
@@ -286,7 +288,9 @@
     let cli = Cli::parse();
     let output = match cli.command {
         Command::List { use_new_storage: true, container } => {
-            list(FlagSourceType::AconfigStorage, container).map(Some)
+            list(FlagSourceType::AconfigStorage, container)
+                .map_err(|_| anyhow!("storage may not be enabled"))
+                .map(Some)
         }
         Command::List { use_new_storage: false, container } => {
             list(FlagSourceType::DeviceConfig, container).map(Some)
diff --git a/tools/aconfig/fake_device_config/src/android/provider/Log.java b/tools/aconfig/fake_device_config/src/android/provider/Log.java
new file mode 100644
index 0000000..3e7fd0f
--- /dev/null
+++ b/tools/aconfig/fake_device_config/src/android/provider/Log.java
@@ -0,0 +1,15 @@
+package android.util;
+
+public final class Log {
+    public static int i(String tag, String msg) {
+        return 0;
+    }
+
+    public static int e(String tag, String msg) {
+        return 0;
+    }
+
+    public static int e(String tag, String msg, Throwable tr) {
+        return 0;
+    }
+}