Merge "Check API version levels for backcompat tests" into main
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/Application.kt b/android/TerminalApp/java/com/android/virtualization/terminal/Application.kt
index efe651e..9f4909d 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/Application.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/Application.kt
@@ -18,12 +18,21 @@
 import android.app.Application as AndroidApplication
 import android.app.NotificationChannel
 import android.app.NotificationManager
+import android.content.ComponentName
 import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.os.IBinder
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.ProcessLifecycleOwner
 
 public class Application : AndroidApplication() {
     override fun onCreate() {
         super.onCreate()
         setupNotificationChannels()
+        val lifecycleObserver = ApplicationLifecycleObserver()
+        ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleObserver)
     }
 
     private fun setupNotificationChannels() {
@@ -52,4 +61,53 @@
 
         fun getInstance(c: Context): Application = c.getApplicationContext() as Application
     }
+
+    /**
+     * Observes application lifecycle events and interacts with the VmLauncherService to manage
+     * virtual machine state based on application lifecycle transitions. This class binds to the
+     * VmLauncherService and notifies it of application lifecycle events (onStart, onStop), allowing
+     * the service to manage the VM accordingly.
+     */
+    inner class ApplicationLifecycleObserver() : DefaultLifecycleObserver {
+        private var vmLauncherService: VmLauncherService? = null
+        private val connection =
+            object : ServiceConnection {
+                override fun onServiceConnected(className: ComponentName, service: IBinder) {
+                    val binder = service as VmLauncherService.VmLauncherServiceBinder
+                    vmLauncherService = binder.getService()
+                }
+
+                override fun onServiceDisconnected(arg0: ComponentName) {
+                    vmLauncherService = null
+                }
+            }
+
+        override fun onCreate(owner: LifecycleOwner) {
+            super.onCreate(owner)
+            bindToVmLauncherService()
+        }
+
+        override fun onStart(owner: LifecycleOwner) {
+            super.onStart(owner)
+            vmLauncherService?.processAppLifeCycleEvent(ApplicationLifeCycleEvent.APP_ON_START)
+        }
+
+        override fun onStop(owner: LifecycleOwner) {
+            vmLauncherService?.processAppLifeCycleEvent(ApplicationLifeCycleEvent.APP_ON_STOP)
+            super.onStop(owner)
+        }
+
+        override fun onDestroy(owner: LifecycleOwner) {
+            if (vmLauncherService != null) {
+                this@Application.unbindService(connection)
+                vmLauncherService = null
+            }
+            super.onDestroy(owner)
+        }
+
+        fun bindToVmLauncherService() {
+            val intent = Intent(this@Application, VmLauncherService::class.java)
+            this@Application.bindService(intent, connection, 0) // No BIND_AUTO_CREATE
+        }
+    }
 }
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/ApplicationLifeCycleEvent.kt b/android/TerminalApp/java/com/android/virtualization/terminal/ApplicationLifeCycleEvent.kt
new file mode 100644
index 0000000..4e26c3c
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/ApplicationLifeCycleEvent.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2025 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.
+ */
+package com.android.virtualization.terminal
+
+enum class ApplicationLifeCycleEvent {
+    APP_ON_START,
+    APP_ON_STOP,
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/ImageArchive.kt b/android/TerminalApp/java/com/android/virtualization/terminal/ImageArchive.kt
index 017ff89..be1f922 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/ImageArchive.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/ImageArchive.kt
@@ -65,6 +65,14 @@
         }
     }
 
