Merge changes Iadea7ba2,Iaedb8a68,I511e05ab into main

* changes:
  aconfig: add c/c++ codegen exported mode integration test
  aconfig: add new testing flag enabled_fixed_ro_exported
  aconfig: add exported mode in c/c++ codegen
diff --git a/tools/aconfig/Android.bp b/tools/aconfig/Android.bp
index 82bfa7e..05fbad1 100644
--- a/tools/aconfig/Android.bp
+++ b/tools/aconfig/Android.bp
@@ -174,6 +174,12 @@
     mode: "test",
 }
 
+cc_aconfig_library {
+    name: "aconfig_test_cpp_library_exported_variant",
+    aconfig_declarations: "aconfig.test.flags",
+    mode: "exported",
+}
+
 cc_test {
     name: "aconfig.test.cpp",
     srcs: [
@@ -204,6 +210,21 @@
     test_suites: ["general-tests"],
 }
 
+cc_test {
+    name: "aconfig.test.cpp.exported_mode",
+    srcs: [
+        "tests/aconfig_exported_mode_test.cpp",
+    ],
+    static_libs: [
+        "aconfig_test_cpp_library_exported_variant",
+        "libgmock",
+    ],
+    shared_libs: [
+        "server_configurable_flags",
+    ],
+    test_suites: ["general-tests"],
+}
+
 rust_aconfig_library {
     name: "libaconfig_test_rust_library",
     crate_name: "aconfig_test_rust_library",
diff --git a/tools/aconfig/src/codegen/cpp.rs b/tools/aconfig/src/codegen/cpp.rs
index 568302d..c420913 100644
--- a/tools/aconfig/src/codegen/cpp.rs
+++ b/tools/aconfig/src/codegen/cpp.rs
@@ -49,7 +49,9 @@
         has_fixed_read_only,
         readwrite,
         readwrite_count,
-        for_test: codegen_mode == CodegenMode::Test,
+        is_test_mode: codegen_mode == CodegenMode::Test,
+        is_prod_mode: codegen_mode == CodegenMode::Production,
+        is_exported_mode: codegen_mode == CodegenMode::Exported,
         class_elements,
     };
 
@@ -92,7 +94,9 @@
     pub has_fixed_read_only: bool,
     pub readwrite: bool,
     pub readwrite_count: i32,
-    pub for_test: bool,
+    pub is_test_mode: bool,
+    pub is_prod_mode: bool,
+    pub is_exported_mode: bool,
     pub class_elements: Vec<ClassElement>,
 }
 
@@ -149,6 +153,10 @@
 #define COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO true
 #endif
 
+#ifndef COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO_EXPORTED
+#define COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO_EXPORTED true
+#endif
+
 #ifdef __cplusplus
 
 #include <memory>
@@ -169,6 +177,8 @@
 
     virtual bool enabled_fixed_ro() = 0;
 
+    virtual bool enabled_fixed_ro_exported() = 0;
+
     virtual bool enabled_ro() = 0;
 
     virtual bool enabled_ro_exported() = 0;
@@ -198,6 +208,10 @@
     return COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO;
 }
 
+inline bool enabled_fixed_ro_exported() {
+    return COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO_EXPORTED;
+}
+
 inline bool enabled_ro() {
     return true;
 }
@@ -225,6 +239,8 @@
 
 bool com_android_aconfig_test_enabled_fixed_ro();
 
+bool com_android_aconfig_test_enabled_fixed_ro_exported();
+
 bool com_android_aconfig_test_enabled_ro();
 
 bool com_android_aconfig_test_enabled_ro_exported();
@@ -270,6 +286,10 @@
 
     virtual void enabled_fixed_ro(bool val) = 0;
 
+    virtual bool enabled_fixed_ro_exported() = 0;
+
+    virtual void enabled_fixed_ro_exported(bool val) = 0;
+
     virtual bool enabled_ro() = 0;
 
     virtual void enabled_ro(bool val) = 0;
@@ -327,6 +347,14 @@
     provider_->enabled_fixed_ro(val);
 }
 
+inline bool enabled_fixed_ro_exported() {
+    return provider_->enabled_fixed_ro_exported();
+}
+
+inline void enabled_fixed_ro_exported(bool val) {
+    provider_->enabled_fixed_ro_exported(val);
+}
+
 inline bool enabled_ro() {
     return provider_->enabled_ro();
 }
@@ -380,6 +408,10 @@
 
 void set_com_android_aconfig_test_enabled_fixed_ro(bool val);
 
+bool com_android_aconfig_test_enabled_fixed_ro_exported();
+
+void set_com_android_aconfig_test_enabled_fixed_ro_exported(bool val);
+
 bool com_android_aconfig_test_enabled_ro();
 
 void set_com_android_aconfig_test_enabled_ro(bool val);
