1 use lazy_static::lazy_static;
2 use log::{error, info};
3 use paste::paste;
4 use std::collections::{BTreeMap, HashMap};
5 use std::convert::TryFrom;
6 use std::fmt;
7 use std::sync::Mutex;
8
9 // Fallback to bool when type is not specified
10 macro_rules! type_expand {
11 () => {
12 bool
13 };
14 ($type:ty) => {
15 $type
16 };
17 }
18
19 macro_rules! default_value {
20 () => {
21 false
22 };
23 ($type:ty) => {
24 <$type>::default()
25 };
26 ($($type:ty)? = $default:tt) => {
27 $default
28 };
29 }
30
31 macro_rules! test_value {
32 () => {
33 true
34 };
35 ($type:ty) => {
36 <$type>::default()
37 };
38 }
39
40 #[cfg(test)]
41 macro_rules! call_getter_fn {
42 ($flag:ident) => {
43 paste! {
44 [<$flag _is_enabled>]()
45 }
46 };
47 ($flag:ident $type:ty) => {
48 paste! {
49 [<get_ $flag>]()
50 }
51 };
52 }
53
54 macro_rules! create_getter_fn {
55 ($flag:ident) => {
56 paste! {
57 #[doc = concat!(" Return true if ", stringify!($flag), " is enabled")]
58 pub fn [<$flag _is_enabled>]() -> bool {
59 FLAGS.lock().unwrap().$flag
60 }
61 }
62 };
63 ($flag:ident $type:ty) => {
64 paste! {
65 #[doc = concat!(" Return the flag value of ", stringify!($flag))]
66 pub fn [<get_ $flag>]() -> $type {
67 FLAGS.lock().unwrap().$flag
68 }
69 }
70 };
71 }
72
73 macro_rules! create_setter_fn {
74 ($flag:ident) => {
75 paste! {
76 #[doc = concat!(" Update value of ", stringify!($flag), " at runtime")]
77 pub fn [<update_ $flag>](value: bool) {
78 FLAGS.lock().unwrap().$flag = value;
79 }
80 }
81 };
82 ($flag:ident $type:ty) => {
83 paste! {
84 #[doc = concat!(" Update value of ", stringify!($flag), " at runtime")]
85 pub fn [<update_ $flag>](value: $type) {
86 FLAGS.lock().unwrap().$flag = value;
87 }
88 }
89 };
90 }
91
92 macro_rules! init_flags {
93 (
94 name: $name:ident
95 $($args:tt)*
96 ) => {
97 init_flags_struct! {
98 name: $name
99 $($args)*
100 }
101
102 init_flags_getters! {
103 $($args)*
104 }
105 }
106 }
107
108 trait FlagHolder: Default {
get_defaults_for_test() -> Self109 fn get_defaults_for_test() -> Self;
parse(flags: Vec<String>) -> Self110 fn parse(flags: Vec<String>) -> Self;
dump(&self) -> BTreeMap<&'static str, String>111 fn dump(&self) -> BTreeMap<&'static str, String>;
reconcile(self) -> Self112 fn reconcile(self) -> Self;
113 }
114
115 macro_rules! init_flags_struct {
116 (
117 name: $name:ident
118 flags: { $($flag:ident $(: $type:ty)? $(= $default:tt)?,)* }
119 dynamic_flags: { $($dy_flag:ident $(: $dy_type:ty)? $(= $dy_default:tt)?,)* }
120 extra_fields: { $($extra_field:ident : $extra_field_type:ty $(= $extra_default:tt)?,)* }
121 extra_parsed_flags: { $($extra_flag:tt => $extra_flag_fn:ident(_, _ $(,$extra_args:tt)*),)*}
122 dependencies: { $($parent:ident => $child:ident),* }) => {
123
124 struct $name {
125 $($flag : type_expand!($($type)?),)*
126 $($dy_flag : type_expand!($($dy_type)?),)*
127 $($extra_field : $extra_field_type,)*
128 }
129
130 impl Default for $name {
131 fn default() -> Self {
132 Self {
133 $($flag : default_value!($($type)? $(= $default)?),)*
134 $($dy_flag : default_value!($($dy_type)? $(= $dy_default)?),)*
135 $($extra_field : default_value!($extra_field_type $(= $extra_default)?),)*
136 }
137 }
138 }
139
140 impl FlagHolder for $name {
141 fn get_defaults_for_test() -> Self {
142 Self {
143 $($flag: test_value!($($type)?),)*
144 $($dy_flag: test_value!($($dy_type)?),)*
145 $($extra_field: test_value!($extra_field_type),)*
146 }
147 }
148
149 fn dump(&self) -> BTreeMap<&'static str, String> {
150 [
151 $((stringify!($flag), format!("{}", self.$flag)),)*
152 $((stringify!($dy_flag), format!("{}", self.$dy_flag)),)*
153 $((stringify!($extra_field), format!("{}", self.$extra_field)),)*
154 ].into()
155 }
156
157 fn parse(flags: Vec<String>) -> Self {
158 let mut init_flags = Self::default();
159
160 for flag in flags {
161 let values: Vec<&str> = flag.split("=").collect();
162 if values.len() != 2 {
163 error!("Bad flag {}, must be in <FLAG>=<VALUE> format", flag);
164 continue;
165 }
166
167 match values[0] {
168 $(concat!("INIT_", stringify!($flag)) =>
169 init_flags.$flag = values[1].parse().unwrap_or_else(|e| {
170 error!("Parse failure on '{}': {}", flag, e);
171 default_value!($($type)? $(= $default)?)}),)*
172 $(concat!("INIT_", stringify!($dy_flag)) =>
173 init_flags.$dy_flag = values[1].parse().unwrap_or_else(|e| {
174 error!("Parse failure on '{}': {}", flag, e);
175 default_value!($($dy_type)? $(= $dy_default)?)}),)*
176 $($extra_flag => $extra_flag_fn(&mut init_flags, values $(, $extra_args)*),)*
177 _ => error!("Unsaved flag: {} = {}", values[0], values[1])
178 }
179 }
180
181 init_flags.reconcile()
182 }
183
184 #[allow(unused_mut)]
185 fn reconcile(mut self) -> Self {
186 loop {
187 // dependencies can be specified in any order
188 $(if self.$parent && !self.$child {
189 self.$child = true;
190 continue;
191 })*
192 break;
193 }
194 self
195 }
196 }
197
198 impl fmt::Display for $name {
199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200 write!(f, concat!(
201 concat!($(concat!(stringify!($flag), "={}")),*),
202 concat!($(concat!(stringify!($dy_flag), "={}")),*),
203 $(concat!(stringify!($extra_field), "={}")),*),
204 $(self.$flag),*,
205 $(self.$dy_flag),*,
206 $(self.$extra_field),*)
207 }
208 }
209
210 }
211 }
212
213 macro_rules! init_flags_getters {
214 (
215 flags: { $($flag:ident $(: $type:ty)? $(= $default:tt)?,)* }
216 dynamic_flags: { $($dy_flag:ident $(: $dy_type:ty)? $(= $dy_default:tt)?,)* }
217 extra_fields: { $($extra_field:ident : $extra_field_type:ty $(= $extra_default:tt)?,)* }
218 extra_parsed_flags: { $($extra_flag:tt => $extra_flag_fn:ident(_, _ $(,$extra_args:tt)*),)*}
219 dependencies: { $($parent:ident => $child:ident),* }) => {
220
221 $(create_getter_fn!($flag $($type)?);)*
222
223 $(create_getter_fn!($dy_flag $($dy_type)?);)*
224 $(create_setter_fn!($dy_flag $($dy_type)?);)*
225
226 #[cfg(test)]
227 mod tests_autogenerated {
228 use super::*;
229 $(paste! {
230 #[test]
231 pub fn [<test_get_ $flag>]() {
232 let _guard = tests::ASYNC_LOCK.lock().unwrap();
233 tests::test_load(vec![
234 &*format!(concat!(concat!("INIT_", stringify!($flag)), "={}"), test_value!($($type)?))
235 ]);
236 let get_value = call_getter_fn!($flag $($type)?);
237 drop(_guard); // Prevent poisonning other tests if a panic occurs
238 assert_eq!(get_value, test_value!($($type)?));
239 }
240 })*
241
242 $(paste! {
243 #[test]
244 pub fn [<test_dynamic_get_ $dy_flag>]() {
245 let _guard = tests::ASYNC_LOCK.lock().unwrap();
246 tests::test_load(vec![
247 &*format!(concat!(concat!("INIT_", stringify!($dy_flag)), "={}"), test_value!($($dy_type)?))
248 ]);
249 let get_value = call_getter_fn!($dy_flag $($dy_type)?);
250 drop(_guard); // Prevent poisonning other tests if a panic occurs
251 assert_eq!(get_value, test_value!($($dy_type)?));
252 }
253 })*
254 }
255 }
256 }
257
258 #[derive(Default)]
259 struct ExplicitTagSettings {
260 map: HashMap<String, i32>,
261 }
262
263 impl fmt::Display for ExplicitTagSettings {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result264 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
265 write!(f, "{:?}", self.map)
266 }
267 }
268
269 struct LogLevel(i32);
270
271 impl TryFrom<&str> for LogLevel {
272 type Error = &'static str;
273
try_from(tag_value: &str) -> Result<Self, Self::Error>274 fn try_from(tag_value: &str) -> Result<Self, Self::Error> {
275 match tag_value {
276 "LOG_FATAL" => Ok(LogLevel(LOG_TAG_FATAL)),
277 "LOG_ERROR" => Ok(LogLevel(LOG_TAG_ERROR)),
278 "LOG_WARN" => Ok(LogLevel(LOG_TAG_WARN)),
279 "LOG_NOTICE" => Ok(LogLevel(LOG_TAG_NOTICE)),
280 "LOG_INFO" => Ok(LogLevel(LOG_TAG_INFO)),
281 "LOG_DEBUG" => Ok(LogLevel(LOG_TAG_DEBUG)),
282 "LOG_VERBOSE" => Ok(LogLevel(LOG_TAG_VERBOSE)),
283 _ => Err("Invalid tag value"),
284 }
285 }
286 }
287
deprecated_set_debug_logging_enabled_for_all(flags: &mut InitFlags, values: Vec<&str>)288 fn deprecated_set_debug_logging_enabled_for_all(flags: &mut InitFlags, values: Vec<&str>) {
289 let truthy: bool = values[1].parse().unwrap_or(false);
290 flags.default_log_level = if truthy { LOG_TAG_VERBOSE } else { LOG_TAG_INFO };
291
292 // Leave a note that this flag is deprecated in the logs.
293 log::error!(
294 "DEPRECATED flag used: INIT_logging_debug_enabled_for_all. Use INIT_default_log_level_str=LOG_VERBOSE instead.",
295 );
296 }
297
parse_log_level(flags: &mut InitFlags, values: Vec<&str>)298 fn parse_log_level(flags: &mut InitFlags, values: Vec<&str>) {
299 if let Ok(v) = LogLevel::try_from(values[1]) {
300 flags.default_log_level = v.0;
301 }
302 }
303
parse_logging_tag(flags: &mut InitFlags, values: Vec<&str>)304 fn parse_logging_tag(flags: &mut InitFlags, values: Vec<&str>) {
305 for tag in values[1].split(',') {
306 let tagstr = tag.to_string();
307 let pair = tagstr.split(':').collect::<Vec<&str>>();
308 if pair.len() == 2 {
309 if let Ok(v) = LogLevel::try_from(pair[1]) {
310 flags.logging_explicit_tag_settings.map.insert(pair[0].into(), v.0);
311 }
312 }
313 }
314 }
315
parse_debug_logging_tag(flags: &mut InitFlags, values: Vec<&str>, enabled: bool)316 fn parse_debug_logging_tag(flags: &mut InitFlags, values: Vec<&str>, enabled: bool) {
317 let log_level: i32 = if enabled { LOG_TAG_VERBOSE } else { LOG_TAG_INFO };
318
319 for tag in values[1].split(',') {
320 flags.logging_explicit_tag_settings.map.insert(tag.to_string(), log_level);
321 }
322 }
323
parse_hci_adapter(flags: &mut InitFlags, values: Vec<&str>)324 fn parse_hci_adapter(flags: &mut InitFlags, values: Vec<&str>) {
325 flags.hci_adapter = values[1].parse().unwrap_or(0);
326 }
327
328 /// Returns the log level for given flag.
get_log_level_for_tag(tag: &str) -> i32329 pub fn get_log_level_for_tag(tag: &str) -> i32 {
330 let guard = FLAGS.lock().unwrap();
331 *guard.logging_explicit_tag_settings.map.get(tag).unwrap_or(&guard.default_log_level)
332 }
333
334 /// Sets all bool flags to true
335 /// Set all other flags and extra fields to their default type value
set_all_for_testing()336 pub fn set_all_for_testing() {
337 *FLAGS.lock().unwrap() = InitFlags::get_defaults_for_test();
338 }
339
340 // Keep these values in sync with the values in gd/os/log_tags.h
341 // They are used to control the log level for each tag.
342
343 /// Fatal log level.
344 pub const LOG_TAG_FATAL: i32 = 0;
345 /// Error log level.
346 pub const LOG_TAG_ERROR: i32 = 1;
347 /// Warning log level.
348 pub const LOG_TAG_WARN: i32 = 2;
349 /// Notice log level.
350 pub const LOG_TAG_NOTICE: i32 = 3;
351 /// Info log level. This is usually the default log level on most systems.
352 pub const LOG_TAG_INFO: i32 = 4;
353 /// Debug log level.
354 pub const LOG_TAG_DEBUG: i32 = 5;
355 /// Verbose log level.
356 pub const LOG_TAG_VERBOSE: i32 = 6;
357
358 init_flags!(
359 name: InitFlags
360 flags: {
361 asha_packet_drop_frequency_threshold: i32 = 60,
362 asha_phy_update_retry_limit: i32 = 5,
363 always_send_services_if_gatt_disc_done = true,
364 always_use_private_gatt_for_debugging,
365 asynchronously_start_l2cap_coc = true,
366 btaa_hci = true,
367 bta_dm_clear_conn_id_on_client_close = true,
368 btm_dm_flush_discovery_queue_on_search_cancel,
369 classic_discovery_only,
370 clear_hidd_interrupt_cid_on_disconnect = true,
371 delay_hidh_cleanup_until_hidh_ready_start = true,
372 device_iot_config_logging,
373 dynamic_avrcp_version_enhancement = true,
374 finite_att_timeout = true,
375 gatt_robust_caching_client = true,
376 gatt_robust_caching_server,
377 gd_core,
378 gd_hal_snoop_logger_socket = true,
379 gd_hal_snoop_logger_filtering = true,
380 gd_l2cap,
381 gd_link_policy,
382 gd_remote_name_request,
383 gd_rust,
384 hci_adapter: i32,
385 hfp_dynamic_version = true,
386 irk_rotation,
387 leaudio_targeted_announcement_reconnection_mode = true,
388 pass_phy_update_callback = true,
389 pbap_pse_dynamic_version_upgrade = false,
390 periodic_advertising_adi = true,
391 private_gatt = true,
392 queue_l2cap_coc_while_encrypting = true,
393 read_encryption_key_size = true,
394 redact_log = true,
395 rust_event_loop = true,
396 sco_codec_select_lc3,
397 sco_codec_timeout_clear,
398 sdp_serialization = true,
399 sdp_skip_rnr_if_known = true,
400 bluetooth_quality_report_callback = true,
401 set_min_encryption = true,
402 subrating = true,
403 trigger_advertising_callbacks_on_first_resume_after_pause = true,
404 use_unified_connection_manager,
405 sdp_return_classic_services_when_le_discovery_fails = true,
406 }
407 // dynamic flags can be updated at runtime and should be accessed directly
408 // to check.
409 dynamic_flags: {
410 default_log_level : i32 = LOG_TAG_INFO,
411 }
412 // extra_fields are not a 1 to 1 match with "INIT_*" flags
413 extra_fields: {
414 logging_explicit_tag_settings: ExplicitTagSettings,
415 }
416 extra_parsed_flags: {
417 "INIT_default_log_level_str" => parse_log_level(_, _),
418 "INIT_log_level_for_tags" => parse_logging_tag(_, _),
419 "INIT_logging_debug_enabled_for_all" => deprecated_set_debug_logging_enabled_for_all(_, _),
420 "INIT_logging_debug_enabled_for_tags" => parse_debug_logging_tag(_, _, true),
421 "INIT_logging_debug_disabled_for_tags" => parse_debug_logging_tag(_, _, false),
422 "--hci" => parse_hci_adapter(_, _),
423 }
424 dependencies: {
425 always_use_private_gatt_for_debugging => private_gatt,
426 private_gatt => rust_event_loop
427 }
428 );
429
430 lazy_static! {
431 /// Store some flag values
432 static ref FLAGS: Mutex<InitFlags> = Mutex::new(InitFlags::default());
433 /// Store the uid of bluetooth
434 pub static ref AID_BLUETOOTH: Mutex<u32> = Mutex::new(1002);
435 /// Store the prefix for file system
436 pub static ref MISC: Mutex<String> = Mutex::new("/data/misc/".to_string());
437 }
438
439 /// Loads the flag values from the passed-in vector of string values
load(raw_flags: Vec<String>)440 pub fn load(raw_flags: Vec<String>) {
441 crate::init_logging();
442
443 let flags = InitFlags::parse(raw_flags);
444 info!("Flags loaded: {}", flags);
445 *FLAGS.lock().unwrap() = flags;
446
447 // re-init to respect log levels set by flags
448 crate::init_logging();
449 }
450
451 /// Dumps all flag K-V pairs, storing values as strings
dump() -> BTreeMap<&'static str, String>452 pub fn dump() -> BTreeMap<&'static str, String> {
453 FLAGS.lock().unwrap().dump()
454 }
455
456 #[cfg(test)]
457 mod tests {
458 use super::*;
459 lazy_static! {
460 /// do not run concurrent tests as they all use the same global init_flag struct and
461 /// accessor
462 pub(super) static ref ASYNC_LOCK: Mutex<bool> = Mutex::new(false);
463 }
464
test_load(raw_flags: Vec<&str>)465 pub(super) fn test_load(raw_flags: Vec<&str>) {
466 let raw_flags = raw_flags.into_iter().map(|x| x.to_string()).collect();
467 load(raw_flags);
468 }
469
470 #[test]
simple_flag()471 fn simple_flag() {
472 let _guard = ASYNC_LOCK.lock().unwrap();
473 test_load(vec![
474 "INIT_btaa_hci=false", //override a default flag
475 "INIT_gatt_robust_caching_server=true",
476 ]);
477 assert!(!btaa_hci_is_enabled());
478 assert!(gatt_robust_caching_server_is_enabled());
479 }
480 #[test]
parsing_failure()481 fn parsing_failure() {
482 let _guard = ASYNC_LOCK.lock().unwrap();
483 test_load(vec![
484 "foo=bar=?", // vec length
485 "foo=bar", // flag not save
486 "INIT_btaa_hci=not_false", // parse error but has default value
487 "INIT_gatt_robust_caching_server=not_true", // parse error
488 ]);
489 assert!(btaa_hci_is_enabled());
490 assert!(!gatt_robust_caching_server_is_enabled());
491 }
492 #[test]
int_flag()493 fn int_flag() {
494 let _guard = ASYNC_LOCK.lock().unwrap();
495 test_load(vec!["--hci=2"]);
496 assert_eq!(get_hci_adapter(), 2);
497 }
498 #[test]
explicit_flag()499 fn explicit_flag() {
500 let _guard = ASYNC_LOCK.lock().unwrap();
501 test_load(vec![
502 "INIT_default_log_level_str=LOG_VERBOSE",
503 "INIT_logging_debug_enabled_for_tags=foo,bar",
504 "INIT_logging_debug_disabled_for_tags=foo,bar2,fizz",
505 "INIT_logging_debug_enabled_for_tags=bar2",
506 "INIT_log_level_for_tags=fizz:LOG_WARN,buzz:LOG_NOTICE",
507 ]);
508
509 assert!(get_log_level_for_tag("foo") == LOG_TAG_INFO);
510 assert!(get_log_level_for_tag("bar") == LOG_TAG_VERBOSE);
511 assert!(get_log_level_for_tag("bar2") == LOG_TAG_VERBOSE);
512 assert!(get_log_level_for_tag("unknown_flag") == LOG_TAG_VERBOSE);
513 assert!(get_default_log_level() == LOG_TAG_VERBOSE);
514 FLAGS.lock().unwrap().default_log_level = LOG_TAG_INFO;
515 assert!(get_log_level_for_tag("foo") == LOG_TAG_INFO);
516 assert!(get_log_level_for_tag("bar") == LOG_TAG_VERBOSE);
517 assert!(get_log_level_for_tag("bar2") == LOG_TAG_VERBOSE);
518 assert!(get_log_level_for_tag("unknown_flag") == LOG_TAG_INFO);
519 assert!(get_default_log_level() == LOG_TAG_INFO);
520 }
521 #[test]
test_redact_logging()522 fn test_redact_logging() {
523 let _guard = ASYNC_LOCK.lock().unwrap();
524 assert!(redact_log_is_enabled()); // default is true
525 test_load(vec!["INIT_redact_log=false"]);
526 assert!(!redact_log_is_enabled()); // turned off
527 test_load(vec!["INIT_redact_log=foo"]);
528 assert!(redact_log_is_enabled()); // invalid value, interpreted as default, true
529 test_load(vec!["INIT_redact_log=true"]);
530 assert!(redact_log_is_enabled()); // turned on
531 }
532 #[test]
test_runtime_update()533 fn test_runtime_update() {
534 let _guard = ASYNC_LOCK.lock().unwrap();
535 test_load(vec!["INIT_btaa_hci=true", "INIT_default_log_level_str=LOG_WARN"]);
536 assert!(btaa_hci_is_enabled());
537 assert!(get_default_log_level() == LOG_TAG_WARN);
538
539 update_default_log_level(LOG_TAG_DEBUG);
540 assert!(get_default_log_level() == LOG_TAG_DEBUG);
541 update_default_log_level(LOG_TAG_ERROR);
542 assert!(get_default_log_level() == LOG_TAG_ERROR);
543 }
544 #[test]
test_default_log_level()545 fn test_default_log_level() {
546 // Default log level can be provided via int value or string.
547 // The string version is just for ease-of-use.
548 let _guard = ASYNC_LOCK.lock().unwrap();
549 test_load(vec!["INIT_default_log_level=1"]);
550 assert!(get_default_log_level() == LOG_TAG_ERROR);
551 test_load(vec!["INIT_default_log_level_str=LOG_VERBOSE"]);
552 assert!(get_default_log_level() == LOG_TAG_VERBOSE);
553 test_load(vec!["INIT_default_log_level_str=LOG_VERBOSE", "INIT_default_log_level=0"]);
554 assert!(get_default_log_level() == LOG_TAG_FATAL);
555 }
556 #[test]
test_deprecated_logging_flag()557 fn test_deprecated_logging_flag() {
558 let _guard = ASYNC_LOCK.lock().unwrap();
559 test_load(vec!["INIT_default_log_level_str=1", "INIT_logging_debug_enabled_for_all=true"]);
560 assert!(get_default_log_level() == LOG_TAG_VERBOSE);
561 test_load(vec!["INIT_logging_debug_enabled_for_all=false"]);
562 assert!(get_default_log_level() == LOG_TAG_INFO);
563 }
564
565 init_flags_struct!(
566 name: InitFlagsForTest
567 flags: {
568 cat,
569 }
570 dynamic_flags: {
571 dog: i32 = 8,
572 }
573 extra_fields: {
574 elephant: String,
575 }
576 extra_parsed_flags: {}
577 dependencies: {}
578 );
579
580 #[test]
test_dumpsys()581 fn test_dumpsys() {
582 let flags = InitFlagsForTest { dog: 3, elephant: "Go bears!".into(), ..Default::default() };
583
584 let out = flags.dump();
585
586 assert_eq!(out.len(), 3);
587 assert_eq!(out["cat"], "false");
588 assert_eq!(out["dog"], "3");
589 assert_eq!(out["elephant"], "Go bears!");
590 }
591 }
592