Snap for 12722466 from c12dae24ce161b1002bff70a3c00f2d0784ba23a to 25Q1-release

Change-Id: Ib01001412dc6bb2fb984cc21e00e2303b21de00c
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.java b/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.java
index 623fbe4..f616b87 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstalledImage.java
@@ -98,7 +98,7 @@
     }
 
     public long getSize() throws IOException {
-        return roundUp(Files.size(mRootPartition));
+        return Files.size(mRootPartition);
     }
 
     public long getSmallestSizePossible() throws IOException {
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
index deef825..22f7c4e 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
@@ -505,21 +505,15 @@
         String prefKey = getString(R.string.preference_file_key);
         String key = getString(R.string.preference_disk_size_key);
         SharedPreferences sharedPref = this.getSharedPreferences(prefKey, Context.MODE_PRIVATE);
-        long newSize = sharedPref.getLong(key, -1);
-
-        // No preferred size. Don't resize.
-        if (newSize == -1) {
-            return;
-        }
-
         try {
+            // Use current size as default value to ensure if its size is multiple of 4096
+            long newSize = sharedPref.getLong(key, image.getSize());
             Log.d(TAG, "Resizing disk to " + newSize + " bytes");
             newSize = image.resize(newSize);
+            sharedPref.edit().putLong(key, newSize).apply();
         } catch (IOException e) {
             Log.e(TAG, "Failed to resize disk", e);
             return;
         }
-
-        sharedPref.edit().putLong(key, newSize).apply();
     }
 }
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsActivity.kt
index 73bb0b9..6a30971 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsActivity.kt
@@ -16,6 +16,10 @@
 package com.android.virtualization.terminal
 
 import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.view.Window
+import android.view.WindowManager
 import androidx.appcompat.app.AppCompatActivity
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
@@ -28,6 +32,12 @@
         super.onCreate(savedInstanceState)
         setContentView(R.layout.settings_activity)
 
+        Handler(Looper.getMainLooper()).post {
+            val lp: WindowManager.LayoutParams = getWindow().getAttributes()
+            lp.accessibilityTitle = getString(R.string.action_settings)
+            getWindow().setAttributes(lp)
+        }
+
         val toolbar: MaterialToolbar = findViewById(R.id.settings_toolbar)
         setSupportActionBar(toolbar)
         val settingsItems = arrayOf(
@@ -56,4 +66,4 @@
         recyclerView.layoutManager = LinearLayoutManager(this)
         recyclerView.adapter = settingsListItemAdapter
     }
-}
\ No newline at end of file
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
index 442f896..d9086a4 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
@@ -17,23 +17,36 @@
 
 import android.content.Context
 import android.content.Intent
+import android.icu.text.MeasureFormat
+import android.icu.text.NumberFormat
+import android.icu.util.Measure
+import android.icu.util.MeasureUnit
 import android.os.Bundle
 import android.os.FileUtils
+import android.os.Handler
+import android.os.Looper
 import android.text.SpannableString
 import android.text.Spanned
 import android.text.TextUtils
-import android.text.format.Formatter
 import android.text.style.RelativeSizeSpan
+import android.widget.SeekBar
+import android.view.Window
+import android.view.WindowManager
 import android.widget.TextView
 import androidx.appcompat.app.AppCompatActivity
 import androidx.core.view.isVisible
 import com.google.android.material.button.MaterialButton
-import com.google.android.material.slider.Slider
+import java.util.Locale
 import java.util.regex.Pattern
 
 class SettingsDiskResizeActivity : AppCompatActivity() {
-    private val maxDiskSizeMb: Float = (16 shl 10).toFloat()
-    private val numberPattern: Pattern = Pattern.compile("[\\d]*[\\٫.,]?[\\d]+");
+    private val maxDiskSizeMb: Long = 16 shl 10
+    private val numberPattern: Pattern = Pattern.compile("[\\d]*[\\٫.,]?[\\d]+")
+
+    private var diskSizeStepMb: Long = 0
+    private var diskSizeMb: Long = 0
+    private lateinit var diskSizeText: TextView
+    private lateinit var diskSizeSlider: SeekBar
 
     private fun bytesToMb(bytes: Long): Long {
         return bytes shr 20;
@@ -43,68 +56,80 @@
         return bytes shl 20;
     }
 
+    private fun mbToProgress(bytes: Long): Int {
+        return (bytes / diskSizeStepMb).toInt()
+    }
+
+    private fun progressToMb(progress: Int): Long {
+        return progress * diskSizeStepMb
+    }
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.settings_disk_resize)
+
+        Handler(Looper.getMainLooper()).post {
+            val lp: WindowManager.LayoutParams = getWindow().getAttributes()
+            lp.accessibilityTitle = getString(R.string.settings_disk_resize_title)
+            getWindow().setAttributes(lp)
+        }
+
+        diskSizeStepMb = 1L shl resources.getInteger(R.integer.disk_size_round_up_step_size_in_mb)
+
         val sharedPref =
             this.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE)
