Merge "Use test install base template instead of a hardcoded path" into main am: bd0cba45be

Original change: https://android-review.googlesource.com/c/platform/build/+/3176019

Change-Id: Ic82c841725dd995748917dd2e0ccfd1281e2b097
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/core/config.mk b/core/config.mk
index ae65944..82b63cf 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1201,6 +1201,11 @@
 
 APPS_DEFAULT_VERSION_NAME := $(PLATFORM_VERSION)
 
+# Add BUILD_NUMBER to apps if PRODUCT_BUILD_APPS_WITH_BUILD_NUMBER is defined.
+ifeq ($(PRODUCT_BUILD_APPS_WITH_BUILD_NUMBER),true)
+  APPS_DEFAULT_VERSION_NAME := $(PLATFORM_VERSION)-$(BUILD_NUMBER_FROM_FILE)
+endif
+
 # ANDROID_WARNING_ALLOWED_PROJECTS is generated by build/soong.
 define find_warning_allowed_projects
     $(filter $(ANDROID_WARNING_ALLOWED_PROJECTS),$(1)/)
diff --git a/core/product.mk b/core/product.mk
index ad80ee4..832d094 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -492,6 +492,9 @@
 # by this flag.
 _product_single_value_vars += PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG
 
+# If set, the default value of the versionName of apps will include the build number.
+_product_single_value_vars += PRODUCT_BUILD_APPS_WITH_BUILD_NUMBER
+
 # If set, build would generate system image from Soong-defined module.
 _product_single_value_vars += PRODUCT_SOONG_DEFINED_SYSTEM_IMAGE
 
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index 86c23f8..9189c2d 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -29,7 +29,9 @@
 special_mts_test_suites :=
 special_mts_test_suites += mcts
 special_mts_test_suites += $(mts_modules)
-ifneq ($(filter $(special_mts_test_suites),$(subst -, ,$(test_suite_name))),)
+ifneq ($(filter $(special_mts_test_suites),$(patsubst mcts-%,%,$(test_suite_name))),)
+	test_suite_subdir := android-mts
+else ifneq ($(filter $(special_mts_test_suites),$(patsubst mts-%,%,$(test_suite_name))),)
 	test_suite_subdir := android-mts
 else
 	test_suite_subdir := android-$(test_suite_name)
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 795d3f8..d8b34f1 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -83,7 +83,6 @@
     CtsShimPrivPrebuilt \
     debuggerd\
     device_config \
-    DeviceDiagnostics \
     dmctl \
     dnsmasq \
     dmesgd \
@@ -514,3 +513,4 @@
 
 $(call soong_config_set, bionic, large_system_property_node, $(RELEASE_LARGE_SYSTEM_PROPERTY_NODE))
 $(call soong_config_set, Aconfig, read_from_new_storage, $(RELEASE_READ_FROM_NEW_STORAGE))
+$(call soong_config_set, SettingsLib, legacy_avatar_picker_app_enabled, $(if $(RELEASE_AVATAR_PICKER_APP),,true))
diff --git a/target/product/go_defaults.mk b/target/product/go_defaults.mk
index 4627fde..c928530 100644
--- a/target/product/go_defaults.mk
+++ b/target/product/go_defaults.mk
@@ -17,7 +17,8 @@
 # Inherit common Android Go defaults.
 $(call inherit-product, build/make/target/product/go_defaults_common.mk)
 
-PRODUCT_RELEASE_CONFIG_MAPS += $(wildcard vendor/google_shared/build/release/go_devices/release_config_map.textproto)
+# Product config map to toggle between sources and prebuilts of required mainline modules
+PRODUCT_RELEASE_CONFIG_MAPS += $(wildcard vendor/google_shared/build/release/gms_mainline_go/required/release_config_map.textproto)
 
 # Add the system properties.
 TARGET_SYSTEM_PROP += \
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index 3f3bd01..546bbe7 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -46,6 +46,7 @@
     CertInstaller \
     CredentialManager \
     DeviceAsWebcam \
+    DeviceDiagnostics \
     DocumentsUI \
     DownloadProviderUi \
     EasterEgg \
diff --git a/target/product/media_system_ext.mk b/target/product/media_system_ext.mk
index 2e20af3..30dd2e2 100644
--- a/target/product/media_system_ext.mk
+++ b/target/product/media_system_ext.mk
@@ -23,3 +23,6 @@
 # /system_ext packages
 PRODUCT_PACKAGES += \
     vndk_apex_snapshot_package \
+
+# Window Extensions
+$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions_base.mk)
diff --git a/target/product/window_extensions.mk b/target/product/window_extensions.mk
index 5f5431f..d27a613 100644
--- a/target/product/window_extensions.mk
+++ b/target/product/window_extensions.mk
@@ -14,11 +14,14 @@
 # limitations under the License.
 #
 
-# /system_ext packages
-PRODUCT_PACKAGES += \
-    androidx.window.extensions \
-    androidx.window.sidecar
-
-# properties
+# Extension of window_extensions_base.mk to enable the activity embedding
+# feature for all apps by default. All large screen devices must inherit
+# this in build. Optional for other form factors.
+#
+# Indicated whether the Activity Embedding feature should be guarded by
+# Android 15 to avoid app compat impact.
+# If true (or not set), the feature is only enabled for apps with target
+# SDK of Android 15 or above.
+# If false, the feature is enabled for all apps.
 PRODUCT_PRODUCT_PROPERTIES += \
-    persist.wm.extensions.enabled=true
+    persist.wm.extensions.activity_embedding_guard_with_android_15=false
diff --git a/target/product/window_extensions_base.mk b/target/product/window_extensions_base.mk
new file mode 100644
index 0000000..ee0e5e7
--- /dev/null
+++ b/target/product/window_extensions_base.mk
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+# The base version of window_extensions.mk to be included on all non-wearable
+# devices. Devices that don't support multi-window can choose to drop this.
+#
+# Note: by default the Activity Embedding feature is guarded by app's
+# targetSDK on Android 15 to avoid app compat impact.
+#
+# Large screen devices must inherit window_extensions.mk to enable the
+# Activity Embedding feature for all apps.
+
+# /system_ext packages
+PRODUCT_PACKAGES += \
+    androidx.window.extensions \
+    androidx.window.sidecar
+
+# properties
+PRODUCT_PRODUCT_PROPERTIES += \
+    persist.wm.extensions.enabled=true
diff --git a/tools/aconfig/aconfig/src/codegen/rust.rs b/tools/aconfig/aconfig/src/codegen/rust.rs
index 33c3d37..45488b0 100644
--- a/tools/aconfig/aconfig/src/codegen/rust.rs
+++ b/tools/aconfig/aconfig/src/codegen/rust.rs
@@ -20,26 +20,34 @@
 
 use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
 