+    /** Returns path to the archive. */
+    fun getPath(): String {
+        return when (source) {
+            is UrlSource -> source.value.toString()
+            is PathSource -> source.value.toString()
+        }
+    }
+
     /** Returns size of the archive in bytes */
     @Throws(IOException::class)
     fun getSize(): Long {
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt
index 7180e87..01c3880 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt
@@ -150,21 +150,26 @@
 
     private fun downloadFromSdcard(): Boolean {
         val archive = fromSdCard()
+        val archive_path = archive.getPath()
 
         // Installing from sdcard is preferred, but only supported only in debuggable build.
-        if (Build.isDebuggable() && archive.exists()) {
-            Log.i(TAG, "trying to install /sdcard/linux/images.tar.gz")
+        if (!Build.isDebuggable()) {
+            Log.i(TAG, "Non-debuggable build doesn't support installation from $archive_path")
+            return false
+        }
+        if (!archive.exists()) {
+            return false
+        }
 
-            val dest = getDefault(this).installDir
-            try {
-                archive.installTo(dest, null)
-                Log.i(TAG, "image is installed from /sdcard/linux/images.tar.gz")
-                return true
-            } catch (e: IOException) {
-                Log.i(TAG, "Failed to install /sdcard/linux/images.tar.gz", e)
-            }
-        } else {
-            Log.i(TAG, "Non-debuggable build doesn't support installation from /sdcard/linux")
+        Log.i(TAG, "trying to install $archive_path")
+
+        val dest = getDefault(this).installDir
+        try {
+            archive.installTo(dest, null)
+            Log.i(TAG, "image is installed from $archive_path")
+            return true
+        } catch (e: IOException) {
+            Log.i(TAG, "Failed to install $archive_path", e)
         }
         return false
     }
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
index 6301da4..4aac37a 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -62,6 +62,12 @@
 import java.util.concurrent.Executors
 
 class VmLauncherService : Service() {
+    inner class VmLauncherServiceBinder : android.os.Binder() {
+        fun getService(): VmLauncherService = this@VmLauncherService
+    }
+
+    private val binder = VmLauncherServiceBinder()
+
     // TODO: using lateinit for some fields to avoid null
     private var executorService: ExecutorService? = null
     private var virtualMachine: VirtualMachine? = null
@@ -79,7 +85,32 @@
     }
 
     override fun onBind(intent: Intent?): IBinder? {
-        return null
+        return binder
+    }
+
+    /**
+     * Processes application lifecycle events and adjusts the virtual machine's memory balloon
+     * accordingly.
+     *
+     * @param event The application lifecycle event.
+     */
+    fun processAppLifeCycleEvent(event: ApplicationLifeCycleEvent) {
+        when (event) {
+            // When the app starts, reset the memory balloon to 0%.
+            // This gives the app maximum available memory.
+            ApplicationLifeCycleEvent.APP_ON_START -> {
+                virtualMachine?.setMemoryBalloonByPercent(0)
+            }
+            ApplicationLifeCycleEvent.APP_ON_STOP -> {
+                // When the app stops, inflate the memory balloon to 10%.
+                // This allows the system to reclaim memory while the app is in the background.
+                // TODO(b/400590341) Inflate the balloon while the application remains Stop status.
+                virtualMachine?.setMemoryBalloonByPercent(10)
+            }
+            else -> {
+                Log.e(TAG, "unrecognized lifecycle event: $event")
+            }
+        }
     }
 
     override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
@@ -108,10 +139,7 @@
         val displaySize = intent.getParcelableExtra(EXTRA_DISPLAY_INFO, DisplayInfo::class.java)
 
         customImageConfigBuilder.setAudioConfig(
-            AudioConfig.Builder()
-                .setUseSpeaker(true)
-                .setUseMicrophone(true)
-                .build()
+            AudioConfig.Builder().setUseSpeaker(true).setUseMicrophone(true).build()
         )
         if (overrideConfigIfNecessary(customImageConfigBuilder, displaySize)) {
             configBuilder.setCustomImageConfig(customImageConfigBuilder.build())
@@ -227,6 +255,21 @@
             )
             Toast.makeText(this, R.string.virgl_enabled, Toast.LENGTH_SHORT).show()
             changed = true
+        } else if (Files.exists(ImageArchive.getSdcardPathForTesting().resolve("gfxstream"))) {
+            // TODO: check if the configuration is right. current config comes from cuttlefish's one
+            builder.setGpuConfig(
+                VirtualMachineCustomImageConfig.GpuConfig.Builder()
+                    .setBackend("gfxstream")
+                    .setRendererUseEgl(false)
+                    .setRendererUseGles(false)
+                    .setRendererUseGlx(false)
+                    .setRendererUseSurfaceless(true)
+                    .setRendererUseVulkan(true)
+                    .setContextTypes(arrayOf<String>("gfxstream-vulkan", "gfxstream-composer"))
+                    .build()
+            )
+            Toast.makeText(this, "gfxstream", Toast.LENGTH_SHORT).show()
+            changed = true
         }
 
         // Set the initial display size
diff --git a/android/TerminalApp/res/values-af/strings.xml b/android/TerminalApp/res/values-af/strings.xml
index 6928614..d906b07 100644
--- a/android/TerminalApp/res/values-af/strings.xml
+++ b/android/TerminalApp/res/values-af/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> is geaktiveer"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Take wat lank neem"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Stelselgebeurtenisse"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Tab"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-az/strings.xml b/android/TerminalApp/res/values-az/strings.xml
index 9b84701..b3ad1f6 100644
--- a/android/TerminalApp/res/values-az/strings.xml
+++ b/android/TerminalApp/res/values-az/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> aktivləşdirilib"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Uzunmüddətli tapşırıqlar"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistem tədbirləri"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Tab"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-b+sr+Latn/strings.xml b/android/TerminalApp/res/values-b+sr+Latn/strings.xml
index 1bdef6d..6ec0a06 100644
--- a/android/TerminalApp/res/values-b+sr+Latn/strings.xml
+++ b/android/TerminalApp/res/values-b+sr+Latn/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> je omogućen"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dugotrajni zadaci"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistemski događaji"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Kartica"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-be/strings.xml b/android/TerminalApp/res/values-be/strings.xml
index a056517..e78ba9c 100644
--- a/android/TerminalApp/res/values-be/strings.xml
+++ b/android/TerminalApp/res/values-be/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"Модуль <xliff:g id="ID_1">VirGL</xliff:g> уключаны"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Працяглыя задачы"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Сістэмныя падзеі"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Укладка"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-bn/strings.xml b/android/TerminalApp/res/values-bn/strings.xml
index e81c3ea..f871f00 100644
--- a/android/TerminalApp/res/values-bn/strings.xml
+++ b/android/TerminalApp/res/values-bn/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> চালু করা আছে"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"দীর্ঘ সময় ধরে চালানো টাস্ক"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"সিস্টেম ইভেন্ট"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"ট্যাব"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-bs/strings.xml b/android/TerminalApp/res/values-bs/strings.xml
index 914cff9..1971481 100644
--- a/android/TerminalApp/res/values-bs/strings.xml
+++ b/android/TerminalApp/res/values-bs/strings.xml
@@ -90,5 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"Omogućeno: <xliff:g id="ID_1">VirGL</xliff:g>"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dugotrajni zadaci"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Događaji sistema"</string>
-    <string name="tab_default_title" msgid="2300417689389397930">"Tab"</string>
+    <string name="tab_default_title" msgid="2300417689389397930">"Kartica"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ca/strings.xml b/android/TerminalApp/res/values-ca/strings.xml
index 7cb50d9..db72829 100644
--- a/android/TerminalApp/res/values-ca/strings.xml
+++ b/android/TerminalApp/res/values-ca/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> està activat"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tasques de llarga durada"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Esdeveniments del sistema"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Tab"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-cs/strings.xml b/android/TerminalApp/res/values-cs/strings.xml
index 41e7756..14fcd27 100644
--- a/android/TerminalApp/res/values-cs/strings.xml
+++ b/android/TerminalApp/res/values-cs/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"Modul <xliff:g id="ID_1">VirGL</xliff:g> je aktivován"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dlouho spuštěné úlohy"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systémové události"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Karta"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-da/strings.xml b/android/TerminalApp/res/values-da/strings.xml
index e3eb0a8..4e153ef 100644
--- a/android/TerminalApp/res/values-da/strings.xml
+++ b/android/TerminalApp/res/values-da/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> er aktiveret"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Længerevarende opgaver"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systemhændelser"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Fane"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-es/strings.xml b/android/TerminalApp/res/values-es/strings.xml
index 3cabc84..76ebaf9 100644
--- a/android/TerminalApp/res/values-es/strings.xml
+++ b/android/TerminalApp/res/values-es/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> se ha habilitado"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tareas de larga duración"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Eventos del sistema"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Tab"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-et/strings.xml b/android/TerminalApp/res/values-et/strings.xml
index 4adaa33..5234a4e 100644
--- a/android/TerminalApp/res/values-et/strings.xml
+++ b/android/TerminalApp/res/values-et/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> on lubatud"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Pikalt kestvad ülesanded"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Süsteemisündmused"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Tabulaator"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-eu/strings.xml b/android/TerminalApp/res/values-eu/strings.xml
index 63aa7bb..403c305 100644
--- a/android/TerminalApp/res/values-eu/strings.xml
+++ b/android/TerminalApp/res/values-eu/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> gaituta dago"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Luze exekutatzen diren zereginak"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistemako gertaerak"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Fitxa"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-fr-rCA/strings.xml b/android/TerminalApp/res/values-fr-rCA/strings.xml
index 3660576..d4c1235 100644
--- a/android/TerminalApp/res/values-fr-rCA/strings.xml
+++ b/android/TerminalApp/res/values-fr-rCA/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> est activé"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tâches de longue durée"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Événements système"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Onglet"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-hu/strings.xml b/android/TerminalApp/res/values-hu/strings.xml
index afde089..bd4fe52 100644
--- a/android/TerminalApp/res/values-hu/strings.xml
+++ b/android/TerminalApp/res/values-hu/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"A(z) <xliff:g id="ID_1">VirGL</xliff:g> engedélyezve van"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Hosszan futó feladatok"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Rendszeresemények"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Lap"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-hy/strings.xml b/android/TerminalApp/res/values-hy/strings.xml
index 0df7a91..d33642c 100644
--- a/android/TerminalApp/res/values-hy/strings.xml
+++ b/android/TerminalApp/res/values-hy/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g>-ը միացված է"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Երկար աշխատող առաջադրանքներ"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Համակարգի իրադարձություններ"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Ներդիր"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-is/strings.xml b/android/TerminalApp/res/values-is/strings.xml
index 4d3d7a6..e7aad2b 100644
--- a/android/TerminalApp/res/values-is/strings.xml
+++ b/android/TerminalApp/res/values-is/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"Kveikt er á <xliff:g id="ID_1">VirGL</xliff:g>"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Langvarandi verkefni"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Kerfistilvik"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Flipi"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-iw/strings.xml b/android/TerminalApp/res/values-iw/strings.xml
index 6b56764..6d2a0f3 100644
--- a/android/TerminalApp/res/values-iw/strings.xml
+++ b/android/TerminalApp/res/values-iw/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"‫<xliff:g id="ID_1">VirGL</xliff:g> מופעל"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"משימות ממושכות"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"אירועי מערכת"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"כרטיסייה"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ky/strings.xml b/android/TerminalApp/res/values-ky/strings.xml
index 814c808..c80f891 100644
--- a/android/TerminalApp/res/values-ky/strings.xml
+++ b/android/TerminalApp/res/values-ky/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> иштетилди"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Узак тапшырмалар"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Тутумдук иш-чаралар"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Өтмөк"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-lv/strings.xml b/android/TerminalApp/res/values-lv/strings.xml
index 412b454..b87f61f 100644
--- a/android/TerminalApp/res/values-lv/strings.xml
+++ b/android/TerminalApp/res/values-lv/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ir iespējots"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Ilgstoši uzdevumi"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistēmas notikumi"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Cilne"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-mk/strings.xml b/android/TerminalApp/res/values-mk/strings.xml
index 00ee26b..d071f41 100644
--- a/android/TerminalApp/res/values-mk/strings.xml
+++ b/android/TerminalApp/res/values-mk/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"Овозможено: <xliff:g id="ID_1">VirGL</xliff:g>"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Задачи што се извршуваат долго"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Системски настани"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Картичка"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-nb/strings.xml b/android/TerminalApp/res/values-nb/strings.xml
index 3d3a50a..7481be8 100644
--- a/android/TerminalApp/res/values-nb/strings.xml
+++ b/android/TerminalApp/res/values-nb/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> er aktivert"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Langvarige oppgaver"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systemhendelser"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Fane"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-pl/strings.xml b/android/TerminalApp/res/values-pl/strings.xml
index 59710d0..b5ad6d7 100644
--- a/android/TerminalApp/res/values-pl/strings.xml
+++ b/android/TerminalApp/res/values-pl/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"Układ <xliff:g id="ID_1">VirGL</xliff:g> jest włączony"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Długotrwałe zadania"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Zdarzenia systemowe"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Karta"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-pt/strings.xml b/android/TerminalApp/res/values-pt/strings.xml
index ddfb46d..8c05964 100644
--- a/android/TerminalApp/res/values-pt/strings.xml
+++ b/android/TerminalApp/res/values-pt/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"O <xliff:g id="ID_1">VirGL</xliff:g> está ativado"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tarefas de longa duração"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Eventos do sistema"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Guia"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ro/strings.xml b/android/TerminalApp/res/values-ro/strings.xml
index b5575b4..c333535 100644
--- a/android/TerminalApp/res/values-ro/strings.xml
+++ b/android/TerminalApp/res/values-ro/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> este activat"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Activități de durată"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Evenimente de sistem"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Tab"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ru/strings.xml b/android/TerminalApp/res/values-ru/strings.xml
index c8ab061..7e86cb1 100644
--- a/android/TerminalApp/res/values-ru/strings.xml
+++ b/android/TerminalApp/res/values-ru/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g>: включено."</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Длительные задачи"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Системные события"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Вкладка"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-si/strings.xml b/android/TerminalApp/res/values-si/strings.xml
index 84c4840..7085d17 100644
--- a/android/TerminalApp/res/values-si/strings.xml
+++ b/android/TerminalApp/res/values-si/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> සබලයි"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"දිගු කාලයක් ධාවනය වන කාර්යයන්"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"පද්ධති සිදුවීම්"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"පටිත්ත"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sk/strings.xml b/android/TerminalApp/res/values-sk/strings.xml
index 35a9806..b11ada0 100644
--- a/android/TerminalApp/res/values-sk/strings.xml
+++ b/android/TerminalApp/res/values-sk/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"Procesor <xliff:g id="ID_1">VirGL</xliff:g> je aktivovaný"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dlho spustené úlohy"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systémové udalosti"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Tab"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sl/strings.xml b/android/TerminalApp/res/values-sl/strings.xml
index ecd3931..8785b84 100644
--- a/android/TerminalApp/res/values-sl/strings.xml
+++ b/android/TerminalApp/res/values-sl/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> je omogočen"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dolgotrajna opravila"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistemski dogodki"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Zavihek"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sq/strings.xml b/android/TerminalApp/res/values-sq/strings.xml
index d1a5fe1..f540af8 100644
--- a/android/TerminalApp/res/values-sq/strings.xml
+++ b/android/TerminalApp/res/values-sq/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> është aktivizuar"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Detyrat afatgjata"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Ngjarjet e sistemit"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Tab"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sr/strings.xml b/android/TerminalApp/res/values-sr/strings.xml
index 635c467..8620b8a 100644
--- a/android/TerminalApp/res/values-sr/strings.xml
+++ b/android/TerminalApp/res/values-sr/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> је омогућен"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Дуготрајни задаци"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Системски догађаји"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Картица"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ta/strings.xml b/android/TerminalApp/res/values-ta/strings.xml
index 1b4c766..ba6edbf 100644
--- a/android/TerminalApp/res/values-ta/strings.xml
+++ b/android/TerminalApp/res/values-ta/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> இயக்கப்பட்டது"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"நீண்ட நேரம் இயங்கும் பணிகள்"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"சிஸ்டம் நிகழ்வுகள்"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"பிரிவு"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-tr/strings.xml b/android/TerminalApp/res/values-tr/strings.xml
index e97728c..cc3812e 100644
--- a/android/TerminalApp/res/values-tr/strings.xml
+++ b/android/TerminalApp/res/values-tr/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> etkinleştirildi"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Uzun süredir çalışan görevler"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistem etkinlikleri"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Sekme"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-uk/strings.xml b/android/TerminalApp/res/values-uk/strings.xml
index 8cb7601..4224d98 100644
--- a/android/TerminalApp/res/values-uk/strings.xml
+++ b/android/TerminalApp/res/values-uk/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> увімкнено"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Довготривалі завдання"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Події системи"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Вкладка"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-zh-rTW/strings.xml b/android/TerminalApp/res/values-zh-rTW/strings.xml
index 7ddb8cd..94f473d 100644
--- a/android/TerminalApp/res/values-zh-rTW/strings.xml
+++ b/android/TerminalApp/res/values-zh-rTW/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> 已啟用"</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"長時間執行的工作"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"系統事件"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"分頁"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-zu/strings.xml b/android/TerminalApp/res/values-zu/strings.xml
index 1af2744..432102b 100644
--- a/android/TerminalApp/res/values-zu/strings.xml
+++ b/android/TerminalApp/res/values-zu/strings.xml
@@ -90,6 +90,5 @@
     <string name="virgl_enabled" msgid="5242525588039698086">"I-<xliff:g id="ID_1">VirGL</xliff:g> inikwe amandla."</string>
     <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Imisebenzi esebenza isikhathi eside"</string>
     <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Imicimbi yesistimu"</string>
-    <!-- no translation found for tab_default_title (2300417689389397930) -->
-    <skip />
+    <string name="tab_default_title" msgid="2300417689389397930">"Ithebhu"</string>
 </resources>
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index 1a263bd..1c4c2eb 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -151,6 +151,17 @@
     }
 });
 
+// TODO(ioffe): add service for guest-ffa.
+const KNOWN_TEE_SERVICES: [&str; 0] = [];
+
+fn check_known_tee_service(tee_service: &str) -> binder::Result<()> {
+    if !KNOWN_TEE_SERVICES.contains(&tee_service) {
+        return Err(anyhow!("unknown tee_service {tee_service}"))
+            .or_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION);
+    }
+    Ok(())
+}
+
 fn create_or_update_idsig_file(
     input_fd: &ParcelFileDescriptor,
     idsig_fd: &ParcelFileDescriptor,
@@ -303,6 +314,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,
@@ -459,6 +498,12 @@
     if path.starts_with("/system/product/") {
         return Ok(CallingPartition::Product);
     }
+    if path.starts_with("/data/nativetest/vendor/")
+        || path.starts_with("/data/nativetest64/vendor/")
+    {
+        return Ok(CallingPartition::Vendor);
+    }
+
     let partition = {
         let mut components = path.components();
         let Some(std::path::Component::Normal(partition)) = components.nth(1) else {
@@ -682,11 +727,38 @@
         *is_protected = config.protectedVm;
 
         if !config.teeServices.is_empty() {
+            if !config.protectedVm {
+                return Err(anyhow!("only protected VMs can request tee services"))
+                    .or_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION);
+            }
             check_tee_service_permission(&caller_secontext, &config.teeServices)
                 .with_log()
                 .or_binder_exception(ExceptionCode::SECURITY)?;
         }
 
+        let mut system_tee_services = Vec::new();
+        let mut vendor_tee_services = Vec::new();
+        for tee_service in config.teeServices.clone() {
+            if !tee_service.starts_with("vendor.") {
+                check_known_tee_service(&tee_service)?;
+                system_tee_services.push(tee_service);
+            } else {
+                vendor_tee_services.push(tee_service);
+            }
+        }
+
+        // TODO(b/391774181): handle vendor tee services (which require talking to HAL) as well.
+        if !vendor_tee_services.is_empty() {
+            return Err(anyhow!("support for vendor tee services is coming soon!"))
+                .or_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION);
+        }
+
+        // TODO(b/391774181): remove this check in a follow-up patch.
+        if !system_tee_services.is_empty() {
+            return Err(anyhow!("support for system tee services is coming soon!"))
+                .or_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION);
+        }
+
         let kernel = maybe_clone_file(&config.kernel)?;
         let initrd = maybe_clone_file(&config.initrd)?;
 
@@ -863,6 +935,20 @@
             })
             .collect::<binder::Result<_>>()?;
 
+        let memory_reclaim_supported =
+            system_properties::read_bool("hypervisor.memory_reclaim.supported", false)
+                .unwrap_or(false);
+
+        let balloon = config.balloon && memory_reclaim_supported;
+
+        if !balloon {
+            warn!(
+                "Memory balloon not enabled:
+                config.balloon={},hypervisor.memory_reclaim.supported={}",
+                config.balloon, memory_reclaim_supported
+            );
+        }
+
         // Actually start the VM.
         let crosvm_config = CrosvmConfig {
             cid,
@@ -902,7 +988,7 @@
             boost_uclamp: config.boostUclamp,
             gpu_config,
             audio_config,
-            balloon: config.balloon,
+            balloon,
             usb_config,
             dump_dt_fd,
             enable_hypervisor_specific_auth_method: config.enableHypervisorSpecificAuthMethod,
@@ -1374,7 +1460,7 @@
     calling_partition: CallingPartition,
 ) -> Result<()> {
     let path = format!("/proc/self/fd/{}", fd.as_raw_fd());
-    let link = fs::read_link(&path).context(format!("can't read_link {path}"))?;
+    let link = fs::read_link(&path).with_context(|| format!("can't read_link {path}"))?;
 
     // microdroid vendor image is OK
     if cfg!(vendor_modules) && link == Path::new("/vendor/etc/avf/microdroid/microdroid_vendor.img")
@@ -1382,7 +1468,10 @@
         return Ok(());
     }
 
-    let is_fd_vendor = link.starts_with("/vendor") || link.starts_with("/odm");
+    let fd_partition = find_partition(Some(&link))
+        .with_context(|| format!("can't find_partition {}", link.display()))?;
+    let is_fd_vendor =
+        fd_partition == CallingPartition::Vendor || fd_partition == CallingPartition::Odm;
     let is_caller_vendor =
         calling_partition == CallingPartition::Vendor || calling_partition == CallingPartition::Odm;
 
@@ -1558,9 +1647,8 @@
         | "virtualizationservice_data_file" // files created by VS / VirtMgr
         | "vendor_microdroid_file" // immutable dm-verity protected partition (/vendor/etc/avf/microdroid/.*)
          => Ok(()),
-        // It is difficult to require specific label types for vendor initiated VM's files, so we
-        // allow anything with a vendor prefix.
-        t if calling_partition == CallingPartition::Vendor && t.starts_with("vendor_")  => Ok(()),
+        // It is difficult to require specific label types for vendor initiated VM's files.
+        _ if calling_partition == CallingPartition::Vendor => Ok(()),
         _ => bail!("Label {} is not allowed", context),
     }
 }
@@ -1659,6 +1747,10 @@
             .or_service_specific_exception(-1)
     }
 
