Define debug levels

Previously, a VM can be configured as running in debug mode or not.
However, the debug mode was not defined clearly and debugging features
like logging and adb-shell were actually left enabled even when the
debug mode is off.

This CL re-defines the debuggability of a VM. A VM has a debug level
which can be either of these three:

1. None: In this level, VM is not debuggable at all. No log is exported
from the VM, and debugger can't be attached to any process in the VM.
adb-shell of course is not supported.

2. App-only: In this level, only the app payload is debuggable. Logs
from the app process is exported to the host and the process can be
attached to debugger. adb-shell is not supported.

3. Full: In this level, the VM is fully debuggable. All logs including
kernel logs are exported to the VM and developers can adb-shell into the
VM.

Note that this CL doesn't fully implement all the levels yet, but
implements the framework around supporting multiple debug levels.
Specifically, each debug level is associated with a bootconfig image.
Each image has config values each of which enables or disables a
debugging feature. For example, bootconfig images for the none and
app-only levels have "kernel.console = none" to not show kernel console
output.

The `vm` tool and the Java APIs are also amended accordingly. The debug
level can be set via `--debug <level>` flag and the `DebugLevel(...)`
method.

Future work:
* Implement each debug level
* Each level uses different vm-instance image. Debug level is stored in
the instance image and is compared against the given level when
microdroid boots.
* Sign bootconfig images with avb and let uboot verify them
(b/203031847)

Bug: 201362865
Test: atest MicrodroidHostTestCases
Test: adb shell /apex/com.android.virt/bin/vm run-app
/data/local/tmp/virt/MicrodroidDemoApp.apk
/data/local/tmp/virt/MicrodroidDemoApp.apk.idsig
/data/local/tmp/virt/instance.img assets/vm_config.json

shows ...

Created VM from
"/data/local/tmp/virt/MicrodroidDemoApp.apk"!"assets/vm_config.json"
with CID 13, state is NOT_STARTED.
Started VM, state now STARTING.
Hello Microdroid /mnt/apk/lib/arm64-v8a/MicrodroidTestNativeLib.so hello
microdroid

, which is without logs from the bootloader and the kernel

Change-Id: I897dcd88723f014524d2cd2b6ffaa6f9fb5696d6
diff --git a/apex/Android.bp b/apex/Android.bp
index b1c5190..19f5428 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -61,7 +61,9 @@
         "microdroid.json",
         "microdroid_uboot_env",
         "microdroid_bootloader",
-        "microdroid_bootconfig_debug",
+        "microdroid_bootconfig_normal",
+        "microdroid_bootconfig_app_debuggable",
+        "microdroid_bootconfig_full_debuggable",
     ],
     file_contexts: ":com.android.virt-file_contexts",
 }
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
index 3d97ee7..f06c8f5 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
+++ b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
@@ -111,7 +111,7 @@
                         apkName,
                         packageName,
                         configPath,
-                        /* debug */ false,
+                        /* debug */ true,
                         /* use default memoryMib */ 0);
         adbConnectToMicrodroid(androidDevice, sCid);
 
diff --git a/compos/compos_key_cmd/compos_key_cmd.cpp b/compos/compos_key_cmd/compos_key_cmd.cpp
index f495816..7bf622d 100644
--- a/compos/compos_key_cmd/compos_key_cmd.cpp
+++ b/compos/compos_key_cmd/compos_key_cmd.cpp
@@ -53,6 +53,7 @@
 using aidl::android::system::virtualizationservice::IVirtualMachine;
 using aidl::android::system::virtualizationservice::IVirtualMachineCallback;
 using aidl::android::system::virtualizationservice::PartitionType;
+using aidl::android::system::virtualizationservice::VirtualMachineAppConfig;
 using aidl::android::system::virtualizationservice::VirtualMachineConfig;
 using aidl::com::android::compos::CompOsKeyData;
 using aidl::com::android::compos::ICompOsService;
@@ -234,7 +235,7 @@
         appConfig.idsig = std::move(idsigFd);
         appConfig.instanceImage = std::move(instanceFd);
         appConfig.configPath = kConfigFilePath;
