Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e33fce3 authored by Andre Le's avatar Andre Le
Browse files

QSDetailedView: Create ScreenRecordPermissionViewBinder

Create the new view binder class that is associated with
ScreenRecordPermissionDialogDelegate. This view binder inherits
BaseMediaProjectionPermissionViewBinder, with some customizations that
are specific to screen record (more customization will be added in later
CLs).

In order for BaseMediaProjectionPermissionDialogDelegate to use this new
view binder, this CL also creates a new function called
createViewBinder() that allows child class to specify a different view
binder to use.

This CL follows the design mentioned in
go/al-screen-record-detailed-view.

Bug: b/378514312
Flag: NONE refactor
Test: ScreenRecordPermissionDialogDelegateTest
Test: Click on screen record tile in the QS -> verify that screen
recording in single app and entire screen both works

Change-Id: I88be4dbdc56bc188c5dbb392633e51b2dbea20ca
parent e761adc7
Loading
Loading
Loading
Loading
+17 −10
Original line number Diff line number Diff line
@@ -53,7 +53,22 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>(
    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 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>(
        updateIcon()
        createOptionsView(getOptionsViewLayoutId())
        if (!::viewBinder.isInitialized) {
            viewBinder =
                BaseMediaProjectionPermissionViewBinder(
                    screenShareOptions,
                    appName,
                    hostUid,
                    mediaProjectionMetricsLogger,
                    defaultSelectedMode,
                    dialog,
                )
            viewBinder = createViewBinder()
        }
        viewBinder.bind()
        initScreenShareSpinner()
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ open class BaseMediaProjectionPermissionViewBinder(
        startButton.text = startButtonText
    }

    fun onItemSelected(pos: Int) {
    open fun onItemSelected(pos: Int) {
        selectedScreenShareOption = screenShareOptions[pos]
        setOptionSpecificFields()
    }
+15 −97
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.app.PendingIntent
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.os.UserHandle
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.MediaProjectionCaptureTarget
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 @@ class ScreenRecordPermissionDialogDelegate(
    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 @@ class ScreenRecordPermissionDialogDelegate(
    }

    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 @@ class ScreenRecordPermissionDialogDelegate(

    @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 @@ class ScreenRecordPermissionDialogDelegate(
        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 @@ class ScreenRecordPermissionDialogDelegate(
        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 @@ class ScreenRecordPermissionDialogDelegate(
            )
        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,
                        )
                    }
        }
    }
}
+149 −0
Original line number Diff line number Diff line
/*
 * 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,
                        )
                    }
        }
    }
}