Merge "libfdt: Use cstr!()" into main
diff --git a/apex/Android.bp b/apex/Android.bp
index 7983181..a05f7b0 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -60,20 +60,7 @@
     ],
 }
 
-soong_config_module_type {
-    name: "flag_aware_apex_defaults",
-    module_type: "apex_defaults",
-    config_namespace: "ANDROID",
-    bool_variables: [
-        "release_avf_enable_remote_attestation",
-    ],
-    properties: [
-        "prebuilts",
-        "vintf_fragments",
-    ],
-}
-
-flag_aware_apex_defaults {
+apex_defaults {
     name: "com.android.virt_avf_enabled",
 
     defaults: ["com.android.virt_common"],
@@ -105,19 +92,8 @@
         "fd_server",
         "vm",
     ],
-    soong_config_variables: {
-        release_avf_enable_remote_attestation: {
-            prebuilts: ["com.android.virt.init_attestation_enabled.rc"],
-            vintf_fragments: [
-                "virtualizationservice.xml",
-            ],
-            conditions_default: {
-                prebuilts: ["com.android.virt.init.rc"],
-            },
-        },
-    },
     prebuilts: [
-        "com.android.virt.vfio_handler.rc",
+        "com.android.virt.init.rc",
         "features_com.android.virt.xml",
         "microdroid_initrd_debuggable",
         "microdroid_initrd_normal",
@@ -152,23 +128,9 @@
 }
 
 prebuilt_etc {
-    name: "com.android.virt.vfio_handler.rc",
-    src: "vfio_handler.rc",
-    filename: "vfio_handler.rc",
-    installable: false,
-}
-
-prebuilt_etc {
     name: "com.android.virt.init.rc",
     src: "virtualizationservice.rc",
-    filename: "virtualizationservice.rc",
-    installable: false,
-}
-
-prebuilt_etc {
-    name: "com.android.virt.init_attestation_enabled.rc",
-    src: "virtualizationservice_attestation_enabled.rc",
-    filename: "virtualizationservice.rc",
+    filename: "init.rc",
     installable: false,
 }
 
diff --git a/apex/vfio_handler.rc b/apex/vfio_handler.rc
deleted file mode 100644
index 419acef..0000000
--- a/apex/vfio_handler.rc
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (C) 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.
-
-service vfio_handler /apex/com.android.virt/bin/vfio_handler
-    user root
-    group system
-    interface aidl android.system.virtualizationservice_internal.IVfioHandler
-    disabled
-    oneshot
diff --git a/apex/virtualizationservice.rc b/apex/virtualizationservice.rc
index 02b2081..8283594 100644
--- a/apex/virtualizationservice.rc
+++ b/apex/virtualizationservice.rc
@@ -19,3 +19,10 @@
     interface aidl android.system.virtualizationservice
     disabled
     oneshot
+
+service vfio_handler /apex/com.android.virt/bin/vfio_handler
+    user root
+    group system
+    interface aidl android.system.virtualizationservice_internal.IVfioHandler
+    disabled
+    oneshot
diff --git a/apex/virtualizationservice.xml b/apex/virtualizationservice.xml
index 60f466f..0ce1e10 100644
--- a/apex/virtualizationservice.xml
+++ b/apex/virtualizationservice.xml
@@ -1,6 +1,6 @@
 <manifest version="1.0" type="framework">
     <hal format="aidl">
-        <name>android.hardware.security.keymint</name>
+        <name>android.system.virtualization</name>
         <version>3</version>
         <fqname>IRemotelyProvisionedComponent/avf</fqname>
     </hal>
diff --git a/apex/virtualizationservice_attestation_enabled.rc b/apex/virtualizationservice_attestation_enabled.rc
deleted file mode 100644
index 8eaccae..0000000
--- a/apex/virtualizationservice_attestation_enabled.rc
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2021 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.
-
-service virtualizationservice /apex/com.android.virt/bin/virtualizationservice
-    class main
-    user system
-    group system
-    interface aidl android.system.virtualizationservice
-    interface aidl android.hardware.security.keymint.IRemotelyProvisionedComponent/avf
-    disabled
-    oneshot
diff --git a/libs/apkmanifest/src/apkmanifest.rs b/libs/apkmanifest/src/apkmanifest.rs
index 6766b21..b92aa74 100644
--- a/libs/apkmanifest/src/apkmanifest.rs
+++ b/libs/apkmanifest/src/apkmanifest.rs
@@ -28,7 +28,7 @@
 use std::path::Path;
 
 /// Information extracted from the Android manifest inside an APK.
-#[derive(Debug)]
+#[derive(Debug, Default, Eq, PartialEq)]
 pub struct ApkManifestInfo {
     /// The package name of the app.
     pub package: String,
diff --git a/libs/apkverify/tests/apkverify_test.rs b/libs/apkverify/tests/apkverify_test.rs
index 680c81e..0d8e020 100644
--- a/libs/apkverify/tests/apkverify_test.rs
+++ b/libs/apkverify/tests/apkverify_test.rs
@@ -20,6 +20,7 @@
 use apkzip::zip_sections;
 use byteorder::{LittleEndian, ReadBytesExt};
 use log::info;
+use std::fmt::Write;
 use std::io::{Seek, SeekFrom};
 use std::{fs, matches, path::Path};
 
@@ -330,7 +331,10 @@
     assert!(
         fs::metadata(&expected_data_path).is_ok(),
         "File does not exist. You can re-create it with:\n$ echo -en {} > {}\n",
-        bytes_data.iter().map(|b| format!("\\\\x{:02x}", b)).collect::<String>(),
+        bytes_data.iter().fold(String::new(), |mut output, b| {
+            let _ = write!(output, "\\\\x{:02x}", b);
+            output
+        }),
         expected_data_path
     );
     let expected_data = fs::read(&expected_data_path).unwrap();
diff --git a/libs/dice/open_dice/src/error.rs b/libs/dice/open_dice/src/error.rs
index 53ffd2d..bef9a9c 100644
--- a/libs/dice/open_dice/src/error.rs
+++ b/libs/dice/open_dice/src/error.rs
@@ -38,11 +38,11 @@
 impl fmt::Display for DiceError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Self::InvalidInput => write!(f, "invalid input"),
+            Self::InvalidInput => write!(f, "Invalid input"),
             Self::BufferTooSmall(buffer_required_size) => {
-                write!(f, "buffer too small. Required {buffer_required_size} bytes.")
+                write!(f, "Buffer too small; need {buffer_required_size} bytes")
             }
-            Self::PlatformError => write!(f, "platform error"),
+            Self::PlatformError => write!(f, "Platform error"),
         }
     }
 }
