Loading tools/aconfig/aconfig/src/codegen/java.rs +241 −58 Original line number Diff line number Diff line Loading @@ -508,12 +508,15 @@ mod tests { private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl(); }"#; let expect_featureflagsimpl_content = r#" let expected_featureflagsmpl_content_0 = r#" package com.android.aconfig.test; // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; "#; let expected_featureflagsmpl_content_1 = r#" /** @hide */ public final class FeatureFlagsImpl implements FeatureFlags { private static boolean aconfig_test_is_cached = false; Loading @@ -522,48 +525,8 @@ mod tests { private static boolean disabledRwExported = false; private static boolean disabledRwInOtherNamespace = false; private static boolean enabledRw = true; private void load_overrides_aconfig_test() { try { Properties properties = DeviceConfig.getProperties("aconfig_test"); disabledRw = properties.getBoolean(Flags.FLAG_DISABLED_RW, false); disabledRwExported = properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false); enabledRw = properties.getBoolean(Flags.FLAG_ENABLED_RW, true); } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace aconfig_test " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } aconfig_test_is_cached = true; } private void load_overrides_other_namespace() { try { Properties properties = DeviceConfig.getProperties("other_namespace"); disabledRwInOtherNamespace = properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false); } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace other_namespace " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } other_namespace_is_cached = true; } "#; let expected_featureflagsmpl_content_2 = r#" @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage Loading Loading @@ -632,9 +595,229 @@ mod tests { } } "#; let expect_featureflagsimpl_content_old = expected_featureflagsmpl_content_0.to_owned() + expected_featureflagsmpl_content_1 + r#" private void load_overrides_aconfig_test() { try { Properties properties = DeviceConfig.getProperties("aconfig_test"); disabledRw = properties.getBoolean(Flags.FLAG_DISABLED_RW, false); disabledRwExported = properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false); enabledRw = properties.getBoolean(Flags.FLAG_ENABLED_RW, true); } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace aconfig_test " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } aconfig_test_is_cached = true; } private void load_overrides_other_namespace() { try { Properties properties = DeviceConfig.getProperties("other_namespace"); disabledRwInOtherNamespace = properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false); } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace other_namespace " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } other_namespace_is_cached = true; }"# + expected_featureflagsmpl_content_2; let mut file_set = HashMap::from([ ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ( "com/android/aconfig/test/FeatureFlagsImpl.java", &expect_featureflagsimpl_content_old, ), ("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, ), ]); 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()); let parsed_flags = crate::test::parse_test_flags(); let mode = CodegenMode::Production; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); 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, true, ) .unwrap(); let expect_featureflagsimpl_content_new = expected_featureflagsmpl_content_0.to_owned() + r#" import android.aconfig.storage.StorageInternalReader; import android.util.Log; import java.io.File; "# + expected_featureflagsmpl_content_1 + r#" 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; try { reader = new StorageInternalReader("system", "com.android.aconfig.test"); } catch (Exception e) { reader = null; } } } private void load_overrides_aconfig_test() { try { boolean val; Properties properties = DeviceConfig.getProperties("aconfig_test"); disabledRw = properties.getBoolean(Flags.FLAG_DISABLED_RW, false); if (readFromNewStorage && reader != null) { try { val = reader.getBooleanFlagValue(1); if (val == disabledRw) { Log.i(TAG, "success: disabledRw value matches"); } else { Log.i(TAG, String.format( "error: disabledRw value mismatch, new storage value is %s, old storage value is %s", val, disabledRw)); } } catch (Exception e) { Log.e(TAG, "error: failed to read flag value of disabledRw", e); } } disabledRwExported = properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false); if (readFromNewStorage && reader != null) { try { val = reader.getBooleanFlagValue(2); if (val == disabledRwExported) { Log.i(TAG, "success: disabledRwExported value matches"); } else { Log.i(TAG, String.format( "error: disabledRwExported value mismatch, new storage value is %s, old storage value is %s", val, disabledRwExported)); } } catch (Exception e) { Log.e(TAG, "error: failed to read flag value of disabledRwExported", e); } } enabledRw = properties.getBoolean(Flags.FLAG_ENABLED_RW, true); if (readFromNewStorage && reader != null) { try { val = reader.getBooleanFlagValue(8); if (val == enabledRw) { Log.i(TAG, "success: enabledRw value matches"); } else { Log.i(TAG, String.format( "error: enabledRw value mismatch, new storage value is %s, old storage value is %s", val, enabledRw)); } } catch (Exception e) { Log.e(TAG, "error: failed to read flag value of enabledRw", e); } } } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace aconfig_test " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } aconfig_test_is_cached = true; } private void load_overrides_other_namespace() { try { boolean val; Properties properties = DeviceConfig.getProperties("other_namespace"); disabledRwInOtherNamespace = properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false); if (readFromNewStorage && reader != null) { try { val = reader.getBooleanFlagValue(3); if (val == disabledRwInOtherNamespace) { Log.i(TAG, "success: disabledRwInOtherNamespace value matches"); } else { Log.i(TAG, String.format( "error: disabledRwInOtherNamespace value mismatch, new storage value is %s, old storage value is %s", val, disabledRwInOtherNamespace)); } } catch (Exception e) { Log.e(TAG, "error: failed to read flag value of disabledRwInOtherNamespace", e); } } } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace other_namespace " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } other_namespace_is_cached = true; }"# + expected_featureflagsmpl_content_2; let mut file_set = HashMap::from([ ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ( "com/android/aconfig/test/FeatureFlagsImpl.java", &expect_featureflagsimpl_content_new, ), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT), ( "com/android/aconfig/test/CustomFeatureFlags.java", Loading tools/aconfig/aconfig_storage_file/tests/Android.bp +0 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ android_test { "androidx.test.runner", "junit", ], sdk_version: "test_current", test_config: "AndroidStorageJaveTest.xml", data: [ "package.map", Loading tools/aconfig/aconfig_storage_read_api/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,9 @@ java_library { srcs: [ "srcs/android/aconfig/storage/StorageInternalReader.java", ], libs: [ "unsupportedappusage", ], static_libs: [ "aconfig_storage_file_java", ], Loading tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java +6 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package android.aconfig.storage; import android.compat.annotation.UnsupportedAppUsage; import java.io.FileInputStream; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; /** @hide */ public class StorageInternalReader { private static final String MAP_PATH = "/metadata/aconfig/maps/"; Loading @@ -30,16 +33,19 @@ public class StorageInternalReader { private int mPackageBooleanStartOffset; @UnsupportedAppUsage public StorageInternalReader(String container, String packageName) { this(packageName, MAP_PATH + container + ".package.map", BOOT_PATH + container + ".val"); } @UnsupportedAppUsage public StorageInternalReader(String packageName, String packageMapFile, String flagValueFile) { mPackageTable = PackageTable.fromBytes(mapStorageFile(packageMapFile)); mFlagValueList = FlagValueList.fromBytes(mapStorageFile(flagValueFile)); mPackageBooleanStartOffset = getPackageBooleanStartOffset(packageName); } @UnsupportedAppUsage public boolean getBooleanFlagValue(int index) { index += mPackageBooleanStartOffset; if (index >= mFlagValueList.size()) { Loading tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template +2 −2 File changed.Contains only whitespace changes. Show changes Loading
tools/aconfig/aconfig/src/codegen/java.rs +241 −58 Original line number Diff line number Diff line Loading @@ -508,12 +508,15 @@ mod tests { private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl(); }"#; let expect_featureflagsimpl_content = r#" let expected_featureflagsmpl_content_0 = r#" package com.android.aconfig.test; // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; "#; let expected_featureflagsmpl_content_1 = r#" /** @hide */ public final class FeatureFlagsImpl implements FeatureFlags { private static boolean aconfig_test_is_cached = false; Loading @@ -522,48 +525,8 @@ mod tests { private static boolean disabledRwExported = false; private static boolean disabledRwInOtherNamespace = false; private static boolean enabledRw = true; private void load_overrides_aconfig_test() { try { Properties properties = DeviceConfig.getProperties("aconfig_test"); disabledRw = properties.getBoolean(Flags.FLAG_DISABLED_RW, false); disabledRwExported = properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false); enabledRw = properties.getBoolean(Flags.FLAG_ENABLED_RW, true); } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace aconfig_test " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } aconfig_test_is_cached = true; } private void load_overrides_other_namespace() { try { Properties properties = DeviceConfig.getProperties("other_namespace"); disabledRwInOtherNamespace = properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false); } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace other_namespace " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } other_namespace_is_cached = true; } "#; let expected_featureflagsmpl_content_2 = r#" @Override @com.android.aconfig.annotations.AconfigFlagAccessor @UnsupportedAppUsage Loading Loading @@ -632,9 +595,229 @@ mod tests { } } "#; let expect_featureflagsimpl_content_old = expected_featureflagsmpl_content_0.to_owned() + expected_featureflagsmpl_content_1 + r#" private void load_overrides_aconfig_test() { try { Properties properties = DeviceConfig.getProperties("aconfig_test"); disabledRw = properties.getBoolean(Flags.FLAG_DISABLED_RW, false); disabledRwExported = properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false); enabledRw = properties.getBoolean(Flags.FLAG_ENABLED_RW, true); } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace aconfig_test " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } aconfig_test_is_cached = true; } private void load_overrides_other_namespace() { try { Properties properties = DeviceConfig.getProperties("other_namespace"); disabledRwInOtherNamespace = properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false); } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace other_namespace " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } other_namespace_is_cached = true; }"# + expected_featureflagsmpl_content_2; let mut file_set = HashMap::from([ ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ( "com/android/aconfig/test/FeatureFlagsImpl.java", &expect_featureflagsimpl_content_old, ), ("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, ), ]); 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()); let parsed_flags = crate::test::parse_test_flags(); let mode = CodegenMode::Production; let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); 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, true, ) .unwrap(); let expect_featureflagsimpl_content_new = expected_featureflagsmpl_content_0.to_owned() + r#" import android.aconfig.storage.StorageInternalReader; import android.util.Log; import java.io.File; "# + expected_featureflagsmpl_content_1 + r#" 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; try { reader = new StorageInternalReader("system", "com.android.aconfig.test"); } catch (Exception e) { reader = null; } } } private void load_overrides_aconfig_test() { try { boolean val; Properties properties = DeviceConfig.getProperties("aconfig_test"); disabledRw = properties.getBoolean(Flags.FLAG_DISABLED_RW, false); if (readFromNewStorage && reader != null) { try { val = reader.getBooleanFlagValue(1); if (val == disabledRw) { Log.i(TAG, "success: disabledRw value matches"); } else { Log.i(TAG, String.format( "error: disabledRw value mismatch, new storage value is %s, old storage value is %s", val, disabledRw)); } } catch (Exception e) { Log.e(TAG, "error: failed to read flag value of disabledRw", e); } } disabledRwExported = properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false); if (readFromNewStorage && reader != null) { try { val = reader.getBooleanFlagValue(2); if (val == disabledRwExported) { Log.i(TAG, "success: disabledRwExported value matches"); } else { Log.i(TAG, String.format( "error: disabledRwExported value mismatch, new storage value is %s, old storage value is %s", val, disabledRwExported)); } } catch (Exception e) { Log.e(TAG, "error: failed to read flag value of disabledRwExported", e); } } enabledRw = properties.getBoolean(Flags.FLAG_ENABLED_RW, true); if (readFromNewStorage && reader != null) { try { val = reader.getBooleanFlagValue(8); if (val == enabledRw) { Log.i(TAG, "success: enabledRw value matches"); } else { Log.i(TAG, String.format( "error: enabledRw value mismatch, new storage value is %s, old storage value is %s", val, enabledRw)); } } catch (Exception e) { Log.e(TAG, "error: failed to read flag value of enabledRw", e); } } } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace aconfig_test " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } aconfig_test_is_cached = true; } private void load_overrides_other_namespace() { try { boolean val; Properties properties = DeviceConfig.getProperties("other_namespace"); disabledRwInOtherNamespace = properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false); if (readFromNewStorage && reader != null) { try { val = reader.getBooleanFlagValue(3); if (val == disabledRwInOtherNamespace) { Log.i(TAG, "success: disabledRwInOtherNamespace value matches"); } else { Log.i(TAG, String.format( "error: disabledRwInOtherNamespace value mismatch, new storage value is %s, old storage value is %s", val, disabledRwInOtherNamespace)); } } catch (Exception e) { Log.e(TAG, "error: failed to read flag value of disabledRwInOtherNamespace", e); } } } catch (NullPointerException e) { throw new RuntimeException( "Cannot read value from namespace other_namespace " + "from DeviceConfig. It could be that the code using flag " + "executed before SettingsProvider initialization. Please use " + "fixed read-only flag by adding is_fixed_read_only: true in " + "flag declaration.", e ); } other_namespace_is_cached = true; }"# + expected_featureflagsmpl_content_2; let mut file_set = HashMap::from([ ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ( "com/android/aconfig/test/FeatureFlagsImpl.java", &expect_featureflagsimpl_content_new, ), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT), ( "com/android/aconfig/test/CustomFeatureFlags.java", Loading
tools/aconfig/aconfig_storage_file/tests/Android.bp +0 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ android_test { "androidx.test.runner", "junit", ], sdk_version: "test_current", test_config: "AndroidStorageJaveTest.xml", data: [ "package.map", Loading
tools/aconfig/aconfig_storage_read_api/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,9 @@ java_library { srcs: [ "srcs/android/aconfig/storage/StorageInternalReader.java", ], libs: [ "unsupportedappusage", ], static_libs: [ "aconfig_storage_file_java", ], Loading
tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java +6 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package android.aconfig.storage; import android.compat.annotation.UnsupportedAppUsage; import java.io.FileInputStream; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; /** @hide */ public class StorageInternalReader { private static final String MAP_PATH = "/metadata/aconfig/maps/"; Loading @@ -30,16 +33,19 @@ public class StorageInternalReader { private int mPackageBooleanStartOffset; @UnsupportedAppUsage public StorageInternalReader(String container, String packageName) { this(packageName, MAP_PATH + container + ".package.map", BOOT_PATH + container + ".val"); } @UnsupportedAppUsage public StorageInternalReader(String packageName, String packageMapFile, String flagValueFile) { mPackageTable = PackageTable.fromBytes(mapStorageFile(packageMapFile)); mFlagValueList = FlagValueList.fromBytes(mapStorageFile(flagValueFile)); mPackageBooleanStartOffset = getPackageBooleanStartOffset(packageName); } @UnsupportedAppUsage public boolean getBooleanFlagValue(int index) { index += mPackageBooleanStartOffset; if (index >= mFlagValueList.size()) { Loading
tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template +2 −2 File changed.Contains only whitespace changes. Show changes