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

Commit 275847c7 authored by Darrell Shi's avatar Darrell Shi
Browse files

Implement UMO transitions to & from the communal hub

Bug: 311243906
Fix: 311243906
Test: verified UMO transitions to & from keyguard and dream
Test: atest CommunalTransitionViewModelTest
Test: atest MediaHierarchyManagerTest
Test: atest LockscreenToGlanceableHubTransitionViewModelTest
Test: atest GlanceableHubToLockscreenTransitionViewModelTest
Flag: ACONFIG com.android.systemui.communal_hub TEAMFOOD
Change-Id: Ib0ac59d2d7f8d36ca9de8bf6041e75e1932b9c1e
parent cd407d19
Loading
Loading
Loading
Loading
+89 −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.communal.ui.viewmodel

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class CommunalTransitionViewModelTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope

    val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository

    private lateinit var underTest: CommunalTransitionViewModel

    @Before
    fun setup() {
        underTest = kosmos.communalTransitionViewModel
    }

    @Test
    fun testIsUmoOnCommunalDuringTransitionBetweenLockscreenAndGlanceableHub() =
        testScope.runTest {
            val isUmoOnCommunal by collectLastValue(underTest.isUmoOnCommunal)
            assertThat(isUmoOnCommunal).isNull()

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GLANCEABLE_HUB,
                testScope
            )
            assertThat(isUmoOnCommunal).isTrue()

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.LOCKSCREEN,
                testScope
            )
            assertThat(isUmoOnCommunal).isFalse()
        }

    @Test
    fun testIsUmoOnCommunalDuringTransitionBetweenDreamingAndGlanceableHub() =
        testScope.runTest {
            val isUmoOnCommunal by collectLastValue(underTest.isUmoOnCommunal)
            assertThat(isUmoOnCommunal).isNull()

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.DREAMING,
                to = KeyguardState.GLANCEABLE_HUB,
                testScope
            )
            assertThat(isUmoOnCommunal).isTrue()

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.DREAMING,
                testScope
            )
            assertThat(isUmoOnCommunal).isFalse()
        }
}
+2 −2
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ class GlanceableHubToLockscreenTransitionViewModelTest : SysuiTestCase() {
    fun lockscreenFadeIn() =
        testScope.runTest {
            val values by collectValues(underTest.keyguardAlpha)
            assertThat(values).containsExactly(0f)
            assertThat(values).isEmpty()

            keyguardTransitionRepository.sendTransitionSteps(
                listOf(
@@ -70,7 +70,7 @@ class GlanceableHubToLockscreenTransitionViewModelTest : SysuiTestCase() {
                testScope,
            )

            assertThat(values).hasSize(5)
            assertThat(values).hasSize(4)
            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
        }

+2 −2
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ class LockscreenToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
    fun lockscreenFadeOut() =
        testScope.runTest {
            val values by collectValues(underTest.keyguardAlpha)
            assertThat(values).containsExactly(1f)
            assertThat(values).isEmpty()

            keyguardTransitionRepository.sendTransitionSteps(
                listOf(
@@ -71,7 +71,7 @@ class LockscreenToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
                testScope,
            )

            assertThat(values).hasSize(4)
            assertThat(values).hasSize(3)
            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
        }

+54 −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.communal.ui.viewmodel

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToGlanceableHubTransitionViewModel
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.merge

/** View model for transitions related to the communal hub. */
@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalTransitionViewModel
@Inject
constructor(
    glanceableHubToLockscreenTransitionViewModel: GlanceableHubToLockscreenTransitionViewModel,
    lockscreenToGlanceableHubTransitionViewModel: LockscreenToGlanceableHubTransitionViewModel,
    dreamToGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel,
    glanceableHubToDreamTransitionViewModel: GlanceableHubToDreamingTransitionViewModel,
) {
    /**
     * Whether UMO location should be on communal. This flow is responsive to transitions so that a
     * new value is emitted at the right step of a transition to/from communal hub that the location
     * of UMO should be updated.
     */
    val isUmoOnCommunal: Flow<Boolean> =
        merge(
                lockscreenToGlanceableHubTransitionViewModel.showUmo,
                glanceableHubToLockscreenTransitionViewModel.showUmo,
                dreamToGlanceableHubTransitionViewModel.showUmo,
                glanceableHubToDreamTransitionViewModel.showUmo,
            )
            .distinctUntilChanged()
}
+12 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map

@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
@@ -71,6 +72,17 @@ constructor(
            name = "DREAMING->GLANCEABLE_HUB: dreamOverlayAlpha",
        )

    // Show UMO once the transition starts.
    val showUmo: Flow<Boolean> =
        transitionAnimation
            .sharedFlow(
                duration = TO_GLANCEABLE_HUB_DURATION,
                onStep = { it },
                onCancel = { 0f },
                onFinish = { 1f },
            )
            .map { step -> step != 0f }

    private companion object {
        val TO_GLANCEABLE_HUB_DURATION = 1.seconds
    }
Loading