Merge "gen_rpc -> require_rpc"
diff --git a/compos/composd/src/composd_main.rs b/compos/composd/src/composd_main.rs
index 235c107..d1b711d 100644
--- a/compos/composd/src/composd_main.rs
+++ b/compos/composd/src/composd_main.rs
@@ -29,6 +29,7 @@
 use anyhow::{Context, Result};
 use compos_common::compos_client::VmInstance;
 use log::{error, info};
+use std::panic;
 use std::sync::Arc;
 
 fn try_main() -> Result<()> {
@@ -38,6 +39,11 @@
         android_logger::Config::default().with_tag("composd").with_min_level(log_level),
     );
 
+    // Redirect panic messages to logcat.
+    panic::set_hook(Box::new(|panic_info| {
+        log::error!("{}", panic_info);
+    }));
+
     ProcessState::start_thread_pool();
 
     let virtualization_service = VmInstance::connect_to_virtualization_service()?;
diff --git a/compos/src/compsvc_main.rs b/compos/src/compsvc_main.rs
index c2923f0..ebb5514 100644
--- a/compos/src/compsvc_main.rs
+++ b/compos/src/compsvc_main.rs
@@ -38,6 +38,7 @@
 use binder_common::rpc_server::run_rpc_server;
 use compos_common::COMPOS_VSOCK_PORT;
 use log::{debug, error};
+use std::panic;
 
 /// The CID representing the host VM
 const VMADDR_CID_HOST: u32 = 2;
@@ -59,6 +60,10 @@
         android_logger::init_once(
             android_logger::Config::default().with_tag("compsvc").with_min_level(log::Level::Debug),
         );
+        // Redirect panic messages to logcat.
+        panic::set_hook(Box::new(|panic_info| {
+            log::error!("{}", panic_info);
+        }));
     }
 
     let service = compsvc::new_binder()?.as_binder();
diff --git a/compos/tests/java/android/compos/test/ComposTestCase.java b/compos/tests/java/android/compos/test/ComposTestCase.java
index ff3baa2..1213ada 100644
--- a/compos/tests/java/android/compos/test/ComposTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposTestCase.java
@@ -38,6 +38,8 @@
     // Binaries used in test. (These paths are valid both in host and Microdroid.)
     private static final String ODREFRESH_BIN = "/apex/com.android.art/bin/odrefresh";
     private static final String COMPOSD_CMD_BIN = "/apex/com.android.compos/bin/composd_cmd";
+    private static final String COMPOS_VERIFY_KEY_BIN =
+            "/apex/com.android.compos/bin/compos_verify_key";
 
     /** Output directory of odrefresh */
     private static final String TEST_ARTIFACTS_DIR = "test-artifacts";
@@ -148,8 +150,11 @@
         assertThat(actualChecksumSnapshot).isEqualTo(expectedChecksumSnapshot);
 
         // Expect extra files generated by CompOS exist.
-        android.assumeSuccess("test -f " + ODREFRESH_OUTPUT_DIR + "/compos.info");
-        android.assumeSuccess("test -f " + ODREFRESH_OUTPUT_DIR + "/compos.info.signature");
+        android.run("test -f " + ODREFRESH_OUTPUT_DIR + "/compos.info");
+        android.run("test -f " + ODREFRESH_OUTPUT_DIR + "/compos.info.signature");
+
+        // Expect the CompOS public key & key blob to be valid
+        android.run(COMPOS_VERIFY_KEY_BIN + " --debug --instance test");
     }
 
     private CommandResult runOdrefresh(CommandRunner android, String command) throws Exception {
diff --git a/compos/verify_key/verify_key.rs b/compos/verify_key/verify_key.rs
index 13d3c8b..9454442 100644
--- a/compos/verify_key/verify_key.rs
+++ b/compos/verify_key/verify_key.rs
@@ -27,6 +27,7 @@
 };
 use std::fs::{self, File};
 use std::io::Read;
+use std::panic;
 use std::path::{Path, PathBuf};
 
 const MAX_FILE_SIZE_BYTES: u64 = 8 * 1024;
@@ -38,6 +39,11 @@
             .with_min_level(log::Level::Info),
     );
 
+    // Redirect panic messages to logcat.
+    panic::set_hook(Box::new(|panic_info| {
+        log::error!("{}", panic_info);
+    }));
+
     if let Err(e) = try_main() {
         log::error!("{:?}", e);
         std::process::exit(-1)
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
index 04a90e0..35d600a 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -206,6 +206,9 @@
             // TODO(jiyong): should we treat APP_ONLY and FULL the same?
             return false;
         }
+        if (this.mProtectedVm != other.mProtectedVm) {
+            return false;
+        }
         return true;
     }
 
diff --git a/tests/Android.bp b/tests/Android.bp
index 8cfefcc..0b3a821 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -38,6 +38,7 @@
         // The existence of the library in the system partition is not guaranteed.
         // Let's have our own copy of it.
         "android.system.virtualizationservice-cpp",
+        "PlatformProperties",
     ],
     shared_libs: [
         "libbase",
diff --git a/tests/vsock_test.cc b/tests/vsock_test.cc
index 0b863a9..9550651 100644
--- a/tests/vsock_test.cc
+++ b/tests/vsock_test.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android/sysprop/HypervisorProperties.sysprop.h>
 #include <linux/kvm.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
@@ -48,15 +49,26 @@
 static constexpr const char kVmParams[] = "rdinit=/bin/init bin/vsock_client 2 45678 HelloWorld";
 static constexpr const char kTestMessage[] = "HelloWorld";
 
-/** Returns true if the kernel supports Protected KVM. */
-bool isPkvmSupported() {
-    unique_fd kvm_fd(open("/dev/kvm", O_NONBLOCK | O_CLOEXEC));
-    return kvm_fd != 0 && ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_PROTECTED_VM) == 1;
+/** Returns true if the kernel supports protected VMs. */
+bool isProtectedVmSupported() {
+    return android::sysprop::HypervisorProperties::hypervisor_protected_vm_supported().value_or(
+            false);
+}
+
+/** Returns true if the kernel supports unprotected VMs. */
+bool isUnprotectedVmSupported() {
+    return android::sysprop::HypervisorProperties::hypervisor_vm_supported().value_or(false);
 }
 
 void runTest(sp<IVirtualizationService> virtualization_service, bool protected_vm) {
-    if (protected_vm && !isPkvmSupported()) {
-        GTEST_SKIP() << "Skipping as pKVM is not supported on this device.";
+    if (protected_vm) {
+        if (!isProtectedVmSupported()) {
+            GTEST_SKIP() << "Skipping as protected VMs are not supported on this device.";
+        }
+    } else {
+        if (!isUnprotectedVmSupported()) {
+            GTEST_SKIP() << "Skipping as unprotected VMs are not supported on this device.";
+        }
     }
 
     binder::Status status;