+use std::collections::HashMap;
+
 use crate::codegen;
 use crate::codegen::CodegenMode;
 use crate::commands::OutputFile;
 
 pub fn generate_rust_code<I>(
     package: &str,
+    flag_ids: HashMap<String, u16>,
     parsed_flags_iter: I,
     codegen_mode: CodegenMode,
+    allow_instrumentation: bool,
 ) -> Result<OutputFile>
 where
     I: Iterator<Item = ProtoParsedFlag>,
 {
-    let template_flags: Vec<TemplateParsedFlag> =
-        parsed_flags_iter.map(|pf| TemplateParsedFlag::new(package, &pf)).collect();
+    let template_flags: Vec<TemplateParsedFlag> = parsed_flags_iter
+        .map(|pf| TemplateParsedFlag::new(package, flag_ids.clone(), &pf))
+        .collect();
     let has_readwrite = template_flags.iter().any(|item| item.readwrite);
+    let container = (template_flags.first().expect("zero template flags").container).to_string();
     let context = TemplateContext {
         package: package.to_string(),
         template_flags,
         modules: package.split('.').map(|s| s.to_string()).collect::<Vec<_>>(),
         has_readwrite,
+        allow_instrumentation,
+        container,
     };
     let mut template = TinyTemplate::new();
     template.add_template(
@@ -62,6 +70,8 @@
     pub template_flags: Vec<TemplateParsedFlag>,
     pub modules: Vec<String>,
     pub has_readwrite: bool,
+    pub allow_instrumentation: bool,
+    pub container: String,
 }
 
 #[derive(Serialize)]
@@ -69,25 +79,28 @@
     pub readwrite: bool,
     pub default_value: String,
     pub name: String,
+    pub container: String,
+    pub flag_offset: u16,
     pub device_config_namespace: String,
     pub device_config_flag: String,
 }
 
 impl TemplateParsedFlag {
     #[allow(clippy::nonminimal_bool)]
-    fn new(package: &str, pf: &ProtoParsedFlag) -> Self {
-        let template = TemplateParsedFlag {
+    fn new(package: &str, flag_offsets: HashMap<String, u16>, pf: &ProtoParsedFlag) -> Self {
+        Self {
             readwrite: pf.permission() == ProtoFlagPermission::READ_WRITE,
             default_value: match pf.state() {
                 ProtoFlagState::ENABLED => "true".to_string(),
                 ProtoFlagState::DISABLED => "false".to_string(),
             },
             name: pf.name().to_string(),
+            container: pf.container().to_string(),
+            flag_offset: *flag_offsets.get(pf.name()).expect("didnt find package offset :("),
             device_config_namespace: pf.namespace().to_string(),
             device_config_flag: codegen::create_device_config_ident(package, pf.name())
                 .expect("values checked at flag parse time"),
-        };
-        template
+        }
     }
 }
 
@@ -97,6 +110,14 @@
 
     const PROD_EXPECTED: &str = r#"
 //! codegenerated rust flag lib
+use aconfig_storage_read_api::{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
+use std::path::Path;
+use std::io::Write;
+use log::{log, LevelFilter, Level};
+
+static STORAGE_MIGRATION_MARKER_FILE: &str =
+    "/metadata/aconfig_test_missions/mission_1";
+static MIGRATION_LOG_TAG: &str = "AconfigTestMission1";
 
 /// flag provider
 pub struct FlagProvider;
@@ -233,6 +254,634 @@
 }
 "#;
 
+    const PROD_INSTRUMENTED_EXPECTED: &str = r#"
+//! codegenerated rust flag lib
+use aconfig_storage_read_api::{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
+use std::path::Path;
+use std::io::Write;
+use log::{log, LevelFilter, Level};
+
+static STORAGE_MIGRATION_MARKER_FILE: &str =
+    "/metadata/aconfig_test_missions/mission_1";
+static MIGRATION_LOG_TAG: &str = "AconfigTestMission1";
+
+/// flag provider
+pub struct FlagProvider;
+
+lazy_static::lazy_static! {
+
+    static ref PACKAGE_OFFSET: Result<Option<u32>, AconfigStorageError> = unsafe {
+        get_mapped_storage_file("system", StorageFileType::PackageMap)
+        .and_then(|package_map| get_package_read_context(&package_map, "com.android.aconfig.test"))
+        .map(|context| context.map(|c| c.boolean_start_index))
+    };
+
+    static ref FLAG_VAL_MAP: Result<Mmap, AconfigStorageError> = unsafe {
+        get_mapped_storage_file("system", StorageFileType::FlagVal)
+    };
+    /// flag value cache for disabled_rw
+
+    static ref CACHED_disabled_rw: bool = {
+        let result = flags_rust::GetServerConfigurableFlag(
+            "aconfig_flags.aconfig_test",
+            "com.android.aconfig.test.disabled_rw",
+            "false") == "true";
+
+        if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+            // This will be called multiple times. Subsequent calls after the first are noops.
+            logger::init(
+                logger::Config::default()
+                    .with_tag_on_device(MIGRATION_LOG_TAG)
+                    .with_max_level(LevelFilter::Info));
+
+            let aconfig_storage_result = FLAG_VAL_MAP
+                .as_ref()
+                .map_err(|err| format!("failed to get flag val map: {err}"))
+                .and_then(|flag_val_map| {
+                    PACKAGE_OFFSET
+                        .as_ref()
+                        .map_err(|err| format!("failed to get package read offset: {err}"))
+                        .and_then(|package_offset| {
+                            match package_offset {
+                                Some(offset) => {
+                                    get_boolean_flag_value(&flag_val_map, offset + 1)
+                                        .map_err(|err| format!("failed to get flag: {err}"))
+                                },
+                                None => Err("no context found for package 'com.android.aconfig.test'".to_string())
+                            }
+                        })
+                    });
+
+            match aconfig_storage_result {
+                Ok(storage_result) if storage_result == result => {
+                    log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw' contained correct value. Legacy storage was {result}, new storage was {storage_result}");
+                },
+                Ok(storage_result) => {
+                    log!(Level::Error, "AconfigTestMission1: error: mismatch for flag 'disabled_rw'. Legacy storage was {result}, new storage was {storage_result}");
+                },
+                Err(err) => {
+                    log!(Level::Error, "AconfigTestMission1: error: {err}")
+                }
+            }
+        }
+
+        result
+        };
+
+    /// flag value cache for disabled_rw_exported
+
+    static ref CACHED_disabled_rw_exported: bool = {
+        let result = flags_rust::GetServerConfigurableFlag(
+            "aconfig_flags.aconfig_test",
+            "com.android.aconfig.test.disabled_rw_exported",
+            "false") == "true";
+
+        if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+            // This will be called multiple times. Subsequent calls after the first are noops.
+            logger::init(
+                logger::Config::default()
+                    .with_tag_on_device(MIGRATION_LOG_TAG)
+                    .with_max_level(LevelFilter::Info));
+
+            let aconfig_storage_result = FLAG_VAL_MAP
+                .as_ref()
+                .map_err(|err| format!("failed to get flag val map: {err}"))
+                .and_then(|flag_val_map| {
+                    PACKAGE_OFFSET
+                        .as_ref()
+                        .map_err(|err| format!("failed to get package read offset: {err}"))
+                        .and_then(|package_offset| {
+                            match package_offset {
+                                Some(offset) => {
+                                    get_boolean_flag_value(&flag_val_map, offset + 2)
+                                        .map_err(|err| format!("failed to get flag: {err}"))
+                                },
+                                None => Err("no context found for package 'com.android.aconfig.test'".to_string())
+                            }
+                        })
+                    });
+
+            match aconfig_storage_result {
+                Ok(storage_result) if storage_result == result => {
+                    log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw_exported' contained correct value. Legacy storage was {result}, new storage was {storage_result}");
+                },
+                Ok(storage_result) => {
+                    log!(Level::Error, "AconfigTestMission1: error: mismatch for flag 'disabled_rw_exported'. Legacy storage was {result}, new storage was {storage_result}");
+                },
+                Err(err) => {
+                    log!(Level::Error, "AconfigTestMission1: error: {err}")
+                }
+            }
+        }
+
+        result
+        };
+
+    /// flag value cache for disabled_rw_in_other_namespace
+
+    static ref CACHED_disabled_rw_in_other_namespace: bool = {
+        let result = flags_rust::GetServerConfigurableFlag(
+            "aconfig_flags.other_namespace",
+            "com.android.aconfig.test.disabled_rw_in_other_namespace",
+            "false") == "true";
+
+        if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+            // This will be called multiple times. Subsequent calls after the first are noops.
+            logger::init(
+                logger::Config::default()
+                    .with_tag_on_device(MIGRATION_LOG_TAG)
+                    .with_max_level(LevelFilter::Info));
+
+            let aconfig_storage_result = FLAG_VAL_MAP
+                .as_ref()
+                .map_err(|err| format!("failed to get flag val map: {err}"))
+                .and_then(|flag_val_map| {
+                    PACKAGE_OFFSET
+                        .as_ref()
+                        .map_err(|err| format!("failed to get package read offset: {err}"))
+                        .and_then(|package_offset| {
+                            match package_offset {
+                                Some(offset) => {
+                                    get_boolean_flag_value(&flag_val_map, offset + 3)
+                                        .map_err(|err| format!("failed to get flag: {err}"))
+                                },
+                                None => Err("no context found for package 'com.android.aconfig.test'".to_string())
+                            }
+                        })
+                    });
+
+            match aconfig_storage_result {
+                Ok(storage_result) if storage_result == result => {
+                    log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw_in_other_namespace' contained correct value. Legacy storage was {result}, new storage was {storage_result}");
+                },
+                Ok(storage_result) => {
+                    log!(Level::Error, "AconfigTestMission1: error: mismatch for flag 'disabled_rw_in_other_namespace'. Legacy storage was {result}, new storage was {storage_result}");
+                },
+                Err(err) => {
+                    log!(Level::Error, "AconfigTestMission1: error: {err}")
+                }
+            }
+        }
+
+        result
+        };
+
+    /// flag value cache for enabled_rw
+
+    static ref CACHED_enabled_rw: bool = {
+        let result = flags_rust::GetServerConfigurableFlag(
+            "aconfig_flags.aconfig_test",
+            "com.android.aconfig.test.enabled_rw",
+            "true") == "true";
+
+        if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+            // This will be called multiple times. Subsequent calls after the first are noops.
+            logger::init(
+                logger::Config::default()
+                    .with_tag_on_device(MIGRATION_LOG_TAG)
+                    .with_max_level(LevelFilter::Info));
+
+            let aconfig_storage_result = FLAG_VAL_MAP
+                .as_ref()
+                .map_err(|err| format!("failed to get flag val map: {err}"))
+                .and_then(|flag_val_map| {
+                    PACKAGE_OFFSET
+                        .as_ref()
+                        .map_err(|err| format!("failed to get package read offset: {err}"))
+                        .and_then(|package_offset| {
+                            match package_offset {
+                                Some(offset) => {
+                                    get_boolean_flag_value(&flag_val_map, offset + 8)
+                                        .map_err(|err| format!("failed to get flag: {err}"))
+                                },
+                                None => Err("no context found for package 'com.android.aconfig.test'".to_string())
+                            }
+                        })
+                    });
+
+            match aconfig_storage_result {
+                Ok(storage_result) if storage_result == result => {
+                    log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_rw' contained correct value. Legacy storage was {result}, new storage was {storage_result}");
+                },
+                Ok(storage_result) => {
+                    log!(Level::Error, "AconfigTestMission1: error: mismatch for flag 'enabled_rw'. Legacy storage was {result}, new storage was {storage_result}");
+                },
+                Err(err) => {
+                    log!(Level::Error, "AconfigTestMission1: error: {err}")
+                }
+            }
+        }
+
+        result
+        };
+
+}
+
+impl FlagProvider {
+
+
+    /// query flag disabled_ro
+    pub fn disabled_ro(&self) -> bool {
+        false
+    }
+
+    /// query flag disabled_rw
+    pub fn disabled_rw(&self) -> bool {
+        *CACHED_disabled_rw
+    }
+
+    /// query flag disabled_rw_exported
+    pub fn disabled_rw_exported(&self) -> bool {
+        *CACHED_disabled_rw_exported
+    }
+
+    /// query flag disabled_rw_in_other_namespace
+    pub fn disabled_rw_in_other_namespace(&self) -> bool {
+        *CACHED_disabled_rw_in_other_namespace
+    }
+
+    /// query flag enabled_fixed_ro
+    pub fn enabled_fixed_ro(&self) -> bool {
+        true
+    }
+
+    /// query flag enabled_fixed_ro_exported
+    pub fn enabled_fixed_ro_exported(&self) -> bool {
+        true
+    }
+
+    /// query flag enabled_ro
+    pub fn enabled_ro(&self) -> bool {
+        true
+    }
+
+    /// query flag enabled_ro_exported
+    pub fn enabled_ro_exported(&self) -> bool {
+        true
+    }
+
+    /// query flag enabled_rw
+    pub fn enabled_rw(&self) -> bool {
+        *CACHED_enabled_rw
+    }
+
+
+}
+
+/// flag provider
+pub static PROVIDER: FlagProvider = FlagProvider;
+
+
+/// query flag disabled_ro
+#[inline(always)]
+pub fn disabled_ro() -> bool {
+
+
+    let result = false;
+    if !Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+        return result;
+    }
+
+    // This will be called multiple times. Subsequent calls after the first
+    // are noops.
+    logger::init(
+        logger::Config::default()
+            .with_tag_on_device(MIGRATION_LOG_TAG)
+            .with_max_level(LevelFilter::Info),
+    );
+
+    unsafe {
+        let package_map = match get_mapped_storage_file("system", StorageFileType::PackageMap) {
+            Ok(file) => file,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'disabled_ro': {err}");
+                return result;
+            }
+        };
+
+        let package_read_context = match get_package_read_context(&package_map, "com.android.aconfig.test") {
+            Ok(Some(context)) => context,
+            Ok(None) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'disabled_ro': did not get context");
+                return result;
+            },
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'disabled_ro': {err}");
+                return result;
+            }
+        };
+        let flag_val_map = match get_mapped_storage_file("system", StorageFileType::FlagVal) {
+            Ok(val_map) => val_map,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'disabled_ro': {err}");
+                return result;
+            }
+        };
+        let value = match get_boolean_flag_value(&flag_val_map, 0 + package_read_context.boolean_start_index) {
+            Ok(val) => val,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'disabled_ro': {err}");
+                return result;
+            }
+        };
+
+        if result != value {
+            log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'disabled_ro'. Legacy storage was {result}, new storage was {value}");
+        } else {
+            let default_value = false;
+            log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_ro' contained correct value. Legacy storage was {default_value}, new storage was {value}");
+        }
+    }
+
+    result
+
+}
+
+/// query flag disabled_rw
+#[inline(always)]
+pub fn disabled_rw() -> bool {
+    PROVIDER.disabled_rw()
+}
+
+/// query flag disabled_rw_exported
+#[inline(always)]
+pub fn disabled_rw_exported() -> bool {
+    PROVIDER.disabled_rw_exported()
+}
+
+/// query flag disabled_rw_in_other_namespace
+#[inline(always)]
+pub fn disabled_rw_in_other_namespace() -> bool {
+    PROVIDER.disabled_rw_in_other_namespace()
+}
+
+/// query flag enabled_fixed_ro
+#[inline(always)]
+pub fn enabled_fixed_ro() -> bool {
+
+
+    let result = true;
+    if !Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+        return result;
+    }
+
+    // This will be called multiple times. Subsequent calls after the first
+    // are noops.
+    logger::init(
+        logger::Config::default()
+            .with_tag_on_device(MIGRATION_LOG_TAG)
+            .with_max_level(LevelFilter::Info),
+    );
+
+    unsafe {
+        let package_map = match get_mapped_storage_file("system", StorageFileType::PackageMap) {
+            Ok(file) => file,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro': {err}");
+                return result;
+            }
+        };
+
+        let package_read_context = match get_package_read_context(&package_map, "com.android.aconfig.test") {
+            Ok(Some(context)) => context,
+            Ok(None) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro': did not get context");
+                return result;
+            },
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro': {err}");
+                return result;
+            }
+        };
+        let flag_val_map = match get_mapped_storage_file("system", StorageFileType::FlagVal) {
+            Ok(val_map) => val_map,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro': {err}");
+                return result;
+            }
+        };
+        let value = match get_boolean_flag_value(&flag_val_map, 4 + package_read_context.boolean_start_index) {
+            Ok(val) => val,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro': {err}");
+                return result;
+            }
+        };
+
+        if result != value {
+            log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'enabled_fixed_ro'. Legacy storage was {result}, new storage was {value}");
+        } else {
+            let default_value = true;
+            log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_fixed_ro' contained correct value. Legacy storage was {default_value}, new storage was {value}");
+        }
+    }
+
+    result
+
+}
+
+/// query flag enabled_fixed_ro_exported
+#[inline(always)]
+pub fn enabled_fixed_ro_exported() -> bool {
+
+
+    let result = true;
+    if !Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+        return result;
+    }
+
+    // This will be called multiple times. Subsequent calls after the first
+    // are noops.
+    logger::init(
+        logger::Config::default()
+            .with_tag_on_device(MIGRATION_LOG_TAG)
+            .with_max_level(LevelFilter::Info),
+    );
+
+    unsafe {
+        let package_map = match get_mapped_storage_file("system", StorageFileType::PackageMap) {
+            Ok(file) => file,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro_exported': {err}");
+                return result;
+            }
+        };
+
+        let package_read_context = match get_package_read_context(&package_map, "com.android.aconfig.test") {
+            Ok(Some(context)) => context,
+            Ok(None) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro_exported': did not get context");
+                return result;
+            },
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro_exported': {err}");
+                return result;
+            }
+        };
+        let flag_val_map = match get_mapped_storage_file("system", StorageFileType::FlagVal) {
+            Ok(val_map) => val_map,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro_exported': {err}");
+                return result;
+            }
+        };
+        let value = match get_boolean_flag_value(&flag_val_map, 5 + package_read_context.boolean_start_index) {
+            Ok(val) => val,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_fixed_ro_exported': {err}");
+                return result;
+            }
+        };
+
+        if result != value {
+            log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'enabled_fixed_ro_exported'. Legacy storage was {result}, new storage was {value}");
+        } else {
+            let default_value = true;
+            log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_fixed_ro_exported' contained correct value. Legacy storage was {default_value}, new storage was {value}");
+        }
+    }
+
+    result
+
+}
+
+/// query flag enabled_ro
+#[inline(always)]
+pub fn enabled_ro() -> bool {
+
+
+    let result = true;
+    if !Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+        return result;
+    }
+
+    // This will be called multiple times. Subsequent calls after the first
+    // are noops.
+    logger::init(
+        logger::Config::default()
+            .with_tag_on_device(MIGRATION_LOG_TAG)
+            .with_max_level(LevelFilter::Info),
+    );
+
+    unsafe {
+        let package_map = match get_mapped_storage_file("system", StorageFileType::PackageMap) {
+            Ok(file) => file,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro': {err}");
+                return result;
+            }
+        };
+
+        let package_read_context = match get_package_read_context(&package_map, "com.android.aconfig.test") {
+            Ok(Some(context)) => context,
+            Ok(None) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro': did not get context");
+                return result;
+            },
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro': {err}");
+                return result;
+            }
+        };
+        let flag_val_map = match get_mapped_storage_file("system", StorageFileType::FlagVal) {
+            Ok(val_map) => val_map,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro': {err}");
+                return result;
+            }
+        };
+        let value = match get_boolean_flag_value(&flag_val_map, 6 + package_read_context.boolean_start_index) {
+            Ok(val) => val,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro': {err}");
+                return result;
+            }
+        };
+
+        if result != value {
+            log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'enabled_ro'. Legacy storage was {result}, new storage was {value}");
+        } else {
+            let default_value = true;
+            log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_ro' contained correct value. Legacy storage was {default_value}, new storage was {value}");
+        }
+    }
+
+    result
+
+}
+
+/// query flag enabled_ro_exported
+#[inline(always)]
+pub fn enabled_ro_exported() -> bool {
+
+
+    let result = true;
+    if !Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
+        return result;
+    }
+
+    // This will be called multiple times. Subsequent calls after the first
+    // are noops.
+    logger::init(
+        logger::Config::default()
+            .with_tag_on_device(MIGRATION_LOG_TAG)
+            .with_max_level(LevelFilter::Info),
+    );
+
+    unsafe {
+        let package_map = match get_mapped_storage_file("system", StorageFileType::PackageMap) {
+            Ok(file) => file,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro_exported': {err}");
+                return result;
+            }
+        };
+
+        let package_read_context = match get_package_read_context(&package_map, "com.android.aconfig.test") {
+            Ok(Some(context)) => context,
+            Ok(None) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro_exported': did not get context");
+                return result;
+            },
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro_exported': {err}");
+                return result;
+            }
+        };
+        let flag_val_map = match get_mapped_storage_file("system", StorageFileType::FlagVal) {
+            Ok(val_map) => val_map,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro_exported': {err}");
+                return result;
+            }
+        };
+        let value = match get_boolean_flag_value(&flag_val_map, 7 + package_read_context.boolean_start_index) {
+            Ok(val) => val,
+            Err(err) => {
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag 'enabled_ro_exported': {err}");
+                return result;
+            }
+        };
+
+        if result != value {
+            log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'enabled_ro_exported'. Legacy storage was {result}, new storage was {value}");
+        } else {
+            let default_value = true;
+            log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_ro_exported' contained correct value. Legacy storage was {default_value}, new storage was {value}");
+        }
+    }
+
+    result
+
+}
+
+/// query flag enabled_rw
+#[inline(always)]
+pub fn enabled_rw() -> bool {
+    PROVIDER.enabled_rw()
+}
+"#;
+
     const TEST_EXPECTED: &str = r#"
 //! codegenerated rust flag lib
 
