Merge "Add BccHandover to OwnedDiceArtifacts conversion function" into main
diff --git a/android/TerminalApp/Android.bp b/android/TerminalApp/Android.bp
index e1e236a..c18ada4 100644
--- a/android/TerminalApp/Android.bp
+++ b/android/TerminalApp/Android.bp
@@ -14,6 +14,7 @@
         // TODO(b/330257000): will be removed when binder RPC is used
         "android.system.virtualizationservice_internal-java",
         "androidx-constraintlayout_constraintlayout",
+        "androidx.navigation_navigation-fragment-ktx",
         "androidx.window_window",
         "androidx.work_work-runtime",
         "apache-commons-compress",
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.kt b/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.kt
index 7acc5f3..a4663c8 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.kt
@@ -116,11 +116,12 @@
         val roundedUpDesiredSize = roundUp(desiredSize)
         val curSize = getSize()
 
+        runE2fsck(rootPartition)
+
         if (roundedUpDesiredSize == curSize) {
             return roundedUpDesiredSize
         }
 
-        runE2fsck(rootPartition)
         if (roundedUpDesiredSize > curSize) {
             allocateSpace(rootPartition, roundedUpDesiredSize)
         }
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
index 487b7e8..e4eaecb 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
@@ -45,7 +45,7 @@
 import androidx.activity.result.ActivityResultCallback
 import androidx.activity.result.ActivityResultLauncher
 import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
-import androidx.lifecycle.ViewModelProvider
+import androidx.activity.viewModels
 import androidx.viewpager2.widget.ViewPager2
 import com.android.internal.annotations.VisibleForTesting
 import com.android.microdroid.test.common.DeviceProperties
@@ -72,11 +72,11 @@
     private lateinit var image: InstalledImage
     private lateinit var accessibilityManager: AccessibilityManager
     private lateinit var manageExternalStorageActivityResultLauncher: ActivityResultLauncher<Intent>
-    private lateinit var terminalViewModel: TerminalViewModel
     private lateinit var viewPager: ViewPager2
     private lateinit var tabLayout: TabLayout
     private lateinit var terminalTabAdapter: TerminalTabAdapter
     private val terminalInfo = CompletableFuture<TerminalInfo>()