+    fn isMemoryBalloonEnabled(&self) -> binder::Result<bool> {
+        Ok(self.instance.balloon_enabled)
+    }
+
     fn getMemoryBalloon(&self) -> binder::Result<i64> {
         let balloon = self
             .instance
@@ -2210,6 +2302,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 {
@@ -2762,6 +2858,14 @@
     }
 
     #[test]
+    fn test_vendor_in_data() {
+        assert_eq!(
+            CallingPartition::Vendor,
+            find_partition(Some(Path::new("/data/nativetest64/vendor/file"))).unwrap()
+        );
+    }
+
+    #[test]
     fn early_vm_exe_paths_match_succeeds_with_same_paths() {
         let early_vm = EarlyVm {
             name: "vm_demo_native_early".to_owned(),
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 77710c3..5f81e90 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -417,6 +417,8 @@
     pub vm_service: Mutex<Option<Strong<dyn IVirtualMachineService>>>,
     /// Recorded metrics of VM such as timestamp or cpu / memory usage.
     pub vm_metric: Mutex<VmMetric>,
+    // Whether virtio-balloon is enabled
+    pub balloon_enabled: bool,
     /// The latest lifecycle state which the payload reported itself to be in.
     payload_state: Mutex<PayloadState>,
     /// Represents the condition that payload_state was updated
@@ -449,6 +451,7 @@
         let cid = config.cid;
         let name = config.name.clone();
         let protected = config.protected;
+        let balloon_enabled = config.balloon;
         let requester_uid_name = User::from_uid(Uid::from_raw(requester_uid))
             .ok()
             .flatten()
@@ -469,6 +472,7 @@
             payload_state: Mutex::new(PayloadState::Starting),
             payload_state_updated: Condvar::new(),
             requester_uid_name,
+            balloon_enabled,
         };
         info!("{} created", &instance);
         Ok(instance)
@@ -722,6 +726,9 @@
 
     /// Returns current virtio-balloon size.
     pub fn get_memory_balloon(&self) -> Result<u64, Error> {
+        if !self.balloon_enabled {
+            bail!("virtio-balloon is not enabled");
+        }
         let socket_path_cstring = path_to_cstring(&self.crosvm_control_socket_path);
         let mut balloon_actual = 0u64;
         // SAFETY: Pointers are valid for the lifetime of the call. Null `stats` is valid.
@@ -741,6 +748,9 @@
     /// Inflates the virtio-balloon by `num_bytes` to reclaim guest memory. Called in response to
     /// memory-trimming notifications.
     pub fn set_memory_balloon(&self, num_bytes: u64) -> Result<(), Error> {
+        if !self.balloon_enabled {
+            bail!("virtio-balloon is not enabled");
+        }
         let socket_path_cstring = path_to_cstring(&self.crosvm_control_socket_path);
         // SAFETY: Pointer is valid for the lifetime of the call.
         let success = unsafe {
@@ -1038,8 +1048,7 @@
         .arg("--cid")
         .arg(config.cid.to_string());
 
-    if system_properties::read_bool("hypervisor.memory_reclaim.supported", false)? && config.balloon
-    {
+    if config.balloon {
         command.arg("--balloon-page-reporting");
     } else {
         command.arg("--no-balloon");
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachine.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachine.aidl
index a01d385..e7aeefd 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachine.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachine.aidl
@@ -49,6 +49,7 @@
     void stop();
 
     /** Access to the VM's memory balloon. */
+    boolean isMemoryBalloonEnabled();
     long getMemoryBalloon();
     void setMemoryBalloon(long num_bytes);
 
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/main.rs b/android/vm/src/main.rs
index ff846a1..7178de5 100644
--- a/android/vm/src/main.rs
+++ b/android/vm/src/main.rs
@@ -22,8 +22,6 @@
     CpuOptions::CpuTopology::CpuTopology, IVirtualizationService::IVirtualizationService,
     PartitionType::PartitionType, VirtualMachineAppConfig::DebugLevel::DebugLevel,
 };
-#[cfg(not(llpvm_changes))]
-use anyhow::anyhow;
 use anyhow::{bail, Context, Error};
 use binder::{ProcessState, Strong};
 use clap::{Args, Parser};
@@ -220,7 +218,6 @@
     instance: PathBuf,
 
     /// Path to file containing instance_id. Required iff llpvm feature is enabled.
-    #[cfg(llpvm_changes)]
     #[arg(long = "instance-id-file")]
     instance_id: PathBuf,
 
@@ -255,26 +252,8 @@
         }
     }
 
-    fn instance_id(&self) -> Result<PathBuf, Error> {
-        cfg_if::cfg_if! {
-            if #[cfg(llpvm_changes)] {
-                Ok(self.instance_id.clone())
-            } else {
-                Err(anyhow!("LLPVM feature is disabled, --instance_id flag not supported"))
-            }
-        }
-    }
-
-    fn set_instance_id(&mut self, instance_id_file: PathBuf) -> Result<(), Error> {
-        cfg_if::cfg_if! {
-            if #[cfg(llpvm_changes)] {
-                self.instance_id = instance_id_file;
-                Ok(())
-            } else {
-                let _ = instance_id_file;
-                Err(anyhow!("LLPVM feature is disabled, --instance_id flag not supported"))
-            }
-        }
+    fn set_instance_id(&mut self, instance_id_file: PathBuf) {
+        self.instance_id = instance_id_file;
     }
 }
 
diff --git a/android/vm/src/run.rs b/android/vm/src/run.rs
index a362b8e..1033164 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;
@@ -86,8 +87,8 @@
         )?;
     }
 
-    let instance_id = if cfg!(llpvm_changes) {
-        let id_file = config.instance_id()?;
+    let instance_id = {
+        let id_file = config.instance_id;
         if id_file.exists() {
             let mut id = [0u8; 64];
             let mut instance_id_file = File::open(id_file)?;
@@ -99,9 +100,6 @@
             instance_id_file.write_all(&id)?;
             id
         }
-    } else {
-        // if llpvm feature flag is disabled, instance_id is not used.
-        [0u8; 64]
     };
 
     let storage = if let Some(ref path) = config.microdroid.storage {
@@ -112,6 +110,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 {
@@ -251,10 +251,8 @@
         ..Default::default()
     };
 
-    if cfg!(llpvm_changes) {
-        app_config.set_instance_id(work_dir.join("instance_id"))?;
-        println!("instance_id file path: {}", app_config.instance_id()?.display());
-    }
+    app_config.set_instance_id(work_dir.join("instance_id"));
+    println!("instance_id file path: {}", app_config.instance_id.display());
 
     command_run_app(app_config)
 }
@@ -370,6 +368,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/android/vm_demo_native/main.cpp b/android/vm_demo_native/main.cpp
index e1acc05..8fc14bf 100644
--- a/android/vm_demo_native/main.cpp
+++ b/android/vm_demo_native/main.cpp
@@ -329,11 +329,15 @@
                                                                       &ARpcSession_free);
     ARpcSession_setMaxIncomingThreads(session.get(), 1);
 
+    auto param = std::make_unique<std::shared_ptr<IVirtualMachine>>(std::move(vm));
+    auto paramDeleteFd = [](void* param) {
+        delete static_cast<std::shared_ptr<IVirtualMachine>*>(param);
+    };
+
     AIBinder* binder = ARpcSession_setupPreconnectedClient(
             session.get(),
             [](void* param) {
-                std::shared_ptr<IVirtualMachine> vm =
-                        *static_cast<std::shared_ptr<IVirtualMachine>*>(param);
+                IVirtualMachine* vm = static_cast<std::shared_ptr<IVirtualMachine>*>(param)->get();
                 ScopedFileDescriptor sock_fd;
                 ScopedAStatus ret = vm->connectVsock(ITestService::PORT, &sock_fd);
                 if (!ret.isOk()) {
@@ -341,7 +345,7 @@
                 }
                 return sock_fd.release();
             },
-            &vm);
+            param.release(), paramDeleteFd);
     if (binder == nullptr) {
         return Error() << "Failed to connect to vm payload";
     }
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 20f44fe..79675cb 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -251,11 +251,6 @@
     srcs: [
         "sign_virt_apex.py",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     required: [
         // sign_virt_apex should be runnable from outside the source tree,
         // therefore, any required tool should be listed in build/make/core/Makefile as well.
@@ -324,11 +319,6 @@
     srcs: [
         "replace_bytes.py",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
 }
 
 // Encapsulate the contributions made by the com.android.virt to the bootclasspath.
diff --git a/build/apex/manifest.json b/build/apex/manifest.json
index b32aa7b..e596ce1 100644
--- a/build/apex/manifest.json
+++ b/build/apex/manifest.json
@@ -3,6 +3,7 @@
   "version": 2,
   "requireNativeLibs": [
     "libEGL.so",
-    "libGLESv2.so"
+    "libGLESv2.so",
+    "libvulkan.so"
   ]
 }
diff --git a/build/compos/CompOSPayloadApp/Android.bp b/build/compos/CompOSPayloadApp/Android.bp
index c6192b9..04465b3 100644
--- a/build/compos/CompOSPayloadApp/Android.bp
+++ b/build/compos/CompOSPayloadApp/Android.bp
@@ -5,5 +5,6 @@
 android_app {
     name: "CompOSPayloadApp",
     sdk_version: "current",
+    system_ext_specific: true,
     apex_available: ["com.android.compos"],
 }
diff --git a/build/debian/build.sh b/build/debian/build.sh
index 63035ae..9c4d4b1 100755
--- a/build/debian/build.sh
+++ b/build/debian/build.sh
@@ -114,14 +114,6 @@
 		)
 	fi
 
