Merge "Generate CustomFeatureFlags" into main
This commit is contained in:
@@ -63,21 +63,28 @@ where
|
|||||||
"FeatureFlags.java",
|
"FeatureFlags.java",
|
||||||
include_str!("../../templates/FeatureFlags.java.template"),
|
include_str!("../../templates/FeatureFlags.java.template"),
|
||||||
)?;
|
)?;
|
||||||
|
template.add_template(
|
||||||
|
"CustomFeatureFlags.java",
|
||||||
|
include_str!("../../templates/CustomFeatureFlags.java.template"),
|
||||||
|
)?;
|
||||||
template.add_template(
|
template.add_template(
|
||||||
"FakeFeatureFlagsImpl.java",
|
"FakeFeatureFlagsImpl.java",
|
||||||
include_str!("../../templates/FakeFeatureFlagsImpl.java.template"),
|
include_str!("../../templates/FakeFeatureFlagsImpl.java.template"),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let path: PathBuf = package.split('.').collect();
|
let path: PathBuf = package.split('.').collect();
|
||||||
["Flags.java", "FeatureFlags.java", "FeatureFlagsImpl.java", "FakeFeatureFlagsImpl.java"]
|
[
|
||||||
.iter()
|
"Flags.java",
|
||||||
.map(|file| {
|
"FeatureFlags.java",
|
||||||
Ok(OutputFile {
|
"FeatureFlagsImpl.java",
|
||||||
contents: template.render(file, &context)?.into(),
|
"CustomFeatureFlags.java",
|
||||||
path: path.join(file),
|
"FakeFeatureFlagsImpl.java",
|
||||||
})
|
]
|
||||||
})
|
.iter()
|
||||||
.collect::<Result<Vec<OutputFile>>>()
|
.map(|file| {
|
||||||
|
Ok(OutputFile { contents: template.render(file, &context)?.into(), path: path.join(file) })
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<OutputFile>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_flags_by_namespace(flags: &[FlagElement]) -> Vec<NamespaceFlags> {
|
fn gen_flags_by_namespace(flags: &[FlagElement]) -> Vec<NamespaceFlags> {
|
||||||
@@ -292,76 +299,82 @@ mod tests {
|
|||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#"
|
const EXPECTED_CUSTOMFEATUREFLAGS_CONTENT: &str = r#"
|
||||||
package com.android.aconfig.test;
|
package com.android.aconfig.test;
|
||||||
|
|
||||||
// TODO(b/303773055): Remove the annotation after access issue is resolved.
|
// TODO(b/303773055): Remove the annotation after access issue is resolved.
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class FakeFeatureFlagsImpl implements FeatureFlags {
|
public class CustomFeatureFlags implements FeatureFlags {
|
||||||
public FakeFeatureFlagsImpl() {
|
|
||||||
resetAll();
|
private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl;
|
||||||
|
|
||||||
|
public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) {
|
||||||
|
mGetValueImpl = getValueImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean disabledRo() {
|
public boolean disabledRo() {
|
||||||
return getValue(Flags.FLAG_DISABLED_RO);
|
return getValue(Flags.FLAG_DISABLED_RO,
|
||||||
|
FeatureFlags::disabledRo);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean disabledRw() {
|
public boolean disabledRw() {
|
||||||
return getValue(Flags.FLAG_DISABLED_RW);
|
return getValue(Flags.FLAG_DISABLED_RW,
|
||||||
|
FeatureFlags::disabledRw);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean disabledRwExported() {
|
public boolean disabledRwExported() {
|
||||||
return getValue(Flags.FLAG_DISABLED_RW_EXPORTED);
|
return getValue(Flags.FLAG_DISABLED_RW_EXPORTED,
|
||||||
|
FeatureFlags::disabledRwExported);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean disabledRwInOtherNamespace() {
|
public boolean disabledRwInOtherNamespace() {
|
||||||
return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE);
|
return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE,
|
||||||
|
FeatureFlags::disabledRwInOtherNamespace);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean enabledFixedRo() {
|
public boolean enabledFixedRo() {
|
||||||
return getValue(Flags.FLAG_ENABLED_FIXED_RO);
|
return getValue(Flags.FLAG_ENABLED_FIXED_RO,
|
||||||
|
FeatureFlags::enabledFixedRo);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean enabledFixedRoExported() {
|
public boolean enabledFixedRoExported() {
|
||||||
return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED);
|
return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED,
|
||||||
|
FeatureFlags::enabledFixedRoExported);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean enabledRo() {
|
public boolean enabledRo() {
|
||||||
return getValue(Flags.FLAG_ENABLED_RO);
|
return getValue(Flags.FLAG_ENABLED_RO,
|
||||||
|
FeatureFlags::enabledRo);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean enabledRoExported() {
|
public boolean enabledRoExported() {
|
||||||
return getValue(Flags.FLAG_ENABLED_RO_EXPORTED);
|
return getValue(Flags.FLAG_ENABLED_RO_EXPORTED,
|
||||||
|
FeatureFlags::enabledRoExported);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean enabledRw() {
|
public boolean enabledRw() {
|
||||||
return getValue(Flags.FLAG_ENABLED_RW);
|
return getValue(Flags.FLAG_ENABLED_RW,
|
||||||
}
|
FeatureFlags::enabledRw);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFlagReadOnlyOptimized(String flagName) {
|
public boolean isFlagReadOnlyOptimized(String flagName) {
|
||||||
if (mReadOnlyFlagsSet.contains(flagName) &&
|
if (mReadOnlyFlagsSet.contains(flagName) &&
|
||||||
isOptimizationEnabled()) {
|
isOptimizationEnabled()) {
|
||||||
@@ -369,30 +382,30 @@ mod tests {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@com.android.aconfig.annotations.AssumeTrueForR8
|
@com.android.aconfig.annotations.AssumeTrueForR8
|
||||||
private boolean isOptimizationEnabled() {
|
private boolean isOptimizationEnabled() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private boolean getValue(String flagName) {
|
|
||||||
Boolean value = this.mFlagMap.get(flagName);
|
protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) {
|
||||||
if (value == null) {
|
return mGetValueImpl.test(flagName, getter);
|
||||||
throw new IllegalArgumentException(flagName + " is not set");
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
private Map<String, Boolean> mFlagMap = new HashMap<>(
|
|
||||||
Map.ofEntries(
|
public List<String> getFlagNames() {
|
||||||
Map.entry(Flags.FLAG_DISABLED_RO, false),
|
return Arrays.asList(
|
||||||
Map.entry(Flags.FLAG_DISABLED_RW, false),
|
Flags.FLAG_DISABLED_RO,
|
||||||
Map.entry(Flags.FLAG_DISABLED_RW_EXPORTED, false),
|
Flags.FLAG_DISABLED_RW,
|
||||||
Map.entry(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false),
|
Flags.FLAG_DISABLED_RW_EXPORTED,
|
||||||
Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false),
|
Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE,
|
||||||
Map.entry(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, false),
|
Flags.FLAG_ENABLED_FIXED_RO,
|
||||||
Map.entry(Flags.FLAG_ENABLED_RO, false),
|
Flags.FLAG_ENABLED_FIXED_RO_EXPORTED,
|
||||||
Map.entry(Flags.FLAG_ENABLED_RO_EXPORTED, false),
|
Flags.FLAG_ENABLED_RO,
|
||||||
Map.entry(Flags.FLAG_ENABLED_RW, false)
|
Flags.FLAG_ENABLED_RO_EXPORTED,
|
||||||
)
|
Flags.FLAG_ENABLED_RW
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private Set<String> mReadOnlyFlagsSet = new HashSet<>(
|
private Set<String> mReadOnlyFlagsSet = new HashSet<>(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
Flags.FLAG_DISABLED_RO,
|
Flags.FLAG_DISABLED_RO,
|
||||||
@@ -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]
|
#[test]
|
||||||
fn test_generate_java_code_production() {
|
fn test_generate_java_code_production() {
|
||||||
let parsed_flags = crate::test::parse_test_flags();
|
let parsed_flags = crate::test::parse_test_flags();
|
||||||
@@ -548,6 +604,10 @@ mod tests {
|
|||||||
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
|
("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),
|
||||||
("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_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",
|
"com/android/aconfig/test/FakeFeatureFlagsImpl.java",
|
||||||
EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
|
EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
|
||||||
@@ -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;
|
package com.android.aconfig.test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class FakeFeatureFlagsImpl implements FeatureFlags {
|
public class CustomFeatureFlags implements FeatureFlags {
|
||||||
public FakeFeatureFlagsImpl() {
|
|
||||||
resetAll();
|
private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl;
|
||||||
|
|
||||||
|
public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) {
|
||||||
|
mGetValueImpl = getValueImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean disabledRwExported() {
|
public boolean disabledRwExported() {
|
||||||
return getValue(Flags.FLAG_DISABLED_RW_EXPORTED);
|
return getValue(Flags.FLAG_DISABLED_RW_EXPORTED,
|
||||||
|
FeatureFlags::disabledRwExported);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean enabledFixedRoExported() {
|
public boolean enabledFixedRoExported() {
|
||||||
return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED);
|
return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED,
|
||||||
|
FeatureFlags::enabledFixedRoExported);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean enabledRoExported() {
|
public boolean enabledRoExported() {
|
||||||
return getValue(Flags.FLAG_ENABLED_RO_EXPORTED);
|
return getValue(Flags.FLAG_ENABLED_RO_EXPORTED,
|
||||||
|
FeatureFlags::enabledRoExported);
|
||||||
}
|
}
|
||||||
public void setFlag(String flagName, boolean value) {
|
|
||||||
if (!this.mFlagMap.containsKey(flagName)) {
|
protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) {
|
||||||
throw new IllegalArgumentException("no such flag " + flagName);
|
return mGetValueImpl.test(flagName, getter);
|
||||||
}
|
|
||||||
this.mFlagMap.put(flagName, value);
|
|
||||||
}
|
}
|
||||||
public void resetAll() {
|
|
||||||
for (Map.Entry entry : mFlagMap.entrySet()) {
|
public List<String> getFlagNames() {
|
||||||
entry.setValue(null);
|
return Arrays.asList(
|
||||||
}
|
Flags.FLAG_DISABLED_RW_EXPORTED,
|
||||||
|
Flags.FLAG_ENABLED_FIXED_RO_EXPORTED,
|
||||||
|
Flags.FLAG_ENABLED_RO_EXPORTED
|
||||||
|
);
|
||||||
}
|
}
|
||||||
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_RW_EXPORTED, false),
|
|
||||||
Map.entry(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, false),
|
|
||||||
Map.entry(Flags.FLAG_ENABLED_RO_EXPORTED, false)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
private Set<String> mReadOnlyFlagsSet = new HashSet<>(
|
private Set<String> mReadOnlyFlagsSet = new HashSet<>(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
""
|
""
|
||||||
@@ -732,9 +790,13 @@ mod tests {
|
|||||||
("com/android/aconfig/test/Flags.java", expect_flags_content),
|
("com/android/aconfig/test/Flags.java", expect_flags_content),
|
||||||
("com/android/aconfig/test/FeatureFlags.java", expect_feature_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/FeatureFlagsImpl.java", expect_feature_flags_impl_content),
|
||||||
|
(
|
||||||
|
"com/android/aconfig/test/CustomFeatureFlags.java",
|
||||||
|
expect_custom_feature_flags_content,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"com/android/aconfig/test/FakeFeatureFlagsImpl.java",
|
"com/android/aconfig/test/FakeFeatureFlagsImpl.java",
|
||||||
expect_fake_feature_flags_impl_content,
|
EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -853,6 +915,10 @@ mod tests {
|
|||||||
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
|
("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/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
|
||||||
("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_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",
|
"com/android/aconfig/test/FakeFeatureFlagsImpl.java",
|
||||||
EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
|
EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
|
||||||
@@ -1020,61 +1086,64 @@ mod tests {
|
|||||||
private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
|
private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
let expect_fakefeatureflags_content = r#"
|
let expect_customfeatureflags_content = r#"
|
||||||
package com.android.aconfig.test;
|
package com.android.aconfig.test;
|
||||||
|
|
||||||
// TODO(b/303773055): Remove the annotation after access issue is resolved.
|
// TODO(b/303773055): Remove the annotation after access issue is resolved.
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class FakeFeatureFlagsImpl implements FeatureFlags {
|
public class CustomFeatureFlags implements FeatureFlags {
|
||||||
public FakeFeatureFlagsImpl() {
|
|
||||||
resetAll();
|
private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl;
|
||||||
|
|
||||||
|
public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) {
|
||||||
|
mGetValueImpl = getValueImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean disabledRo() {
|
public boolean disabledRo() {
|
||||||
return getValue(Flags.FLAG_DISABLED_RO);
|
return getValue(Flags.FLAG_DISABLED_RO,
|
||||||
|
FeatureFlags::disabledRo);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean disabledRw() {
|
public boolean disabledRw() {
|
||||||
return getValue(Flags.FLAG_DISABLED_RW);
|
return getValue(Flags.FLAG_DISABLED_RW,
|
||||||
|
FeatureFlags::disabledRw);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean disabledRwInOtherNamespace() {
|
public boolean disabledRwInOtherNamespace() {
|
||||||
return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE);
|
return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE,
|
||||||
|
FeatureFlags::disabledRwInOtherNamespace);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean enabledFixedRo() {
|
public boolean enabledFixedRo() {
|
||||||
return getValue(Flags.FLAG_ENABLED_FIXED_RO);
|
return getValue(Flags.FLAG_ENABLED_FIXED_RO,
|
||||||
|
FeatureFlags::enabledFixedRo);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean enabledRo() {
|
public boolean enabledRo() {
|
||||||
return getValue(Flags.FLAG_ENABLED_RO);
|
return getValue(Flags.FLAG_ENABLED_RO,
|
||||||
|
FeatureFlags::enabledRo);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public boolean enabledRw() {
|
public boolean enabledRw() {
|
||||||
return getValue(Flags.FLAG_ENABLED_RW);
|
return getValue(Flags.FLAG_ENABLED_RW,
|
||||||
}
|
FeatureFlags::enabledRw);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFlagReadOnlyOptimized(String flagName) {
|
public boolean isFlagReadOnlyOptimized(String flagName) {
|
||||||
if (mReadOnlyFlagsSet.contains(flagName) &&
|
if (mReadOnlyFlagsSet.contains(flagName) &&
|
||||||
isOptimizationEnabled()) {
|
isOptimizationEnabled()) {
|
||||||
@@ -1082,27 +1151,27 @@ mod tests {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@com.android.aconfig.annotations.AssumeTrueForR8
|
@com.android.aconfig.annotations.AssumeTrueForR8
|
||||||
private boolean isOptimizationEnabled() {
|
private boolean isOptimizationEnabled() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private boolean getValue(String flagName) {
|
|
||||||
Boolean value = this.mFlagMap.get(flagName);
|
protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) {
|
||||||
if (value == null) {
|
return mGetValueImpl.test(flagName, getter);
|
||||||
throw new IllegalArgumentException(flagName + " is not set");
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
private Map<String, Boolean> mFlagMap = new HashMap<>(
|
|
||||||
Map.ofEntries(
|
public List<String> getFlagNames() {
|
||||||
Map.entry(Flags.FLAG_DISABLED_RO, false),
|
return Arrays.asList(
|
||||||
Map.entry(Flags.FLAG_DISABLED_RW, false),
|
Flags.FLAG_DISABLED_RO,
|
||||||
Map.entry(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false),
|
Flags.FLAG_DISABLED_RW,
|
||||||
Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false),
|
Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE,
|
||||||
Map.entry(Flags.FLAG_ENABLED_RO, false),
|
Flags.FLAG_ENABLED_FIXED_RO,
|
||||||
Map.entry(Flags.FLAG_ENABLED_RW, false)
|
Flags.FLAG_ENABLED_RO,
|
||||||
)
|
Flags.FLAG_ENABLED_RW
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private Set<String> mReadOnlyFlagsSet = new HashSet<>(
|
private Set<String> mReadOnlyFlagsSet = new HashSet<>(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
Flags.FLAG_DISABLED_RO,
|
Flags.FLAG_DISABLED_RO,
|
||||||
@@ -1116,11 +1185,16 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let mut file_set = HashMap::from([
|
let mut file_set = HashMap::from([
|
||||||
("com/android/aconfig/test/Flags.java", expect_flags_content),
|
("com/android/aconfig/test/Flags.java", expect_flags_content),
|
||||||
("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
|
("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
|
||||||
("com/android/aconfig/test/FeatureFlags.java", expect_featureflags_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 {
|
for file in generated_files {
|
||||||
|
@@ -0,0 +1,70 @@
|
|||||||
|
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 #}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
@@ -1,27 +1,30 @@
|
|||||||
package {package_name};
|
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.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class FakeFeatureFlagsImpl implements FeatureFlags \{
|
public class FakeFeatureFlagsImpl extends CustomFeatureFlags \{
|
||||||
|
private Map<String, Boolean> mFlagMap = new HashMap<>();
|
||||||
|
|
||||||
public FakeFeatureFlagsImpl() \{
|
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
|
@Override
|
||||||
{{ if not library_exported }} @UnsupportedAppUsage{{ -endif }}
|
protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) \{
|
||||||
public boolean {item.method_name}() \{
|
Boolean value = this.mFlagMap.get(flagName);
|
||||||
return getValue(Flags.FLAG_{item.flag_name_constant_suffix});
|
if (value == null) \{
|
||||||
|
throw new IllegalArgumentException(flagName + " is not set");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
{{ endfor}}
|
|
||||||
public void setFlag(String flagName, boolean value) \{
|
public void setFlag(String flagName, boolean value) \{
|
||||||
if (!this.mFlagMap.containsKey(flagName)) \{
|
if (!this.mFlagMap.containsKey(flagName)) \{
|
||||||
throw new IllegalArgumentException("no such flag " + flagName);
|
throw new IllegalArgumentException("no such flag " + flagName);
|
||||||
@@ -34,46 +37,4 @@ public class FakeFeatureFlagsImpl implements FeatureFlags \{
|
|||||||
entry.setValue(null);
|
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 #}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user