-        var diskSizeMb =
-            bytesToMb(
-                sharedPref.getLong(
+        diskSizeMb = bytesToMb(sharedPref.getLong(
                     getString(R.string.preference_disk_size_key),
-                    0
-                )
-            ).toFloat();
+                    /* defValue= */ 0))
         val image = InstalledImage.getDefault(this)
         val minDiskSizeMb =
-            bytesToMb(image.getSmallestSizePossible()).toFloat()
+            bytesToMb(image.getSmallestSizePossible())
                 .coerceAtMost(diskSizeMb)
 
-        val diskSizeText = findViewById<TextView>(R.id.settings_disk_resize_resize_gb_assigned)
+        diskSizeText = findViewById<TextView>(R.id.settings_disk_resize_resize_gb_assigned)!!
         val diskMaxSizeText = findViewById<TextView>(R.id.settings_disk_resize_resize_gb_max)
         diskMaxSizeText.text = getString(R.string.settings_disk_resize_resize_gb_max_format,
-            localizedFileSize(maxDiskSizeMb)
+            localizedFileSize(maxDiskSizeMb, /* isShort= */ true)
         );
 
-        val diskSizeSlider = findViewById<Slider>(R.id.settings_disk_resize_disk_size_slider)
-        diskSizeSlider.setValueTo(maxDiskSizeMb)
+        diskSizeSlider = findViewById<SeekBar>(R.id.settings_disk_resize_disk_size_slider)!!
         val cancelButton = findViewById<MaterialButton>(R.id.settings_disk_resize_cancel_button)
         val resizeButton = findViewById<MaterialButton>(R.id.settings_disk_resize_resize_button)
-        diskSizeSlider.valueFrom = minDiskSizeMb
-        diskSizeSlider.valueTo = maxDiskSizeMb
-        diskSizeSlider.value = diskSizeMb
-        diskSizeSlider.stepSize =
-            resources.getInteger(R.integer.disk_size_round_up_step_size_in_mb).toFloat()
-        diskSizeSlider.setLabelFormatter { value: Float ->
-            localizedFileSize(value)
-        }
-        diskSizeText.text = enlargeFontOfNumber(
-            getString(R.string.settings_disk_resize_resize_gb_assigned_format,
-                localizedFileSize(diskSizeMb)
-            )
-        )
+        diskSizeSlider.min = mbToProgress(minDiskSizeMb)
+        diskSizeSlider.max = mbToProgress(maxDiskSizeMb)
+        diskSizeSlider.progress = mbToProgress(diskSizeMb)
+        updateSliderText(diskSizeMb)
 
-        diskSizeSlider.addOnChangeListener { _, value, _ ->
-            diskSizeText.text = enlargeFontOfNumber(
-                getString(R.string.settings_disk_resize_resize_gb_assigned_format,
-                localizedFileSize(value)))
-            cancelButton.isVisible = true
-            resizeButton.isVisible = true
-        }
+        diskSizeSlider.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+            override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+                updateSliderText(progressToMb(progress))
+                cancelButton.isVisible = true
+                resizeButton.isVisible = true
+            }
+
+            override fun onStartTrackingTouch(seekBar: SeekBar?) {
+                // no-op
+            }
+
+            override fun onStopTrackingTouch(seekBar: SeekBar?) {
+                // no-op
+            }
+        })
+
         cancelButton.setOnClickListener {
-            diskSizeSlider.value = diskSizeMb
+            diskSizeSlider.progress = mbToProgress(diskSizeMb)
             cancelButton.isVisible = false
             resizeButton.isVisible = false
         }
 
         resizeButton.setOnClickListener {
-            diskSizeMb = diskSizeSlider.value
+            diskSizeMb = progressToMb(diskSizeSlider.progress)
             cancelButton.isVisible = false
             resizeButton.isVisible = false
             val editor = sharedPref.edit()
             editor.putLong(
                 getString(R.string.preference_disk_size_key),
-                mbToBytes(diskSizeMb.toLong())
+                mbToBytes(diskSizeMb)
             )
             editor.apply()
 
@@ -117,11 +142,28 @@
         }
     }
 
