Snap for 10453563 from f6151f845dd997a9e324388d07b7142c6c346914 to mainline-ipsec-release

Change-Id: I746748dd3333036c9d54c6ca45935208ad4301f6
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 00435b7..c1be5ef 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "c20ec25acacf0731583140b230e6ce94e59b054d"
-  }
-}
+    "sha1": "596b92d5907f0054884412d2f7137704edae4208"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 056c310..f03803b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,7 +43,7 @@
     name: "android_logger_test_src_lib",
     crate_name: "android_logger",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.10.1",
+    cargo_pkg_version: "0.12.0",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -55,8 +55,8 @@
     rustlibs: [
         "libandroid_log_sys",
         "libenv_logger",
-        "liblazy_static",
         "liblog_rust",
+        "libonce_cell",
     ],
 }
 
@@ -64,7 +64,7 @@
     name: "android_logger_test_defaults",
     crate_name: "android_logger",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.10.1",
+    cargo_pkg_version: "0.12.0",
     test_suites: ["general-tests"],
     auto_gen_config: true,
     edition: "2015",
@@ -76,8 +76,8 @@
         "libandroid_log_sys",
         "libandroid_logger",
         "libenv_logger",
-        "liblazy_static",
         "liblog_rust",
+        "libonce_cell",
     ],
 }
 
@@ -103,7 +103,7 @@
     name: "libandroid_logger",
     crate_name: "android_logger",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.10.1",