diff --git a/microdroid_manager/Android.bp b/microdroid_manager/Android.bp
index db65193..8710e54 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -24,6 +24,7 @@
         "libbyteorder",
         "libcap_rust",
         "libciborium",
+        "libcoset",
         "libdiced_open_dice",
         "libdiced_sample_inputs",
         "libglob",
diff --git a/microdroid_manager/src/dice.rs b/microdroid_manager/src/dice.rs
index a576416..6b0775a 100644
--- a/microdroid_manager/src/dice.rs
+++ b/microdroid_manager/src/dice.rs
@@ -13,12 +13,15 @@
 // limitations under the License.
 
 use crate::dice_driver::DiceDriver;
+use crate::instance::ApkData;
 use crate::{is_debuggable, MicrodroidData};
 use anyhow::{bail, Context, Result};
-use ciborium::{cbor, ser};
+use ciborium::{cbor, Value};
+use coset::CborSerializable;
 use diced_open_dice::OwnedDiceArtifacts;
 use microdroid_metadata::PayloadMetadata;
-use openssl::sha::Sha512;
+use openssl::sha::{sha512, Sha512};
+use std::iter::once;
 
 /// Perform an open DICE derivation for the payload.
 pub fn dice_derivation(
@@ -26,6 +29,11 @@
     verified_data: &MicrodroidData,
     payload_metadata: &PayloadMetadata,
 ) -> Result<OwnedDiceArtifacts> {
+    let subcomponents = build_subcomponent_list(verified_data);
+
+    let config_descriptor = format_payload_config_descriptor(payload_metadata, &subcomponents)
+        .context("Building config descriptor")?;
+
     // Calculate compound digests of code and authorities
     let mut code_hash_ctx = Sha512::new();
     let mut authority_hash_ctx = Sha512::new();
@@ -42,8 +50,6 @@
     let code_hash = code_hash_ctx.finish();
     let authority_hash = authority_hash_ctx.finish();
 
-    let config_descriptor = format_payload_config_descriptor(payload_metadata)?;
-
     // Check debuggability, conservatively assuming it is debuggable
     let debuggable = is_debuggable()?;
 
@@ -52,35 +58,71 @@
     dice.derive(code_hash, &config_descriptor, authority_hash, debuggable, hidden)
 }
 
