Upgrade rust/crates/env_logger to 0.8.4

Test: make
Change-Id: I84192922a0e39dd63dbf6a0cd48f751fd66d4264
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 8b186b2..8469382 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "67adcba945148ef3bc1a867832f1422779d626cc"
+    "sha1": "13cafce572362582f57964eae6cb4a41f52fd04a"
   }
 }
diff --git a/Cargo.toml b/Cargo.toml
index bd952f8..56361f9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "env_logger"
-version = "0.8.3"
+version = "0.8.4"
 authors = ["The Rust Project Developers"]
 include = ["src/**/*", "tests", "LICENSE-*", "README.md", "CHANGELOG.md"]
 description = "A logging implementation for `log` which is configured via an environment\nvariable.\n"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 42fa5ae..3a3e176 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,7 +1,7 @@
 [package]
 name = "env_logger"
 edition = "2018"
-version = "0.8.3"
+version = "0.8.4"
 authors = ["The Rust Project Developers"]
 license = "MIT/Apache-2.0"
 readme = "README.md"
diff --git a/METADATA b/METADATA
index b1e7cb0..2bcd175 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/env_logger/env_logger-0.8.3.crate"
+    value: "https://static.crates.io/crates/env_logger/env_logger-0.8.4.crate"
   }
-  version: "0.8.3"
+  version: "0.8.4"
   license_type: NOTICE
   last_upgrade_date {
     year: 2021
-    month: 2
-    day: 11
+    month: 6
+    day: 21
   }
 }
