Merge "QSDetailedView: Create ScreenRecordPermissionViewBinder" into main
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt
index 6f5d262..e17255a 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt
@@ -53,7 +53,22 @@
     private lateinit var cancelButton: TextView
     private lateinit var screenShareModeSpinner: Spinner
     protected lateinit var dialog: AlertDialog
-    private lateinit var viewBinder: BaseMediaProjectionPermissionViewBinder
+    protected lateinit var viewBinder: BaseMediaProjectionPermissionViewBinder
+
+    /**
+     * Create the view binder for the permission dialog, this can be override by child classes to
+     * support a different type of view binder
+     */
+    open fun createViewBinder(): BaseMediaProjectionPermissionViewBinder {
+        return BaseMediaProjectionPermissionViewBinder(
+            screenShareOptions,
+            appName,
+            hostUid,
+            mediaProjectionMetricsLogger,
+            defaultSelectedMode,
+            dialog,
+        )
+    }
 
     @CallSuper
     override fun onStop(dialog: T) {
@@ -71,15 +86,7 @@
         updateIcon()
         createOptionsView(getOptionsViewLayoutId())
         if (!::viewBinder.isInitialized) {
-            viewBinder =
-                BaseMediaProjectionPermissionViewBinder(
-                    screenShareOptions,
-                    appName,
-                    hostUid,
-                    mediaProjectionMetricsLogger,
-                    defaultSelectedMode,
-                    dialog,
-                )
+            viewBinder = createViewBinder()
         }
         viewBinder.bind()
         initScreenShareSpinner()
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt
index 70b25f5..728255d 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt
@@ -61,7 +61,7 @@
         startButton.text = startButtonText
     }
 