-    fun localizedFileSize(sizeMb: Float): String {
-        // formatShortFileSize() uses SI unit (i.e. kB = 1000 bytes),
-        // so covert sizeMb with "MB" instead of "MIB".
-        val bytes = FileUtils.parseSize(sizeMb.toLong().toString() + "MB")
-        return Formatter.formatShortFileSize(this, bytes)
+    fun updateSliderText(sizeMb: Long) {
+        diskSizeText.text = enlargeFontOfNumber(
+            getString(R.string.settings_disk_resize_resize_gb_assigned_format,
+                localizedFileSize(sizeMb, /* isShort= */ true)))
+        diskSizeSlider.stateDescription =
+            getString(R.string.settings_disk_resize_resize_gb_assigned_format,
+                localizedFileSize(sizeMb, /* isShort= */ false))
+    }
+
+    fun localizedFileSize(sizeMb: Long, isShort: Boolean): String {
+        val sizeGb = sizeMb / (1 shl 10).toFloat()
+        val measure = Measure(sizeGb, MeasureUnit.GIGABYTE)
+
+        val localeFromContext: Locale = resources.configuration.locales[0]
+        val numberFormatter: NumberFormat = NumberFormat.getInstance(localeFromContext)
+        numberFormatter.minimumFractionDigits = 1
+        numberFormatter.maximumFractionDigits = 1
+
+        val formatWidth = if (isShort) MeasureFormat.FormatWidth.SHORT else MeasureFormat.FormatWidth.WIDE
+        val measureFormat: MeasureFormat =
+            MeasureFormat.getInstance(localeFromContext, formatWidth, numberFormatter)
+        return measureFormat.format(measure)
     }
 
     fun enlargeFontOfNumber(summary: CharSequence): CharSequence {
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
index a332a9d..0377de4 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
@@ -15,52 +15,48 @@
  */
 package com.android.virtualization.terminal
 
-import android.Manifest
-import android.app.Notification
-import android.app.NotificationManager
-import android.app.PendingIntent
 import android.content.Context
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.graphics.drawable.Icon
+import android.content.SharedPreferences
 import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.view.Window
+import android.view.WindowManager
 import androidx.appcompat.app.AppCompatActivity
-import androidx.core.app.ActivityCompat
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
-import com.android.virtualization.terminal.MainActivity.TAG
 
 class SettingsPortForwardingActivity : AppCompatActivity() {
+    private lateinit var mSharedPref: SharedPreferences
+    private lateinit var mAdapter: SettingsPortForwardingAdapter
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.settings_port_forwarding)
 
-        val settingsPortForwardingItems = ArrayList<SettingsPortForwardingItem>()
-
-        val sharedPref = this.getSharedPreferences(
-            getString(R.string.preference_file_key), Context.MODE_PRIVATE
-        )
-
-        val ports =
-            sharedPref.getStringSet(
-                getString(R.string.preference_forwarding_ports),
-                HashSet<String>()
-            )
-
-        for (port in ports!!.sortedWith(compareBy( { it.toInt() } ))) {
-            val enabled =
-                sharedPref.getBoolean(
-                    getString(R.string.preference_forwarding_port_is_enabled) + port,
-                    false
-                )
-            settingsPortForwardingItems.add(SettingsPortForwardingItem(port.toInt(), enabled));
+        Handler(Looper.getMainLooper()).post {
+            val lp: WindowManager.LayoutParams = getWindow().getAttributes()
+            lp.accessibilityTitle = getString(R.string.settings_port_forwarding_title)
+            getWindow().setAttributes(lp)
         }
 
-        val settingsPortForwardingAdapter =
-            SettingsPortForwardingAdapter(settingsPortForwardingItems, this)
+        mSharedPref =
+            this.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE)
+
+        mAdapter = SettingsPortForwardingAdapter(mSharedPref, this)
 
         val recyclerView: RecyclerView = findViewById(R.id.settings_port_forwarding_recycler_view)
         recyclerView.layoutManager = LinearLayoutManager(this)
-        recyclerView.adapter = settingsPortForwardingAdapter
+        recyclerView.adapter = mAdapter
+    }
+
+    override fun onResume() {
+        super.onResume()
+        mSharedPref.registerOnSharedPreferenceChangeListener(mAdapter)
+    }
+
+    override fun onPause() {
+        mSharedPref.unregisterOnSharedPreferenceChangeListener(mAdapter)
+        super.onPause()
     }
 }
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingAdapter.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingAdapter.kt
index 904f7f6..c3501d4 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingAdapter.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingAdapter.kt
@@ -22,13 +22,66 @@
 import android.view.ViewGroup
 import android.widget.TextView
 import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.SortedList
+import androidx.recyclerview.widget.SortedListAdapterCallback
 import com.google.android.material.materialswitch.MaterialSwitch
 
 class SettingsPortForwardingAdapter(
-    private val dataSet: ArrayList<SettingsPortForwardingItem>,
-    private val context: Context
+    private val sharedPref: SharedPreferences?,
+    private val context: Context,
 ) :