-/// Returns a configuration descriptor of the given payload following the BCC's specification:
-/// https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl
-/// {
-///   -70002: "Microdroid payload",
-///   ? -71000: tstr ; payload_config_path
-///   ? -71001: PayloadConfig
-/// }
-/// PayloadConfig = {
-///   1: tstr ; payload_binary_name
-/// }
-fn format_payload_config_descriptor(payload: &PayloadMetadata) -> Result<Vec<u8>> {
-    const MICRODROID_PAYLOAD_COMPONENT_NAME: &str = "Microdroid payload";
+struct Subcomponent<'a> {
+    name: String,
+    version: u64,
+    code_hash: &'a [u8],
+    authority_hash: Box<[u8]>,
+}
 
-    let config_descriptor_cbor_value = match payload {
-        PayloadMetadata::ConfigPath(payload_config_path) => cbor!({
-            -70002 => MICRODROID_PAYLOAD_COMPONENT_NAME,
-            -71000 => payload_config_path
-        }),
-        PayloadMetadata::Config(payload_config) => cbor!({
-            -70002 => MICRODROID_PAYLOAD_COMPONENT_NAME,
-            -71001 => {1 => payload_config.payload_binary_name}
-        }),
-        _ => bail!("Failed to match the payload against a config type: {:?}", payload),
+impl<'a> Subcomponent<'a> {
+    fn to_value(&self) -> Result<Value> {
+        Ok(cbor!({
+           1 => self.name,
+           2 => self.version,
+           3 => self.code_hash,
+           4 => self.authority_hash
+        })?)
     }
-    .context("Failed to build a CBOR Value from payload metadata")?;
-    let mut config_descriptor = Vec::new();
 
-    ser::into_writer(&config_descriptor_cbor_value, &mut config_descriptor)?;
-    Ok(config_descriptor)
+    fn for_apk(apk: &'a ApkData) -> Self {
+        Self {
+            name: format!("apk:{}", apk.package_name),
+            version: apk.version_code,
+            code_hash: &apk.root_hash,
+            authority_hash:
+                // TODO(b/305925597): Hash the certificate not the pubkey
+                Box::new(sha512(&apk.pubkey)),
+        }
+    }
+}
+
+fn build_subcomponent_list(verified_data: &MicrodroidData) -> Vec<Subcomponent> {
+    if !cfg!(dice_changes) {
+        return vec![];
+    }
+
+    once(&verified_data.apk_data)
+        .chain(&verified_data.extra_apks_data)
+        .map(Subcomponent::for_apk)
+        .collect()
+}
+
+// Returns a configuration descriptor of the given payload. See vm_config.cddl for a definition
+// of the format.
+fn format_payload_config_descriptor(
+    payload: &PayloadMetadata,
+    subcomponents: &[Subcomponent],
+) -> Result<Vec<u8>> {
+    let mut map = Vec::new();
+    map.push((cbor!(-70002)?, cbor!("Microdroid payload")?));
+    map.push(match payload {
+        PayloadMetadata::ConfigPath(payload_config_path) => {
+            (cbor!(-71000)?, cbor!(payload_config_path)?)
+        }
+        PayloadMetadata::Config(payload_config) => {
+            (cbor!(-71001)?, cbor!({1 => payload_config.payload_binary_name})?)
+        }
+        _ => bail!("Failed to match the payload against a config type: {:?}", payload),
+    });
+
+    if !subcomponents.is_empty() {
+        let values =
+            subcomponents.iter().map(Subcomponent::to_value).collect::<Result<Vec<_>>>()?;
+        map.push((cbor!(-71002)?, cbor!(values)?));
+    }
+
+    Ok(Value::Map(map).to_vec()?)
 }
 
 #[cfg(test)]
@@ -88,17 +130,30 @@
     use super::*;
     use microdroid_metadata::PayloadConfig;
 
+    const NO_SUBCOMPONENTS: [Subcomponent; 0] = [];
+
+    fn assert_eq_bytes(expected: &[u8], actual: &[u8]) {
+        assert_eq!(
+            expected,
+            actual,
+            "Expected {}, got {}",
+            hex::encode(expected),
+            hex::encode(actual)
+        )
+    }
+
     #[test]
     fn payload_metadata_with_path_formats_correctly() -> Result<()> {
         let payload_metadata = PayloadMetadata::ConfigPath("/config_path".to_string());
-        let config_descriptor = format_payload_config_descriptor(&payload_metadata)?;
+        let config_descriptor =
+            format_payload_config_descriptor(&payload_metadata, &NO_SUBCOMPONENTS)?;
         static EXPECTED_CONFIG_DESCRIPTOR: &[u8] = &[
             0xa2, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x72, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x64, 0x72,
             0x6f, 0x69, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x00, 0x01,
             0x15, 0x57, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74,
             0x68,
         ];
-        assert_eq!(EXPECTED_CONFIG_DESCRIPTOR, &config_descriptor);
+        assert_eq_bytes(EXPECTED_CONFIG_DESCRIPTOR, &config_descriptor);
         Ok(())
     }
 
@@ -109,14 +164,48 @@
             ..Default::default()
         };
         let payload_metadata = PayloadMetadata::Config(payload_config);