-    fun onItemSelected(pos: Int) {
+    open fun onItemSelected(pos: Int) {
         selectedScreenShareOption = screenShareOptions[pos]
         setOptionSpecificFields()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
index d9cc0c8..1da4c1d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
@@ -21,7 +21,6 @@
 import android.content.Context
 import android.content.Intent
 import android.hardware.display.DisplayManager
-import android.os.Build
 import android.os.Bundle
 import android.os.Handler
 import android.os.Looper
@@ -30,8 +29,6 @@
 import android.view.Display
 import android.view.MotionEvent.ACTION_MOVE
 import android.view.View
-import android.view.View.GONE
-import android.view.View.VISIBLE
 import android.view.accessibility.AccessibilityNodeInfo
 import android.widget.AdapterView
 import android.widget.ArrayAdapter
@@ -44,10 +41,10 @@
 import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity
 import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionDialogDelegate
+import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionViewBinder
 import com.android.systemui.mediaprojection.permission.ENTIRE_SCREEN
 import com.android.systemui.mediaprojection.permission.SINGLE_APP
 import com.android.systemui.mediaprojection.permission.ScreenShareMode
-import com.android.systemui.mediaprojection.permission.ScreenShareOption
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserContextProvider
@@ -64,15 +61,15 @@
     private val activityStarter: ActivityStarter,
     private val userContextProvider: UserContextProvider,
     private val onStartRecordingClicked: Runnable?,
-    mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
+    private val mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
     private val systemUIDialogFactory: SystemUIDialog.Factory,
     @ScreenShareMode defaultSelectedMode: Int,
     @StyleRes private val theme: Int,
     private val context: Context,
-    displayManager: DisplayManager,
+    private val displayManager: DisplayManager,
 ) :
     BaseMediaProjectionPermissionDialogDelegate<SystemUIDialog>(
-        createOptionList(displayManager),
+        ScreenRecordPermissionViewBinder.createOptionList(displayManager),
         appName = null,
         hostUid = hostUid,
         mediaProjectionMetricsLogger,
@@ -119,10 +116,19 @@
     }
 
     private lateinit var tapsSwitch: Switch
-    private lateinit var tapsView: View
     private lateinit var audioSwitch: Switch
     private lateinit var options: Spinner
 
+    override fun createViewBinder(): BaseMediaProjectionPermissionViewBinder {
+        return ScreenRecordPermissionViewBinder(
+            hostUid,
+            mediaProjectionMetricsLogger,
+            defaultSelectedMode,
+            displayManager,
+            dialog,
+        )
+    }
+
     override fun createDialog(): SystemUIDialog {
         return systemUIDialogFactory.create(this, context, theme)
     }
@@ -169,6 +175,7 @@
 
     @SuppressLint("ClickableViewAccessibility")
     private fun initRecordOptionsView() {
+        // TODO(b/378514312): Move this function to ScreenRecordPermissionViewBinder
         audioSwitch = dialog.requireViewById(R.id.screenrecord_audio_switch)
         tapsSwitch = dialog.requireViewById(R.id.screenrecord_taps_switch)
 
@@ -177,9 +184,6 @@
         audioSwitch.setOnTouchListener { _, event -> event.action == ACTION_MOVE }
         tapsSwitch.setOnTouchListener { _, event -> event.action == ACTION_MOVE }
 
-        tapsView = dialog.requireViewById(R.id.show_taps)
-        updateTapsViewVisibility()
-
         options = dialog.requireViewById(R.id.screen_recording_options)
         val a: ArrayAdapter<*> =
             ScreenRecordingAdapter(
@@ -207,16 +211,6 @@
         options.isLongClickable = false
     }
 
-    override fun onItemSelected(adapterView: AdapterView<*>?, view: View, pos: Int, id: Long) {
-        super.onItemSelected(adapterView, view, pos, id)
-        updateTapsViewVisibility()
-    }
-
-    private fun updateTapsViewVisibility() {
-        tapsView.visibility =
-            if (getSelectedScreenShareOption().mode == SINGLE_APP) GONE else VISIBLE
-    }
-
     /**
      * Starts screen capture after some countdown
      *
@@ -281,81 +275,5 @@
             )
         private const val DELAY_MS: Long = 3000
         private const val INTERVAL_MS: Long = 1000
-
-        private val RECORDABLE_DISPLAY_TYPES =
-            intArrayOf(
-                Display.TYPE_OVERLAY,
-                Display.TYPE_EXTERNAL,
-                Display.TYPE_INTERNAL,
-                Display.TYPE_WIFI,
-            )
-
-        private val filterDeviceTypeFlag: Boolean =
-            com.android.media.projection.flags.Flags
-                .mediaProjectionConnectedDisplayNoVirtualDevice()
-
-        private fun createOptionList(displayManager: DisplayManager): List<ScreenShareOption> {
-            if (!com.android.media.projection.flags.Flags.mediaProjectionConnectedDisplay()) {
-                return listOf(
-                    ScreenShareOption(
-                        SINGLE_APP,
-                        R.string.screenrecord_permission_dialog_option_text_single_app,
-                        R.string.screenrecord_permission_dialog_warning_single_app,
-                        startButtonText =
-                            R.string
-                                .media_projection_entry_generic_permission_dialog_continue_single_app,
-                    ),
-                    ScreenShareOption(
-                        ENTIRE_SCREEN,
-                        R.string.screenrecord_permission_dialog_option_text_entire_screen,
-                        R.string.screenrecord_permission_dialog_warning_entire_screen,
-                        startButtonText =
-                            R.string.screenrecord_permission_dialog_continue_entire_screen,
-                        displayId = Display.DEFAULT_DISPLAY,
-                        displayName = Build.MODEL,
-                    ),
-                )
-            }
-
-            return listOf(
-                ScreenShareOption(
-                    SINGLE_APP,
-                    R.string.screenrecord_permission_dialog_option_text_single_app,
-                    R.string.screenrecord_permission_dialog_warning_single_app,
-                    startButtonText =
-                        R.string
-                            .media_projection_entry_generic_permission_dialog_continue_single_app,
-                ),
-                ScreenShareOption(
-                    ENTIRE_SCREEN,
-                    R.string.screenrecord_permission_dialog_option_text_entire_screen_for_display,
-                    R.string.screenrecord_permission_dialog_warning_entire_screen,
-                    startButtonText =
-                        R.string.screenrecord_permission_dialog_continue_entire_screen,
-                    displayId = Display.DEFAULT_DISPLAY,
-                    displayName = Build.MODEL,
-                ),
-            ) +
-                displayManager.displays
-                    .filter {
-                        it.displayId != Display.DEFAULT_DISPLAY &&
-                            (!filterDeviceTypeFlag || it.type in RECORDABLE_DISPLAY_TYPES)
-                    }
-                    .map {
-                        ScreenShareOption(
-                            ENTIRE_SCREEN,
-                            R.string
-                                .screenrecord_permission_dialog_option_text_entire_screen_for_display,
-                            warningText =
-                                R.string
-                                    .media_projection_entry_app_permission_dialog_warning_entire_screen,
-                            startButtonText =
-                                R.string
-                                    .media_projection_entry_app_permission_dialog_continue_entire_screen,
-                            displayId = it.displayId,
-                            displayName = it.name,
-                        )
-                    }
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
new file mode 100644
index 0000000..91c6b47
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.screenrecord
+
+import android.annotation.SuppressLint
+import android.app.AlertDialog
+import android.hardware.display.DisplayManager
+import android.os.Build
+import android.view.Display
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
+import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionViewBinder
+import com.android.systemui.mediaprojection.permission.ENTIRE_SCREEN
+import com.android.systemui.mediaprojection.permission.SINGLE_APP
+import com.android.systemui.mediaprojection.permission.ScreenShareMode
+import com.android.systemui.mediaprojection.permission.ScreenShareOption
+import com.android.systemui.res.R
+
+class ScreenRecordPermissionViewBinder(
+    hostUid: Int,
+    mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
+    @ScreenShareMode defaultSelectedMode: Int,
+    displayManager: DisplayManager,
+    private val dialog: AlertDialog,
+) :
+    BaseMediaProjectionPermissionViewBinder(
+        createOptionList(displayManager),
+        appName = null,
+        hostUid = hostUid,
+        mediaProjectionMetricsLogger,
+        defaultSelectedMode,
+        dialog,
+    ) {
+    private lateinit var tapsView: View
+
+    override fun bind() {
+        super.bind()
+        initRecordOptionsView()
+    }
+
+    @SuppressLint("ClickableViewAccessibility")
+    private fun initRecordOptionsView() {
+        tapsView = dialog.requireViewById(R.id.show_taps)
+        updateTapsViewVisibility()
+    }
+
+    override fun onItemSelected(pos: Int) {
+        super.onItemSelected(pos)
+        updateTapsViewVisibility()
+    }
+
+    private fun updateTapsViewVisibility() {
+        tapsView.visibility = if (selectedScreenShareOption.mode == SINGLE_APP) GONE else VISIBLE
+    }
+
+    companion object {
+        private val RECORDABLE_DISPLAY_TYPES =
+            intArrayOf(
+                Display.TYPE_OVERLAY,
+                Display.TYPE_EXTERNAL,
+                Display.TYPE_INTERNAL,
+                Display.TYPE_WIFI,
+            )
+
+        private val filterDeviceTypeFlag: Boolean =
+            com.android.media.projection.flags.Flags
+                .mediaProjectionConnectedDisplayNoVirtualDevice()
+
+        fun createOptionList(displayManager: DisplayManager): List<ScreenShareOption> {
+            if (!com.android.media.projection.flags.Flags.mediaProjectionConnectedDisplay()) {
+                return listOf(
+                    ScreenShareOption(
+                        SINGLE_APP,
+                        R.string.screenrecord_permission_dialog_option_text_single_app,
+                        R.string.screenrecord_permission_dialog_warning_single_app,
+                        startButtonText =
+                            R.string
+                                .media_projection_entry_generic_permission_dialog_continue_single_app,
+                    ),
+                    ScreenShareOption(
+                        ENTIRE_SCREEN,
+                        R.string.screenrecord_permission_dialog_option_text_entire_screen,
+                        R.string.screenrecord_permission_dialog_warning_entire_screen,
+                        startButtonText =
+                            R.string.screenrecord_permission_dialog_continue_entire_screen,
+                        displayId = Display.DEFAULT_DISPLAY,
+                        displayName = Build.MODEL,
+                    ),
+                )
+            }
+
+            return listOf(
+                ScreenShareOption(
+                    SINGLE_APP,
+                    R.string.screenrecord_permission_dialog_option_text_single_app,
+                    R.string.screenrecord_permission_dialog_warning_single_app,
+                    startButtonText =
+                        R.string
+                            .media_projection_entry_generic_permission_dialog_continue_single_app,
+                ),
+                ScreenShareOption(
+                    ENTIRE_SCREEN,
+                    R.string.screenrecord_permission_dialog_option_text_entire_screen_for_display,
+                    R.string.screenrecord_permission_dialog_warning_entire_screen,
+                    startButtonText =
+                        R.string.screenrecord_permission_dialog_continue_entire_screen,
+                    displayId = Display.DEFAULT_DISPLAY,
+                    displayName = Build.MODEL,
+                ),
+            ) +
+                displayManager.displays
+                    .filter {
+                        it.displayId != Display.DEFAULT_DISPLAY &&
+                            (!filterDeviceTypeFlag || it.type in RECORDABLE_DISPLAY_TYPES)
+                    }
+                    .map {
+                        ScreenShareOption(
+                            ENTIRE_SCREEN,
+                            R.string
+                                .screenrecord_permission_dialog_option_text_entire_screen_for_display,
+                            warningText =
+                                R.string
+                                    .media_projection_entry_app_permission_dialog_warning_entire_screen,
+                            startButtonText =
+                                R.string
+                                    .media_projection_entry_app_permission_dialog_continue_entire_screen,
+                            displayId = it.displayId,
+                            displayName = it.name,
+                        )
+                    }
+        }
+    }
+}