@@ -85,21 +85,70 @@ pub use env_logger::fmt::Formatter;
8585
8686pub ( crate ) type FormatFn = Box < dyn Fn ( & mut dyn fmt:: Write , & Record ) -> fmt:: Result + Sync + Send > ;
8787
88- /// Output log to android system.
88+ /// Possible identifiers of a specific buffer of Android logging system for
89+ /// logging a message.
90+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
91+ pub enum LogId {
92+ /// Main log buffer.
93+ ///
94+ /// This is the only log buffer available to apps.
95+ Main ,
96+
97+ /// Radio log buffer.
98+ Radio ,
99+
100+ /// Event log buffer.
101+ Events ,
102+
103+ /// System log buffer.
104+ System ,
105+
106+ /// Crash log buffer.
107+ Crash ,
108+
109+ /// Kernel log buffer.
110+ Kernel ,
111+
112+ /// Security log buffer.
113+ Security ,
114+
115+ /// Statistics log buffer.
116+ Stats ,
117+ }
118+
89119#[ cfg( target_os = "android" ) ]
90- fn android_log ( prio : log_ffi:: LogPriority , tag : & CStr , msg : & CStr ) {
120+ impl LogId {
121+ fn to_native ( log_id : Option < Self > ) -> log_ffi:: log_id_t {
122+ match log_id {
123+ Some ( Self :: Main ) => log_ffi:: log_id_t:: MAIN ,
124+ Some ( Self :: Radio ) => log_ffi:: log_id_t:: RADIO ,
125+ Some ( Self :: Events ) => log_ffi:: log_id_t:: EVENTS ,
126+ Some ( Self :: System ) => log_ffi:: log_id_t:: SYSTEM ,
127+ Some ( Self :: Crash ) => log_ffi:: log_id_t:: CRASH ,
128+ Some ( Self :: Kernel ) => log_ffi:: log_id_t:: KERNEL ,
129+ Some ( Self :: Security ) => log_ffi:: log_id_t:: SECURITY ,
130+ Some ( Self :: Stats ) => log_ffi:: log_id_t:: STATS ,
131+ None => log_ffi:: log_id_t:: DEFAULT ,
132+ }
133+ }
134+ }
135+
136+ /// Outputs log to Android system.
137+ #[ cfg( target_os = "android" ) ]
138+ fn android_log ( buf_id : log_ffi:: log_id_t , prio : log_ffi:: LogPriority , tag : & CStr , msg : & CStr ) {
91139 unsafe {
92- log_ffi:: __android_log_write (
140+ log_ffi:: __android_log_buf_write (
141+ buf_id as log_ffi:: c_int ,
93142 prio as log_ffi:: c_int ,
94143 tag. as_ptr ( ) as * const log_ffi:: c_char ,
95144 msg. as_ptr ( ) as * const log_ffi:: c_char ,
96- )
145+ ) ;
97146 } ;
98147}
99148
100149/// Dummy output placeholder for tests.
101150#[ cfg( not( target_os = "android" ) ) ]
102- fn android_log ( _priority : Level , _tag : & CStr , _msg : & CStr ) { }
151+ fn android_log ( _buf_id : Option < LogId > , _priority : Level , _tag : & CStr , _msg : & CStr ) { }
103152
104153/// Underlying android logger backend
105154pub struct AndroidLogger {
@@ -172,7 +221,7 @@ impl Log for AndroidLogger {
172221
173222 // message must not exceed LOGGING_MSG_MAX_LEN
174223 // therefore split log message into multiple log calls
175- let mut writer = PlatformLogWriter :: new ( record. level ( ) , tag) ;
224+ let mut writer = PlatformLogWriter :: new ( config . buf_id , record. level ( ) , tag) ;
176225
177226 // If a custom tag is used, add the module path to the message.
178227 // Use PlatformLogWriter to output chunks if they exceed max size.
@@ -215,6 +264,7 @@ impl AndroidLogger {
215264#[ derive( Default ) ]
216265pub struct Config {
217266 log_level : Option < LevelFilter > ,
267+ buf_id : Option < LogId > ,
218268 filter : Option < env_logger:: filter:: Filter > ,
219269 tag : Option < CString > ,
220270 custom_format : Option < FormatFn > ,
@@ -241,6 +291,17 @@ impl Config {
241291 self
242292 }
243293
294+ /// Changes the Android logging system buffer to be used.
295+ ///
296+ /// By default, logs are sent to the [`Main`] log. Other logging buffers may
297+ /// only be accessible to certain processes.
298+ ///
299+ /// [`Main`]: LogId::Main
300+ pub fn with_log_buffer ( mut self , buf_id : LogId ) -> Self {
301+ self . buf_id = Some ( buf_id) ;
302+ self
303+ }
304+
244305 fn filter_matches ( & self , record : & Record ) -> bool {
245306 if let Some ( ref filter) = self . filter {
246307 filter. matches ( record)
@@ -282,6 +343,10 @@ pub struct PlatformLogWriter<'a> {
282343 priority : LogPriority ,
283344 #[ cfg( not( target_os = "android" ) ) ]
284345 priority : Level ,
346+ #[ cfg( target_os = "android" ) ]
347+ buf_id : log_ffi:: log_id_t ,
348+ #[ cfg( not( target_os = "android" ) ) ]
349+ buf_id : Option < LogId > ,
285350 len : usize ,
286351 last_newline_index : usize ,
287352 tag : & ' a CStr ,
@@ -290,10 +355,15 @@ pub struct PlatformLogWriter<'a> {
290355
291356impl < ' a > PlatformLogWriter < ' a > {
292357 #[ cfg( target_os = "android" ) ]
293- pub fn new_with_priority ( priority : log_ffi:: LogPriority , tag : & CStr ) -> PlatformLogWriter {
358+ pub fn new_with_priority (
359+ buf_id : Option < LogId > ,
360+ priority : log_ffi:: LogPriority ,
361+ tag : & CStr ,
362+ ) -> PlatformLogWriter < ' _ > {
294363 #[ allow( deprecated) ] // created an issue #35 for this
295364 PlatformLogWriter {
296365 priority,
366+ buf_id : LogId :: to_native ( buf_id) ,
297367 len : 0 ,
298368 last_newline_index : 0 ,
299369 tag,
@@ -302,8 +372,9 @@ impl<'a> PlatformLogWriter<'a> {
302372 }
303373
304374 #[ cfg( target_os = "android" ) ]
305- pub fn new ( level : Level , tag : & CStr ) -> PlatformLogWriter {
306- Self :: new_with_priority (
375+ pub fn new ( buf_id : Option < LogId > , level : Level , tag : & CStr ) -> PlatformLogWriter < ' _ > {
376+ PlatformLogWriter :: new_with_priority (
377+ buf_id,
307378 match level {
308379 Level :: Warn => LogPriority :: WARN ,
309380 Level :: Info => LogPriority :: INFO ,
@@ -316,10 +387,11 @@ impl<'a> PlatformLogWriter<'a> {
316387 }
317388
318389 #[ cfg( not( target_os = "android" ) ) ]
319- pub fn new ( level : Level , tag : & CStr ) -> PlatformLogWriter {
390+ pub fn new ( buf_id : Option < LogId > , level : Level , tag : & CStr ) -> PlatformLogWriter < ' _ > {
320391 #[ allow( deprecated) ] // created an issue #35 for this
321392 PlatformLogWriter {
322393 priority : level,
394+ buf_id,
323395 len : 0 ,
324396 last_newline_index : 0 ,
325397 tag,
@@ -376,7 +448,7 @@ impl<'a> PlatformLogWriter<'a> {
376448 } ) ;
377449
378450 let msg: & CStr = unsafe { CStr :: from_ptr ( self . buffer . as_ptr ( ) . cast ( ) ) } ;
379- android_log ( self . priority , self . tag , msg) ;
451+ android_log ( self . buf_id , self . priority , self . tag , msg) ;
380452
381453 unsafe { * self . buffer . get_unchecked_mut ( len) = last_byte } ;
382454 }
@@ -481,9 +553,11 @@ mod tests {
481553 // Filter is checked in config_filter_match below.
482554 let config = Config :: default ( )
483555 . with_max_level ( LevelFilter :: Trace )
556+ . with_log_buffer ( LogId :: System )
484557 . with_tag ( "my_app" ) ;
485558
486559 assert_eq ! ( config. log_level, Some ( LevelFilter :: Trace ) ) ;
560+ assert_eq ! ( config. buf_id, Some ( LogId :: System ) ) ;
487561 assert_eq ! ( config. tag, Some ( CString :: new( "my_app" ) . unwrap( ) ) ) ;
488562 }
489563
@@ -556,7 +630,7 @@ mod tests {
556630 fn platform_log_writer_init_values ( ) {
557631 let tag = CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ;
558632
559- let writer = PlatformLogWriter :: new ( Level :: Warn , tag) ;
633+ let writer = PlatformLogWriter :: new ( None , Level :: Warn , tag) ;
560634
561635 assert_eq ! ( writer. tag, tag) ;
562636 // Android uses LogPriority instead, which doesn't implement equality checks
@@ -661,7 +735,11 @@ mod tests {
661735 }
662736
663737 fn get_tag_writer ( ) -> PlatformLogWriter < ' static > {
664- PlatformLogWriter :: new ( Level :: Warn , CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) )
738+ PlatformLogWriter :: new (
739+ None ,
740+ Level :: Warn ,
741+ CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ,
742+ )
665743 }
666744
667745 unsafe fn assume_init_slice < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
0 commit comments