-        let config_descriptor = format_payload_config_descriptor(&payload_metadata)?;
+        let config_descriptor =
+            format_payload_config_descriptor(&payload_metadata, &NO_SUBCOMPONENTS)?;
         static EXPECTED_CONFIG_DESCRIPTOR: &[u8] = &[
             0xa2, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x72, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x64, 0x72,
             0x6f, 0x69, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x00, 0x01,
             0x15, 0x58, 0xa1, 0x01, 0x6e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x62,
             0x69, 0x6e, 0x61, 0x72, 0x79,
         ];
-        assert_eq!(EXPECTED_CONFIG_DESCRIPTOR, &config_descriptor);
+        assert_eq_bytes(EXPECTED_CONFIG_DESCRIPTOR, &config_descriptor);
+        Ok(())
+    }
+
+    #[test]
+    fn payload_metadata_with_subcomponents_formats_correctly() -> Result<()> {
+        let payload_metadata = PayloadMetadata::ConfigPath("/config_path".to_string());
+        let subcomponents = [
+            Subcomponent {
+                name: "apk1".to_string(),
+                version: 1,
+                code_hash: &[42u8],
+                authority_hash: Box::new([17u8]),
+            },
+            Subcomponent {
+                name: "apk2".to_string(),
+                version: 0x1000_0000_0001,
+                code_hash: &[43u8],
+                authority_hash: Box::new([19u8]),
+            },
+        ];
+        let config_descriptor =
+            format_payload_config_descriptor(&payload_metadata, &subcomponents)?;
+        // Verified using cbor.me.
+        static EXPECTED_CONFIG_DESCRIPTOR: &[u8] = &[
+            0xa3, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x72, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x64, 0x72,
+            0x6f, 0x69, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x00, 0x01,
+            0x15, 0x57, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74,
+            0x68, 0x3a, 0x00, 0x01, 0x15, 0x59, 0x82, 0xa4, 0x01, 0x64, 0x61, 0x70, 0x6b, 0x31,
+            0x02, 0x01, 0x03, 0x81, 0x18, 0x2a, 0x04, 0x81, 0x11, 0xa4, 0x01, 0x64, 0x61, 0x70,
+            0x6b, 0x32, 0x02, 0x1b, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x81,
+            0x18, 0x2b, 0x04, 0x81, 0x13,
+        ];
+        assert_eq_bytes(EXPECTED_CONFIG_DESCRIPTOR, &config_descriptor);
         Ok(())
     }
 }
diff --git a/microdroid_manager/src/instance.rs b/microdroid_manager/src/instance.rs
index 2ff04f1..6c9e245 100644
--- a/microdroid_manager/src/instance.rs
+++ b/microdroid_manager/src/instance.rs
@@ -289,6 +289,8 @@
 pub struct ApkData {
     pub root_hash: Box<RootHash>,
     pub pubkey: Box<[u8]>,
+    pub package_name: String,
+    pub version_code: u64,
 }
 
 impl ApkData {
diff --git a/microdroid_manager/src/verify.rs b/microdroid_manager/src/verify.rs
index 06b15f7..22f3414 100644
--- a/microdroid_manager/src/verify.rs
+++ b/microdroid_manager/src/verify.rs
@@ -145,19 +145,26 @@
     // taken only when the root_hash is un-trustful which can be either when this is the first boot
     // of the VM or APK was updated in the host.
     // TODO(jooyung): consider multithreading to make this faster
-    let main_apk_pubkey = get_public_key_from_apk(DM_MOUNTED_APK_PATH, root_hash_trustful)?;
+
+    let main_apk_data =
+        get_data_from_apk(DM_MOUNTED_APK_PATH, root_hash_from_idsig, root_hash_trustful)?;
+
     let extra_apks_data = extra_root_hashes_from_idsig
         .into_iter()
         .enumerate()
         .map(|(i, extra_root_hash)| {
             let mount_path = format!("/dev/block/mapper/{}", &extra_apk_names[i]);
-            let apk_pubkey = get_public_key_from_apk(&mount_path, extra_root_hashes_trustful[i])?;
-            Ok(ApkData { root_hash: extra_root_hash, pubkey: apk_pubkey })
+            get_data_from_apk(&mount_path, extra_root_hash, extra_root_hashes_trustful[i])
         })
         .collect::<Result<Vec<_>>>()?;
 
     info!("payload verification successful. took {:#?}", start_time.elapsed().unwrap());
 
+    // At this point, we can ensure that the root hashes from the idsig files are trusted, either
+    // because we have fully verified the APK signature (and apkdmverity checks all the data we
+    // verified is consistent with the root hash) or because we have the saved APK data which will
+    // be checked as identical to the data we have verified.
+
     // Use the salt from a verified instance, or generate a salt for a new instance.
     let salt = if let Some(saved_data) = saved_data {
         saved_data.salt.clone()
@@ -170,16 +177,36 @@
         salt
     };
 
-    // At this point, we can ensure that the root_hash from the idsig file is trusted, either by
-    // fully verifying the APK or by comparing it with the saved root_hash.
     Ok(MicrodroidData {
         salt,
-        apk_data: ApkData { root_hash: root_hash_from_idsig, pubkey: main_apk_pubkey },
+        apk_data: main_apk_data,
         extra_apks_data,
         apex_data: apex_data_from_payload,
     })
 }
 