-        appConfig.debug = false; // Don't disable selinux in VM
+        appConfig.debugLevel = VirtualMachineAppConfig::DebugLevel::NONE;
         appConfig.memoryMib = 0; // Use default
 
         LOG(INFO) << "Starting VM";
diff --git a/compos/tests/java/android/compos/test/ComposKeyTestCase.java b/compos/tests/java/android/compos/test/ComposKeyTestCase.java
index d9f7065..140f74b 100644
--- a/compos/tests/java/android/compos/test/ComposKeyTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposKeyTestCase.java
@@ -159,7 +159,7 @@
                         apkName,
                         packageName,
                         "assets/vm_test_config.json",
-                        /* debug */ false,
+                        /* debug */ true,
                         /* use default memoryMib */ 0);
         adbConnectToMicrodroid(getDevice(), mCid);
     }
diff --git a/demo/java/com/android/microdroid/demo/MainActivity.java b/demo/java/com/android/microdroid/demo/MainActivity.java
index ce21fdf..bc87c3c 100644
--- a/demo/java/com/android/microdroid/demo/MainActivity.java
+++ b/demo/java/com/android/microdroid/demo/MainActivity.java
@@ -24,6 +24,7 @@
 import android.system.virtualmachine.VirtualMachine;
 import android.system.virtualmachine.VirtualMachineCallback;
 import android.system.virtualmachine.VirtualMachineConfig;
+import android.system.virtualmachine.VirtualMachineConfig.DebugLevel;
 import android.system.virtualmachine.VirtualMachineException;
 import android.system.virtualmachine.VirtualMachineManager;
 import android.util.Log;
@@ -253,8 +254,10 @@
 
             try {
                 VirtualMachineConfig.Builder builder =
-                        new VirtualMachineConfig.Builder(getApplication(), "assets/vm_config.json")
-                                .debugMode(debug);
+                        new VirtualMachineConfig.Builder(getApplication(), "assets/vm_config.json");
+                if (debug) {
+                    builder.debugLevel(DebugLevel.FULL);
+                }
                 VirtualMachineConfig config = builder.build();
                 VirtualMachineManager vmm = VirtualMachineManager.getInstance(getApplication());
                 mVirtualMachine = vmm.getOrCreate("demo_vm", config);
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
index 2550087..dba4c8f 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -49,13 +49,36 @@
     private static final String KEY_CERTS = "certs";
     private static final String KEY_APKPATH = "apkPath";
     private static final String KEY_PAYLOADCONFIGPATH = "payloadConfigPath";
-    private static final String KEY_DEBUGMODE = "debugMode";
+    private static final String KEY_DEBUGLEVEL = "debugLevel";
     private static final String KEY_MEMORY_MIB = "memoryMib";
 
     // Paths to the APK file of this application.
     private final @NonNull String mApkPath;
     private final @NonNull Signature[] mCerts;
-    private final boolean mDebugMode;
+
+    /** A debug level defines the set of debug features that the VM can be configured to. */
+    public enum DebugLevel {
+        /**
+         * Not debuggable at all. No log is exported from the VM. Debugger can't be attached to the
+         * app process running in the VM. This is the default level.
+         */
+        NONE,
+
+        /**
+         * Only the app is debuggable. Log from the app is exported from the VM. Debugger can be
+         * attached to the app process. Rest of the VM is not debuggable.
+         */
+        APP_ONLY,
+
+        /**
+         * Fully debuggable. All logs (both logcat and kernel message) are exported. All processes
+         * running in the VM can be attached to the debugger. Rooting is possible.
+         */
+        FULL,
+    }
+
+    private final DebugLevel mDebugLevel;
+
     /**
      * The amount of RAM to give the VM, in MiB. If this is 0 or negative the default will be used.
      */
@@ -72,12 +95,12 @@
             @NonNull String apkPath,
             @NonNull Signature[] certs,
             @NonNull String payloadConfigPath,
-            boolean debugMode,
+            DebugLevel debugLevel,
             int memoryMib) {
         mApkPath = apkPath;
         mCerts = certs;
         mPayloadConfigPath = payloadConfigPath;
-        mDebugMode = debugMode;
+        mDebugLevel = debugLevel;
         mMemoryMib = memoryMib;
     }
 
