Merge "Specify system server compiler filter if configured"
diff --git a/apex/Android.bp b/apex/Android.bp
index f1eeed9..25cd480 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -5,6 +5,7 @@
 microdroid_filesystem_images = [
     "microdroid_super",
     "microdroid_boot-5.10",
+    "microdroid_init_boot",
     "microdroid_vendor_boot-5.10",
     "microdroid_vbmeta",
     "microdroid_vbmeta_bootconfig",
diff --git a/apex/product_packages.mk b/apex/product_packages.mk
index 322b73e..ec295f5 100644
--- a/apex/product_packages.mk
+++ b/apex/product_packages.mk
@@ -31,3 +31,5 @@
 PRODUCT_APEX_SYSTEM_SERVER_JARS := com.android.compos:service-compos
 
 PRODUCT_SYSTEM_EXT_PROPERTIES := ro.config.isolated_compilation_enabled=true
+
+PRODUCT_SYSTEM_FSVERITY_GENERATE_METADATA := true
diff --git a/apex/sign_virt_apex.py b/apex/sign_virt_apex.py
index 153b5dd..9a0fe1a 100644
--- a/apex/sign_virt_apex.py
+++ b/apex/sign_virt_apex.py
@@ -282,6 +282,8 @@
     boot_img = os.path.join(input_dir, 'etc', 'fs', 'microdroid_boot-5.10.img')
     vendor_boot_img = os.path.join(
         input_dir, 'etc', 'fs', 'microdroid_vendor_boot-5.10.img')
+    init_boot_img = os.path.join(
+        input_dir, 'etc', 'fs', 'microdroid_init_boot.img')
     super_img = os.path.join(input_dir, 'etc', 'fs', 'microdroid_super.img')
     vbmeta_img = os.path.join(input_dir, 'etc', 'fs', 'microdroid_vbmeta.img')
     vbmeta_bootconfig_img = os.path.join(
@@ -297,10 +299,11 @@
     # while it's okay to use different keys for other image files.
     ReplaceBootloaderPubkey(args, key, bootloader, bootloader_pubkey)
 
-    # re-sign bootloader, boot.img, vendor_boot.img
+    # re-sign bootloader, boot.img, vendor_boot.img, and init_boot.img
     AddHashFooter(args, key, bootloader)
     AddHashFooter(args, key, boot_img)
     AddHashFooter(args, key, vendor_boot_img)
+    AddHashFooter(args, key, init_boot_img)
 
     # re-sign super.img
     with TempDirectory() as work_dir:
@@ -320,12 +323,12 @@
         # re-pack super.img
         MakeSuperImage(args, partitions, super_img)
 
-        # re-generate vbmeta from re-signed {boot, vendor_boot, system_a, vendor_a}.img
+        # re-generate vbmeta from re-signed {boot, vendor_boot, init_boot, system_a, vendor_a}.img
         # Ideally, making VBmeta should be done out of TempDirectory block. But doing it here
         # to avoid unpacking re-signed super.img for system/vendor images which are available
         # in this block.
         MakeVbmetaImage(args, key, vbmeta_img, images=[
-                        boot_img, vendor_boot_img, system_a_img, vendor_a_img])
+                        boot_img, vendor_boot_img, init_boot_img, system_a_img, vendor_a_img])
 
     # Re-sign bootconfigs with the same key
     bootconfig_sign_key = key
diff --git a/compos/apk/assets/vm_config.json b/compos/apk/assets/vm_config.json
index 0e97228..260332e 100644
--- a/compos/apk/assets/vm_config.json
+++ b/compos/apk/assets/vm_config.json
@@ -10,6 +10,11 @@
       "--log_to_stderr"
     ]
   },
+  "extra_apks": [
+    {
+      "path": "/system/etc/security/fsverity/BuildManifest.apk"
+    }
+  ],
   "apexes": [
     {
       "name": "com.android.art"
diff --git a/compos/apk/assets/vm_config_staged.json b/compos/apk/assets/vm_config_staged.json
index 5820982..1affa79 100644
--- a/compos/apk/assets/vm_config_staged.json
+++ b/compos/apk/assets/vm_config_staged.json
@@ -11,6 +11,11 @@
     ]
   },
   "prefer_staged": true,
