Snap for 13204655 from cd03064b89f76b4ee41bcc0db282f9fb080d9fb8 to 25Q2-release

Change-Id: Ib1712afef21a380bbe3afa44166c43d2a04f0e5a
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/ModifierKeysController.kt b/android/TerminalApp/java/com/android/virtualization/terminal/ModifierKeysController.kt
index ed340d2..7c3eb69 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/ModifierKeysController.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/ModifierKeysController.kt
@@ -115,10 +115,12 @@
             activeTerminalView!!.hasFocus() &&
             !(activity.resources.configuration.keyboard == Configuration.KEYBOARD_QWERTY)
 
-    // If terminal's height is less than 30% of the screen height, we need to show modifier keys in
-    // a single line to save the vertical space
-    private fun needsKeysInSingleLine(): Boolean =
-        activeTerminalView!!.height.div(activity.window.decorView.height.toFloat()) < 0.3f
+    // If terminal's height including height of modifier keys is less than 40% of the screen
+    // height, we need to show modifier keys in a single line to save the vertical space
+    private fun needsKeysInSingleLine(): Boolean {
+        val keys = if (keysInSingleLine) keysSingleLine else keysDoubleLine
+        return activeTerminalView!!.height + keys.height < 0.4f * activity.window.decorView.height
+    }
 
     companion object {
         private val BTN_KEY_CODE_MAP =
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
index 345e8dd..94b7011 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -63,6 +63,7 @@
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.ExecutorService
 import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
 
 class VmLauncherService : Service() {
     inner class VmLauncherServiceBinder : android.os.Binder() {
@@ -246,6 +247,15 @@
                 },
                 executorService,
             )
+            .exceptionallyAsync(
+                { e ->
+                    Log.e(TAG, "Failed to start VM", e)
+                    resultReceiver!!.send(RESULT_ERROR, null)
+                    stopSelf()
+                    null
+                },
+                executorService,
+            )
 
         return START_NOT_STICKY
     }
@@ -282,6 +292,8 @@
                 }
             },
         )
+
+        resolvedInfo.orTimeout(VM_BOOT_TIMEOUT_SECONDS.toLong(), TimeUnit.SECONDS)
         return resolvedInfo
     }
 
@@ -467,6 +479,8 @@
         private const val KEY_TERMINAL_IPADDRESS = "address"
         private const val KEY_TERMINAL_PORT = "port"
 
+        private const val VM_BOOT_TIMEOUT_SECONDS = 20
+
         private const val INITIAL_MEM_BALLOON_PERCENT = 10
         private const val MAX_MEM_BALLOON_PERCENT = 50
         private const val MEM_BALLOON_INFLATE_INTERVAL_MILLIS = 60000L
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 5f81e90..15a4199 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -677,6 +677,10 @@
         }
     }
 
+    fn is_vm_running(&self) -> bool {
+        matches!(&*self.vm_state.lock().unwrap(), VmState::Running { .. })
+    }
+
     /// Returns the last reported state of the VM payload.
     pub fn payload_state(&self) -> PayloadState {
         *self.payload_state.lock().unwrap()
@@ -726,6 +730,9 @@
 
     /// Returns current virtio-balloon size.
     pub fn get_memory_balloon(&self) -> Result<u64, Error> {
+        if !self.is_vm_running() {
+            bail!("get_memory_balloon when VM is not running");
+        }
         if !self.balloon_enabled {
             bail!("virtio-balloon is not enabled");
         }
@@ -748,6 +755,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.is_vm_running() {
+            bail!("set_memory_balloon when VM is not running");
+        }
         if !self.balloon_enabled {
             bail!("virtio-balloon is not enabled");
         }
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index 9afbcc3..30624cd 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -41,7 +41,6 @@
 use alloc::boxed::Box;
 use bssl_avf::Digester;
 use diced_open_dice::{bcc_handover_parse, DiceArtifacts, DiceContext, Hidden, VM_KEY_ALGORITHM};
-use hypervisor_backends::get_mem_sharer;
 use libfdt::Fdt;
 use log::{debug, error, info, trace, warn};
 use pvmfw_avb::verify_payload;
@@ -99,15 +98,7 @@
     }
 
     let guest_page_size = verified_boot_data.page_size.unwrap_or(SIZE_4KB);
-    // TODO(ptosi): Cache the (single?) granule once, in vmbase.
-    let hyp_page_size = if let Some(mem_sharer) = get_mem_sharer() {
-        Some(mem_sharer.granule().map_err(|e| {
-            error!("Failed to get granule size: {e}");
-            RebootReason::InternalError
-        })?)
-    } else {
-        None
-    };
+    let hyp_page_size = hypervisor_backends::get_granule_size();
     let _ =
         sanitize_device_tree(untrusted_fdt, vm_dtbo, vm_ref_dt, guest_page_size, hyp_page_size)?;
     let fdt = untrusted_fdt; // DT has now been sanitized.
diff --git a/libs/libhypervisor_backends/src/hypervisor.rs b/libs/libhypervisor_backends/src/hypervisor.rs
index aa65133..7c274f5 100644
--- a/libs/libhypervisor_backends/src/hypervisor.rs
+++ b/libs/libhypervisor_backends/src/hypervisor.rs
@@ -152,3 +152,8 @@
 pub fn get_device_assigner() -> Option<&'static dyn DeviceAssigningHypervisor> {
     get_hypervisor().as_device_assigner()
 }