@@ -106,9 +129,9 @@
         if (payloadConfigPath == null) {
             throw new VirtualMachineException("No payloadConfigPath");
         }
-        final boolean debugMode = b.getBoolean(KEY_DEBUGMODE);
+        final DebugLevel debugLevel = DebugLevel.values()[b.getInt(KEY_DEBUGLEVEL)];
         final int memoryMib = b.getInt(KEY_MEMORY_MIB);
-        return new VirtualMachineConfig(apkPath, certs, payloadConfigPath, debugMode, memoryMib);
+        return new VirtualMachineConfig(apkPath, certs, payloadConfigPath, debugLevel, memoryMib);
     }
 
     /** Persists this config to a stream, for example a file. */
@@ -123,7 +146,7 @@
         String[] certs = certList.toArray(new String[0]);
         b.putStringArray(KEY_CERTS, certs);
         b.putString(KEY_PAYLOADCONFIGPATH, mPayloadConfigPath);
-        b.putBoolean(KEY_DEBUGMODE, mDebugMode);
+        b.putInt(KEY_DEBUGLEVEL, mDebugLevel.ordinal());
         if (mMemoryMib > 0) {
             b.putInt(KEY_MEMORY_MIB, mMemoryMib);
         }
@@ -146,7 +169,8 @@
         if (!Arrays.equals(this.mCerts, other.mCerts)) {
             return false;
         }
-        if (this.mDebugMode != other.mDebugMode) {
+        if (this.mDebugLevel != other.mDebugLevel) {
+            // TODO(jiyong): should we treat APP_ONLY and FULL the same?
             return false;
         }
         return true;
@@ -162,7 +186,17 @@
         VirtualMachineAppConfig parcel = new VirtualMachineAppConfig();
         parcel.apk = ParcelFileDescriptor.open(new File(mApkPath), MODE_READ_ONLY);
         parcel.configPath = mPayloadConfigPath;
-        parcel.debug = mDebugMode;
+        switch (mDebugLevel) {
+            case NONE:
+                parcel.debugLevel = VirtualMachineAppConfig.DebugLevel.NONE;
+                break;
+            case APP_ONLY:
+                parcel.debugLevel = VirtualMachineAppConfig.DebugLevel.APP_ONLY;
+                break;
+            case FULL:
+                parcel.debugLevel = VirtualMachineAppConfig.DebugLevel.FULL;
+                break;
+        }
         parcel.memoryMib = mMemoryMib;
         return parcel;
     }
@@ -171,7 +205,7 @@
     public static class Builder {
         private Context mContext;
         private String mPayloadConfigPath;
-        private boolean mDebugMode;
+        private DebugLevel mDebugLevel;
         private int mMemoryMib;
         // TODO(jiyong): add more items like # of cpu, size of ram, debuggability, etc.
 
@@ -179,12 +213,12 @@
         public Builder(@NonNull Context context, @NonNull String payloadConfigPath) {
             mContext = context;
             mPayloadConfigPath = payloadConfigPath;
-            mDebugMode = false;
+            mDebugLevel = DebugLevel.NONE;
         }
 
-        /** Enables or disables the debug mode */
-        public Builder debugMode(boolean enableOrDisable) {
-            mDebugMode = enableOrDisable;
+        /** Sets the debug level */
+        public Builder debugLevel(DebugLevel debugLevel) {
+            mDebugLevel = debugLevel;
             return this;
         }
 
@@ -215,7 +249,7 @@
             }
 
             return new VirtualMachineConfig(
-                    apkPath, certs, mPayloadConfigPath, mDebugMode, mMemoryMib);
+                    apkPath, certs, mPayloadConfigPath, mDebugLevel, mMemoryMib);
         }
     }
 }
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 9683eb1..389ebb0 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -228,11 +228,6 @@
             cmdline: microdroid_boot_cmdline + ["acpi=noirq"],
         },
     },