+  "extra_apks": [
+    {
+      "path": "/system/etc/security/fsverity/BuildManifest.apk"
+    }
+  ],
   "apexes": [
     {
       "name": "com.android.art"
diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs
index 3bb066f..4216e1a 100644
--- a/compos/common/compos_client.rs
+++ b/compos/common/compos_client.rs
@@ -73,6 +73,7 @@
         service: &dyn IVirtualizationService,
         instance_image: File,
         idsig: &Path,
+        idsig_manifest_apk: &Path,
         parameters: &VmParameters,
     ) -> Result<VmInstance> {
         let instance_fd = ParcelFileDescriptor::new(instance_image);
@@ -83,19 +84,12 @@
         let apk_fd = File::open(apex_dir.join("app/CompOSPayloadApp/CompOSPayloadApp.apk"))
             .context("Failed to open config APK file")?;
         let apk_fd = ParcelFileDescriptor::new(apk_fd);
+        let idsig_fd = prepare_idsig(service, &apk_fd, idsig)?;
 
-        if !idsig.exists() {
-            // Prepare idsig file via VirtualizationService
-            let idsig_file = File::create(idsig).context("Failed to create idsig file")?;
-            let idsig_fd = ParcelFileDescriptor::new(idsig_file);
-            service
-                .createOrUpdateIdsigFile(&apk_fd, &idsig_fd)
-                .context("Failed to update idsig file")?;
-        }
-
-        // Open idsig as read-only
-        let idsig_file = File::open(idsig).context("Failed to open idsig file")?;
-        let idsig_fd = ParcelFileDescriptor::new(idsig_file);
+        let manifest_apk_fd = File::open("/system/etc/security/fsverity/BuildManifest.apk")
+            .context("Failed to open build manifest APK file")?;
+        let manifest_apk_fd = ParcelFileDescriptor::new(manifest_apk_fd);
+        let idsig_manifest_apk_fd = prepare_idsig(service, &manifest_apk_fd, idsig_manifest_apk)?;
 
         let (console_fd, log_fd, debug_level) = if parameters.debug_mode {
             // Console output and the system log output from the VM are redirected to file.
@@ -117,6 +111,7 @@
             instanceImage: Some(instance_fd),
             configPath: config_path.to_owned(),
             debugLevel: debug_level,
+            extraIdsigs: vec![idsig_manifest_apk_fd],
             ..Default::default()
         });
 
@@ -165,6 +160,26 @@
     }
 }
 
+fn prepare_idsig(
+    service: &dyn IVirtualizationService,
+    apk_fd: &ParcelFileDescriptor,
+    idsig_path: &Path,
+) -> Result<ParcelFileDescriptor> {
+    if !idsig_path.exists() {
+        // Prepare idsig file via VirtualizationService
+        let idsig_file = File::create(idsig_path).context("Failed to create idsig file")?;
+        let idsig_fd = ParcelFileDescriptor::new(idsig_file);
+        service
+            .createOrUpdateIdsigFile(apk_fd, &idsig_fd)
+            .context("Failed to update idsig file")?;
+    }
+
+    // Open idsig as read-only
+    let idsig_file = File::open(idsig_path).context("Failed to open idsig file")?;
+    let idsig_fd = ParcelFileDescriptor::new(idsig_file);
+    Ok(idsig_fd)
+}
+
 struct VsockFactory<'a> {
     vm: &'a dyn IVirtualMachine,
 }
diff --git a/compos/common/lib.rs b/compos/common/lib.rs
index 9a4d0e3..66ce8cb 100644
--- a/compos/common/lib.rs
+++ b/compos/common/lib.rs
@@ -58,6 +58,10 @@
 /// The file that holds the idsig for the CompOS Payload APK.
 pub const IDSIG_FILE: &str = "idsig";
 
+/// The file that holds the idsig for the build manifest APK (that makes enumerated files from
+/// /system available in CompOS).
+pub const IDSIG_MANIFEST_APK_FILE: &str = "idsig_manifest_apk";
+
 /// The path within our config APK of our default VM configuration file, used at boot time.
 pub const DEFAULT_VM_CONFIG_PATH: &str = "assets/vm_config.json";
 
diff --git a/compos/composd/src/instance_starter.rs b/compos/composd/src/instance_starter.rs
index 6946c11..4fed98a 100644
--- a/compos/composd/src/instance_starter.rs
+++ b/compos/composd/src/instance_starter.rs
@@ -26,7 +26,8 @@
 use compos_aidl_interface::binder::{ParcelFileDescriptor, Strong};
 use compos_common::compos_client::{VmInstance, VmParameters};
 use compos_common::{
-    COMPOS_DATA_ROOT, IDSIG_FILE, INSTANCE_IMAGE_FILE, PRIVATE_KEY_BLOB_FILE, PUBLIC_KEY_FILE,
+    COMPOS_DATA_ROOT, IDSIG_FILE, IDSIG_MANIFEST_APK_FILE, INSTANCE_IMAGE_FILE,
+    PRIVATE_KEY_BLOB_FILE, PUBLIC_KEY_FILE,
 };
 use log::{info, warn};
 use std::fs;
@@ -51,6 +52,7 @@
     instance_root: PathBuf,
     instance_image: PathBuf,
     idsig: PathBuf,
+    idsig_manifest_apk: PathBuf,
     key_blob: PathBuf,
     public_key: PathBuf,
     vm_parameters: VmParameters,
@@ -62,6 +64,7 @@
         let instance_root_path = instance_root.as_path();
         let instance_image = instance_root_path.join(INSTANCE_IMAGE_FILE);
         let idsig = instance_root_path.join(IDSIG_FILE);
