Loading tools/aconfig/aconfig/src/codegen/java.rs +202 −128 Original line number Diff line number Diff line Loading @@ -63,19 +63,26 @@ where "FeatureFlags.java", include_str!("../../templates/FeatureFlags.java.template"), )?; template.add_template( "CustomFeatureFlags.java", include_str!("../../templates/CustomFeatureFlags.java.template"), )?; template.add_template( "FakeFeatureFlagsImpl.java", include_str!("../../templates/FakeFeatureFlagsImpl.java.template"), )?; let path: PathBuf = package.split('.').collect(); ["Flags.java", "FeatureFlags.java", "FeatureFlagsImpl.java", "FakeFeatureFlagsImpl.java"] [ "Flags.java", "FeatureFlags.java", "FeatureFlagsImpl.java", "CustomFeatureFlags.java", "FakeFeatureFlagsImpl.java", ] .iter() .map(|file| { Ok(OutputFile { contents: template.render(file, &context)?.into(), path: path.join(file), }) Ok(OutputFile { contents: template.render(file, &context)?.into(), path: path.join(file) }) }) .collect::<Result<Vec<OutputFile>>>() } Loading Loading @@ -292,76 +299,82 @@ mod tests { } "#; const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#" const EXPECTED_CUSTOMFEATUREFLAGS_CONTENT: &str = r#" package com.android.aconfig.test; // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.List; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl implements FeatureFlags { public FakeFeatureFlagsImpl() { resetAll(); public class CustomFeatureFlags implements FeatureFlags { private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { mGetValueImpl = getValueImpl; } @Override @UnsupportedAppUsage public boolean disabledRo() { return getValue(Flags.FLAG_DISABLED_RO); return getValue(Flags.FLAG_DISABLED_RO, FeatureFlags::disabledRo); } @Override @UnsupportedAppUsage public boolean disabledRw() { return getValue(Flags.FLAG_DISABLED_RW); return getValue(Flags.FLAG_DISABLED_RW, FeatureFlags::disabledRw); } @Override @UnsupportedAppUsage public boolean disabledRwExported() { return getValue(Flags.FLAG_DISABLED_RW_EXPORTED); return getValue(Flags.FLAG_DISABLED_RW_EXPORTED, FeatureFlags::disabledRwExported); } @Override @UnsupportedAppUsage public boolean disabledRwInOtherNamespace() { return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE); return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, FeatureFlags::disabledRwInOtherNamespace); } @Override @UnsupportedAppUsage public boolean enabledFixedRo() { return getValue(Flags.FLAG_ENABLED_FIXED_RO); return getValue(Flags.FLAG_ENABLED_FIXED_RO, FeatureFlags::enabledFixedRo); } @Override @UnsupportedAppUsage public boolean enabledFixedRoExported() { return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED); return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, FeatureFlags::enabledFixedRoExported); } @Override @UnsupportedAppUsage public boolean enabledRo() { return getValue(Flags.FLAG_ENABLED_RO); return getValue(Flags.FLAG_ENABLED_RO, FeatureFlags::enabledRo); } @Override @UnsupportedAppUsage public boolean enabledRoExported() { return getValue(Flags.FLAG_ENABLED_RO_EXPORTED); return getValue(Flags.FLAG_ENABLED_RO_EXPORTED, FeatureFlags::enabledRoExported); } @Override @UnsupportedAppUsage public boolean enabledRw() { return getValue(Flags.FLAG_ENABLED_RW); } public void setFlag(String flagName, boolean value) { if (!this.mFlagMap.containsKey(flagName)) { throw new IllegalArgumentException("no such flag " + flagName); } this.mFlagMap.put(flagName, value); } public void resetAll() { for (Map.Entry entry : mFlagMap.entrySet()) { entry.setValue(null); } return getValue(Flags.FLAG_ENABLED_RW, FeatureFlags::enabledRw); } public boolean isFlagReadOnlyOptimized(String flagName) { if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) { Loading @@ -369,30 +382,30 @@ mod tests { } return false; } @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() { return false; } private boolean getValue(String flagName) { Boolean value = this.mFlagMap.get(flagName); if (value == null) { throw new IllegalArgumentException(flagName + " is not set"); } return value; protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { return mGetValueImpl.test(flagName, getter); } private Map<String, Boolean> mFlagMap = new HashMap<>( Map.ofEntries( Map.entry(Flags.FLAG_DISABLED_RO, false), Map.entry(Flags.FLAG_DISABLED_RW, false), 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) ) public List<String> getFlagNames() { return Arrays.asList( Flags.FLAG_DISABLED_RO, Flags.FLAG_DISABLED_RW, Flags.FLAG_DISABLED_RW_EXPORTED, Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, Flags.FLAG_ENABLED_FIXED_RO, Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, Flags.FLAG_ENABLED_RO, Flags.FLAG_ENABLED_RO_EXPORTED, Flags.FLAG_ENABLED_RW ); } private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( Flags.FLAG_DISABLED_RO, Loading @@ -406,6 +419,49 @@ mod tests { } "#; const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#" package com.android.aconfig.test; import java.util.HashMap; import java.util.Map; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl extends CustomFeatureFlags { private Map<String, Boolean> mFlagMap = new HashMap<>(); public FakeFeatureFlagsImpl() { super(null); // Initialize the map with null values for (String flagName : getFlagNames()) { mFlagMap.put(flagName, null); } } @Override protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { Boolean value = this.mFlagMap.get(flagName); if (value == null) { throw new IllegalArgumentException(flagName + " is not set"); } return value; } public void setFlag(String flagName, boolean value) { if (!this.mFlagMap.containsKey(flagName)) { throw new IllegalArgumentException("no such flag " + flagName); } this.mFlagMap.put(flagName, value); } public void resetAll() { for (Map.Entry entry : mFlagMap.entrySet()) { entry.setValue(null); } } } "#; #[test] fn test_generate_java_code_production() { let parsed_flags = crate::test::parse_test_flags(); Loading Loading @@ -548,6 +604,10 @@ mod tests { ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT), ( "com/android/aconfig/test/CustomFeatureFlags.java", EXPECTED_CUSTOMFEATUREFLAGS_CONTENT, ), ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, Loading Loading @@ -671,55 +731,53 @@ mod tests { } }"#; let expect_fake_feature_flags_impl_content = r#" let expect_custom_feature_flags_content = r#" package com.android.aconfig.test; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.List; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl implements FeatureFlags { public FakeFeatureFlagsImpl() { resetAll(); public class CustomFeatureFlags implements FeatureFlags { private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { mGetValueImpl = getValueImpl; } @Override public boolean disabledRwExported() { return getValue(Flags.FLAG_DISABLED_RW_EXPORTED); return getValue(Flags.FLAG_DISABLED_RW_EXPORTED, FeatureFlags::disabledRwExported); } @Override public boolean enabledFixedRoExported() { return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED); return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, FeatureFlags::enabledFixedRoExported); } @Override public boolean enabledRoExported() { return getValue(Flags.FLAG_ENABLED_RO_EXPORTED); } public void setFlag(String flagName, boolean value) { if (!this.mFlagMap.containsKey(flagName)) { throw new IllegalArgumentException("no such flag " + flagName); } this.mFlagMap.put(flagName, value); } public void resetAll() { for (Map.Entry entry : mFlagMap.entrySet()) { entry.setValue(null); } } private boolean getValue(String flagName) { Boolean value = this.mFlagMap.get(flagName); if (value == null) { throw new IllegalArgumentException(flagName + " is not set"); return getValue(Flags.FLAG_ENABLED_RO_EXPORTED, FeatureFlags::enabledRoExported); } return value; protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { return mGetValueImpl.test(flagName, getter); } 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) ) public List<String> getFlagNames() { return Arrays.asList( Flags.FLAG_DISABLED_RW_EXPORTED, Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, Flags.FLAG_ENABLED_RO_EXPORTED ); } private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( "" Loading @@ -732,9 +790,13 @@ mod tests { ("com/android/aconfig/test/Flags.java", expect_flags_content), ("com/android/aconfig/test/FeatureFlags.java", expect_feature_flags_content), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_feature_flags_impl_content), ( "com/android/aconfig/test/CustomFeatureFlags.java", expect_custom_feature_flags_content, ), ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", expect_fake_feature_flags_impl_content, EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, ), ]); Loading Loading @@ -853,6 +915,10 @@ mod tests { ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ( "com/android/aconfig/test/CustomFeatureFlags.java", EXPECTED_CUSTOMFEATUREFLAGS_CONTENT, ), ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, Loading Loading @@ -1020,61 +1086,64 @@ mod tests { private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl(); }"#; let expect_fakefeatureflags_content = r#" let expect_customfeatureflags_content = r#" package com.android.aconfig.test; // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.List; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl implements FeatureFlags { public FakeFeatureFlagsImpl() { resetAll(); public class CustomFeatureFlags implements FeatureFlags { private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { mGetValueImpl = getValueImpl; } @Override @UnsupportedAppUsage public boolean disabledRo() { return getValue(Flags.FLAG_DISABLED_RO); return getValue(Flags.FLAG_DISABLED_RO, FeatureFlags::disabledRo); } @Override @UnsupportedAppUsage public boolean disabledRw() { return getValue(Flags.FLAG_DISABLED_RW); return getValue(Flags.FLAG_DISABLED_RW, FeatureFlags::disabledRw); } @Override @UnsupportedAppUsage public boolean disabledRwInOtherNamespace() { return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE); return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, FeatureFlags::disabledRwInOtherNamespace); } @Override @UnsupportedAppUsage public boolean enabledFixedRo() { return getValue(Flags.FLAG_ENABLED_FIXED_RO); return getValue(Flags.FLAG_ENABLED_FIXED_RO, FeatureFlags::enabledFixedRo); } @Override @UnsupportedAppUsage public boolean enabledRo() { return getValue(Flags.FLAG_ENABLED_RO); return getValue(Flags.FLAG_ENABLED_RO, FeatureFlags::enabledRo); } @Override @UnsupportedAppUsage public boolean enabledRw() { return getValue(Flags.FLAG_ENABLED_RW); } public void setFlag(String flagName, boolean value) { if (!this.mFlagMap.containsKey(flagName)) { throw new IllegalArgumentException("no such flag " + flagName); } this.mFlagMap.put(flagName, value); } public void resetAll() { for (Map.Entry entry : mFlagMap.entrySet()) { entry.setValue(null); } return getValue(Flags.FLAG_ENABLED_RW, FeatureFlags::enabledRw); } public boolean isFlagReadOnlyOptimized(String flagName) { if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) { Loading @@ -1082,27 +1151,27 @@ mod tests { } return false; } @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() { return false; } private boolean getValue(String flagName) { Boolean value = this.mFlagMap.get(flagName); if (value == null) { throw new IllegalArgumentException(flagName + " is not set"); } return value; protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { return mGetValueImpl.test(flagName, getter); } private Map<String, Boolean> mFlagMap = new HashMap<>( Map.ofEntries( Map.entry(Flags.FLAG_DISABLED_RO, false), Map.entry(Flags.FLAG_DISABLED_RW, false), Map.entry(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false), Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false), Map.entry(Flags.FLAG_ENABLED_RO, false), Map.entry(Flags.FLAG_ENABLED_RW, false) ) public List<String> getFlagNames() { return Arrays.asList( Flags.FLAG_DISABLED_RO, Flags.FLAG_DISABLED_RW, Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, Flags.FLAG_ENABLED_FIXED_RO, Flags.FLAG_ENABLED_RO, Flags.FLAG_ENABLED_RW ); } private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( Flags.FLAG_DISABLED_RO, Loading @@ -1116,11 +1185,16 @@ mod tests { ); } "#; let mut file_set = HashMap::from([ ("com/android/aconfig/test/Flags.java", expect_flags_content), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ("com/android/aconfig/test/FeatureFlags.java", expect_featureflags_content), ("com/android/aconfig/test/FakeFeatureFlagsImpl.java", expect_fakefeatureflags_content), ("com/android/aconfig/test/CustomFeatureFlags.java", expect_customfeatureflags_content), ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, ), ]); for file in generated_files { Loading tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template 0 → 100644 +70 −0 Original line number Diff line number Diff line package {package_name}; {{ if not library_exported- }} // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; {{ -endif }} import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Predicate; /** @hide */ public class CustomFeatureFlags implements FeatureFlags \{ private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) \{ mGetValueImpl = getValueImpl; } {{ -for item in flag_elements}} @Override {{ if not library_exported }} @UnsupportedAppUsage{{ -endif }} public boolean {item.method_name}() \{ return getValue(Flags.FLAG_{item.flag_name_constant_suffix}, FeatureFlags::{item.method_name}); } {{ endfor }} {{ -if not library_exported }} public boolean isFlagReadOnlyOptimized(String flagName) \{ if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) \{ return true; } return false; } @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() \{ return false; } {{ -endif }} protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) \{ return mGetValueImpl.test(flagName, getter); } public List<String> getFlagNames() \{ return Arrays.asList( {{ -for item in flag_elements }} Flags.FLAG_{item.flag_name_constant_suffix} {{ -if not @last }},{{ endif }} {{ -endfor }} ); } private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( {{ -for item in flag_elements }} {{ -if not item.is_read_write }} Flags.FLAG_{item.flag_name_constant_suffix}, {{ -endif }} {{ -endfor }} ""{# The empty string here is to resolve the ending comma #} ) ); } tools/aconfig/aconfig/templates/FakeFeatureFlagsImpl.java.template +17 −56 Original line number Diff line number Diff line package {package_name}; {{ if not library_exported- }} // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; {{ -endif }} import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl implements FeatureFlags \{ public class FakeFeatureFlagsImpl extends CustomFeatureFlags \{ private Map<String, Boolean> mFlagMap = new HashMap<>(); public FakeFeatureFlagsImpl() \{ resetAll(); super(null); // Initialize the map with null values for (String flagName : getFlagNames()) \{ mFlagMap.put(flagName, null); } } {{ for item in flag_elements}} @Override {{ if not library_exported }} @UnsupportedAppUsage{{ -endif }} public boolean {item.method_name}() \{ return getValue(Flags.FLAG_{item.flag_name_constant_suffix}); protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) \{ Boolean value = this.mFlagMap.get(flagName); if (value == null) \{ throw new IllegalArgumentException(flagName + " is not set"); } {{ endfor}} return value; } public void setFlag(String flagName, boolean value) \{ if (!this.mFlagMap.containsKey(flagName)) \{ throw new IllegalArgumentException("no such flag " + flagName); Loading @@ -34,46 +37,4 @@ public class FakeFeatureFlagsImpl implements FeatureFlags \{ entry.setValue(null); } } {{ if not library_exported }} public boolean isFlagReadOnlyOptimized(String flagName) \{ if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) \{ return true; } return false; } @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() \{ return false; } {{ -endif }} private boolean getValue(String flagName) \{ Boolean value = this.mFlagMap.get(flagName); if (value == null) \{ throw new IllegalArgumentException(flagName + " is not set"); } return value; } private Map<String, Boolean> mFlagMap = new HashMap<>( Map.ofEntries( {{ -for item in flag_elements }} Map.entry(Flags.FLAG_{item.flag_name_constant_suffix}, false) {{ -if not @last }},{{ endif }} {{ -endfor }} ) ); private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( {{ -for item in flag_elements }} {{ -if not item.is_read_write }} Flags.FLAG_{item.flag_name_constant_suffix}, {{ -endif }} {{ -endfor }} ""{# The empty string here is to resolve the ending comma #} ) ); } Loading
tools/aconfig/aconfig/src/codegen/java.rs +202 −128 Original line number Diff line number Diff line Loading @@ -63,19 +63,26 @@ where "FeatureFlags.java", include_str!("../../templates/FeatureFlags.java.template"), )?; template.add_template( "CustomFeatureFlags.java", include_str!("../../templates/CustomFeatureFlags.java.template"), )?; template.add_template( "FakeFeatureFlagsImpl.java", include_str!("../../templates/FakeFeatureFlagsImpl.java.template"), )?; let path: PathBuf = package.split('.').collect(); ["Flags.java", "FeatureFlags.java", "FeatureFlagsImpl.java", "FakeFeatureFlagsImpl.java"] [ "Flags.java", "FeatureFlags.java", "FeatureFlagsImpl.java", "CustomFeatureFlags.java", "FakeFeatureFlagsImpl.java", ] .iter() .map(|file| { Ok(OutputFile { contents: template.render(file, &context)?.into(), path: path.join(file), }) Ok(OutputFile { contents: template.render(file, &context)?.into(), path: path.join(file) }) }) .collect::<Result<Vec<OutputFile>>>() } Loading Loading @@ -292,76 +299,82 @@ mod tests { } "#; const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#" const EXPECTED_CUSTOMFEATUREFLAGS_CONTENT: &str = r#" package com.android.aconfig.test; // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.List; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl implements FeatureFlags { public FakeFeatureFlagsImpl() { resetAll(); public class CustomFeatureFlags implements FeatureFlags { private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { mGetValueImpl = getValueImpl; } @Override @UnsupportedAppUsage public boolean disabledRo() { return getValue(Flags.FLAG_DISABLED_RO); return getValue(Flags.FLAG_DISABLED_RO, FeatureFlags::disabledRo); } @Override @UnsupportedAppUsage public boolean disabledRw() { return getValue(Flags.FLAG_DISABLED_RW); return getValue(Flags.FLAG_DISABLED_RW, FeatureFlags::disabledRw); } @Override @UnsupportedAppUsage public boolean disabledRwExported() { return getValue(Flags.FLAG_DISABLED_RW_EXPORTED); return getValue(Flags.FLAG_DISABLED_RW_EXPORTED, FeatureFlags::disabledRwExported); } @Override @UnsupportedAppUsage public boolean disabledRwInOtherNamespace() { return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE); return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, FeatureFlags::disabledRwInOtherNamespace); } @Override @UnsupportedAppUsage public boolean enabledFixedRo() { return getValue(Flags.FLAG_ENABLED_FIXED_RO); return getValue(Flags.FLAG_ENABLED_FIXED_RO, FeatureFlags::enabledFixedRo); } @Override @UnsupportedAppUsage public boolean enabledFixedRoExported() { return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED); return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, FeatureFlags::enabledFixedRoExported); } @Override @UnsupportedAppUsage public boolean enabledRo() { return getValue(Flags.FLAG_ENABLED_RO); return getValue(Flags.FLAG_ENABLED_RO, FeatureFlags::enabledRo); } @Override @UnsupportedAppUsage public boolean enabledRoExported() { return getValue(Flags.FLAG_ENABLED_RO_EXPORTED); return getValue(Flags.FLAG_ENABLED_RO_EXPORTED, FeatureFlags::enabledRoExported); } @Override @UnsupportedAppUsage public boolean enabledRw() { return getValue(Flags.FLAG_ENABLED_RW); } public void setFlag(String flagName, boolean value) { if (!this.mFlagMap.containsKey(flagName)) { throw new IllegalArgumentException("no such flag " + flagName); } this.mFlagMap.put(flagName, value); } public void resetAll() { for (Map.Entry entry : mFlagMap.entrySet()) { entry.setValue(null); } return getValue(Flags.FLAG_ENABLED_RW, FeatureFlags::enabledRw); } public boolean isFlagReadOnlyOptimized(String flagName) { if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) { Loading @@ -369,30 +382,30 @@ mod tests { } return false; } @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() { return false; } private boolean getValue(String flagName) { Boolean value = this.mFlagMap.get(flagName); if (value == null) { throw new IllegalArgumentException(flagName + " is not set"); } return value; protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { return mGetValueImpl.test(flagName, getter); } private Map<String, Boolean> mFlagMap = new HashMap<>( Map.ofEntries( Map.entry(Flags.FLAG_DISABLED_RO, false), Map.entry(Flags.FLAG_DISABLED_RW, false), 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) ) public List<String> getFlagNames() { return Arrays.asList( Flags.FLAG_DISABLED_RO, Flags.FLAG_DISABLED_RW, Flags.FLAG_DISABLED_RW_EXPORTED, Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, Flags.FLAG_ENABLED_FIXED_RO, Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, Flags.FLAG_ENABLED_RO, Flags.FLAG_ENABLED_RO_EXPORTED, Flags.FLAG_ENABLED_RW ); } private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( Flags.FLAG_DISABLED_RO, Loading @@ -406,6 +419,49 @@ mod tests { } "#; const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#" package com.android.aconfig.test; import java.util.HashMap; import java.util.Map; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl extends CustomFeatureFlags { private Map<String, Boolean> mFlagMap = new HashMap<>(); public FakeFeatureFlagsImpl() { super(null); // Initialize the map with null values for (String flagName : getFlagNames()) { mFlagMap.put(flagName, null); } } @Override protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { Boolean value = this.mFlagMap.get(flagName); if (value == null) { throw new IllegalArgumentException(flagName + " is not set"); } return value; } public void setFlag(String flagName, boolean value) { if (!this.mFlagMap.containsKey(flagName)) { throw new IllegalArgumentException("no such flag " + flagName); } this.mFlagMap.put(flagName, value); } public void resetAll() { for (Map.Entry entry : mFlagMap.entrySet()) { entry.setValue(null); } } } "#; #[test] fn test_generate_java_code_production() { let parsed_flags = crate::test::parse_test_flags(); Loading Loading @@ -548,6 +604,10 @@ mod tests { ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT), ( "com/android/aconfig/test/CustomFeatureFlags.java", EXPECTED_CUSTOMFEATUREFLAGS_CONTENT, ), ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, Loading Loading @@ -671,55 +731,53 @@ mod tests { } }"#; let expect_fake_feature_flags_impl_content = r#" let expect_custom_feature_flags_content = r#" package com.android.aconfig.test; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.List; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl implements FeatureFlags { public FakeFeatureFlagsImpl() { resetAll(); public class CustomFeatureFlags implements FeatureFlags { private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { mGetValueImpl = getValueImpl; } @Override public boolean disabledRwExported() { return getValue(Flags.FLAG_DISABLED_RW_EXPORTED); return getValue(Flags.FLAG_DISABLED_RW_EXPORTED, FeatureFlags::disabledRwExported); } @Override public boolean enabledFixedRoExported() { return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED); return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, FeatureFlags::enabledFixedRoExported); } @Override public boolean enabledRoExported() { return getValue(Flags.FLAG_ENABLED_RO_EXPORTED); } public void setFlag(String flagName, boolean value) { if (!this.mFlagMap.containsKey(flagName)) { throw new IllegalArgumentException("no such flag " + flagName); } this.mFlagMap.put(flagName, value); } public void resetAll() { for (Map.Entry entry : mFlagMap.entrySet()) { entry.setValue(null); } } private boolean getValue(String flagName) { Boolean value = this.mFlagMap.get(flagName); if (value == null) { throw new IllegalArgumentException(flagName + " is not set"); return getValue(Flags.FLAG_ENABLED_RO_EXPORTED, FeatureFlags::enabledRoExported); } return value; protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { return mGetValueImpl.test(flagName, getter); } 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) ) public List<String> getFlagNames() { return Arrays.asList( Flags.FLAG_DISABLED_RW_EXPORTED, Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, Flags.FLAG_ENABLED_RO_EXPORTED ); } private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( "" Loading @@ -732,9 +790,13 @@ mod tests { ("com/android/aconfig/test/Flags.java", expect_flags_content), ("com/android/aconfig/test/FeatureFlags.java", expect_feature_flags_content), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_feature_flags_impl_content), ( "com/android/aconfig/test/CustomFeatureFlags.java", expect_custom_feature_flags_content, ), ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", expect_fake_feature_flags_impl_content, EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, ), ]); Loading Loading @@ -853,6 +915,10 @@ mod tests { ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ( "com/android/aconfig/test/CustomFeatureFlags.java", EXPECTED_CUSTOMFEATUREFLAGS_CONTENT, ), ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, Loading Loading @@ -1020,61 +1086,64 @@ mod tests { private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl(); }"#; let expect_fakefeatureflags_content = r#" let expect_customfeatureflags_content = r#" package com.android.aconfig.test; // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.List; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl implements FeatureFlags { public FakeFeatureFlagsImpl() { resetAll(); public class CustomFeatureFlags implements FeatureFlags { private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { mGetValueImpl = getValueImpl; } @Override @UnsupportedAppUsage public boolean disabledRo() { return getValue(Flags.FLAG_DISABLED_RO); return getValue(Flags.FLAG_DISABLED_RO, FeatureFlags::disabledRo); } @Override @UnsupportedAppUsage public boolean disabledRw() { return getValue(Flags.FLAG_DISABLED_RW); return getValue(Flags.FLAG_DISABLED_RW, FeatureFlags::disabledRw); } @Override @UnsupportedAppUsage public boolean disabledRwInOtherNamespace() { return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE); return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, FeatureFlags::disabledRwInOtherNamespace); } @Override @UnsupportedAppUsage public boolean enabledFixedRo() { return getValue(Flags.FLAG_ENABLED_FIXED_RO); return getValue(Flags.FLAG_ENABLED_FIXED_RO, FeatureFlags::enabledFixedRo); } @Override @UnsupportedAppUsage public boolean enabledRo() { return getValue(Flags.FLAG_ENABLED_RO); return getValue(Flags.FLAG_ENABLED_RO, FeatureFlags::enabledRo); } @Override @UnsupportedAppUsage public boolean enabledRw() { return getValue(Flags.FLAG_ENABLED_RW); } public void setFlag(String flagName, boolean value) { if (!this.mFlagMap.containsKey(flagName)) { throw new IllegalArgumentException("no such flag " + flagName); } this.mFlagMap.put(flagName, value); } public void resetAll() { for (Map.Entry entry : mFlagMap.entrySet()) { entry.setValue(null); } return getValue(Flags.FLAG_ENABLED_RW, FeatureFlags::enabledRw); } public boolean isFlagReadOnlyOptimized(String flagName) { if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) { Loading @@ -1082,27 +1151,27 @@ mod tests { } return false; } @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() { return false; } private boolean getValue(String flagName) { Boolean value = this.mFlagMap.get(flagName); if (value == null) { throw new IllegalArgumentException(flagName + " is not set"); } return value; protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { return mGetValueImpl.test(flagName, getter); } private Map<String, Boolean> mFlagMap = new HashMap<>( Map.ofEntries( Map.entry(Flags.FLAG_DISABLED_RO, false), Map.entry(Flags.FLAG_DISABLED_RW, false), Map.entry(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false), Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false), Map.entry(Flags.FLAG_ENABLED_RO, false), Map.entry(Flags.FLAG_ENABLED_RW, false) ) public List<String> getFlagNames() { return Arrays.asList( Flags.FLAG_DISABLED_RO, Flags.FLAG_DISABLED_RW, Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, Flags.FLAG_ENABLED_FIXED_RO, Flags.FLAG_ENABLED_RO, Flags.FLAG_ENABLED_RW ); } private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( Flags.FLAG_DISABLED_RO, Loading @@ -1116,11 +1185,16 @@ mod tests { ); } "#; let mut file_set = HashMap::from([ ("com/android/aconfig/test/Flags.java", expect_flags_content), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ("com/android/aconfig/test/FeatureFlags.java", expect_featureflags_content), ("com/android/aconfig/test/FakeFeatureFlagsImpl.java", expect_fakefeatureflags_content), ("com/android/aconfig/test/CustomFeatureFlags.java", expect_customfeatureflags_content), ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, ), ]); for file in generated_files { Loading
tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template 0 → 100644 +70 −0 Original line number Diff line number Diff line package {package_name}; {{ if not library_exported- }} // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; {{ -endif }} import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Predicate; /** @hide */ public class CustomFeatureFlags implements FeatureFlags \{ private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) \{ mGetValueImpl = getValueImpl; } {{ -for item in flag_elements}} @Override {{ if not library_exported }} @UnsupportedAppUsage{{ -endif }} public boolean {item.method_name}() \{ return getValue(Flags.FLAG_{item.flag_name_constant_suffix}, FeatureFlags::{item.method_name}); } {{ endfor }} {{ -if not library_exported }} public boolean isFlagReadOnlyOptimized(String flagName) \{ if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) \{ return true; } return false; } @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() \{ return false; } {{ -endif }} protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) \{ return mGetValueImpl.test(flagName, getter); } public List<String> getFlagNames() \{ return Arrays.asList( {{ -for item in flag_elements }} Flags.FLAG_{item.flag_name_constant_suffix} {{ -if not @last }},{{ endif }} {{ -endfor }} ); } private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( {{ -for item in flag_elements }} {{ -if not item.is_read_write }} Flags.FLAG_{item.flag_name_constant_suffix}, {{ -endif }} {{ -endfor }} ""{# The empty string here is to resolve the ending comma #} ) ); }
tools/aconfig/aconfig/templates/FakeFeatureFlagsImpl.java.template +17 −56 Original line number Diff line number Diff line package {package_name}; {{ if not library_exported- }} // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; {{ -endif }} import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.function.Predicate; /** @hide */ public class FakeFeatureFlagsImpl implements FeatureFlags \{ public class FakeFeatureFlagsImpl extends CustomFeatureFlags \{ private Map<String, Boolean> mFlagMap = new HashMap<>(); public FakeFeatureFlagsImpl() \{ resetAll(); super(null); // Initialize the map with null values for (String flagName : getFlagNames()) \{ mFlagMap.put(flagName, null); } } {{ for item in flag_elements}} @Override {{ if not library_exported }} @UnsupportedAppUsage{{ -endif }} public boolean {item.method_name}() \{ return getValue(Flags.FLAG_{item.flag_name_constant_suffix}); protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) \{ Boolean value = this.mFlagMap.get(flagName); if (value == null) \{ throw new IllegalArgumentException(flagName + " is not set"); } {{ endfor}} return value; } public void setFlag(String flagName, boolean value) \{ if (!this.mFlagMap.containsKey(flagName)) \{ throw new IllegalArgumentException("no such flag " + flagName); Loading @@ -34,46 +37,4 @@ public class FakeFeatureFlagsImpl implements FeatureFlags \{ entry.setValue(null); } } {{ if not library_exported }} public boolean isFlagReadOnlyOptimized(String flagName) \{ if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) \{ return true; } return false; } @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() \{ return false; } {{ -endif }} private boolean getValue(String flagName) \{ Boolean value = this.mFlagMap.get(flagName); if (value == null) \{ throw new IllegalArgumentException(flagName + " is not set"); } return value; } private Map<String, Boolean> mFlagMap = new HashMap<>( Map.ofEntries( {{ -for item in flag_elements }} Map.entry(Flags.FLAG_{item.flag_name_constant_suffix}, false) {{ -if not @last }},{{ endif }} {{ -endfor }} ) ); private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( {{ -for item in flag_elements }} {{ -if not item.is_read_write }} Flags.FLAG_{item.flag_name_constant_suffix}, {{ -endif }} {{ -endfor }} ""{# The empty string here is to resolve the ending comma #} ) ); }