-    product_variables: {
-        debuggable: {
-            cmdline: ["printk.devkmsg=on"],
-        },
-    },
 
     dtb_prebuilt: "dummy_dtb.img",
     header_version: "4",
@@ -325,10 +320,23 @@
     cmd: "cat $(in) > $(out)",
 }
 
+// TODO(b/203031847) sign these bootconfig images using avb
 prebuilt_etc {
-    name: "microdroid_bootconfig_debug",
-    src: "bootconfig.debug",
-    filename: "microdroid_bootconfig.debug",
+    name: "microdroid_bootconfig_normal",
+    src: "bootconfig.normal",
+    filename: "microdroid_bootconfig.normal",
+}
+
+prebuilt_etc {
+    name: "microdroid_bootconfig_app_debuggable",
+    src: "bootconfig.app_debuggable",
+    filename: "microdroid_bootconfig.app_debuggable",
+}
+
+prebuilt_etc {
+    name: "microdroid_bootconfig_full_debuggable",
+    src: "bootconfig.full_debuggable",
+    filename: "microdroid_bootconfig.full_debuggable",
 }
 
 prebuilt_etc {
diff --git a/microdroid/bootconfig.app_debuggable b/microdroid/bootconfig.app_debuggable
new file mode 100644
index 0000000..79e2b08
--- /dev/null
+++ b/microdroid/bootconfig.app_debuggable
@@ -0,0 +1 @@
+kernel.console = null
diff --git a/microdroid/bootconfig.debug b/microdroid/bootconfig.debug
deleted file mode 100644
index d83ecb9..0000000
--- a/microdroid/bootconfig.debug
+++ /dev/null
@@ -1 +0,0 @@
-androidboot.selinux = permissive
diff --git a/microdroid/bootconfig.full_debuggable b/microdroid/bootconfig.full_debuggable
new file mode 100644
index 0000000..d67cd76
--- /dev/null
+++ b/microdroid/bootconfig.full_debuggable
@@ -0,0 +1 @@
+kernel.printk.devkmsg=on
diff --git a/microdroid/bootconfig.normal b/microdroid/bootconfig.normal
new file mode 100644
index 0000000..79e2b08
--- /dev/null
+++ b/microdroid/bootconfig.normal
@@ -0,0 +1 @@
+kernel.console = null
diff --git a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
index d62892c..9340200 100644
--- a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
+++ b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
@@ -198,7 +198,7 @@
 
         final String instanceImg = TEST_ROOT + INSTANCE_IMG;
         final String logPath = TEST_ROOT + "log.txt";
-        final String debugFlag = debug ? "--debug " : "";
+        final String debugFlag = debug ? "--debug full" : "";
 
         // Run the VM
         String ret =
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index 6548428..eabeaf3 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -60,7 +60,7 @@
                         APK_NAME,
                         PACKAGE_NAME,
                         configPath,
-                        /* debug */ false,
+                        /* debug */ true,
                         minMemorySize());
         adbConnectToMicrodroid(getDevice(), cid);
 
@@ -104,26 +104,6 @@
         shutdownMicrodroid(getDevice(), cid);
     }
 
