diff --git a/CHANGELOG.md b/CHANGELOG.md index 4952ca1..4071f6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,25 @@ All user visible changes to this project will be documented in this file. This p +## [0.13.0] · 2023-02-?? +[0.13.0]: /../../tree/v0.13.0 + +[Diff](/../../compare/v0.12.0...v0.13.0) + +### BC Breaks + +- Added `buf_id` argument to `PlatformLogWriter::new()` method allowing to specify concrete Android logging system buffer. ([#50], [#64]) + +### Added + +- `Config::with_log_buffer()` method to specify concrete Android logging system buffer. ([#50], [#64]) + +[#50]: /../../pull/50 +[#64]: /../../pull/64 + + + + ## [0.12.0] · 2023-01-19 [0.12.0]: /../../tree/v0.12.0 diff --git a/Cargo.toml b/Cargo.toml index ca1b723..2f813e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ once_cell = "1.9" version = "0.4" [dependencies.android_log-sys] -version = "0.2" +version = "0.3" [dependencies.env_logger] version = "0.10" diff --git a/src/lib.rs b/src/lib.rs index 0446fad..ecf67b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,21 +85,70 @@ pub use env_logger::fmt::Formatter; pub(crate) type FormatFn = Box fmt::Result + Sync + Send>; -/// Output log to android system. +/// Possible identifiers of a specific buffer of Android logging system for +/// logging a message. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum LogId { + /// Main log buffer. + /// + /// This is the only log buffer available to apps. + Main, + + /// Radio log buffer. + Radio, + + /// Event log buffer. + Events, + + /// System log buffer. + System, + + /// Crash log buffer. + Crash, + + /// Kernel log buffer. + Kernel, + + /// Security log buffer. + Security, + + /// Statistics log buffer. + Stats, +} + #[cfg(target_os = "android")] -fn android_log(prio: log_ffi::LogPriority, tag: &CStr, msg: &CStr) { +impl LogId { + fn to_native(log_id: Option) -> log_ffi::log_id_t { + match log_id { + Some(Self::Main) => log_ffi::log_id_t::MAIN, + Some(Self::Radio) => log_ffi::log_id_t::RADIO, + Some(Self::Events) => log_ffi::log_id_t::EVENTS, + Some(Self::System) => log_ffi::log_id_t::SYSTEM, + Some(Self::Crash) => log_ffi::log_id_t::CRASH, + Some(Self::Kernel) => log_ffi::log_id_t::KERNEL, + Some(Self::Security) => log_ffi::log_id_t::SECURITY, + Some(Self::Stats) => log_ffi::log_id_t::STATS, + None => log_ffi::log_id_t::DEFAULT, + } + } +} + +/// Outputs log to Android system. +#[cfg(target_os = "android")] +fn android_log(buf_id: log_ffi::log_id_t, prio: log_ffi::LogPriority, tag: &CStr, msg: &CStr) { unsafe { - log_ffi::__android_log_write( + log_ffi::__android_log_buf_write( + buf_id as log_ffi::c_int, prio as log_ffi::c_int, tag.as_ptr() as *const log_ffi::c_char, msg.as_ptr() as *const log_ffi::c_char, - ) + ); }; } /// Dummy output placeholder for tests. #[cfg(not(target_os = "android"))] -fn android_log(_priority: Level, _tag: &CStr, _msg: &CStr) {} +fn android_log(_buf_id: Option, _priority: Level, _tag: &CStr, _msg: &CStr) {} /// Underlying android logger backend pub struct AndroidLogger { @@ -172,7 +221,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.buf_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 +264,7 @@ impl AndroidLogger { #[derive(Default)] pub struct Config { log_level: Option, + buf_id: Option, filter: Option, tag: Option, custom_format: Option, @@ -241,6 +291,17 @@ impl Config { self } + /// Changes the Android logging system buffer to be used. + /// + /// By default, logs are sent to the [`Main`] log. Other logging buffers may + /// only be accessible to certain processes. + /// + /// [`Main`]: LogId::Main + pub fn with_log_buffer(mut self, buf_id: LogId) -> Self { + self.buf_id = Some(buf_id); + self + } + fn filter_matches(&self, record: &Record) -> bool { if let Some(ref filter) = self.filter { filter.matches(record) @@ -282,6 +343,10 @@ pub struct PlatformLogWriter<'a> { priority: LogPriority, #[cfg(not(target_os = "android"))] priority: Level, + #[cfg(target_os = "android")] + buf_id: log_ffi::log_id_t, + #[cfg(not(target_os = "android"))] + buf_id: Option, len: usize, last_newline_index: usize, tag: &'a CStr, @@ -290,10 +355,15 @@ 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( + buf_id: Option, + priority: log_ffi::LogPriority, + tag: &CStr, + ) -> PlatformLogWriter<'_> { #[allow(deprecated)] // created an issue #35 for this PlatformLogWriter { priority, + buf_id: LogId::to_native(buf_id), len: 0, last_newline_index: 0, tag, @@ -302,8 +372,9 @@ impl<'a> PlatformLogWriter<'a> { } #[cfg(target_os = "android")] - pub fn new(level: Level, tag: &CStr) -> PlatformLogWriter { - Self::new_with_priority( + pub fn new(buf_id: Option, level: Level, tag: &CStr) -> PlatformLogWriter<'_> { + PlatformLogWriter::new_with_priority( + buf_id, match level { Level::Warn => LogPriority::WARN, Level::Info => LogPriority::INFO, @@ -316,10 +387,11 @@ impl<'a> PlatformLogWriter<'a> { } #[cfg(not(target_os = "android"))] - pub fn new(level: Level, tag: &CStr) -> PlatformLogWriter { + pub fn new(buf_id: Option, level: Level, tag: &CStr) -> PlatformLogWriter<'_> { #[allow(deprecated)] // created an issue #35 for this PlatformLogWriter { priority: level, + buf_id, len: 0, last_newline_index: 0, tag, @@ -376,7 +448,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.buf_id, self.priority, self.tag, msg); unsafe { *self.buffer.get_unchecked_mut(len) = last_byte }; } @@ -481,9 +553,11 @@ mod tests { // Filter is checked in config_filter_match below. let config = Config::default() .with_max_level(LevelFilter::Trace) + .with_log_buffer(LogId::System) .with_tag("my_app"); assert_eq!(config.log_level, Some(LevelFilter::Trace)); + assert_eq!(config.buf_id, Some(LogId::System)); assert_eq!(config.tag, Some(CString::new("my_app").unwrap())); } @@ -556,7 +630,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 +735,11 @@ 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(slice: &[MaybeUninit]) -> &[T] {