+    cargo_pkg_version: "0.12.0",
     srcs: ["src/lib.rs"],
     edition: "2015",
     features: [
@@ -113,17 +113,14 @@
     rustlibs: [
         "libandroid_log_sys",
         "libenv_logger",
-        "liblazy_static",
         "liblog_rust",
+        "libonce_cell",
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
-        "com.android.compos",
-        "com.android.resolv",
-        "com.android.uwb",
-        "com.android.virt",
+        "//apex_available:anyapex",
     ],
+    product_available: true,
     vendor_available: true,
     min_sdk_version: "29",
 }
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..4952ca1
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,54 @@
+`android_logger` changelog
+==========================
+
+All user visible changes to this project will be documented in this file. This project uses [Semantic Versioning 2.0.0].
+
+
+
+
+## [0.12.0] · 2023-01-19
+[0.12.0]: /../../tree/v0.12.0
+
+[Diff](/../../compare/v0.11.3...v0.12.0)
+
+### Added
+
+- `Config::with_max_level()` method to filters logs via `log::LevelFilter`. ([#62])
+
+### Deprecated
+
+- `Config::with_min_level()` method accepting `log::Level`. ([#62])
+
+### Fixed
+
+- Incorrect logs level filtering. ([#62])
+
+[#62]: /../../pull/62
+
+
+
+
+## [0.11.3] · 2022-12-20
+[0.11.3]: /../../tree/v0.11.3
+
+[Diff](/../../compare/38186ece1056d90b8f75fd2a5eb5c860e0a1704e...v0.11.3)
+
+### Fixed 
+
+- Broken compilation on [Android] targets. ([#59], [#58])
+
+[#58]: /../../issues/58
+[#59]: /../../pull/59
+
+
+
+
+## Previous releases
+
+See [Git log](/../../commits/master?after=1a5a07ec6742f0069acc2be223c1bb3b6a9d15f8+0).
+
+
+
+
+[Android]: https://www.android.com
+[Semantic Versioning 2.0.0]: https://semver.org
diff --git a/Cargo.toml b/Cargo.toml
index dec0113..a9fd573 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,38 +3,46 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 name = "android_logger"
-version = "0.10.1"
+version = "0.12.0"
 authors = ["The android_logger Developers"]
-description = "A logging implementation for `log` which hooks to android log output.\n"
+description = """
+A logging implementation for `log` which hooks to android log output.
+"""
 readme = "README.md"
-keywords = ["android", "bindings", "log", "logger"]
+keywords = [
+    "android",
+    "bindings",
+    "log",
+    "logger",
+]
 categories = ["api-bindings"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/Nercury/android_logger-rs"
+
 [dependencies.android_log-sys]
 version = "0.2"
 
 [dependencies.env_logger]
-version = "0.8"
+version = "0.10"
 default-features = false
 
-[dependencies.lazy_static]
-version = "1.4"
-
 [dependencies.log]
 version = "0.4"
 
+[dependencies.once_cell]
+version = "1.9"
+
 [features]
 default = ["regex"]
 regex = ["env_logger/regex"]
+
 [badges.travis-ci]
 repository = "Nercury/android_logger-rs"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index a9ad77f..ca1b723 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "android_logger"
-version = "0.10.1"
+version = "0.12.0"
 authors = ["The android_logger Developers"]
 license = "MIT OR Apache-2.0"
 readme = "README.md"
@@ -16,7 +16,7 @@
 regex = ["env_logger/regex"]
 
 [dependencies]
-lazy_static = "1.4"
+once_cell = "1.9"
 
 [dependencies.log]
 version = "0.4"
@@ -25,7 +25,7 @@
 version = "0.2"
 
 [dependencies.env_logger]
-version = "0.8"
+version = "0.10"
 default-features = false
 
 [badges]
diff --git a/METADATA b/METADATA
index 27e229f..df2996f 100644
--- a/METADATA
+++ b/METADATA
@@ -1,5 +1,5 @@
 name: "android_logger"
-description: "A logging implementation for `log` which hooks to android log output."
+description: "()"
 third_party {
   url {
     type: HOMEPAGE
@@ -7,13 +7,14 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/android_logger/android_logger-0.10.1.crate"
+    value: "https://static.crates.io/crates/android_logger/android_logger-0.12.0.crate"
   }
-  version: "0.10.1"
+  version: "0.12.0"
+  # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same.
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 4
-    day: 19
+    year: 2023
+    month: 2
+    day: 2
   }
 }
diff --git a/OWNERS b/OWNERS
index 46fc303..45dc4dd 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1 +1 @@
-include platform/prebuilts/rust:/OWNERS
+include platform/prebuilts/rust:master:/OWNERS
diff --git a/README.md b/README.md
index c3b88bf..eec1eba 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
 
 ```toml
 [target.'cfg(target_os = "android")'.dependencies]
-android_logger = "0.10"
+android_logger = "0.11"
 ```
 
 Example of initialization on activity creation, with log configuration:
@@ -22,13 +22,13 @@
 #[macro_use] extern crate log;
 extern crate android_logger;
 
-use log::Level;
+use log::LevelFilter;
 use android_logger::{Config,FilterBuilder};
 
 fn native_activity_create() {
     android_logger::init_once(
         Config::default()
-            .with_min_level(Level::Trace) // limit log level
+            .with_max_level(LevelFilter::Trace) // limit log level
             .with_tag("mytag") // logs will show under mytag tag
             .with_filter( // configure messages for specific crate
                 FilterBuilder::new()
@@ -47,12 +47,13 @@
 #[macro_use] extern crate log;
 extern crate android_logger;
 
-use log::Level;
+use log::LevelFilter;
 use android_logger::Config;
 
 fn native_activity_create() {
     android_logger::init_once(
-        Config::default().with_min_level(Level::Trace));
+        Config::default().with_max_level(LevelFilter::Trace),
+    );
 }
 ```
 
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 526e77a..d42c05d 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,5 +1,28 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
+  "imports": [
+    {
+      "path": "packages/modules/DnsResolver"
+    },
+    {
+      "path": "packages/modules/Virtualization/authfs"
+    },
+    {
+      "path": "packages/modules/Virtualization/encryptedstore"
+    },
+    {
+      "path": "packages/modules/Virtualization/virtualizationmanager"
+    },
+    {
+      "path": "system/logging/rust"
+    },
+    {
+      "path": "system/security/keystore2"
+    },
+    {
+      "path": "system/security/keystore2/selinux"
+    }
+  ],
   "presubmit": [
     {
       "name": "android_logger_test_src_lib"
@@ -12,39 +35,6 @@
     },
     {
       "name": "android_logger_test_tests_multiple_init"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "doh_unit_test"
-    },
-    {
-      "name": "keystore2_selinux_concurrency_test"
-    },
-    {
-      "name": "keystore2_selinux_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "logger_device_unit_tests"
-    },
-    {
-      "name": "logger_test_config_log_level"
-    },
-    {
-      "name": "logger_test_default_init"
-    },
-    {
-      "name": "logger_test_env_log_level"
-    },
-    {
-      "name": "logger_test_multiple_init"
-    },
-    {
-      "name": "virtualizationservice_device_test"
     }
   ],
   "presubmit-rust": [
@@ -59,39 +49,6 @@
     },
     {
       "name": "android_logger_test_tests_multiple_init"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "doh_unit_test"
-    },
-    {
-      "name": "keystore2_selinux_concurrency_test"
-    },
-    {
-      "name": "keystore2_selinux_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "logger_device_unit_tests"
-    },
-    {
-      "name": "logger_test_config_log_level"
-    },
-    {
-      "name": "logger_test_default_init"
-    },
-    {
-      "name": "logger_test_env_log_level"
-    },
-    {
-      "name": "logger_test_multiple_init"
-    },
-    {
-      "name": "virtualizationservice_device_test"
     }
   ]
 }
diff --git a/cargo2android.json b/cargo2android.json
index 18ba06d..2733be4 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,11 +1,7 @@
 {
   "apex-available": [
     "//apex_available:platform",
-    "com.android.bluetooth",
-    "com.android.compos",
-    "com.android.resolv",
-    "com.android.uwb",
-    "com.android.virt"
+    "//apex_available:anyapex"
   ],
   "dependencies": true,
   "device": true,
diff --git a/patches/0001-Support-selecting-target-log-buffer.patch b/patches/0001-Support-selecting-target-log-buffer.patch
index e5fc33b..a9e11a4 100644
--- a/patches/0001-Support-selecting-target-log-buffer.patch
+++ b/patches/0001-Support-selecting-target-log-buffer.patch
@@ -1,6 +1,6 @@
-From 2bc2650d0a7a11a74670a6583b16aa6714d7c993 Mon Sep 17 00:00:00 2001
-From: Matthew Maurer <mmaurer@google.com>
-Date: Thu, 17 Feb 2022 20:23:37 +0000
+From a41a079a81f381f2002917fb1c030690e0798f0c Mon Sep 17 00:00:00 2001
+From: Jeff Vander Stoep <jeffv@google.com>
+Date: Thu, 2 Feb 2023 13:33:47 +0100
 Subject: [PATCH] Support selecting target log buffer
 
 Android has several different log buffers. Previously, this library
@@ -8,16 +8,17 @@
 default log (which is Main for most processes), with the option to
 override which log buffer you send messages to in the config.
 
-Change-Id: I72779e62bd963586e3dfad431cd82c75daf04d92
+Test: atest
+Change-Id: I3cc393b989b8189675581ba6bf700f95715aa9e9
 ---
- src/lib.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++----------
- 1 file changed, 58 insertions(+), 13 deletions(-)
+ src/lib.rs | 73 +++++++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 59 insertions(+), 14 deletions(-)
 
 diff --git a/src/lib.rs b/src/lib.rs
-index 11a127e..d21be3f 100644
+index 0446fad..9ec7f0d 100644
 --- a/src/lib.rs
 +++ b/src/lib.rs
-@@ -87,21 +87,49 @@ pub use env_logger::fmt::Formatter;
+@@ -85,21 +85,49 @@ pub use env_logger::fmt::Formatter;
  
  pub(crate) type FormatFn = Box<dyn Fn(&mut dyn fmt::Write, &Record) -> fmt::Result + Sync + Send>;
  
@@ -74,7 +75,7 @@
  
  /// Underlying android logger backend
  pub struct AndroidLogger {
-@@ -164,7 +192,7 @@ impl Log for AndroidLogger {
+@@ -172,7 +200,7 @@ impl Log for AndroidLogger {
  
          // message must not exceed LOGGING_MSG_MAX_LEN
          // therefore split log message into multiple log calls
@@ -83,23 +84,15 @@
  
          // If a custom tag is used, add the module path to the message.
          // Use PlatformLogWriter to output chunks if they exceed max size.
-@@ -208,6 +236,7 @@ impl AndroidLogger {
- /// Filter for android logger.
+@@ -215,6 +243,7 @@ impl AndroidLogger {
+ #[derive(Default)]
  pub struct Config {
-     log_level: Option<Level>,
+     log_level: Option<LevelFilter>,
 +    log_id: Option<LogId>,
      filter: Option<env_logger::filter::Filter>,
      tag: Option<CString>,
      custom_format: Option<FormatFn>,
-@@ -217,6 +246,7 @@ impl Default for Config {
-     fn default() -> Self {
-         Config {
-             log_level: None,
-+            log_id: None,
-             filter: None,
-             tag: None,
-             custom_format: None,
-@@ -234,6 +264,15 @@ impl Config {
+@@ -241,6 +270,15 @@ impl Config {
          self
      }
  
@@ -114,34 +107,41 @@
 +
      fn filter_matches(&self, record: &Record) -> bool {
          if let Some(ref filter) = self.filter {
-             filter.matches(&record)
-@@ -273,6 +312,8 @@ impl Config {
- struct PlatformLogWriter<'a> {
-     #[cfg(target_os = "android")] priority: LogPriority,
-     #[cfg(not(target_os = "android"))] priority: Level,
+             filter.matches(record)
+@@ -282,6 +320,8 @@ pub struct PlatformLogWriter<'a> {
+     priority: LogPriority,
+     #[cfg(not(target_os = "android"))]
+     priority: Level,
 +    #[cfg(target_os = "android")] log_id: log_ffi::log_id_t,
 +    #[cfg(not(target_os = "android"))] log_id: Option<LogId>,
      len: usize,
      last_newline_index: usize,
      tag: &'a CStr,
-@@ -281,7 +322,7 @@ struct PlatformLogWriter<'a> {
+@@ -290,10 +330,11 @@ pub struct PlatformLogWriter<'a> {
  
  impl<'a> PlatformLogWriter<'a> {
      #[cfg(target_os = "android")]
--    pub fn new(level: Level, tag: &CStr) -> PlatformLogWriter {
-+    pub fn new(log_id: Option<LogId>, level: Level, tag: &CStr) -> PlatformLogWriter {
+-    pub fn new_with_priority(priority: log_ffi::LogPriority, tag: &CStr) -> PlatformLogWriter {
++    pub fn new_with_priority(log_id: Option<LogId>, priority: log_ffi::LogPriority, tag: &CStr) -> PlatformLogWriter {
          #[allow(deprecated)] // created an issue #35 for this
          PlatformLogWriter {
-             priority: match level {
-@@ -291,6 +332,7 @@ impl<'a> PlatformLogWriter<'a> {
-                 Level::Error => LogPriority::ERROR,
-                 Level::Trace => LogPriority::VERBOSE,
-             },
+             priority,
 +            log_id: LogId::to_native(log_id),
              len: 0,
              last_newline_index: 0,
              tag,
-@@ -299,10 +341,11 @@ impl<'a> PlatformLogWriter<'a> {
+@@ -302,8 +343,9 @@ impl<'a> PlatformLogWriter<'a> {
+     }
+ 
+     #[cfg(target_os = "android")]
+-    pub fn new(level: Level, tag: &CStr) -> PlatformLogWriter {
++    pub fn new(log_id: Option<LogId>, level: Level, tag: &CStr) -> PlatformLogWriter {
+         Self::new_with_priority(
++            log_id,
+             match level {
+                 Level::Warn => LogPriority::WARN,
+                 Level::Info => LogPriority::INFO,
+@@ -316,10 +358,11 @@ impl<'a> PlatformLogWriter<'a> {
      }
  
      #[cfg(not(target_os = "android"))]
@@ -154,44 +154,45 @@
              len: 0,
              last_newline_index: 0,
              tag,
-@@ -358,7 +401,7 @@ impl<'a> PlatformLogWriter<'a> {
+@@ -376,7 +419,7 @@ impl<'a> PlatformLogWriter<'a> {
          });
  
-         let msg: &CStr = unsafe { CStr::from_ptr(mem::transmute(self.buffer.as_ptr())) };
+         let msg: &CStr = unsafe { CStr::from_ptr(self.buffer.as_ptr().cast()) };
 -        android_log(self.priority, self.tag, msg);
 +        android_log(self.log_id, self.priority, self.tag, msg);
  
-         *unsafe { self.buffer.get_unchecked_mut(len) } = last_byte;
+         unsafe { *self.buffer.get_unchecked_mut(len) = last_byte };
      }
-@@ -458,9 +501,11 @@ mod tests {
+@@ -481,9 +524,11 @@ mod tests {
          // Filter is checked in config_filter_match below.
          let config = Config::default()
-             .with_min_level(Level::Trace)
+             .with_max_level(LevelFilter::Trace)
 +            .with_log_id(LogId::System)
              .with_tag("my_app");
  
-         assert_eq!(config.log_level, Some(Level::Trace));
+         assert_eq!(config.log_level, Some(LevelFilter::Trace));
 +        assert_eq!(config.log_id, Some(LogId::System));
          assert_eq!(config.tag, Some(CString::new("my_app").unwrap()));
      }
  
-@@ -531,7 +576,7 @@ mod tests {
+@@ -556,7 +601,7 @@ mod tests {
      fn platform_log_writer_init_values() {
          let tag = CStr::from_bytes_with_nul(b"tag\0").unwrap();
  
--        let writer = PlatformLogWriter::new(Level::Warn, &tag);
-+        let writer = PlatformLogWriter::new(None, Level::Warn, &tag);
+-        let writer = PlatformLogWriter::new(Level::Warn, tag);
++        let writer = PlatformLogWriter::new(None, Level::Warn, tag);
  
          assert_eq!(writer.tag, tag);
          // Android uses LogPriority instead, which doesn't implement equality checks
-@@ -630,6 +675,6 @@ mod tests {
+@@ -661,7 +706,7 @@ mod tests {
      }
  
      fn get_tag_writer() -> PlatformLogWriter<'static> {
--        PlatformLogWriter::new(Level::Warn, &CStr::from_bytes_with_nul(b"tag\0").unwrap())
-+        PlatformLogWriter::new(None, Level::Warn, &CStr::from_bytes_with_nul(b"tag\0").unwrap())
+-        PlatformLogWriter::new(Level::Warn, CStr::from_bytes_with_nul(b"tag\0").unwrap())
++        PlatformLogWriter::new(None, Level::Warn, CStr::from_bytes_with_nul(b"tag\0").unwrap())
      }
- }
+ 
+     unsafe fn assume_init_slice<T>(slice: &[MaybeUninit<T>]) -> &[T] {
 -- 
-2.35.1.265.g69c8d7142f-goog
+2.39.1.456.gfc5497dd1b-goog
 
diff --git a/patches/0002-Use-older-API-to-avoid-requiring-API-v30.patch b/patches/0002-Use-older-API-to-avoid-requiring-API-v30.patch
index 721e9eb..44f08fb 100644
--- a/patches/0002-Use-older-API-to-avoid-requiring-API-v30.patch
+++ b/patches/0002-Use-older-API-to-avoid-requiring-API-v30.patch
@@ -1,20 +1,20 @@
-From ec84856e0f0bc5a307529122bfed3d94d2ef4011 Mon Sep 17 00:00:00 2001
-From: Matthew Maurer <mmaurer@google.com>
-Date: Thu, 24 Feb 2022 14:07:03 -0800
-Subject: [PATCH] Use older API to avoid requiring API v30
+From b5ee33076e1868c5946345b2cfb15a519b8c2577 Mon Sep 17 00:00:00 2001
+From: Jeff Vander Stoep <jeffv@google.com>
+Date: Mon, 5 Dec 2022 12:42:22 +0100
+Subject: [PATCH 2/2] Use older API to avoid requiring API v30
 
 Test: Check that keystore still outputs logs to system
 Bug: 221185310
-Change-Id: I25174f1617557e270db70cd432cec78c037c6b75
+Change-Id: If81d66cb145cbb41b4338fd64ac024d77243482e
 ---
  src/lib.rs | 14 ++++----------
  1 file changed, 4 insertions(+), 10 deletions(-)
 
 diff --git a/src/lib.rs b/src/lib.rs
-index d21be3f..bc4fa61 100644
+index 4bcce0c..59f942b 100644
 --- a/src/lib.rs
 +++ b/src/lib.rs
-@@ -113,17 +113,11 @@ impl LogId {
+@@ -111,17 +111,11 @@ impl LogId {
  /// Output log to android system.
  #[cfg(target_os = "android")]
  fn android_log(log_id: log_ffi::log_id_t, prio: log_ffi::LogPriority, tag: &CStr, msg: &CStr) {
@@ -37,5 +37,5 @@
  }
  
 -- 
-2.35.1.574.g5d30c73bfb-goog
+2.39.0.rc0.267.gcb52ba06e7-goog
 
diff --git a/src/lib.rs b/src/lib.rs
index bc4fa61..c22f07e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,13 +13,13 @@
 //! #[macro_use] extern crate log;
 //! extern crate android_logger;
 //!
-//! use log::Level;
+//! use log::LevelFilter;
 //! use android_logger::Config;
 //!
 //! /// Android code may not have obvious "main", this is just an example.
 //! fn main() {
 //!     android_logger::init_once(
-//!         Config::default().with_min_level(Level::Trace),
+//!         Config::default().with_max_level(LevelFilter::Trace),
 //!     );
 //!
 //!     debug!("this is a debug {}", "message");
@@ -36,13 +36,13 @@
 //! #[macro_use] extern crate log;
 //! extern crate android_logger;
 //!
-//! use log::Level;
+//! use log::LevelFilter;
 //! use android_logger::{Config,FilterBuilder};
 //!
 //! fn main() {
 //!     android_logger::init_once(
 //!         Config::default()
-//!             .with_min_level(Level::Trace)
+//!             .with_max_level(LevelFilter::Trace)
 //!             .with_tag("mytag")
 //!             .with_filter(FilterBuilder::new().parse("debug,hello::crate=trace").build()),
 //!     );
@@ -58,31 +58,29 @@
 //!
 //! android_logger::init_once(
 //!     Config::default()
-//!         .with_min_level(log::Level::Trace)
+//!         .with_max_level(log::LevelFilter::Trace)
 //!         .format(|f, record| write!(f, "my_app: {}", record.args()))
 //! )
 //! ```
 
 #[cfg(target_os = "android")]
 extern crate android_log_sys as log_ffi;
-#[macro_use]
-extern crate lazy_static;
+extern crate once_cell;
+use once_cell::sync::OnceCell;
 #[macro_use]
 extern crate log;
 
 extern crate env_logger;
 
-use std::sync::RwLock;
-
+use log::{Level, LevelFilter, Log, Metadata, Record};
 #[cfg(target_os = "android")]
 use log_ffi::LogPriority;
-use log::{Level, Log, Metadata, Record};
 use std::ffi::{CStr, CString};
-use std::mem;
 use std::fmt;
+use std::mem::{self, MaybeUninit};
 use std::ptr;
 
-pub use env_logger::filter::{Filter, Builder as FilterBuilder};
+pub use env_logger::filter::{Builder as FilterBuilder, Filter};
 pub use env_logger::fmt::Formatter;
 
 pub(crate) type FormatFn = Box<dyn Fn(&mut dyn fmt::Write, &Record) -> fmt::Result + Sync + Send>;
@@ -127,21 +125,23 @@
 
 /// Underlying android logger backend
 pub struct AndroidLogger {
-    config: RwLock<Config>,
+    config: OnceCell<Config>,
 }
 
 impl AndroidLogger {
     /// Create new logger instance from config
     pub fn new(config: Config) -> AndroidLogger {
         AndroidLogger {
-            config: RwLock::new(config),
+            config: OnceCell::from(config),
         }
     }
+
+    fn config(&self) -> &Config {
+        self.config.get_or_init(Config::default)
+    }
 }
 
-lazy_static! {
-   static ref ANDROID_LOGGER: AndroidLogger = AndroidLogger::default();
-}
+static ANDROID_LOGGER: OnceCell<AndroidLogger> = OnceCell::new();
 
 const LOGGING_TAG_MAX_LEN: usize = 23;
 const LOGGING_MSG_MAX_LEN: usize = 4000;
@@ -150,34 +150,42 @@
     /// Create a new logger with default config
     fn default() -> AndroidLogger {
         AndroidLogger {
-            config: RwLock::new(Config::default()),
+            config: OnceCell::from(Config::default()),
         }
     }
 }
 
 impl Log for AndroidLogger {
-    fn enabled(&self, _: &Metadata) -> bool {
-        true
+    fn enabled(&self, metadata: &Metadata) -> bool {
+        let config = self.config();
+        // todo: consider __android_log_is_loggable.
+        metadata.level() <= config.log_level.unwrap_or_else(log::max_level)
     }
 
     fn log(&self, record: &Record) {
-        let config = self.config
-            .read()
-            .expect("failed to acquire android_log filter lock for read");
+        let config = self.config();
 
+        if !self.enabled(record.metadata()) {
+            return;
+        }
+
+        // this also checks the level, but only if a filter was
+        // installed.
         if !config.filter_matches(record) {
             return;
         }
 
         // tag must not exceed LOGGING_TAG_MAX_LEN
-        #[allow(deprecated)] // created an issue #35 for this
-        let mut tag_bytes: [u8; LOGGING_TAG_MAX_LEN + 1] = unsafe { mem::uninitialized() };
+        let mut tag_bytes: [MaybeUninit<u8>; LOGGING_TAG_MAX_LEN + 1] = uninit_array();
 
         let module_path = record.module_path().unwrap_or_default().to_owned();
 
         // If no tag was specified, use module name
         let custom_tag = &config.tag;
-        let tag = custom_tag.as_ref().map(|s| s.as_bytes()).unwrap_or(module_path.as_bytes());
+        let tag = custom_tag
+            .as_ref()
+            .map(|s| s.as_bytes())
+            .unwrap_or_else(|| module_path.as_bytes());
 
         // truncate the tag here to fit into LOGGING_TAG_MAX_LEN
         self.fill_tag_bytes(&mut tag_bytes, tag);
@@ -207,53 +215,51 @@
 }
 
 impl AndroidLogger {
-    fn fill_tag_bytes(&self, array: &mut [u8], tag: &[u8]) {
+    fn fill_tag_bytes(&self, array: &mut [MaybeUninit<u8>], tag: &[u8]) {
         if tag.len() > LOGGING_TAG_MAX_LEN {
-            for (input, output) in tag.iter()
+            for (input, output) in tag
+                .iter()
                 .take(LOGGING_TAG_MAX_LEN - 2)
                 .chain(b"..\0".iter())
                 .zip(array.iter_mut())
             {
-                *output = *input;
+                output.write(*input);
             }
         } else {
-            for (input, output) in tag.iter()
-                .chain(b"\0".iter())
-                .zip(array.iter_mut())
-            {
-                *output = *input;
+            for (input, output) in tag.iter().chain(b"\0".iter()).zip(array.iter_mut()) {
+                output.write(*input);
             }
         }
     }
 }
 
 /// Filter for android logger.
+#[derive(Default)]
 pub struct Config {
-    log_level: Option<Level>,
+    log_level: Option<LevelFilter>,
     log_id: Option<LogId>,
     filter: Option<env_logger::filter::Filter>,
     tag: Option<CString>,
     custom_format: Option<FormatFn>,
 }
 
-impl Default for Config {
-    fn default() -> Self {
-        Config {
-            log_level: None,
-            log_id: None,
-            filter: None,
-            tag: None,
-            custom_format: None,
-        }
-    }
-}
-
 impl Config {
-    /// Change the minimum log level.
+    // TODO: Remove on 0.13 version release.
+    /// **DEPRECATED**, use [`Config::with_max_level()`] instead.
+    #[deprecated(note = "use `.with_max_level()` instead")]
+    pub fn with_min_level(self, level: Level) -> Self {
+        self.with_max_level(level.to_level_filter())
+    }
+
+    /// Changes the maximum log level.
     ///
-    /// All values above the set level are logged. For example, if
-    /// `Warn` is set, the `Error` is logged too, but `Info` isn't.
-    pub fn with_min_level(mut self, level: Level) -> Self {
+    /// Note, that `Trace` is the maximum level, because it provides the
+    /// maximum amount of detail in the emitted logs.
+    ///
+    /// If `Off` level is provided, then nothing is logged at all.
+    ///
+    /// [`log::max_level()`] is considered as the default level.
+    pub fn with_max_level(mut self, level: LevelFilter) -> Self {
         self.log_level = Some(level);
         self
     }
@@ -269,7 +275,7 @@
 
     fn filter_matches(&self, record: &Record) -> bool {
         if let Some(ref filter) = self.filter {
-            filter.matches(&record)
+            filter.matches(record)
         } else {
             true
         }
@@ -290,7 +296,7 @@
     /// # use android_logger::Config;
     /// android_logger::init_once(
     ///     Config::default()
-    ///         .with_min_level(log::Level::Trace)
+    ///         .with_max_level(log::LevelFilter::Trace)
     ///         .format(|f, record| write!(f, "my_app: {}", record.args()))
     /// )
     /// ```
@@ -303,35 +309,46 @@
     }
 }
 
-struct PlatformLogWriter<'a> {
-    #[cfg(target_os = "android")] priority: LogPriority,
-    #[cfg(not(target_os = "android"))] priority: Level,
+pub struct PlatformLogWriter<'a> {
+    #[cfg(target_os = "android")]
+    priority: LogPriority,
+    #[cfg(not(target_os = "android"))]
+    priority: Level,
     #[cfg(target_os = "android")] log_id: log_ffi::log_id_t,
     #[cfg(not(target_os = "android"))] log_id: Option<LogId>,
     len: usize,
     last_newline_index: usize,
     tag: &'a CStr,
-    buffer: [u8; LOGGING_MSG_MAX_LEN + 1],
+    buffer: [MaybeUninit<u8>; LOGGING_MSG_MAX_LEN + 1],
 }
 
 impl<'a> PlatformLogWriter<'a> {
     #[cfg(target_os = "android")]
-    pub fn new(log_id: Option<LogId>, level: Level, tag: &CStr) -> PlatformLogWriter {
+    pub fn new_with_priority(log_id: Option<LogId>, priority: log_ffi::LogPriority, tag: &CStr) -> PlatformLogWriter {
         #[allow(deprecated)] // created an issue #35 for this
         PlatformLogWriter {
-            priority: match level {
+            priority,
+            log_id: LogId::to_native(log_id),
+            len: 0,
+            last_newline_index: 0,
+            tag,
+            buffer: uninit_array(),
+        }
+    }
+
+    #[cfg(target_os = "android")]
+    pub fn new(log_id: Option<LogId>, level: Level, tag: &CStr) -> PlatformLogWriter {
+        Self::new_with_priority(
+            log_id,
+            match level {
                 Level::Warn => LogPriority::WARN,
                 Level::Info => LogPriority::INFO,
                 Level::Debug => LogPriority::DEBUG,
                 Level::Error => LogPriority::ERROR,
                 Level::Trace => LogPriority::VERBOSE,
             },
-            log_id: LogId::to_native(log_id),
-            len: 0,
-            last_newline_index: 0,
             tag,
-            buffer: unsafe { mem::uninitialized() },
-        }
+        )
     }
 
     #[cfg(not(target_os = "android"))]
@@ -343,7 +360,7 @@
             len: 0,
             last_newline_index: 0,
             tag,
-            buffer: unsafe { mem::uninitialized() },
+            buffer: uninit_array(),
         }
     }
 
@@ -375,7 +392,7 @@
     }
 
     /// Flush everything remaining to android logger.
-    fn flush(&mut self) {
+    pub fn flush(&mut self) {
         let total_len = self.len;
 
         if total_len == 0 {
@@ -389,21 +406,22 @@
 
     /// Output buffer up until the \0 which will be placed at `len` position.
     fn output_specified_len(&mut self, len: usize) {
-        let mut last_byte: u8 = b'\0';
+        let mut last_byte = MaybeUninit::new(b'\0');
+
         mem::swap(&mut last_byte, unsafe {
             self.buffer.get_unchecked_mut(len)
         });
 
-        let msg: &CStr = unsafe { CStr::from_ptr(mem::transmute(self.buffer.as_ptr())) };
+        let msg: &CStr = unsafe { CStr::from_ptr(self.buffer.as_ptr().cast()) };
         android_log(self.log_id, self.priority, self.tag, msg);
 
-        *unsafe { self.buffer.get_unchecked_mut(len) } = last_byte;
+        unsafe { *self.buffer.get_unchecked_mut(len) = last_byte };
     }
 
     /// Copy `len` bytes from `index` position to starting position.
     fn copy_bytes_to_start(&mut self, index: usize, len: usize) {
-        let src = unsafe { self.buffer.as_ptr().offset(index as isize) };
         let dst = self.buffer.as_mut_ptr();
+        let src = unsafe { self.buffer.as_ptr().add(index) };
         unsafe { ptr::copy(src, dst, len) };
     }
 }
@@ -422,7 +440,7 @@
                 .zip(incomming_bytes)
                 .enumerate()
                 .fold(None, |acc, (i, (output, input))| {
-                    *output = *input;
+                    output.write(*input);
                     if *input == b'\n' {
                         Some(i)
                     } else {
@@ -460,7 +478,9 @@
 /// This action does not require initialization. However, without initialization it
 /// will use the default filter, which allows all logs.
 pub fn log(record: &Record) {
-    ANDROID_LOGGER.log(record)
+    ANDROID_LOGGER
+        .get_or_init(AndroidLogger::default)
+        .log(record)
 }
 
 /// Initializes the global logger with an android logger.
@@ -471,19 +491,22 @@
 /// It is ok to call this at the activity creation, and it will be
 /// repeatedly called on every lifecycle restart (i.e. screen rotation).
 pub fn init_once(config: Config) {
-    if let Err(err) = log::set_logger(&*ANDROID_LOGGER) {
+    let log_level = config.log_level;
+    let logger = ANDROID_LOGGER.get_or_init(|| AndroidLogger::new(config));
+
+    if let Err(err) = log::set_logger(logger) {
         debug!("android_logger: log::set_logger failed: {}", err);
-    } else {
-        if let Some(level) = config.log_level {
-            log::set_max_level(level.to_level_filter());
-        }
-        *ANDROID_LOGGER
-            .config
-            .write()
-            .expect("failed to acquire android_log filter lock for write") = config;
+    } else if let Some(level) = log_level {
+        log::set_max_level(level);
     }
 }
 
+// FIXME: When `maybe_uninit_uninit_array ` is stabilized, use it instead of this helper
+fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] {
+    // SAFETY: Array contains MaybeUninit, which is fine to be uninit
+    unsafe { MaybeUninit::uninit().assume_init() }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -494,11 +517,11 @@
     fn check_config_values() {
         // Filter is checked in config_filter_match below.
         let config = Config::default()
-            .with_min_level(Level::Trace)
+            .with_max_level(LevelFilter::Trace)
             .with_log_id(LogId::System)
             .with_tag("my_app");
 
-        assert_eq!(config.log_level, Some(Level::Trace));
+        assert_eq!(config.log_level, Some(LevelFilter::Trace));
         assert_eq!(config.log_id, Some(LogId::System));
         assert_eq!(config.tag, Some(CString::new("my_app").unwrap()));
     }
@@ -507,7 +530,7 @@
     fn log_calls_formatter() {
         static FORMAT_FN_WAS_CALLED: AtomicBool = AtomicBool::new(false);
         let config = Config::default()
-            .with_min_level(Level::Info)
+            .with_max_level(LevelFilter::Info)
             .format(|_, _| {
                 FORMAT_FN_WAS_CALLED.store(true, Ordering::SeqCst);
                 Ok(())
@@ -520,10 +543,12 @@
     }
 
     #[test]
-    fn logger_always_enabled() {
-        let logger = AndroidLogger::new(Config::default());
+    fn logger_enabled_threshold() {
+        let logger = AndroidLogger::new(Config::default().with_max_level(LevelFilter::Info));
 
-        assert!(logger.enabled(&log::MetadataBuilder::new().build()));
+        assert!(logger.enabled(&log::MetadataBuilder::new().level(Level::Warn).build()));
+        assert!(logger.enabled(&log::MetadataBuilder::new().level(Level::Info).build()));
+        assert!(!logger.enabled(&log::MetadataBuilder::new().level(Level::Debug).build()));
     }
 
     // Test whether the filter gets called correctly. Not meant to be exhaustive for all filter
@@ -545,12 +570,12 @@
         let logger = AndroidLogger::new(Config::default());
         let too_long_tag: [u8; LOGGING_TAG_MAX_LEN + 20] = [b'a'; LOGGING_TAG_MAX_LEN + 20];
 
-        let mut result: [u8; LOGGING_TAG_MAX_LEN + 1] = Default::default();
+        let mut result: [MaybeUninit<u8>; LOGGING_TAG_MAX_LEN + 1] = uninit_array();
         logger.fill_tag_bytes(&mut result, &too_long_tag);
 
         let mut expected_result = [b'a'; LOGGING_TAG_MAX_LEN - 2].to_vec();
         expected_result.extend("..\0".as_bytes());
-        assert_eq!(result.to_vec(), expected_result);
+        assert_eq!(unsafe { assume_init_slice(&result) }, expected_result);
     }
 
     #[test]
@@ -558,19 +583,19 @@
         let logger = AndroidLogger::new(Config::default());
         let short_tag: [u8; 3] = [b'a'; 3];
 
-        let mut result: [u8; LOGGING_TAG_MAX_LEN + 1] = Default::default();
+        let mut result: [MaybeUninit<u8>; LOGGING_TAG_MAX_LEN + 1] = uninit_array();
         logger.fill_tag_bytes(&mut result, &short_tag);
 
         let mut expected_result = short_tag.to_vec();
         expected_result.push(0);
-        assert_eq!(result.to_vec()[..4], expected_result);
+        assert_eq!(unsafe { assume_init_slice(&result[..4]) }, expected_result);
     }
 
     #[test]
     fn platform_log_writer_init_values() {
         let tag = CStr::from_bytes_with_nul(b"tag\0").unwrap();
 
-        let writer = PlatformLogWriter::new(None, Level::Warn, &tag);
+        let writer = PlatformLogWriter::new(None, Level::Warn, tag);
 
         assert_eq!(writer.tag, tag);
         // Android uses LogPriority instead, which doesn't implement equality checks
@@ -591,7 +616,10 @@
         // Should have flushed up until the last newline.
         assert_eq!(writer.len, 3);
         assert_eq!(writer.last_newline_index, 0);
-        assert_eq!(&writer.buffer.to_vec()[..writer.len], "\n90".as_bytes());
+        assert_eq!(
+            unsafe { assume_init_slice(&writer.buffer[..writer.len]) },
+            "\n90".as_bytes()
+        );
 
         writer.temporal_flush();
         // Should have flushed all remaining bytes.
@@ -634,7 +662,7 @@
         writer.output_specified_len(5);
 
         assert_eq!(
-            writer.buffer[..log_string.len()].to_vec(),
+            unsafe { assume_init_slice(&writer.buffer[..log_string.len()]) },
             log_string.as_bytes()
         );
     }
@@ -648,7 +676,10 @@
 
         writer.copy_bytes_to_start(3, 2);
 
-        assert_eq!(writer.buffer[..10].to_vec(), "3423456789".as_bytes());
+        assert_eq!(
+            unsafe { assume_init_slice(&writer.buffer[..10]) },
+            "3423456789".as_bytes()
+        );
     }
 
     #[test]
@@ -663,12 +694,16 @@
         writer.copy_bytes_to_start(10, 0);
 
         assert_eq!(
-            writer.buffer[..test_string.len()].to_vec(),
+            unsafe { assume_init_slice(&writer.buffer[..test_string.len()]) },
             test_string.as_bytes()
         );
     }
 
     fn get_tag_writer() -> PlatformLogWriter<'static> {
-        PlatformLogWriter::new(None, Level::Warn, &CStr::from_bytes_with_nul(b"tag\0").unwrap())
+        PlatformLogWriter::new(None, Level::Warn, CStr::from_bytes_with_nul(b"tag\0").unwrap())
+    }
+
+    unsafe fn assume_init_slice<T>(slice: &[MaybeUninit<T>]) -> &[T] {
+        &*(slice as *const [MaybeUninit<T>] as *const [T])
     }
 }
diff --git a/tests/config_log_level.rs b/tests/config_log_level.rs
index ca6ad59..864b229 100644
--- a/tests/config_log_level.rs
+++ b/tests/config_log_level.rs
@@ -3,7 +3,9 @@
 
 #[test]
 fn config_log_level() {
-    android_logger::init_once(android_logger::Config::default().with_min_level(log::Level::Trace));
+    android_logger::init_once(
+        android_logger::Config::default().with_max_level(log::LevelFilter::Trace),
+    );
 
     assert_eq!(log::max_level(), log::LevelFilter::Trace);
-}
\ No newline at end of file
+}
diff --git a/tests/default_init.rs b/tests/default_init.rs
index e7ca9e2..7b04c24 100644
--- a/tests/default_init.rs
+++ b/tests/default_init.rs
@@ -7,4 +7,4 @@
 
     // android_logger has default log level "off"
     assert_eq!(log::max_level(), log::LevelFilter::Off);
-}
\ No newline at end of file
+}
diff --git a/tests/multiple_init.rs b/tests/multiple_init.rs
index 99b58c8..26f815d 100644
--- a/tests/multiple_init.rs
+++ b/tests/multiple_init.rs
@@ -3,10 +3,14 @@
 
 #[test]
 fn multiple_init() {
-    android_logger::init_once(android_logger::Config::default().with_min_level(log::Level::Trace));
+    android_logger::init_once(
+        android_logger::Config::default().with_max_level(log::LevelFilter::Trace),
+    );
 
     // Second initialization should be silently ignored
-    android_logger::init_once(android_logger::Config::default().with_min_level(log::Level::Error));
+    android_logger::init_once(
+        android_logger::Config::default().with_max_level(log::LevelFilter::Error),
+    );
 
     assert_eq!(log::max_level(), log::LevelFilter::Trace);
-}
\ No newline at end of file
+}