65
65
66
66
#[ cfg( target_os = "android" ) ]
67
67
extern crate android_log_sys as log_ffi;
68
- # [ macro_use ]
69
- extern crate lazy_static ;
68
+ extern crate once_cell ;
69
+ use once_cell :: sync :: OnceCell ;
70
70
#[ macro_use]
71
71
extern crate log;
72
72
73
73
extern crate env_logger;
74
74
75
- use std:: sync:: RwLock ;
76
-
77
75
#[ cfg( target_os = "android" ) ]
78
76
use log_ffi:: LogPriority ;
79
77
use log:: { Level , Log , Metadata , Record } ;
@@ -105,21 +103,20 @@ fn android_log(_priority: Level, _tag: &CStr, _msg: &CStr) {}
105
103
106
104
/// Underlying android logger backend
107
105
pub struct AndroidLogger {
108
- config : RwLock < Config > ,
106
+ config : OnceCell < Config > ,
109
107
}
110
108
111
109
impl AndroidLogger {
112
110
/// Create new logger instance from config
113
111
pub fn new ( config : Config ) -> AndroidLogger {
114
112
AndroidLogger {
115
- config : RwLock :: new ( config) ,
113
+ config : OnceCell :: from ( config) ,
116
114
}
117
115
}
118
116
}
119
117
120
- lazy_static ! {
121
- static ref ANDROID_LOGGER : AndroidLogger = AndroidLogger :: default ( ) ;
122
- }
118
+
119
+ static ANDROID_LOGGER : OnceCell < AndroidLogger > = OnceCell :: new ( ) ;
123
120
124
121
const LOGGING_TAG_MAX_LEN : usize = 23 ;
125
122
const LOGGING_MSG_MAX_LEN : usize = 4000 ;
@@ -128,7 +125,7 @@ impl Default for AndroidLogger {
128
125
/// Create a new logger with default config
129
126
fn default ( ) -> AndroidLogger {
130
127
AndroidLogger {
131
- config : RwLock :: new ( Config :: default ( ) ) ,
128
+ config : OnceCell :: from ( Config :: default ( ) ) ,
132
129
}
133
130
}
134
131
}
@@ -140,8 +137,7 @@ impl Log for AndroidLogger {
140
137
141
138
fn log ( & self , record : & Record ) {
142
139
let config = self . config
143
- . read ( )
144
- . expect ( "failed to acquire android_log filter lock for read" ) ;
140
+ . get_or_init ( Config :: default) ;
145
141
146
142
if !config. filter_matches ( record) {
147
143
return ;
@@ -155,7 +151,7 @@ impl Log for AndroidLogger {
155
151
156
152
// If no tag was specified, use module name
157
153
let custom_tag = & config. tag ;
158
- let tag = custom_tag. as_ref ( ) . map ( |s| s. as_bytes ( ) ) . unwrap_or ( module_path. as_bytes ( ) ) ;
154
+ let tag = custom_tag. as_ref ( ) . map ( |s| s. as_bytes ( ) ) . unwrap_or_else ( || module_path. as_bytes ( ) ) ;
159
155
160
156
// truncate the tag here to fit into LOGGING_TAG_MAX_LEN
161
157
self . fill_tag_bytes ( & mut tag_bytes, tag) ;
@@ -206,24 +202,14 @@ impl AndroidLogger {
206
202
}
207
203
208
204
/// Filter for android logger.
205
+ #[ derive( Default ) ]
209
206
pub struct Config {
210
207
log_level : Option < Level > ,
211
208
filter : Option < env_logger:: filter:: Filter > ,
212
209
tag : Option < CString > ,
213
210
custom_format : Option < FormatFn > ,
214
211
}
215
212
216
- impl Default for Config {
217
- fn default ( ) -> Self {
218
- Config {
219
- log_level : None ,
220
- filter : None ,
221
- tag : None ,
222
- custom_format : None ,
223
- }
224
- }
225
- }
226
-
227
213
impl Config {
228
214
/// Change the minimum log level.
229
215
///
@@ -236,7 +222,7 @@ impl Config {
236
222
237
223
fn filter_matches ( & self , record : & Record ) -> bool {
238
224
if let Some ( ref filter) = self . filter {
239
- filter. matches ( & record)
225
+ filter. matches ( record)
240
226
} else {
241
227
true
242
228
}
@@ -365,7 +351,7 @@ impl<'a> PlatformLogWriter<'a> {
365
351
366
352
/// Copy `len` bytes from `index` position to starting position.
367
353
fn copy_bytes_to_start ( & mut self , index : usize , len : usize ) {
368
- let src = unsafe { self . buffer . as_ptr ( ) . offset ( index as isize ) } ;
354
+ let src = unsafe { self . buffer . as_ptr ( ) . add ( index) } ;
369
355
let dst = self . buffer . as_mut_ptr ( ) ;
370
356
unsafe { ptr:: copy ( src, dst, len) } ;
371
357
}
@@ -423,7 +409,7 @@ impl<'a> fmt::Write for PlatformLogWriter<'a> {
423
409
/// This action does not require initialization. However, without initialization it
424
410
/// will use the default filter, which allows all logs.
425
411
pub fn log ( record : & Record ) {
426
- ANDROID_LOGGER . log ( record)
412
+ ANDROID_LOGGER . get_or_init ( AndroidLogger :: default ) . log ( record)
427
413
}
428
414
429
415
/// Initializes the global logger with an android logger.
@@ -434,16 +420,13 @@ pub fn log(record: &Record) {
434
420
/// It is ok to call this at the activity creation, and it will be
435
421
/// repeatedly called on every lifecycle restart (i.e. screen rotation).
436
422
pub fn init_once ( config : Config ) {
437
- if let Err ( err) = log:: set_logger ( & * ANDROID_LOGGER ) {
423
+ let log_level = config. log_level ;
424
+ let logger = ANDROID_LOGGER . get_or_init ( || AndroidLogger :: new ( config) ) ;
425
+
426
+ if let Err ( err) = log:: set_logger ( logger) {
438
427
debug ! ( "android_logger: log::set_logger failed: {}" , err) ;
439
- } else {
440
- if let Some ( level) = config. log_level {
441
- log:: set_max_level ( level. to_level_filter ( ) ) ;
442
- }
443
- * ANDROID_LOGGER
444
- . config
445
- . write ( )
446
- . expect ( "failed to acquire android_log filter lock for write" ) = config;
428
+ } else if let Some ( level) = log_level {
429
+ log:: set_max_level ( level. to_level_filter ( ) ) ;
447
430
}
448
431
}
449
432
@@ -531,7 +514,7 @@ mod tests {
531
514
fn platform_log_writer_init_values ( ) {
532
515
let tag = CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ;
533
516
534
- let writer = PlatformLogWriter :: new ( Level :: Warn , & tag) ;
517
+ let writer = PlatformLogWriter :: new ( Level :: Warn , tag) ;
535
518
536
519
assert_eq ! ( writer. tag, tag) ;
537
520
// Android uses LogPriority instead, which doesn't implement equality checks
@@ -630,6 +613,6 @@ mod tests {
630
613
}
631
614
632
615
fn get_tag_writer ( ) -> PlatformLogWriter < ' static > {
633
- PlatformLogWriter :: new ( Level :: Warn , & CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) )
616
+ PlatformLogWriter :: new ( Level :: Warn , CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) )
634
617
}
635
618
}
0 commit comments