-    @Test
-    public void testDebugMode() throws Exception {
-        final String configPath = "assets/vm_config.json"; // path inside the APK
-        final boolean debug = true;
-        final String cid =
-                startMicrodroid(
-                        getDevice(),
-                        getBuild(),
-                        APK_NAME,
-                        PACKAGE_NAME,
-                        configPath,
-                        debug,
-                        minMemorySize());
-        adbConnectToMicrodroid(getDevice(), cid);
-
-        assertThat(runOnMicrodroid("getenforce"), is("Permissive"));
-
-        shutdownMicrodroid(getDevice(), cid);
-    }
-
     @Before
     public void setUp() throws Exception {
         testIfDeviceIsCapable(getDevice());
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index a522dee..073c088 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -29,8 +29,20 @@
     /** Path to a configuration in an APK. This is the actual configuration for a VM. */
     @utf8InCpp String configPath;
 
-    /** Whether to run the VM in debug mode or not */
-    boolean debug;
+    enum DebugLevel {
+        /** Not debuggable at all */
+        NONE,
+        /** Only the logs from app is shown */
+        APP_ONLY,
+        /**
+         * Fully debuggable. All logs are shown, kernel messages are shown, and adb shell is
+         * supported
+         */
+        FULL,
+    }
+
+    /** Debug level of the VM */
+    DebugLevel debugLevel;
 
     /**
      * The amount of RAM to give the VM, in MiB. If this is 0 or negative then it will default to
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index dbcc5ce..2738e2e 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -27,6 +27,7 @@
     IVirtualMachineCallback::IVirtualMachineCallback,
     IVirtualizationService::IVirtualizationService,
     PartitionType::PartitionType,
+    VirtualMachineAppConfig::DebugLevel::DebugLevel,
     VirtualMachineAppConfig::VirtualMachineAppConfig,
     VirtualMachineConfig::VirtualMachineConfig,
     VirtualMachineDebugInfo::VirtualMachineDebugInfo,
@@ -99,7 +100,7 @@
     ) -> binder::Result<Strong<dyn IVirtualMachine>> {
         check_manage_access()?;
         let state = &mut *self.state.lock().unwrap();
-        let log_fd = log_fd.map(clone_file).transpose()?;
+        let mut log_fd = log_fd.map(clone_file).transpose()?;
         let requester_uid = ThreadState::get_calling_uid();
         let requester_sid = get_calling_sid()?;
         let requester_debug_pid = ThreadState::get_calling_pid();
@@ -127,6 +128,16 @@
             )
         })?;
 
+        // Disable console logging if debug level != full. Note that kernel anyway doesn't use the
+        // console output when debug level != full. So, users won't be able to see the kernel
+        // output even without this overriding. This is to silence output from the bootloader which
+        // doesn't understand the bootconfig parameters.
+        if let VirtualMachineConfig::AppConfig(config) = config {
+            if config.debugLevel != DebugLevel::FULL {
+                log_fd = None;
+            }
+        }
+
         let config = match config {
             VirtualMachineConfig::AppConfig(config) => BorrowedOrOwned::Owned(
                 load_app_config(config, &temporary_directory).map_err(|e| {
diff --git a/virtualizationservice/src/payload.rs b/virtualizationservice/src/payload.rs
index 2d238a8..4c71c37 100644
--- a/virtualizationservice/src/payload.rs
+++ b/virtualizationservice/src/payload.rs
@@ -15,7 +15,8 @@
 //! Payload disk image
 
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
-    DiskImage::DiskImage, Partition::Partition, VirtualMachineAppConfig::VirtualMachineAppConfig,
+    DiskImage::DiskImage, Partition::Partition, VirtualMachineAppConfig::DebugLevel::DebugLevel,
+    VirtualMachineAppConfig::VirtualMachineAppConfig,
     VirtualMachineRawConfig::VirtualMachineRawConfig,
 };
 use android_system_virtualizationservice::binder::ParcelFileDescriptor;
@@ -290,16 +291,18 @@
         temporary_directory,
     )?);
 
-    if config.debug {
-        vm_config.disks[1].partitions.push(Partition {
-            label: "bootconfig".to_owned(),
-            image: Some(open_parcel_file(
-                Path::new("/apex/com.android.virt/etc/microdroid_bootconfig.debug"),
-                false,
-            )?),
-            writable: false,
-        });
-    }
+    let bootconfig_image = "/apex/com.android.virt/etc/microdroid_bootconfig.".to_owned()
+        + match config.debugLevel {
+            DebugLevel::NONE => "normal",
+            DebugLevel::APP_ONLY => "app_debuggable",
+            DebugLevel::FULL => "full_debuggable",
+            _ => return Err(anyhow!("unsupported debug level: {:?}", config.debugLevel)),
+        };
+    vm_config.disks[1].partitions.push(Partition {
+        label: "bootconfig".to_owned(),
+        image: Some(open_parcel_file(Path::new(&bootconfig_image), false)?),
+        writable: false,
+    });
 
     // instance image is at the second partition in the second disk.
     vm_config.disks[1].partitions.push(Partition {
diff --git a/vm/src/main.rs b/vm/src/main.rs
index 062773b..7e2a925 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -18,8 +18,10 @@
 mod run;
 mod sync;
 
-use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::IVirtualizationService;
-use android_system_virtualizationservice::aidl::android::system::virtualizationservice::PartitionType::PartitionType;
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+    IVirtualizationService::IVirtualizationService, PartitionType::PartitionType,
+    VirtualMachineAppConfig::DebugLevel::DebugLevel,
+};
 use android_system_virtualizationservice::binder::{wait_for_interface, ProcessState, Strong};
 use anyhow::{Context, Error};
 use create_partition::command_create_partition;
@@ -59,9 +61,9 @@
         #[structopt(short, long)]
         log: Option<PathBuf>,
 
-        /// Whether to run VM in debug mode.
-        #[structopt(short, long)]
-        debug: bool,
+        /// Debug level of the VM. Supported values: "none" (default), "app_only", and "full".
+        #[structopt(short, long, default_value = "none", parse(try_from_str=parse_debug_level))]
+        debug: DebugLevel,
 
         /// Memory size (in MiB) of the VM. If unspecified, defaults to the value of `memory_mib`
         /// in the VM config file.
@@ -104,6 +106,15 @@
     },
 }
 
+fn parse_debug_level(s: &str) -> Result<DebugLevel, String> {
+    match s {
+        "none" => Ok(DebugLevel::NONE),
+        "app_only" => Ok(DebugLevel::APP_ONLY),
+        "full" => Ok(DebugLevel::FULL),
+        _ => Err(format!("Invalid debug level {}", s)),
+    }
+}
+
 fn parse_partition_type(s: &str) -> Result<PartitionType, String> {
     match s {
         "raw" => Ok(PartitionType::RAW),
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 42da6a3..2d771fc 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -16,15 +16,12 @@
 
 use crate::create_partition::command_create_partition;
 use crate::sync::AtomicFlag;
-use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualMachineCallback::{
-    BnVirtualMachineCallback, IVirtualMachineCallback,
-};
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
-    IVirtualMachine::IVirtualMachine,
-    IVirtualizationService::IVirtualizationService,
-    PartitionType::PartitionType,
-    VirtualMachineAppConfig::VirtualMachineAppConfig,
-    VirtualMachineConfig::VirtualMachineConfig,
+    IVirtualMachine::IVirtualMachine, IVirtualMachineCallback::BnVirtualMachineCallback,
+    IVirtualMachineCallback::IVirtualMachineCallback,
+    IVirtualizationService::IVirtualizationService, PartitionType::PartitionType,
+    VirtualMachineAppConfig::DebugLevel::DebugLevel,
+    VirtualMachineAppConfig::VirtualMachineAppConfig, VirtualMachineConfig::VirtualMachineConfig,
     VirtualMachineState::VirtualMachineState,
 };
 use android_system_virtualizationservice::binder::{
@@ -48,7 +45,7 @@
     config_path: &str,
     daemonize: bool,
     log_path: Option<&Path>,
-    debug: bool,
+    debug_level: DebugLevel,
     mem: Option<u32>,
 ) -> Result<(), Error> {
     let apk_file = File::open(apk).context("Failed to open APK file")?;
@@ -76,7 +73,7 @@
         idsig: idsig_fd.into(),
         instanceImage: open_parcel_file(instance, true /* writable */)?.into(),
         configPath: config_path.to_owned(),
-        debug,
+        debugLevel: debug_level,
         memoryMib: mem.unwrap_or(0) as i32, // 0 means use the VM default
     });
     run(service, &config, &format!("{:?}!{:?}", apk, config_path), daemonize, log_path)