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

Commit ebbcfc14 authored by Nicolo' Mazzucato's avatar Nicolo' Mazzucato
Browse files

Open screen recording dialog using statusbar context

As the screen recording dialog needs to be visible also while the shade is collapsed, it is now using the statusbar context (falling back to the shade context only when the statusbar is not available).

The main issue here was that if the screen recording is started while on the lockscreen, the dialog creation was postponed until after unlocking, and the shade was hidden by then. As the dialog was a child of the shade window, it was hidden too.

Bug: 362719719
Bug: 419577795
Test: ScreenRecordPermissionDialogDelegateTest
Flag: com.android.systemui.shade_window_goes_around
Change-Id: Iee65f9cb44c9c8267e79a86925eccacfc8331cbb
parent c92c6491
Loading
Loading
Loading
Loading
+37 −2
Original line number Diff line number Diff line
@@ -21,9 +21,11 @@ import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.hardware.display.VirtualDisplayConfig
import android.os.UserHandle
import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.RequiresFlagsEnabled
import android.testing.TestableLooper
import android.view.View
import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR
import android.widget.Spinner
import android.widget.TextView
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -33,6 +35,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.domain.interactor.SysUIStateDisplaysInteractor
import com.android.systemui.display.data.repository.FakeDisplayWindowPropertiesRepository
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity
import com.android.systemui.mediaprojection.permission.ENTIRE_SCREEN
@@ -40,6 +43,7 @@ import com.android.systemui.mediaprojection.permission.SINGLE_APP
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.mockito.argumentCaptor
@@ -67,8 +71,11 @@ class ScreenRecordPermissionDialogDelegateTest : SysuiTestCase() {
    @Mock private lateinit var userContextProvider: UserContextProvider
    @Mock private lateinit var onStartRecordingClicked: Runnable
    @Mock private lateinit var mediaProjectionMetricsLogger: MediaProjectionMetricsLogger
    private val fakeDisplayWindowPropertiesRepository =
        FakeDisplayWindowPropertiesRepository(context)

    private lateinit var dialog: SystemUIDialog
    private lateinit var underTest: ScreenRecordPermissionDialogDelegate

    @Before
    fun setUp() {
@@ -83,7 +90,7 @@ class ScreenRecordPermissionDialogDelegateTest : SysuiTestCase() {
                Dependency.get(DialogTransitionAnimator::class.java),
            )

        val delegate =
        underTest =
            ScreenRecordPermissionDialogDelegate(
                UserHandle.of(0),
                TEST_HOST_UID,
@@ -95,8 +102,9 @@ class ScreenRecordPermissionDialogDelegateTest : SysuiTestCase() {
                systemUIDialogFactory,
                context,
                context.getSystemService(DisplayManager::class.java)!!,
                fakeDisplayWindowPropertiesRepository,
            )
        dialog = delegate.createDialog()
        dialog = underTest.createDialog()
    }

    @After
@@ -256,6 +264,33 @@ class ScreenRecordPermissionDialogDelegateTest : SysuiTestCase() {
        }
    }

    @Test
    @EnableFlags(ShadeWindowGoesAround.FLAG_NAME)
    fun createDialog_usesDisplayContextInsteadOfDefaultOne() {
        val shadeContext = context
        val displayManager = context.getSystemService(DisplayManager::class.java)!!
        var virtualDisplay: VirtualDisplay? = null
        try {
            virtualDisplay =
                displayManager.createVirtualDisplay(
                    VirtualDisplayConfig.Builder("virtual display", 1, 1, 160).build()
                )!!
            val displayContext = context.createDisplayContext(virtualDisplay.display)
            fakeDisplayWindowPropertiesRepository.insertForContext(
                displayId = virtualDisplay.display.displayId,
                TYPE_STATUS_BAR,
                displayContext,
            )
            shadeContext.display = virtualDisplay.display

            dialog = underTest.createDialog()

            assertThat(dialog.context.displayId).isEqualTo(virtualDisplay.display.displayId)
        } finally {
            virtualDisplay?.release()
        }
    }

    private fun showDialog() {
        dialog.show()
    }
+20 −1
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@ import android.hardware.display.DisplayManager
import android.os.Bundle
import android.os.UserHandle
import android.view.View
import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR
import androidx.annotation.StyleRes
import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionContentManager
import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionDialogDelegate
@@ -30,6 +32,7 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import com.android.systemui.statusbar.phone.SystemUIDialog
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@@ -49,6 +52,7 @@ class ScreenRecordPermissionDialogDelegate(
    @StyleRes private val theme: Int,
    private val context: Context,
    private val displayManager: DisplayManager,
    private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository,
) :
    BaseMediaProjectionPermissionDialogDelegate<SystemUIDialog>(
        ScreenRecordPermissionContentManager.createOptionList(displayManager),
@@ -72,6 +76,7 @@ class ScreenRecordPermissionDialogDelegate(
        systemUIDialogFactory: SystemUIDialog.Factory,
        @ShadeDisplayAware context: Context,
        displayManager: DisplayManager,
        displayWindowPropertiesRepository: DisplayWindowPropertiesRepository,
    ) : this(
        hostUserHandle,
        hostUid,
@@ -85,6 +90,7 @@ class ScreenRecordPermissionDialogDelegate(
        theme = SystemUIDialog.DEFAULT_THEME,
        context,
        displayManager,
        displayWindowPropertiesRepository,
    )

    @AssistedFactory
@@ -112,7 +118,20 @@ class ScreenRecordPermissionDialogDelegate(
    }

    override fun createDialog(): SystemUIDialog {
        return systemUIDialogFactory.create(this, context, theme)
        val displayContext =
            if (ShadeWindowGoesAround.isEnabled) {
                // This dialog needs to stay visible even if the notification shade closes,
                // for example, after unlocking the device. If we used the shade's own context, the
                // dialog would be tied to the shade and disappear when the shade collapses.
                // To avoid this, we get a context associated with the status bar on the current
                // display.  This ensures the dialog remains visible independently of the shade.
                displayWindowPropertiesRepository.get(context.displayId, TYPE_STATUS_BAR)?.context
                    // falls back to the default context if the status bar context is not available
                    ?: context
            } else {
                context
            }
        return systemUIDialogFactory.create(this, displayContext, theme)
    }

    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {