aconfig: add fixed read only flag
Add a new field in the declaration to indicate whether the permission can be overridden. When the field “is_fixed_read_only” is set to true, the flag permission will be set as fixed “READ_ONLY”, and the permission should not be changed by Gantry. Bug: 292521627 Test: atest aconfig.test Change-Id: Ic9bcd7823bccb8b947cf05568c7ced3763490a23
This commit is contained in:
parent
07c4b5c0f2
commit
71f1b35fb4
10 changed files with 236 additions and 4 deletions
|
@ -39,6 +39,7 @@ message flag_declaration {
|
|||
optional string namespace = 2;
|
||||
optional string description = 3;
|
||||
repeated string bug = 4;
|
||||
optional bool is_fixed_read_only = 5;
|
||||
};
|
||||
|
||||
message flag_declarations {
|
||||
|
@ -75,6 +76,7 @@ message parsed_flag {
|
|||
optional flag_state state = 6;
|
||||
optional flag_permission permission = 7;
|
||||
repeated tracepoint trace = 8;
|
||||
optional bool is_fixed_read_only = 9;
|
||||
}
|
||||
|
||||
message parsed_flags {
|
||||
|
|
|
@ -131,6 +131,8 @@ public:
|
|||
|
||||
virtual bool disabled_rw() = 0;
|
||||
|
||||
virtual bool enabled_fixed_ro() = 0;
|
||||
|
||||
virtual bool enabled_ro() = 0;
|
||||
|
||||
virtual bool enabled_rw() = 0;
|
||||
|
@ -146,6 +148,10 @@ inline bool disabled_rw() {
|
|||
return provider_->disabled_rw();
|
||||
}
|
||||
|
||||
inline bool enabled_fixed_ro() {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool enabled_ro() {
|
||||
return true;
|
||||
}
|
||||
|
@ -163,6 +169,8 @@ bool com_android_aconfig_test_disabled_ro();
|
|||
|
||||
bool com_android_aconfig_test_disabled_rw();
|
||||
|
||||
bool com_android_aconfig_test_enabled_fixed_ro();
|
||||
|
||||
bool com_android_aconfig_test_enabled_ro();
|
||||
|
||||
bool com_android_aconfig_test_enabled_rw();
|
||||
|
@ -194,6 +202,10 @@ public:
|
|||
|
||||
virtual void disabled_rw(bool val) = 0;
|
||||
|
||||
virtual bool enabled_fixed_ro() = 0;
|
||||
|
||||
virtual void enabled_fixed_ro(bool val) = 0;
|
||||
|
||||
virtual bool enabled_ro() = 0;
|
||||
|
||||
virtual void enabled_ro(bool val) = 0;
|
||||
|
@ -223,6 +235,14 @@ inline void disabled_rw(bool val) {
|
|||
provider_->disabled_rw(val);
|
||||
}
|
||||
|
||||
inline bool enabled_fixed_ro() {
|
||||
return provider_->enabled_fixed_ro();
|
||||
}
|
||||
|
||||
inline void enabled_fixed_ro(bool val) {
|
||||
provider_->enabled_fixed_ro(val);
|
||||
}
|
||||
|
||||
inline bool enabled_ro() {
|
||||
return provider_->enabled_ro();
|
||||
}
|
||||
|
@ -256,6 +276,10 @@ bool com_android_aconfig_test_disabled_rw();
|
|||
|
||||
void set_com_android_aconfig_test_disabled_rw(bool val);
|
||||
|
||||
bool com_android_aconfig_test_enabled_fixed_ro();
|
||||
|
||||
void set_com_android_aconfig_test_enabled_fixed_ro(bool val);
|
||||
|
||||
bool com_android_aconfig_test_enabled_ro();
|
||||
|
||||
void set_com_android_aconfig_test_enabled_ro(bool val);
|
||||
|
@ -294,6 +318,10 @@ namespace com::android::aconfig::test {
|
|||
"false") == "true";
|
||||
}
|
||||
|
||||
virtual bool enabled_fixed_ro() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool enabled_ro() override {
|
||||
return true;
|
||||
}
|
||||
|
@ -319,6 +347,10 @@ bool com_android_aconfig_test_disabled_rw() {
|
|||
return com::android::aconfig::test::disabled_rw();
|
||||
}
|
||||
|
||||
bool com_android_aconfig_test_enabled_fixed_ro() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool com_android_aconfig_test_enabled_ro() {
|
||||
return true;
|
||||
}
|
||||
|
@ -373,6 +405,19 @@ namespace com::android::aconfig::test {
|
|||
overrides_["disabled_rw"] = val;
|
||||
}
|
||||
|
||||
virtual bool enabled_fixed_ro() override {
|
||||
auto it = overrides_.find("enabled_fixed_ro");
|
||||
if (it != overrides_.end()) {
|
||||
return it->second;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void enabled_fixed_ro(bool val) override {
|
||||
overrides_["enabled_fixed_ro"] = val;
|
||||
}
|
||||
|
||||
virtual bool enabled_ro() override {
|
||||
auto it = overrides_.find("enabled_ro");
|
||||
if (it != overrides_.end()) {
|
||||
|
@ -402,7 +447,6 @@ namespace com::android::aconfig::test {
|
|||
overrides_["enabled_rw"] = val;
|
||||
}
|
||||
|
||||
|
||||
virtual void reset_flags() override {
|
||||
overrides_.clear();
|
||||
}
|
||||
|
@ -430,6 +474,16 @@ void set_com_android_aconfig_test_disabled_rw(bool val) {
|
|||
com::android::aconfig::test::disabled_rw(val);
|
||||
}
|
||||
|
||||
|
||||
bool com_android_aconfig_test_enabled_fixed_ro() {
|
||||
return com::android::aconfig::test::enabled_fixed_ro();
|
||||
}
|
||||
|
||||
void set_com_android_aconfig_test_enabled_fixed_ro(bool val) {
|
||||
com::android::aconfig::test::enabled_fixed_ro(val);
|
||||
}
|
||||
|
||||
|
||||
bool com_android_aconfig_test_enabled_ro() {
|
||||
return com::android::aconfig::test::enabled_ro();
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ mod tests {
|
|||
public interface FeatureFlags {
|
||||
boolean disabledRo();
|
||||
boolean disabledRw();
|
||||
boolean enabledFixedRo();
|
||||
boolean enabledRo();
|
||||
boolean enabledRw();
|
||||
"#;
|
||||
|
@ -130,6 +131,7 @@ mod tests {
|
|||
public final class Flags {
|
||||
public static final String FLAG_DISABLED_RO = "com.android.aconfig.test.disabled_ro";
|
||||
public static final String FLAG_DISABLED_RW = "com.android.aconfig.test.disabled_rw";
|
||||
public static final String FLAG_ENABLED_FIXED_RO = "com.android.aconfig.test.enabled_fixed_ro";
|
||||
public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro";
|
||||
public static final String FLAG_ENABLED_RW = "com.android.aconfig.test.enabled_rw";
|
||||
|
||||
|
@ -139,6 +141,9 @@ mod tests {
|
|||
public static boolean disabledRw() {
|
||||
return FEATURE_FLAGS.disabledRw();
|
||||
}
|
||||
public static boolean enabledFixedRo() {
|
||||
return FEATURE_FLAGS.enabledFixedRo();
|
||||
}
|
||||
public static boolean enabledRo() {
|
||||
return FEATURE_FLAGS.enabledRo();
|
||||
}
|
||||
|
@ -159,6 +164,11 @@ mod tests {
|
|||
"Method is not implemented.");
|
||||
}
|
||||
@Override
|
||||
public boolean enabledFixedRo() {
|
||||
throw new UnsupportedOperationException(
|
||||
"Method is not implemented.");
|
||||
}
|
||||
@Override
|
||||
public boolean enabledRo() {
|
||||
throw new UnsupportedOperationException(
|
||||
"Method is not implemented.");
|
||||
|
@ -211,6 +221,10 @@ mod tests {
|
|||
);
|
||||
}
|
||||
@Override
|
||||
public boolean enabledFixedRo() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean enabledRo() {
|
||||
return true;
|
||||
}
|
||||
|
@ -311,6 +325,10 @@ mod tests {
|
|||
return getFlag(Flags.FLAG_DISABLED_RW);
|
||||
}
|
||||
@Override
|
||||
public boolean enabledFixedRo() {
|
||||
return getFlag(Flags.FLAG_ENABLED_FIXED_RO);
|
||||
}
|
||||
@Override
|
||||
public boolean enabledRo() {
|
||||
return getFlag(Flags.FLAG_ENABLED_RO);
|
||||
}
|
||||
|
@ -341,6 +359,7 @@ mod tests {
|
|||
private HashMap<String, Boolean> mFlagMap = Stream.of(
|
||||
Flags.FLAG_DISABLED_RO,
|
||||
Flags.FLAG_DISABLED_RW,
|
||||
Flags.FLAG_ENABLED_FIXED_RO,
|
||||
Flags.FLAG_ENABLED_RO,
|
||||
Flags.FLAG_ENABLED_RW
|
||||
)
|
||||
|
|
|
@ -108,6 +108,11 @@ impl FlagProvider {
|
|||
"false") == "true"
|
||||
}
|
||||
|
||||
/// query flag enabled_fixed_ro
|
||||
pub fn enabled_fixed_ro(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// query flag enabled_ro
|
||||
pub fn enabled_ro(&self) -> bool {
|
||||
true
|
||||
|
@ -137,6 +142,12 @@ pub fn disabled_rw() -> bool {
|
|||
PROVIDER.disabled_rw()
|
||||
}
|
||||
|
||||
/// query flag enabled_fixed_ro
|
||||
#[inline(always)]
|
||||
pub fn enabled_fixed_ro() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// query flag enabled_ro
|
||||
#[inline(always)]
|
||||
pub fn enabled_ro() -> bool {
|
||||
|
@ -189,6 +200,18 @@ impl FlagProvider {
|
|||
self.overrides.insert("disabled_rw", val);
|
||||
}
|
||||
|
||||
/// query flag enabled_fixed_ro
|
||||
pub fn enabled_fixed_ro(&self) -> bool {
|
||||
self.overrides.get("enabled_fixed_ro").copied().unwrap_or(
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
/// set flag enabled_fixed_ro
|
||||
pub fn set_enabled_fixed_ro(&mut self, val: bool) {
|
||||
self.overrides.insert("enabled_fixed_ro", val);
|
||||
}
|
||||
|
||||
/// query flag enabled_ro
|
||||
pub fn enabled_ro(&self) -> bool {
|
||||
self.overrides.get("enabled_ro").copied().unwrap_or(
|
||||
|
@ -251,6 +274,18 @@ pub fn set_disabled_rw(val: bool) {
|
|||
PROVIDER.lock().unwrap().set_disabled_rw(val);
|
||||
}
|
||||
|
||||
/// query flag enabled_fixed_ro
|
||||
#[inline(always)]
|
||||
pub fn enabled_fixed_ro() -> bool {
|
||||
PROVIDER.lock().unwrap().enabled_fixed_ro()
|
||||
}
|
||||
|
||||
/// set flag enabled_fixed_ro
|
||||
#[inline(always)]
|
||||
pub fn set_enabled_fixed_ro(val: bool) {
|
||||
PROVIDER.lock().unwrap().set_enabled_fixed_ro(val);
|
||||
}
|
||||
|
||||
/// query flag enabled_ro
|
||||
#[inline(always)]
|
||||
pub fn enabled_ro() -> bool {
|
||||
|
|
|
@ -91,11 +91,17 @@ pub fn parse_flags(
|
|||
parsed_flag.set_description(flag_declaration.take_description());
|
||||
parsed_flag.bug.append(&mut flag_declaration.bug);
|
||||
parsed_flag.set_state(DEFAULT_FLAG_STATE);
|
||||
parsed_flag.set_permission(default_permission);
|
||||
let flag_permission = if flag_declaration.is_fixed_read_only() {
|
||||
ProtoFlagPermission::READ_ONLY
|
||||
} else {
|
||||
default_permission
|
||||
};
|
||||
parsed_flag.set_permission(flag_permission);
|
||||
parsed_flag.set_is_fixed_read_only(flag_declaration.is_fixed_read_only());
|
||||
let mut tracepoint = ProtoTracepoint::new();
|
||||
tracepoint.set_source(input.source.clone());
|
||||
tracepoint.set_state(DEFAULT_FLAG_STATE);
|
||||
tracepoint.set_permission(default_permission);
|
||||
tracepoint.set_permission(flag_permission);
|
||||
parsed_flag.trace.push(tracepoint);
|
||||
|
||||
// verify ParsedFlag looks reasonable
|
||||
|
@ -135,6 +141,13 @@ pub fn parse_flags(
|
|||
continue;
|
||||
};
|
||||
|
||||
ensure!(
|
||||
!parsed_flag.is_fixed_read_only()
|
||||
|| flag_value.permission() == ProtoFlagPermission::READ_ONLY,
|
||||
"failed to set permission of flag {}, since this flag is fixed read only flag",
|
||||
flag_value.name()
|
||||
);
|
||||
|
||||
parsed_flag.set_state(flag_value.state());
|
||||
parsed_flag.set_permission(flag_value.permission());
|
||||
let mut tracepoint = ProtoTracepoint::new();
|
||||
|
@ -310,6 +323,7 @@ mod tests {
|
|||
assert_eq!(ProtoFlagState::ENABLED, enabled_ro.state());
|
||||
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.permission());
|
||||
assert_eq!(3, enabled_ro.trace.len());
|
||||
assert!(!enabled_ro.is_fixed_read_only());
|
||||
assert_eq!("tests/test.aconfig", enabled_ro.trace[0].source());
|
||||
assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[0].state());
|
||||
assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[0].permission());
|
||||
|
@ -320,8 +334,11 @@ mod tests {
|
|||
assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
|
||||
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
|
||||
|
||||
assert_eq!(4, parsed_flags.parsed_flag.len());
|
||||
assert_eq!(5, parsed_flags.parsed_flag.len());
|
||||
for pf in parsed_flags.parsed_flag.iter() {
|
||||
if pf.name() == "enabled_fixed_ro" {
|
||||
continue;
|
||||
}
|
||||
let first = pf.trace.first().unwrap();
|
||||
assert_eq!(DEFAULT_FLAG_STATE, first.state());
|
||||
assert_eq!(DEFAULT_FLAG_PERMISSION, first.permission());
|
||||
|
@ -330,6 +347,15 @@ mod tests {
|
|||
assert_eq!(pf.state(), last.state());
|
||||
assert_eq!(pf.permission(), last.permission());
|
||||
}
|
||||
|
||||
let enabled_fixed_ro =
|
||||
parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_fixed_ro").unwrap();
|
||||
assert!(enabled_fixed_ro.is_fixed_read_only());
|
||||
assert_eq!(ProtoFlagState::ENABLED, enabled_fixed_ro.state());
|
||||
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.permission());
|
||||
assert_eq!(2, enabled_fixed_ro.trace.len());
|
||||
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[0].permission());
|
||||
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[1].permission());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -362,6 +388,46 @@ mod tests {
|
|||
assert_eq!(ProtoFlagPermission::READ_ONLY, parsed_flag.permission());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_flags_override_fixed_read_only() {
|
||||
let first_flag = r#"
|
||||
package: "com.first"
|
||||
flag {
|
||||
name: "first"
|
||||
namespace: "first_ns"
|
||||
description: "This is the description of the first flag."
|
||||
bug: "123"
|
||||
is_fixed_read_only: true
|
||||
}
|
||||
"#;
|
||||
let declaration =
|
||||
vec![Input { source: "memory".to_string(), reader: Box::new(first_flag.as_bytes()) }];
|
||||
|
||||
let first_flag_value = r#"
|
||||
flag_value {
|
||||
package: "com.first"
|
||||
name: "first"
|
||||
state: DISABLED
|
||||
permission: READ_WRITE
|
||||
}
|
||||
"#;
|
||||
let value = vec![Input {
|
||||
source: "memory".to_string(),
|
||||
reader: Box::new(first_flag_value.as_bytes()),
|
||||
}];
|
||||
let error = crate::commands::parse_flags(
|
||||
"com.first",
|
||||
declaration,
|
||||
value,
|
||||
ProtoFlagPermission::READ_WRITE,
|
||||
)
|
||||
.unwrap_err();
|
||||
assert_eq!(
|
||||
format!("{:?}", error),
|
||||
"failed to set permission of flag first, since this flag is fixed read only flag"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_device_config_defaults() {
|
||||
let input = parse_test_flags_as_input();
|
||||
|
|
|
@ -303,6 +303,7 @@ flag {
|
|||
namespace: "second_ns"
|
||||
description: "This is the description of the second flag."
|
||||
bug: "abc"
|
||||
is_fixed_read_only: true
|
||||
}
|
||||
"#,
|
||||
)
|
||||
|
@ -313,11 +314,13 @@ flag {
|
|||
assert_eq!(first.namespace(), "first_ns");
|
||||
assert_eq!(first.description(), "This is the description of the first flag.");
|
||||
assert_eq!(first.bug, vec!["123"]);
|
||||
assert!(!first.is_fixed_read_only());
|
||||
let second = flag_declarations.flag.iter().find(|pf| pf.name() == "second").unwrap();
|
||||
assert_eq!(second.name(), "second");
|
||||
assert_eq!(second.namespace(), "second_ns");
|
||||
assert_eq!(second.description(), "This is the description of the second flag.");
|
||||
assert_eq!(second.bug, vec!["abc"]);
|
||||
assert!(second.is_fixed_read_only());
|
||||
|
||||
// bad input: missing package in flag declarations
|
||||
let error = flag_declarations::try_from_text_proto(
|
||||
|
@ -555,6 +558,7 @@ parsed_flag {
|
|||
state: ENABLED
|
||||
permission: READ_WRITE
|
||||
}
|
||||
is_fixed_read_only: true
|
||||
}
|
||||
"#;
|
||||
let parsed_flags = try_from_binary_proto_from_text_proto(text_proto).unwrap();
|
||||
|
@ -574,6 +578,7 @@ parsed_flag {
|
|||
assert_eq!(second.trace[1].source(), "flags.values");
|
||||
assert_eq!(second.trace[1].state(), ProtoFlagState::ENABLED);
|
||||
assert_eq!(second.trace[1].permission(), ProtoFlagPermission::READ_WRITE);
|
||||
assert!(second.is_fixed_read_only());
|
||||
|
||||
// valid input: empty
|
||||
let parsed_flags = try_from_binary_proto_from_text_proto("").unwrap();
|
||||
|
|
|
@ -41,6 +41,7 @@ parsed_flag {
|
|||
state: DISABLED
|
||||
permission: READ_ONLY
|
||||
}
|
||||
is_fixed_read_only: false
|
||||
}
|
||||
parsed_flag {
|
||||
package: "com.android.aconfig.test"
|
||||
|
@ -55,6 +56,27 @@ parsed_flag {
|
|||
state: DISABLED
|
||||
permission: READ_WRITE
|
||||
}
|
||||
is_fixed_read_only: false
|
||||
}
|
||||
parsed_flag {
|
||||
package: "com.android.aconfig.test"
|
||||
name: "enabled_fixed_ro"
|
||||
namespace: "aconfig_test"
|
||||
description: "This flag is fixed READ_ONLY + ENABLED"
|
||||
bug: ""
|
||||
state: ENABLED
|
||||
permission: READ_ONLY
|
||||
trace {
|
||||
source: "tests/test.aconfig"
|
||||
state: DISABLED
|
||||
permission: READ_ONLY
|
||||
}
|
||||
trace {
|
||||
source: "tests/first.values"
|
||||
state: ENABLED
|
||||
permission: READ_ONLY
|
||||
}
|
||||
is_fixed_read_only: true
|
||||
}
|
||||
parsed_flag {
|
||||
package: "com.android.aconfig.test"
|
||||
|
@ -79,6 +101,7 @@ parsed_flag {
|
|||
state: ENABLED
|
||||
permission: READ_ONLY
|
||||
}
|
||||
is_fixed_read_only: false
|
||||
}
|
||||
parsed_flag {
|
||||
package: "com.android.aconfig.test"
|
||||
|
@ -98,6 +121,7 @@ parsed_flag {
|
|||
state: ENABLED
|
||||
permission: READ_WRITE
|
||||
}
|
||||
is_fixed_read_only: false
|
||||
}
|
||||
"#;
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import static com.android.aconfig.test.Flags.FLAG_DISABLED_RO;
|
||||
import static com.android.aconfig.test.Flags.FLAG_DISABLED_RW;
|
||||
import static com.android.aconfig.test.Flags.FLAG_ENABLED_FIXED_RO;
|
||||
import static com.android.aconfig.test.Flags.FLAG_ENABLED_RO;
|
||||
import static com.android.aconfig.test.Flags.FLAG_ENABLED_RW;
|
||||
import static com.android.aconfig.test.Flags.disabledRo;
|
||||
import static com.android.aconfig.test.Flags.disabledRw;
|
||||
import static com.android.aconfig.test.Flags.enabledFixedRo;
|
||||
import static com.android.aconfig.test.Flags.enabledRo;
|
||||
import static com.android.aconfig.test.Flags.enabledRw;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -34,6 +36,14 @@ public final class AconfigTest {
|
|||
assertFalse(enabledRo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnabledFixedReadOnlyFlag() {
|
||||
assertEquals("com.android.aconfig.test.enabled_fixed_ro", FLAG_ENABLED_FIXED_RO);
|
||||
// TODO: change to assertTrue(enabledFixedRo()) when the build supports reading tests/*.values
|
||||
// (currently all flags are assigned the default READ_ONLY + DISABLED)
|
||||
assertFalse(enabledFixedRo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisabledReadWriteFlag() {
|
||||
assertEquals("com.android.aconfig.test.enabled_ro", FLAG_ENABLED_RO);
|
||||
|
|
|
@ -16,3 +16,9 @@ flag_value {
|
|||
state: ENABLED
|
||||
permission: READ_WRITE
|
||||
}
|
||||
flag_value {
|
||||
package: "com.android.aconfig.test"
|
||||
name: "enabled_fixed_ro"
|
||||
state: ENABLED
|
||||
permission: READ_ONLY
|
||||
}
|
||||
|
|
|
@ -40,3 +40,14 @@ flag {
|
|||
description: "This flag is DISABLED + READ_WRITE"
|
||||
bug: "456"
|
||||
}
|
||||
|
||||
# This flag's final value calculated from:
|
||||
# - test.aconfig: DISABLED + READ_ONLY
|
||||
# - first.values: ENABLED + READ_ONLY
|
||||
flag {
|
||||
name: "enabled_fixed_ro"
|
||||
namespace: "aconfig_test"
|
||||
description: "This flag is fixed READ_ONLY + ENABLED"
|
||||
bug: ""
|
||||
is_fixed_read_only: true
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue