Merge "build/debian: Remove x86_64 boot workarounds" into main
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index 1a263bd..e98ab5c 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -303,6 +303,34 @@
         Ok(())
     }
 
+    fn setEncryptedStorageSize(
+        &self,
+        image_fd: &ParcelFileDescriptor,
+        size: i64,
+    ) -> binder::Result<()> {
+        check_manage_access()?;
+
+        let size = size
+            .try_into()
+            .with_context(|| format!("Invalid size: {}", size))
+            .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT)?;
+        let size = round_up(size, PARTITION_GRANULARITY_BYTES);
+
+        let image = clone_file(image_fd)?;
+        let image_size = image.metadata().unwrap().len();
+
+        if image_size > size {
+            return Err(Status::new_exception_str(
+                ExceptionCode::ILLEGAL_ARGUMENT,
+                Some("Can't shrink encrypted storage"),
+            ));
+        }
+        // Reset the file length. In most filesystems, this will not allocate any physical disk
+        // space, it will only change the logical size.
+        image.set_len(size).context("Failed to extend file").or_service_specific_exception(-1)?;
+        Ok(())
+    }
+
     /// Creates or update the idsig file by digesting the input APK file.
     fn createOrUpdateIdsigFile(
         &self,
@@ -2210,6 +2238,10 @@
     fn requestAttestation(&self, csr: &[u8], test_mode: bool) -> binder::Result<Vec<Certificate>> {
         GLOBAL_SERVICE.requestAttestation(csr, get_calling_uid() as i32, test_mode)
     }
+
+    fn claimSecretkeeperEntry(&self, id: &[u8; 64]) -> binder::Result<()> {
+        GLOBAL_SERVICE.claimSecretkeeperEntry(id)
+    }
 }
 
 fn is_secretkeeper_supported() -> bool {
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
index 169c3dc..37222ba 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
@@ -58,6 +58,13 @@
             in ParcelFileDescriptor imageFd, long sizeBytes, PartitionType type);
 
     /**
+     * Set the encrypted storage size.
+     *
+     * The file must be open with both read and write permissions.
+     */
+    void setEncryptedStorageSize(in ParcelFileDescriptor imageFd, long size);
+
+    /**
      * Create or update an idsig file that digests the given APK file. The idsig file follows the
      * idsig format that is defined by the APK Signature Scheme V4. The idsig file is not updated
      * when it is up to date with the input file, which is checked by comparing the
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
index 0da7755..4f549cb 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
@@ -134,4 +134,10 @@
      * @param file descriptor of the TAP network interface.
      */
     void deleteTapInterface(in ParcelFileDescriptor tapFd);
+
+    /**
+     * Account the caller for the corresponding Secretkeeper entry.
+     * @param id Identifier for the secret held in Secretkeeper for the caller
+     */
+    void claimSecretkeeperEntry(in byte[64] id);
 }
diff --git a/android/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl b/android/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
index 662c8f1..7fe11e9 100644
--- a/android/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualmachineservice/IVirtualMachineService.aidl
@@ -63,4 +63,10 @@
      * that Secretkeeper is supported from Linux device tree before calling this.
      */
     ISecretkeeper getSecretkeeper();
+
+    /**
+     * Account the caller for the corresponding Secretkeeper entry.
+     * @param id Identifier for the secret held in Secretkeeper for the caller
+     */
+    void claimSecretkeeperEntry(in byte[64] id);
 }
diff --git a/android/virtualizationservice/src/aidl.rs b/android/virtualizationservice/src/aidl.rs
index f4e64e3..62cede8 100644
--- a/android/virtualizationservice/src/aidl.rs
+++ b/android/virtualizationservice/src/aidl.rs
@@ -196,6 +196,28 @@
 
         service
     }
+
+    // Attempt to update the sk_state maintenance database. Errors are ignored - calling app
+    // can not really do much to fix the errors & letting AVF VMs run irrespective of such internal
+    // error is acceptable.
+    fn try_updating_sk_state(&self, id: &[u8; 64]) {
+        let state = &mut *self.state.lock().unwrap();
+        if let Some(sk_state) = &mut state.sk_state {
+            let uid = get_calling_uid();
+            let user_id = multiuser_get_user_id(uid);
+            let app_id = multiuser_get_app_id(uid);
+            info!(
+                "Recording possible new owner of Secretkeeper entry={:?}:
+                 (user_id={user_id}, app_id={app_id},)",
+                hex::encode(id)
+            );
+            if let Err(e) = sk_state.add_id(id, user_id, app_id) {
+                error!("Failed to update the Secretkeeper entry owner: {e:?}");
+            }
+        } else {
+            info!("ignoring update of Secretkeeper entry as no ISecretkeeper");
+        }
+    }
 }
 
 impl Interface for VirtualizationServiceInternal {}
@@ -467,16 +489,7 @@
             .or_service_specific_exception(-1)?;
         let uid = get_calling_uid();
         info!("Allocated a VM's instance_id: {:?}..., for uid: {:?}", &hex::encode(id)[..8], uid);
-        let state = &mut *self.state.lock().unwrap();
-        if let Some(sk_state) = &mut state.sk_state {
-            let user_id = multiuser_get_user_id(uid);
-            let app_id = multiuser_get_app_id(uid);
-            info!("Recording possible existence of state for (user_id={user_id}, app_id={app_id})");
-            if let Err(e) = sk_state.add_id(&id, user_id, app_id) {
-                error!("Failed to record the instance_id: {e:?}");
-            }
-        }
-
+        self.try_updating_sk_state(&id);
         Ok(id)
     }
 
@@ -500,24 +513,8 @@
     }
 
     fn claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
-        let state = &mut *self.state.lock().unwrap();
-        if let Some(sk_state) = &mut state.sk_state {
-            let uid = get_calling_uid();
-            info!(
-                "Claiming a VM's instance_id: {:?}, for uid: {:?}",
-                hex::encode(instance_id),
-                uid
-            );
-
-            let user_id = multiuser_get_user_id(uid);
-            let app_id = multiuser_get_app_id(uid);
-            info!("Recording possible new owner of state for (user_id={user_id}, app_id={app_id})");
-            if let Err(e) = sk_state.add_id(instance_id, user_id, app_id) {
-                error!("Failed to update the instance_id owner: {e:?}");
-            }
-        } else {
-            info!("ignoring claimVmInstance() as no ISecretkeeper");
-        }
+        info!("Claiming a VM's instance_id: {:?}", hex::encode(instance_id));
+        self.try_updating_sk_state(instance_id);
         Ok(())
     }
 
@@ -559,6 +556,12 @@
 
         NETWORK_SERVICE.deleteTapInterface(tap_fd)
     }
+
+    fn claimSecretkeeperEntry(&self, id: &[u8; 64]) -> binder::Result<()> {
+        info!("Claiming Secretkeeper entry: {:?}", hex::encode(id));
+        self.try_updating_sk_state(id);
+        Ok(())
+    }
 }
 
 impl IVirtualizationMaintenance for VirtualizationServiceInternal {
diff --git a/android/vm/src/run.rs b/android/vm/src/run.rs
index a362b8e..8385fb4 100644
--- a/android/vm/src/run.rs
+++ b/android/vm/src/run.rs
@@ -35,6 +35,7 @@
 use rand::{distributions::Alphanumeric, Rng};
 use std::fs;
 use std::fs::File;
+use std::fs::OpenOptions;
 use std::io;
 use std::io::{Read, Write};
 use std::os::fd::AsFd;
@@ -112,6 +113,8 @@
                 config.microdroid.storage_size.unwrap_or(10 * 1024 * 1024),
                 PartitionType::ENCRYPTEDSTORE,
             )?;
+        } else if let Some(storage_size) = config.microdroid.storage_size {
+            set_encrypted_storage(service.as_ref(), path, storage_size)?;
         }
         Some(open_parcel_file(path, true)?)
     } else {
@@ -370,6 +373,22 @@
     Ok(config.extra_apks.into_iter().map(|x| x.path.into()).collect())
 }
 
+fn set_encrypted_storage(
+    service: &dyn IVirtualizationService,
+    image_path: &Path,
+    size: u64,
+) -> Result<(), Error> {
+    let image = OpenOptions::new()
+        .create_new(false)
+        .read(true)
+        .write(true)
+        .open(image_path)
+        .with_context(|| format!("Failed to open {:?}", image_path))?;
+
+    service.setEncryptedStorageSize(&ParcelFileDescriptor::new(image), size.try_into()?)?;
+    Ok(())
+}
+
 struct Callback {}
 
 impl vmclient::VmCallback for Callback {
diff --git a/build/microdroid/Android.bp b/build/microdroid/Android.bp
index 059077a..10b492b 100644
--- a/build/microdroid/Android.bp
+++ b/build/microdroid/Android.bp
@@ -82,7 +82,9 @@
         "microdroid_file_contexts",
         "microdroid_manifest",
         "microdroid_property_contexts",
+        "e2fsck.microdroid",
         "mke2fs.microdroid",
+        "resize2fs.microdroid",
         "microdroid_fstab",
 
         "libvm_payload", // used by payload to interact with microdroid manager
diff --git a/guest/apkdmverity/Android.bp b/guest/apkdmverity/Android.bp
index 3f45bb4..6e928f6 100644
--- a/guest/apkdmverity/Android.bp
+++ b/guest/apkdmverity/Android.bp
@@ -41,7 +41,6 @@
     name: "apkdmverity.test",
     defaults: [
         "apkdmverity.defaults",
-        "rdroidtest.defaults",
     ],
     test_suites: ["general-tests"],
     compile_multilib: "first",
diff --git a/guest/apkdmverity/src/main.rs b/guest/apkdmverity/src/main.rs
index 2fc964b..167f5d4 100644
--- a/guest/apkdmverity/src/main.rs
+++ b/guest/apkdmverity/src/main.rs
@@ -160,12 +160,8 @@
 }
 
 #[cfg(test)]
-rdroidtest::test_main!();
-
-#[cfg(test)]
 mod tests {
     use crate::*;
-    use rdroidtest::{ignore_if, rdroidtest};
     use std::fs::{File, OpenOptions};
     use std::io::Write;
     use std::ops::Deref;
@@ -236,9 +232,11 @@
         });
     }
 
-    #[rdroidtest]
-    #[ignore_if(should_skip())]
+    #[test]
     fn correct_inputs() {
+        if should_skip() {
+            return;
+        }
         let apk = include_bytes!("../testdata/test.apk");
         let idsig = include_bytes!("../testdata/test.apk.idsig");
         run_test(apk.as_ref(), idsig.as_ref(), "correct", |ctx| {
@@ -250,9 +248,11 @@
     }
 
     // A single byte change in the APK file causes an IO error
-    #[rdroidtest]
-    #[ignore_if(should_skip())]
+    #[test]
     fn incorrect_apk() {
+        if should_skip() {
+            return;
+        }
         let apk = include_bytes!("../testdata/test.apk");
         let idsig = include_bytes!("../testdata/test.apk.idsig");
 
@@ -268,9 +268,11 @@
     }
 
     // A single byte change in the merkle tree also causes an IO error
-    #[rdroidtest]
-    #[ignore_if(should_skip())]
+    #[test]
     fn incorrect_merkle_tree() {
+        if should_skip() {
+            return;
+        }
         let apk = include_bytes!("../testdata/test.apk");
         let idsig = include_bytes!("../testdata/test.apk.idsig");
 
@@ -293,9 +295,11 @@
     // APK is not altered when the verity device is created, but later modified. IO error should
     // occur when trying to read the data around the modified location. This is the main scenario
     // that we'd like to protect.
-    #[rdroidtest]
-    #[ignore_if(should_skip())]
+    #[test]
     fn tampered_apk() {
+        if should_skip() {
+            return;
+        }
         let apk = include_bytes!("../testdata/test.apk");
         let idsig = include_bytes!("../testdata/test.apk.idsig");
 
@@ -315,9 +319,11 @@
 
     // idsig file is not alread when the verity device is created, but later modified. Unlike to
     // the APK case, this doesn't occur IO error because the merkle tree is already cached.
-    #[rdroidtest]
-    #[ignore_if(should_skip())]
+    #[test]
     fn tampered_idsig() {
+        if should_skip() {
+            return;
+        }
         let apk = include_bytes!("../testdata/test.apk");
         let idsig = include_bytes!("../testdata/test.apk.idsig");
         run_test(apk.as_ref(), idsig.as_ref(), "tampered_idsig", |ctx| {
@@ -333,9 +339,11 @@
     }
 
     // test if both files are already block devices
-    #[rdroidtest]
-    #[ignore_if(should_skip())]
+    #[test]
     fn inputs_are_block_devices() {
+        if should_skip() {
+            return;
+        }
         let apk = include_bytes!("../testdata/test.apk");
         let idsig = include_bytes!("../testdata/test.apk.idsig");
 
@@ -383,9 +391,11 @@
     }
 
     // test with custom roothash
-    #[rdroidtest]
-    #[ignore_if(should_skip())]
+    #[test]
     fn correct_custom_roothash() {
+        if should_skip() {
+            return;
+        }
         let apk = include_bytes!("../testdata/test.apk");
         let idsig = include_bytes!("../testdata/test.apk.idsig");
         let roothash = V4Signature::from_idsig_path("testdata/test.apk.idsig")
@@ -406,7 +416,7 @@
         );
     }
 
-    #[rdroidtest]
+    #[test]
     fn verify_command() {
         // Check that the command parsing has been configured in a valid way.
         clap_command().debug_assert();
diff --git a/guest/encryptedstore/src/main.rs b/guest/encryptedstore/src/main.rs
index dd4ee3b..8647003 100644
--- a/guest/encryptedstore/src/main.rs
+++ b/guest/encryptedstore/src/main.rs
@@ -30,7 +30,9 @@
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+const E2FSCK_BIN: &str = "/system/bin/e2fsck";
 const MK2FS_BIN: &str = "/system/bin/mke2fs";
+const RESIZE2FS_BIN: &str = "/system/bin/resize2fs";
 const UNFORMATTED_STORAGE_MAGIC: &str = "UNFORMATTED-STORAGE";
 
 fn main() {
@@ -91,6 +93,8 @@
     if needs_formatting {
         info!("Freshly formatting the crypt device");
         format_ext4(&crypt_device)?;
+    } else {
+        resize_fs(&crypt_device)?;
     }
     mount(&crypt_device, mountpoint)
         .with_context(|| format!("Unable to mount {:?}", crypt_device))?;
@@ -174,6 +178,27 @@
     Ok(())
 }
 
+fn resize_fs(device: &Path) -> Result<()> {
+    // Check the partition
+    Command::new(E2FSCK_BIN)
+        .arg("-fvy")
+        .arg(device)
+        .status()
+        .context("failed to execute e2fsck")?;
+
+    // Resize the filesystem to the size of the device.
+    Command::new(RESIZE2FS_BIN).arg(device).status().context("failed to execute resize2fs")?;
+
+    // Finally check again if we were successful.
+    Command::new(E2FSCK_BIN)
+        .arg("-fvy")
+        .arg(device)
+        .status()
+        .context("failed to execute e2fsck")?;
+
+    Ok(())
+}
+
 fn mount(source: &Path, mountpoint: &Path) -> Result<()> {
     create_dir_all(mountpoint).with_context(|| format!("Failed to create {:?}", &mountpoint))?;
     let mount_options = CString::new(
diff --git a/guest/microdroid_manager/src/main.rs b/guest/microdroid_manager/src/main.rs
index 57ad35d..d665c87 100644
--- a/guest/microdroid_manager/src/main.rs
+++ b/guest/microdroid_manager/src/main.rs
@@ -368,14 +368,6 @@
         umount2("/microdroid_resources", MntFlags::MNT_DETACH)?;
     }
 
-    // Run encryptedstore binary to prepare the storage
-    let encryptedstore_child = if Path::new(ENCRYPTEDSTORE_BACKING_DEVICE).exists() {
-        info!("Preparing encryptedstore ...");
-        Some(prepare_encryptedstore(&vm_secret).context("encryptedstore run")?)
-    } else {
-        None
-    };
-
     let mut zipfuse = Zipfuse::default();
 
     // Before reading a file from the APK, start zipfuse
@@ -410,6 +402,19 @@
     );
     mount_extra_apks(&config, &mut zipfuse)?;
 
+    // Wait until apex config is done. (e.g. linker configuration for apexes)
+    wait_for_property_true(APEX_CONFIG_DONE_PROP).context("Failed waiting for apex config done")?;
+
+    // Run encryptedstore binary to prepare the storage
+    // Postpone initialization until apex mount completes to ensure e2fsck and resize2fs binaries
+    // are accessible.
+    let encryptedstore_child = if Path::new(ENCRYPTEDSTORE_BACKING_DEVICE).exists() {
+        info!("Preparing encryptedstore ...");
+        Some(prepare_encryptedstore(&vm_secret).context("encryptedstore run")?)
+    } else {
+        None
+    };
+
     register_vm_payload_service(
         allow_restricted_apis,
         service.clone(),
@@ -425,9 +430,6 @@
             .context("set microdroid_manager.export_tombstones.enabled")?;
     }
 
-    // Wait until apex config is done. (e.g. linker configuration for apexes)
-    wait_for_property_true(APEX_CONFIG_DONE_PROP).context("Failed waiting for apex config done")?;
-
     // Trigger init post-fs-data. This will start authfs if we wask it to.
     if config.enable_authfs {
         system_properties::write("microdroid_manager.authfs.enabled", "1")
diff --git a/guest/microdroid_manager/src/vm_secret.rs b/guest/microdroid_manager/src/vm_secret.rs
index 6331074..f031859 100644
--- a/guest/microdroid_manager/src/vm_secret.rs
+++ b/guest/microdroid_manager/src/vm_secret.rs
@@ -77,6 +77,7 @@
         dice_artifacts: OwnedDiceArtifactsWithExplicitKey,
         skp_secret: ZVec,
         secretkeeper_session: SkVmSession,
+        virtual_machine_service: Strong<dyn IVirtualMachineService>,
     },
     // V1 secrets are not protected against rollback of boot images.
     // They are reliable only if rollback of images was prevented by verified boot ie,
@@ -131,6 +132,7 @@
             dice_artifacts: explicit_dice,
             skp_secret: ZVec::try_from(skp_secret.to_vec())?,
             secretkeeper_session: session,
+            virtual_machine_service: vm_service.clone(),
         })
     }
 
@@ -180,10 +182,20 @@
 
     pub fn write_payload_data_rp(&self, data: &[u8; SECRET_SIZE]) -> Result<()> {
         let data = Zeroizing::new(*data);
-        let Self::V2 { instance_id, secretkeeper_session, .. } = self else {
+        let Self::V2 { instance_id, secretkeeper_session, virtual_machine_service, .. } = self
+        else {
             return Err(anyhow!("Rollback protected data is not available with V1 secrets"));
         };
         let payload_id = sha::sha512(instance_id);
+        // Claim the Secretkeeper entry - this pings AVF host to account this Secretkeeper entry
+        // correctly.
+        virtual_machine_service.claimSecretkeeperEntry(&payload_id).map_err(|e| {
+            // TODO rename this error!
+            super::MicrodroidError::FailedToConnectToVirtualizationService(format!(
+                "Failed to claim Secretkeeper entry: {e:?}"
+            ))
+        })?;
+
         if let Err(e) = secretkeeper_session.store_secret(payload_id, data.clone()) {
             log::info!("Secretkeeper store failed with {e:?}. Refreshing connection & retrying!");
             secretkeeper_session.refresh()?;
diff --git a/libs/devicemapper/Android.bp b/libs/devicemapper/Android.bp
index 6b7f680..8dc6c8d 100644
--- a/libs/devicemapper/Android.bp
+++ b/libs/devicemapper/Android.bp
@@ -29,7 +29,6 @@
     name: "libdm_rust.test",
     defaults: [
         "libdm_rust.defaults",
-        "rdroidtest.defaults",
     ],
     test_suites: ["general-tests"],
     rustlibs: [
diff --git a/libs/devicemapper/src/lib.rs b/libs/devicemapper/src/lib.rs
index a8c2833..bc8a762 100644
--- a/libs/devicemapper/src/lib.rs
+++ b/libs/devicemapper/src/lib.rs
@@ -230,14 +230,10 @@
 }
 
 #[cfg(test)]
-rdroidtest::test_main!();
-
-#[cfg(test)]
 mod tests {
     use super::*;
     use crate::loopdevice::LoopConfigOptions;
     use crypt::{CipherType, DmCryptTargetBuilder};
-    use rdroidtest::{ignore_if, rdroidtest};
     use rustutils::system_properties;
     use std::fs::{read, File, OpenOptions};
     use std::io::Write;
@@ -294,25 +290,29 @@
         }
     }
 
-    #[rdroidtest]
+    #[test]
     fn mapping_again_keeps_data_xts() {
         mapping_again_keeps_data(&KEY_SET_XTS, "name1");
     }
 
-    #[rdroidtest]
-    #[ignore_if(!is_hctr2_supported())]
+    #[test]
     fn mapping_again_keeps_data_hctr2() {
+        if !is_hctr2_supported() {
+            return;
+        }
         mapping_again_keeps_data(&KEY_SET_HCTR2, "name2");
     }
 
-    #[rdroidtest]
+    #[test]
     fn data_inaccessible_with_diff_key_xts() {
         data_inaccessible_with_diff_key(&KEY_SET_XTS, "name3");
     }
 
-    #[rdroidtest]
-    #[ignore_if(!is_hctr2_supported())]
+    #[test]
     fn data_inaccessible_with_diff_key_hctr2() {
+        if !is_hctr2_supported() {
+            return;
+        }
         data_inaccessible_with_diff_key(&KEY_SET_HCTR2, "name4");
     }
 
diff --git a/libs/devicemapper/src/loopdevice.rs b/libs/devicemapper/src/loopdevice.rs
index b830eda..e41b90c 100644
--- a/libs/devicemapper/src/loopdevice.rs
+++ b/libs/devicemapper/src/loopdevice.rs
@@ -179,7 +179,6 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use rdroidtest::rdroidtest;
     use std::fs;
     use std::path::Path;
 
@@ -199,7 +198,13 @@
         "0" == fs::read_to_string(ro).unwrap().trim()
     }
 
-    #[rdroidtest]
+    fn is_autoclear(dev: &Path) -> bool {
+        let autoclear =
+            Path::new("/sys/block").join(dev.file_name().unwrap()).join("loop/autoclear");
+        "1" == fs::read_to_string(autoclear).unwrap().trim()
+    }
+
+    #[test]
     fn attach_loop_device_with_dio() {
         let a_dir = tempfile::TempDir::new().unwrap();
         let a_file = a_dir.path().join("test");
@@ -215,7 +220,7 @@
         assert!(is_direct_io(&dev));
     }
 
-    #[rdroidtest]
+    #[test]
     fn attach_loop_device_without_dio() {
         let a_dir = tempfile::TempDir::new().unwrap();
         let a_file = a_dir.path().join("test");
@@ -228,7 +233,7 @@
         assert!(!is_direct_io(&dev));
     }
 
-    #[rdroidtest]
+    #[test]
     fn attach_loop_device_with_dio_writable() {
         let a_dir = tempfile::TempDir::new().unwrap();
         let a_file = a_dir.path().join("test");
@@ -249,7 +254,7 @@
         assert!(is_direct_io_writable(&dev));
     }
 
-    #[rdroidtest]
+    #[test]
     fn attach_loop_device_autoclear() {
         let a_dir = tempfile::TempDir::new().unwrap();
         let a_file = a_dir.path().join("test");
@@ -258,10 +263,7 @@
         let dev =
             attach(a_file, 0, a_size, &LoopConfigOptions { autoclear: true, ..Default::default() })
                 .unwrap();
-        drop(dev.file);
 
-        let dev_size_path =
-            Path::new("/sys/block").join(dev.path.file_name().unwrap()).join("size");
-        assert_eq!("0", fs::read_to_string(dev_size_path).unwrap().trim());
+        assert!(is_autoclear(&dev.path));
     }
 }
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
index af313a1..0445fcb 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
@@ -1563,6 +1563,12 @@
                                 ? createVirtualMachineConfigForRawFrom(vmConfig)
                                 : createVirtualMachineConfigForAppFrom(vmConfig, service);
 
+                if (vmConfig.isEncryptedStorageEnabled()) {
+                    service.setEncryptedStorageSize(
+                        ParcelFileDescriptor.open(mEncryptedStoreFilePath, MODE_READ_WRITE),
+                        vmConfig.getEncryptedStorageBytes());
+                }
+
                 mVirtualMachine =
                         service.createVm(
                                 vmConfigParcel, consoleOutFd, consoleInFd, mLogWriter, null);
@@ -1918,6 +1924,8 @@
      * <p>The new config must be {@linkplain VirtualMachineConfig#isCompatibleWith compatible with}
      * the existing config.
      *
+     * <p>NOTE: Modification of the encrypted storage size is restricted to expansion only and is an
+     * irreversible operation.
      * <p>NOTE: This method may block and should not be called on the main thread.
      *
      * @return the old config
@@ -1932,7 +1940,9 @@
             throws VirtualMachineException {
         synchronized (mLock) {
             VirtualMachineConfig oldConfig = mConfig;
-            if (!oldConfig.isCompatibleWith(newConfig)) {
+            if (!oldConfig.isCompatibleWith(newConfig)
+                    || oldConfig.getEncryptedStorageBytes()
+                            > newConfig.getEncryptedStorageBytes()) {
                 throw new VirtualMachineException("incompatible config");
             }
             checkStopped();
@@ -1948,8 +1958,43 @@
         }
     }
 
-    @Nullable
-    private static native IBinder nativeConnectToVsockServer(IBinder vmBinder, int port);
+    /**
+     * Abstracts away the task of creating a vsock connection. Normally, in the same process, you'll
+     * make the connection and then promote it to a binder as part of the same API call, but if you
+     * want to pass a connection to another process first, before establishing the RPC binder
+     * connection, you may implement this method by getting a vsock connection from another process.
+     *
+     * <p>It is recommended to convert other types of exceptions (e.g. remote exceptions) to
+     * VirtualMachineException, so that all connection failures will be visible under the same type
+     * of exception.
+     *
+     * @hide
+     */
+    public interface VsockConnectionProvider {
+        @NonNull
+        public ParcelFileDescriptor addConnection() throws VirtualMachineException;
+    }
+
+    /**
+     * Class to make it easy to use JNI, without needing PFD and other classes.
+     *
+     * @hide
+     */
+    private static class NativeProviderWrapper {
+        private VsockConnectionProvider mProvider = null;
+
+        // ensures last FD is owned until get is called again
+        private ParcelFileDescriptor mMoreLifetime = null;
+
+        public NativeProviderWrapper(VsockConnectionProvider provider) {
+            mProvider = provider;
+        }
+
+        int connect() throws VirtualMachineException {
+            mMoreLifetime = mProvider.addConnection();
+            return mMoreLifetime.getFileDescriptor().getInt$();
+        }
+    }
 
     /**
      * Connect to a VM's binder service via vsock and return the root IBinder object. Guest VMs are
@@ -1969,15 +2014,36 @@
     public IBinder connectToVsockServer(
             @IntRange(from = MIN_VSOCK_PORT, to = MAX_VSOCK_PORT) long port)
             throws VirtualMachineException {
+        VsockConnectionProvider provider =
+                new VsockConnectionProvider() {
+                    @Override
+                    public ParcelFileDescriptor addConnection() throws VirtualMachineException {
+                        return connectVsock(port);
+                    }
+                };
+        return binderFromPreconnectedClient(provider);
+    }
 
-        synchronized (mLock) {
-            IBinder iBinder =
-                    nativeConnectToVsockServer(getRunningVm().asBinder(), validatePort(port));
-            if (iBinder == null) {
-                throw new VirtualMachineException("Failed to connect to vsock server");
-            }
-            return iBinder;
+    @Nullable
+    private static native IBinder nativeBinderFromPreconnectedClient(
+            NativeProviderWrapper provider);
+
+    /**
+     * Convert existing vsock connection to a binder connection.
+     *
+     * <p>connectToVsockServer = connectToVsock + binderFromPreconnectedClient
+     *
+     * @hide
+     */
+    @WorkerThread
+    @NonNull
+    public static IBinder binderFromPreconnectedClient(@NonNull VsockConnectionProvider provider)
+            throws VirtualMachineException {
+        IBinder binder = nativeBinderFromPreconnectedClient(new NativeProviderWrapper(provider));
+        if (binder == null) {
+            throw new VirtualMachineException("Failed to connect to vsock server");
         }
+        return binder;
     }
 
     /**
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
index 2668ca2..ff1f5bf 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -635,7 +635,6 @@
         }
         return this.mDebugLevel == other.mDebugLevel
                 && this.mProtectedVm == other.mProtectedVm
-                && this.mEncryptedStorageBytes == other.mEncryptedStorageBytes
                 && this.mVmOutputCaptured == other.mVmOutputCaptured
                 && this.mVmConsoleInputSupported == other.mVmConsoleInputSupported
                 && this.mConnectVmConsole == other.mConnectVmConsole
diff --git a/libs/libvirtualization_jni/android_system_virtualmachine_VirtualMachine.cpp b/libs/libvirtualization_jni/android_system_virtualmachine_VirtualMachine.cpp
index 3f1d8a0..67a4716 100644
--- a/libs/libvirtualization_jni/android_system_virtualmachine_VirtualMachine.cpp
+++ b/libs/libvirtualization_jni/android_system_virtualmachine_VirtualMachine.cpp
@@ -48,32 +48,30 @@
 } // namespace
 
 extern "C" JNIEXPORT jobject JNICALL
-Java_android_system_virtualmachine_VirtualMachine_nativeConnectToVsockServer(
-        JNIEnv *env, [[maybe_unused]] jclass clazz, jobject vmBinder, jint port) {
-    using aidl::android::system::virtualizationservice::IVirtualMachine;
-    using ndk::ScopedFileDescriptor;
-    using ndk::SpAIBinder;
+Java_android_system_virtualmachine_VirtualMachine_nativeBinderFromPreconnectedClient(
+        [[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass clazz, jobject provider) {
+    ScopedLocalRef<jclass> callback_class(env, env->GetObjectClass(provider));
+    jmethodID mid = env->GetMethodID(callback_class.get(), "connect", "()I");
+    LOG_ALWAYS_FATAL_IF(mid == nullptr, "Could not find method");
 
-    auto vm = IVirtualMachine::fromBinder(SpAIBinder{AIBinder_fromJavaBinder(env, vmBinder)});
+    // TODO(b/398890208): make this memory owned by the connection
+    struct State {
+        JNIEnv *mEnv;
+        jobject mProvider;
+        jmethodID mMid;
+    } state;
 
-    std::tuple args{env, vm.get(), port};
-    using Args = decltype(args);
+    state.mEnv = env;
+    state.mProvider = provider;
+    state.mMid = mid;
 
-    auto requestFunc = [](void *param) {
-        auto [env, vm, port] = *static_cast<Args *>(param);
-
-        ScopedFileDescriptor fd;
-        if (auto status = vm->connectVsock(port, &fd); !status.isOk()) {
-            env->ThrowNew(env->FindClass("android/system/virtualmachine/VirtualMachineException"),
-                          ("Failed to connect vsock: " + status.getDescription()).c_str());
-            return -1;
-        }
-
-        // take ownership
-        int ret = fd.get();
-        *fd.getR() = -1;
-
-        return ret;
+    using RequestFun = int (*)(void *);
+    RequestFun requestFunc = [](void *param) -> int {
+        State *state = reinterpret_cast<State *>(param);
+        int ownedFd = state->mEnv->CallIntMethod(state->mProvider, state->mMid);
+        // FD is owned by PFD in Java layer, need to dupe it so that
+        // ARpcSession_setupPreconnectedClient can take ownership when it calls unique_fd internally
+        return fcntl(ownedFd, F_DUPFD_CLOEXEC, 0);
     };
 
     RpcSessionHandle session;
@@ -82,7 +80,7 @@
     // want too many. The number 1 is chosen after some discussion, and to match
     // the server-side default (mMaxThreads on RpcServer).
     ARpcSession_setMaxIncomingThreads(session.get(), 1);
-    auto client = ARpcSession_setupPreconnectedClient(session.get(), requestFunc, &args);
+    auto client = ARpcSession_setupPreconnectedClient(session.get(), requestFunc, &state);
     return AIBinder_toJavaBinder(env, client);
 }
 
diff --git a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
index 4c824f0..5d92976 100644
--- a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
+++ b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
@@ -47,6 +47,9 @@
     /* get the encrypted storage path. */
     String getEncryptedStoragePath();
 
+    /* get the size of the encrypted storage in bytes. */
+    long getEncryptedStorageSize();
+
     /* start a simple vsock server on ECHO_REVERSE_PORT that reads a line at a time and echoes
      * each line reverse.
      */
diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
index 18ed7b6..4294df4 100644
--- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
+++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
@@ -641,6 +641,7 @@
         public String mExtraApkTestProp;
         public String mApkContentsPath;
         public String mEncryptedStoragePath;
+        public long mEncryptedStorageSize;
         public String[] mEffectiveCapabilities;
         public int mUid;
         public String mFileContent;
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 639224d..418a88e 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -129,6 +129,7 @@
     private static final String TEST_APP_PACKAGE_NAME = "com.android.microdroid.test";
     private static final String VM_ATTESTATION_PAYLOAD_PATH = "libvm_attestation_test_payload.so";
     private static final String VM_ATTESTATION_MESSAGE = "Hello RKP from AVF!";
+    private static final long TOLERANCE_BYTES = 400_000;
     private static final int ENCRYPTED_STORAGE_BYTES = 4_000_000;
 
     private static final String RELAXED_ROLLBACK_PROTECTION_SCHEME_TEST_PACKAGE_NAME =
@@ -741,11 +742,6 @@
         // so in the API spec.
         assertConfigCompatible(baseline, newBaselineBuilder().setApkPath("/different")).isTrue();
 
-        // Changes that are currently incompatible for ease of implementation, but this might change
-        // in the future.
-        assertConfigCompatible(baseline, newBaselineBuilder().setEncryptedStorageBytes(100_000))
-                .isFalse();
-
         VirtualMachineConfig.Builder debuggableBuilder =
                 newBaselineBuilder().setDebugLevel(DEBUG_LEVEL_FULL);
         VirtualMachineConfig debuggable = debuggableBuilder.build();
@@ -1866,6 +1862,169 @@
         assertThat(testResults.mFileContent).isEqualTo(EXAMPLE_STRING);
     }
 
+    @Test
+    @CddTest
+    public void encryptedStorageSupportsExpansion() throws Exception {
+        assumeSupportedDevice();
+
+        VirtualMachineConfig config =
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                        .setEncryptedStorageBytes(ENCRYPTED_STORAGE_BYTES)
+                        .build();
+
+        VirtualMachine vm = forceCreateNewVirtualMachine("test_vm", config);
+        TestResults testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mEncryptedStorageSize = ts.getEncryptedStorageSize();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mEncryptedStorageSize)
+            .isWithin(TOLERANCE_BYTES)
+            .of(ENCRYPTED_STORAGE_BYTES);
+
+        // Re-run the VM with more storage size & verify the file persisted.
+        // Note, the previous `runVmTestService` stopped the VM
+        config = newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                    .setEncryptedStorageBytes(ENCRYPTED_STORAGE_BYTES * 2)
+                    .build();
+        vm.setConfig(config);
+        assertThat(vm.getConfig().getEncryptedStorageBytes())
+            .isEqualTo(ENCRYPTED_STORAGE_BYTES * 2);
+
+        testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mEncryptedStorageSize = ts.getEncryptedStorageSize();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mEncryptedStorageSize)
+            .isWithin(TOLERANCE_BYTES)
+            .of(ENCRYPTED_STORAGE_BYTES * 2);
+    }
+
+    @Test
+    @CddTest
+    public void encryptedStorageExpansionIsPersistent() throws Exception {
+        assumeSupportedDevice();
+
+        VirtualMachineConfig config =
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                        .setEncryptedStorageBytes(ENCRYPTED_STORAGE_BYTES)
+                        .build();
+
+        VirtualMachine vm = forceCreateNewVirtualMachine("test_vm", config);
+        TestResults testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            ts.writeToFile(
+                                    /* content= */ EXAMPLE_STRING,
+                                    /* path= */ "/mnt/encryptedstore/test_file");
+                        });
+        testResults.assertNoException();
+
+        // Re-run the VM with more storage size & verify the file persisted.
+        // Note, the previous `runVmTestService` stopped the VM
+        config = newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                    .setEncryptedStorageBytes(ENCRYPTED_STORAGE_BYTES * 2)
+                    .build();
+        vm.setConfig(config);
+
+        testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mFileContent = ts.readFromFile("/mnt/encryptedstore/test_file");
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mFileContent).isEqualTo(EXAMPLE_STRING);
+    }
+
+    @Test
+    @CddTest
+    public void encryptedStorageSizeUnchanged() throws Exception {
+        assumeSupportedDevice();
+
+        VirtualMachineConfig config =
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                        .setEncryptedStorageBytes(ENCRYPTED_STORAGE_BYTES)
+                        .build();
+
+        VirtualMachine vm = forceCreateNewVirtualMachine("test_vm", config);
+        TestResults testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mEncryptedStorageSize = ts.getEncryptedStorageSize();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mEncryptedStorageSize)
+            .isWithin(TOLERANCE_BYTES)
+            .of(ENCRYPTED_STORAGE_BYTES);
+
+        // Re-run the VM with more storage size & verify the file persisted.
+        // Note, the previous `runVmTestService` stopped the VM
+        config = newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                    .setEncryptedStorageBytes(ENCRYPTED_STORAGE_BYTES)
+                    .build();
+        vm.setConfig(config);
+        assertThat(vm.getConfig().getEncryptedStorageBytes())
+            .isEqualTo(ENCRYPTED_STORAGE_BYTES);
+
+        testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mEncryptedStorageSize = ts.getEncryptedStorageSize();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mEncryptedStorageSize)
+            .isWithin(TOLERANCE_BYTES)
+            .of(ENCRYPTED_STORAGE_BYTES);
+    }
+
+    @Test
+    @CddTest
+    public void encryptedStorageShrinkFails() throws Exception {
+        assumeSupportedDevice();
+
+        VirtualMachineConfig config =
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                        .setEncryptedStorageBytes(ENCRYPTED_STORAGE_BYTES)
+                        .build();
+
+        VirtualMachine vm = forceCreateNewVirtualMachine("test_vm", config);
+        TestResults testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mEncryptedStorageSize = ts.getEncryptedStorageSize();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mEncryptedStorageSize)
+            .isWithin(TOLERANCE_BYTES)
+            .of(ENCRYPTED_STORAGE_BYTES);
+
+        // Re-run the VM with more storage size & verify the file persisted.
+        // Note, the previous `runVmTestService` stopped the VM
+        VirtualMachineConfig newConfig =
+            newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                    .setEncryptedStorageBytes(ENCRYPTED_STORAGE_BYTES / 2)
+                    .build();
+        assertThrowsVmExceptionContaining(
+            () -> vm.setConfig(newConfig), "incompatible config");
+    }
+
     private boolean deviceCapableOfProtectedVm() {
         int capabilities = getVirtualMachineManager().getCapabilities();
         if ((capabilities & CAPABILITY_PROTECTED_VM) != 0) {
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index 355cfb1..13eafce 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -29,6 +29,7 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <sys/capability.h>
+#include <sys/statvfs.h>
 #include <sys/system_properties.h>
 #ifdef __MICRODROID_TEST_PAYLOAD_USES_LIBICU__
 #include <unicode/uchar.h>
@@ -232,6 +233,23 @@
             return ScopedAStatus::ok();
         }
 
+        ScopedAStatus getEncryptedStorageSize(int64_t *out) override {
+            const char* path_c = AVmPayload_getEncryptedStoragePath();
+            if (path_c == nullptr) {
+                *out = 0;
+                return ScopedAStatus::ok();
+            }
+            struct statvfs buffer;
+            if (statvfs(path_c, &buffer) != 0) {
+                std::string msg = "statvfs " + std::string(path_c) + " failed :  " +
+                    std::strerror(errno);
+                return ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
+                                                                   msg.c_str());
+            }
+            *out= buffer.f_blocks * buffer.f_frsize;
+            return ScopedAStatus::ok();
+        }
+
         ScopedAStatus getEffectiveCapabilities(std::vector<std::string>* out) override {
             if (out == nullptr) {
                 return ScopedAStatus::ok();
diff --git a/tests/testapk/src/native/testbinary.rs b/tests/testapk/src/native/testbinary.rs
index 3900cad..6a7d96e 100644
--- a/tests/testapk/src/native/testbinary.rs
+++ b/tests/testapk/src/native/testbinary.rs
@@ -87,6 +87,10 @@
 
     // Everything below here is unimplemented. Implementations may be added as needed.
 
+    fn getEncryptedStorageSize(&self) -> BinderResult<i64> {
+        unimplemented()
+    }
+
     fn readProperty(&self, _: &str) -> BinderResult<String> {
         unimplemented()
     }
diff --git a/tests/vm_accessor/test/Android.bp b/tests/vm_accessor/test/Android.bp
index 71746c7..16e9b1e 100644
--- a/tests/vm_accessor/test/Android.bp
+++ b/tests/vm_accessor/test/Android.bp
@@ -22,9 +22,6 @@
 rust_test {
     name: "vm_accessor_test",
     srcs: ["src/test.rs"],
-    defaults: [
-        "rdroidtest.defaults",
-    ],
     test_suites: [
         "general-tests",
     ],
diff --git a/tests/vm_accessor/test/src/test.rs b/tests/vm_accessor/test/src/test.rs
index d521acf..4d25fcd 100644
--- a/tests/vm_accessor/test/src/test.rs
+++ b/tests/vm_accessor/test/src/test.rs
@@ -18,7 +18,6 @@
 
 use com_android_virt_accessor_demo_vm_service::aidl::com::android::virt::accessor_demo::vm_service::IAccessorVmService::IAccessorVmService;
 use binder::{Strong, ProcessState};
-use rdroidtest::rdroidtest;
 
 const VM_SERVICE: &str = "com.android.virt.accessor_demo.vm_service.IAccessorVmService/default";
 
@@ -39,7 +38,7 @@
     binder::check_interface(VM_SERVICE).unwrap()
 }
 
-#[rdroidtest]
+#[test]
 fn test_wait_for_interface() {
     init();
 
@@ -49,7 +48,7 @@
     assert_eq!(sum, 23);
 }
 
-#[rdroidtest]
+#[test]
 fn test_wait_for_interface_twice() {
     init();
 
@@ -60,7 +59,7 @@
     assert_eq!(service2.add(11, 12).unwrap(), 23);
 }
 
-#[rdroidtest]
+#[test]
 fn test_wait_and_get_interface() {
     init();
 
@@ -71,7 +70,7 @@
     assert_eq!(service2.add(11, 12).unwrap(), 23);
 }
 
-#[rdroidtest]
+#[test]
 fn test_wait_and_check_interface() {
     init();
 
@@ -81,5 +80,3 @@
     assert_eq!(service1.add(11, 12).unwrap(), 23);
     assert_eq!(service2.add(11, 12).unwrap(), 23);
 }
-
-rdroidtest::test_main!();
diff --git a/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java b/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
index 7f44fa5..9489aed 100644
--- a/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
+++ b/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
@@ -223,6 +223,11 @@
         }
 
         @Override
+        public long getEncryptedStorageSize() throws RemoteException {
+            throw new UnsupportedOperationException("Not supported");
+        }
+
+        @Override
         public void runEchoReverseServer() throws RemoteException {
             throw new UnsupportedOperationException("Not supported");
         }