+fn get_data_from_apk(
+    apk_path: &str,
+    root_hash: Box<RootHash>,
+    root_hash_trustful: bool,
+) -> Result<ApkData> {
+    let pubkey = get_public_key_from_apk(apk_path, root_hash_trustful)?;
+    // Read package name etc from the APK manifest. In the unlikely event that they aren't present
+    // we use the default values. We simply put these values in the DICE node for the payload, and
+    // users of that can decide how to handle blank information - there's no reason for us
+    // to fail starting a VM even with such a weird APK.
+    let manifest_info = get_manifest_info(apk_path)
+        .map_err(|e| warn!("Failed to read manifest info from APK: {e:?}"))
+        .unwrap_or_default();
+
+    Ok(ApkData {
+        root_hash,
+        pubkey,
+        package_name: manifest_info.package,
+        version_code: manifest_info.version_code,
+    })
+}
+
 fn get_apk_root_hash_from_idsig<P: AsRef<Path>>(idsig_path: P) -> Result<Box<RootHash>> {
     Ok(V4Signature::from_idsig_path(idsig_path)?.hashing_info.raw_root_hash)
 }
@@ -187,24 +214,14 @@
 fn get_public_key_from_apk(apk: &str, root_hash_trustful: bool) -> Result<Box<[u8]>> {
     let current_sdk = get_current_sdk()?;
 
-    let public_key_der = if !root_hash_trustful {
+    if !root_hash_trustful {
         verify(apk, current_sdk).context(MicrodroidError::PayloadVerificationFailed(format!(
             "failed to verify {}",
             apk
-        )))?
+        )))
     } else {
-        get_public_key_der(apk, current_sdk)?
-    };
-
-    match get_manifest_info(apk) {
-        Ok(manifest_info) => {
-            // TODO (b/299591171): Do something with this info
-            info!("Manifest info is {manifest_info:?}")
-        }
-        Err(e) => warn!("Failed to read manifest info from APK: {e:?}"),
-    };
-
-    Ok(public_key_der)
+        get_public_key_der(apk, current_sdk)
+    }
 }
 
 fn get_current_sdk() -> Result<u32> {
diff --git a/microdroid_manager/src/vm_config.cddl b/microdroid_manager/src/vm_config.cddl
new file mode 100644
index 0000000..052262d
--- /dev/null
+++ b/microdroid_manager/src/vm_config.cddl
@@ -0,0 +1,31 @@
+; Configuration Descriptor used in the DICE node that describes the payload of a Microdroid virtual
+; machine.
+;
+; See the Open DICE specification
+; https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md,
+; and the Android Profile for DICE
+; https://pigweed.googlesource.com/open-dice/+/HEAD/docs/android.md.
+;
+; CDDL for the normal Configuration Descriptor can be found at
+; https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
+
+; The configuration descriptor node for a Microdroid VM, with extensions to describe the contents
+; of the VM payload.
+VmConfigDescriptor = {
+    -70002 : "Microdroid payload",      ; Component name
+    (? -71000: tstr //                  ; Path to the payload config file
+    ? -71001: PayloadConfig),
+    ? -71002: [+ SubcomponentDescriptor],
+}
+
+PayloadConfig = {
+    1: tstr                             ; Path to the binary file where payload execution starts
+}
+
+; Describes a unit of code (e.g. an APK or an APEX) present inside the VM.
+SubcomponentDescriptor = {
+  1: tstr,                              ; Component name
+  2: uint,                              ; Security version
+  ? 3: bstr,                            ; Code hash
+  4: bstr,                              ; Authority hash
+}
diff --git a/service_vm/requests/src/rkp.rs b/service_vm/requests/src/rkp.rs
index f5b9203..8d7d771 100644
--- a/service_vm/requests/src/rkp.rs
+++ b/service_vm/requests/src/rkp.rs
@@ -75,13 +75,10 @@
         public_keys.push(public_key.to_cbor_value()?);
     }
     // Builds `CsrPayload`.
