Loading tools/aconfig/aconfig_protos/protos/aconfig.proto +67 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,19 @@ syntax = "proto2"; package android.aconfig; // This protobuf file defines messages used to represent and manage flags in the "aconfig" system // The following format requirements apply across various message fields: // # name: a lowercase string in snake_case format, no consecutive underscores, and no leading digit // For example adjust_rate is a valid name, while AdjustRate, adjust__rate, and // 2adjust_rate are invalid // // # namespace: a lowercase string in snake_case format, no consecutive underscores, and no leading // digit. For example android_bar_system // // # package: lowercase strings in snake_case format, delimited by dots, no consecutive underscores // and no leading digit in each string. For example com.android.mypackage is a valid name // while com.android.myPackage, com.android.1mypackage are invalid // messages used in both aconfig input and output enum flag_state { Loading @@ -35,12 +48,30 @@ enum flag_permission { // aconfig input messages: flag declarations and values message flag_declaration { // Name of the flag (required) // See # name for format detail optional string name = 1; // Namespace the flag belongs to (required) // See # namespace for format detail optional string namespace = 2; // Textual description of the flag's purpose (required) optional string description = 3; // Single bug id related to the flag (required) repeated string bug = 4; // Indicates if the flag is permanently read-only and cannot be changed // via release configs (optional) // Default value false optional bool is_fixed_read_only = 5; // Indicates if the flag is exported and accessible beyond its originating container (optional) // Default value false optional bool is_exported = 6; // Additional information about the flag, including its purpose and form factors (optional) optional flag_metadata metadata = 7; }; Loading @@ -59,14 +90,26 @@ message flag_metadata { } message flag_declarations { // Package to which the flag belongs (required) // See # package for format detail optional string package = 1; // List of flag_declaration objects (required) repeated flag_declaration flag = 2; // Container the flag belongs to (optional) optional string container = 3; }; message flag_value { // Package to which the flag belongs (required) // See # package for format detail optional string package = 1; // Name of the flag (required) // See # name for format detail optional string name = 2; optional flag_state state = 3; optional flag_permission permission = 4; }; Loading @@ -85,17 +128,41 @@ message tracepoint { } message parsed_flag { // Package to which the flag belongs (required) // See # package for format detail optional string package = 1; // Name of the flag (required) // See # name for format detail optional string name = 2; // Namespace the flag belongs to (required) // See # namespace for format detail optional string namespace = 3; // Textual description of the flag's purpose (required) optional string description = 4; // Single bug id related to the flag (required) repeated string bug = 5; optional flag_state state = 6; optional flag_permission permission = 7; repeated tracepoint trace = 8; // Indicates if the flag is permanently read-only and cannot be changed // via release configs (optional) // Default value false optional bool is_fixed_read_only = 9; // Indicates if the flag is exported and accessible beyond its originating container (optional) // Default value false optional bool is_exported = 10; // Container the flag belongs to (optional) optional string container = 11; // Additional information about the flag, including its purpose and form factors (optional) optional flag_metadata metadata = 12; } Loading tools/aconfig/aconfig_protos/src/lib.rs +51 −9 Original line number Diff line number Diff line Loading @@ -69,6 +69,9 @@ pub use auto_generated::*; use anyhow::Result; use paste::paste; /// Path to proto file const ACONFIG_PROTO_PATH: &str = "//build/make/tools/aconfig/aconfig_protos/protos/aconfig.proto"; /// Check if the name identifier is valid pub fn is_valid_name_ident(s: &str) -> bool { // Identifiers must match [a-z][a-z0-9_]*, except consecutive underscores are not allowed Loading Loading @@ -124,8 +127,18 @@ pub mod flag_declaration { pub fn verify_fields(pdf: &ProtoFlagDeclaration) -> Result<()> { ensure_required_fields!("flag declaration", pdf, "name", "namespace", "description"); ensure!(is_valid_name_ident(pdf.name()), "bad flag declaration: bad name"); ensure!(is_valid_name_ident(pdf.namespace()), "bad flag declaration: bad name"); ensure!( is_valid_name_ident(pdf.name()), "bad flag declaration: bad name {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", pdf.name() ); ensure!( is_valid_name_ident(pdf.namespace()), "bad flag declaration: bad namespace {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", pdf.namespace() ); ensure!(!pdf.description().is_empty(), "bad flag declaration: empty description"); ensure!(pdf.bug.len() == 1, "bad flag declaration: exactly one bug required"); Loading @@ -149,8 +162,12 @@ pub mod flag_declarations { pub fn verify_fields(pdf: &ProtoFlagDeclarations) -> Result<()> { ensure_required_fields!("flag declarations", pdf, "package"); // TODO(b/312769710): Make the container field required. ensure!(is_valid_package_ident(pdf.package()), "bad flag declarations: bad package"); ensure!( is_valid_package_ident(pdf.package()), "bad flag declarations: bad package {} expected snake_case strings delimited by dots; \ see {ACONFIG_PROTO_PATH} for details", pdf.package() ); ensure!( !pdf.has_container() || is_valid_container_ident(pdf.container()), "bad flag declarations: bad container" Loading @@ -172,8 +189,18 @@ pub mod flag_value { pub fn verify_fields(fv: &ProtoFlagValue) -> Result<()> { ensure_required_fields!("flag value", fv, "package", "name", "state", "permission"); ensure!(is_valid_package_ident(fv.package()), "bad flag value: bad package"); ensure!(is_valid_name_ident(fv.name()), "bad flag value: bad name"); ensure!( is_valid_package_ident(fv.package()), "bad flag value: bad package {} expected snake_case strings delimited by dots; \ see {ACONFIG_PROTO_PATH} for details", fv.package() ); ensure!( is_valid_name_ident(fv.name()), "bad flag value: bad name {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", fv.name() ); Ok(()) } Loading Loading @@ -255,13 +282,28 @@ pub mod parsed_flag { "permission" ); ensure!(is_valid_package_ident(pf.package()), "bad parsed flag: bad package"); ensure!( is_valid_package_ident(pf.package()), "bad parsed flag: bad package {} expected snake_case strings delimited by dots; \ see {ACONFIG_PROTO_PATH} for details", pf.package() ); ensure!( !pf.has_container() || is_valid_container_ident(pf.container()), "bad parsed flag: bad container" ); ensure!(is_valid_name_ident(pf.name()), "bad parsed flag: bad name"); ensure!(is_valid_name_ident(pf.namespace()), "bad parsed flag: bad namespace"); ensure!( is_valid_name_ident(pf.name()), "bad parsed flag: bad name {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", pf.name() ); ensure!( is_valid_name_ident(pf.namespace()), "bad parsed flag: bad namespace {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", pf.namespace() ); ensure!(!pf.description().is_empty(), "bad parsed flag: empty description"); ensure!(!pf.trace.is_empty(), "bad parsed flag: empty trace"); for tp in pf.trace.iter() { Loading Loading
tools/aconfig/aconfig_protos/protos/aconfig.proto +67 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,19 @@ syntax = "proto2"; package android.aconfig; // This protobuf file defines messages used to represent and manage flags in the "aconfig" system // The following format requirements apply across various message fields: // # name: a lowercase string in snake_case format, no consecutive underscores, and no leading digit // For example adjust_rate is a valid name, while AdjustRate, adjust__rate, and // 2adjust_rate are invalid // // # namespace: a lowercase string in snake_case format, no consecutive underscores, and no leading // digit. For example android_bar_system // // # package: lowercase strings in snake_case format, delimited by dots, no consecutive underscores // and no leading digit in each string. For example com.android.mypackage is a valid name // while com.android.myPackage, com.android.1mypackage are invalid // messages used in both aconfig input and output enum flag_state { Loading @@ -35,12 +48,30 @@ enum flag_permission { // aconfig input messages: flag declarations and values message flag_declaration { // Name of the flag (required) // See # name for format detail optional string name = 1; // Namespace the flag belongs to (required) // See # namespace for format detail optional string namespace = 2; // Textual description of the flag's purpose (required) optional string description = 3; // Single bug id related to the flag (required) repeated string bug = 4; // Indicates if the flag is permanently read-only and cannot be changed // via release configs (optional) // Default value false optional bool is_fixed_read_only = 5; // Indicates if the flag is exported and accessible beyond its originating container (optional) // Default value false optional bool is_exported = 6; // Additional information about the flag, including its purpose and form factors (optional) optional flag_metadata metadata = 7; }; Loading @@ -59,14 +90,26 @@ message flag_metadata { } message flag_declarations { // Package to which the flag belongs (required) // See # package for format detail optional string package = 1; // List of flag_declaration objects (required) repeated flag_declaration flag = 2; // Container the flag belongs to (optional) optional string container = 3; }; message flag_value { // Package to which the flag belongs (required) // See # package for format detail optional string package = 1; // Name of the flag (required) // See # name for format detail optional string name = 2; optional flag_state state = 3; optional flag_permission permission = 4; }; Loading @@ -85,17 +128,41 @@ message tracepoint { } message parsed_flag { // Package to which the flag belongs (required) // See # package for format detail optional string package = 1; // Name of the flag (required) // See # name for format detail optional string name = 2; // Namespace the flag belongs to (required) // See # namespace for format detail optional string namespace = 3; // Textual description of the flag's purpose (required) optional string description = 4; // Single bug id related to the flag (required) repeated string bug = 5; optional flag_state state = 6; optional flag_permission permission = 7; repeated tracepoint trace = 8; // Indicates if the flag is permanently read-only and cannot be changed // via release configs (optional) // Default value false optional bool is_fixed_read_only = 9; // Indicates if the flag is exported and accessible beyond its originating container (optional) // Default value false optional bool is_exported = 10; // Container the flag belongs to (optional) optional string container = 11; // Additional information about the flag, including its purpose and form factors (optional) optional flag_metadata metadata = 12; } Loading
tools/aconfig/aconfig_protos/src/lib.rs +51 −9 Original line number Diff line number Diff line Loading @@ -69,6 +69,9 @@ pub use auto_generated::*; use anyhow::Result; use paste::paste; /// Path to proto file const ACONFIG_PROTO_PATH: &str = "//build/make/tools/aconfig/aconfig_protos/protos/aconfig.proto"; /// Check if the name identifier is valid pub fn is_valid_name_ident(s: &str) -> bool { // Identifiers must match [a-z][a-z0-9_]*, except consecutive underscores are not allowed Loading Loading @@ -124,8 +127,18 @@ pub mod flag_declaration { pub fn verify_fields(pdf: &ProtoFlagDeclaration) -> Result<()> { ensure_required_fields!("flag declaration", pdf, "name", "namespace", "description"); ensure!(is_valid_name_ident(pdf.name()), "bad flag declaration: bad name"); ensure!(is_valid_name_ident(pdf.namespace()), "bad flag declaration: bad name"); ensure!( is_valid_name_ident(pdf.name()), "bad flag declaration: bad name {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", pdf.name() ); ensure!( is_valid_name_ident(pdf.namespace()), "bad flag declaration: bad namespace {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", pdf.namespace() ); ensure!(!pdf.description().is_empty(), "bad flag declaration: empty description"); ensure!(pdf.bug.len() == 1, "bad flag declaration: exactly one bug required"); Loading @@ -149,8 +162,12 @@ pub mod flag_declarations { pub fn verify_fields(pdf: &ProtoFlagDeclarations) -> Result<()> { ensure_required_fields!("flag declarations", pdf, "package"); // TODO(b/312769710): Make the container field required. ensure!(is_valid_package_ident(pdf.package()), "bad flag declarations: bad package"); ensure!( is_valid_package_ident(pdf.package()), "bad flag declarations: bad package {} expected snake_case strings delimited by dots; \ see {ACONFIG_PROTO_PATH} for details", pdf.package() ); ensure!( !pdf.has_container() || is_valid_container_ident(pdf.container()), "bad flag declarations: bad container" Loading @@ -172,8 +189,18 @@ pub mod flag_value { pub fn verify_fields(fv: &ProtoFlagValue) -> Result<()> { ensure_required_fields!("flag value", fv, "package", "name", "state", "permission"); ensure!(is_valid_package_ident(fv.package()), "bad flag value: bad package"); ensure!(is_valid_name_ident(fv.name()), "bad flag value: bad name"); ensure!( is_valid_package_ident(fv.package()), "bad flag value: bad package {} expected snake_case strings delimited by dots; \ see {ACONFIG_PROTO_PATH} for details", fv.package() ); ensure!( is_valid_name_ident(fv.name()), "bad flag value: bad name {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", fv.name() ); Ok(()) } Loading Loading @@ -255,13 +282,28 @@ pub mod parsed_flag { "permission" ); ensure!(is_valid_package_ident(pf.package()), "bad parsed flag: bad package"); ensure!( is_valid_package_ident(pf.package()), "bad parsed flag: bad package {} expected snake_case strings delimited by dots; \ see {ACONFIG_PROTO_PATH} for details", pf.package() ); ensure!( !pf.has_container() || is_valid_container_ident(pf.container()), "bad parsed flag: bad container" ); ensure!(is_valid_name_ident(pf.name()), "bad parsed flag: bad name"); ensure!(is_valid_name_ident(pf.namespace()), "bad parsed flag: bad namespace"); ensure!( is_valid_name_ident(pf.name()), "bad parsed flag: bad name {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", pf.name() ); ensure!( is_valid_name_ident(pf.namespace()), "bad parsed flag: bad namespace {} expected snake_case string; \ see {ACONFIG_PROTO_PATH} for details", pf.namespace() ); ensure!(!pf.description().is_empty(), "bad parsed flag: empty description"); ensure!(!pf.trace.is_empty(), "bad parsed flag: empty trace"); for tp in pf.trace.iter() { Loading