-	# TODO(b/365955006): remove these lines when uboot supports x86_64 EFI application
-	if [[ "$arch" == "x86_64" ]]; then
-		packages+=(
-			libguestfs-tools
-			linux-image-generic
-		)
-	fi
-
 	if [[ "$use_generic_kernel" != 1 ]]; then
 		packages+=(
 			bc
@@ -326,9 +318,8 @@
 
 generate_output_package() {
 	fdisk -l "${raw_disk_image}"
-	local vm_config="$SCRIPT_DIR/vm_config.json.${arch}"
+	local vm_config="$SCRIPT_DIR/vm_config.json"
 	local root_partition_num=1
-	local bios_partition_num=14
 	local efi_partition_num=15
 
 	pushd ${workdir} > /dev/null
@@ -337,9 +328,6 @@
 
 	loop=$(losetup -f --show --partscan $raw_disk_image)
 	dd if="${loop}p$root_partition_num" of=root_part
-	if [[ "$arch" == "x86_64" ]]; then
-		dd if="${loop}p$bios_partition_num" of=bios_part
-	fi
 	dd if="${loop}p$efi_partition_num" of=efi_part
 	losetup -d "${loop}"
 
@@ -350,36 +338,19 @@
 	fi
 
 	sed -i "s/{root_part_guid}/$(sfdisk --part-uuid $raw_disk_image $root_partition_num)/g" vm_config.json
-	if [[ "$arch" == "x86_64" ]]; then
-		sed -i "s/{bios_part_guid}/$(sfdisk --part-uuid $raw_disk_image $bios_partition_num)/g" vm_config.json
-	fi
 	sed -i "s/{efi_part_guid}/$(sfdisk --part-uuid $raw_disk_image $efi_partition_num)/g" vm_config.json
 
-	images=()
-	if [[ "$arch" == "aarch64" ]]; then
-		images+=(
-			root_part
-			efi_part
-		)
-	# TODO(b/365955006): remove these lines when uboot supports x86_64 EFI application
-	elif [[ "$arch" == "x86_64" ]]; then
-		rm -f vmlinuz initrd.img
-		virt-get-kernel -a "${raw_disk_image}"
-		mv vmlinuz* vmlinuz
-		mv initrd.img* initrd.img
-		images+=(
-			bios_part
-			root_part
-			efi_part
-			vmlinuz
-			initrd.img
-		)
-	fi
-
 	popd > /dev/null
 
+	contents=(
+		build_id
+		root_part
+		efi_part
+		vm_config.json
+	)
+
 	# --sparse option isn't supported in apache-commons-compress
-	tar czv -f ${output} -C ${workdir} build_id "${images[@]}" vm_config.json
+	tar czv -f ${output} -C ${workdir} "${contents[@]}"
 }
 
 clean_up() {
diff --git a/build/debian/vm_config.json.aarch64 b/build/debian/vm_config.json
similarity index 100%
rename from build/debian/vm_config.json.aarch64
rename to build/debian/vm_config.json
diff --git a/build/debian/vm_config.json.x86_64 b/build/debian/vm_config.json.x86_64
deleted file mode 100644
index bc4e00a..0000000
--- a/build/debian/vm_config.json.x86_64
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-    "name": "debian",
-    "disks": [
-        {
-            "partitions": [
-                {
-                    "label": "ROOT",
-                    "path": "$PAYLOAD_DIR/root_part",
-                    "writable": true,
-                    "guid": "{root_part_guid}"
-                },
-                {
-                    "label": "BIOS",
-                    "path": "$PAYLOAD_DIR/bios_part",
-                    "writable": true,
-                    "guid": "{bios_part_guid}"
-                },
-                {
-                    "label": "EFI",
-                    "path": "$PAYLOAD_DIR/efi_part",
-                    "writable": false,
-                    "guid": "{efi_part_guid}"
-                }
-            ],
-            "writable": true
-        }
-    ],
-    "sharedPath": [
-        {
-            "sharedPath": "/storage/emulated"
-        },
-        {
-            "sharedPath": "$APP_DATA_DIR/files"
-        }
-    ],
-    "kernel": "$PAYLOAD_DIR/vmlinuz",
-    "initrd": "$PAYLOAD_DIR/initrd.img",
-    "params": "root=/dev/vda1",
-    "protected": false,
-    "cpu_topology": "match_host",
-    "platform_version": "~1.0",
-    "memory_mib": 4096,
-    "debuggable": true,
-    "console_out": true,
-    "console_input_device": "ttyS0",
-    "network": true,
-    "auto_memory_balloon": true,
-    "gpu": {
-        "backend": "2d"
-    }
-}
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/forwarder_guest_launcher/debian/service b/guest/forwarder_guest_launcher/debian/service
index 6824c70..ad57a26 100644
--- a/guest/forwarder_guest_launcher/debian/service
+++ b/guest/forwarder_guest_launcher/debian/service
@@ -11,6 +11,8 @@
 RestartSec=1
 User=root
 Group=root
+StandardOutput=journal
+StandardError=journal
 
 [Install]
 WantedBy=multi-user.target
diff --git a/guest/microdroid_manager/src/main.rs b/guest/microdroid_manager/src/main.rs
index 57ad35d..4537834 100644
--- a/guest/microdroid_manager/src/main.rs
+++ b/guest/microdroid_manager/src/main.rs
@@ -244,13 +244,14 @@
 fn verify_payload_with_instance_img(
     metadata: &Metadata,
     dice: &DiceDriver,
+    state: &mut VmInstanceState,
 ) -> Result<MicrodroidData> {
     let mut instance = InstanceDisk::new().context("Failed to load instance.img")?;
     let saved_data = instance.read_microdroid_data(dice).context("Failed to read identity data")?;
 
     if is_strict_boot() {
         // Provisioning must happen on the first boot and never again.
-        if is_new_instance_legacy() {
+        if Path::new(AVF_NEW_INSTANCE).exists() {
             ensure!(
                 saved_data.is_none(),
                 MicrodroidError::PayloadInvalidConfig(
@@ -286,12 +287,14 @@
             );
             info!("Saved data is verified.");
         }
+        *state = VmInstanceState::PreviouslySeen;
         saved_data
     } else {
         info!("Saving verified data.");
         instance
             .write_microdroid_data(&extracted_data, dice)
             .context("Failed to write identity data")?;
+        *state = VmInstanceState::NewlyCreated;
         extracted_data
     };
     Ok(instance_data)
@@ -321,13 +324,14 @@
             .context("Failed to load DICE from driver")?
     };
 
+    let mut state = VmInstanceState::Unknown;
     // Microdroid skips checking payload against instance image iff the device supports
-    // secretkeeper. In that case Microdroid use VmSecret::V2, which provide protection against
-    // rollback of boot images and packages.
+    // secretkeeper. In that case Microdroid use VmSecret::V2, which provides instance state
+    // and protection against rollback of boot images and packages.
     let instance_data = if should_defer_rollback_protection() {
         verify_payload(&metadata, None)?
     } else {
-        verify_payload_with_instance_img(&metadata, &dice)?
+        verify_payload_with_instance_img(&metadata, &dice, &mut state)?
     };
 
     let payload_metadata = metadata.payload.ok_or_else(|| {
@@ -337,7 +341,6 @@
     // To minimize the exposure to untrusted data, derive dice profile as soon as possible.
     info!("DICE derivation for payload");
     let dice_artifacts = dice_derivation(dice, &instance_data, &payload_metadata)?;
-    let mut state = VmInstanceState::Unknown;
     let vm_secret = VmSecret::new(dice_artifacts, service, &mut state)
         .context("Failed to create VM secrets")?;
 
@@ -345,15 +348,7 @@
         VmInstanceState::NewlyCreated => true,
         VmInstanceState::PreviouslySeen => false,
         VmInstanceState::Unknown => {
-            // VmSecret instantiation was not able to determine the state. This should only happen
-            // for legacy secret mechanism (V1) - in which case fallback to legacy
-            // instance.img based determination of state.
-            ensure!(
-                !should_defer_rollback_protection(),
-                "VmInstanceState is Unknown whilst guest is expected to use V2 based secrets.
-                This should've never happened"
-            );
-            is_new_instance_legacy()
+            bail!("Vm instance state is still unknown, this should not have happened");
         }
     };
 
@@ -368,14 +363,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 +397,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 +425,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")
@@ -517,10 +514,6 @@
     Path::new(AVF_STRICT_BOOT).exists()
 }
 
-fn is_new_instance_legacy() -> bool {
-    Path::new(AVF_NEW_INSTANCE).exists()
-}
-
 fn is_verified_boot() -> bool {
     !Path::new(DEBUG_MICRODROID_NO_VERIFIED_BOOT).exists()
 }
diff --git a/guest/microdroid_manager/src/vm_secret.rs b/guest/microdroid_manager/src/vm_secret.rs
index 6331074..674f010 100644
--- a/guest/microdroid_manager/src/vm_secret.rs
+++ b/guest/microdroid_manager/src/vm_secret.rs
@@ -35,6 +35,9 @@
     StoreSecretRequest, GetSecretResponse, GetSecretRequest};
 use secretkeeper_comm::data_types::error::SecretkeeperError;
 use std::fs;
+use std::thread;
+use rand::Rng;
+use std::time::Duration;
 use zeroize::Zeroizing;
 use std::sync::Mutex;
 use std::sync::Arc;
@@ -63,6 +66,8 @@
     0x55, 0xF8, 0x08, 0x23, 0x81, 0x5F, 0xF5, 0x16, 0x20, 0x3E, 0xBE, 0xBA, 0xB7, 0xA8, 0x43, 0x92,
 ];
 
+const BACKOFF_SK_ACCESS_MS: u64 = 100;
+
 pub enum VmSecret {
     // V2 secrets are derived from 2 independently secured secrets:
     //      1. Secretkeeper protected secrets (skp secret).
@@ -77,6 +82,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,
@@ -117,20 +123,25 @@
             .map_err(|e| anyhow!("Failed to build a sealing_policy: {e}"))?;
         let session = SkVmSession::new(vm_service, &explicit_dice, policy)?;
         let mut skp_secret = Zeroizing::new([0u8; SECRET_SIZE]);
-        if let Some(secret) = session.get_secret(id)? {
-            *skp_secret = secret;
-            *state = VmInstanceState::PreviouslySeen;
-        } else {
-            log::warn!("No entry found in Secretkeeper for this VM instance, creating new secret.");
-            *skp_secret = rand::random();
-            session.store_secret(id, skp_secret.clone())?;
-            *state = VmInstanceState::NewlyCreated;
-        }
+        get_or_create_sk_secret(&session, id, &mut skp_secret, state).or_else(|e| {
+            // TODO(b/399304956): Secretkeeper rejects requests when overloaded with
+            // connections from multiple clients. Backoff & retry again, hoping it is
+            // less busy then. Secretkeeper changes are required for more robust solutions.
+            log::info!(
+                "get_or_create_sk_secret failed with {e:?}. Refreshing connection & retrying!"
+            );
+            let mut rng = rand::thread_rng();
+            let backoff = rng.gen_range(BACKOFF_SK_ACCESS_MS..2 * BACKOFF_SK_ACCESS_MS);
+            thread::sleep(Duration::from_millis(backoff));
+            session.refresh()?;
+            get_or_create_sk_secret(&session, id, &mut skp_secret, state)
+        })?;
         Ok(Self::V2 {
             instance_id: id,
             dice_artifacts: explicit_dice,
             skp_secret: ZVec::try_from(skp_secret.to_vec())?,
             secretkeeper_session: session,
+            virtual_machine_service: vm_service.clone(),
         })
     }
 
@@ -180,10 +191,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()?;
@@ -271,8 +292,6 @@
     sealing_policy: Vec<u8>,
 }
 
-// TODO(b/378911776): This get_secret/store_secret fails on expired session.
-// Introduce retry after refreshing the session
 impl SkVmSession {
     fn new(
         vm_service: &Strong<dyn IVirtualMachineService>,
@@ -354,3 +373,21 @@
             ))
         })?)
 }
