Merge "VmTerminalApp: Fix a11y for resize slider" into main
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/build/debian/build.sh b/build/debian/build.sh
index 466c2e0..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 \