diff --git a/README.md b/README.md
index 329d1be..4e84e8f 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@
 ```toml
 [dependencies]
 log = "0.4.0"
-env_logger = "0.8.3"
+env_logger = "0.8.4"
 ```
 
 `env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging.
@@ -88,7 +88,7 @@
 log = "0.4.0"
 
 [dev-dependencies]
-env_logger = "0.8.3"
+env_logger = "0.8.4"
 ```
 
 ```rust
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 15e6776..5958510 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,31 +2,64 @@
 {
   "presubmit": [
     {
-      "name": "keystore2_test"
+      "name": "android_logger_device_test_src_lib"
     },
     {
-      "name": "env_logger_device_test_tests_regexp_filter"
+      "name": "android_logger_device_test_tests_config_log_level"
+    },
+    {
+      "name": "android_logger_device_test_tests_default_init"
+    },
+    {
+      "name": "android_logger_device_test_tests_multiple_init"
+    },
+    {
+      "name": "doh_unit_test"
     },
     {
       "name": "env_logger_device_test_src_lib"
     },
     {
-      "name": "env_logger_device_test_tests_log-in-log"
-    },
-    {
       "name": "env_logger_device_test_tests_init-twice-retains-filter"
     },
     {
-      "name": "libsqlite3-sys_device_test_src_lib"
+      "name": "env_logger_device_test_tests_log-in-log"
     },
     {
-      "name": "android_logger_device_test_src_lib"
+      "name": "env_logger_device_test_tests_log_tls_dtors"
+    },
+    {
+      "name": "env_logger_device_test_tests_regexp_filter"
+    },
+    {
+      "name": "keystore2_selinux_concurrency_test"
     },
     {
       "name": "keystore2_selinux_test"
     },
     {
-      "name": "env_logger_device_test_tests_log_tls_dtors"
+      "name": "keystore2_test"
+    },
+    {
+      "name": "libsqlite3-sys_device_test_src_lib"
+    },
+    {
+      "name": "logger_device_test_config_log_level"
+    },
+    {
+      "name": "logger_device_test_default_init"
+    },
+    {
+      "name": "logger_device_test_env_log_level"
+    },
+    {
+      "name": "logger_device_test_multiple_init"
+    },
+    {
+      "name": "logger_device_unit_tests"
+    },
+    {
+      "name": "vpnprofilestore_test"
     }
   ]
 }
diff --git a/src/filter/mod.rs b/src/filter/mod.rs
index 8f7787f..7ef3f39 100644
--- a/src/filter/mod.rs
+++ b/src/filter/mod.rs
@@ -59,6 +59,7 @@
 //! [`Filter::matches`]: struct.Filter.html#method.matches
 
 use log::{Level, LevelFilter, Metadata, Record};
+use std::collections::HashMap;
 use std::env;
 use std::fmt;
 use std::mem;
@@ -107,7 +108,7 @@
 ///
 /// [`Filter`]: struct.Filter.html
 pub struct Builder {
-    directives: Vec<Directive>,
+    directives: HashMap<Option<String>, LevelFilter>,
     filter: Option<inner::Filter>,
     built: bool,
 }
@@ -171,7 +172,7 @@
     /// Initializes the filter builder with defaults.
     pub fn new() -> Builder {
         Builder {
-            directives: Vec::new(),
+            directives: HashMap::new(),
             filter: None,
             built: false,
         }
@@ -203,10 +204,7 @@
     /// The given module (if any) will log at most the specified level provided.
     /// If no module is provided then the filter will apply to all log messages.
     pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
-        self.directives.push(Directive {
-            name: module.map(|s| s.to_string()),
-            level,
-        });
+        self.directives.insert(module.map(|s| s.to_string()), level);
         self
     }
 
@@ -221,7 +219,7 @@
         self.filter = filter;
 
         for directive in directives {
-            self.directives.push(directive);
+            self.directives.insert(directive.name, directive.level);
         }
         self
     }
@@ -231,16 +229,23 @@
         assert!(!self.built, "attempt to re-use consumed builder");
         self.built = true;
 
+        let mut directives = Vec::new();
         if self.directives.is_empty() {
             // Adds the default filter if none exist
-            self.directives.push(Directive {
+            directives.push(Directive {
                 name: None,
                 level: LevelFilter::Error,
             });
         } else {
+            // Consume map of directives.
+            let directives_map = mem::replace(&mut self.directives, HashMap::new());
+            directives = directives_map
+                .into_iter()
+                .map(|(name, level)| Directive { name, level })
+                .collect();
             // Sort the directives by length of their name, this allows a
             // little more efficient lookup at runtime.
-            self.directives.sort_by(|a, b| {
+            directives.sort_by(|a, b| {
                 let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0);
                 let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0);
                 alen.cmp(&blen)
@@ -248,7 +253,7 @@
         }
 
         Filter {
-            directives: mem::replace(&mut self.directives, Vec::new()),
+            directives: mem::replace(&mut directives, Vec::new()),
             filter: mem::replace(&mut self.filter, None),
         }
     }
diff --git a/src/fmt/writer/mod.rs b/src/fmt/writer/mod.rs
index 6ee63a3..5bb5353 100644
--- a/src/fmt/writer/mod.rs
+++ b/src/fmt/writer/mod.rs
@@ -3,22 +3,24 @@
 
 use self::atty::{is_stderr, is_stdout};
 use self::termcolor::BufferWriter;
-use std::{fmt, io};
+use std::{fmt, io, mem, sync::Mutex};
 
-pub(in crate::fmt) mod glob {
+pub(super) mod glob {
     pub use super::termcolor::glob::*;
     pub use super::*;
 }
 
-pub(in crate::fmt) use self::termcolor::Buffer;
+pub(super) use self::termcolor::Buffer;
 
-/// Log target, either `stdout` or `stderr`.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+/// Log target, either `stdout`, `stderr` or a custom pipe.
+#[non_exhaustive]
 pub enum Target {
     /// Logs will be sent to standard output.
     Stdout,
     /// Logs will be sent to standard error.
     Stderr,
+    /// Logs will be sent to a custom pipe.
+    Pipe(Box<dyn io::Write + Send + 'static>),
 }
 
 impl Default for Target {
@@ -27,6 +29,61 @@
     }
 }
 
+impl fmt::Debug for Target {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "{}",
+            match self {
+                Self::Stdout => "stdout",
+                Self::Stderr => "stderr",
+                Self::Pipe(_) => "pipe",
+            }
+        )
+    }
+}
+
+/// Log target, either `stdout`, `stderr` or a custom pipe.
+///
+/// Same as `Target`, except the pipe is wrapped in a mutex for interior mutability.
+pub(super) enum WritableTarget {
+    /// Logs will be sent to standard output.
+    Stdout,
+    /// Logs will be sent to standard error.
+    Stderr,
+    /// Logs will be sent to a custom pipe.
+    Pipe(Box<Mutex<dyn io::Write + Send + 'static>>),
+}
+
+impl From<Target> for WritableTarget {
+    fn from(target: Target) -> Self {
+        match target {
+            Target::Stdout => Self::Stdout,
+            Target::Stderr => Self::Stderr,
+            Target::Pipe(pipe) => Self::Pipe(Box::new(Mutex::new(pipe))),
+        }
+    }
+}
+
+impl Default for WritableTarget {
+    fn default() -> Self {
+        Self::from(Target::default())
+    }
+}
+
+impl fmt::Debug for WritableTarget {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "{}",
+            match self {
+                Self::Stdout => "stdout",
+                Self::Stderr => "stderr",
+                Self::Pipe(_) => "pipe",
+            }
+        )
+    }
+}
 /// Whether or not to print styles to the target.
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub enum WriteStyle {
@@ -55,11 +112,11 @@
         self.write_style
     }
 
-    pub(in crate::fmt) fn buffer(&self) -> Buffer {
+    pub(super) fn buffer(&self) -> Buffer {
         self.inner.buffer()
     }
 
-    pub(in crate::fmt) fn print(&self, buf: &Buffer) -> io::Result<()> {
+    pub(super) fn print(&self, buf: &Buffer) -> io::Result<()> {
         self.inner.print(buf)
     }
 }
@@ -67,8 +124,9 @@
 /// A builder for a terminal writer.
 ///
 /// The target and style choice can be configured before building.
+#[derive(Debug)]
 pub(crate) struct Builder {
-    target: Target,
+    target: WritableTarget,
     write_style: WriteStyle,
     is_test: bool,
     built: bool,
@@ -87,7 +145,7 @@
 
     /// Set the target to write to.
     pub(crate) fn target(&mut self, target: Target) -> &mut Self {
-        self.target = target;
+        self.target = target.into();
         self
     }
 
@@ -119,9 +177,10 @@
 
         let color_choice = match self.write_style {
             WriteStyle::Auto => {
-                if match self.target {
-                    Target::Stderr => is_stderr(),
-                    Target::Stdout => is_stdout(),
+                if match &self.target {
+                    WritableTarget::Stderr => is_stderr(),
+                    WritableTarget::Stdout => is_stdout(),
+                    WritableTarget::Pipe(_) => false,
                 } {
                     WriteStyle::Auto
                 } else {
@@ -131,9 +190,10 @@
             color_choice => color_choice,
         };
 
-        let writer = match self.target {
-            Target::Stderr => BufferWriter::stderr(self.is_test, color_choice),
-            Target::Stdout => BufferWriter::stdout(self.is_test, color_choice),
+        let writer = match mem::take(&mut self.target) {
+            WritableTarget::Stderr => BufferWriter::stderr(self.is_test, color_choice),
+            WritableTarget::Stdout => BufferWriter::stdout(self.is_test, color_choice),
+            WritableTarget::Pipe(pipe) => BufferWriter::pipe(self.is_test, color_choice, pipe),
         };
 
         Writer {
@@ -149,15 +209,6 @@
     }
 }
 
-impl fmt::Debug for Builder {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Logger")
-            .field("target", &self.target)
-            .field("write_style", &self.write_style)
-            .finish()
-    }
-}
-
 impl fmt::Debug for Writer {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("Writer").finish()
diff --git a/src/fmt/writer/termcolor/extern_impl.rs b/src/fmt/writer/termcolor/extern_impl.rs
index 4324a45..11012fb 100644
--- a/src/fmt/writer/termcolor/extern_impl.rs
+++ b/src/fmt/writer/termcolor/extern_impl.rs
@@ -3,11 +3,12 @@
 use std::fmt;
 use std::io::{self, Write};
 use std::rc::Rc;
+use std::sync::Mutex;
 
 use log::Level;
 use termcolor::{self, ColorChoice, ColorSpec, WriteColor};
 
-use crate::fmt::{Formatter, Target, WriteStyle};
+use crate::fmt::{Formatter, WritableTarget, WriteStyle};
 
 pub(in crate::fmt::writer) mod glob {
     pub use super::*;
@@ -70,46 +71,71 @@
 
 pub(in crate::fmt::writer) struct BufferWriter {
     inner: termcolor::BufferWriter,
-    test_target: Option<Target>,
+    test_target: Option<WritableTarget>,
 }
 
 pub(in crate::fmt) struct Buffer {
     inner: termcolor::Buffer,
-    test_target: Option<Target>,
+    has_test_target: bool,
 }
 
 impl BufferWriter {
     pub(in crate::fmt::writer) fn stderr(is_test: bool, write_style: WriteStyle) -> Self {
         BufferWriter {
             inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()),
-            test_target: if is_test { Some(Target::Stderr) } else { None },
+            test_target: if is_test {
+                Some(WritableTarget::Stderr)
+            } else {
+                None
+            },
         }
     }
 
     pub(in crate::fmt::writer) fn stdout(is_test: bool, write_style: WriteStyle) -> Self {
         BufferWriter {
             inner: termcolor::BufferWriter::stdout(write_style.into_color_choice()),
-            test_target: if is_test { Some(Target::Stdout) } else { None },
+            test_target: if is_test {
+                Some(WritableTarget::Stdout)
+            } else {
+                None
+            },
+        }
+    }
+
+    pub(in crate::fmt::writer) fn pipe(
+        is_test: bool,
+        write_style: WriteStyle,
+        pipe: Box<Mutex<dyn io::Write + Send + 'static>>,
+    ) -> Self {
+        BufferWriter {
+            // The inner Buffer is never printed from, but it is still needed to handle coloring and other formating
+            inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()),
+            test_target: if is_test {
+                Some(WritableTarget::Pipe(pipe))
+            } else {
+                None
+            },
         }
     }
 
     pub(in crate::fmt::writer) fn buffer(&self) -> Buffer {
         Buffer {
             inner: self.inner.buffer(),
-            test_target: self.test_target,
+            has_test_target: self.test_target.is_some(),
         }
     }
 
     pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
-        if let Some(target) = self.test_target {
+        if let Some(target) = &self.test_target {
             // This impl uses the `eprint` and `print` macros
             // instead of `termcolor`'s buffer.
             // This is so their output can be captured by `cargo test`
             let log = String::from_utf8_lossy(buf.bytes());
 
             match target {
-                Target::Stderr => eprint!("{}", log),
-                Target::Stdout => print!("{}", log),
+                WritableTarget::Stderr => eprint!("{}", log),
+                WritableTarget::Stdout => print!("{}", log),
+                WritableTarget::Pipe(pipe) => write!(pipe.lock().unwrap(), "{}", log)?,
             }
 
             Ok(())
@@ -138,7 +164,7 @@
 
     fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
         // Ignore styles for test captured logs because they can't be printed
-        if self.test_target.is_none() {
+        if !self.has_test_target {
             self.inner.set_color(spec)
         } else {
             Ok(())
@@ -147,7 +173,7 @@
 
     fn reset(&mut self) -> io::Result<()> {
         // Ignore styles for test captured logs because they can't be printed
-        if self.test_target.is_none() {
+        if !self.has_test_target {
             self.inner.reset()
         } else {
             Ok(())
@@ -255,7 +281,7 @@
     /// });
     /// ```
     pub fn set_color(&mut self, color: Color) -> &mut Style {
-        self.spec.set_fg(color.into_termcolor());
+        self.spec.set_fg(Some(color.into_termcolor()));
         self
     }
 