-    RecyclerView.Adapter<SettingsPortForwardingAdapter.ViewHolder>() {
+    RecyclerView.Adapter<SettingsPortForwardingAdapter.ViewHolder>(),
+    SharedPreferences.OnSharedPreferenceChangeListener {
+
+    private var mItems: SortedList<SettingsPortForwardingItem>
+
+    init {
+        mItems =
+            SortedList(
+                SettingsPortForwardingItem::class.java,
+                object : SortedListAdapterCallback<SettingsPortForwardingItem>(this) {
+                    override fun compare(
+                        o1: SettingsPortForwardingItem,
+                        o2: SettingsPortForwardingItem,
+                    ): Int {
+                        return o1.port - o2.port
+                    }
+
+                    override fun areContentsTheSame(
+                        o1: SettingsPortForwardingItem,
+                        o2: SettingsPortForwardingItem,
+                    ): Boolean {
+                        return o1.port == o2.port && o1.enabled == o2.enabled
+                    }
+
+                    override fun areItemsTheSame(
+                        o1: SettingsPortForwardingItem,
+                        o2: SettingsPortForwardingItem,
+                    ): Boolean {
+                        return o1.port == o2.port
+                    }
+                },
+            )
+        mItems.addAll(getCurrentSettingsPortForwardingItem())
+    }
+
+    private fun getCurrentSettingsPortForwardingItem(): ArrayList<SettingsPortForwardingItem> {
+        val items = ArrayList<SettingsPortForwardingItem>()
+        val ports =
+            sharedPref!!.getStringSet(
+                context.getString(R.string.preference_forwarding_ports),
+                HashSet<String>(),
+            )
+        for (port in ports!!) {
+            val enabled =
+                sharedPref.getBoolean(
+                    context.getString(R.string.preference_forwarding_port_is_enabled) + port,
+                    false,
+                )
+            items.add(SettingsPortForwardingItem(port.toInt(), enabled))
+        }
+        return items
+    }
 
     class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
         val enabledSwitch: MaterialSwitch =
@@ -43,8 +96,9 @@
     }
 
     override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
-        viewHolder.port.text = dataSet[position].port.toString()
-        viewHolder.enabledSwitch.isChecked = dataSet[position].enabled
+        viewHolder.port.text = mItems[position].port.toString()
+        viewHolder.enabledSwitch.contentDescription = viewHolder.port.text
+        viewHolder.enabledSwitch.isChecked = mItems[position].enabled
         viewHolder.enabledSwitch.setOnCheckedChangeListener { _, isChecked ->
             val sharedPref: SharedPreferences = context.getSharedPreferences(
                 context.getString(R.string.preference_file_key), Context.MODE_PRIVATE
@@ -58,5 +112,14 @@
         }
     }
 
-    override fun getItemCount() = dataSet.size
-}
\ No newline at end of file
+    override fun getItemCount() = mItems.size()
+
+    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
+        if (
+            key == context.getString(R.string.preference_forwarding_ports) ||
+                key!!.startsWith(context.getString(R.string.preference_forwarding_port_is_enabled))
+        ) {
+            mItems.replaceAll(getCurrentSettingsPortForwardingItem())
+        }
+    }
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsRecoveryActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsRecoveryActivity.kt
index 00730ff..3adeece 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsRecoveryActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsRecoveryActivity.kt
@@ -17,8 +17,12 @@
 
 import android.content.Intent
 import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
 import android.util.Log
 import android.view.View
+import android.view.Window
+import android.view.WindowManager
 import androidx.appcompat.app.AppCompatActivity
 import androidx.core.view.isVisible
 import androidx.lifecycle.lifecycleScope