@@ -492,6 +1141,14 @@
 
     const EXPORTED_EXPECTED: &str = r#"
 //! codegenerated rust flag lib
+use aconfig_storage_read_api::{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
+use std::path::Path;
+use std::io::Write;
+use log::{log, LevelFilter, Level};
+
+static STORAGE_MIGRATION_MARKER_FILE: &str =
+    "/metadata/aconfig_test_missions/mission_1";
+static MIGRATION_LOG_TAG: &str = "AconfigTestMission1";
 
 /// flag provider
 pub struct FlagProvider;
@@ -558,6 +1215,14 @@
 
     const FORCE_READ_ONLY_EXPECTED: &str = r#"
 //! codegenerated rust flag lib
+use aconfig_storage_read_api::{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
+use std::path::Path;
+use std::io::Write;
+use log::{log, LevelFilter, Level};
+
+static STORAGE_MIGRATION_MARKER_FILE: &str =
+    "/metadata/aconfig_test_missions/mission_1";
+static MIGRATION_LOG_TAG: &str = "AconfigTestMission1";
 
 /// flag provider
 pub struct FlagProvider;
@@ -633,24 +1298,27 @@
     true
 }
 "#;
+    use crate::commands::assign_flag_ids;
 
-    fn test_generate_rust_code(mode: CodegenMode) {
+    fn test_generate_rust_code(mode: CodegenMode, allow_instrumentation: bool, expected: &str) {
         let parsed_flags = crate::test::parse_test_flags();
         let modified_parsed_flags =
             crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap();
-        let generated =
-            generate_rust_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode)
-                .unwrap();
+        let flag_ids =
+            assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap();
+        let generated = generate_rust_code(
+            crate::test::TEST_PACKAGE,
+            flag_ids,
+            modified_parsed_flags.into_iter(),
+            mode,
+            allow_instrumentation,
+        )
+        .unwrap();
         assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
         assert_eq!(
             None,
             crate::test::first_significant_code_diff(
-                match mode {
-                    CodegenMode::Production => PROD_EXPECTED,
-                    CodegenMode::Test => TEST_EXPECTED,
-                    CodegenMode::Exported => EXPORTED_EXPECTED,
-                    CodegenMode::ForceReadOnly => FORCE_READ_ONLY_EXPECTED,
-                },
+                expected,
                 &String::from_utf8(generated.contents).unwrap()
             )
         );
@@ -658,21 +1326,26 @@
 
     #[test]
     fn test_generate_rust_code_for_prod() {
-        test_generate_rust_code(CodegenMode::Production);
+        test_generate_rust_code(CodegenMode::Production, false, PROD_EXPECTED);
+    }
+
+    #[test]
+    fn test_generate_rust_code_for_prod_instrumented() {
+        test_generate_rust_code(CodegenMode::Production, true, PROD_INSTRUMENTED_EXPECTED);
     }
 
     #[test]
     fn test_generate_rust_code_for_test() {
-        test_generate_rust_code(CodegenMode::Test);
+        test_generate_rust_code(CodegenMode::Test, false, TEST_EXPECTED);
     }
 
     #[test]
     fn test_generate_rust_code_for_exported() {
-        test_generate_rust_code(CodegenMode::Exported);
+        test_generate_rust_code(CodegenMode::Exported, false, EXPORTED_EXPECTED);
     }
 
     #[test]
     fn test_generate_rust_code_for_force_read_only() {
-        test_generate_rust_code(CodegenMode::ForceReadOnly);
+        test_generate_rust_code(CodegenMode::ForceReadOnly, false, FORCE_READ_ONLY_EXPECTED);
     }
 }
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 6d1c2f5..59f0662 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -238,7 +238,11 @@
     )
 }
 
-pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
+pub fn create_rust_lib(
+    mut input: Input,
+    codegen_mode: CodegenMode,
+    allow_instrumentation: bool,
+) -> Result<OutputFile> {
     // // TODO(327420679): Enable export mode for native flag library
     ensure!(
         codegen_mode != CodegenMode::Exported,
@@ -250,8 +254,14 @@
         bail!("no parsed flags, or the parsed flags use different packages");
     };
     let package = package.to_string();
-    let _flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
-    generate_rust_code(&package, modified_parsed_flags.into_iter(), codegen_mode)
+    let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
+    generate_rust_code(
+        &package,
+        flag_ids,
+        modified_parsed_flags.into_iter(),
+        codegen_mode,
+        allow_instrumentation,
+    )
 }
 
 pub fn create_storage(
diff --git a/tools/aconfig/aconfig/src/main.rs b/tools/aconfig/aconfig/src/main.rs
index 7ec272f..1fb64f9 100644
--- a/tools/aconfig/aconfig/src/main.rs
+++ b/tools/aconfig/aconfig/src/main.rs
@@ -102,6 +102,12 @@
                 .arg(Arg::new("cache").long("cache").required(true))
                 .arg(Arg::new("out").long("out").required(true))
                 .arg(
+                    Arg::new("allow-instrumentation")
+                        .long("allow-instrumentation")
+                        .value_parser(clap::value_parser!(bool))
+                        .default_value("false"),
+                )
+                .arg(
                     Arg::new("mode")
                         .long("mode")
                         .value_parser(EnumValueParser::<CodegenMode>::new())
@@ -267,8 +273,10 @@
         Some(("create-rust-lib", sub_matches)) => {
             let cache = open_single_file(sub_matches, "cache")?;
             let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
-            let generated_file =
-                commands::create_rust_lib(cache, *mode).context("failed to create rust lib")?;
+            let allow_instrumentation =
+                get_required_arg::<bool>(sub_matches, "allow-instrumentation")?;
+            let generated_file = commands::create_rust_lib(cache, *mode, *allow_instrumentation)
+                .context("failed to create rust lib")?;
             let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
             write_output_file_realtive_to_dir(&dir, &generated_file)?;
         }
diff --git a/tools/aconfig/aconfig/templates/rust.template b/tools/aconfig/aconfig/templates/rust.template
index f9a2829..cfd9d6a 100644
--- a/tools/aconfig/aconfig/templates/rust.template
+++ b/tools/aconfig/aconfig/templates/rust.template
@@ -1,17 +1,86 @@
 //! codegenerated rust flag lib
+use aconfig_storage_read_api::\{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
+use std::path::Path;
+use std::io::Write;
+use log::\{log, LevelFilter, Level};
+
+static STORAGE_MIGRATION_MARKER_FILE: &str =
+    "/metadata/aconfig_test_missions/mission_1";
+static MIGRATION_LOG_TAG: &str = "AconfigTestMission1";
 
 /// flag provider
 pub struct FlagProvider;
 
 {{ if has_readwrite- }}
 lazy_static::lazy_static! \{
+    {{ if allow_instrumentation }}
+    static ref PACKAGE_OFFSET: Result<Option<u32>, AconfigStorageError> = unsafe \{
+        get_mapped_storage_file("{container}", StorageFileType::PackageMap)
+        .and_then(|package_map| get_package_read_context(&package_map, "{package}"))
+        .map(|context| context.map(|c| c.boolean_start_index))
+    };
+
+    static ref FLAG_VAL_MAP: Result<Mmap, AconfigStorageError> = unsafe \{
+        get_mapped_storage_file("{container}", StorageFileType::FlagVal)
+    };
+    {{ -endif }}
+
 {{ -for flag in template_flags }}
     {{ -if flag.readwrite }}
     /// flag value cache for {flag.name}
+    {{ if allow_instrumentation }}
+    static ref CACHED_{flag.name}: bool = \{
+        let result = flags_rust::GetServerConfigurableFlag(
+            "aconfig_flags.{flag.device_config_namespace}",
+            "{flag.device_config_flag}",
+            "{flag.default_value}") == "true";
+
+        if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() \{
+            // This will be called multiple times. Subsequent calls after the first are noops.
+            logger::init(
+                logger::Config::default()
+                    .with_tag_on_device(MIGRATION_LOG_TAG)
+                    .with_max_level(LevelFilter::Info));
+
+            let aconfig_storage_result = FLAG_VAL_MAP
+                .as_ref()
+                .map_err(|err| format!("failed to get flag val map: \{err}"))
+                .and_then(|flag_val_map| \{
+                    PACKAGE_OFFSET
+                        .as_ref()
+                        .map_err(|err| format!("failed to get package read offset: \{err}"))
+                        .and_then(|package_offset| \{
+                            match package_offset \{
+                                Some(offset) => \{
+                                    get_boolean_flag_value(&flag_val_map, offset + {flag.flag_offset})
+                                        .map_err(|err| format!("failed to get flag: \{err}"))
+                                },
+                                None => Err("no context found for package '{package}'".to_string())
+                            }
+                        })
+                    });
+
+            match aconfig_storage_result \{
+                Ok(storage_result) if storage_result == result => \{
+                    log!(Level::Info, "AconfigTestMission1: success! flag '{flag.name}' contained correct value. Legacy storage was \{result}, new storage was \{storage_result}");
+                },
+                Ok(storage_result) => \{
+                    log!(Level::Error, "AconfigTestMission1: error: mismatch for flag '{flag.name}'. Legacy storage was \{result}, new storage was \{storage_result}");
+                },
+                Err(err) => \{
+                    log!(Level::Error, "AconfigTestMission1: error: \{err}")
+                }
+            }
+        }
+
+        result
+        };
+    {{ else }}
     static ref CACHED_{flag.name}: bool = flags_rust::GetServerConfigurableFlag(
         "aconfig_flags.{flag.device_config_namespace}",
         "{flag.device_config_flag}",
         "{flag.default_value}") == "true";
+    {{ endif }}
     {{ -endif }}
 {{ -endfor }}
 }
@@ -22,11 +91,11 @@
 {{ for flag in template_flags }}
     /// query flag {flag.name}
     pub fn {flag.name}(&self) -> bool \{
-    {{ -if flag.readwrite }}
+        {{ -if flag.readwrite }}
         *CACHED_{flag.name}
-    {{ -else }}
+        {{ -else }}
         {flag.default_value}
-    {{ -endif }}
+        {{ -endif }}
     }
 {{ endfor }}
 
@@ -43,7 +112,68 @@
     PROVIDER.{flag.name}()
 {{ -else }}
 pub fn {flag.name}() -> bool \{
+    {{ if not allow_instrumentation }}
     {flag.default_value}
+    {{ else }}
+
+    let result = {flag.default_value};
+    if !Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() \{
+        return result;
+    }
+
+    // This will be called multiple times. Subsequent calls after the first
+    // are noops.
+    logger::init(
+        logger::Config::default()
+            .with_tag_on_device(MIGRATION_LOG_TAG)
+            .with_max_level(LevelFilter::Info),
+    );
+
+    unsafe \{
+        let package_map = match get_mapped_storage_file("{flag.container}", StorageFileType::PackageMap) \{
+            Ok(file) => file,
+            Err(err) => \{
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag '{flag.name}': \{err}");
+                return result;
+            }
+        };
+
+        let package_read_context = match get_package_read_context(&package_map, "{package}") \{
+            Ok(Some(context)) => context,
+            Ok(None) => \{
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag '{flag.name}': did not get context");
+                return result;
+            },
+            Err(err) => \{
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag '{flag.name}': \{err}");
+                return result;
+            }
+        };
+        let flag_val_map = match get_mapped_storage_file("{flag.container}", StorageFileType::FlagVal) \{
+            Ok(val_map) => val_map,
+            Err(err) => \{
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag '{flag.name}': \{err}");
+                return result;
+            }
+        };
+        let value = match get_boolean_flag_value(&flag_val_map, {flag.flag_offset} + package_read_context.boolean_start_index) \{
+            Ok(val) => val,
+            Err(err) => \{
+                log!(Level::Error, "AconfigTestMission1: error: failed to read flag '{flag.name}': \{err}");
+                return result;
+            }
+        };
+
+        if result != value \{
+            log!(Level::Error, "AconfigTestMission1: error: flag mismatch for '{flag.name}'. Legacy storage was \{result}, new storage was \{value}");
+        } else \{
+            let default_value = {flag.default_value};
+            log!(Level::Info, "AconfigTestMission1: success! flag '{flag.name}' contained correct value. Legacy storage was \{default_value}, new storage was \{value}");
+        }
+    }
+
+    result
+    {{ endif }}
 {{ -endif }}
 }
 {{ endfor }}
diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
index 61f9e96..d76cf3f 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
@@ -53,7 +53,7 @@
 use package_table_query::find_package_read_context;
 
 use anyhow::anyhow;
-use memmap2::Mmap;
+pub use memmap2::Mmap;
 use std::fs::File;
 use std::io::Read;
 
diff --git a/tools/filelistdiff/Android.bp b/tools/filelistdiff/Android.bp
index 632ada3..ab766d6 100644
--- a/tools/filelistdiff/Android.bp
+++ b/tools/filelistdiff/Android.bp
@@ -24,4 +24,4 @@
 prebuilt_etc_host {
     name: "system_image_diff_allowlist",
     src: "allowlist",
-}
+}
\ No newline at end of file
diff --git a/tools/finalization/README.md b/tools/finalization/README.md
index d0aed69..5e2aecd 100644
--- a/tools/finalization/README.md
+++ b/tools/finalization/README.md
@@ -19,3 +19,8 @@
 
 ## Utility:
 [Full cleanup](./cleanup.sh). Remove all local changes and switch each project into head-less state. This is the best state to sync/rebase/finalize the branch.
+
+## Dry run:
+[Full cleanup](./dryrun-cleanup.sh). Remove all local changes and switch each project into head-less state. Also removes "DryRun" branches.
+[SDK](./dryrun-step-1.sh). Perform SDK finalization and upload the CLs to Gerrit.
+[SDK and REL](./dryrun-step-1-and-2.sh). Perform SDK finalization, plus all necessary changes to switch configuration to REL, and upload the CLs to Gerrit.
\ No newline at end of file
diff --git a/tools/finalization/build-step-1-and-m.sh b/tools/finalization/build-step-1-and-m.sh
index 0e7129f..88bb347 100755
--- a/tools/finalization/build-step-1-and-m.sh
+++ b/tools/finalization/build-step-1-and-m.sh
@@ -9,10 +9,9 @@
     local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
 
     # This command tests:
-    #   The release state for AIDL.
     #   ABI difference between user and userdebug builds.
     #   Resource/SDK finalization.
-    AIDL_FROZEN_REL=true $m
+    $m
 }
 
 finalize_main_step1_and_m
diff --git a/tools/finalization/cleanup.sh b/tools/finalization/cleanup.sh
index cd87b1d..e2a0592 100755
--- a/tools/finalization/cleanup.sh
+++ b/tools/finalization/cleanup.sh
@@ -14,8 +14,8 @@
 
     repo forall -c '\
         git checkout . ; git revert --abort ; git clean -fdx ;\
-        git checkout @ ; git branch fina-step1 -D ; git reset --hard; \
-        repo start fina-step1 ; git checkout @ ; git b fina-step1 -D ;'
+        git checkout @ --detach ; git branch fina-step1 -D ; git reset --hard; \
+        repo start fina-step1 ; git checkout @ --detach ; git b fina-step1 -D ;'
 }
 
 finalize_revert_local_changes_main
