199 lines
7.3 KiB
Diff
199 lines
7.3 KiB
Diff
From a41a079a81f381f2002917fb1c030690e0798f0c Mon Sep 17 00:00:00 2001
|
|
From: Jeff Vander Stoep <jeffv@google.com>
|
|
Date: Thu, 2 Feb 2023 13:33:47 +0100
|
|
Subject: [PATCH] Support selecting target log buffer
|
|
|
|
Android has several different log buffers. Previously, this library
|
|
would only support logging to the "Main" log. Now, it logs to the
|
|
default log (which is Main for most processes), with the option to
|
|
override which log buffer you send messages to in the config.
|
|
|
|
Test: atest
|
|
Change-Id: I3cc393b989b8189675581ba6bf700f95715aa9e9
|
|
---
|
|
src/lib.rs | 73 +++++++++++++++++++++++++++++++++++++++++++-----------
|
|
1 file changed, 59 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/src/lib.rs b/src/lib.rs
|
|
index 0446fad..9ec7f0d 100644
|
|
--- a/src/lib.rs
|
|
+++ b/src/lib.rs
|
|
@@ -85,21 +85,49 @@ pub use env_logger::fmt::Formatter;
|
|
|
|
pub(crate) type FormatFn = Box<dyn Fn(&mut dyn fmt::Write, &Record) -> fmt::Result + Sync + Send>;
|
|
|
|
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
|
+pub enum LogId {
|
|
+ Main,
|
|
+ Radio,
|
|
+ Events,
|
|
+ System,
|
|
+ Crash
|
|
+}
|
|
+
|
|
+impl LogId {
|
|
+ #[cfg(target_os = "android")]
|
|
+ fn to_native(log_id: Option<Self>) -> log_ffi::log_id_t {
|
|
+ match log_id {
|
|
+ Some(LogId::Main) => log_ffi::log_id_t::MAIN,
|
|
+ Some(LogId::Radio) => log_ffi::log_id_t::RADIO,
|
|
+ Some(LogId::Events) => log_ffi::log_id_t::EVENTS,
|
|
+ Some(LogId::System) => log_ffi::log_id_t::SYSTEM,
|
|
+ Some(LogId::Crash) => log_ffi::log_id_t::CRASH,
|
|
+ None => log_ffi::log_id_t::DEFAULT,
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
/// Output log to android system.
|
|
#[cfg(target_os = "android")]
|
|
-fn android_log(prio: log_ffi::LogPriority, tag: &CStr, msg: &CStr) {
|
|
+fn android_log(log_id: log_ffi::log_id_t, prio: log_ffi::LogPriority, tag: &CStr, msg: &CStr) {
|
|
+ let mut message = log_ffi::__android_log_message {
|
|
+ struct_size: std::mem::size_of::<log_ffi::__android_log_message>(),
|
|
+ buffer_id: log_id as i32,
|
|
+ priority: prio as i32,
|
|
+ tag: tag.as_ptr() as *const log_ffi::c_char,
|
|
+ file: ptr::null(),
|
|
+ line: 0,
|
|
+ message: msg.as_ptr() as *const log_ffi::c_char,
|
|
+ };
|
|
unsafe {
|
|
- log_ffi::__android_log_write(
|
|
- prio as log_ffi::c_int,
|
|
- tag.as_ptr() as *const log_ffi::c_char,
|
|
- msg.as_ptr() as *const log_ffi::c_char,
|
|
- )
|
|
+ log_ffi::__android_log_write_log_message(&mut message as *mut _);
|
|
};
|
|
}
|
|
|
|
/// Dummy output placeholder for tests.
|
|
#[cfg(not(target_os = "android"))]
|
|
-fn android_log(_priority: Level, _tag: &CStr, _msg: &CStr) {}
|
|
+fn android_log(_log_id: Option<LogId>, _priority: Level, _tag: &CStr, _msg: &CStr) {}
|
|
|
|
/// Underlying android logger backend
|
|
pub struct AndroidLogger {
|
|
@@ -172,7 +200,7 @@ impl Log for AndroidLogger {
|
|
|
|
// message must not exceed LOGGING_MSG_MAX_LEN
|
|
// therefore split log message into multiple log calls
|
|
- let mut writer = PlatformLogWriter::new(record.level(), tag);
|
|
+ let mut writer = PlatformLogWriter::new(config.log_id, record.level(), tag);
|
|
|
|
// If a custom tag is used, add the module path to the message.
|
|
// Use PlatformLogWriter to output chunks if they exceed max size.
|
|
@@ -215,6 +243,7 @@ impl AndroidLogger {
|
|
#[derive(Default)]
|
|
pub struct Config {
|
|
log_level: Option<LevelFilter>,
|
|
+ log_id: Option<LogId>,
|
|
filter: Option<env_logger::filter::Filter>,
|
|
tag: Option<CString>,
|
|
custom_format: Option<FormatFn>,
|
|
@@ -241,6 +270,15 @@ impl Config {
|
|
self
|
|
}
|
|
|
|
+ /// Change which log buffer is used
|
|
+ ///
|
|
+ /// By default, logs are sent to the `Main` log. Other logging buffers may only be accessible
|
|
+ /// to certain processes.
|
|
+ pub fn with_log_id(mut self, log_id: LogId) -> Self {
|
|
+ self.log_id = Some(log_id);
|
|
+ self
|
|
+ }
|
|
+
|
|
fn filter_matches(&self, record: &Record) -> bool {
|
|
if let Some(ref filter) = self.filter {
|
|
filter.matches(record)
|
|
@@ -282,6 +320,8 @@ pub struct PlatformLogWriter<'a> {
|
|
priority: LogPriority,
|
|
#[cfg(not(target_os = "android"))]
|
|
priority: Level,
|
|
+ #[cfg(target_os = "android")] log_id: log_ffi::log_id_t,
|
|
+ #[cfg(not(target_os = "android"))] log_id: Option<LogId>,
|
|
len: usize,
|
|
last_newline_index: usize,
|
|
tag: &'a CStr,
|
|
@@ -290,10 +330,11 @@ pub struct PlatformLogWriter<'a> {
|
|
|
|
impl<'a> PlatformLogWriter<'a> {
|
|
#[cfg(target_os = "android")]
|
|
- pub fn new_with_priority(priority: log_ffi::LogPriority, tag: &CStr) -> PlatformLogWriter {
|
|
+ pub fn new_with_priority(log_id: Option<LogId>, priority: log_ffi::LogPriority, tag: &CStr) -> PlatformLogWriter {
|
|
#[allow(deprecated)] // created an issue #35 for this
|
|
PlatformLogWriter {
|
|
priority,
|
|
+ log_id: LogId::to_native(log_id),
|
|
len: 0,
|
|
last_newline_index: 0,
|
|
tag,
|
|
@@ -302,8 +343,9 @@ impl<'a> PlatformLogWriter<'a> {
|
|
}
|
|
|
|
#[cfg(target_os = "android")]
|
|
- pub fn new(level: Level, tag: &CStr) -> PlatformLogWriter {
|
|
+ pub fn new(log_id: Option<LogId>, level: Level, tag: &CStr) -> PlatformLogWriter {
|
|
Self::new_with_priority(
|
|
+ log_id,
|
|
match level {
|
|
Level::Warn => LogPriority::WARN,
|
|
Level::Info => LogPriority::INFO,
|
|
@@ -316,10 +358,11 @@ impl<'a> PlatformLogWriter<'a> {
|
|
}
|
|
|
|
#[cfg(not(target_os = "android"))]
|
|
- pub fn new(level: Level, tag: &CStr) -> PlatformLogWriter {
|
|
+ pub fn new(log_id: Option<LogId>, level: Level, tag: &CStr) -> PlatformLogWriter {
|
|
#[allow(deprecated)] // created an issue #35 for this
|
|
PlatformLogWriter {
|
|
priority: level,
|
|
+ log_id,
|
|
len: 0,
|
|
last_newline_index: 0,
|
|
tag,
|
|
@@ -376,7 +419,7 @@ impl<'a> PlatformLogWriter<'a> {
|
|
});
|
|
|
|
let msg: &CStr = unsafe { CStr::from_ptr(self.buffer.as_ptr().cast()) };
|
|
- android_log(self.priority, self.tag, msg);
|
|
+ android_log(self.log_id, self.priority, self.tag, msg);
|
|
|
|
unsafe { *self.buffer.get_unchecked_mut(len) = last_byte };
|
|
}
|
|
@@ -481,9 +524,11 @@ mod tests {
|
|
// Filter is checked in config_filter_match below.
|
|
let config = Config::default()
|
|
.with_max_level(LevelFilter::Trace)
|
|
+ .with_log_id(LogId::System)
|
|
.with_tag("my_app");
|
|
|
|
assert_eq!(config.log_level, Some(LevelFilter::Trace));
|
|
+ assert_eq!(config.log_id, Some(LogId::System));
|
|
assert_eq!(config.tag, Some(CString::new("my_app").unwrap()));
|
|
}
|
|
|
|
@@ -556,7 +601,7 @@ mod tests {
|
|
fn platform_log_writer_init_values() {
|
|
let tag = CStr::from_bytes_with_nul(b"tag\0").unwrap();
|
|
|
|
- let writer = PlatformLogWriter::new(Level::Warn, tag);
|
|
+ let writer = PlatformLogWriter::new(None, Level::Warn, tag);
|
|
|
|
assert_eq!(writer.tag, tag);
|
|
// Android uses LogPriority instead, which doesn't implement equality checks
|
|
@@ -661,7 +706,7 @@ mod tests {
|
|
}
|
|
|
|
fn get_tag_writer() -> PlatformLogWriter<'static> {
|
|
- PlatformLogWriter::new(Level::Warn, CStr::from_bytes_with_nul(b"tag\0").unwrap())
|
|
+ PlatformLogWriter::new(None, Level::Warn, CStr::from_bytes_with_nul(b"tag\0").unwrap())
|
|
}
|
|
|
|
unsafe fn assume_init_slice<T>(slice: &[MaybeUninit<T>]) -> &[T] {
|
|
--
|
|
2.39.1.456.gfc5497dd1b-goog
|
|
|