@@ -36,6 +40,13 @@
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.settings_recovery)
+
+        Handler(Looper.getMainLooper()).post {
+            val lp: WindowManager.LayoutParams = getWindow().getAttributes()
+            lp.accessibilityTitle = getString(R.string.settings_recovery_title)
+            getWindow().setAttributes(lp)
+        }
+
         val resetCard = findViewById<MaterialCardView>(R.id.settings_recovery_reset_card)
         resetCard.setOnClickListener {
             var backupRootfs = false
diff --git a/android/TerminalApp/res/layout/settings_disk_resize.xml b/android/TerminalApp/res/layout/settings_disk_resize.xml
index 7b8b9fc..fb7f85b 100644
--- a/android/TerminalApp/res/layout/settings_disk_resize.xml
+++ b/android/TerminalApp/res/layout/settings_disk_resize.xml
@@ -57,12 +57,11 @@
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintBottom_toTopOf="@+id/settings_disk_resize_disk_size_slider"/>
 
-        <com.google.android.material.slider.Slider
+        <SeekBar
             android:id="@+id/settings_disk_resize_disk_size_slider"
-            android:layout_height="wrap_content"
+            android:layout_height="40dp"
             android:layout_width="match_parent"
             android:layout_marginBottom="36dp"
-            app:tickVisible="false"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent" />
 
diff --git a/android/TerminalApp/res/layout/settings_list_item.xml b/android/TerminalApp/res/layout/settings_list_item.xml
index 645efbb..ce595ff 100644
--- a/android/TerminalApp/res/layout/settings_list_item.xml
+++ b/android/TerminalApp/res/layout/settings_list_item.xml
@@ -22,7 +22,7 @@
     app:cardCornerRadius="28dp"
     app:checkedIcon="@null"
     android:focusable="true"
-    android:checkable="true"
+    android:longClickable="false"
     android:layout_height="wrap_content"
     android:layout_width="match_parent">
 
@@ -66,4 +66,4 @@
             app:layout_constraintStart_toEndOf="@id/settings_list_item_icon"
             app:layout_constraintEnd_toEndOf="parent" />
     </androidx.constraintlayout.widget.ConstraintLayout>
-</com.google.android.material.card.MaterialCardView>
\ No newline at end of file
+</com.google.android.material.card.MaterialCardView>
diff --git a/android/TerminalApp/res/layout/settings_recovery.xml b/android/TerminalApp/res/layout/settings_recovery.xml
index d33f9a3..3ace35c 100644
--- a/android/TerminalApp/res/layout/settings_recovery.xml
+++ b/android/TerminalApp/res/layout/settings_recovery.xml
@@ -53,7 +53,7 @@
                 app:cardCornerRadius="0dp"
                 app:checkedIcon="@null"
                 android:focusable="true"
-                android:checkable="true"
+                android:longClickable="false"
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent">
                 <androidx.constraintlayout.widget.ConstraintLayout
@@ -91,7 +91,7 @@
                 app:cardCornerRadius="0dp"
                 app:checkedIcon="@null"
                 android:focusable="true"
-                android:checkable="true"
+                android:longClickable="false"
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent">
                 <androidx.constraintlayout.widget.ConstraintLayout
diff --git a/android/compos_verify/verify.rs b/android/compos_verify/verify.rs
index a3f18d5..b94ebbc 100644
--- a/android/compos_verify/verify.rs
+++ b/android/compos_verify/verify.rs
@@ -124,6 +124,7 @@
         &idsig_manifest_ext_apk,
         &VmParameters {
             name: String::from("ComposVerify"),
+            os: String::from("microdroid"),
             cpu_topology: VmCpuTopology::OneCpu, // This VM runs very little work at boot
             debug_mode: args.debug,
             ..Default::default()
diff --git a/android/composd/aidl/android/system/composd/IIsolatedCompilationService.aidl b/android/composd/aidl/android/system/composd/IIsolatedCompilationService.aidl
index dde75e1..3748899 100644
--- a/android/composd/aidl/android/system/composd/IIsolatedCompilationService.aidl
+++ b/android/composd/aidl/android/system/composd/IIsolatedCompilationService.aidl
@@ -48,5 +48,6 @@
      * callback, unless the returned ICompilationTask is cancelled. The caller should maintain
      * a reference to the ICompilationTask until compilation completes or is cancelled.
      */
-    ICompilationTask startTestCompile(ApexSource apexSource, ICompilationTaskCallback callback);
+    ICompilationTask startTestCompile(
+            ApexSource apexSource, ICompilationTaskCallback callback, String os);
 }
diff --git a/android/composd/src/instance_manager.rs b/android/composd/src/instance_manager.rs
index 9e94035..cb1f7e4 100644
--- a/android/composd/src/instance_manager.rs
+++ b/android/composd/src/instance_manager.rs
@@ -46,11 +46,12 @@
         self.start_instance(CURRENT_INSTANCE_DIR, vm_parameters)
     }
 
-    pub fn start_test_instance(&self, prefer_staged: bool) -> Result<CompOsInstance> {
+    pub fn start_test_instance(&self, prefer_staged: bool, os: &str) -> Result<CompOsInstance> {
         let mut vm_parameters = new_vm_parameters()?;
         vm_parameters.name = String::from("ComposdTest");
         vm_parameters.debug_mode = true;
         vm_parameters.prefer_staged = prefer_staged;
+        vm_parameters.os = os.to_owned();
         self.start_instance(TEST_INSTANCE_DIR, vm_parameters)
     }
 
diff --git a/android/composd/src/service.rs b/android/composd/src/service.rs
index 49cfd3a..3cc40af 100644
--- a/android/composd/src/service.rs
+++ b/android/composd/src/service.rs
@@ -60,6 +60,7 @@
         &self,
         apex_source: ApexSource,
         callback: &Strong<dyn ICompilationTaskCallback>,
+        os: &str,
     ) -> binder::Result<Strong<dyn ICompilationTask>> {
         check_permissions()?;
         let prefer_staged = match apex_source {
@@ -67,7 +68,7 @@
             ApexSource::PreferStaged => true,
             _ => unreachable!("Invalid ApexSource {:?}", apex_source),
         };
-        to_binder_result(self.do_start_test_compile(prefer_staged, callback))
+        to_binder_result(self.do_start_test_compile(prefer_staged, callback, os))
     }
 }
 