diff --git a/tools/finalization/command-line-options.sh b/tools/finalization/command-line-options.sh
new file mode 100644
index 0000000..d9397c2
--- /dev/null
+++ b/tools/finalization/command-line-options.sh
@@ -0,0 +1,8 @@
+ARGV=$(getopt --options '' --long dry-run -- "$@")
+eval set -- "$ARGV"
+while true; do
+    case "$1" in
+        --dry-run) repo_upload_dry_run_arg="--dry-run"; repo_branch="finalization-dry-run"; shift ;;
+        *) break
+    esac
+done
diff --git a/tools/finalization/dryrun-cleanup.sh b/tools/finalization/dryrun-cleanup.sh
new file mode 100755
index 0000000..ddaffae
--- /dev/null
+++ b/tools/finalization/dryrun-cleanup.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Brings local repository to a remote head state. Also removes all dryrun branches.
+
+# set -ex
+
+function finalize_revert_local_changes_main() {
+    local top="$(dirname "$0")"/../../../..
+    source $top/build/make/tools/finalization/environment.sh
+
+    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+
+    # remove the out folder
+    $m clobber
+
+    repo selfupdate
+
+    repo forall -c '\
+        git checkout . ; git revert --abort ; git clean -fdx ;\
+        git checkout @ --detach ; git branch fina-step1 -D ; git reset --hard; \
+        repo start fina-step1 ; git checkout @ --detach ; git b fina-step1 -D ; \
+        git b $FINAL_PLATFORM_CODENAME-SDK-Finalization-DryRun -D; \
+        git b $FINAL_PLATFORM_CODENAME-SDK-Finalization-DryRun-Rel -D; '
+}
+
+finalize_revert_local_changes_main
diff --git a/tools/finalization/dryrun-step-1-and-2.sh b/tools/finalization/dryrun-step-1-and-2.sh
new file mode 100755
index 0000000..f883bca
--- /dev/null
+++ b/tools/finalization/dryrun-step-1-and-2.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# Script to perform 1st and 2nd step of Android Finalization, create CLs and upload to Gerrit.
+
+function commit_step_2_changes() {
+    repo forall -c '\
+        if [[ $(git status --short) ]]; then
+            repo start "$FINAL_PLATFORM_CODENAME-SDK-Finalization-DryRun-Rel" ;
+            git add -A . ;
+            git commit -m "$FINAL_PLATFORM_CODENAME/$FINAL_PLATFORM_SDK_VERSION is now REL" \
+                       -m "Ignore-AOSP-First: $FINAL_PLATFORM_CODENAME Finalization
+Bug: $FINAL_BUG_ID
+Test: build";
+
+            repo upload --cbr --no-verify -o nokeycheck -t -y . ;
+        fi'
+}
+
+function finalize_step_2_main() {
+    local top="$(dirname "$0")"/../../../..
+    source $top/build/make/tools/finalization/environment.sh
+
+    source $top/build/make/tools/finalization/finalize-sdk-resources.sh
+
+    source $top/build/make/tools/finalization/localonly-steps.sh
+
+    source $top/build/make/tools/finalization/finalize-sdk-rel.sh
+
+    # move all changes to finalization branch/topic and upload to gerrit
+    commit_step_2_changes
+
+    # build to confirm everything is OK
+    local m_next="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=next TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    $m_next
+
+    local m_fina="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=fina_2 TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    $m_fina
+}
+
+finalize_step_2_main
diff --git a/tools/finalization/dryrun-step-1.sh b/tools/finalization/dryrun-step-1.sh
new file mode 100755
index 0000000..0f2bc63
--- /dev/null
+++ b/tools/finalization/dryrun-step-1.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Script to perform a dry run of step 1 of Android Finalization, create CLs and upload to Gerrit.
+
+function commit_step_1_changes() {
+    repo forall -c '\
+        if [[ $(git status --short) ]]; then
+            repo start "$FINAL_PLATFORM_CODENAME-SDK-Finalization-DryRun" ;
+            git add -A . ;
+            git commit -m "$FINAL_PLATFORM_CODENAME is now $FINAL_PLATFORM_SDK_VERSION" \
+                       -m "Ignore-AOSP-First: $FINAL_PLATFORM_CODENAME Finalization
+Bug: $FINAL_BUG_ID
+Test: build";
+
+            repo upload --cbr --no-verify -o nokeycheck -t -y . ;
+        fi'
+}
+
+function finalize_step_1_main() {
+    local top="$(dirname "$0")"/../../../..
+    source $top/build/make/tools/finalization/environment.sh
+
+    source $top/build/make/tools/finalization/finalize-sdk-resources.sh
+
+    # move all changes to finalization branch/topic and upload to gerrit
+    commit_step_1_changes
+
+    # build to confirm everything is OK
+    local m_next="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=next TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    $m_next
+
+    local m_fina="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=fina_1 TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    $m_fina
+}
+
+finalize_step_1_main
diff --git a/tools/finalization/environment.sh b/tools/finalization/environment.sh
index 7961e8b..f68a68b 100755
--- a/tools/finalization/environment.sh
+++ b/tools/finalization/environment.sh
@@ -15,14 +15,14 @@
 # We might or might not fix this in future, but for now let's keep it +1.
 export FINAL_PLATFORM_SDK_VERSION='35'
 # Feel free to randomize once in a while to detect buggy version detection code.
