Merge "Install `linux-image-generic` in x86_64 containerized builds" into main
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/SettingsPortForwardingActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
index a332a9d..fe693c4 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsPortForwardingActivity.kt
@@ -15,52 +15,38 @@
  */
 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 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>()
+        mSharedPref =
+            this.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE)
 
-        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));
-        }
-
-        val settingsPortForwardingAdapter =
-            SettingsPortForwardingAdapter(settingsPortForwardingItems, this)
+        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/res/layout/settings_list_item.xml b/android/TerminalApp/res/layout/settings_list_item.xml
index 645efbb..38c1d7b 100644
--- a/android/TerminalApp/res/layout/settings_list_item.xml
+++ b/android/TerminalApp/res/layout/settings_list_item.xml
@@ -22,7 +22,6 @@
     app:cardCornerRadius="28dp"
     app:checkedIcon="@null"
     android:focusable="true"
-    android:checkable="true"
     android:layout_height="wrap_content"
     android:layout_width="match_parent">
 
@@ -66,4 +65,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/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/build/apex/Android.bp b/build/apex/Android.bp
index 4759c19..6541764 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -182,12 +182,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 26234c7..1e43b60 100755
--- a/build/debian/build.sh
+++ b/build/debian/build.sh
@@ -242,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/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,