@@ -93,9 +94,12 @@
         &self,
         prefer_staged: bool,
         callback: &Strong<dyn ICompilationTaskCallback>,
+        os: &str,
     ) -> Result<Strong<dyn ICompilationTask>> {
-        let comp_os =
-            self.instance_manager.start_test_instance(prefer_staged).context("Starting CompOS")?;
+        let comp_os = self
+            .instance_manager
+            .start_test_instance(prefer_staged, os)
+            .context("Starting CompOS")?;
 
         let target_dir_name = TEST_ARTIFACTS_SUBDIR.to_owned();
         let task = OdrefreshTask::start(
diff --git a/android/composd_cmd/composd_cmd.rs b/android/composd_cmd/composd_cmd.rs
index 6d096a1..6281bd0 100644
--- a/android/composd_cmd/composd_cmd.rs
+++ b/android/composd_cmd/composd_cmd.rs
@@ -46,6 +46,10 @@
         /// If any APEX is staged, prefer the staged version.
         #[clap(long)]
         prefer_staged: bool,
+
+        /// OS for the VM.
+        #[clap(long, default_value = "microdroid")]
+        os: String,
     },
 }
 
@@ -56,7 +60,7 @@
 
     match action {
         Actions::StagedApexCompile {} => run_staged_apex_compile()?,
-        Actions::TestCompile { prefer_staged } => run_test_compile(prefer_staged)?,
+        Actions::TestCompile { prefer_staged, os } => run_test_compile(prefer_staged, &os)?,
     }
 
     println!("All Ok!");
@@ -116,9 +120,9 @@
     run_async_compilation(|service, callback| service.startStagedApexCompile(callback))
 }
 
-fn run_test_compile(prefer_staged: bool) -> Result<()> {
+fn run_test_compile(prefer_staged: bool, os: &str) -> Result<()> {
     let apex_source = if prefer_staged { ApexSource::PreferStaged } else { ApexSource::NoStaged };
-    run_async_compilation(|service, callback| service.startTestCompile(apex_source, callback))
+    run_async_compilation(|service, callback| service.startTestCompile(apex_source, callback, os))
 }
 
 fn run_async_compilation<F>(start_compile_fn: F) -> Result<()>
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index b0944fc..46f4e80 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -1022,6 +1022,13 @@
         command.arg("--params").arg("console=hvc0");
     }
 
+    // Move the PCI MMIO regions to near the end of the low-MMIO space.
+    // This is done to accommodate a limitation in a partner's hypervisor.
+    #[cfg(target_arch = "aarch64")]
+    command
+        .arg("--pci")
+        .arg("mem=[start=0x70000000,size=0x2000000],cam=[start=0x72000000,size=0x1000000]");
+
     command.arg("--mem").arg(memory_mib.to_string());
 
     if let Some(cpus) = config.cpus {
diff --git a/android/vm/src/run.rs b/android/vm/src/run.rs
index 2157ea8..0037327 100644
--- a/android/vm/src/run.rs
+++ b/android/vm/src/run.rs
@@ -173,6 +173,7 @@
         } else {
             bail!("unexpected architecture!");
         }
+        custom_config.extraKernelCmdlineParams.push(String::from("keep_bootcon"));
     }
 
     let vm_config = VirtualMachineConfig::AppConfig(VirtualMachineAppConfig {
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 39f6d65..ce415aa 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -190,12 +190,6 @@
         "true": ["virtualizationservice.xml"],
         default: unset,
     }),
-    required: select(release_flag("RELEASE_AVF_SUPPORT_CUSTOM_VM_WITH_PARAVIRTUALIZED_DEVICES"), {
-        true: [
-            "default-permissions_com.android.virt.xml",
-        ],
-        default: [],
-    }),
 }
 
 apex_defaults {
diff --git a/build/apex/permissions/Android.bp b/build/apex/permissions/Android.bp
index d773df6..678a4f2 100644
--- a/build/apex/permissions/Android.bp
+++ b/build/apex/permissions/Android.bp
@@ -23,9 +23,3 @@
     src: "features_com.android.virt.xml",
     soc_specific: true,
 }