-export FINAL_MAINLINE_EXTENSION='58'
+export FINAL_MAINLINE_EXTENSION='13'
 
 # Options:
 # 'unfinalized' - branch is in development state,
 # 'vintf' - VINTF is finalized
 # 'sdk' - VINTF and SDK/API are finalized
 # 'rel' - branch is finalized, switched to REL
-export FINAL_STATE='vintf'
+export FINAL_STATE='rel'
 
 export BUILD_FROM_SOURCE_STUB=true
 
diff --git a/tools/finalization/finalize-sdk-rel.sh b/tools/finalization/finalize-sdk-rel.sh
index 59fe28c..c49f974 100755
--- a/tools/finalization/finalize-sdk-rel.sh
+++ b/tools/finalization/finalize-sdk-rel.sh
@@ -8,12 +8,6 @@
     fi
 }
 
-function revert_resources_sdk_int_fix() {
-    if grep -q 'public static final int RESOURCES_SDK_INT = SDK_INT;' "$top/frameworks/base/core/java/android/os/Build.java" ; then
-        patch --strip=1 --no-backup-if-mismatch --directory="$top/frameworks/base" --input=../../build/make/tools/finalization/frameworks_base.revert_resource_sdk_int.diff
-    fi
-}
-
 function apply_prerelease_sdk_hack() {
     if ! grep -q 'STOPSHIP: hack for the pre-release SDK' "$top/frameworks/base/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java" ; then
         patch --strip=1 --no-backup-if-mismatch --directory="$top/frameworks/base" --input=../../build/make/tools/finalization/frameworks_base.apply_hack.diff
@@ -30,25 +24,18 @@
     # let the apps built with pre-release SDK parse
     apply_prerelease_sdk_hack
 
-    # in REL mode, resources would correctly set the resources_sdk_int, no fix required
-    revert_resources_sdk_int_fix
-
     # cts
-    echo "$FINAL_PLATFORM_VERSION" > "$top/cts/tests/tests/os/assets/platform_versions.txt"
+    if ! grep -q "${FINAL_PLATFORM_VERSION}" "$top/cts/tests/tests/os/assets/platform_versions.txt" ; then
+        echo ${FINAL_PLATFORM_VERSION} >> "$top/cts/tests/tests/os/assets/platform_versions.txt"
+    fi
     if [ "$FINAL_PLATFORM_CODENAME" != "$CURRENT_PLATFORM_CODENAME" ]; then
         echo "$CURRENT_PLATFORM_CODENAME" >> "./cts/tests/tests/os/assets/platform_versions.txt"
     fi
     git -C "$top/cts" mv hostsidetests/theme/assets/${FINAL_PLATFORM_CODENAME} hostsidetests/theme/assets/${FINAL_PLATFORM_SDK_VERSION}
 
     # prebuilts/abi-dumps/platform
-    mkdir -p "$top/prebuilts/abi-dumps/platform/$FINAL_PLATFORM_SDK_VERSION"
-    cp -r "$top/prebuilts/abi-dumps/platform/current/64/" "$top/prebuilts/abi-dumps/platform/$FINAL_PLATFORM_SDK_VERSION/"
-
-    # TODO(b/309880485)
-    # uncomment and update
-    # prebuilts/abi-dumps/ndk
-    #mkdir -p "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION"
-    #cp -r "$top/prebuilts/abi-dumps/ndk/current/64/" "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION/"
+    "$top/build/soong/soong_ui.bash" --make-mode TARGET_RELEASE=next TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug create_reference_dumps
+    ANDROID_BUILD_TOP="$top" "$top/out/host/linux-x86/bin/create_reference_dumps" -release next --build-variant userdebug --lib-variant APEX
 }
 
 finalize_sdk_rel