+
+fn get_or_create_sk_secret(
+    session: &SkVmSession,
+    id: [u8; ID_SIZE],
+    skp_secret: &mut Zeroizing<[u8; SECRET_SIZE]>,
+    state: &mut VmInstanceState,
+) -> Result<()> {
+    if let Some(secret) = session.get_secret(id)? {
+        **skp_secret = secret;
+        *state = VmInstanceState::PreviouslySeen;
+    } else {
+        log::warn!("No entry found in Secretkeeper for this VM instance, creating new secret.");
+        **skp_secret = rand::random();
+        session.store_secret(id, skp_secret.clone())?;
+        *state = VmInstanceState::NewlyCreated;
+    }
+    Ok(())
+}
diff --git a/guest/shutdown_runner/debian/service b/guest/shutdown_runner/debian/service
index 7188d36..2668930 100644
--- a/guest/shutdown_runner/debian/service
+++ b/guest/shutdown_runner/debian/service
@@ -10,6 +10,8 @@
 RestartSec=1
 User=root
 Group=root
+StandardOutput=journal
+StandardError=journal
 
 [Install]
 WantedBy=multi-user.target
diff --git a/guest/trusty/common/Android.bp b/guest/trusty/common/Android.bp
index d6c524f..1a4c4d7 100644
--- a/guest/trusty/common/Android.bp
+++ b/guest/trusty/common/Android.bp
@@ -1,22 +1,3 @@
-soong_config_module_type {
-    name: "trusty_vm_prebuilt_etc",
-    module_type: "prebuilt_etc",
-    config_namespace: "trusty_system_vm",
-    bool_variables: [
-        "enabled",
-        "placeholder_trusted_hal",
-    ],
-    properties: ["src"],
-}
-
-soong_config_module_type {
-    name: "trusty_vm_avb_add_hash_footer",
-    module_type: "avb_add_hash_footer",
-    config_namespace: "trusty_system_vm",
-    bool_variables: ["enabled"],
-    properties: ["src"],
-}
-
 prebuilt_etc {
     name: "early_vms.xml",
     filename: "early_vms.xml",
diff --git a/guest/trusty/security_vm/launcher/security_vm_launcher-arm64.rc b/guest/trusty/security_vm/launcher/security_vm_launcher-arm64.rc
index c0e0537..b9c7147 100644
--- a/guest/trusty/security_vm/launcher/security_vm_launcher-arm64.rc
+++ b/guest/trusty/security_vm/launcher/security_vm_launcher-arm64.rc
@@ -1,9 +1,9 @@
-# TODO(b/393848713): use --protected for the vm launcher when issues are fixed
 # TODO(b/393848753): determine whether task_profiles shall be defined
 service trusty_security_vm_launcher /system_ext/bin/trusty_security_vm_launcher \
 --name trusty_security_vm_launcher \
 --kernel /system_ext/etc/vm/trusty_vm/trusty_security_vm.elf \
---memory-size-mib 32
+--memory-size-mib 32 \
+--protected
     disabled
     user system
     group system virtualmachine
diff --git a/guest/trusty/security_vm/vm/Android.bp b/guest/trusty/security_vm/vm/Android.bp
index cc01d1c..35d7313 100644
--- a/guest/trusty/security_vm/vm/Android.bp
+++ b/guest/trusty/security_vm/vm/Android.bp
@@ -2,11 +2,6 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-soong_config_module_type_import {
-    from: "packages/modules/Virtualization/guest/trusty/common/Android.bp",
-    module_types: ["trusty_vm_avb_add_hash_footer"],
-}
-
 // - Trusty VM payloads on arm64 are pvmfw enabled
 //   AVF VM build system uses the raw binary image (:trusty_security_vm_unsigned),
 //   adds pvmfw footer and generates a pvmfw-compliant signed elf file)
@@ -115,7 +110,7 @@
 
 TRUSTY_SECURITY_VM_VERSION = 1
 
-trusty_vm_avb_add_hash_footer {
+avb_add_hash_footer {
     name: "trusty_security_vm_signed_bin",
     filename: "trusty_security_vm_signed.bin",
     partition_name: "boot",
diff --git a/guest/trusty/test_vm/Android.bp b/guest/trusty/test_vm/Android.bp
index 699b673..06b7d9d 100644
--- a/guest/trusty/test_vm/Android.bp
+++ b/guest/trusty/test_vm/Android.bp
@@ -20,6 +20,7 @@
 prebuilt_etc {
     name: "trusty_test_vm_config",
     enabled: false,
+    installable: false,
     arch: {
         arm64: {
             src: "trusty-test_vm-config-arm64.json",
@@ -33,38 +34,10 @@
     filename: "trusty-test_vm-config.json",
 }
 
-prebuilt_etc {
-    name: "trusty_vm_launcher_sh",
-    enabled: false,
-    arch: {
-        arm64: {
-            enabled: true,
-        },
-        x86_64: {
-            enabled: true,
-        },
-    },
-    src: "trusty-vm-launcher.sh",
-    filename: "trusty-vm-launcher.sh",
-}
-
-prebuilt_etc {
-    name: "trusty_wait_ready_sh",
-    enabled: false,
-    arch: {
-        arm64: {
-            enabled: true,
-        },
-        x86_64: {
-            enabled: true,
-        },
-    },
-    src: "trusty-wait-ready.sh",
-    filename: "trusty-wait-ready.sh",
-}
-
 sh_test {
-    name: "TrustyTestVM_UnitTests",
+    // VTS tests for all Trusted HALs defined
+    // under hardware/interfaces/security/see
+    name: "VtsSeeHalTargetTest",
     src: "trusty-ut-ctrl.sh",
     enabled: false,
     arch: {
@@ -81,9 +54,8 @@
         ":trusty_test_vm_config",
         "trusty-vm-launcher.sh",
         "trusty-wait-ready.sh",
+        ":trusty-ut-ctrl.system",
     ],
-    // TODO(b/378367793) use the AndroidTest.xml generated from the trusty
-    // test-map for test_vm payload
     test_config_template: "AndroidTest.xml",
     test_suites: [
         "general-tests",
diff --git a/guest/trusty/test_vm/AndroidTest.xml b/guest/trusty/test_vm/AndroidTest.xml
index 6fb0879..925b43c 100644
--- a/guest/trusty/test_vm/AndroidTest.xml
+++ b/guest/trusty/test_vm/AndroidTest.xml
@@ -23,6 +23,7 @@
     <!-- Target Preparers - Run Shell Commands -->
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
+        <option name="push-file" key="trusty-ut-ctrl.system" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl" />
         <option name="push-file" key="trusty-ut-ctrl.sh" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh" />
         <option name="push-file" key="trusty-vm-launcher.sh" value="/data/local/tmp/trusty_test_vm/trusty-vm-launcher.sh" />
         <option name="push-file" key="trusty-wait-ready.sh" value="/data/local/tmp/trusty_test_vm/trusty-wait-ready.sh" />
@@ -34,76 +35,16 @@
         <!--Note: the first run-command shall not expect the background command to have started -->
         <option name="run-bg-command" value="sh /data/local/tmp/trusty_test_vm/trusty-vm-launcher.sh" />
         <option name="run-command" value="sh /data/local/tmp/trusty_test_vm/trusty-wait-ready.sh" />
-        <option name="run-command" value="start storageproxyd_test_system" />
-        <option name="teardown-command" value="stop storageproxyd_test_system" />
-        <option name="teardown-command" value="killall storageproxyd_test_system || true" />
+        <option name="run-command" value="start storageproxyd_test_vm" />
+        <option name="teardown-command" value="stop storageproxyd_test_vm" />
+        <option name="teardown-command" value="killall storageproxyd_test_vm || true" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.binary.ExecutableTargetTest" >
         <option name="parse-gtest" value="true" />
         <option name="abort-if-device-lost" value="true"/>
         <option name="abort-if-root-lost" value="true" />
         <option name="per-binary-timeout" value="10m" />
-        <option name="test-command-line" key="com.android.kernel.mmutest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.mmutest"/>
-        <option name="test-command-line" key="com.android.kernel.threadtest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.threadtest"/>
-        <option name="test-command-line" key="com.android.kernel.iovectest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.iovectest"/>
-        <option name="test-command-line" key="com.android.kernel.timertest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.timertest"/>
-        <option name="test-command-line" key="com.android.kernel.btitest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.btitest"/>
-        <option name="test-command-line" key="com.android.kernel.cachetest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.cachetest"/>
-        <option name="test-command-line" key="com.android.kernel.console-unittest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.console-unittest"/>
-        <option name="test-command-line" key="com.android.kernel.dpc-unittest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.dpc-unittest"/>
-        <option name="test-command-line" key="com.android.kernel.iovectest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.iovectest"/>
-        <option name="test-command-line" key="com.android.kernel.ktipc.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.ktipc.test"/>
-        <option name="test-command-line" key="com.android.kernel.memorytest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.memorytest"/>
-        <option name="test-command-line" key="com.android.kernel.pactest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.pactest"/>
-        <option name="test-command-line" key="com.android.kernel.uirq-unittest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.uirq-unittest"/>
-        <option name="test-command-line" key="com.android.kernel.usercopy-unittest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.usercopy-unittest"/>
-        <option name="test-command-line" key="com.android.kernel.userscstest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.kernel.userscstest"/>
-        <option name="test-command-line" key="com.android.trusty.rust.keymint.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.keymint.test"/>
-        <option name="test-command-line" key="com.android.manifesttest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.manifesttest"/>
-        <option name="test-command-line" key="com.android.memref.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.memref.test"/>
-        <option name="test-command-line" key="com.android.trusty.rust.memref.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.memref.test"/>
-        <option name="test-command-line" key="com.android.timer-unittest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.timer-unittest"/>
-        <option name="test-command-line" key="com.android.ipc-unittest.ctrl" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.ipc-unittest.ctrl"/>
-        <!--option name="test-command-line" key="com.android.trusty.cfitest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.cfitest"/-->
-        <option name="test-command-line" key="com.android.trusty.crashtest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.crashtest"/>
-        <option name="test-command-line" key="com.android.trusty.dlmalloctest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.dlmalloctest"/>
-        <option name="test-command-line" key="com.android.trusty.hwaes.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.hwaes.test"/>
-        <option name="test-command-line" key="com.android.trusty.hwbcc.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.hwbcc.test"/>
-        <option name="test-command-line" key="com.android.trusty.rust.tipc.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.tipc.test"/>
-        <option name="test-command-line" key="com.android.trusty.rust.hwkey.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.hwkey.test"/>
-        <option name="test-command-line" key="com.android.trusty.rust.hwbcc.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.hwbcc.test"/>
-        <option name="test-command-line" key="com.android.trusty.rust.hwwsk.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.hwwsk.test"/>
-        <option name="test-command-line" key="com.android.trusty.rust.storage.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.storage.test"/>
-        <option name="test-command-line" key="com.android.trusty.smc.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.smc.test"/>
-        <option name="test-command-line" key="com.android.uirq-unittest" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.uirq-unittest"/>
-        <!-- Unit tests for legacy hwcrypto services - these hwcrypto services are used by hwcryptohal /-->
-        <option name="test-command-line" key="com.android.trusty.hwcrypto.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.hwcrypto.test"/>
-        <option name="test-command-line" key="com.android.trusty.hwrng.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.hwrng.test"/>
-        <!-- Unit tests for hwcryptohal (exposing IHWCryptoKey/IHWCryptoOperations AIDL) - Note: VTS tests are defined alongside the interface /-->
-        <option name="test-command-line" key="com.android.trusty.rust.hwcryptohalserver.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.hwcryptohalserver.test"/>
-        <option name="test-command-line" key="com.android.trusty.rust.hwcryptohal_common.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.hwcryptohal_common.test"/>
         <option name="test-command-line" key="com.android.trusty.rust.hwcryptokey_test.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.hwcryptokey_test.test"/>
-    </test>
-    <!-- disabling storage test as they are redundant with the VTS -->
-    <!--test class="com.android.tradefed.testtype.binary.ExecutableTargetTest" >
-        <option name="parse-gtest" value="true" />
-        <option name="abort-if-device-lost" value="true" />
-        <option name="abort-if-root-lost" value="true" />
-        <option name="per-binary-timeout" value="40m" />
         <option name="test-command-line" key="com.android.trusty.rust.storage_unittest_aidl.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.storage_unittest_aidl.test"/>
-        <option name="test-command-line" key="com.android.trusty.rust.storage_unittest_aidl_ns.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.storage_unittest_aidl_ns.test"/>
-        <option name="test-command-line" key="com.android.storage-unittest.tp" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.storage-unittest.tp"/>
-        <option name="test-command-line" key="com.android.storage-unittest.tdea" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.storage-unittest.tdea"/>
-        <option name="test-command-line" key="com.android.storage-unittest.nsp" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.storage-unittest.nsp"/>
-        <option name="test-command-line" key="com.android.storage-unittest.td" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.storage-unittest.td"/>
-        <option name="test-command-line" key="com.android.storage-unittest.tdp" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.storage-unittest.tdp"/>
-    </test-->
-    <test class="com.android.tradefed.testtype.binary.ExecutableTargetTest" >
-        <option name="parse-gtest" value="true" />
-        <!--option name="abort-if-device-lost" value="true" /-->
-        <!--option name="abort-if-root-lost" value="true" /-->
-        <option name="per-binary-timeout" value="40m" />
-        <option name="test-command-line" key="com.android.trusty.rust.binder_rpc_test.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.binder_rpc_test.test"/>
-        <option name="test-command-line" key="com.android.trusty.binder.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.binder.test"/>
     </test>
     </configuration>
diff --git a/guest/trusty/test_vm/README.md b/guest/trusty/test_vm/README.md
index 1673844..71368b5 100644
--- a/guest/trusty/test_vm/README.md
+++ b/guest/trusty/test_vm/README.md
@@ -1,7 +1,13 @@
-## Trusty test_vm
+## test_vm
 
-The Trusty test_vm ought to include the test TAs for different test types:
-- Trusty kernel OS test
-- Trusty IPC tests
-- Trusty user-space tests for service TAs (DT tree for example)
-- and most importantly the VTS tests TA for the trusted HALs.
+The Trusty test_vm ought to include the test TAs for the Trusted HALs,
+defined under hardware/interfaces/security/see:
+
+- AuthMgr
+- Secure Storage
+- HWCrypto
+- HDCP
+
+The Trusty test_vm also includes the VINTF test which allows to check the vendor
+support of the Trusted HALs (version and API hash), against the expected
+compatibility matrix for a given Android Dessert Release.
diff --git a/guest/trusty/test_vm/trusty-test_vm-config-arm64.json b/guest/trusty/test_vm/trusty-test_vm-config-arm64.json
index 18b275e..ac95aab 100644
--- a/guest/trusty/test_vm/trusty-test_vm-config-arm64.json
+++ b/guest/trusty/test_vm/trusty-test_vm-config-arm64.json
@@ -1,7 +1,8 @@
 {
     "name": "trusty_test_vm",
-    "kernel": "/data/local/tmp/trusty_test_vm/trusty_test_vm_.elf",
+    "kernel": "/data/local/tmp/trusty_test_vm/trusty_test_vm.elf",
     "platform_version": "1.0",
+    "cpu_topology": "one_cpu",
     "memory_mib": 112,
     "protected": true
 }
diff --git a/guest/trusty/test_vm/trusty-test_vm-config-x86_64.json b/guest/trusty/test_vm/trusty-test_vm-config-x86_64.json
index d491c3a..5ce65ba 100644
--- a/guest/trusty/test_vm/trusty-test_vm-config-x86_64.json
+++ b/guest/trusty/test_vm/trusty-test_vm-config-x86_64.json
@@ -2,5 +2,6 @@
     "name": "trusty_test_vm",
     "kernel": "/data/local/tmp/trusty_test_vm/trusty_test_vm.elf",
     "platform_version": "1.0",
+    "cpu_topology": "one_cpu",
     "memory_mib": 112
 }
diff --git a/guest/trusty/test_vm/trusty-ut-ctrl.sh b/guest/trusty/test_vm/trusty-ut-ctrl.sh
index 77a9459..2317496 100644
--- a/guest/trusty/test_vm/trusty-ut-ctrl.sh
+++ b/guest/trusty/test_vm/trusty-ut-ctrl.sh
@@ -14,4 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-/system_ext/bin/trusty-ut-ctrl.system -D VSOCK:${2:-$(getprop trusty.test_vm.vm_cid)}:1 $1
+/data/local/tmp/trusty_test_vm/trusty-ut-ctrl -D VSOCK:${2:-$(getprop trusty.test_vm.vm_cid)}:1 $1
diff --git a/guest/trusty/test_vm/vm/Android.bp b/guest/trusty/test_vm/vm/Android.bp
index 4f696b1..f978c92 100644
--- a/guest/trusty/test_vm/vm/Android.bp
+++ b/guest/trusty/test_vm/vm/Android.bp
@@ -2,11 +2,6 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-soong_config_module_type_import {
-    from: "packages/modules/Virtualization/guest/trusty/common/Android.bp",
-    module_types: ["trusty_vm_avb_add_hash_footer"],
-}
-
 prebuilt_etc {
     name: "trusty_test_vm_elf",
     system_ext_specific: true,
@@ -94,7 +89,7 @@
 
 TRUSTY_TEST_VM_VERSION = 1
 
-trusty_vm_avb_add_hash_footer {
+avb_add_hash_footer {
     name: "trusty_test_vm_signed_bin",
     filename: "trusty_test_vm_signed.bin",
     partition_name: "boot",
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..40050c0 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
@@ -288,17 +288,7 @@
                 percent = 50;
             }
 
-            synchronized (mLock) {
-                try {
-                    if (mVirtualMachine != null) {
-                        long bytes = mConfig.getMemoryBytes();
-                        mVirtualMachine.setMemoryBalloon(bytes * percent / 100);
-                    }
-                } catch (Exception e) {
-                    /* Caller doesn't want our exceptions. Log them instead. */
-                    Log.w(TAG, "TrimMemory failed: ", e);
-                }
-            }
+            setMemoryBalloonByPercent(percent);
         }
     }
 
@@ -1392,6 +1382,24 @@
         }
     }
 
+    /** @hide */
+    public void setMemoryBalloonByPercent(int percent) {
+        if (percent < 0 || percent > 100) {
+            Log.e(TAG, String.format("Invalid percent value: %d", percent));
+            return;
+        }
+        synchronized (mLock) {
+            try {
+                if (mVirtualMachine != null && mVirtualMachine.isMemoryBalloonEnabled()) {
+                    long bytes = mConfig.getMemoryBytes();
+                    mVirtualMachine.setMemoryBalloon(bytes * percent / 100);
+                }
+            } catch (RemoteException | ServiceSpecificException e) {
+                Log.w(TAG, "Cannot setMemoryBalloon", e);
+            }
+        }
+    }
+
     private boolean writeEventsToSock(ParcelFileDescriptor sock, List<InputEvent> evtList) {
         ByteBuffer byteBuffer =
                 ByteBuffer.allocate(8 /* (type: u16 + code: u16 + value: i32) */ * evtList.size());
@@ -1563,6 +1571,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 +1932,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 +1948,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 +1966,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 +2022,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/libservice_vm_requests/src/client_vm.rs b/libs/libservice_vm_requests/src/client_vm.rs
index 4e54510..8ad10fd 100644
--- a/libs/libservice_vm_requests/src/client_vm.rs
+++ b/libs/libservice_vm_requests/src/client_vm.rs
@@ -25,7 +25,7 @@
 use core::result;
 use coset::{AsCborValue, CborSerializable, CoseSign, CoseSign1};
 use der::{Decode, Encode};
-use diced_open_dice::{DiceArtifacts, HASH_SIZE};
+use diced_open_dice::DiceArtifacts;
 use log::{debug, error, info};
 use microdroid_kernel_hashes::{HASH_SIZE as KERNEL_HASH_SIZE, OS_HASHES};
 use service_vm_comm::{ClientVmAttestationParams, Csr, CsrPayload, RequestProcessingError};
@@ -252,7 +252,7 @@
     Ok(false)
 }
 
-fn expected_kernel_authority_hash(service_vm_entry: &Value) -> Result<[u8; HASH_SIZE]> {
+fn expected_kernel_authority_hash(service_vm_entry: &Value) -> Result<Vec<u8>> {
     let cose_sign1 = CoseSign1::from_cbor_value(service_vm_entry.clone())?;
     let payload = cose_sign1.payload.ok_or_else(|| {
         error!("No payload found in the service VM DICE chain entry");
diff --git a/libs/libservice_vm_requests/src/dice.rs b/libs/libservice_vm_requests/src/dice.rs
index ef9d894..ba67450 100644
--- a/libs/libservice_vm_requests/src/dice.rs
+++ b/libs/libservice_vm_requests/src/dice.rs
@@ -19,8 +19,8 @@
 use alloc::vec::Vec;
 use bssl_avf::{ed25519_verify, Digester, EcKey};
 use cbor_util::{
-    cbor_value_type, get_label_value, get_label_value_as_bytes, value_to_array,
-    value_to_byte_array, value_to_bytes, value_to_map, value_to_num, value_to_text,
+    cbor_value_type, get_label_value, get_label_value_as_bytes, value_to_array, value_to_bytes,
+    value_to_map, value_to_num, value_to_text,
 };
 use ciborium::value::Value;
 use core::cell::OnceCell;
@@ -31,7 +31,7 @@
     Algorithm, AsCborValue, CborSerializable, CoseError, CoseKey, CoseSign1, KeyOperation, KeyType,
     Label,
 };
-use diced_open_dice::{DiceMode, HASH_SIZE};
+use diced_open_dice::DiceMode;
 use log::{debug, error, info};
 use service_vm_comm::RequestProcessingError;
 
@@ -288,8 +288,8 @@
 pub(crate) struct DiceChainEntryPayload {
     pub(crate) subject_public_key: PublicKey,
     mode: DiceMode,
-    pub(crate) code_hash: [u8; HASH_SIZE],
-    pub(crate) authority_hash: [u8; HASH_SIZE],
+    pub(crate) code_hash: Vec<u8>,
+    pub(crate) authority_hash: Vec<u8>,
     config_descriptor: ConfigDescriptor,
 }
 
@@ -327,12 +327,12 @@
                 }
                 MODE => builder.mode(to_mode(value)?)?,
                 CODE_HASH => {
-                    let code_hash = value_to_byte_array(value, "DiceChainEntryPayload code_hash")?;
+                    let code_hash = value_to_bytes(value, "DiceChainEntryPayload code_hash")?;
                     builder.code_hash(code_hash)?;
                 }
                 AUTHORITY_HASH => {
                     let authority_hash =
-                        value_to_byte_array(value, "DiceChainEntryPayload authority_hash")?;
+                        value_to_bytes(value, "DiceChainEntryPayload authority_hash")?;
                     builder.authority_hash(authority_hash)?;
                 }
                 CONFIG_DESC => {
@@ -524,8 +524,8 @@
 struct PayloadBuilder {
     subject_public_key: OnceCell<PublicKey>,
     mode: OnceCell<DiceMode>,
-    code_hash: OnceCell<[u8; HASH_SIZE]>,
-    authority_hash: OnceCell<[u8; HASH_SIZE]>,
+    code_hash: OnceCell<Vec<u8>>,
+    authority_hash: OnceCell<Vec<u8>>,
     config_descriptor: OnceCell<ConfigDescriptor>,
 }
 
@@ -552,11 +552,11 @@
         set_once(&self.mode, mode, "mode")
     }
 
-    fn code_hash(&mut self, code_hash: [u8; HASH_SIZE]) -> Result<()> {
+    fn code_hash(&mut self, code_hash: Vec<u8>) -> Result<()> {
         set_once(&self.code_hash, code_hash, "code_hash")
     }
 
-    fn authority_hash(&mut self, authority_hash: [u8; HASH_SIZE]) -> Result<()> {
+    fn authority_hash(&mut self, authority_hash: Vec<u8>) -> Result<()> {
         set_once(&self.authority_hash, authority_hash, "authority_hash")
     }
 
@@ -570,7 +570,9 @@
         // the Open Profile for DICE spec.
         let mode = self.mode.take().unwrap_or(DiceMode::kDiceModeNotInitialized);
         let code_hash = take_value(&mut self.code_hash, "code_hash")?;
+        validate_hash_size(code_hash.len(), "code_hash")?;
         let authority_hash = take_value(&mut self.authority_hash, "authority_hash")?;
+        validate_hash_size(authority_hash.len(), "authority_hash")?;
         let config_descriptor = take_value(&mut self.config_descriptor, "config_descriptor")?;
         Ok(DiceChainEntryPayload {
             subject_public_key,
@@ -581,3 +583,18 @@
         })
     }
 }
+
+fn validate_hash_size(len: usize, name: &str) -> Result<()> {
+    // According to the Android Profile for DICE specification, SHA-256, SHA-384, and SHA-512
+    // are all acceptable hash algorithms.
+    const ACCEPTABLE_HASH_SIZES: [usize; 3] = [32, 48, 64];
+    if ACCEPTABLE_HASH_SIZES.contains(&len) {
+        Ok(())
+    } else {
+        error!(
+            "Invalid hash size for {}: {}. Acceptable hash sizes are: {:?}",
+            name, len, ACCEPTABLE_HASH_SIZES
+        );
+        Err(RequestProcessingError::InvalidDiceChain)
+    }
+}
diff --git a/libs/libvirtualization_jni/android_system_virtualmachine_VirtualMachine.cpp b/libs/libvirtualization_jni/android_system_virtualmachine_VirtualMachine.cpp
index 3f1d8a0..8452344 100644
--- a/libs/libvirtualization_jni/android_system_virtualmachine_VirtualMachine.cpp
+++ b/libs/libvirtualization_jni/android_system_virtualmachine_VirtualMachine.cpp
@@ -48,41 +48,40 @@
 } // 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)});
-
-    std::tuple args{env, vm.get(), port};
-    using Args = decltype(args);
-
-    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;
+    // TODO(b/398890208): make this memory owned by the connection
+    struct State {
+        JNIEnv *mEnv;
+        jobject mProvider;
+        jmethodID mMid;
     };
 
+    auto state = std::make_unique<State>(env, provider, mid);
+
+    using RequestFun = int (*)(void *);
+    RequestFun requestFunc = [](void *param) -> int {
+        State *state = static_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);
+    };
+
+    auto paramDeleteFunc = [](void *param) { delete static_cast<State *>(param); };
+
     RpcSessionHandle session;
     // We need a thread pool to be able to support linkToDeath, or callbacks
     // (b/268335700). These threads are currently created eagerly, so we don't
     // 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.release(),
+                                                      paramDeleteFunc);
     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..9d08ed7 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) {
@@ -2007,11 +2166,6 @@
         assumeFalse(
                 "Cuttlefish/Goldfish doesn't support device tree under /proc/device-tree",
                 isCuttlefish() || isGoldfish());
-        if (!isUpdatableVmSupported()) {
-            // TODO(b/389611249): Non protected VMs using legacy secret mechanisms do not reliably
-            // implement `AVmPayload_isNewInstance`.
-            assumeProtectedVM();
-        }
         VirtualMachine vm = forceCreateNewVirtualMachine("test_vm_a", config);
         TestResults testResults =
                 runVmTestService(
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");
         }
diff --git a/tests/vts/AndroidTest.xml b/tests/vts/AndroidTest.xml
index 6926f9f..a59f161 100644
--- a/tests/vts/AndroidTest.xml
+++ b/tests/vts/AndroidTest.xml
@@ -21,7 +21,7 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="vts_libavf_test->/data/nativetest64/vendor/vts_libavf_test" />
-        <option name="push" value="rialto.bin->/data/local/tmp/rialto.bin" />
+        <option name="push" value="rialto.bin->/data/nativetest64/vendor/rialto.bin" />
     </target_preparer>
 
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.ArchModuleController">
diff --git a/tests/vts/src/vts_libavf_test.rs b/tests/vts/src/vts_libavf_test.rs
index dc37aad..c13b510 100644
--- a/tests/vts/src/vts_libavf_test.rs
+++ b/tests/vts/src/vts_libavf_test.rs
@@ -75,7 +75,7 @@
 
 fn run_rialto(protected_vm: bool) -> Result<()> {
     let kernel_file =
-        File::open("/data/local/tmp/rialto.bin").context("Failed to open kernel file")?;
+        File::open("/data/nativetest64/vendor/rialto.bin").context("Failed to open kernel file")?;
     let kernel_fd = kernel_file.into_raw_fd();
 
     // SAFETY: AVirtualMachineRawConfig_create() isn't unsafe but rust_bindgen forces it to be seen