-
-prebuilt_etc {
-    name: "default-permissions_com.android.virt.xml",
-    sub_dir: "default-permissions",
-    src: "default-permissions_com.android.virt.xml",
-}
diff --git a/build/apex/permissions/default-permissions_com.android.virt.xml b/build/apex/permissions/default-permissions_com.android.virt.xml
deleted file mode 100644
index ac15708..0000000
--- a/build/apex/permissions/default-permissions_com.android.virt.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
-<!--
-    Copyright (C) 2024 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
--->
-
-<!--
-    This file contains permissions to be granted by default. Default
-    permissions are granted to special platform components and to apps
-    that are approved to get default grants. The special components
-    are apps that are expected tto work out-of-the-box as they provide
-    core use cases such as default dialer, default email, etc. These
-    grants are managed by the platform. The apps that are additionally
-    approved for default grants are ones that provide carrier specific
-    functionality, ones legally required at some location, ones providing
-    alternative disclosure and opt-out UI, ones providing highlight features
-    of a dedicated device, etc. This file contains only the latter exceptions.
-    Fixed permissions cannot be controlled by the user and need a special
-    approval. Typically these are to ensure either legally mandated functions
-    or the app is considered a part of the OS.
--->
-<exceptions>
-    <!-- This is an example of an exception:
-    <exception
-        package="foo.bar.permission"
-      <permission name="android.permission.READ_CONTACTS" fixed="true"/>
-      <permission name="android.permission.READ_CALENDAR" fixed="false"/>
-    </exception>
-    -->
-    <exception package="com.android.virtualization.terminal">
-        <permission name="android.permission.POST_NOTIFICATIONS" fixed="true"/>
-    </exception>
-</exceptions>
diff --git a/build/debian/build.sh b/build/debian/build.sh
index 8f232aa..1e43b60 100755
--- a/build/debian/build.sh
+++ b/build/debian/build.sh
@@ -97,6 +97,7 @@
 	if [[ "$arch" == "x86_64" ]]; then
 		packages+=(
 			libguestfs-tools
+			linux-image-generic
 		)
 	fi
 	DEBIAN_FRONTEND=noninteractive \