-    // TODO(b/299256925): The device information is currently empty as we do not
-    // have sufficient details to include.
-    let device_info = Value::Map(Vec::new());
     let csr_payload = cbor!([
         Value::Integer(CSR_PAYLOAD_SCHEMA_V3.into()),
         Value::Text(String::from(CERTIFICATE_TYPE)),
-        device_info,
+        // TODO(b/299256925): Add device info in CBOR format here.
         Value::Array(public_keys),
     ])?;
     let csr_payload = cbor_util::serialize(&csr_payload)?;
diff --git a/service_vm/client_apk/Android.bp b/service_vm/test_apk/Android.bp
similarity index 95%
rename from service_vm/client_apk/Android.bp
rename to service_vm/test_apk/Android.bp
index d94489d..4da3f81 100644
--- a/service_vm/client_apk/Android.bp
+++ b/service_vm/test_apk/Android.bp
@@ -3,7 +3,7 @@
 }
 
 android_app {
-    name: "ServiceVmClientApp",
+    name: "ServiceVmClientTestApp",
     installable: true,
     jni_libs: ["libservice_vm_client"],
     jni_uses_platform_apis: true,
diff --git a/service_vm/client_apk/AndroidManifest.xml b/service_vm/test_apk/AndroidManifest.xml
similarity index 100%
rename from service_vm/client_apk/AndroidManifest.xml
rename to service_vm/test_apk/AndroidManifest.xml
diff --git a/service_vm/client_apk/assets/config.json b/service_vm/test_apk/assets/config.json
similarity index 100%
rename from service_vm/client_apk/assets/config.json
rename to service_vm/test_apk/assets/config.json
diff --git a/service_vm/client_apk/src/main.rs b/service_vm/test_apk/src/main.rs
similarity index 97%
rename from service_vm/client_apk/src/main.rs
rename to service_vm/test_apk/src/main.rs
index bd48dc3..7d8416f 100644
--- a/service_vm/client_apk/src/main.rs
+++ b/service_vm/test_apk/src/main.rs
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Main executable of Service VM client.
+//! Main executable of Service VM client for manual testing.
 
 use anyhow::Result;
 use log::{error, info};
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index 7bdab0a..c00445d 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -31,7 +31,6 @@
         "libanyhow",
         "libavflog",
         "libbinder_rs",
-        "libhypervisor_props",
         "liblibc",
         "liblog_rust",
         "libnix",
diff --git a/virtualizationservice/src/main.rs b/virtualizationservice/src/main.rs
index c2e55eb..fd668bc 100644
--- a/virtualizationservice/src/main.rs
+++ b/virtualizationservice/src/main.rs
@@ -33,8 +33,8 @@
 use std::path::Path;
 
 const LOG_TAG: &str = "VirtualizationService";
-const REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME: &str =
-    "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
+const _REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME: &str =
+    "android.system.virtualization.IRemotelyProvisionedComponent/avf";
 
 fn get_calling_pid() -> pid_t {
     ThreadState::get_calling_pid()
@@ -69,17 +69,10 @@
     register_lazy_service(BINDER_SERVICE_IDENTIFIER, service.as_binder()).unwrap();
     info!("Registered Binder service {}.", BINDER_SERVICE_IDENTIFIER);
 
-    if cfg!(remote_attestation) {
-        // The IRemotelyProvisionedComponent service is only supposed to be triggered by rkpd for
-        // RKP VM attestation.
-        let remote_provisioning_service = remote_provisioning::new_binder();
-        register_lazy_service(
-            REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
-            remote_provisioning_service.as_binder(),
-        )
-        .unwrap();
-        info!("Registered Binder service {}.", REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME);
-    }
+    // The IRemotelyProvisionedComponent service is only supposed to be triggered by rkpd for
+    // RKP VM attestation.
+    let _remote_provisioning_service = remote_provisioning::new_binder();
+    // TODO(b/274881098): Register the RKP service when the implementation is ready.
 
     ProcessState::join_thread_pool();
 }
diff --git a/virtualizationservice/src/remote_provisioning.rs b/virtualizationservice/src/remote_provisioning.rs
index 40f54db..a9a07a5 100644
--- a/virtualizationservice/src/remote_provisioning.rs
+++ b/virtualizationservice/src/remote_provisioning.rs
@@ -27,11 +27,7 @@
 };
 use anyhow::Context;
 use avflog::LogResult;