+    private val terminalViewModel: TerminalViewModel by viewModels()
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -111,7 +111,6 @@
     }
 
     private fun initializeUi() {
-        terminalViewModel = ViewModelProvider(this)[TerminalViewModel::class.java]
         setContentView(R.layout.activity_headless)
         tabLayout = findViewById<TabLayout>(R.id.tab_layout)
         displayMenu = findViewById<Button>(R.id.display_button)
@@ -151,6 +150,20 @@
         TabLayoutMediator(tabLayout, viewPager, false, false) { _: TabLayout.Tab?, _: Int -> }
             .attach()
 
+        tabLayout.addOnTabSelectedListener(
+            object : TabLayout.OnTabSelectedListener {
+                override fun onTabSelected(tab: TabLayout.Tab?) {
+                    tab?.position?.let {
+                        terminalViewModel.selectedTabViewId = terminalTabAdapter.tabs[it].id
+                    }
+                }
+
+                override fun onTabUnselected(tab: TabLayout.Tab?) {}
+
+                override fun onTabReselected(tab: TabLayout.Tab?) {}
+            }
+        )
+
         addTerminalTab()
 
         tabAddButton?.setOnClickListener { addTerminalTab() }
@@ -160,7 +173,9 @@
         val tab = tabLayout.newTab()
         tab.setCustomView(R.layout.tabitem_terminal)
         viewPager.offscreenPageLimit += 1
-        terminalTabAdapter.addTab()
+        val tabId = terminalTabAdapter.addTab()
+        terminalViewModel.selectedTabViewId = tabId
+        terminalViewModel.terminalTabs[tabId] = tab
         tab.customView!!
             .findViewById<Button>(R.id.tab_close_button)
             .setOnClickListener(
@@ -223,9 +238,7 @@
                 "&fontWeightBold=" +
                 (FontStyle.FONT_WEIGHT_BOLD + config.fontWeightAdjustment) +
                 "&screenReaderMode=" +
-                accessibilityManager.isEnabled +
-                "&titleFixed=" +
-                getString(R.string.app_name))
+                accessibilityManager.isEnabled)
 
         try {
             return URL("https", ipAddress, port, "/$query")
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/TerminalTabFragment.kt b/android/TerminalApp/java/com/android/virtualization/terminal/TerminalTabFragment.kt
index 7e78235..a0c6e4e 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/TerminalTabFragment.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/TerminalTabFragment.kt
@@ -31,8 +31,9 @@
 import android.webkit.WebSettings
 import android.webkit.WebView
 import android.webkit.WebViewClient
+import android.widget.TextView
 import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
+import androidx.fragment.app.activityViewModels
 import com.android.system.virtualmachine.flags.Flags.terminalGuiSupport
 import com.android.virtualization.terminal.CertificateUtils.createOrGetKey
 import com.android.virtualization.terminal.CertificateUtils.writeCertificateToFile
@@ -45,7 +46,7 @@
     private lateinit var id: String
     private var certificates: Array<X509Certificate>? = null
     private var privateKey: PrivateKey? = null
-    private lateinit var terminalViewModel: TerminalViewModel
+    private val terminalViewModel: TerminalViewModel by activityViewModels()
 
     override fun onCreateView(
         inflater: LayoutInflater,
@@ -59,7 +60,6 @@
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
-        terminalViewModel = ViewModelProvider(this)[TerminalViewModel::class.java]
         terminalView = view.findViewById(R.id.webview)
         bootProgressView = view.findViewById(R.id.boot_progress)
         initializeWebView()
@@ -79,19 +79,46 @@
         terminalView.saveState(outState)
     }
 
+    override fun onResume() {
+        super.onResume()
+        updateFocus()
+    }
+
     private fun initializeWebView() {
         terminalView.settings.databaseEnabled = true
         terminalView.settings.domStorageEnabled = true
         terminalView.settings.javaScriptEnabled = true
         terminalView.settings.cacheMode = WebSettings.LOAD_DEFAULT
 
-        terminalView.webChromeClient = WebChromeClient()
+        terminalView.webChromeClient = TerminalWebChromeClient()
         terminalView.webViewClient = TerminalWebViewClient()
 
         (activity as MainActivity).modifierKeysController.addTerminalView(terminalView)
         terminalViewModel.terminalViews.add(terminalView)
     }
 
+    private inner class TerminalWebChromeClient : WebChromeClient() {
+        override fun onReceivedTitle(view: WebView?, title: String?) {
+            super.onReceivedTitle(view, title)
+            title?.let { originalTitle ->
+                val ttydSuffix = " | login -f droid (localhost)"
+                val displayedTitle =
+                    if (originalTitle.endsWith(ttydSuffix)) {
+                        // When the session is created. The format of the title will be
+                        // 'droid@localhost: ~ | login -f droid (localhost)'.
+                        originalTitle.dropLast(ttydSuffix.length)
+                    } else {
+                        originalTitle
+                    }
+
+                terminalViewModel.terminalTabs[id]
+                    ?.customView
+                    ?.findViewById<TextView>(R.id.tab_title)
+                    ?.text = displayedTitle
+            }
+        }
+    }
+
     private inner class TerminalWebViewClient : WebViewClient() {
         private var loadFailed = false
         private var requestId: Long = 0
@@ -148,6 +175,7 @@
                             terminalView.visibility = View.VISIBLE
                             terminalView.mapTouchToMouseEvent()
                             updateMainActivity()
+                            updateFocus()
                         }
                     }
                 },
@@ -189,6 +217,12 @@
         certificates = arrayOf<X509Certificate>(pke.certificate as X509Certificate)
     }
 
