@@ -85,21 +85,70 @@ pub use env_logger::fmt::Formatter;
85
85
86
86
pub ( crate ) type FormatFn = Box < dyn Fn ( & mut dyn fmt:: Write , & Record ) -> fmt:: Result + Sync + Send > ;
87
87
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
+
89
119
#[ 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 ) {
91
139
unsafe {
92
- log_ffi:: __android_log_write (
140
+ log_ffi:: __android_log_buf_write (
141
+ buf_id as log_ffi:: c_int ,
93
142
prio as log_ffi:: c_int ,
94
143
tag. as_ptr ( ) as * const log_ffi:: c_char ,
95
144
msg. as_ptr ( ) as * const log_ffi:: c_char ,
96
- )
145
+ ) ;
97
146
} ;
98
147
}
99
148
100
149
/// Dummy output placeholder for tests.
101
150
#[ 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 ) { }
103
152
104
153
/// Underlying android logger backend
105
154
pub struct AndroidLogger {
@@ -172,7 +221,7 @@ impl Log for AndroidLogger {
172
221
173
222
// message must not exceed LOGGING_MSG_MAX_LEN
174
223
// 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) ;
176
225
177
226
// If a custom tag is used, add the module path to the message.
178
227
// Use PlatformLogWriter to output chunks if they exceed max size.
@@ -215,6 +264,7 @@ impl AndroidLogger {
215
264
#[ derive( Default ) ]
216
265
pub struct Config {
217
266
log_level : Option < LevelFilter > ,
267
+ buf_id : Option < LogId > ,
218
268
filter : Option < env_logger:: filter:: Filter > ,
219
269
tag : Option < CString > ,
220
270
custom_format : Option < FormatFn > ,
@@ -241,6 +291,17 @@ impl Config {
241
291
self
242
292
}
243
293
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
+
244
305
fn filter_matches ( & self , record : & Record ) -> bool {
245
306
if let Some ( ref filter) = self . filter {
246
307
filter. matches ( record)
@@ -282,6 +343,10 @@ pub struct PlatformLogWriter<'a> {
282
343
priority : LogPriority ,
283
344
#[ cfg( not( target_os = "android" ) ) ]
284
345
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 > ,
285
350
len : usize ,
286
351
last_newline_index : usize ,
287
352
tag : & ' a CStr ,
@@ -290,10 +355,15 @@ pub struct PlatformLogWriter<'a> {
290
355
291
356
impl < ' a > PlatformLogWriter < ' a > {
292
357
#[ 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 < ' _ > {
294
363
#[ allow( deprecated) ] // created an issue #35 for this
295
364
PlatformLogWriter {
296
365
priority,
366
+ buf_id : LogId :: to_native ( buf_id) ,
297
367
len : 0 ,
298
368
last_newline_index : 0 ,
299
369
tag,
@@ -302,8 +372,9 @@ impl<'a> PlatformLogWriter<'a> {
302
372
}
303
373
304
374
#[ 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,
307
378
match level {
308
379
Level :: Warn => LogPriority :: WARN ,
309
380
Level :: Info => LogPriority :: INFO ,
@@ -316,10 +387,11 @@ impl<'a> PlatformLogWriter<'a> {
316
387
}
317
388
318
389
#[ 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 < ' _ > {
320
391
#[ allow( deprecated) ] // created an issue #35 for this
321
392
PlatformLogWriter {
322
393
priority : level,
394
+ buf_id,
323
395
len : 0 ,
324
396
last_newline_index : 0 ,
325
397
tag,
@@ -376,7 +448,7 @@ impl<'a> PlatformLogWriter<'a> {
376
448
} ) ;
377
449
378
450
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) ;
380
452
381
453
unsafe { * self . buffer . get_unchecked_mut ( len) = last_byte } ;
382
454
}
@@ -481,9 +553,11 @@ mod tests {
481
553
// Filter is checked in config_filter_match below.
482
554
let config = Config :: default ( )
483
555
. with_max_level ( LevelFilter :: Trace )
556
+ . with_log_buffer ( LogId :: System )
484
557
. with_tag ( "my_app" ) ;
485
558
486
559
assert_eq ! ( config. log_level, Some ( LevelFilter :: Trace ) ) ;
560
+ assert_eq ! ( config. buf_id, Some ( LogId :: System ) ) ;
487
561
assert_eq ! ( config. tag, Some ( CString :: new( "my_app" ) . unwrap( ) ) ) ;
488
562
}
489
563
@@ -556,7 +630,7 @@ mod tests {
556
630
fn platform_log_writer_init_values ( ) {
557
631
let tag = CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ;
558
632
559
- let writer = PlatformLogWriter :: new ( Level :: Warn , tag) ;
633
+ let writer = PlatformLogWriter :: new ( None , Level :: Warn , tag) ;
560
634
561
635
assert_eq ! ( writer. tag, tag) ;
562
636
// Android uses LogPriority instead, which doesn't implement equality checks
@@ -661,7 +735,11 @@ mod tests {
661
735
}
662
736
663
737
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
+ )
665
743
}
666
744
667
745
unsafe fn assume_init_slice < T > ( slice : & [ MaybeUninit < T > ] ) -> & [ T ] {
0 commit comments