-use binder::{
-    BinderFeatures, ExceptionCode, Interface, IntoBinderResult, Result as BinderResult, Status,
-    Strong,
-};
-use hypervisor_props::is_protected_vm_supported;
+use binder::{BinderFeatures, Interface, IntoBinderResult, Result as BinderResult, Status, Strong};
 use service_vm_comm::{RequestProcessingError, Response};
 
 /// Constructs a binder object that implements `IRemotelyProvisionedComponent`.
@@ -49,13 +45,11 @@
 #[allow(non_snake_case)]
 impl IRemotelyProvisionedComponent for AvfRemotelyProvisionedComponent {
     fn getHardwareInfo(&self) -> BinderResult<RpcHardwareInfo> {
-        check_protected_vm_is_supported()?;
-
         Ok(RpcHardwareInfo {
             versionNumber: 3,
             rpcAuthorName: String::from("Android Virtualization Framework"),
             supportedEekCurve: CURVE_NONE,
-            uniqueId: Some(String::from("AVF Remote Provisioning 1")),
+            uniqueId: Some(String::from("Android Virtualization Framework 1")),
             supportedNumKeysInCsr: MIN_SUPPORTED_NUM_KEYS_IN_CSR,
         })
     }
@@ -65,8 +59,6 @@
         testMode: bool,
         macedPublicKey: &mut MacedPublicKey,
     ) -> BinderResult<Vec<u8>> {
-        check_protected_vm_is_supported()?;
-
         if testMode {
             return Err(Status::new_service_specific_error_str(
                 STATUS_REMOVED,
@@ -109,8 +101,6 @@
         keysToSign: &[MacedPublicKey],
         challenge: &[u8],
     ) -> BinderResult<Vec<u8>> {
-        check_protected_vm_is_supported()?;
-
         const MAX_CHALLENGE_SIZE: usize = 64;
         if challenge.len() > MAX_CHALLENGE_SIZE {
             let message = format!(
@@ -133,18 +123,6 @@
     }
 }
 
-fn check_protected_vm_is_supported() -> BinderResult<()> {
-    if is_protected_vm_supported().unwrap_or(false) {
-        Ok(())
-    } else {
-        Err(Status::new_exception_str(
-            ExceptionCode::UNSUPPORTED_OPERATION,
-            Some("Protected VM support is missing for this operation"),
-        ))
-        .with_log()
-    }
-}
-
 fn to_service_specific_error(response: Response) -> Status {
     match response {
         Response::Err(e) => match e {
diff --git a/vm_payload/Android.bp b/vm_payload/Android.bp
index d2ac7ee..b5322a8 100644
--- a/vm_payload/Android.bp
+++ b/vm_payload/Android.bp
@@ -35,7 +35,7 @@
     apex_available: ["com.android.compos"],
     visibility: [
         "//packages/modules/Virtualization/compos",
-        "//packages/modules/Virtualization/service_vm/client_apk",
+        "//packages/modules/Virtualization/service_vm/test_apk",
     ],
     shared_libs: [
         "libvm_payload#current",