@@ -402,6 +434,56 @@
 
 "#;
 
+    const EXPORTED_EXPORTED_HEADER_EXPECTED: &str = r#"
+#pragma once
+
+#ifdef __cplusplus
+
+#include <memory>
+
+namespace com::android::aconfig::test {
+
+class flag_provider_interface {
+public:
+    virtual ~flag_provider_interface() = default;
+
+    virtual bool disabled_rw_exported() = 0;
+
+    virtual bool enabled_fixed_ro_exported() = 0;
+
+    virtual bool enabled_ro_exported() = 0;
+};
+
+extern std::unique_ptr<flag_provider_interface> provider_;
+
+inline bool disabled_rw_exported() {
+    return provider_->disabled_rw_exported();
+}
+
+inline bool enabled_fixed_ro_exported() {
+    return provider_->enabled_fixed_ro_exported();
+}
+
+inline bool enabled_ro_exported() {
+    return provider_->enabled_ro_exported();
+}
+
+}
+
+extern "C" {
+#endif // __cplusplus
+
+bool com_android_aconfig_test_disabled_rw_exported();
+
+bool com_android_aconfig_test_enabled_fixed_ro_exported();
+
+bool com_android_aconfig_test_enabled_ro_exported();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+"#;
+
     const PROD_SOURCE_FILE_EXPECTED: &str = r#"
 #include "com_android_aconfig_test.h"
 #include <server_configurable_flags/get_flags.h>
@@ -450,6 +532,10 @@
                 return COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO;
             }
 
+            virtual bool enabled_fixed_ro_exported() override {
+                return COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO_EXPORTED;
+            }
+
             virtual bool enabled_ro() override {
                 return true;
             }
@@ -496,6 +582,10 @@
     return COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO;
 }
 
+bool com_android_aconfig_test_enabled_fixed_ro_exported() {
+    return COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO_EXPORTED;
+}
+
 bool com_android_aconfig_test_enabled_ro() {
     return true;
 }
@@ -601,6 +691,19 @@
                 overrides_["enabled_fixed_ro"] = val;
             }
 
