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

Commit a997b8ed authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[SB][Screen share] Proactively start screen record timer." into main

parents 5b685ed0 51ef42f7
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -413,6 +413,17 @@ flag {
    }
    }
}
}


flag {
    name: "status_bar_auto_start_screen_record_chip"
    namespace: "systemui"
    description: "When screen recording, use the specified start time to update the screen record "
        "chip state instead of waiting for an official 'recording started' signal"
    bug: "366448907"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
flag {
    name: "status_bar_use_repos_for_call_chip"
    name: "status_bar_use_repos_for_call_chip"
    namespace: "systemui"
    namespace: "systemui"
+140 −3
Original line number Original line Diff line number Diff line
@@ -16,29 +16,35 @@


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


import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_STATUS_BAR_AUTO_START_SCREEN_RECORD_CHIP
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testCase
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
import com.android.systemui.mediaprojection.taskswitcher.FakeActivityTaskManager.Companion.createTask
import com.android.systemui.mediaprojection.taskswitcher.FakeActivityTaskManager.Companion.createTask
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
import com.android.systemui.screenrecord.data.repository.screenRecordRepository
import com.android.systemui.screenrecord.data.repository.screenRecordRepository
import com.android.systemui.statusbar.chips.screenrecord.domain.model.ScreenRecordChipModel
import com.android.systemui.statusbar.chips.screenrecord.domain.model.ScreenRecordChipModel
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlin.test.Test
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.runTest
import org.junit.runner.RunWith
import org.junit.runner.RunWith


@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
class ScreenRecordChipInteractorTest : SysuiTestCase() {
class ScreenRecordChipInteractorTest : SysuiTestCase() {
    private val kosmos = Kosmos().also { it.testCase = this }
    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val testScope = kosmos.testScope
    private val testScope = kosmos.testScope
    private val screenRecordRepo = kosmos.screenRecordRepository
    private val screenRecordRepo = kosmos.screenRecordRepository
    private val mediaProjectionRepo = kosmos.fakeMediaProjectionRepository
    private val mediaProjectionRepo = kosmos.fakeMediaProjectionRepository
@@ -115,6 +121,137 @@ class ScreenRecordChipInteractorTest : SysuiTestCase() {
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Recording(recordedTask = task))
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Recording(recordedTask = task))
        }
        }


    @Test
    @DisableFlags(FLAG_STATUS_BAR_AUTO_START_SCREEN_RECORD_CHIP)
    fun screenRecordState_flagOff_doesNotAutomaticallySwitchToRecordingBasedOnTime() =
        testScope.runTest {
            val latest by collectLastValue(underTest.screenRecordState)

            // WHEN screen record should start in 900ms
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Starting(900)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Starting(900))

            // WHEN 900ms has elapsed
            advanceTimeBy(901)

            // THEN we don't automatically update to the recording state if the flag is off
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Starting(900))
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_AUTO_START_SCREEN_RECORD_CHIP)
    fun screenRecordState_flagOn_automaticallySwitchesToRecordingBasedOnTime() =
        testScope.runTest {
            val latest by collectLastValue(underTest.screenRecordState)

            // WHEN screen record should start in 900ms
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Starting(900)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Starting(900))

            // WHEN 900ms has elapsed
            advanceTimeBy(901)

            // THEN we automatically update to the recording state
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Recording(recordedTask = null))
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_AUTO_START_SCREEN_RECORD_CHIP)
    fun screenRecordState_recordingBeginsEarly_switchesToRecording() =
        testScope.runTest {
            val latest by collectLastValue(underTest.screenRecordState)

            // WHEN screen record should start in 900ms
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Starting(900)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Starting(900))

            // WHEN we update to the Recording state earlier than 900ms
            advanceTimeBy(800)
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
            val task = createTask(taskId = 1)
            mediaProjectionRepo.mediaProjectionState.value =
                MediaProjectionState.Projecting.SingleTask(
                    "host.package",
                    hostDeviceName = null,
                    task,
                )

            // THEN we immediately switch to Recording, and we have the task
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Recording(recordedTask = task))

            // WHEN more than 900ms has elapsed
            advanceTimeBy(200)

            // THEN we still stay in the Recording state and we have the task
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Recording(recordedTask = task))
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_AUTO_START_SCREEN_RECORD_CHIP)
    fun screenRecordState_secondRecording_doesNotAutomaticallyStart() =
        testScope.runTest {
            val latest by collectLastValue(underTest.screenRecordState)

            // First recording starts, records, and stops
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Starting(900)
            advanceTimeBy(900)
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Recording
            advanceTimeBy(5000)
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.DoingNothing
            advanceTimeBy(10000)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.DoingNothing)

            // WHEN a second recording is starting
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Starting(2900)

            // THEN we stay as starting and do not switch to Recording (verifying the auto-start
            // timer is reset)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Starting(2900))
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_AUTO_START_SCREEN_RECORD_CHIP)
    fun screenRecordState_startingButThenDoingNothing_doesNotAutomaticallyStart() =
        testScope.runTest {
            val latest by collectLastValue(underTest.screenRecordState)

            // WHEN a screen recording is starting in 500ms
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Starting(500)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Starting(500))

            // But it's cancelled after 300ms
            advanceTimeBy(300)
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.DoingNothing

            // THEN we don't automatically start the recording 200ms later
            advanceTimeBy(201)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.DoingNothing)
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_AUTO_START_SCREEN_RECORD_CHIP)
    fun screenRecordState_multipleStartingValues_autoStartResets() =
        testScope.runTest {
            val latest by collectLastValue(underTest.screenRecordState)

            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Starting(2900)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Starting(2900))

            advanceTimeBy(2800)

            // WHEN there's 100ms left to go before auto-start, but then we get a new start time
            // that's in 500ms
            screenRecordRepo.screenRecordState.value = ScreenRecordModel.Starting(500)

            // THEN we don't auto-start in 100ms
            advanceTimeBy(101)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Starting(500))

            // THEN we *do* auto-start 400ms later
            advanceTimeBy(401)
            assertThat(latest).isEqualTo(ScreenRecordChipModel.Recording(recordedTask = null))
        }

    @Test
    @Test
    fun stopRecording_sendsToRepo() =
    fun stopRecording_sendsToRepo() =
        testScope.runTest {
        testScope.runTest {
+9 −29
Original line number Original line Diff line number Diff line
@@ -26,9 +26,8 @@ import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.mockDialogTransitionAnimator
import com.android.systemui.animation.mockDialogTransitionAnimator
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testCase
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
import com.android.systemui.mediaprojection.taskswitcher.FakeActivityTaskManager
import com.android.systemui.mediaprojection.taskswitcher.FakeActivityTaskManager
@@ -44,6 +43,7 @@ import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.getStopActionFromDialog
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlin.test.Test
@@ -61,7 +61,7 @@ import org.mockito.kotlin.whenever
@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
class ScreenRecordChipViewModelTest : SysuiTestCase() {
class ScreenRecordChipViewModelTest : SysuiTestCase() {
    private val kosmos = Kosmos().also { it.testCase = this }
    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val testScope = kosmos.testScope
    private val testScope = kosmos.testScope
    private val screenRecordRepo = kosmos.screenRecordRepository
    private val screenRecordRepo = kosmos.screenRecordRepository
    private val mediaProjectionRepo = kosmos.fakeMediaProjectionRepository
    private val mediaProjectionRepo = kosmos.fakeMediaProjectionRepository
@@ -254,7 +254,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
                MediaProjectionState.Projecting.SingleTask(
                MediaProjectionState.Projecting.SingleTask(
                    "host.package",
                    "host.package",
                    hostDeviceName = null,
                    hostDeviceName = null,
                    FakeActivityTaskManager.createTask(taskId = 1)
                    FakeActivityTaskManager.createTask(taskId = 1),
                )
                )


            // THEN the start time is still the old start time
            // THEN the start time is still the old start time
@@ -275,12 +275,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
            clickListener!!.onClick(chipView)
            clickListener!!.onClick(chipView)
            // EndScreenRecordingDialogDelegate will test that the dialog has the right message
            // EndScreenRecordingDialogDelegate will test that the dialog has the right message
            verify(kosmos.mockDialogTransitionAnimator)
            verify(kosmos.mockDialogTransitionAnimator)
                .showFromView(
                .showFromView(eq(mockSystemUIDialog), eq(chipBackgroundView), any(), anyBoolean())
                    eq(mockSystemUIDialog),
                    eq(chipBackgroundView),
                    any(),
                    anyBoolean(),
                )
        }
        }


    @Test
    @Test
@@ -297,12 +292,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
            clickListener!!.onClick(chipView)
            clickListener!!.onClick(chipView)
            // EndScreenRecordingDialogDelegate will test that the dialog has the right message
            // EndScreenRecordingDialogDelegate will test that the dialog has the right message
            verify(kosmos.mockDialogTransitionAnimator)
            verify(kosmos.mockDialogTransitionAnimator)
                .showFromView(
                .showFromView(eq(mockSystemUIDialog), eq(chipBackgroundView), any(), anyBoolean())
                    eq(mockSystemUIDialog),
                    eq(chipBackgroundView),
                    any(),
                    anyBoolean(),
                )
        }
        }


    @Test
    @Test