@@ -334,7 +360,7 @@
     /// });
     /// ```
     pub fn set_bg(&mut self, color: Color) -> &mut Style {
-        self.spec.set_bg(color.into_termcolor());
+        self.spec.set_bg(Some(color.into_termcolor()));
         self
     }
 
@@ -467,18 +493,18 @@
 }
 
 impl Color {
-    fn into_termcolor(self) -> Option<termcolor::Color> {
+    fn into_termcolor(self) -> termcolor::Color {
         match self {
-            Color::Black => Some(termcolor::Color::Black),
-            Color::Blue => Some(termcolor::Color::Blue),
-            Color::Green => Some(termcolor::Color::Green),
-            Color::Red => Some(termcolor::Color::Red),
-            Color::Cyan => Some(termcolor::Color::Cyan),
-            Color::Magenta => Some(termcolor::Color::Magenta),
-            Color::Yellow => Some(termcolor::Color::Yellow),
-            Color::White => Some(termcolor::Color::White),
-            Color::Ansi256(value) => Some(termcolor::Color::Ansi256(value)),
-            Color::Rgb(r, g, b) => Some(termcolor::Color::Rgb(r, g, b)),
+            Color::Black => termcolor::Color::Black,
+            Color::Blue => termcolor::Color::Blue,
+            Color::Green => termcolor::Color::Green,
+            Color::Red => termcolor::Color::Red,
+            Color::Cyan => termcolor::Color::Cyan,
+            Color::Magenta => termcolor::Color::Magenta,
+            Color::Yellow => termcolor::Color::Yellow,
+            Color::White => termcolor::Color::White,
+            Color::Ansi256(value) => termcolor::Color::Ansi256(value),
+            Color::Rgb(r, g, b) => termcolor::Color::Rgb(r, g, b),
         }
     }
 }
diff --git a/src/fmt/writer/termcolor/shim_impl.rs b/src/fmt/writer/termcolor/shim_impl.rs
index 563f8ad..bfc31d0 100644
--- a/src/fmt/writer/termcolor/shim_impl.rs
+++ b/src/fmt/writer/termcolor/shim_impl.rs
@@ -1,11 +1,11 @@
-use std::io;
+use std::{io, sync::Mutex};
 
-use crate::fmt::{Target, WriteStyle};
+use crate::fmt::{WritableTarget, WriteStyle};
 
 pub(in crate::fmt::writer) mod glob {}
 
 pub(in crate::fmt::writer) struct BufferWriter {
-    target: Target,
+    target: WritableTarget,
 }
 
 pub(in crate::fmt) struct Buffer(Vec<u8>);
@@ -13,13 +13,23 @@
 impl BufferWriter {
     pub(in crate::fmt::writer) fn stderr(_is_test: bool, _write_style: WriteStyle) -> Self {
         BufferWriter {
-            target: Target::Stderr,
+            target: WritableTarget::Stderr,
         }
     }
 
     pub(in crate::fmt::writer) fn stdout(_is_test: bool, _write_style: WriteStyle) -> Self {
         BufferWriter {
-            target: Target::Stdout,
+            target: WritableTarget::Stdout,
+        }
+    }
+
+    pub(in crate::fmt::writer) fn pipe(
+        _is_test: bool,
+        _write_style: WriteStyle,
+        pipe: Box<Mutex<dyn io::Write + Send + 'static>>,
+    ) -> Self {
+        BufferWriter {
+            target: WritableTarget::Pipe(pipe),
         }
     }
 
@@ -30,12 +40,12 @@
     pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
         // This impl uses the `eprint` and `print` macros
         // instead of using the streams directly.
-        // This is so their output can be captured by `cargo test`
-        let log = String::from_utf8_lossy(&buf.0);
-
-        match self.target {
-            Target::Stderr => eprint!("{}", log),
-            Target::Stdout => print!("{}", log),
+        // This is so their output can be captured by `cargo test`.
+        match &self.target {
+            // Safety: If the target type is `Pipe`, `target_pipe` will always be non-empty.
+            WritableTarget::Pipe(pipe) => pipe.lock().unwrap().write_all(&buf.0)?,
+            WritableTarget::Stdout => print!("{}", String::from_utf8_lossy(&buf.0)),
+            WritableTarget::Stderr => eprint!("{}", String::from_utf8_lossy(&buf.0)),
         }
 
         Ok(())
diff --git a/src/lib.rs b/src/lib.rs
index 31ea7c3..6a77266 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -708,7 +708,10 @@
 
     /// Sets the target for the log output.
     ///
-    /// Env logger can log to either stdout or stderr. The default is stderr.
+    /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr.
+    ///
+    /// The custom pipe can be used to send the log messages to a custom sink (for example a file).
+    /// Do note that direct writes to a file can become a bottleneck due to IO operation times.
     ///
     /// # Examples
     ///
@@ -1277,4 +1280,20 @@
 
         assert_eq!(Some("from default".to_owned()), env.get_write_style());
     }
+
+    #[test]
+    fn builder_parse_env_overrides_existing_filters() {
+        env::set_var(
+            "builder_parse_default_env_overrides_existing_filters",
+            "debug",
+        );
+        let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters");
+
+        let mut builder = Builder::new();
+        builder.filter_level(LevelFilter::Trace);
+        // Overrides global level to debug
+        builder.parse_env(env);
+
+        assert_eq!(builder.filter.build().filter(), LevelFilter::Debug);
+    }
 }