+    private fun updateFocus() {
+        if (terminalViewModel.selectedTabViewId == id) {
+            terminalView.requestFocus()
+        }
+    }
+
     companion object {
         const val TAG: String = "VmTerminalApp"
     }
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/TerminalViewModel.kt b/android/TerminalApp/java/com/android/virtualization/terminal/TerminalViewModel.kt
index 4a69f75..dd40143 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/TerminalViewModel.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/TerminalViewModel.kt
@@ -16,7 +16,10 @@
 package com.android.virtualization.terminal
 
 import androidx.lifecycle.ViewModel
+import com.google.android.material.tabs.TabLayout.Tab
 
 class TerminalViewModel : ViewModel() {
     val terminalViews: MutableSet<TerminalView> = mutableSetOf()
+    var selectedTabViewId: String? = null
+    val terminalTabs: MutableMap<String, Tab> = mutableMapOf()
 }
diff --git a/android/TerminalApp/res/layout/tabitem_terminal.xml b/android/TerminalApp/res/layout/tabitem_terminal.xml
index 92e3802..9eba163 100644
--- a/android/TerminalApp/res/layout/tabitem_terminal.xml
+++ b/android/TerminalApp/res/layout/tabitem_terminal.xml
@@ -25,7 +25,7 @@
       android:layout_alignParentStart="true"
       android:layout_alignParentTop="true"
       android:layout_toStartOf="@id/tab_close_button"
-      android:gravity="center"
+      android:gravity="center_vertical"
       android:padding="8dp"
       android:text="@string/tab_default_title"/>
 
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index 1c4c2eb..1e756eb 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -597,9 +597,10 @@
         config: &VirtualMachineConfig,
     ) -> binder::Result<(VmContext, Cid, PathBuf)> {
         const NUM_ATTEMPTS: usize = 5;
+        let name = get_name(config);
 
         for _ in 0..NUM_ATTEMPTS {
-            let vm_context = GLOBAL_SERVICE.allocateGlobalVmContext(requester_debug_pid)?;
+            let vm_context = GLOBAL_SERVICE.allocateGlobalVmContext(name, requester_debug_pid)?;
             let cid = vm_context.getCid()? as Cid;
             let temp_dir: PathBuf = vm_context.getTemporaryDirectory()?.into();
 
@@ -1053,6 +1054,14 @@
     }
 }
 