+            virtual bool enabled_fixed_ro_exported() override {
+                auto it = overrides_.find("enabled_fixed_ro_exported");
+                  if (it != overrides_.end()) {
+                      return it->second;
+                } else {
+                  return true;
+                }
+            }
+
+            virtual void enabled_fixed_ro_exported(bool val) override {
+                overrides_["enabled_fixed_ro_exported"] = val;
+            }
+
             virtual bool enabled_ro() override {
                 auto it = overrides_.find("enabled_ro");
                   if (it != overrides_.end()) {
@@ -697,6 +800,13 @@
     com::android::aconfig::test::enabled_fixed_ro(val);
 }
 
+bool com_android_aconfig_test_enabled_fixed_ro_exported() {
+    return com::android::aconfig::test::enabled_fixed_ro_exported();
+}
+
+void set_com_android_aconfig_test_enabled_fixed_ro_exported(bool val) {
+    com::android::aconfig::test::enabled_fixed_ro_exported(val);
+}
 
 bool com_android_aconfig_test_enabled_ro() {
     return com::android::aconfig::test::enabled_ro();
@@ -733,6 +843,68 @@
 
 "#;
 
+    const EXPORTED_SOURCE_FILE_EXPECTED: &str = r#"
+#include "com_android_aconfig_test.h"
+#include <server_configurable_flags/get_flags.h>
+#include <vector>
+
+namespace com::android::aconfig::test {
+
+    class flag_provider : public flag_provider_interface {
+        public:
+            virtual bool disabled_rw_exported() override {
+                if (cache_[0] == -1) {
+                    cache_[0] = server_configurable_flags::GetServerConfigurableFlag(
+                        "aconfig_flags.aconfig_test",
+                        "com.android.aconfig.test.disabled_rw_exported",
+                        "false") == "true";
+                }
+                return cache_[0];
+            }
+
+            virtual bool enabled_fixed_ro_exported() override {
+                if (cache_[1] == -1) {
+                    cache_[1] = server_configurable_flags::GetServerConfigurableFlag(
+                        "aconfig_flags.aconfig_test",
+                        "com.android.aconfig.test.enabled_fixed_ro_exported",
+                        "false") == "true";
+                }
+                return cache_[1];
+            }
+
+            virtual bool enabled_ro_exported() override {
+                if (cache_[2] == -1) {
+                    cache_[2] = server_configurable_flags::GetServerConfigurableFlag(
+                        "aconfig_flags.aconfig_test",
+                        "com.android.aconfig.test.enabled_ro_exported",
+                        "false") == "true";
+                }
+                return cache_[2];
+            }
+
+    private:
+        std::vector<int8_t> cache_ = std::vector<int8_t>(3, -1);
+    };
+
+    std::unique_ptr<flag_provider_interface> provider_ =
+        std::make_unique<flag_provider>();
+}
+
+bool com_android_aconfig_test_disabled_rw_exported() {
+    return com::android::aconfig::test::disabled_rw_exported();
+}
+
+bool com_android_aconfig_test_enabled_fixed_ro_exported() {
+    return com::android::aconfig::test::enabled_fixed_ro_exported();
+}
+
+bool com_android_aconfig_test_enabled_ro_exported() {
+    return com::android::aconfig::test::enabled_ro_exported();
+}
+
+
+"#;
+
     const READ_ONLY_EXPORTED_PROD_HEADER_EXPECTED: &str = r#"
 #pragma once
 
@@ -854,12 +1026,11 @@
         expected_header: &str,
         expected_src: &str,
     ) {
-        let generated = generate_cpp_code(
-            crate::test::TEST_PACKAGE,
-            parsed_flags.parsed_flag.into_iter(),
-            mode,
-        )
-        .unwrap();
+        let modified_parsed_flags =
+            crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode);
+        let generated =
+            generate_cpp_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode)
+                .unwrap();
         let mut generated_files_map = HashMap::new();
         for file in generated {
             generated_files_map.insert(
@@ -912,6 +1083,17 @@
     }
 
     #[test]
+    fn test_generate_cpp_code_for_exported() {
+        let parsed_flags = crate::test::parse_test_flags();
+        test_generate_cpp_code(
+            parsed_flags,
+            CodegenMode::Exported,
+            EXPORTED_EXPORTED_HEADER_EXPECTED,
+            EXPORTED_SOURCE_FILE_EXPECTED,
+        );
+    }
+
+    #[test]
     fn test_generate_cpp_code_for_read_only_prod() {
         let parsed_flags = crate::test::parse_read_only_test_flags();
         test_generate_cpp_code(
diff --git a/tools/aconfig/src/codegen/java.rs b/tools/aconfig/src/codegen/java.rs
index 1d5dabf..f874b34 100644
--- a/tools/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/src/codegen/java.rs
@@ -202,6 +202,9 @@
         boolean enabledFixedRo();
         @com.android.aconfig.annotations.AssumeTrueForR8
         @UnsupportedAppUsage
+        boolean enabledFixedRoExported();
+        @com.android.aconfig.annotations.AssumeTrueForR8
+        @UnsupportedAppUsage
         boolean enabledRo();
         @com.android.aconfig.annotations.AssumeTrueForR8
         @UnsupportedAppUsage
@@ -228,6 +231,8 @@
         /** @hide */
         public static final String FLAG_ENABLED_FIXED_RO = "com.android.aconfig.test.enabled_fixed_ro";
         /** @hide */
+        public static final String FLAG_ENABLED_FIXED_RO_EXPORTED = "com.android.aconfig.test.enabled_fixed_ro_exported";
+        /** @hide */
         public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro";
         /** @hide */
         public static final String FLAG_ENABLED_RO_EXPORTED = "com.android.aconfig.test.enabled_ro_exported";
@@ -258,6 +263,11 @@
         }
         @com.android.aconfig.annotations.AssumeTrueForR8
         @UnsupportedAppUsage
+        public static boolean enabledFixedRoExported() {
+            return FEATURE_FLAGS.enabledFixedRoExported();
+        }
+        @com.android.aconfig.annotations.AssumeTrueForR8
+        @UnsupportedAppUsage
         public static boolean enabledRo() {
             return FEATURE_FLAGS.enabledRo();
         }
@@ -310,6 +320,11 @@
         }
         @Override
         @UnsupportedAppUsage
+        public boolean enabledFixedRoExported() {
+            return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED);
+        }
+        @Override
+        @UnsupportedAppUsage
         public boolean enabledRo() {
             return getValue(Flags.FLAG_ENABLED_RO);
         }
@@ -348,6 +363,7 @@
                 Map.entry(Flags.FLAG_DISABLED_RW_EXPORTED, false),
                 Map.entry(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false),
                 Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false),
+                Map.entry(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, false),
                 Map.entry(Flags.FLAG_ENABLED_RO, false),
                 Map.entry(Flags.FLAG_ENABLED_RO_EXPORTED, false),
                 Map.entry(Flags.FLAG_ENABLED_RW, false)
@@ -463,6 +479,11 @@
             }
             @Override
             @UnsupportedAppUsage
