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

Commit 4bdaab3f authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[SB][Screen Chips] Show a stop dialog when tapping on screen record chip

Bug: 332662551
Flag: com.android.systemui.status_bar_screen_sharing_chips
Test: Start a screen recording -> click on the chip -> verify you see a
dialog.
Test: On dialog, click Close -> verify dialog closes, recording is still
going
Test: On dialog, click Stop recording -> verify dialog closes, recording
is stopped
Test: atest EndScreenRecordingDialogDelegateTest
ScreenRecordChipInteractorTest

Change-Id: I16cd74a663f14e129113bb1defbbde28bdb44a7d
parent 0f4a2604
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
import com.android.systemui.screenrecord.data.repository.ScreenRecordRepositoryImpl
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -72,11 +73,18 @@ class ScreenRecordTileUserActionInteractorTest : SysuiTestCase() {
                .thenReturn(dialog)
        }

    private val screenRecordRepository =
        ScreenRecordRepositoryImpl(
            bgCoroutineContext = testScope.testScheduler,
            recordingController = recordingController,
        )

    private val underTest =
        ScreenRecordTileUserActionInteractor(
            context,
            testScope.testScheduler,
            testScope.testScheduler,
            screenRecordRepository,
            recordingController,
            keyguardInteractor,
            keyguardDismissUtil,
+9 −0
Original line number Diff line number Diff line
@@ -319,6 +319,15 @@
    <string name="screenrecord_save_error">Error saving screen recording</string>
    <!-- A toast message shown when the screen recording cannot be started due to a generic error [CHAR LIMIT=NONE] -->
    <string name="screenrecord_start_error">Error starting screen recording</string>
    <!-- Title for a dialog shown to the user that will let them stop recording their screen [CHAR LIMIT=50] -->
    <string name="screenrecord_stop_dialog_title">Stop recording screen?</string>
    <!-- Text telling a user that they will stop recording their screen if they click the "Stop recording" button [CHAR LIMIT=100] -->
    <string name="screenrecord_stop_dialog_message">You will stop recording your screen</string>
    <!-- Button to stop a screen recording [CHAR LIMIT=35] -->
    <string name="screenrecord_stop_dialog_button">Stop recording</string>

    <!-- Button to close a dialog without doing any action [CHAR LIMIT=20] -->
    <string name="close_dialog_button">Close</string>

    <!-- Notification title displayed for issue recording [CHAR LIMIT=50]-->
    <string name="issuerecord_title">Issue Recorder</string>
+4 −4
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
import com.android.systemui.screenrecord.data.repository.ScreenRecordRepository
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
@@ -47,6 +48,7 @@ constructor(
    @Application private val context: Context,
    @Main private val mainContext: CoroutineContext,
    @Background private val backgroundContext: CoroutineContext,
    private val screenRecordRepository: ScreenRecordRepository,
    private val recordingController: RecordingController,
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardDismissUtil: KeyguardDismissUtil,
@@ -65,8 +67,7 @@ constructor(
                            Log.d(TAG, "Cancelling countdown")
                            withContext(backgroundContext) { recordingController.cancelCountdown() }
                        }
                        is ScreenRecordModel.Recording ->
                            withContext(backgroundContext) { recordingController.stopRecording() }
                        is ScreenRecordModel.Recording -> screenRecordRepository.stopRecording()
                        is ScreenRecordModel.DoingNothing ->
                            withContext(mainContext) {
                                showPrompt(action.expandable, user.identifier)
@@ -122,8 +123,7 @@ constructor(
                            controller,
                            animateBackgroundBoundsChange = true,
                        )
                    }
                        ?: dialog.show()
                    } ?: dialog.show()
                } else {
                    dialog.show()
                }
+8 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext

/**
 * Repository storing information about the state of screen recording.
@@ -38,6 +39,9 @@ import kotlinx.coroutines.flow.onStart
interface ScreenRecordRepository {
    /** The current screen recording state. Note that this is a cold flow. */
    val screenRecordState: Flow<ScreenRecordModel>

    /** Stops the recording. */
    suspend fun stopRecording()
}

@SysUISingleton
@@ -90,4 +94,8 @@ constructor(
            ScreenRecordModel.DoingNothing
        }
    }

    override suspend fun stopRecording() {
        withContext(bgCoroutineContext) { recordingController.stopRecording() }
    }
}
+26 −0
Original line number Diff line number Diff line
@@ -16,11 +16,37 @@

package com.android.systemui.statusbar.chips.domain.interactor

import android.view.View
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.domain.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.phone.SystemUIDialog
import kotlinx.coroutines.flow.StateFlow

/** Interface for an interactor that knows the state of a single type of ongoing activity chip. */
interface OngoingActivityChipInteractor {
    /** A flow modeling the chip that should be shown. */
    val chip: StateFlow<OngoingActivityChipModel>

    companion object {
        /** Creates a chip click listener that launches a dialog created by [dialogDelegate]. */
        fun createDialogLaunchOnClickListener(
            dialogDelegate: SystemUIDialog.Delegate,
            dialogTransitionAnimator: DialogTransitionAnimator,
        ): View.OnClickListener {
            return View.OnClickListener { view ->
                val dialog = dialogDelegate.createDialog()
                val launchableView =
                    view.requireViewById<ChipBackgroundContainer>(
                        R.id.ongoing_activity_chip_background
                    )
                // TODO(b/343699052): This makes a beautiful animate-in, but the
                //  animate-out looks odd because the dialog animates back into the chip
                //  but then the chip disappears. If we aren't able to address
                //  b/343699052 in time for launch, we should just use `dialog.show`.
                dialogTransitionAnimator.showFromView(dialog, launchableView)
            }
        }
    }
}
Loading