Merge "aconfig: Add exported mode to aconfig Java library generation." into main

This commit is contained in:
Ted Bauer
2023-11-29 18:23:10 +00:00
committed by Gerrit Code Review
11 changed files with 478 additions and 12 deletions

View File

@@ -162,6 +162,8 @@ public:
virtual bool disabled_rw() = 0;
virtual bool disabled_rw_exported() = 0;
virtual bool disabled_rw_in_other_namespace() = 0;
virtual bool enabled_fixed_ro() = 0;
@@ -181,6 +183,10 @@ inline bool disabled_rw() {
return provider_->disabled_rw();
}
inline bool disabled_rw_exported() {
return provider_->disabled_rw_exported();
}
inline bool disabled_rw_in_other_namespace() {
return provider_->disabled_rw_in_other_namespace();
}
@@ -206,6 +212,8 @@ bool com_android_aconfig_test_disabled_ro();
bool com_android_aconfig_test_disabled_rw();
bool com_android_aconfig_test_disabled_rw_exported();
bool com_android_aconfig_test_disabled_rw_in_other_namespace();
bool com_android_aconfig_test_enabled_fixed_ro();
@@ -241,6 +249,10 @@ public:
virtual void disabled_rw(bool val) = 0;
virtual bool disabled_rw_exported() = 0;
virtual void disabled_rw_exported(bool val) = 0;
virtual bool disabled_rw_in_other_namespace() = 0;
virtual void disabled_rw_in_other_namespace(bool val) = 0;
@@ -278,6 +290,14 @@ inline void disabled_rw(bool val) {
provider_->disabled_rw(val);
}
inline bool disabled_rw_exported() {
return provider_->disabled_rw_exported();
}
inline void disabled_rw_exported(bool val) {
provider_->disabled_rw_exported(val);
}
inline bool disabled_rw_in_other_namespace() {
return provider_->disabled_rw_in_other_namespace();
}
@@ -327,6 +347,10 @@ bool com_android_aconfig_test_disabled_rw();
void set_com_android_aconfig_test_disabled_rw(bool val);
bool com_android_aconfig_test_disabled_rw_exported();
void set_com_android_aconfig_test_disabled_rw_exported(bool val);
bool com_android_aconfig_test_disabled_rw_in_other_namespace();
void set_com_android_aconfig_test_disabled_rw_in_other_namespace(bool val);
@@ -377,14 +401,24 @@ namespace com::android::aconfig::test {
return cache_[0];
}
virtual bool disabled_rw_in_other_namespace() override {
virtual bool disabled_rw_exported() override {
if (cache_[1] == -1) {
cache_[1] = server_configurable_flags::GetServerConfigurableFlag(
"aconfig_flags.aconfig_test",
"com.android.aconfig.test.disabled_rw_exported",
"false") == "true";
}
return cache_[1];
}
virtual bool disabled_rw_in_other_namespace() override {
if (cache_[2] == -1) {
cache_[2] = server_configurable_flags::GetServerConfigurableFlag(
"aconfig_flags.other_namespace",
"com.android.aconfig.test.disabled_rw_in_other_namespace",
"false") == "true";
}
return cache_[1];
return cache_[2];
}
virtual bool enabled_fixed_ro() override {
@@ -396,17 +430,17 @@ namespace com::android::aconfig::test {
}
virtual bool enabled_rw() override {
if (cache_[2] == -1) {
cache_[2] = server_configurable_flags::GetServerConfigurableFlag(
if (cache_[3] == -1) {
cache_[3] = server_configurable_flags::GetServerConfigurableFlag(
"aconfig_flags.aconfig_test",
"com.android.aconfig.test.enabled_rw",
"true") == "true";
}
return cache_[2];
return cache_[3];
}
private:
std::vector<int8_t> cache_ = std::vector<int8_t>(3, -1);
std::vector<int8_t> cache_ = std::vector<int8_t>(4, -1);
};
std::unique_ptr<flag_provider_interface> provider_ =
@@ -421,6 +455,10 @@ bool com_android_aconfig_test_disabled_rw() {
return com::android::aconfig::test::disabled_rw();
}
bool com_android_aconfig_test_disabled_rw_exported() {
return com::android::aconfig::test::disabled_rw_exported();
}
bool com_android_aconfig_test_disabled_rw_in_other_namespace() {
return com::android::aconfig::test::disabled_rw_in_other_namespace();
}
@@ -485,6 +523,22 @@ namespace com::android::aconfig::test {
overrides_["disabled_rw"] = val;
}
virtual bool disabled_rw_exported() override {
auto it = overrides_.find("disabled_rw_exported");
if (it != overrides_.end()) {
return it->second;
} else {
return server_configurable_flags::GetServerConfigurableFlag(
"aconfig_flags.aconfig_test",
"com.android.aconfig.test.disabled_rw_exported",
"false") == "true";
}
}
virtual void disabled_rw_exported(bool val) override {
overrides_["disabled_rw_exported"] = val;
}
virtual bool disabled_rw_in_other_namespace() override {
auto it = overrides_.find("disabled_rw_in_other_namespace");
if (it != overrides_.end()) {
@@ -570,11 +624,20 @@ void set_com_android_aconfig_test_disabled_rw(bool val) {
com::android::aconfig::test::disabled_rw(val);
}
bool com_android_aconfig_test_disabled_rw_exported() {
return com::android::aconfig::test::disabled_rw_exported();
}
void set_com_android_aconfig_test_disabled_rw_exported(bool val) {
com::android::aconfig::test::disabled_rw_exported(val);
}
bool com_android_aconfig_test_disabled_rw_in_other_namespace() {
return com::android::aconfig::test::disabled_rw_in_other_namespace();
}
void set_com_android_aconfig_test_disabled_rw_in_other_namespace(bool val) {
com::android::aconfig::test::disabled_rw_in_other_namespace(val);
}
@@ -634,6 +697,8 @@ void com_android_aconfig_test_reset_flags() {
match mode {
CodegenMode::Production => EXPORTED_PROD_HEADER_EXPECTED,
CodegenMode::Test => EXPORTED_TEST_HEADER_EXPECTED,
CodegenMode::Exported =>
todo!("exported mode not yet supported for cpp, see b/313894653."),
},
generated_files_map.get(&target_file_path).unwrap()
)
@@ -647,6 +712,8 @@ void com_android_aconfig_test_reset_flags() {
match mode {
CodegenMode::Production => PROD_SOURCE_FILE_EXPECTED,
CodegenMode::Test => TEST_SOURCE_FILE_EXPECTED,
CodegenMode::Exported =>
todo!("exported mode not yet supported for cpp, see b/313894653."),
},
generated_files_map.get(&target_file_path).unwrap()
)

View File

@@ -39,6 +39,7 @@ where
flag_elements.iter().map(|fe| format_property_name(&fe.device_config_namespace)).collect();
let is_read_write = flag_elements.iter().any(|elem| elem.is_read_write);
let is_test_mode = codegen_mode == CodegenMode::Test;
let library_exported = codegen_mode == CodegenMode::Exported;
let context = Context {
flag_elements,
namespace_flags,
@@ -46,6 +47,7 @@ where
is_read_write,
properties_set,
package_name: package.to_string(),
library_exported,
};
let mut template = TinyTemplate::new();
template.add_template("Flags.java", include_str!("../templates/Flags.java.template"))?;
@@ -103,6 +105,7 @@ struct Context {
pub is_read_write: bool,
pub properties_set: BTreeSet<String>,
pub package_name: String,
pub library_exported: bool,
}
#[derive(Serialize, Debug)]
@@ -120,6 +123,7 @@ struct FlagElement {
pub is_read_write: bool,
pub method_name: String,
pub properties: String,
pub exported: bool,
}
fn create_flag_element(package: &str, pf: &ProtoParsedFlag) -> FlagElement {
@@ -133,6 +137,7 @@ fn create_flag_element(package: &str, pf: &ProtoParsedFlag) -> FlagElement {
is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE,
method_name: format_java_method_name(pf.name()),
properties: format_property_name(pf.namespace()),
exported: pf.is_exported.unwrap_or(false),
}
}
@@ -179,6 +184,8 @@ mod tests {
@UnsupportedAppUsage
boolean disabledRw();
@UnsupportedAppUsage
boolean disabledRwExported();
@UnsupportedAppUsage
boolean disabledRwInOtherNamespace();
@com.android.aconfig.annotations.AssumeTrueForR8
@UnsupportedAppUsage
@@ -202,6 +209,8 @@ mod tests {
/** @hide */
public static final String FLAG_DISABLED_RW = "com.android.aconfig.test.disabled_rw";
/** @hide */
public static final String FLAG_DISABLED_RW_EXPORTED = "com.android.aconfig.test.disabled_rw_exported";
/** @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";
@@ -220,6 +229,10 @@ mod tests {
return FEATURE_FLAGS.disabledRw();
}
@UnsupportedAppUsage
public static boolean disabledRwExported() {
return FEATURE_FLAGS.disabledRwExported();
}
@UnsupportedAppUsage
public static boolean disabledRwInOtherNamespace() {
return FEATURE_FLAGS.disabledRwInOtherNamespace();
}
@@ -262,6 +275,11 @@ mod tests {
}
@Override
@UnsupportedAppUsage
public boolean disabledRwExported() {
return getValue(Flags.FLAG_DISABLED_RW_EXPORTED);
}
@Override
@UnsupportedAppUsage
public boolean disabledRwInOtherNamespace() {
return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE);
}
@@ -302,6 +320,7 @@ mod tests {
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_RO, false),
@@ -336,6 +355,7 @@ mod tests {
private static boolean aconfig_test_is_cached = false;
private static boolean other_namespace_is_cached = false;
private static boolean disabledRw = false;
private static boolean disabledRwExported = false;
private static boolean disabledRwInOtherNamespace = false;
private static boolean enabledRw = true;
@@ -345,6 +365,8 @@ mod tests {
Properties properties = DeviceConfig.getProperties("aconfig_test");
disabledRw =
properties.getBoolean("com.android.aconfig.test.disabled_rw", false);
disabledRwExported =
properties.getBoolean("com.android.aconfig.test.disabled_rw_exported", false);
enabledRw =
properties.getBoolean("com.android.aconfig.test.enabled_rw", true);
} catch (NullPointerException e) {
@@ -394,6 +416,14 @@ mod tests {
}
@Override
@UnsupportedAppUsage
public boolean disabledRwExported() {
if (!aconfig_test_is_cached) {
load_overrides_aconfig_test();
}
return disabledRwExported;
}
@Override
@UnsupportedAppUsage
public boolean disabledRwInOtherNamespace() {
if (!other_namespace_is_cached) {
load_overrides_other_namespace();
@@ -448,6 +478,202 @@ mod tests {
assert!(file_set.is_empty());
}
#[test]
fn test_generate_java_code_exported() {
let parsed_flags = crate::test::parse_test_flags();
let generated_files = generate_java_code(
crate::test::TEST_PACKAGE,
parsed_flags.parsed_flag.iter(),
CodegenMode::Exported,
)
.unwrap();
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_RW = "com.android.aconfig.test.disabled_rw";
/** @hide */
public static final String FLAG_DISABLED_RW_EXPORTED = "com.android.aconfig.test.disabled_rw_exported";
@UnsupportedAppUsage
public static boolean disabledRw() {
return FEATURE_FLAGS.disabledRw();
}
@UnsupportedAppUsage
public static boolean disabledRwExported() {
return FEATURE_FLAGS.disabledRwExported();
}
private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
}
"#;
let expect_feature_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 interface FeatureFlags {
@UnsupportedAppUsage
boolean disabledRw();
@UnsupportedAppUsage
boolean disabledRwExported();
}
"#;
let expect_feature_flags_impl_content = 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;
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags {
private static boolean aconfig_test_is_cached = false;
private static boolean other_namespace_is_cached = false;
private static boolean disabledRw = false;
private static boolean disabledRwExported = false;
private void load_overrides_aconfig_test() {
try {
Properties properties = DeviceConfig.getProperties("aconfig_test");
disabledRw =
properties.getBoolean("com.android.aconfig.test.disabled_rw", false);
disabledRwExported =
properties.getBoolean("com.android.aconfig.test.disabled_rw_exported", false);
} 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");
} 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;
}
@Override
@UnsupportedAppUsage
public boolean disabledRw() {
if (!aconfig_test_is_cached) {
load_overrides_aconfig_test();
}
return disabledRw;
}
@Override
@UnsupportedAppUsage
public boolean disabledRwExported() {
if (!aconfig_test_is_cached) {
load_overrides_aconfig_test();
}
return disabledRwExported;
}
}"#;
let expect_fake_feature_flags_impl_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 disabledRw() {
return getValue(Flags.FLAG_DISABLED_RW);
}
@Override
@UnsupportedAppUsage
public boolean disabledRwExported() {
return getValue(Flags.FLAG_DISABLED_RW_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 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_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_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/FeatureFlags.java", expect_feature_flags_content),
("com/android/aconfig/test/FeatureFlagsImpl.java", expect_feature_flags_impl_content),
(
"com/android/aconfig/test/FakeFeatureFlagsImpl.java",
expect_fake_feature_flags_impl_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_generate_java_code_test() {
let parsed_flags = crate::test::parse_test_flags();
@@ -489,6 +715,12 @@ mod tests {
}
@Override
@UnsupportedAppUsage
public boolean disabledRwExported() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
@UnsupportedAppUsage
public boolean disabledRwInOtherNamespace() {
throw new UnsupportedOperationException(
"Method is not implemented.");

View File

@@ -45,6 +45,9 @@ where
match codegen_mode {
CodegenMode::Production => include_str!("../templates/rust_prod.template"),
CodegenMode::Test => include_str!("../templates/rust_test.template"),
CodegenMode::Exported => {
todo!("exported mode not yet supported for rust, see b/313894653.")
}
},
)?;
let contents = template.render("rust_code_gen", &context)?;
@@ -104,6 +107,12 @@ lazy_static::lazy_static! {
"com.android.aconfig.test.disabled_rw",
"false") == "true";
/// flag value cache for disabled_rw_exported
static ref CACHED_disabled_rw_exported: bool = flags_rust::GetServerConfigurableFlag(
"aconfig_flags.aconfig_test",
"com.android.aconfig.test.disabled_rw_exported",
"false") == "true";
/// flag value cache for disabled_rw_in_other_namespace
static ref CACHED_disabled_rw_in_other_namespace: bool = flags_rust::GetServerConfigurableFlag(
"aconfig_flags.other_namespace",
@@ -115,6 +124,7 @@ lazy_static::lazy_static! {
"aconfig_flags.aconfig_test",
"com.android.aconfig.test.enabled_rw",
"true") == "true";
}
impl FlagProvider {
@@ -128,6 +138,11 @@ impl FlagProvider {
*CACHED_disabled_rw
}
/// query flag disabled_rw_exported
pub fn disabled_rw_exported(&self) -> bool {
*CACHED_disabled_rw_exported
}
/// query flag disabled_rw_in_other_namespace
pub fn disabled_rw_in_other_namespace(&self) -> bool {
*CACHED_disabled_rw_in_other_namespace
@@ -164,6 +179,12 @@ pub fn disabled_rw() -> bool {
PROVIDER.disabled_rw()
}
/// query flag disabled_rw_exported
#[inline(always)]
pub fn disabled_rw_exported() -> bool {
PROVIDER.disabled_rw_exported()
}
/// query flag disabled_rw_in_other_namespace
#[inline(always)]
pub fn disabled_rw_in_other_namespace() -> bool {
@@ -228,6 +249,21 @@ impl FlagProvider {
self.overrides.insert("disabled_rw", val);
}
/// query flag disabled_rw_exported
pub fn disabled_rw_exported(&self) -> bool {
self.overrides.get("disabled_rw_exported").copied().unwrap_or(
flags_rust::GetServerConfigurableFlag(
"aconfig_flags.aconfig_test",
"com.android.aconfig.test.disabled_rw_exported",
"false") == "true"
)
}
/// set flag disabled_rw_exported
pub fn set_disabled_rw_exported(&mut self, val: bool) {
self.overrides.insert("disabled_rw_exported", val);
}
/// query flag disabled_rw_in_other_namespace
pub fn disabled_rw_in_other_namespace(&self) -> bool {
self.overrides.get("disabled_rw_in_other_namespace").copied().unwrap_or(
@@ -317,6 +353,18 @@ pub fn set_disabled_rw(val: bool) {
PROVIDER.lock().unwrap().set_disabled_rw(val);
}
/// query flag disabled_rw_exported
#[inline(always)]
pub fn disabled_rw_exported() -> bool {
PROVIDER.lock().unwrap().disabled_rw_exported()
}
/// set flag disabled_rw_exported
#[inline(always)]
pub fn set_disabled_rw_exported(val: bool) {
PROVIDER.lock().unwrap().set_disabled_rw_exported(val);
}
/// query flag disabled_rw_in_other_namespace
#[inline(always)]
pub fn disabled_rw_in_other_namespace() -> bool {
@@ -383,6 +431,8 @@ pub fn reset_flags() {
match mode {
CodegenMode::Production => PROD_EXPECTED,
CodegenMode::Test => TEST_EXPECTED,
CodegenMode::Exported =>
todo!("exported mode not yet supported for rust, see b/313894653."),
},
&String::from_utf8(generated.contents).unwrap()
)

View File

@@ -171,6 +171,7 @@ pub fn parse_flags(
pub enum CodegenMode {
Production,
Test,
Exported,
}
pub fn create_java_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
@@ -335,7 +336,7 @@ mod tests {
assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
assert_eq!(6, parsed_flags.parsed_flag.len());
assert_eq!(7, parsed_flags.parsed_flag.len());
for pf in parsed_flags.parsed_flag.iter() {
if pf.name() == "enabled_fixed_ro" {
continue;
@@ -434,7 +435,7 @@ mod tests {
let input = parse_test_flags_as_input();
let bytes = create_device_config_defaults(input).unwrap();
let text = std::str::from_utf8(&bytes).unwrap();
assert_eq!("aconfig_test:com.android.aconfig.test.disabled_rw=disabled\nother_namespace:com.android.aconfig.test.disabled_rw_in_other_namespace=disabled\naconfig_test:com.android.aconfig.test.enabled_rw=enabled\n", text);
assert_eq!("aconfig_test:com.android.aconfig.test.disabled_rw=disabled\naconfig_test:com.android.aconfig.test.disabled_rw_exported=disabled\nother_namespace:com.android.aconfig.test.disabled_rw_in_other_namespace=disabled\naconfig_test:com.android.aconfig.test.enabled_rw=enabled\n", text);
}
#[test]
@@ -442,7 +443,7 @@ mod tests {
let input = parse_test_flags_as_input();
let bytes = create_device_config_sysprops(input).unwrap();
let text = std::str::from_utf8(&bytes).unwrap();
assert_eq!("persist.device_config.com.android.aconfig.test.disabled_rw=false\npersist.device_config.com.android.aconfig.test.disabled_rw_in_other_namespace=false\npersist.device_config.com.android.aconfig.test.enabled_rw=true\n", text);
assert_eq!("persist.device_config.com.android.aconfig.test.disabled_rw=false\npersist.device_config.com.android.aconfig.test.disabled_rw_exported=false\npersist.device_config.com.android.aconfig.test.disabled_rw_in_other_namespace=false\npersist.device_config.com.android.aconfig.test.enabled_rw=true\n", text);
}
#[test]

View File

@@ -60,6 +60,27 @@ parsed_flag {
is_fixed_read_only: false
is_exported: true
}
parsed_flag {
package: "com.android.aconfig.test"
name: "disabled_rw_exported"
namespace: "aconfig_test"
description: "This flag is exported"
bug: "111"
state: DISABLED
permission: READ_WRITE
trace {
source: "tests/test.aconfig"
state: DISABLED
permission: READ_WRITE
}
trace {
source: "tests/first.values"
state: DISABLED
permission: READ_WRITE
}
is_fixed_read_only: false
is_exported: true
}
parsed_flag {
package: "com.android.aconfig.test"
name: "disabled_rw_in_other_namespace"

View File

@@ -12,11 +12,23 @@ public class FakeFeatureFlagsImpl implements FeatureFlags \{
}
{{ for item in flag_elements}}
{{ if library_exported }}
{{ if item.exported }}
@Override
@UnsupportedAppUsage
public boolean {item.method_name}() \{
return getValue(Flags.FLAG_{item.flag_name_constant_suffix});
}
{{ endif }}
{{ else }}
@Override
@UnsupportedAppUsage
public boolean {item.method_name}() \{
return getValue(Flags.FLAG_{item.flag_name_constant_suffix});
}
{{ endif }}
{{ endfor}}
public void setFlag(String flagName, boolean value) \{
if (!this.mFlagMap.containsKey(flagName)) \{

View File

@@ -5,6 +5,15 @@ import android.compat.annotation.UnsupportedAppUsage;
/** @hide */
public interface FeatureFlags \{
{{ for item in flag_elements }}
{{ if library_exported }}
{{ if item.exported }}
@UnsupportedAppUsage
boolean {item.method_name}();
{{ endif }}
{{ else }}
{{ -if not item.is_read_write }}
{{ -if item.default_value }}
@com.android.aconfig.annotations.AssumeTrueForR8
@@ -14,5 +23,7 @@ public interface FeatureFlags \{
{{ endif }}
@UnsupportedAppUsage
boolean {item.method_name}();
{{ endif }}
{{ endfor }}
}

View File

@@ -14,9 +14,17 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
{{- endfor- }}
{{ for flag in flag_elements }}
{{ if library_exported }}
{{ if flag.exported }}
private static boolean {flag.method_name} = false;
{{ endif }}
{{ else }}
{{- if flag.is_read_write }}
private static boolean {flag.method_name} = {flag.default_value};
{{- endif- }}
{{ endif }}
{{ endfor }}
{{ for namespace_with_flags in namespace_flags }}
@@ -25,10 +33,21 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}");
{{- for flag in namespace_with_flags.flags }}
{{- if flag.is_read_write }}
{{ if library_exported }}
{{ if flag.exported }}
{flag.method_name} =
properties.getBoolean("{flag.device_config_flag}", false);
{{ endif }}
{{ else }}
{{ if flag.is_read_write }}
{flag.method_name} =
properties.getBoolean("{flag.device_config_flag}", {flag.default_value});
{{- endif- }}
{{ endif }}
{{ endif }}
{{ endfor }}
} catch (NullPointerException e) \{
throw new RuntimeException(
@@ -46,6 +65,9 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
{{ endif- }}
{{ for flag in flag_elements }}
{{ if library_exported }}
{{ if flag.exported }}
@Override
@UnsupportedAppUsage
public boolean {flag.method_name}() \{
@@ -58,6 +80,23 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
return {flag.default_value};
{{ endif- }}
}
{{ endif }}
{{ else }}
@Override
@UnsupportedAppUsage
public boolean {flag.method_name}() \{
{{ -if flag.is_read_write }}
if (!{flag.device_config_namespace}_is_cached) \{
load_overrides_{flag.device_config_namespace}();
}
return {flag.method_name};
{{ else }}
return {flag.default_value};
{{ endif- }}
}
{{ endif }}
{{ endfor }}
}
{{ else }}

View File

@@ -6,10 +6,28 @@ import android.compat.annotation.UnsupportedAppUsage;
/** @hide */
public final class Flags \{
{{- for item in flag_elements}}
{{ if library_exported }}
{{ if item.exported }}
/** @hide */
public static final String FLAG_{item.flag_name_constant_suffix} = "{item.device_config_flag}";
{{ endif }}
{{ else }}
/** @hide */
public static final String FLAG_{item.flag_name_constant_suffix} = "{item.device_config_flag}";
{{ endif }}
{{- endfor }}
{{ for item in flag_elements}}
{{ if library_exported }}
{{ if item.exported }}
@UnsupportedAppUsage
public static boolean {item.method_name}() \{
return FEATURE_FLAGS.{item.method_name}();
}
{{ endif }}
{{ else }}
{{ -if not item.is_read_write }}
{{ -if item.default_value }}
@com.android.aconfig.annotations.AssumeTrueForR8
@@ -21,6 +39,7 @@ public final class Flags \{
public static boolean {item.method_name}() \{
return FEATURE_FLAGS.{item.method_name}();
}
{{ endif }}
{{ endfor }}
{{ -if is_test_mode }}
public static void setFeatureFlags(FeatureFlags featureFlags) \{

View File

@@ -28,3 +28,9 @@ flag_value {
state: ENABLED
permission: READ_ONLY
}
flag_value {
package: "com.android.aconfig.test"
name: "disabled_rw_exported"
state: DISABLED
permission: READ_WRITE
}

View File

@@ -59,3 +59,11 @@ flag {
description: "This flag is DISABLED + READ_WRITE, and is defined in another namespace"
bug: "999"
}
flag {
name: "disabled_rw_exported"
namespace: "aconfig_test"
description: "This flag is exported"
bug: "111"
is_exported: true
}