198 lines
7.1 KiB
Diff
198 lines
7.1 KiB
Diff
From 2bc2650d0a7a11a74670a6583b16aa6714d7c993 Mon Sep 17 00:00:00 2001
|
|
From: Matthew Maurer <mmaurer@google.com>
|
|
Date: Thu, 17 Feb 2022 20:23:37 +0000
|
|
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.
|
|
|
|
Change-Id: I72779e62bd963586e3dfad431cd82c75daf04d92
|
|
---
|
|
src/lib.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++----------
|
|
1 file changed, 58 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/src/lib.rs b/src/lib.rs
|
|
index 11a127e..d21be3f 100644
|
|
--- a/src/lib.rs
|
|
+++ b/src/lib.rs
|
|
@@ -87,21 +87,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 {
|
|
@@ -164,7 +192,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.
|
|
@@ -208,6 +236,7 @@ impl AndroidLogger {
|
|
/// Filter for android logger.
|
|
pub struct Config {
|
|
log_level: Option<Level>,
|
|
+ log_id: Option<LogId>,
|
|
filter: Option<env_logger::filter::Filter>,
|
|
tag: Option<CString>,
|
|
custom_format: Option<FormatFn>,
|
|
@@ -217,6 +246,7 @@ impl Default for Config {
|
|
fn default() -> Self {
|
|
Config {
|
|
log_level: None,
|
|
+ log_id: None,
|
|
filter: None,
|
|
tag: None,
|
|
custom_format: None,
|
|
@@ -234,6 +264,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)
|
|
@@ -273,6 +312,8 @@ impl Config {
|
|
struct PlatformLogWriter<'a> {
|
|
#[cfg(target_os = "android")] 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,
|
|
@@ -281,7 +322,7 @@ struct PlatformLogWriter<'a> {
|
|
|
|
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 {
|
|
#[allow(deprecated)] // created an issue #35 for this
|
|
PlatformLogWriter {
|
|
priority: match level {
|
|
@@ -291,6 +332,7 @@ impl<'a> PlatformLogWriter<'a> {
|
|
Level::Error => LogPriority::ERROR,
|
|
Level::Trace => LogPriority::VERBOSE,
|
|
},
|
|
+ log_id: LogId::to_native(log_id),
|
|
len: 0,
|
|
last_newline_index: 0,
|
|
tag,
|
|
@@ -299,10 +341,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,
|
|
@@ -358,7 +401,7 @@ impl<'a> PlatformLogWriter<'a> {
|
|
});
|
|
|
|
let msg: &CStr = unsafe { CStr::from_ptr(mem::transmute(self.buffer.as_ptr())) };
|
|
- 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;
|
|
}
|
|
@@ -458,9 +501,11 @@ mod tests {
|
|
// Filter is checked in config_filter_match below.
|
|
let config = Config::default()
|
|
.with_min_level(Level::Trace)
|
|
+ .with_log_id(LogId::System)
|
|
.with_tag("my_app");
|
|
|
|
assert_eq!(config.log_level, Some(Level::Trace));
|
|
+ assert_eq!(config.log_id, Some(LogId::System));
|
|
assert_eq!(config.tag, Some(CString::new("my_app").unwrap()));
|
|
}
|
|
|
|
@@ -531,7 +576,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
|
|
@@ -630,6 +675,6 @@ 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())
|
|
}
|
|
}
|
|
--
|
|
2.35.1.265.g69c8d7142f-goog
|
|
|