diff options
| author | 2023-12-21 02:14:46 +0000 | |
|---|---|---|
| committer | 2024-01-03 15:56:18 +0000 | |
| commit | e567abdf3ea29bb777f03923d7f61c797d29c9ac (patch) | |
| tree | d9b2ea2b0074c542817917a3ab7ddb19497fb8f8 | |
| parent | 1a8281ccc22d0351a35cf9735061c11d27398beb (diff) | |
aconfig: add ForceReadOnly mode to aconfig java codegen
This commit adds ForceReadOnly mode to java codegen.
Bug: 316357759
Test: atest aconfig.test aconfig.test.java
Change-Id: I10cd60def9ea20f7d56d87d18f680afeac61dc9d
| -rw-r--r-- | tools/aconfig/Android.bp | 13 | ||||
| -rw-r--r-- | tools/aconfig/src/codegen/java.rs | 222 | ||||
| -rw-r--r-- | tools/aconfig/tests/AconfigTest.java | 6 | ||||
| -rw-r--r-- | tools/aconfig/tests/test_force_read_only.aconfig | 17 |
4 files changed, 258 insertions, 0 deletions
diff --git a/tools/aconfig/Android.bp b/tools/aconfig/Android.bp index 37be2dd975..b9289d6773 100644 --- a/tools/aconfig/Android.bp +++ b/tools/aconfig/Android.bp @@ -96,6 +96,12 @@ aconfig_declarations { srcs: ["tests/test_exported.aconfig"], } +aconfig_declarations { + name: "aconfig.test.forcereadonly.flags", + package: "com.android.aconfig.test.forcereadonly", + srcs: ["tests/test_force_read_only.aconfig"], +} + aconfig_values { name: "aconfig.test.flag.values", package: "com.android.aconfig.test", @@ -125,6 +131,12 @@ java_aconfig_library { mode: "exported", } +java_aconfig_library { + name: "aconfig_test_java_library_forcereadonly", + aconfig_declarations: "aconfig.test.forcereadonly.flags", + mode: "force-read-only", +} + android_test { name: "aconfig.test.java", srcs: [ @@ -135,6 +147,7 @@ android_test { static_libs: [ "aconfig_test_java_library", "aconfig_test_java_library_exported", + "aconfig_test_java_library_forcereadonly", "androidx.test.rules", "testng", ], diff --git a/tools/aconfig/src/codegen/java.rs b/tools/aconfig/src/codegen/java.rs index a02a7e2d90..f214fa53cc 100644 --- a/tools/aconfig/src/codegen/java.rs +++ b/tools/aconfig/src/codegen/java.rs @@ -834,6 +834,228 @@ mod tests { } #[test] + fn test_generate_java_code_force_read_only() { + let parsed_flags = crate::test::parse_test_flags(); + 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) + .unwrap(); + let expect_featureflags_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 interface FeatureFlags { + @com.android.aconfig.annotations.AssumeFalseForR8 + @UnsupportedAppUsage + boolean disabledRo(); + @com.android.aconfig.annotations.AssumeFalseForR8 + @UnsupportedAppUsage + boolean disabledRw(); + @com.android.aconfig.annotations.AssumeFalseForR8 + @UnsupportedAppUsage + boolean disabledRwInOtherNamespace(); + @com.android.aconfig.annotations.AssumeTrueForR8 + @UnsupportedAppUsage + boolean enabledFixedRo(); + @com.android.aconfig.annotations.AssumeTrueForR8 + @UnsupportedAppUsage + boolean enabledRo(); + @com.android.aconfig.annotations.AssumeTrueForR8 + @UnsupportedAppUsage + boolean enabledRw(); + }"#; + + 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 + @UnsupportedAppUsage + public boolean disabledRo() { + return false; + } + @Override + @UnsupportedAppUsage + public boolean disabledRw() { + return false; + } + @Override + @UnsupportedAppUsage + public boolean disabledRwInOtherNamespace() { + return false; + } + @Override + @UnsupportedAppUsage + public boolean enabledFixedRo() { + return true; + } + @Override + @UnsupportedAppUsage + public boolean enabledRo() { + return true; + } + @Override + @UnsupportedAppUsage + public boolean enabledRw() { + return true; + } + } + "#; + + let expect_flags_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 Flags { + /** @hide */ + public static final String FLAG_DISABLED_RO = "com.android.aconfig.test.disabled_ro"; + /** @hide */ + public static final String FLAG_DISABLED_RW = "com.android.aconfig.test.disabled_rw"; + /** @hide */ + public static final String FLAG_DISABLED_RW_IN_OTHER_NAMESPACE = "com.android.aconfig.test.disabled_rw_in_other_namespace"; + /** @hide */ + public static final String FLAG_ENABLED_FIXED_RO = "com.android.aconfig.test.enabled_fixed_ro"; + /** @hide */ + public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro"; + /** @hide */ + public static final String FLAG_ENABLED_RW = "com.android.aconfig.test.enabled_rw"; + + @com.android.aconfig.annotations.AssumeFalseForR8 + @UnsupportedAppUsage + public static boolean disabledRo() { + return FEATURE_FLAGS.disabledRo(); + } + @com.android.aconfig.annotations.AssumeFalseForR8 + @UnsupportedAppUsage + public static boolean disabledRw() { + return FEATURE_FLAGS.disabledRw(); + } + @com.android.aconfig.annotations.AssumeFalseForR8 + @UnsupportedAppUsage + public static boolean disabledRwInOtherNamespace() { + return FEATURE_FLAGS.disabledRwInOtherNamespace(); + } + @com.android.aconfig.annotations.AssumeTrueForR8 + @UnsupportedAppUsage + public static boolean enabledFixedRo() { + return FEATURE_FLAGS.enabledFixedRo(); + } + @com.android.aconfig.annotations.AssumeTrueForR8 + @UnsupportedAppUsage + public static boolean enabledRo() { + return FEATURE_FLAGS.enabledRo(); + } + @com.android.aconfig.annotations.AssumeTrueForR8 + @UnsupportedAppUsage + public static boolean enabledRw() { + return FEATURE_FLAGS.enabledRw(); + } + private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl(); + }"#; + + let expect_fakefeatureflags_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.HashMap; + import java.util.Map; + /** @hide */ + public class FakeFeatureFlagsImpl implements FeatureFlags { + public FakeFeatureFlagsImpl() { + resetAll(); + } + @Override + @UnsupportedAppUsage + public boolean disabledRo() { + return getValue(Flags.FLAG_DISABLED_RO); + } + @Override + @UnsupportedAppUsage + public boolean disabledRw() { + return getValue(Flags.FLAG_DISABLED_RW); + } + @Override + @UnsupportedAppUsage + public boolean disabledRwInOtherNamespace() { + return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE); + } + @Override + @UnsupportedAppUsage + public boolean enabledFixedRo() { + return getValue(Flags.FLAG_ENABLED_FIXED_RO); + } + @Override + @UnsupportedAppUsage + public boolean enabledRo() { + return getValue(Flags.FLAG_ENABLED_RO); + } + @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); + } + } + 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( + 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) + ) + ); + } + "#; + 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), + ]); + + for file in generated_files { + let file_path = file.path.to_str().unwrap(); + assert!(file_set.contains_key(file_path), "Cannot find {}", file_path); + assert_eq!( + None, + crate::test::first_significant_code_diff( + file_set.get(file_path).unwrap(), + &String::from_utf8(file.contents).unwrap() + ), + "File {} content is not correct", + file_path + ); + file_set.remove(file_path); + } + + assert!(file_set.is_empty()); + } + + #[test] fn test_format_java_method_name() { let expected = "someSnakeName"; let input = "____some_snake___name____"; diff --git a/tools/aconfig/tests/AconfigTest.java b/tools/aconfig/tests/AconfigTest.java index b2deca03b1..7e76efba3c 100644 --- a/tools/aconfig/tests/AconfigTest.java +++ b/tools/aconfig/tests/AconfigTest.java @@ -10,6 +10,7 @@ import static com.android.aconfig.test.Flags.enabledRo; import static com.android.aconfig.test.Flags.enabledRw; import static com.android.aconfig.test.exported.Flags.exportedFlag; import static com.android.aconfig.test.exported.Flags.FLAG_EXPORTED_FLAG; +import static com.android.aconfig.test.forcereadonly.Flags.froRw; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThrows; @@ -66,4 +67,9 @@ public final class AconfigTest { assertEquals("com.android.aconfig.test.exported.exported_flag", FLAG_EXPORTED_FLAG); assertFalse(exportedFlag()); } + + @Test + public void testForceReadOnly() { + assertFalse(froRw()); + } } diff --git a/tools/aconfig/tests/test_force_read_only.aconfig b/tools/aconfig/tests/test_force_read_only.aconfig new file mode 100644 index 0000000000..05ab0e27d3 --- /dev/null +++ b/tools/aconfig/tests/test_force_read_only.aconfig @@ -0,0 +1,17 @@ +package: "com.android.aconfig.test.forcereadonly" +container: "system" + +flag { + name: "fro_exported" + namespace: "aconfig_test" + description: "This is an exported flag" + is_exported: true + bug: "888" +} + +flag { + name: "fro_rw" + namespace: "aconfig_test" + description: "This flag is not exported" + bug: "777" +} |