+
+/// Gets the unique hypervisor granule size, if any.
+pub fn get_granule_size() -> Option<usize> {
+    get_hypervisor().get_granule_size()
+}
diff --git a/libs/libhypervisor_backends/src/hypervisor/common.rs b/libs/libhypervisor_backends/src/hypervisor/common.rs
index bfe638f..f229e14 100644
--- a/libs/libhypervisor_backends/src/hypervisor/common.rs
+++ b/libs/libhypervisor_backends/src/hypervisor/common.rs
@@ -32,6 +32,13 @@
     fn as_device_assigner(&self) -> Option<&dyn DeviceAssigningHypervisor> {
         None
     }
+
+    /// Returns the granule used by all APIs (MEM_SHARE, MMIO_GUARD, device assignment, ...).
+    ///
+    /// If no such API is supported or if they support different granule sizes, returns None.
+    fn get_granule_size(&self) -> Option<usize> {
+        None
+    }
 }
 
 pub trait MmioGuardedHypervisor {
diff --git a/libs/libhypervisor_backends/src/hypervisor/geniezone.rs b/libs/libhypervisor_backends/src/hypervisor/geniezone.rs
index 76e010b..0913ff3 100644
--- a/libs/libhypervisor_backends/src/hypervisor/geniezone.rs
+++ b/libs/libhypervisor_backends/src/hypervisor/geniezone.rs
@@ -84,6 +84,10 @@
     fn as_mem_sharer(&self) -> Option<&dyn MemSharingHypervisor> {
         Some(self)
     }
+
+    fn get_granule_size(&self) -> Option<usize> {
+        <Self as MemSharingHypervisor>::granule(self).ok()
+    }
 }
 
 impl MmioGuardedHypervisor for GeniezoneHypervisor {
diff --git a/libs/libhypervisor_backends/src/hypervisor/kvm_aarch64.rs b/libs/libhypervisor_backends/src/hypervisor/kvm_aarch64.rs
index 233097b..f183107 100644
--- a/libs/libhypervisor_backends/src/hypervisor/kvm_aarch64.rs
+++ b/libs/libhypervisor_backends/src/hypervisor/kvm_aarch64.rs
@@ -90,6 +90,10 @@
     fn as_device_assigner(&self) -> Option<&dyn DeviceAssigningHypervisor> {
         Some(self)
     }
+
+    fn get_granule_size(&self) -> Option<usize> {
+        <Self as MemSharingHypervisor>::granule(self).ok()
+    }
 }
 
 impl MmioGuardedHypervisor for ProtectedKvmHypervisor {
diff --git a/libs/libhypervisor_backends/src/hypervisor/kvm_x86.rs b/libs/libhypervisor_backends/src/hypervisor/kvm_x86.rs
index 7f9ea4d..d72f788 100644
--- a/libs/libhypervisor_backends/src/hypervisor/kvm_x86.rs
+++ b/libs/libhypervisor_backends/src/hypervisor/kvm_x86.rs
@@ -84,6 +84,10 @@
     fn as_mem_sharer(&self) -> Option<&dyn MemSharingHypervisor> {
         Some(self)
     }
+
+    fn get_granule_size(&self) -> Option<usize> {
+        <Self as MemSharingHypervisor>::granule(self).ok()
+    }
 }
 
 macro_rules! vmcall {
diff --git a/libs/libhypervisor_backends/src/lib.rs b/libs/libhypervisor_backends/src/lib.rs
index 33dc5ad..3c81ac8 100644
--- a/libs/libhypervisor_backends/src/lib.rs
+++ b/libs/libhypervisor_backends/src/lib.rs
@@ -24,5 +24,6 @@
 
 pub use error::{Error, Result};
 pub use hypervisor::{
-    get_device_assigner, get_mem_sharer, get_mmio_guard, DeviceAssigningHypervisor, KvmError,
+    get_device_assigner, get_granule_size, get_mem_sharer, get_mmio_guard,
+    DeviceAssigningHypervisor, KvmError,
 };