diff --git a/tools/finalization/finalize-sdk-resources.sh b/tools/finalization/finalize-sdk-resources.sh
index 596f803..10266ed 100755
--- a/tools/finalization/finalize-sdk-resources.sh
+++ b/tools/finalization/finalize-sdk-resources.sh
@@ -9,13 +9,6 @@
     fi
 }
 
-function apply_resources_sdk_int_fix() {
-    if ! grep -q 'public static final int RESOURCES_SDK_INT = SDK_INT;' "$top/frameworks/base/core/java/android/os/Build.java" ; then
-        local base_git_root="$(readlink -f $top/frameworks/base)"
-        patch --strip=1 --no-backup-if-mismatch --directory="$base_git_root" --input=../../build/make/tools/finalization/frameworks_base.apply_resource_sdk_int.diff
-    fi
-}
-
 function finalize_bionic_ndk() {
     # Adding __ANDROID_API_<>__.
     # If this hasn't done then it's not used and not really needed. Still, let's check and add this.
@@ -41,7 +34,8 @@
     echo "    /** Checks if the device is running on a release version of Android $FINAL_PLATFORM_CODENAME or newer */
     @ChecksSdkIntAtLeast(api = $FINAL_PLATFORM_SDK_VERSION /* BUILD_VERSION_CODES.$FINAL_PLATFORM_CODENAME */)
     public static boolean isAtLeast${FINAL_PLATFORM_CODENAME:0:1}() {
-        return SDK_INT >= $FINAL_PLATFORM_SDK_VERSION;
+        return SDK_INT >= $FINAL_PLATFORM_SDK_VERSION ||
+                (SDK_INT == $(($FINAL_PLATFORM_SDK_VERSION - 1)) && isAtLeastPreReleaseCodename(\"$FINAL_PLATFORM_CODENAME\"));
     }" > "$tmpfile"
 
     local javaFuncRegex='\/\*\*[^{]*isAtLeast'"${shortCodename}"'() {[^{}]*}'
@@ -55,7 +49,11 @@
            d}' $javaSdkLevel
 
     echo "// Checks if the device is running on release version of Android ${FINAL_PLATFORM_CODENAME:0:1} or newer.
-inline bool IsAtLeast${FINAL_PLATFORM_CODENAME:0:1}() { return android_get_device_api_level() >= $FINAL_PLATFORM_SDK_VERSION; }" > "$tmpfile"
+inline bool IsAtLeast${FINAL_PLATFORM_CODENAME:0:1}() {
+  return android_get_device_api_level() >= $FINAL_PLATFORM_SDK_VERSION ||
+         (android_get_device_api_level() == $(($FINAL_PLATFORM_SDK_VERSION - 1)) &&
+          detail::IsAtLeastPreReleaseCodename(\"$FINAL_PLATFORM_CODENAME\"));
+}" > "$tmpfile"
 
     local cppFuncRegex='\/\/[^{]*IsAtLeast'"${shortCodename}"'() {[^{}]*}'
     local cppFuncReplace="N;N;N;N;N;N; s/$cppFuncRegex/$methodPlaceholder/; /$cppFuncRegex/!{P;D};"
@@ -123,14 +121,18 @@
     sed -i -e 's/Pkg\.Revision.*/Pkg\.Revision=${PLATFORM_SDK_VERSION}.0.0/g' $build_tools_source
 
     # build/soong
-    local codename_version="\"${FINAL_PLATFORM_CODENAME}\": ${FINAL_PLATFORM_SDK_VERSION}"
+    local codename_version="\"${FINAL_PLATFORM_CODENAME}\":     ${FINAL_PLATFORM_SDK_VERSION}"
     if ! grep -q "$codename_version" "$top/build/soong/android/api_levels.go" ; then
         sed -i -e "/:.*$((${FINAL_PLATFORM_SDK_VERSION}-1)),/a \\\t\t$codename_version," "$top/build/soong/android/api_levels.go"
     fi
 
     # cts
-    echo ${FINAL_PLATFORM_VERSION} > "$top/cts/tests/tests/os/assets/platform_releases.txt"
-    sed -i -e "s/EXPECTED_SDK = $((${FINAL_PLATFORM_SDK_VERSION}-1))/EXPECTED_SDK = ${FINAL_PLATFORM_SDK_VERSION}/g" "$top/cts/tests/tests/os/src/android/os/cts/BuildVersionTest.java"
+    if ! grep -q "${FINAL_PLATFORM_VERSION}" "$top/cts/tests/tests/os/assets/platform_releases.txt" ; then
+        echo ${FINAL_PLATFORM_VERSION} >> "$top/cts/tests/tests/os/assets/platform_releases.txt"
+    fi
+    if ! grep -q "$((${FINAL_PLATFORM_SDK_VERSION}-1)), ${FINAL_PLATFORM_VERSION}" "$top/cts/tests/tests/os/src/android/os/cts/BuildVersionTest.java" ; then
+        sed -i -e "s/.*EXPECTED_SDKS = List.of(.*$((${FINAL_PLATFORM_SDK_VERSION}-1))/&, $FINAL_PLATFORM_SDK_VERSION/" "$top/cts/tests/tests/os/src/android/os/cts/BuildVersionTest.java"
+    fi
 
     # libcore
     sed -i "s%$SDK_CODENAME%$SDK_VERSION%g" "$top/libcore/dalvik/src/main/java/dalvik/annotation/compat/VersionCodes.java"
@@ -153,7 +155,6 @@
 
     # frameworks/base
     sed -i "s%$SDK_CODENAME%$SDK_VERSION%g" "$top/frameworks/base/core/java/android/os/Build.java"
-    apply_resources_sdk_int_fix
     sed -i -e "/=.*$((${FINAL_PLATFORM_SDK_VERSION}-1)),/a \\    SDK_${FINAL_PLATFORM_CODENAME_JAVA} = ${FINAL_PLATFORM_SDK_VERSION}," "$top/frameworks/base/tools/aapt/SdkConstants.h"
     sed -i -e "/=.*$((${FINAL_PLATFORM_SDK_VERSION}-1)),/a \\  SDK_${FINAL_PLATFORM_CODENAME_JAVA} = ${FINAL_PLATFORM_SDK_VERSION}," "$top/frameworks/base/tools/aapt2/SdkConstants.h"
 
diff --git a/tools/finalization/finalize-vintf-resources.sh b/tools/finalization/finalize-vintf-resources.sh
index a55d8e1..d532b25 100755
--- a/tools/finalization/finalize-vintf-resources.sh
+++ b/tools/finalization/finalize-vintf-resources.sh
@@ -16,8 +16,6 @@
     export TARGET_RELEASE=fina_0
     export TARGET_PRODUCT=aosp_arm64
 
-    # TODO(b/314010764): finalize LL_NDK
-
     # system/sepolicy
     "$top/system/sepolicy/tools/finalize-vintf-resources.sh" "$top" "$FINAL_BOARD_API_LEVEL"
 
@@ -25,7 +23,11 @@
 
     # pre-finalization build target (trunk)
     local aidl_m="$top/build/soong/soong_ui.bash --make-mode"
-    AIDL_TRANSITIVE_FREEZE=true $aidl_m aidl-freeze-api
+    AIDL_TRANSITIVE_FREEZE=true $aidl_m aidl-freeze-api create_reference_dumps
+
+    # Generate LLNDK ABI dumps
+    # This command depends on ANDROID_BUILD_TOP
+    "$ANDROID_HOST_OUT/bin/create_reference_dumps" -release "$TARGET_RELEASE" --build-variant "$TARGET_BUILD_VARIANT" --lib-variant LLNDK
 }
 
 function create_new_compat_matrix_and_kernel_configs() {
diff --git a/tools/finalization/frameworks_base.apply_resource_sdk_int.diff b/tools/finalization/frameworks_base.apply_resource_sdk_int.diff
deleted file mode 100644
index f0576d0..0000000
--- a/tools/finalization/frameworks_base.apply_resource_sdk_int.diff
+++ /dev/null
@@ -1,24 +0,0 @@
-From cdb47fc90b8d6860ec1dc5efada1f9ccd471618b Mon Sep 17 00:00:00 2001
-From: Alex Buynytskyy <alexbuy@google.com>
-Date: Tue, 11 Apr 2023 22:12:44 +0000
-Subject: [PATCH] Don't force +1 for resource resolution.
-
-Bug: 277674088
-Fixes: 277674088
-Test: boots, no crashes
-Change-Id: I17e743a0f1cf6f98fddd40c358dea5a8b9cc7723
----
-
-diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
-index eb47170..4d3e92b 100755
---- a/core/java/android/os/Build.java
-+++ b/core/java/android/os/Build.java
-@@ -493,7 +493,7 @@
-          * @hide
-          */
-         @TestApi
--        public static final int RESOURCES_SDK_INT = SDK_INT + ACTIVE_CODENAMES.length;
-+        public static final int RESOURCES_SDK_INT = SDK_INT;
- 
-         /**
-          * The current lowest supported value of app target SDK. Applications targeting
diff --git a/tools/finalization/frameworks_base.revert_resource_sdk_int.diff b/tools/finalization/frameworks_base.revert_resource_sdk_int.diff
deleted file mode 100644
index 2ade499..0000000
--- a/tools/finalization/frameworks_base.revert_resource_sdk_int.diff
+++ /dev/null
@@ -1,27 +0,0 @@
-From c7e460bb19071d867cd7ca04282ce42694f4f358 Mon Sep 17 00:00:00 2001
-From: Alex Buynytskyy <alexbuy@google.com>
-Date: Wed, 12 Apr 2023 01:06:26 +0000
-Subject: [PATCH] Revert "Don't force +1 for resource resolution."
-
-It's not required for master.
-
-This reverts commit f1cb683988f81579a76ddbf9993848a4a06dd28c.
-
-Bug: 277674088
-Test: boots, no crashes
-Change-Id: Ia1692548f26496fdc6f1e4f0557213c7996d6823
----
-
-diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
-index 4d3e92b..eb47170 100755
---- a/core/java/android/os/Build.java
-+++ b/core/java/android/os/Build.java
-@@ -493,7 +493,7 @@
-          * @hide
-          */
-         @TestApi
--        public static final int RESOURCES_SDK_INT = SDK_INT;
-+        public static final int RESOURCES_SDK_INT = SDK_INT + ACTIVE_CODENAMES.length;
- 
-         /**
-          * The current lowest supported value of app target SDK. Applications targeting
diff --git a/tools/finalization/localonly-steps.sh b/tools/finalization/localonly-steps.sh
index bebd563..94ee368 100755
--- a/tools/finalization/localonly-steps.sh
+++ b/tools/finalization/localonly-steps.sh
@@ -10,14 +10,15 @@
     local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
 
     # adb keys
-    $m adb
-    LOGNAME=android-eng HOSTNAME=google.com "$top/out/host/linux-x86/bin/adb" keygen "$top/vendor/google/security/adb/${FINAL_PLATFORM_VERSION}.adb_key"
+    # The keys are already generated for Android 15. Keeping the command (commented out) for future reference.
+    # $m adb
+    # LOGNAME=android-eng HOSTNAME=google.com "$top/out/host/linux-x86/bin/adb" keygen "$top/vendor/google/security/adb/${FINAL_PLATFORM_VERSION}.adb_key"
 
     # Build Platform SDKs.
     $top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=sdk TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug sdk dist sdk_repo DIST_DIR=out/dist
 
     # Build Modules SDKs.
-    TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true DIST_DIR=out/dist "$top/vendor/google/build/mainline_modules_sdks.sh" --build-release=latest
+    TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true DIST_DIR=out/dist "$top/vendor/google/build/mainline_modules_sdks.sh" --build-release=next
 
     # Update prebuilts.
     "$top/prebuilts/build-tools/path/linux-x86/python3" -W ignore::DeprecationWarning "$top/prebuilts/sdk/update_prebuilts.py" --local_mode -f ${FINAL_PLATFORM_SDK_VERSION} -e ${FINAL_MAINLINE_EXTENSION} --bug 1 1
diff --git a/tools/finalization/step-0.sh b/tools/finalization/step-0.sh
index e61c644..2087f6e 100755
--- a/tools/finalization/step-0.sh
+++ b/tools/finalization/step-0.sh
@@ -9,19 +9,21 @@
     set +e
     repo forall -c '\
         if [[ $(git status --short) ]]; then
-            repo start "VINTF-$FINAL_BOARD_API_LEVEL-Finalization" ;
+            repo start "'$repo_branch'" ;
             git add -A . ;
             git commit -m "Vendor API level $FINAL_BOARD_API_LEVEL is now frozen" \
                        -m "Ignore-AOSP-First: VINTF $FINAL_BOARD_API_LEVEL Finalization
 Bug: $FINAL_BUG_ID
 Test: build";
-            repo upload --cbr --no-verify -o nokeycheck -t -y . ;
+            repo upload '"$repo_upload_dry_run_arg"' --cbr --no-verify -o nokeycheck -t -y . ;
         fi'
 }
 
 function finalize_step_0_main() {
     local top="$(dirname "$0")"/../../../..
     source $top/build/make/tools/finalization/environment.sh
+    local repo_branch="VINTF-$FINAL_BOARD_API_LEVEL-Finalization"
+    source $top/build/make/tools/finalization/command-line-options.sh
 
     local m="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=next TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
 
@@ -34,4 +36,4 @@
     AIDL_FROZEN_REL=true $m
 }
 
-finalize_step_0_main
+finalize_step_0_main $@
diff --git a/tools/finalization/step-1.sh b/tools/finalization/step-1.sh
index 0e483d5..736d641 100755
--- a/tools/finalization/step-1.sh
+++ b/tools/finalization/step-1.sh
@@ -7,21 +7,21 @@
     set +e
     repo forall -c '\
         if [[ $(git status --short) ]]; then
-            repo start "$FINAL_PLATFORM_CODENAME-SDK-Finalization" ;
+            repo start "'$repo_branch'" ;
             git add -A . ;
             git commit -m "$FINAL_PLATFORM_CODENAME is now $FINAL_PLATFORM_SDK_VERSION and extension version $FINAL_MAINLINE_EXTENSION" \
                        -m "Ignore-AOSP-First: $FINAL_PLATFORM_CODENAME Finalization
 Bug: $FINAL_BUG_ID
 Test: build";
-            repo upload --cbr --no-verify -o nokeycheck -t -y . ;
+            repo upload '"$repo_upload_dry_run_arg"' --cbr --no-verify -o nokeycheck -t -y . ;
         fi'
 }
 
 function finalize_step_1_main() {
     local top="$(dirname "$0")"/../../../..
     source $top/build/make/tools/finalization/environment.sh
-
-    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=next TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    local repo_branch="$FINAL_PLATFORM_CODENAME-SDK-Finalization"
+    source $top/build/make/tools/finalization/command-line-options.sh
 
     source $top/build/make/tools/finalization/finalize-sdk-resources.sh
 
@@ -29,7 +29,11 @@
     commit_step_1_changes
 
     # build to confirm everything is OK
-    AIDL_FROZEN_REL=true $m
+    local m_next="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=next TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    $m_next
+
+    local m_fina="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=fina_1 TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    $m_fina
 }
 
-finalize_step_1_main
+finalize_step_1_main $@
diff --git a/tools/finalization/step-2.sh b/tools/finalization/step-2.sh
index 356cad0..52e3887 100755
--- a/tools/finalization/step-2.sh
+++ b/tools/finalization/step-2.sh
@@ -4,22 +4,22 @@
 function commit_step_2_changes() {
     repo forall -c '\
         if [[ $(git status --short) ]]; then
-            repo start "$FINAL_PLATFORM_CODENAME-SDK-Finalization-Rel" ;
+            repo start "'$repo_branch'" ;
             git add -A . ;
             git commit -m "$FINAL_PLATFORM_CODENAME/$FINAL_PLATFORM_SDK_VERSION is now REL" \
                        -m "Ignore-AOSP-First: $FINAL_PLATFORM_CODENAME Finalization
 Bug: $FINAL_BUG_ID
 Test: build";
 
-            repo upload --cbr --no-verify -o nokeycheck -t -y . ;
+            repo upload '"$repo_upload_dry_run_arg"' --cbr --no-verify -o nokeycheck -t -y . ;
         fi'
 }
 
 function finalize_step_2_main() {
     local top="$(dirname "$0")"/../../../..
     source $top/build/make/tools/finalization/environment.sh
-
-    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=next TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    local repo_branch="$FINAL_PLATFORM_CODENAME-SDK-Finalization-Rel"
+    source $top/build/make/tools/finalization/command-line-options.sh
 
     # prebuilts etc
     source $top/build/make/tools/finalization/finalize-sdk-rel.sh
@@ -28,7 +28,11 @@
     commit_step_2_changes
 
     # build to confirm everything is OK
-    AIDL_FROZEN_REL=true $m
+    local m_next="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=next TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    $m_next
+
+    local m_fina="$top/build/soong/soong_ui.bash --make-mode TARGET_RELEASE=fina_2 TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+    $m_fina
 }
 
-finalize_step_2_main
+finalize_step_2_main $@