Enable microdroid console output with debug level or debug policy

With this CL, pvmfw will add kernel.print.devkmsg and console to
bootargs with hardcoded value from microdroid's debuggable bootconfig.

Test: manually start protected/unprotected VMs \
      with various debug levels and debug policies.
Change-Id: I31600f0d337ff47edfb5cfea60f5e6a010c85ab5
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index aceb319..1781007 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -19,6 +19,7 @@
     write_vm_booted_stats, write_vm_creation_stats};
 use crate::composite::make_composite_image;
 use crate::crosvm::{CrosvmConfig, DiskFile, PayloadState, VmContext, VmInstance, VmState};
+use crate::debug_config::should_prepare_console_output;
 use crate::payload::{add_microdroid_payload_images, add_microdroid_system_images};
 use crate::selinux::{getfilecon, SeContext};
 use android_os_permissions_aidl::aidl::android::os::IPermissionController;
@@ -978,13 +979,6 @@
     })
 }
 
-fn is_debuggable(config: &VirtualMachineConfig) -> bool {
-    match config {
-        VirtualMachineConfig::AppConfig(config) => config.debugLevel != DebugLevel::NONE,
-        _ => false,
-    }
-}
-
 fn is_protected(config: &VirtualMachineConfig) -> bool {
     match config {
         VirtualMachineConfig::RawConfig(config) => config.protectedVm,
@@ -1031,7 +1025,11 @@
         return Ok(Some(clone_file(fd)?));
     }
 
-    if !is_debuggable(config) {
+    if let VirtualMachineConfig::AppConfig(app_config) = config {
+        if !should_prepare_console_output(app_config.debugLevel) {
+            return Ok(None);
+        }
+    } else {
         return Ok(None);
     }
 
diff --git a/virtualizationmanager/src/debug_config.rs b/virtualizationmanager/src/debug_config.rs
new file mode 100644
index 0000000..332df08
--- /dev/null
+++ b/virtualizationmanager/src/debug_config.rs
@@ -0,0 +1,39 @@
+// Copyright 2023, 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.
+
+//! Functions for AVF debug policy and debug level
+
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+    VirtualMachineAppConfig::DebugLevel::DebugLevel
+};
+use std::fs::File;
+use std::io::Read;
+
+/// Get debug policy value in bool. It's true iff the value is explicitly set to <1>.
+fn get_debug_policy_bool(path: &'static str) -> Option<bool> {
+    if let Ok(mut file) = File::open(path) {
+        let mut log: [u8; 4] = Default::default();
+        file.read_exact(&mut log).map_err(|_| false).unwrap();
+        // DT spec uses big endian although Android is always little endian.
+        return Some(u32::from_be_bytes(log) == 1);
+    }
+    None
+}
+
+/// Get whether console output should be configred for VM to leave console and adb log.
+/// Caller should create pipe and prepare for receiving VM log with it.
+pub fn should_prepare_console_output(debug_level: DebugLevel) -> bool {
+    debug_level != DebugLevel::NONE
+        || get_debug_policy_bool("/proc/device-tree/avf/guest/common/log").unwrap_or_default()
+}
diff --git a/virtualizationmanager/src/main.rs b/virtualizationmanager/src/main.rs
index 3f0b64b..bd7f8af 100644
--- a/virtualizationmanager/src/main.rs
+++ b/virtualizationmanager/src/main.rs
@@ -18,6 +18,7 @@
 mod atom;
 mod composite;
 mod crosvm;
+mod debug_config;
 mod payload;
 mod selinux;