@@ -85,21 +85,69 @@ 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+ /// Identifies a specific log buffer to use when logging a message.
89+ #[ derive( Copy , Clone , Eq , PartialEq , Debug ) ]
90+ pub enum LogId {
91+ /// The main log buffer.
92+ ///
93+ /// This is the only log buffer available to apps.
94+ Main ,
95+
96+ /// The radio log buffer.
97+ Radio ,
98+
99+ /// The event log buffer.
100+ Events ,
101+
102+ /// The system log buffer.
103+ System ,
104+
105+ /// The crash log buffer.
106+ Crash ,
107+
108+ /// The kernel log buffer.
109+ Kernel ,
110+
111+ /// The security log buffer.
112+ Security ,
113+
114+ /// The statistics log buffer.
115+ Stats ,
116+ }
117+
118+ impl LogId {
119+ #[ cfg( target_os = "android" ) ]
120+ fn to_native ( log_id : Option < Self > ) -> log_ffi:: log_id_t {
121+ match log_id {
122+ Some ( LogId :: Main ) => log_ffi:: log_id_t:: MAIN ,
123+ Some ( LogId :: Radio ) => log_ffi:: log_id_t:: RADIO ,
124+ Some ( LogId :: Events ) => log_ffi:: log_id_t:: EVENTS ,
125+ Some ( LogId :: System ) => log_ffi:: log_id_t:: SYSTEM ,
126+ Some ( LogId :: Crash ) => log_ffi:: log_id_t:: CRASH ,
127+ Some ( LogId :: Kernel ) => log_ffi:: log_id_t:: KERNEL ,
128+ Some ( LogId :: Security ) => log_ffi:: log_id_t:: SECURITY ,
129+ Some ( LogId :: Stats ) => log_ffi:: log_id_t:: STATS ,
130+ None => log_ffi:: log_id_t:: DEFAULT ,
131+ }
132+ }
133+ }
134+
88135/// Output log to android system.
89136#[ cfg( target_os = "android" ) ]
90- fn android_log ( prio : log_ffi:: LogPriority , tag : & CStr , msg : & CStr ) {
137+ fn android_log ( log_id : log_ffi :: log_id_t , prio : log_ffi:: LogPriority , tag : & CStr , msg : & CStr ) {
91138 unsafe {
92- log_ffi:: __android_log_write (
93- prio as log_ffi:: c_int ,
139+ log_ffi:: __android_log_buf_write (
140+ log_id as i32 ,
141+ prio as i32 ,
94142 tag. as_ptr ( ) as * const log_ffi:: c_char ,
95143 msg. as_ptr ( ) as * const log_ffi:: c_char ,
96- )
144+ ) ;
97145 } ;
98146}
99147
100148/// Dummy output placeholder for tests.
101149#[ cfg( not( target_os = "android" ) ) ]
102- fn android_log ( _priority : Level , _tag : & CStr , _msg : & CStr ) { }
150+ fn android_log ( _log_id : Option < LogId > , _priority : Level , _tag : & CStr , _msg : & CStr ) { }
103151
104152/// Underlying android logger backend
105153pub struct AndroidLogger {
@@ -172,7 +220,7 @@ impl Log for AndroidLogger {
172220
173221 // message must not exceed LOGGING_MSG_MAX_LEN
174222 // therefore split log message into multiple log calls
175- let mut writer = PlatformLogWriter :: new ( record. level ( ) , tag) ;
223+ let mut writer = PlatformLogWriter :: new ( config . log_id , record. level ( ) , tag) ;
176224
177225 // If a custom tag is used, add the module path to the message.
178226 // Use PlatformLogWriter to output chunks if they exceed max size.
@@ -215,6 +263,7 @@ impl AndroidLogger {
215263#[ derive( Default ) ]
216264pub struct Config {
217265 log_level : Option < LevelFilter > ,
266+ log_id : Option < LogId > ,
218267 filter : Option < env_logger:: filter:: Filter > ,
219268 tag : Option < CString > ,
220269 custom_format : Option < FormatFn > ,
@@ -241,6 +290,15 @@ impl Config {
241290 self
242291 }
243292
293+ /// Change which log buffer is used
294+ ///
295+ /// By default, logs are sent to the `Main` log. Other logging buffers may only be accessible
296+ /// to certain processes.
297+ pub fn with_log_id ( mut self , log_id : LogId ) -> Self {
298+ self . log_id = Some ( log_id) ;
299+ self
300+ }
301+
244302 fn filter_matches ( & self , record : & Record ) -> bool {
245303 if let Some ( ref filter) = self . filter {
246304 filter. matches ( record)
@@ -282,6 +340,10 @@ pub struct PlatformLogWriter<'a> {
282340 priority : LogPriority ,
283341 #[ cfg( not( target_os = "android" ) ) ]
284342 priority : Level ,
343+ #[ cfg( target_os = "android" ) ]
344+ log_id : log_ffi:: log_id_t ,
345+ #[ cfg( not( target_os = "android" ) ) ]
346+ log_id : Option < LogId > ,
285347 len : usize ,
286348 last_newline_index : usize ,
287349 tag : & ' a CStr ,
@@ -290,9 +352,14 @@ pub struct PlatformLogWriter<'a> {
290352
291353impl < ' a > PlatformLogWriter < ' a > {
292354 #[ cfg( target_os = "android" ) ]
293- pub fn new_with_priority ( priority : log_ffi:: LogPriority , tag : & CStr ) -> PlatformLogWriter {
355+ pub fn new_with_priority (
356+ log_id : Option < LogId > ,
357+ priority : log_ffi:: LogPriority ,
358+ tag : & CStr ,
359+ ) -> PlatformLogWriter {
294360 #[ allow( deprecated) ] // created an issue #35 for this
295361 PlatformLogWriter {
362+ log_id : LogId :: to_native ( log_id) ,
296363 priority,
297364 len : 0 ,
298365 last_newline_index : 0 ,
@@ -302,8 +369,9 @@ impl<'a> PlatformLogWriter<'a> {
302369 }
303370
304371 #[ cfg( target_os = "android" ) ]
305- pub fn new ( level : Level , tag : & CStr ) -> PlatformLogWriter {
372+ pub fn new ( log_id : Option < LogId > , level : Level , tag : & CStr ) -> PlatformLogWriter {
306373 Self :: new_with_priority (
374+ log_id,
307375 match level {
308376 Level :: Warn => LogPriority :: WARN ,
309377 Level :: Info => LogPriority :: INFO ,
@@ -316,10 +384,11 @@ impl<'a> PlatformLogWriter<'a> {
316384 }
317385
318386 #[ cfg( not( target_os = "android" ) ) ]
319- pub fn new ( level : Level , tag : & CStr ) -> PlatformLogWriter {
387+ pub fn new ( log_id : Option < LogId > , level : Level , tag : & CStr ) -> PlatformLogWriter {
320388 #[ allow( deprecated) ] // created an issue #35 for this
321389 PlatformLogWriter {
322390 priority : level,
391+ log_id,
323392 len : 0 ,
324393 last_newline_index : 0 ,
325394 tag,
@@ -375,8 +444,8 @@ impl<'a> PlatformLogWriter<'a> {
375444 self . buffer . get_unchecked_mut ( len)
376445 } ) ;
377446
378- let msg: & CStr = unsafe { CStr :: from_ptr ( self . buffer . as_ptr ( ) . cast ( ) ) } ;
379- android_log ( self . priority , self . tag , msg) ;
447+ let msg: & CStr = unsafe { CStr :: from_ptr ( mem :: transmute ( self . buffer . as_ptr ( ) ) ) } ;
448+ android_log ( self . log_id , self . priority , self . tag , msg) ;
380449
381450 unsafe { * self . buffer . get_unchecked_mut ( len) = last_byte } ;
382451 }
@@ -481,9 +550,11 @@ mod tests {
481550 // Filter is checked in config_filter_match below.
482551 let config = Config :: default ( )
483552 . with_max_level ( LevelFilter :: Trace )
553+ . with_log_id ( LogId :: System )
484554 . with_tag ( "my_app" ) ;
485555
486556 assert_eq ! ( config. log_level, Some ( LevelFilter :: Trace ) ) ;
557+ assert_eq ! ( config. log_id, Some ( LogId :: System ) ) ;
487558 assert_eq ! ( config. tag, Some ( CString :: new( "my_app" ) . unwrap( ) ) ) ;
488559 }
489560
@@ -556,7 +627,7 @@ mod tests {
556627 fn platform_log_writer_init_values ( ) {
557628 let tag = CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ;
558629
559- let writer = PlatformLogWriter :: new ( Level :: Warn , tag) ;
630+ let writer = PlatformLogWriter :: new ( None , Level :: Warn , tag) ;
560631
561632 assert_eq ! ( writer. tag, tag) ;
562633 // Android uses LogPriority instead, which doesn't implement equality checks
@@ -661,7 +732,11 @@ mod tests {
661732 }
662733
663734 fn get_tag_writer ( ) -> PlatformLogWriter < ' static > {
664- PlatformLogWriter :: new ( Level :: Warn , CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) )
735+ PlatformLogWriter :: new (
736+ None ,
737+ Level :: Warn ,
738+ CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ,
739+ )
665740 }
666741
667742 unsafe fn assume_init_slice < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
0 commit comments