+        let idsig_manifest_apk = instance_root_path.join(IDSIG_MANIFEST_APK_FILE);
         let key_blob = instance_root_path.join(PRIVATE_KEY_BLOB_FILE);
         let public_key = instance_root_path.join(PUBLIC_KEY_FILE);
         Self {
@@ -69,6 +72,7 @@
             instance_root,
             instance_image,
             idsig,
+            idsig_manifest_apk,
             key_blob,
             public_key,
             vm_parameters,
@@ -125,8 +129,9 @@
         let _ = fs::create_dir(&self.instance_root);
 
         self.create_instance_image(virtualization_service)?;
-        // Delete existing idsig file. Ignore error in case idsig doesn't exist.
+        // Delete existing idsig files. Ignore error in case idsig doesn't exist.
         let _ = fs::remove_file(&self.idsig);
+        let _ = fs::remove_file(&self.idsig_manifest_apk);
 
         let compos_instance = self.start_vm(virtualization_service)?;
         let service = &compos_instance.service;
@@ -161,6 +166,7 @@
             virtualization_service,
             instance_image,
             &self.idsig,
+            &self.idsig_manifest_apk,
             &self.vm_parameters,
         )
         .context("Starting VM")?;
diff --git a/compos/verify_key/verify_key.rs b/compos/verify_key/verify_key.rs
index a028264..13d3c8b 100644
--- a/compos/verify_key/verify_key.rs
+++ b/compos/verify_key/verify_key.rs
@@ -21,8 +21,9 @@
 use compos_aidl_interface::binder::ProcessState;
 use compos_common::compos_client::{VmInstance, VmParameters};
 use compos_common::{
-    COMPOS_DATA_ROOT, CURRENT_INSTANCE_DIR, IDSIG_FILE, INSTANCE_IMAGE_FILE, PENDING_INSTANCE_DIR,
-    PRIVATE_KEY_BLOB_FILE, PUBLIC_KEY_FILE, TEST_INSTANCE_DIR,
+    COMPOS_DATA_ROOT, CURRENT_INSTANCE_DIR, IDSIG_FILE, IDSIG_MANIFEST_APK_FILE,
+    INSTANCE_IMAGE_FILE, PENDING_INSTANCE_DIR, PRIVATE_KEY_BLOB_FILE, PUBLIC_KEY_FILE,
+    TEST_INSTANCE_DIR,
 };
 use std::fs::{self, File};
 use std::io::Read;
@@ -100,6 +101,7 @@
     let public_key = instance_dir.join(PUBLIC_KEY_FILE);
     let instance_image = instance_dir.join(INSTANCE_IMAGE_FILE);
     let idsig = instance_dir.join(IDSIG_FILE);
+    let idsig_manifest_apk = instance_dir.join(IDSIG_MANIFEST_APK_FILE);
 
     let blob = read_small_file(blob).context("Failed to read key blob")?;
     let public_key = read_small_file(public_key).context("Failed to read public key")?;
@@ -110,6 +112,7 @@
         &*virtualization_service,
         instance_image,
         &idsig,
+        &idsig_manifest_apk,
         &VmParameters { debug_mode, ..Default::default() },
     )?;
     let service = vm_instance.get_service()?;
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 3eaf124..6c96cbf 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -221,7 +221,6 @@
 
 bootimg {
     name: "microdroid_boot-5.10",
-    ramdisk_module: "microdroid_ramdisk-5.10",
     // We don't have kernel for arm and x86. But Soong demands one when it builds for
     // arm or x86 target. Satisfy that by providing an empty file as the kernel.
     kernel_prebuilt: "empty_kernel",
@@ -251,6 +250,16 @@
     avb_private_key: ":microdroid_sign_key",
 }
 
+bootimg {
+    name: "microdroid_init_boot",
+    ramdisk_module: "microdroid_ramdisk-5.10",
+    kernel_prebuilt: "empty_kernel",
+    header_version: "4",
+    partition_name: "init_boot",
+    use_avb: true,
+    avb_private_key: ":microdroid_sign_key",
+}
+
 android_filesystem {
     name: "microdroid_ramdisk-5.10",
     deps: [
@@ -551,6 +560,7 @@
         "microdroid_vendor_boot-5.10",
         "microdroid",
         "microdroid_boot-5.10",
+        "microdroid_init_boot",
     ],
 }
 
diff --git a/microdroid/microdroid.json b/microdroid/microdroid.json
index 8496052..9e630f8 100644
--- a/microdroid/microdroid.json
+++ b/microdroid/microdroid.json
@@ -8,6 +8,10 @@
           "path": "/apex/com.android.virt/etc/fs/microdroid_boot-5.10.img"
         },
         {
+          "label": "init_boot_a",
+          "path": "/apex/com.android.virt/etc/fs/microdroid_init_boot.img"
+        },
+        {
           "label": "vendor_boot_a",
           "path": "/apex/com.android.virt/etc/fs/microdroid_vendor_boot-5.10.img"
         },