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

Commit 92b59bc5 authored by Tao Wu's avatar Tao Wu Committed by Android (Google) Code Review
Browse files

Merge "Growth : add delay before broadcasting device entered event." into main

parents aaaa1ed6 733493bf
Loading
Loading
Loading
Loading
+78 −26
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.broadcast.mockBroadcastSender
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.advanceTimeBy
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
@@ -40,6 +41,7 @@ import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.flow.flowOf
import org.junit.Before
import org.junit.Test
@@ -51,7 +53,6 @@ import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.capture
import org.mockito.kotlin.eq
import org.mockito.kotlin.never
import org.mockito.kotlin.times

@@ -64,8 +65,7 @@ class GrowthInteractorTest : SysuiTestCase() {
    private val broadcastSender by lazy { kosmos.mockBroadcastSender }
    private lateinit var underTest: GrowthInteractor

    @Captor
    private lateinit var intentArgumentCaptor: ArgumentCaptor<Intent>
    @Captor private lateinit var intentArgumentCaptor: ArgumentCaptor<Intent>

    @Before
    fun setUp() {
@@ -76,57 +76,108 @@ class GrowthInteractorTest : SysuiTestCase() {
    @Test
    fun onDeviceEnteredDirectly_sendBroadcast_withAllConfigs() =
        kosmos.runTest {
            overrideResources()
            overrideResources(GROWTH_APP_PACKAGE_NAME, GROWTH_RECEIVER_CLASS_NAME)
            underTest = kosmos.growthInteractor
            underTest.activateIn(kosmos.testScope)
            setDeviceEntered()
            advanceTimeBy(GROWTH_BROADCAST_DELAY.plus(DURATION_50_MILLIS))
            runCurrent()

            verify(broadcastSender, times(1))
                .sendBroadcast(capture(intentArgumentCaptor), eq(GROWTH_RECEIVER_PERMISSION))
            verify(broadcastSender, times(1)).sendBroadcast(capture(intentArgumentCaptor))
            assertThat(intentArgumentCaptor.value.action)
                .isEqualTo(GrowthInteractor.ACTION_DEVICE_ENTERED_DIRECTLY)
            assertThat(intentArgumentCaptor.value.`package`).isEqualTo(GROWTH_APP_PACKAGE_NAME)
            assertThat(intentArgumentCaptor.value.`package`).isNull()
            assertThat(intentArgumentCaptor.value.component?.packageName)
                .isEqualTo(GROWTH_APP_PACKAGE_NAME)
            assertThat(intentArgumentCaptor.value.component?.className)
                .isEqualTo(GROWTH_RECEIVER_CLASS_NAME)
        }

    @Test
    fun onDeviceEnteredDirectly_sendBroadcast_withEmptyPackageName() =
        kosmos.runTest {
            overrideResources("", GROWTH_RECEIVER_CLASS_NAME)
            underTest = kosmos.growthInteractor
            underTest.activateIn(kosmos.testScope)
            setDeviceEntered()
            advanceTimeBy(GROWTH_BROADCAST_DELAY.plus(DURATION_50_MILLIS))
            runCurrent()

            verify(broadcastSender, times(1)).sendBroadcast(capture(intentArgumentCaptor))
            assertThat(intentArgumentCaptor.value.action)
                .isEqualTo(GrowthInteractor.ACTION_DEVICE_ENTERED_DIRECTLY)
            assertThat(intentArgumentCaptor.value.`package`).isNull()
            assertThat(intentArgumentCaptor.value.component).isNull()
        }

    @Test
    fun onDeviceEnteredDirectly_sendBroadcast_withEmptyReceiverClassName() =
        kosmos.runTest {
            overrideResources(GROWTH_APP_PACKAGE_NAME, "")
            underTest = kosmos.growthInteractor
            underTest.activateIn(kosmos.testScope)
            setDeviceEntered()
            advanceTimeBy(GROWTH_BROADCAST_DELAY.plus(DURATION_50_MILLIS))
            runCurrent()

            verify(broadcastSender, times(1)).sendBroadcast(capture(intentArgumentCaptor))
            assertThat(intentArgumentCaptor.value.action)
                .isEqualTo(GrowthInteractor.ACTION_DEVICE_ENTERED_DIRECTLY)
            assertThat(intentArgumentCaptor.value.`package`).isNull()
            assertThat(intentArgumentCaptor.value.component).isNull()
        }

    @Test
    fun onDeviceEnteredDirectly_sendBroadcast_withEmptyConfigs() =
        kosmos.runTest {
            overrideResourcesWithEmptyValues()
            overrideResources("", "")
            underTest = kosmos.growthInteractor
            underTest.activateIn(kosmos.testScope)
            setDeviceEntered()
            advanceTimeBy(GROWTH_BROADCAST_DELAY.plus(DURATION_50_MILLIS))
            runCurrent()

            verify(broadcastSender, times(1))
                .sendBroadcast(capture(intentArgumentCaptor))
            verify(broadcastSender, times(1)).sendBroadcast(capture(intentArgumentCaptor))
            assertThat(intentArgumentCaptor.value.action)
                .isEqualTo(GrowthInteractor.ACTION_DEVICE_ENTERED_DIRECTLY)
            assertThat(intentArgumentCaptor.value.`package`).isNull()
            assertThat(intentArgumentCaptor.value.component)
                .isNull()
            assertThat(intentArgumentCaptor.value.component).isNull()
        }

    @Test
    fun onDeviceNotEnteredDirectly_doNotSendBroadcast() =
    fun onDeviceNotEnteredDirectly_doNotSendBroadcast_onLockscreen() =
        kosmos.runTest {
            overrideResources(GROWTH_APP_PACKAGE_NAME, GROWTH_RECEIVER_CLASS_NAME)
            setDeviceEntered()
            advanceTimeBy(GROWTH_BROADCAST_DELAY.plus(DURATION_50_MILLIS))
            clearInvocations(broadcastSender)

            setScene(Scenes.Lockscreen)
            advanceTimeBy(GROWTH_BROADCAST_DELAY.plus(DURATION_50_MILLIS))
            verify(broadcastSender, never()).sendBroadcast(any(), any())
        }

    private fun overrideResources() {
        overrideResource(R.string.config_growthAppPackageName, GROWTH_APP_PACKAGE_NAME)
        overrideResource(R.string.config_growthReceiverClassName, GROWTH_RECEIVER_CLASS_NAME)
        overrideResource(R.string.config_growthReceiverPermission, GROWTH_RECEIVER_PERMISSION)
    @Test
    fun onDeviceEnteredDirectly_doNotSendBroadcast_lockedBeforeDelay() =
        kosmos.runTest {
            overrideResources(GROWTH_APP_PACKAGE_NAME, GROWTH_RECEIVER_CLASS_NAME)
            underTest = kosmos.growthInteractor
            underTest.activateIn(kosmos.testScope)
            setDeviceEntered()
            advanceTimeBy(DURATION_50_MILLIS)
            runCurrent()
            verify(broadcastSender, never()).sendBroadcast(any(), any())

            setScene(Scenes.Lockscreen)
            advanceTimeBy(GROWTH_BROADCAST_DELAY.plus(DURATION_50_MILLIS))
            runCurrent()
            verify(broadcastSender, never()).sendBroadcast(any(), any())
        }

    private fun overrideResourcesWithEmptyValues() {
        overrideResource(R.string.config_growthAppPackageName, "")
        overrideResource(R.string.config_growthReceiverClassName, "")
        overrideResource(R.string.config_growthReceiverPermission, "")
    private fun overrideResources(packageName: String, receiverClassName: String) {
        overrideResource(R.string.config_growthAppPackageName, packageName)
        overrideResource(R.string.config_growthReceiverClassName, receiverClassName)
        overrideResource(R.integer.config_growthBroadcastDelayMillis, DELAY_200_MILLIS)
    }

    private suspend fun Kosmos.setDeviceEntered() {
@@ -155,7 +206,8 @@ class GrowthInteractorTest : SysuiTestCase() {
    companion object {
        private const val GROWTH_APP_PACKAGE_NAME = "com.android.systemui.growth"
        private const val GROWTH_RECEIVER_CLASS_NAME = "com.android.systemui.growth.GrowthReceiver"
        private const val GROWTH_RECEIVER_PERMISSION =
            "com.android.systemui.growth.permission.SEND_BROADCAST"
        private const val DELAY_200_MILLIS = 200
        private val GROWTH_BROADCAST_DELAY = DELAY_200_MILLIS.milliseconds
        private val DURATION_50_MILLIS = 50.milliseconds
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -1145,6 +1145,6 @@
    <string name="config_growthAppPackageName" translatable="false" />
    <!-- Class name for the growth app's receiver. -->
    <string name="config_growthReceiverClassName" translatable="false" />
    <!-- Permission to send a broadcast to the growth app receiver. -->
    <string name="config_growthReceiverPermission" translatable="false" />
    <!-- Delay in milliseconds before sending the broadcast to the growth app. -->
    <integer name="config_growthBroadcastDelayMillis">10000</integer>
</resources>
+30 −16
Original line number Diff line number Diff line
@@ -28,6 +28,11 @@ import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.res.R
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

/** Interactor to communicate with the growth app. */
@SysUISingleton
@@ -38,31 +43,40 @@ constructor(
    private val deviceEntryInteractor: Lazy<DeviceEntryInteractor>,
    private val broadcastSender: BroadcastSender,
) : ExclusiveActivatable() {
    private val growthAppPackageName =
        resources.getString(R.string.config_growthAppPackageName)
    private val growthAppPackageName = resources.getString(R.string.config_growthAppPackageName)
    private val growthReceiverClassName =
        resources.getString(R.string.config_growthReceiverClassName)
    private val growthReceiverPermission =
        resources.getString(R.string.config_growthReceiverPermission)
    private val growthBroadcastDelayMillis =
        resources.getInteger(R.integer.config_growthBroadcastDelayMillis)

    private var sendBroadcastJob: Job? = null

    override suspend fun onActivated(): Nothing {
        deviceEntryInteractor.get().isDeviceEnteredDirectly.collect {
            // Cancel any existing job before launching a new one.
            sendBroadcastJob?.cancel()
            sendBroadcastJob = null

            if (it) {
                // Broadcast the device entered event to the growth app.
                // Launch the delayed task.
                sendBroadcastJob = coroutineScope {
                    launch {
                        delay(growthBroadcastDelayMillis.toLong())
                        sendBroadcast()
                    }
                }
            }
        }
    }

    private suspend fun sendBroadcast() {
        // Broadcast the device entered event.
        val intent = Intent().apply { setAction(ACTION_DEVICE_ENTERED_DIRECTLY) }
        if (growthAppPackageName.isNotEmpty() && growthReceiverClassName.isNotEmpty()) {
                    intent.setPackage(growthAppPackageName)
            intent.setComponent(ComponentName(growthAppPackageName, growthReceiverClassName))
        }

                if (growthReceiverPermission.isNotEmpty()) {
                    broadcastSender.sendBroadcast(intent, growthReceiverPermission)
                } else {
        broadcastSender.sendBroadcast(intent)
    }
            }
        }
    }

    companion object {
        @VisibleForTesting