+            public boolean enabledFixedRoExported() {
+                return true;
+            }
+            @Override
+            @UnsupportedAppUsage
             public boolean enabledRo() {
                 return true;
             }
@@ -528,6 +549,8 @@
             /** @hide */
             public static final String FLAG_DISABLED_RW_EXPORTED = "com.android.aconfig.test.disabled_rw_exported";
             /** @hide */
+            public static final String FLAG_ENABLED_FIXED_RO_EXPORTED = "com.android.aconfig.test.enabled_fixed_ro_exported";
+            /** @hide */
             public static final String FLAG_ENABLED_RO_EXPORTED = "com.android.aconfig.test.enabled_ro_exported";
 
             @UnsupportedAppUsage
@@ -535,6 +558,10 @@
                 return FEATURE_FLAGS.disabledRwExported();
             }
             @UnsupportedAppUsage
+            public static boolean enabledFixedRoExported() {
+                return FEATURE_FLAGS.enabledFixedRoExported();
+            }
+            @UnsupportedAppUsage
             public static boolean enabledRoExported() {
                 return FEATURE_FLAGS.enabledRoExported();
             }
@@ -551,6 +578,8 @@
             @UnsupportedAppUsage
             boolean disabledRwExported();
             @UnsupportedAppUsage
+            boolean enabledFixedRoExported();
+            @UnsupportedAppUsage
             boolean enabledRoExported();
         }
         "#;
@@ -566,6 +595,7 @@
             private static boolean aconfig_test_is_cached = false;
             private static boolean other_namespace_is_cached = false;
             private static boolean disabledRwExported = false;
+            private static boolean enabledFixedRoExported = false;
             private static boolean enabledRoExported = false;
 
 
@@ -574,6 +604,8 @@
                     Properties properties = DeviceConfig.getProperties("aconfig_test");
                     disabledRwExported =
                         properties.getBoolean("com.android.aconfig.test.disabled_rw_exported", false);
+                    enabledFixedRoExported =
+                        properties.getBoolean("com.android.aconfig.test.enabled_fixed_ro_exported", false);
                     enabledRoExported =
                         properties.getBoolean("com.android.aconfig.test.enabled_ro_exported", false);
                 } catch (NullPointerException e) {
@@ -616,6 +648,15 @@
 
             @Override
             @UnsupportedAppUsage
+            public boolean enabledFixedRoExported() {
+                if (!aconfig_test_is_cached) {
+                    load_overrides_aconfig_test();
+                }
+                return enabledFixedRoExported;
+            }
+
+            @Override
+            @UnsupportedAppUsage
             public boolean enabledRoExported() {
                 if (!aconfig_test_is_cached) {
                     load_overrides_aconfig_test();
@@ -642,6 +683,11 @@
             }
             @Override
             @UnsupportedAppUsage
+            public boolean enabledFixedRoExported() {
+                return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED);
+            }
+            @Override
+            @UnsupportedAppUsage
             public boolean enabledRoExported() {
                 return getValue(Flags.FLAG_ENABLED_RO_EXPORTED);
             }
@@ -666,6 +712,7 @@
             private Map<String, Boolean> mFlagMap = new HashMap<>(
                 Map.ofEntries(
                     Map.entry(Flags.FLAG_DISABLED_RW_EXPORTED, false),
+                    Map.entry(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, false),
                     Map.entry(Flags.FLAG_ENABLED_RO_EXPORTED, false)
                 )
             );
@@ -759,6 +806,12 @@
             }
             @Override
             @UnsupportedAppUsage
+            public boolean enabledFixedRoExported() {
+                throw new UnsupportedOperationException(
+                    "Method is not implemented.");
+            }
+            @Override
+            @UnsupportedAppUsage
             public boolean enabledRo() {
                 throw new UnsupportedOperationException(
                     "Method is not implemented.");
diff --git a/tools/aconfig/src/codegen/rust.rs b/tools/aconfig/src/codegen/rust.rs
index 7aafddb..7c49c50 100644
--- a/tools/aconfig/src/codegen/rust.rs
+++ b/tools/aconfig/src/codegen/rust.rs
@@ -153,6 +153,11 @@
         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
@@ -202,6 +207,12 @@
     true
 }
 
+/// query flag enabled_fixed_ro_exported
+#[inline(always)]
+pub fn enabled_fixed_ro_exported() -> bool {
+    true
+}
+
 /// query flag enabled_ro
 #[inline(always)]
 pub fn enabled_ro() -> bool {
@@ -302,6 +313,18 @@
         self.overrides.insert("enabled_fixed_ro", val);
     }
 
+    /// query flag enabled_fixed_ro_exported
+    pub fn enabled_fixed_ro_exported(&self) -> bool {
+        self.overrides.get("enabled_fixed_ro_exported").copied().unwrap_or(
+            true
+        )
+    }
+
+    /// set flag enabled_fixed_ro_exported
+    pub fn set_enabled_fixed_ro_exported(&mut self, val: bool) {
+        self.overrides.insert("enabled_fixed_ro_exported", val);
+    }
+
     /// query flag enabled_ro
     pub fn enabled_ro(&self) -> bool {
         self.overrides.get("enabled_ro").copied().unwrap_or(
@@ -412,6 +435,18 @@
     PROVIDER.lock().unwrap().set_enabled_fixed_ro(val);
 }
 
+/// query flag enabled_fixed_ro_exported
+#[inline(always)]
+pub fn enabled_fixed_ro_exported() -> bool {
+    PROVIDER.lock().unwrap().enabled_fixed_ro_exported()
+}
+
+/// set flag enabled_fixed_ro_exported
+#[inline(always)]
+pub fn set_enabled_fixed_ro_exported(val: bool) {
+    PROVIDER.lock().unwrap().set_enabled_fixed_ro_exported(val);
+}
+
 /// query flag enabled_ro
 #[inline(always)]
 pub fn enabled_ro() -> bool {
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index 87905fd..38c9fde 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -207,12 +207,12 @@
 
 pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
     let parsed_flags = input.try_parse_flags()?;
-    let filtered_parsed_flags = filter_parsed_flags(parsed_flags, codegen_mode);
-    let Some(package) = find_unique_package(&filtered_parsed_flags) else {
+    let modified_parsed_flags = modify_parsed_flags_based_on_mode(parsed_flags, codegen_mode);
+    let Some(package) = find_unique_package(&modified_parsed_flags) else {
         bail!("no parsed flags, or the parsed flags use different packages");
     };
     let package = package.to_string();
-    generate_cpp_code(&package, filtered_parsed_flags.into_iter(), codegen_mode)
+    generate_cpp_code(&package, modified_parsed_flags.into_iter(), codegen_mode)
 }
 
 pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
@@ -335,6 +335,30 @@
     }
 }
 
