vmbase: Add basic logger

Introduce a logger in vmbase that wraps around the println! into UART to
be able to distinguish different levels of log messages.

Test: atest vmbase_example.integration_test
Change-Id: Id3b98ef4cdc4b23a11f099d75cc1c9902a9da785
diff --git a/vmbase/Android.bp b/vmbase/Android.bp
index e88420e..4c5e9d1 100644
--- a/vmbase/Android.bp
+++ b/vmbase/Android.bp
@@ -9,6 +9,7 @@
     srcs: ["src/lib.rs"],
     edition: "2021",
     rustlibs: [
+        "liblog_rust_nostd",
         "libpsci",
         "libspin_nostd",
     ],
diff --git a/vmbase/src/lib.rs b/vmbase/src/lib.rs
index 90d6fc2..257f415 100644
--- a/vmbase/src/lib.rs
+++ b/vmbase/src/lib.rs
@@ -18,6 +18,7 @@
 
 pub mod console;
 mod entry;
+pub mod logger;
 pub mod power;
 pub mod uart;
 
diff --git a/vmbase/src/logger.rs b/vmbase/src/logger.rs
new file mode 100644
index 0000000..5f0f1c2
--- /dev/null
+++ b/vmbase/src/logger.rs
@@ -0,0 +1,46 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Logger for vmbase.
+//!
+//! Internally uses the println! vmbase macro, which prints to crosvm's UART.
+//! Note: may not work if the VM is in an inconsistent state. Exception handlers
+//! should avoid using this logger and instead print with eprintln!.
+
+extern crate log;
+
+use super::println;
+use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
+
+struct Logger;
+static LOGGER: Logger = Logger;
+
+impl Log for Logger {
+    fn enabled(&self, _metadata: &Metadata) -> bool {
+        true
+    }
+
+    fn log(&self, record: &Record) {
+        println!("[{}] {}", record.level(), record.args());
+    }
+
+    fn flush(&self) {}
+}
+
+/// Initialize vmbase logger with a given max logging level.
+pub fn init(max_level: LevelFilter) -> Result<(), SetLoggerError> {
+    log::set_logger(&LOGGER)?;
+    log::set_max_level(max_level);
+    Ok(())
+}