@@ -241,7 +242,7 @@
 	mv vmlinuz* vmlinuz
 	mv initrd.img* initrd.img
 	images+=(
-		boot_part
+		bios_part
 		root_part
 		efi_part
 		vmlinuz
diff --git a/build/debian/vm_config.json.x86_64 b/build/debian/vm_config.json.x86_64
index 4d31105..496e684 100644
--- a/build/debian/vm_config.json.x86_64
+++ b/build/debian/vm_config.json.x86_64
@@ -13,7 +13,7 @@
                     "label": "BIOS",
                     "path": "$PAYLOAD_DIR/bios_part",
                     "writable": true,
-                    "guid": "{root_part_guid}"
+                    "guid": "{bios_part_guid}"
                 },
                 {
                     "label": "EFI",
diff --git a/build/microdroid/bootconfig.arm64 b/build/microdroid/bootconfig.arm64
index b1e6d56..7509a2c 100644
--- a/build/microdroid/bootconfig.arm64
+++ b/build/microdroid/bootconfig.arm64
@@ -1 +1 @@
-androidboot.boot_devices = 10000.pci
+androidboot.boot_devices = 72000000.pci
diff --git a/guest/pvmfw/platform.dts b/guest/pvmfw/platform.dts
index c3ecd0e..643a5e4 100644
--- a/guest/pvmfw/platform.dts
+++ b/guest/pvmfw/platform.dts
@@ -355,11 +355,11 @@
 		dma-coherent;
 		memory-region = <&swiotlb>;
 		ranges = <
-			0x3000000 0x0 0x02000000 0x0 0x02000000 0x00 0x02000000
+			0x3000000 0x0 0x70000000 0x0 0x70000000 0x00 0x02000000
 			0x3000000 PLACEHOLDER2   PLACEHOLDER2   PLACEHOLDER2
 		>;
 		bus-range = <0x00 0x00>;
-		reg = <0x00 0x10000 0x00 0x1000000>;
+		reg = <0x00 0x72000000 0x00 0x1000000>;
 		interrupt-map = <
 			0x0800 0x0 0x0 1 &intc 0 0 GIC_SPI (IRQ_BASE + 0) IRQ_TYPE_LEVEL_HIGH
 			0x1000 0x0 0x0 1 &intc 0 0 GIC_SPI (IRQ_BASE + 1) IRQ_TYPE_LEVEL_HIGH
diff --git a/guest/vmbase_example/src/layout.rs b/guest/vmbase_example/src/layout.rs
index 50ecb7e..55c7283 100644
--- a/guest/vmbase_example/src/layout.rs
+++ b/guest/vmbase_example/src/layout.rs
@@ -19,8 +19,8 @@
 use log::info;
 use vmbase::{layout, memory::PAGE_SIZE};
 
-/// The first 1 GiB of memory are used for MMIO.
-pub const DEVICE_REGION: MemoryRegion = MemoryRegion::new(0, 0x40000000);
+pub const DEVICE_REGION: MemoryRegion =
+    MemoryRegion::new(layout::crosvm::MMIO_START, layout::crosvm::MMIO_END);
 
 /// Writable data region for the stack.
 pub fn boot_stack_range() -> Range<VirtualAddress> {
diff --git a/libs/libcompos_common/compos_client.rs b/libs/libcompos_common/compos_client.rs
index 316eaa9..6872582 100644
--- a/libs/libcompos_common/compos_client.rs
+++ b/libs/libcompos_common/compos_client.rs
@@ -58,6 +58,8 @@
 pub struct VmParameters {
     /// The name of VM for identifying.
     pub name: String,
+    /// The OS of VM.
+    pub os: String,
     /// Whether the VM should be debuggable.
     pub debug_mode: bool,
     /// CPU topology of the VM. Defaults to 1 vCPU.
@@ -129,6 +131,7 @@
 
         let config = VirtualMachineConfig::AppConfig(VirtualMachineAppConfig {
             name: parameters.name.clone(),
+            osName: parameters.os.clone(),
             apk: Some(apk_fd),
             idsig: Some(idsig_fd),
             instanceId: instance_id,
diff --git a/libs/libvmbase/src/layout/crosvm.rs b/libs/libvmbase/src/layout/crosvm.rs
index d859b20..39a8147 100644
--- a/libs/libvmbase/src/layout/crosvm.rs
+++ b/libs/libvmbase/src/layout/crosvm.rs
@@ -21,10 +21,13 @@
 /// The start address of MMIO space.
 pub const MMIO_START: usize = 0x0;
 /// The end address of MMIO space.
-pub const MMIO_END: usize = 0x4000_0000;
+pub const MMIO_END: usize = PVMFW_START;
 /// MMIO range.
 pub const MMIO_RANGE: Range<usize> = MMIO_START..MMIO_END;
 
+/// Start pvmfw region.
+pub const PVMFW_START: usize = 0x7fc00000;
+
 /// The start of the system's contiguous "main" memory.
 pub const MEM_START: usize = 0x8000_0000;
 
diff --git a/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_golden.dts b/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_golden.dts
index 795c50f..095eb54 100644
--- a/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_golden.dts
+++ b/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_golden.dts
@@ -104,8 +104,8 @@
                 dma-coherent;
                 interrupt-map = <0x800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x04 0x04 0x1000 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x05 0x04 0x1800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x06 0x04 0x2000 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x07 0x04 0x2800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x08 0x04 0x3000 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x09 0x04 0x3800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x0a 0x04 0x4000 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x0b 0x04 0x4800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x0c 0x04>;
                 interrupt-map-mask = <0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07>;
-                ranges = <0x3000000 0x00 0x2000000 0x00 0x2000000 0x00 0x2000000 0x43000000 0x00 0x90800000 0x00 0x90800000 0xff 0x6f800000>;
-                reg = <0x00 0x10000 0x00 0x1000000>;
+                ranges = <0x3000000 0x00 0x70000000 0x00 0x70000000 0x00 0x2000000 0x43000000 0x00 0x90800000 0x00 0x90800000 0xff 0x6f800000>;
+                reg = <0x00 0x72000000 0x00 0x1000000>;
         };
 
         pclk@3M {
diff --git a/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_protected_golden.dts b/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_protected_golden.dts
index 5761c15..f2ebdf9 100644
--- a/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_protected_golden.dts
+++ b/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_protected_golden.dts
@@ -105,8 +105,8 @@
                 interrupt-map = <0x800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x04 0x04 0x1000 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x05 0x04 0x1800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x06 0x04 0x2000 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x07 0x04 0x2800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x08 0x04 0x3000 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x09 0x04 0x3800 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x0a 0x04 0x4000 0x00 0x00 0x01 0x01 0x00 0x00 0x00 0x0b 0x04>;
                 interrupt-map-mask = <0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07 0xf800 0x00 0x00 0x07>;
                 memory-region = <0x02>;
-                ranges = <0x3000000 0x00 0x2000000 0x00 0x2000000 0x00 0x2000000 0x43000000 0x00 0x91600000 0x00 0x91600000 0xff 0x6ea00000>;
-                reg = <0x00 0x10000 0x00 0x1000000>;
+                ranges = <0x3000000 0x00 0x70000000 0x00 0x70000000 0x00 0x2000000 0x43000000 0x00 0x91600000 0x00 0x91600000 0xff 0x6ea00000>;
+                reg = <0x00 0x72000000 0x00 0x1000000>;
         };
 
         pclk@3M {