+pub fn modify_parsed_flags_based_on_mode(
+    parsed_flags: ProtoParsedFlags,
+    codegen_mode: CodegenMode,
+) -> Vec<ProtoParsedFlag> {
+    fn exported_mode_flag_modifier(mut parsed_flag: ProtoParsedFlag) -> ProtoParsedFlag {
+        parsed_flag.set_state(ProtoFlagState::DISABLED);
+        parsed_flag.set_permission(ProtoFlagPermission::READ_WRITE);
+        parsed_flag.set_is_fixed_read_only(false);
+        parsed_flag
+    }
+
+    match codegen_mode {
+        CodegenMode::Exported => parsed_flags
+            .parsed_flag
+            .into_iter()
+            .filter(|pf| pf.is_exported())
+            .map(exported_mode_flag_modifier)
+            .collect(),
+        CodegenMode::Production | CodegenMode::Test => {
+            parsed_flags.parsed_flag.into_iter().collect()
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -366,9 +390,9 @@
         assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
         assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
 
-        assert_eq!(8, parsed_flags.parsed_flag.len());
+        assert_eq!(9, parsed_flags.parsed_flag.len());
         for pf in parsed_flags.parsed_flag.iter() {
-            if pf.name() == "enabled_fixed_ro" {
+            if pf.name().starts_with("enabled_fixed_ro") {
                 continue;
             }
             let first = pf.trace.first().unwrap();
@@ -597,7 +621,13 @@
         let bytes =
             dump_parsed_flags(vec![input, input2], DumpFormat::Textproto, &[], true).unwrap();
         let text = std::str::from_utf8(&bytes).unwrap();
-        assert_eq!(crate::test::TEST_FLAGS_TEXTPROTO.trim(), text.trim());
+        assert_eq!(
+            None,
+            crate::test::first_significant_code_diff(
+                crate::test::TEST_FLAGS_TEXTPROTO.trim(),
+                text.trim()
+            )
+        );
     }
 
     #[test]
@@ -607,14 +637,14 @@
 
         let filtered_parsed_flags =
             filter_parsed_flags(parsed_flags.clone(), CodegenMode::Exported);
-        assert_eq!(2, filtered_parsed_flags.len());
+        assert_eq!(3, filtered_parsed_flags.len());
 
         let filtered_parsed_flags =
             filter_parsed_flags(parsed_flags.clone(), CodegenMode::Production);
-        assert_eq!(8, filtered_parsed_flags.len());
+        assert_eq!(9, filtered_parsed_flags.len());
 
         let filtered_parsed_flags = filter_parsed_flags(parsed_flags.clone(), CodegenMode::Test);
-        assert_eq!(8, filtered_parsed_flags.len());
+        assert_eq!(9, filtered_parsed_flags.len());
     }
 
     fn parse_test_flags_as_input() -> Input {
@@ -624,4 +654,28 @@
         let reader = Box::new(cursor);
         Input { source: "test.data".to_string(), reader }
     }
+
+    #[test]
+    fn test_modify_parsed_flags_based_on_mode_prod() {
+        let parsed_flags = crate::test::parse_test_flags();
+        let p_parsed_flags =
+            modify_parsed_flags_based_on_mode(parsed_flags.clone(), CodegenMode::Production);
+        assert_eq!(parsed_flags.parsed_flag.len(), p_parsed_flags.len());
+        for (i, item) in p_parsed_flags.iter().enumerate() {
+            assert!(parsed_flags.parsed_flag[i].eq(item));
+        }
+    }
+
+    #[test]
+    fn test_modify_parsed_flags_based_on_mode_exported() {
+        let parsed_flags = crate::test::parse_test_flags();
+        let p_parsed_flags = modify_parsed_flags_based_on_mode(parsed_flags, CodegenMode::Exported);
+        assert_eq!(3, p_parsed_flags.len());
+        for flag in p_parsed_flags.iter() {
+            assert_eq!(ProtoFlagState::DISABLED, flag.state());
+            assert_eq!(ProtoFlagPermission::READ_WRITE, flag.permission());
+            assert!(!flag.is_fixed_read_only());
+            assert!(flag.is_exported());
+        }
+    }
 }
diff --git a/tools/aconfig/src/dump.rs b/tools/aconfig/src/dump.rs
index f2b3687..5ee751e 100644
--- a/tools/aconfig/src/dump.rs
+++ b/tools/aconfig/src/dump.rs
@@ -341,6 +341,7 @@
                 "com.android.aconfig.test.disabled_rw_exported",
                 "com.android.aconfig.test.disabled_rw_in_other_namespace",
                 "com.android.aconfig.test.enabled_fixed_ro",
+                "com.android.aconfig.test.enabled_fixed_ro_exported",
                 "com.android.aconfig.test.enabled_ro",
                 "com.android.aconfig.test.enabled_ro_exported",
                 "com.android.aconfig.test.enabled_rw",
@@ -360,6 +361,7 @@
             "state:ENABLED",
             &[
                 "com.android.aconfig.test.enabled_fixed_ro",
+                "com.android.aconfig.test.enabled_fixed_ro_exported",
                 "com.android.aconfig.test.enabled_ro",
                 "com.android.aconfig.test.enabled_ro_exported",
                 "com.android.aconfig.test.enabled_rw",
@@ -370,6 +372,7 @@
             &[
                 "com.android.aconfig.test.disabled_ro",
                 "com.android.aconfig.test.enabled_fixed_ro",
+                "com.android.aconfig.test.enabled_fixed_ro_exported",
                 "com.android.aconfig.test.enabled_ro",
                 "com.android.aconfig.test.enabled_ro_exported",
             ]
@@ -377,12 +380,16 @@
         // trace: not supported yet
         assert_create_filter_predicate!(
             "is_fixed_read_only:true",
-            &["com.android.aconfig.test.enabled_fixed_ro"]
+            &[
+                "com.android.aconfig.test.enabled_fixed_ro",
+                "com.android.aconfig.test.enabled_fixed_ro_exported",
+            ]
         );
         assert_create_filter_predicate!(
             "is_exported:true",
             &[
                 "com.android.aconfig.test.disabled_rw_exported",
+                "com.android.aconfig.test.enabled_fixed_ro_exported",
                 "com.android.aconfig.test.enabled_ro_exported",
             ]
         );
@@ -394,6 +401,7 @@
                 "com.android.aconfig.test.disabled_rw_exported",
                 "com.android.aconfig.test.disabled_rw_in_other_namespace",
                 "com.android.aconfig.test.enabled_fixed_ro",
+                "com.android.aconfig.test.enabled_fixed_ro_exported",
                 "com.android.aconfig.test.enabled_ro",
                 "com.android.aconfig.test.enabled_ro_exported",
                 "com.android.aconfig.test.enabled_rw",
@@ -406,6 +414,7 @@
             "permission:READ_ONLY+state:ENABLED",
             &[
                 "com.android.aconfig.test.enabled_fixed_ro",
+                "com.android.aconfig.test.enabled_fixed_ro_exported",
                 "com.android.aconfig.test.enabled_ro",
                 "com.android.aconfig.test.enabled_ro_exported",
             ]
diff --git a/tools/aconfig/src/test.rs b/tools/aconfig/src/test.rs
index 309cb28..cbb95b8 100644
--- a/tools/aconfig/src/test.rs
+++ b/tools/aconfig/src/test.rs
@@ -145,6 +145,31 @@
 }
 parsed_flag {
   package: "com.android.aconfig.test"
+  name: "enabled_fixed_ro_exported"
+  namespace: "aconfig_test"
+  description: "This flag is fixed ENABLED + READ_ONLY and exported"
+  bug: "111"
+  state: ENABLED
+  permission: READ_ONLY
+  trace {
+    source: "tests/test.aconfig"
+    state: DISABLED
+    permission: READ_ONLY
+  }
+  trace {
+    source: "tests/first.values"
+    state: ENABLED
+    permission: READ_ONLY
+  }
+  is_fixed_read_only: true
+  is_exported: true
+  container: "system"
+  metadata {
+    purpose: PURPOSE_UNSPECIFIED
+  }
+}
+parsed_flag {
+  package: "com.android.aconfig.test"
   name: "enabled_ro"
   namespace: "aconfig_test"
   description: "This flag is ENABLED + READ_ONLY"
diff --git a/tools/aconfig/templates/cpp_exported_header.template b/tools/aconfig/templates/cpp_exported_header.template
index 377295d..8db9ec4 100644
--- a/tools/aconfig/templates/cpp_exported_header.template
+++ b/tools/aconfig/templates/cpp_exported_header.template
@@ -1,6 +1,6 @@
 #pragma once
 
-{{ if not for_test- }}
+{{ if not is_test_mode- }}
 {{ if has_fixed_read_only- }}
 #ifndef {package_macro}
 #define {package_macro}(FLAG) {package_macro}_##FLAG
@@ -29,12 +29,12 @@
     {{ for item in class_elements}}
     virtual bool {item.flag_name}() = 0;
 
-    {{ if for_test- }}
+    {{ if is_test_mode }}
     virtual void {item.flag_name}(bool val) = 0;
     {{ -endif }}
     {{ -endfor }}
 
-    {{ if for_test }}
+    {{ if is_test_mode }}
     virtual void reset_flags() \{}
     {{ -endif }}
 };
@@ -43,9 +43,10 @@
 
 {{ for item in class_elements}}
 inline bool {item.flag_name}() \{
-    {{ if for_test- }}
+    {{ if is_test_mode }}
     return provider_->{item.flag_name}();
     {{ -else- }}
+    {{ if is_prod_mode- }}
     {{ if item.readwrite- }}
     return provider_->{item.flag_name}();
     {{ -else- }}
@@ -55,17 +56,22 @@
     return {item.default_value};
     {{ -endif }}
     {{ -endif }}
+    {{ -else- }}
+    {{ if is_exported_mode- }}
+    return provider_->{item.flag_name}();
+    {{ -endif }}
+    {{ -endif }}
     {{ -endif }}
 }
 
-{{ if for_test- }}
+{{ if is_test_mode }}
 inline void {item.flag_name}(bool val) \{
     provider_->{item.flag_name}(val);
 }
 {{ -endif }}
 {{ -endfor }}
 
-{{ if for_test- }}
+{{ if is_test_mode }}
 inline void reset_flags() \{
     return provider_->reset_flags();
 }
@@ -79,12 +85,12 @@
 {{ for item in class_elements }}
 bool {header}_{item.flag_name}();
 
-{{ if for_test- }}
+{{ if is_test_mode }}
 void set_{header}_{item.flag_name}(bool val);
 {{ -endif }}
 {{ -endfor }}
 
-{{ if for_test- }}
+{{ if is_test_mode }}
 void {header}_reset_flags();
 {{ -endif }}
 
diff --git a/tools/aconfig/templates/cpp_source_file.template b/tools/aconfig/templates/cpp_source_file.template
index fbbfedc..a10d7cb 100644
--- a/tools/aconfig/templates/cpp_source_file.template
+++ b/tools/aconfig/templates/cpp_source_file.template
@@ -2,9 +2,8 @@
 
 {{ if readwrite- }}
 #include <server_configurable_flags/get_flags.h>
-{{ -endif }}
-
-{{ if for_test- }}
+{{ endif }}
+{{ if is_test_mode }}
 #include <unordered_map>
 #include <string>
 {{ -else- }}
@@ -15,7 +14,7 @@
 
 namespace {cpp_namespace} \{
 
-{{ if for_test- }}
+{{ if is_test_mode }}
     class flag_provider : public flag_provider_interface \{
     private:
         std::unordered_map<std::string, bool> overrides_;
@@ -59,6 +58,7 @@
 
         {{ for item in class_elements }}
         virtual bool {item.flag_name}() override \{
+            {{ if is_prod_mode- }}
             {{ if item.readwrite- }}
             if (cache_[{item.readwrite_idx}] == -1) \{
                 cache_[{item.readwrite_idx}] = server_configurable_flags::GetServerConfigurableFlag(
@@ -74,6 +74,17 @@
             return {item.default_value};
             {{ -endif }}
             {{ -endif }}
+            {{ -else- }}
+            {{ if is_exported_mode-}}
+            if (cache_[{item.readwrite_idx}] == -1) \{
+                cache_[{item.readwrite_idx}] = server_configurable_flags::GetServerConfigurableFlag(
+                    "aconfig_flags.{item.device_config_namespace}",
+                    "{item.device_config_flag}",
+                    "false") == "true";
+            }
+            return cache_[{item.readwrite_idx}];
+            {{ -endif }}
+            {{ -endif }}
         }
         {{ endfor }}
     {{ if readwrite- }}
@@ -91,9 +102,10 @@
 
 {{ for item in class_elements }}
 bool {header}_{item.flag_name}() \{
-    {{ if for_test- }}
+    {{ if is_test_mode }}
     return {cpp_namespace}::{item.flag_name}();
     {{ -else- }}
+    {{ if is_prod_mode- }}
     {{ if item.readwrite- }}
     return {cpp_namespace}::{item.flag_name}();
     {{ -else- }}
@@ -103,17 +115,22 @@
     return {item.default_value};
     {{ -endif }}
     {{ -endif }}
+    {{ -else- }}
+    {{ if is_exported_mode- }}
+    return {cpp_namespace}::{item.flag_name}();
+    {{ -endif }}
+    {{ -endif }}
     {{ -endif }}
 }
 
-{{ if for_test- }}
+{{ if is_test_mode }}
 void set_{header}_{item.flag_name}(bool val) \{
     {cpp_namespace}::{item.flag_name}(val);
 }
 {{ -endif }}
 {{ endfor-}}
 
-{{ if for_test }}
+{{ if is_test_mode }}
 void {header}_reset_flags() \{
      {cpp_namespace}::reset_flags();
 }
diff --git a/tools/aconfig/tests/aconfig_exported_mode_test.cpp b/tools/aconfig/tests/aconfig_exported_mode_test.cpp
new file mode 100644
index 0000000..d6eab43
--- /dev/null
+++ b/tools/aconfig/tests/aconfig_exported_mode_test.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "com_android_aconfig_test.h"
+#include "gtest/gtest.h"
+
+using namespace com::android::aconfig::test;
+
+TEST(AconfigTest, TestDisabledRwExportedFlag) {
+  ASSERT_FALSE(com_android_aconfig_test_disabled_rw_exported());
+  ASSERT_FALSE(provider_->disabled_rw_exported());
+  ASSERT_FALSE(disabled_rw_exported());
+}
+
+TEST(AconfigTest, TestEnabledFixedRoExportedFlag) {
+  // TODO: change to assertTrue(enabledFixedRoExported()) when the build supports reading tests/*.values
+  ASSERT_FALSE(com_android_aconfig_test_enabled_fixed_ro_exported());
+  ASSERT_FALSE(provider_->enabled_fixed_ro_exported());
+  ASSERT_FALSE(enabled_fixed_ro_exported());
+}
+
+TEST(AconfigTest, TestEnabledRoExportedFlag) {
+  // TODO: change to assertTrue(enabledRoExported()) when the build supports reading tests/*.values
+  ASSERT_FALSE(com_android_aconfig_test_enabled_ro_exported());
+  ASSERT_FALSE(provider_->enabled_ro_exported());
+  ASSERT_FALSE(enabled_ro_exported());
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/tools/aconfig/tests/first.values b/tools/aconfig/tests/first.values
index 731ce84..2efb463 100644
--- a/tools/aconfig/tests/first.values
+++ b/tools/aconfig/tests/first.values
@@ -40,3 +40,9 @@
     state: DISABLED
     permission: READ_WRITE
 }
+flag_value {
+    package: "com.android.aconfig.test"
+    name: "enabled_fixed_ro_exported"
+    state: ENABLED
+    permission: READ_ONLY
+}
diff --git a/tools/aconfig/tests/test.aconfig b/tools/aconfig/tests/test.aconfig
index 014bced..c11508a 100644
--- a/tools/aconfig/tests/test.aconfig
+++ b/tools/aconfig/tests/test.aconfig
@@ -78,3 +78,12 @@
     bug: "111"
     is_exported: true
 }
+
+flag {
+    name: "enabled_fixed_ro_exported"
+    namespace: "aconfig_test"
+    description: "This flag is fixed ENABLED + READ_ONLY and exported"
+    bug: "111"
+    is_fixed_read_only: true
+    is_exported: true
+}
\ No newline at end of file