6565
6666#[ cfg( target_os = "android" ) ]
6767extern 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 ;
7070#[ macro_use]
7171extern crate log;
7272
7373extern crate env_logger;
7474
75- use std:: sync:: RwLock ;
76-
7775#[ cfg( target_os = "android" ) ]
7876use log_ffi:: LogPriority ;
7977use log:: { Level , Log , Metadata , Record } ;
@@ -105,21 +103,20 @@ fn android_log(_priority: Level, _tag: &CStr, _msg: &CStr) {}
105103
106104/// Underlying android logger backend
107105pub struct AndroidLogger {
108- config : RwLock < Config > ,
106+ config : OnceCell < Config > ,
109107}
110108
111109impl AndroidLogger {
112110 /// Create new logger instance from config
113111 pub fn new ( config : Config ) -> AndroidLogger {
114112 AndroidLogger {
115- config : RwLock :: new ( config) ,
113+ config : OnceCell :: from ( config) ,
116114 }
117115 }
118116}
119117
120- lazy_static ! {
121- static ref ANDROID_LOGGER : AndroidLogger = AndroidLogger :: default ( ) ;
122- }
118+
119+ static ANDROID_LOGGER : OnceCell < AndroidLogger > = OnceCell :: new ( ) ;
123120
124121const LOGGING_TAG_MAX_LEN : usize = 23 ;
125122const LOGGING_MSG_MAX_LEN : usize = 4000 ;
@@ -128,7 +125,7 @@ impl Default for AndroidLogger {
128125 /// Create a new logger with default config
129126 fn default ( ) -> AndroidLogger {
130127 AndroidLogger {
131- config : RwLock :: new ( Config :: default ( ) ) ,
128+ config : OnceCell :: from ( Config :: default ( ) ) ,
132129 }
133130 }
134131}
@@ -140,8 +137,7 @@ impl Log for AndroidLogger {
140137
141138 fn log ( & self , record : & Record ) {
142139 let config = self . config
143- . read ( )
144- . expect ( "failed to acquire android_log filter lock for read" ) ;
140+ . get_or_init ( Config :: default) ;
145141
146142 if !config. filter_matches ( record) {
147143 return ;
@@ -155,7 +151,7 @@ impl Log for AndroidLogger {
155151
156152 // If no tag was specified, use module name
157153 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 ( ) ) ;
159155
160156 // truncate the tag here to fit into LOGGING_TAG_MAX_LEN
161157 self . fill_tag_bytes ( & mut tag_bytes, tag) ;
@@ -206,24 +202,14 @@ impl AndroidLogger {
206202}
207203
208204/// Filter for android logger.
205+ #[ derive( Default ) ]
209206pub struct Config {
210207 log_level : Option < Level > ,
211208 filter : Option < env_logger:: filter:: Filter > ,
212209 tag : Option < CString > ,
213210 custom_format : Option < FormatFn > ,
214211}
215212
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-
227213impl Config {
228214 /// Change the minimum log level.
229215 ///
@@ -236,7 +222,7 @@ impl Config {
236222
237223 fn filter_matches ( & self , record : & Record ) -> bool {
238224 if let Some ( ref filter) = self . filter {
239- filter. matches ( & record)
225+ filter. matches ( record)
240226 } else {
241227 true
242228 }
@@ -365,7 +351,7 @@ impl<'a> PlatformLogWriter<'a> {
365351
366352 /// Copy `len` bytes from `index` position to starting position.
367353 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) } ;
369355 let dst = self . buffer . as_mut_ptr ( ) ;
370356 unsafe { ptr:: copy ( src, dst, len) } ;
371357 }
@@ -423,7 +409,7 @@ impl<'a> fmt::Write for PlatformLogWriter<'a> {
423409/// This action does not require initialization. However, without initialization it
424410/// will use the default filter, which allows all logs.
425411pub fn log ( record : & Record ) {
426- ANDROID_LOGGER . log ( record)
412+ ANDROID_LOGGER . get_or_init ( AndroidLogger :: default ) . log ( record)
427413}
428414
429415/// Initializes the global logger with an android logger.
@@ -434,16 +420,13 @@ pub fn log(record: &Record) {
434420/// It is ok to call this at the activity creation, and it will be
435421/// repeatedly called on every lifecycle restart (i.e. screen rotation).
436422pub 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) {
438427 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 ( ) ) ;
447430 }
448431}
449432
@@ -531,7 +514,7 @@ mod tests {
531514 fn platform_log_writer_init_values ( ) {
532515 let tag = CStr :: from_bytes_with_nul ( b"tag\0 " ) . unwrap ( ) ;
533516
534- let writer = PlatformLogWriter :: new ( Level :: Warn , & tag) ;
517+ let writer = PlatformLogWriter :: new ( Level :: Warn , tag) ;
535518
536519 assert_eq ! ( writer. tag, tag) ;
537520 // Android uses LogPriority instead, which doesn't implement equality checks
@@ -630,6 +613,6 @@ mod tests {
630613 }
631614
632615 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 ( ) )
634617 }
635618}
0 commit comments