Loading tools/aconfig/aconfig/src/codegen/java.rs +60 −27 Original line number Diff line number Diff line Loading @@ -20,22 +20,24 @@ use std::collections::{BTreeMap, BTreeSet}; use std::path::PathBuf; use tinytemplate::TinyTemplate; use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag}; use crate::codegen; use crate::codegen::CodegenMode; use crate::commands::OutputFile; use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag}; use std::collections::HashMap; pub fn generate_java_code<I>( package: &str, parsed_flags_iter: I, codegen_mode: CodegenMode, flag_ids: HashMap<String, u16>, allow_instrumentation: bool, ) -> Result<Vec<OutputFile>> where I: Iterator<Item = ProtoParsedFlag>, { let flag_elements: Vec<FlagElement> = parsed_flags_iter.map(|pf| create_flag_element(package, &pf)).collect(); parsed_flags_iter.map(|pf| create_flag_element(package, &pf, flag_ids.clone())).collect(); let namespace_flags = gen_flags_by_namespace(&flag_elements); let properties_set: BTreeSet<String> = flag_elements.iter().map(|fe| format_property_name(&fe.device_config_namespace)).collect(); Loading @@ -43,6 +45,7 @@ where let library_exported = codegen_mode == CodegenMode::Exported; let runtime_lookup_required = flag_elements.iter().any(|elem| elem.is_read_write) || library_exported; let container = (flag_elements.first().expect("zero template flags").container).to_string(); let context = Context { flag_elements, Loading @@ -52,6 +55,8 @@ where properties_set, package_name: package.to_string(), library_exported, allow_instrumentation, container, }; let mut template = TinyTemplate::new(); template.add_template("Flags.java", include_str!("../../templates/Flags.java.template"))?; Loading Loading @@ -117,6 +122,8 @@ struct Context { pub properties_set: BTreeSet<String>, pub package_name: String, pub library_exported: bool, pub allow_instrumentation: bool, pub container: String, } #[derive(Serialize, Debug)] Loading @@ -127,23 +134,31 @@ struct NamespaceFlags { #[derive(Serialize, Clone, Debug)] struct FlagElement { pub container: String, pub default_value: bool, pub device_config_namespace: String, pub device_config_flag: String, pub flag_name_constant_suffix: String, pub flag_offset: u16, pub is_read_write: bool, pub method_name: String, pub properties: String, } fn create_flag_element(package: &str, pf: &ProtoParsedFlag) -> FlagElement { fn create_flag_element( package: &str, pf: &ProtoParsedFlag, flag_offsets: HashMap<String, u16>, ) -> FlagElement { let device_config_flag = codegen::create_device_config_ident(package, pf.name()) .expect("values checked at flag parse time"); FlagElement { container: pf.container().to_string(), default_value: pf.state() == ProtoFlagState::ENABLED, device_config_namespace: pf.namespace().to_string(), device_config_flag, flag_name_constant_suffix: pf.name().to_ascii_uppercase(), flag_offset: *flag_offsets.get(pf.name()).expect("didnt find package offset :("), is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE, method_name: format_java_method_name(pf.name()), properties: format_property_name(pf.namespace()), Loading Loading @@ -179,6 +194,7 @@ fn format_property_name(property_name: &str) -> String { #[cfg(test)] mod tests { use super::*; use crate::commands::assign_flag_ids; use std::collections::HashMap; const EXPECTED_FEATUREFLAGS_COMMON_CONTENT: &str = r#" Loading Loading @@ -477,8 +493,15 @@ mod tests { let mode = CodegenMode::Production; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); let generated_files = generate_java_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) let flag_ids = assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); let generated_files = generate_java_code( crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode, flag_ids, false, ) .unwrap(); let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string() + r#" Loading Loading @@ -647,8 +670,15 @@ mod tests { let mode = CodegenMode::Exported; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); let generated_files = generate_java_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) let flag_ids = assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); let generated_files = generate_java_code( crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode, flag_ids, false, ) .unwrap(); let expect_flags_content = r#" Loading Loading @@ -833,8 +863,15 @@ mod tests { let mode = CodegenMode::Test; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); let generated_files = generate_java_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) let flag_ids = assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); let generated_files = generate_java_code( crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode, flag_ids, false, ) .unwrap(); let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string() Loading @@ -850,69 +887,58 @@ mod tests { "#; let expect_featureflagsimpl_content = r#" package com.android.aconfig.test; // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; /** @hide */ public final class FeatureFlagsImpl implements FeatureFlags { @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean disabledRo() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean disabledRw() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean disabledRwExported() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean disabledRwInOtherNamespace() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledFixedRo() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledFixedRoExported() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledRo() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledRoExported() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledRw() { throw new UnsupportedOperationException( "Method is not implemented."); Loading Loading @@ -958,8 +984,15 @@ mod tests { let mode = CodegenMode::ForceReadOnly; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); let generated_files = generate_java_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) let flag_ids = assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); let generated_files = generate_java_code( crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode, flag_ids, false, ) .unwrap(); let expect_featureflags_content = r#" package com.android.aconfig.test; Loading tools/aconfig/aconfig/src/commands.rs +13 −3 Original line number Diff line number Diff line Loading @@ -191,15 +191,25 @@ pub fn parse_flags( Ok(output) } pub fn create_java_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> { pub fn create_java_lib( mut input: Input, codegen_mode: CodegenMode, allow_instrumentation: bool, ) -> Result<Vec<OutputFile>> { let parsed_flags = input.try_parse_flags()?; 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(); let _flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?; generate_java_code(&package, modified_parsed_flags.into_iter(), codegen_mode) let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?; generate_java_code( &package, modified_parsed_flags.into_iter(), codegen_mode, flag_ids, allow_instrumentation, ) } pub fn create_cpp_lib( Loading tools/aconfig/aconfig/src/main.rs +10 −2 Original line number Diff line number Diff line Loading @@ -72,6 +72,12 @@ fn cli() -> Command { .long("mode") .value_parser(EnumValueParser::<CodegenMode>::new()) .default_value("production"), ) .arg( Arg::new("allow-instrumentation") .long("allow-instrumentation") .value_parser(clap::value_parser!(bool)) .default_value("false"), ), ) .subcommand( Loading Loading @@ -237,8 +243,10 @@ fn main() -> Result<()> { Some(("create-java-lib", sub_matches)) => { let cache = open_single_file(sub_matches, "cache")?; let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?; let generated_files = commands::create_java_lib(cache, *mode).context("failed to create java lib")?; let allow_instrumentation = get_required_arg::<bool>(sub_matches, "allow-instrumentation")?; let generated_files = commands::create_java_lib(cache, *mode, *allow_instrumentation) .context("failed to create java lib")?; let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?); generated_files .iter() Loading tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template +45 −3 Original line number Diff line number Diff line package {package_name}; {{ -if not is_test_mode }} {{ if not library_exported- }} // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; {{ -endif }} {{ -if not is_test_mode }} {{ -if runtime_lookup_required }} import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; {{ endif }} {{ -if allow_instrumentation }} import android.aconfig.storage.StorageInternalReader; import android.util.Log; import java.io.File; {{ -endif }} {{ -endif }} /** @hide */ public final class FeatureFlagsImpl implements FeatureFlags \{ {{ -if runtime_lookup_required }} Loading @@ -20,14 +30,47 @@ public final class FeatureFlagsImpl implements FeatureFlags \{ private static boolean {flag.method_name} = {flag.default_value}; {{ -endif }} {{ -endfor }} {{ -if allow_instrumentation }} StorageInternalReader reader; boolean readFromNewStorage; private final static String TAG = "AconfigJavaCodegen"; public FeatureFlagsImpl() \{ File file = new File("/metadata/aconfig_test_missions/mission_1"); if (file.exists()) \{ readFromNewStorage = true; reader = new StorageInternalReader("{container}", "{package_name}"); } } {{ -endif }} {{ for namespace_with_flags in namespace_flags }} private void load_overrides_{namespace_with_flags.namespace}() \{ try \{ {{ -if allow_instrumentation }} boolean val; {{ -endif }} Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}"); {{ -for flag in namespace_with_flags.flags }} {{ -if flag.is_read_write }} {flag.method_name} = properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value}); {{ -if allow_instrumentation }} if (readFromNewStorage) \{ try \{ val = reader.getBooleanFlagValue({flag.flag_offset}); if (val == {flag.method_name}) \{ Log.i(TAG, "success: {flag.method_name} value matches"); } else \{ Log.i(TAG, String.format( "error: {flag.method_name} value mismatch, new storage value is %s, old storage value is %s", val, {flag.method_name})); } } catch (Exception e) \{ Log.e(TAG,"error: failed to read flag value of {flag.method_name}"); } } {{ -endif }} {{ -endif }} {{ -endfor }} } catch (NullPointerException e) \{ Loading Loading @@ -70,7 +113,6 @@ public final class FeatureFlagsImpl implements FeatureFlags \{ @Override {{ -if not library_exported }} @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage {{ -endif }} public boolean {flag.method_name}() \{ throw new UnsupportedOperationException( Loading Loading
tools/aconfig/aconfig/src/codegen/java.rs +60 −27 Original line number Diff line number Diff line Loading @@ -20,22 +20,24 @@ use std::collections::{BTreeMap, BTreeSet}; use std::path::PathBuf; use tinytemplate::TinyTemplate; use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag}; use crate::codegen; use crate::codegen::CodegenMode; use crate::commands::OutputFile; use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag}; use std::collections::HashMap; pub fn generate_java_code<I>( package: &str, parsed_flags_iter: I, codegen_mode: CodegenMode, flag_ids: HashMap<String, u16>, allow_instrumentation: bool, ) -> Result<Vec<OutputFile>> where I: Iterator<Item = ProtoParsedFlag>, { let flag_elements: Vec<FlagElement> = parsed_flags_iter.map(|pf| create_flag_element(package, &pf)).collect(); parsed_flags_iter.map(|pf| create_flag_element(package, &pf, flag_ids.clone())).collect(); let namespace_flags = gen_flags_by_namespace(&flag_elements); let properties_set: BTreeSet<String> = flag_elements.iter().map(|fe| format_property_name(&fe.device_config_namespace)).collect(); Loading @@ -43,6 +45,7 @@ where let library_exported = codegen_mode == CodegenMode::Exported; let runtime_lookup_required = flag_elements.iter().any(|elem| elem.is_read_write) || library_exported; let container = (flag_elements.first().expect("zero template flags").container).to_string(); let context = Context { flag_elements, Loading @@ -52,6 +55,8 @@ where properties_set, package_name: package.to_string(), library_exported, allow_instrumentation, container, }; let mut template = TinyTemplate::new(); template.add_template("Flags.java", include_str!("../../templates/Flags.java.template"))?; Loading Loading @@ -117,6 +122,8 @@ struct Context { pub properties_set: BTreeSet<String>, pub package_name: String, pub library_exported: bool, pub allow_instrumentation: bool, pub container: String, } #[derive(Serialize, Debug)] Loading @@ -127,23 +134,31 @@ struct NamespaceFlags { #[derive(Serialize, Clone, Debug)] struct FlagElement { pub container: String, pub default_value: bool, pub device_config_namespace: String, pub device_config_flag: String, pub flag_name_constant_suffix: String, pub flag_offset: u16, pub is_read_write: bool, pub method_name: String, pub properties: String, } fn create_flag_element(package: &str, pf: &ProtoParsedFlag) -> FlagElement { fn create_flag_element( package: &str, pf: &ProtoParsedFlag, flag_offsets: HashMap<String, u16>, ) -> FlagElement { let device_config_flag = codegen::create_device_config_ident(package, pf.name()) .expect("values checked at flag parse time"); FlagElement { container: pf.container().to_string(), default_value: pf.state() == ProtoFlagState::ENABLED, device_config_namespace: pf.namespace().to_string(), device_config_flag, flag_name_constant_suffix: pf.name().to_ascii_uppercase(), flag_offset: *flag_offsets.get(pf.name()).expect("didnt find package offset :("), is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE, method_name: format_java_method_name(pf.name()), properties: format_property_name(pf.namespace()), Loading Loading @@ -179,6 +194,7 @@ fn format_property_name(property_name: &str) -> String { #[cfg(test)] mod tests { use super::*; use crate::commands::assign_flag_ids; use std::collections::HashMap; const EXPECTED_FEATUREFLAGS_COMMON_CONTENT: &str = r#" Loading Loading @@ -477,8 +493,15 @@ mod tests { let mode = CodegenMode::Production; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); let generated_files = generate_java_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) let flag_ids = assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); let generated_files = generate_java_code( crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode, flag_ids, false, ) .unwrap(); let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string() + r#" Loading Loading @@ -647,8 +670,15 @@ mod tests { let mode = CodegenMode::Exported; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); let generated_files = generate_java_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) let flag_ids = assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); let generated_files = generate_java_code( crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode, flag_ids, false, ) .unwrap(); let expect_flags_content = r#" Loading Loading @@ -833,8 +863,15 @@ mod tests { let mode = CodegenMode::Test; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); let generated_files = generate_java_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) let flag_ids = assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); let generated_files = generate_java_code( crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode, flag_ids, false, ) .unwrap(); let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string() Loading @@ -850,69 +887,58 @@ mod tests { "#; let expect_featureflagsimpl_content = r#" package com.android.aconfig.test; // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; /** @hide */ public final class FeatureFlagsImpl implements FeatureFlags { @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean disabledRo() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean disabledRw() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean disabledRwExported() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean disabledRwInOtherNamespace() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledFixedRo() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledFixedRoExported() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledRo() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledRoExported() { throw new UnsupportedOperationException( "Method is not implemented."); } @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage public boolean enabledRw() { throw new UnsupportedOperationException( "Method is not implemented."); Loading Loading @@ -958,8 +984,15 @@ mod tests { let mode = CodegenMode::ForceReadOnly; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); let generated_files = generate_java_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) let flag_ids = assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); let generated_files = generate_java_code( crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode, flag_ids, false, ) .unwrap(); let expect_featureflags_content = r#" package com.android.aconfig.test; Loading
tools/aconfig/aconfig/src/commands.rs +13 −3 Original line number Diff line number Diff line Loading @@ -191,15 +191,25 @@ pub fn parse_flags( Ok(output) } pub fn create_java_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> { pub fn create_java_lib( mut input: Input, codegen_mode: CodegenMode, allow_instrumentation: bool, ) -> Result<Vec<OutputFile>> { let parsed_flags = input.try_parse_flags()?; 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(); let _flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?; generate_java_code(&package, modified_parsed_flags.into_iter(), codegen_mode) let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?; generate_java_code( &package, modified_parsed_flags.into_iter(), codegen_mode, flag_ids, allow_instrumentation, ) } pub fn create_cpp_lib( Loading
tools/aconfig/aconfig/src/main.rs +10 −2 Original line number Diff line number Diff line Loading @@ -72,6 +72,12 @@ fn cli() -> Command { .long("mode") .value_parser(EnumValueParser::<CodegenMode>::new()) .default_value("production"), ) .arg( Arg::new("allow-instrumentation") .long("allow-instrumentation") .value_parser(clap::value_parser!(bool)) .default_value("false"), ), ) .subcommand( Loading Loading @@ -237,8 +243,10 @@ fn main() -> Result<()> { Some(("create-java-lib", sub_matches)) => { let cache = open_single_file(sub_matches, "cache")?; let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?; let generated_files = commands::create_java_lib(cache, *mode).context("failed to create java lib")?; let allow_instrumentation = get_required_arg::<bool>(sub_matches, "allow-instrumentation")?; let generated_files = commands::create_java_lib(cache, *mode, *allow_instrumentation) .context("failed to create java lib")?; let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?); generated_files .iter() Loading
tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template +45 −3 Original line number Diff line number Diff line package {package_name}; {{ -if not is_test_mode }} {{ if not library_exported- }} // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; {{ -endif }} {{ -if not is_test_mode }} {{ -if runtime_lookup_required }} import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; {{ endif }} {{ -if allow_instrumentation }} import android.aconfig.storage.StorageInternalReader; import android.util.Log; import java.io.File; {{ -endif }} {{ -endif }} /** @hide */ public final class FeatureFlagsImpl implements FeatureFlags \{ {{ -if runtime_lookup_required }} Loading @@ -20,14 +30,47 @@ public final class FeatureFlagsImpl implements FeatureFlags \{ private static boolean {flag.method_name} = {flag.default_value}; {{ -endif }} {{ -endfor }} {{ -if allow_instrumentation }} StorageInternalReader reader; boolean readFromNewStorage; private final static String TAG = "AconfigJavaCodegen"; public FeatureFlagsImpl() \{ File file = new File("/metadata/aconfig_test_missions/mission_1"); if (file.exists()) \{ readFromNewStorage = true; reader = new StorageInternalReader("{container}", "{package_name}"); } } {{ -endif }} {{ for namespace_with_flags in namespace_flags }} private void load_overrides_{namespace_with_flags.namespace}() \{ try \{ {{ -if allow_instrumentation }} boolean val; {{ -endif }} Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}"); {{ -for flag in namespace_with_flags.flags }} {{ -if flag.is_read_write }} {flag.method_name} = properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value}); {{ -if allow_instrumentation }} if (readFromNewStorage) \{ try \{ val = reader.getBooleanFlagValue({flag.flag_offset}); if (val == {flag.method_name}) \{ Log.i(TAG, "success: {flag.method_name} value matches"); } else \{ Log.i(TAG, String.format( "error: {flag.method_name} value mismatch, new storage value is %s, old storage value is %s", val, {flag.method_name})); } } catch (Exception e) \{ Log.e(TAG,"error: failed to read flag value of {flag.method_name}"); } } {{ -endif }} {{ -endif }} {{ -endfor }} } catch (NullPointerException e) \{ Loading Loading @@ -70,7 +113,6 @@ public final class FeatureFlagsImpl implements FeatureFlags \{ @Override {{ -if not library_exported }} @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage {{ -endif }} public boolean {flag.method_name}() \{ throw new UnsupportedOperationException( Loading