+/// Returns the name of the config
+fn get_name(config: &VirtualMachineConfig) -> &str {
+    match config {
+        VirtualMachineConfig::AppConfig(config) => &config.name,
+        VirtualMachineConfig::RawConfig(config) => &config.name,
+    }
+}
+
 fn extract_vendor_hashtree_digest(config: &VirtualMachineConfig) -> Result<Option<Vec<u8>>> {
     let VirtualMachineConfig::AppConfig(config) = config else {
         return Ok(None);
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
index 9f033b1..eb71028 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
@@ -19,6 +19,9 @@
 
 /** Information about a running VM, for debug purposes only. */
 parcelable VirtualMachineDebugInfo {
+    /** Name of the VM. */
+    String name;
+
     /** The CID assigned to the VM. */
     int cid;
 
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVfioHandler.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVfioHandler.aidl
index 2cf4efd..4ded2a9 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVfioHandler.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVfioHandler.aidl
@@ -16,7 +16,6 @@
 package android.system.virtualizationservice_internal;
 
 import android.system.virtualizationservice.AssignableDevice;
-import android.system.virtualizationservice.VirtualMachineDebugInfo;
 import android.system.virtualizationservice_internal.AtomVmBooted;
 import android.system.virtualizationservice_internal.AtomVmCreationRequested;
 import android.system.virtualizationservice_internal.AtomVmExited;
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
index 4f549cb..3d4a813 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
@@ -39,7 +39,7 @@
      * The resources will not be recycled as long as there is a strong reference
      * to the returned object.
      */
-    IGlobalVmContext allocateGlobalVmContext(int requesterDebugPid);
+    IGlobalVmContext allocateGlobalVmContext(String name, int requesterDebugPid);
 
     /** Forwards a VmBooted atom to statsd. */
     void atomVmBooted(in AtomVmBooted atom);
diff --git a/android/virtualizationservice/src/aidl.rs b/android/virtualizationservice/src/aidl.rs
index 62cede8..1646117 100644
--- a/android/virtualizationservice/src/aidl.rs
+++ b/android/virtualizationservice/src/aidl.rs
@@ -273,6 +273,7 @@
 
     fn allocateGlobalVmContext(
         &self,
+        name: &str,
         requester_debug_pid: i32,
     ) -> binder::Result<Strong<dyn IGlobalVmContext>> {
         check_manage_access()?;
@@ -281,7 +282,7 @@
         let requester_debug_pid = requester_debug_pid as pid_t;
         let state = &mut *self.state.lock().unwrap();
         state
-            .allocate_vm_context(requester_uid, requester_debug_pid)
+            .allocate_vm_context(name, requester_uid, requester_debug_pid)
             .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
     }
 
@@ -311,6 +312,7 @@
             .map(|vm| {
                 let vm = vm.lock().unwrap();
                 VirtualMachineDebugInfo {
+                    name: vm.name.clone(),
                     cid: vm.cid as i32,
                     temporaryDirectory: vm.get_temp_dir().to_string_lossy().to_string(),
                     requesterUid: vm.requester_uid as i32,
@@ -665,6 +667,8 @@
 
 #[derive(Debug, Default)]
 struct GlobalVmInstance {
+    /// Name of the VM
+    name: String,
     /// The unique CID assigned to the VM for vsock communication.
     cid: Cid,
     /// UID of the client who requested this VM instance.
@@ -760,6 +764,7 @@
 
     fn allocate_vm_context(
         &mut self,
+        name: &str,
         requester_uid: uid_t,
         requester_debug_pid: pid_t,
     ) -> Result<Strong<dyn IGlobalVmContext>> {
@@ -768,6 +773,7 @@
 
         let cid = self.get_next_available_cid()?;
         let instance = Arc::new(Mutex::new(GlobalVmInstance {
+            name: name.to_owned(),
             cid,
             requester_uid,
             requester_debug_pid,
diff --git a/build/debian/fai_config/scripts/AVF/20-useradd b/build/debian/fai_config/scripts/AVF/20-useradd
index b92648a..2289a2a 100755
--- a/build/debian/fai_config/scripts/AVF/20-useradd
+++ b/build/debian/fai_config/scripts/AVF/20-useradd
@@ -2,3 +2,7 @@
 
 $ROOTCMD useradd -m -u 1000 -N -G sudo,video,render -s /usr/bin/bash droid
 $ROOTCMD echo 'droid ALL=(ALL) NOPASSWD:ALL' >> $target/etc/sudoers
+$ROOTCMD cat >> $target/home/droid/.bashrc <<EOF
+# Show title of current running command
+trap 'echo -ne "\e]0;\$BASH_COMMAND\007"' DEBUG
+EOF
diff --git a/guest/microdroid_manager/microdroid_manager.rc b/guest/microdroid_manager/microdroid_manager.rc
index 9fa8a9d..48cc6d7 100644
--- a/guest/microdroid_manager/microdroid_manager.rc
+++ b/guest/microdroid_manager/microdroid_manager.rc
@@ -8,6 +8,7 @@
     # CAP_SYS_BOOT is required to exec kexecload from microdroid_manager
     # CAP_SETPCAP is required to allow microdroid_manager to drop capabilities
     #   before executing the payload
-    capabilities AUDIT_CONTROL SYS_ADMIN SYS_BOOT SETPCAP SETUID SETGID
+    # CAP_SYS_NICE is required for microdroid_manager to adjust priority of the payload
+    capabilities AUDIT_CONTROL SYS_ADMIN SYS_BOOT SETPCAP SETUID SETGID SYS_NICE
     user root
     socket vm_payload_service stream 0666 system system
diff --git a/guest/microdroid_manager/src/main.rs b/guest/microdroid_manager/src/main.rs
index 4537834..a95bcb2 100644
--- a/guest/microdroid_manager/src/main.rs
+++ b/guest/microdroid_manager/src/main.rs
@@ -710,7 +710,21 @@
     info!("notifying payload started");
     service.notifyPayloadStarted()?;
 
-    let exit_status = command.spawn()?.wait()?;
+    let mut payload_process = command.spawn().context("failed to spawn payload process")?;
+    info!("payload pid = {:?}", payload_process.id());
+
+    // SAFETY: setpriority doesn't take any pointers
+    unsafe {
+        let ret = libc::setpriority(libc::PRIO_PROCESS, payload_process.id(), -20);
+        if ret != 0 {
+            error!(
+                "failed to adjust priority of the payload: {:#?}",
+                std::io::Error::last_os_error()
+            );
+        }
+    }
+
+    let exit_status = payload_process.wait()?;
     match exit_status.code() {
         Some(exit_code) => Ok(exit_code),
         None => Err(match exit_status.signal() {
diff --git a/guest/trusty/test_vm/AndroidTest.xml b/guest/trusty/test_vm/AndroidTest.xml
index 925b43c..43d9ef8 100644
--- a/guest/trusty/test_vm/AndroidTest.xml
+++ b/guest/trusty/test_vm/AndroidTest.xml
@@ -15,10 +15,10 @@
   limitations under the License.
   -->
     <configuration description="Runs {MODULE}">
-    <!-- object type="module_controller" class="com.android.tradefed.testtype.suite.module.CommandSuccessModuleController" -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.CommandSuccessModuleController">
         <!--Skip the test when trusty VM is not enabled. -->
-        <!--option name="run-command" value="getprop trusty.test_vm.nonsecure_vm_ready | grep 1" /-->
-    <!--/object-->
+        <option name="run-command" value="getprop trusty.security_vm.enabled | grep 1" />
+    </object>
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
     <!-- Target Preparers - Run Shell Commands -->
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
@@ -38,13 +38,19 @@
         <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" />
+        <!--option name="teardown-command" value="rm -rf /data/local/trusty_test_vm"/-->
     </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.trusty.rust.authmgr_be_lib.test" value="/data/local/tmp/trusty_test_vm/trusty-ut-ctrl.sh com.android.trusty.rust.authmgr_be_lib.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"/>
         <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"/>
     </test>
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="directory-keys" value="/data/local/tmp/trusty_test_vm/logs" />
+        <option name="clean-up" value="false"/>
+    </metrics_collector>
     </configuration>
diff --git a/guest/trusty/test_vm/README.md b/guest/trusty/test_vm/README.md
index 71368b5..81382c5 100644
--- a/guest/trusty/test_vm/README.md
+++ b/guest/trusty/test_vm/README.md
@@ -11,3 +11,16 @@
 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.
+
+### instructions
+
+`atest -s <device-serial-port> VtsSeeHalTargetTest
+
+### test_vm console
+
+The test_vm console can be retrieved from `/data/local/tmp/trusty_test_vm/logs/console.log`.
+The script `trusty-vm-laucher.sh` uses `/apex/com.android.virt/bin/vm run` with the option
+`--console` to store the console log.
+
+This log can be consulted when the tests are running and will be uploaded
+by the Tradefed FilePullerLogCollector runner (see AndroidTest.xml).
diff --git a/guest/trusty/test_vm/TEST_MAPPING b/guest/trusty/test_vm/TEST_MAPPING
deleted file mode 100644
index aa9d65d..0000000
--- a/guest/trusty/test_vm/TEST_MAPPING
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "trusty_test_vm_presubmit": [
-  ],
-  "trusty_test_vm_postsubmit": [
-    {
-        "name": "TrustyTestVM_UnitTests"
-    }
-  ]
-}
diff --git a/guest/trusty/test_vm/trusty-vm-launcher.sh b/guest/trusty/test_vm/trusty-vm-launcher.sh
index cb8661f..079a66a 100755
--- a/guest/trusty/test_vm/trusty-vm-launcher.sh
+++ b/guest/trusty/test_vm/trusty-vm-launcher.sh
@@ -14,4 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-/apex/com.android.virt/bin/vm run /data/local/tmp/trusty_test_vm/trusty-test_vm-config.json
+mkdir -p /data/local/tmp/trusty_test_vm/logs || true
+/apex/com.android.virt/bin/vm run \
+   --console /data/local/tmp/trusty_test_vm/logs/console.log \
+   /data/local/tmp/trusty_test_vm/trusty-test_vm-config.json
diff --git a/guest/trusty/test_vm_os/AndroidTest.xml b/guest/trusty/test_vm_os/AndroidTest.xml
index be5c467..5adafff 100644
--- a/guest/trusty/test_vm_os/AndroidTest.xml
+++ b/guest/trusty/test_vm_os/AndroidTest.xml
@@ -15,10 +15,10 @@
   limitations under the License.
   -->
     <configuration description="Runs {MODULE}">
-    <!-- object type="module_controller" class="com.android.tradefed.testtype.suite.module.CommandSuccessModuleController" -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.CommandSuccessModuleController">
         <!--Skip the test when trusty VM is not enabled. -->
-        <!--option name="run-command" value="getprop trusty.test_vm.nonsecure_vm_ready | grep 1" /-->
-    <!--/object-->
+        <option name="run-command" value="getprop trusty.security_vm.enabled | grep 1" />
+    </object>
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
     <!-- Target Preparers - Run Shell Commands -->
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
@@ -38,6 +38,7 @@
         <option name="run-command" value="start storageproxyd_test_vm_os" />
         <option name="teardown-command" value="stop storageproxyd_test_vm_os" />
         <option name="teardown-command" value="killall storageproxyd_test_vm_os || true" />
+        <!--option name="teardown-command" value="rm -rf /data/local/trusty_test_vm_os"/-->
     </target_preparer>
     <test class="com.android.tradefed.testtype.binary.ExecutableTargetTest" >
         <option name="parse-gtest" value="true" />
@@ -79,4 +80,10 @@
         <option name="test-command-line" key="com.android.trusty.rust.binder_rpc_test.test" value="/data/local/tmp/trusty_test_vm_os/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_os/trusty-ut-ctrl.sh com.android.trusty.binder.test"/>
     </test>
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="directory-keys" value="/data/local/tmp/trusty_test_vm_os/logs" />
+        <option name="collect-on-run-ended-only" value="true" />
+        <option name="clean-up" value="true"/>
+        <option name="collect-on-run-ended-only" value="false" />
+    </metrics_collector>
     </configuration>
diff --git a/guest/trusty/test_vm_os/README.md b/guest/trusty/test_vm_os/README.md
index 4d65d9f..b37a4da 100644
--- a/guest/trusty/test_vm_os/README.md
+++ b/guest/trusty/test_vm_os/README.md
@@ -5,3 +5,6 @@
 - Trusty kernel OS test
 - Trusty/Binder IPC tests
 - Trusty user-space tests for service TAs (DT tree for example)
+
+
+see instructions at [test_vm/README.md](../test_vm/README.md)
diff --git a/guest/trusty/test_vm_os/TEST_MAPPING b/guest/trusty/test_vm_os/TEST_MAPPING
deleted file mode 100644
index 1506720..0000000
--- a/guest/trusty/test_vm_os/TEST_MAPPING
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "trusty_test_vm_presubmit": [
-  ],
-  "trusty_test_vm_postsubmit": [
-    {
-        "name": "TrustyVMOS_UnitTests"
-    }
-  ]
-}
diff --git a/guest/trusty/test_vm_os/trusty-vm-launcher.sh b/guest/trusty/test_vm_os/trusty-vm-launcher.sh
index 497b188..bc256ed 100755
--- a/guest/trusty/test_vm_os/trusty-vm-launcher.sh
+++ b/guest/trusty/test_vm_os/trusty-vm-launcher.sh
@@ -14,4 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-/apex/com.android.virt/bin/vm run /data/local/tmp/trusty_test_vm_os/trusty-test_vm-config.json
+mkdir -p /data/local/tmp/trusty_test_vm_os/logs || true
+/apex/com.android.virt/bin/vm run \
+   --console /data/local/tmp/trusty_test_vm_os/logs/console.log \
+   /data/local/tmp/trusty_test_vm_os/trusty-test_vm-config.json