@@ -314,7 +304,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
                MediaProjectionState.Projecting.SingleTask(
                MediaProjectionState.Projecting.SingleTask(
                    "host.package",
                    "host.package",
                    hostDeviceName = null,
                    hostDeviceName = null,
                    FakeActivityTaskManager.createTask(taskId = 1)
                    FakeActivityTaskManager.createTask(taskId = 1),
                )
                )


            val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
            val clickListener = ((latest as OngoingActivityChipModel.Shown).onClickListener)
@@ -323,12 +313,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {
            clickListener!!.onClick(chipView)
            clickListener!!.onClick(chipView)
            // EndScreenRecordingDialogDelegate will test that the dialog has the right message
            // EndScreenRecordingDialogDelegate will test that the dialog has the right message
            verify(kosmos.mockDialogTransitionAnimator)
            verify(kosmos.mockDialogTransitionAnimator)
                .showFromView(
                .showFromView(eq(mockSystemUIDialog), eq(chipBackgroundView), any(), anyBoolean())
                    eq(mockSystemUIDialog),
                    eq(chipBackgroundView),
                    any(),
                    anyBoolean(),
                )
        }
        }


    @Test
    @Test
@@ -344,12 +329,7 @@ class ScreenRecordChipViewModelTest : SysuiTestCase() {


            val cujCaptor = argumentCaptor<DialogCuj>()
            val cujCaptor = argumentCaptor<DialogCuj>()
            verify(kosmos.mockDialogTransitionAnimator)
            verify(kosmos.mockDialogTransitionAnimator)
                .showFromView(
                .showFromView(any(), any(), cujCaptor.capture(), anyBoolean())
                    any(),
                    any(),
                    cujCaptor.capture(),
                    anyBoolean(),
                )


            assertThat(cujCaptor.firstValue.cujType)
            assertThat(cujCaptor.firstValue.cujType)
                .isEqualTo(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP)
                .isEqualTo(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP)
+2 −2
Original line number Original line Diff line number Diff line
@@ -29,7 +29,6 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testCase
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
@@ -48,6 +47,7 @@ import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
import com.android.systemui.statusbar.phone.ongoingcall.shared.model.inCallModel
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
import com.android.systemui.util.time.fakeSystemClock
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -72,7 +72,7 @@ import org.mockito.kotlin.whenever
@OptIn(ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
@DisableFlags(StatusBarNotifChips.FLAG_NAME)
@DisableFlags(StatusBarNotifChips.FLAG_NAME)
class OngoingActivityChipsViewModelTest : SysuiTestCase() {
class OngoingActivityChipsViewModelTest : SysuiTestCase() {
    private val kosmos = Kosmos().also { it.testCase = this }
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val testScope = kosmos.testScope
    private val systemClock = kosmos.fakeSystemClock
    private val systemClock = kosmos.fakeSystemClock


+82 −32
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


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


import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBuffer
@@ -28,14 +29,19 @@ import com.android.systemui.statusbar.chips.StatusBarChipsLog
import com.android.systemui.statusbar.chips.screenrecord.domain.model.ScreenRecordChipModel
import com.android.systemui.statusbar.chips.screenrecord.domain.model.ScreenRecordChipModel
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.stateIn
import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.launch


/** Interactor for the screen recording chip shown in the status bar. */
/** Interactor for the screen recording chip shown in the status bar. */
@SysUISingleton
@SysUISingleton
@OptIn(ExperimentalCoroutinesApi::class)
class ScreenRecordChipInteractor
class ScreenRecordChipInteractor
@Inject
@Inject
constructor(
constructor(
@@ -44,6 +50,32 @@ constructor(
    private val mediaProjectionRepository: MediaProjectionRepository,
    private val mediaProjectionRepository: MediaProjectionRepository,
    @StatusBarChipsLog private val logger: LogBuffer,
    @StatusBarChipsLog private val logger: LogBuffer,
) {
) {
    /**
     * Emits true if we should assume that we're currently screen recording, even if
     * [ScreenRecordRepository.screenRecordState] hasn't emitted [ScreenRecordModel.Recording] yet.
     */
    private val shouldAssumeIsRecording: Flow<Boolean> =
        screenRecordRepository.screenRecordState
            .transformLatest {
                when (it) {
                    is ScreenRecordModel.DoingNothing -> {
                        emit(false)
                    }
                    is ScreenRecordModel.Starting -> {
                        // If we're told that the recording will start in [it.millisUntilStarted],
                        // optimistically assume the recording did indeed start after that time even
                        // if [ScreenRecordRepository.screenRecordState] hasn't emitted
                        // [ScreenRecordModel.Recording] yet. Start 50ms early so that the chip
                        // timer will definitely be showing by the time the recording actually
                        // starts - see b/366448907.
                        delay(it.millisUntilStarted - 50)
                        emit(true)
                    }
                    is ScreenRecordModel.Recording -> {}
                }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), false)

    val screenRecordState: StateFlow<ScreenRecordChipModel> =
    val screenRecordState: StateFlow<ScreenRecordChipModel> =
        // ScreenRecordRepository has the main "is the screen being recorded?" state, and
        // ScreenRecordRepository has the main "is the screen being recorded?" state, and
        // MediaProjectionRepository has information about what specifically is being recorded (a
        // MediaProjectionRepository has information about what specifically is being recorded (a
@@ -51,25 +83,42 @@ constructor(
        combine(
        combine(
                screenRecordRepository.screenRecordState,
                screenRecordRepository.screenRecordState,
                mediaProjectionRepository.mediaProjectionState,
                mediaProjectionRepository.mediaProjectionState,
            ) { screenRecordState, mediaProjectionState ->
                shouldAssumeIsRecording,
            ) { screenRecordState, mediaProjectionState, shouldAssumeIsRecording ->
                if (
                    Flags.statusBarAutoStartScreenRecordChip() &&
                        shouldAssumeIsRecording &&
                        screenRecordState is ScreenRecordModel.Starting
                ) {
                    logger.log(
                        TAG,
                        LogLevel.INFO,
                        {},
                        { "State: Recording(taskPackage=null) due to force-start" },
                    )
                    ScreenRecordChipModel.Recording(recordedTask = null)
                } else {
                    when (screenRecordState) {
                    when (screenRecordState) {
                        is ScreenRecordModel.DoingNothing -> {
                        is ScreenRecordModel.DoingNothing -> {
                            logger.log(TAG, LogLevel.INFO, {}, { "State: DoingNothing" })
                            logger.log(TAG, LogLevel.INFO, {}, { "State: DoingNothing" })
                            ScreenRecordChipModel.DoingNothing
                            ScreenRecordChipModel.DoingNothing
                        }
                        }

                        is ScreenRecordModel.Starting -> {
                        is ScreenRecordModel.Starting -> {
                            logger.log(
                            logger.log(
                                TAG,
                                TAG,
                                LogLevel.INFO,
                                LogLevel.INFO,
                                { long1 = screenRecordState.millisUntilStarted },
                                { long1 = screenRecordState.millisUntilStarted },
                            { "State: Starting($long1)" }
                                { "State: Starting($long1)" },
                            )
                            )
                            ScreenRecordChipModel.Starting(screenRecordState.millisUntilStarted)
                            ScreenRecordChipModel.Starting(screenRecordState.millisUntilStarted)
                        }
                        }

                        is ScreenRecordModel.Recording -> {
                        is ScreenRecordModel.Recording -> {
                            val recordedTask =
                            val recordedTask =
                                if (
                                if (
                                mediaProjectionState is MediaProjectionState.Projecting.SingleTask
                                    mediaProjectionState
                                        is MediaProjectionState.Projecting.SingleTask
                                ) {
                                ) {
                                    mediaProjectionState.task
                                    mediaProjectionState.task
                                } else {
                                } else {
@@ -79,12 +128,13 @@ constructor(
                                TAG,
                                TAG,
                                LogLevel.INFO,
                                LogLevel.INFO,
                                { str1 = recordedTask?.baseIntent?.component?.packageName },
                                { str1 = recordedTask?.baseIntent?.component?.packageName },
                            { "State: Recording(taskPackage=$str1)" }
                                { "State: Recording(taskPackage=$str1)" },
                            )
                            )
                            ScreenRecordChipModel.Recording(recordedTask)
                            ScreenRecordChipModel.Recording(recordedTask)
                        }
                        }
                    }
                    }
                }
                }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), ScreenRecordChipModel.DoingNothing)
            .stateIn(scope, SharingStarted.WhileSubscribed(), ScreenRecordChipModel.DoingNothing)


    /** Stops the recording. */
    /** Stops the recording. */