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

Commit 8b62f655 authored by Sherry Zhou's avatar Sherry Zhou
Browse files

Refactor focal area to avoid launch scope in WallpaperRepository

Bug: 394939260
Test: atest WallpaperFocalAreaInteractorTest, WallpaperFocalAreaViewModelTest
Flag: com.android.systemui.shared.extended_wallpaper_effects

Change-Id: I077abaaab2b700019e13a9c1c225b4e585b11346
parent 2fb1425d
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
@@ -53,7 +52,6 @@ import org.mockito.kotlin.whenever
@SmallTest
@RunWith(AndroidJUnit4::class)
class WallpaperRepositoryImplTest : SysuiTestCase() {

    private var isWallpaperSupported = true
    private val kosmos =
        testKosmos().apply {
@@ -293,12 +291,9 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
                Intent(Intent.ACTION_WALLPAPER_CHANGED),
            )
            assertThat(latest).isTrue()
            assertThat(underTest.sendLockscreenLayoutJob).isNotNull()
            assertThat(underTest.sendLockscreenLayoutJob!!.isActive).isEqualTo(true)
        }

    @Test
    @Ignore("ag/31591766")
    @EnableFlags(SharedFlags.FLAG_EXTENDED_WALLPAPER_EFFECTS)
    fun shouldSendNotificationLayout_setNotExtendedEffectsWallpaper_cancelSendLayoutJob() =
        testScope.runTest {
@@ -315,8 +310,6 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
                Intent(Intent.ACTION_WALLPAPER_CHANGED),
            )
            assertThat(latest).isTrue()
            assertThat(underTest.sendLockscreenLayoutJob).isNotNull()
            assertThat(underTest.sendLockscreenLayoutJob!!.isActive).isEqualTo(true)

            whenever(kosmos.wallpaperManager.getWallpaperInfoForUser(any()))
                .thenReturn(UNSUPPORTED_WP)
@@ -327,7 +320,6 @@ class WallpaperRepositoryImplTest : SysuiTestCase() {
            runCurrent()

            assertThat(latest).isFalse()
            assertThat(underTest.sendLockscreenLayoutJob?.isCancelled).isEqualTo(true)
        }

    private companion object {
+34 −27
Original line number Diff line number Diff line
@@ -30,11 +30,8 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
import com.android.systemui.testKosmos
import com.android.systemui.wallpapers.data.repository.fakeWallpaperFocalAreaRepository
import com.android.systemui.wallpapers.data.repository.wallpaperFocalAreaRepository
import com.android.systemui.wallpapers.data.repository.wallpaperRepository
import com.android.systemui.wallpapers.ui.viewmodel.wallpaperFocalAreaViewModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -75,36 +72,22 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
            .thenReturn(2f)
        underTest =
            WallpaperFocalAreaInteractor(
                applicationScope = testScope.backgroundScope,
                context = kosmos.mockedContext,
                wallpaperFocalAreaRepository = kosmos.fakeWallpaperFocalAreaRepository,
                wallpaperFocalAreaRepository = kosmos.wallpaperFocalAreaRepository,
                shadeRepository = kosmos.shadeRepository,
                activeNotificationsInteractor = kosmos.activeNotificationsInteractor,
                wallpaperRepository = kosmos.wallpaperRepository,
            )
    }

    private fun overrideMockedResources(overrideResources: OverrideResources) {
        val displayMetrics =
            DisplayMetrics().apply {
                widthPixels = overrideResources.screenWidth
                heightPixels = overrideResources.screenHeight
                density = 2f
            }
        whenever(mockedResources.displayMetrics).thenReturn(displayMetrics)
        whenever(mockedResources.getBoolean(R.bool.center_align_focal_area_shape))
            .thenReturn(overrideResources.centerAlignFocalArea)
    }

    @Test
    fun focalAreaBounds_withoutNotifications_inHandheldDevices() =
        testScope.runTest {
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 1000,
                    screenHeight = 2000,
                    centerAlignFocalArea = false,
                )
                ),
            )
            val bounds by collectLastValue(underTest.wallpaperFocalAreaBounds)
            kosmos.shadeRepository.setShadeLayoutWide(false)
@@ -120,11 +103,12 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
    fun focalAreaBounds_withNotifications_inHandheldDevices() =
        testScope.runTest {
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 1000,
                    screenHeight = 2000,
                    centerAlignFocalArea = false,
                )
                ),
            )
            val bounds by collectLastValue(underTest.wallpaperFocalAreaBounds)
            kosmos.shadeRepository.setShadeLayoutWide(false)
@@ -139,11 +123,12 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
    fun focalAreaBounds_inUnfoldLandscape() =
        testScope.runTest {
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 2000,
                    screenHeight = 1600,
                    centerAlignFocalArea = false,
                )
                ),
            )
            val bounds by collectLastValue(underTest.wallpaperFocalAreaBounds)
            kosmos.shadeRepository.setShadeLayoutWide(true)
@@ -158,11 +143,12 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
    fun focalAreaBounds_withNotifications_inUnfoldPortrait() =
        testScope.runTest {
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 1600,
                    screenHeight = 2000,
                    centerAlignFocalArea = false,
                )
                ),
            )
            val bounds by collectLastValue(underTest.wallpaperFocalAreaBounds)
            kosmos.shadeRepository.setShadeLayoutWide(false)
@@ -177,11 +163,12 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
    fun focalAreaBounds_withoutNotifications_inUnfoldPortrait() =
        testScope.runTest {
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 1600,
                    screenHeight = 2000,
                    centerAlignFocalArea = false,
                )
                ),
            )
            val bounds by collectLastValue(underTest.wallpaperFocalAreaBounds)
            kosmos.shadeRepository.setShadeLayoutWide(false)
@@ -196,11 +183,12 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
    fun focalAreaBounds_inTabletLandscape() =
        testScope.runTest {
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 3000,
                    screenHeight = 2000,
                    centerAlignFocalArea = true,
                )
                ),
            )
            val bounds by collectLastValue(underTest.wallpaperFocalAreaBounds)
            kosmos.shadeRepository.setShadeLayoutWide(true)
@@ -216,11 +204,12 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
        testScope.runTest {
            kosmos.wallpaperFocalAreaRepository.setTapPosition(PointF(0F, 0F))
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 1000,
                    screenHeight = 2000,
                    centerAlignFocalArea = false,
                )
                ),
            )
            kosmos.wallpaperFocalAreaRepository.setWallpaperFocalAreaBounds(
                RectF(250f, 700F, 750F, 1400F)
@@ -240,11 +229,12 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
        testScope.runTest {
            kosmos.wallpaperFocalAreaRepository.setTapPosition(PointF(0F, 0F))
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 1000,
                    screenHeight = 2000,
                    centerAlignFocalArea = false,
                )
                ),
            )
            kosmos.wallpaperFocalAreaViewModel = mock()
            kosmos.wallpaperFocalAreaRepository.setWallpaperFocalAreaBounds(
@@ -262,4 +252,21 @@ class WallpaperFocalAreaInteractorTest : SysuiTestCase() {
        val screenHeight: Int,
        val centerAlignFocalArea: Boolean,
    )

    companion object {
        fun overrideMockedResources(
            mockedResources: Resources,
            overrideResources: OverrideResources,
        ) {
            val displayMetrics =
                DisplayMetrics().apply {
                    widthPixels = overrideResources.screenWidth
                    heightPixels = overrideResources.screenHeight
                    density = 2f
                }
            whenever(mockedResources.displayMetrics).thenReturn(displayMetrics)
            whenever(mockedResources.getBoolean(R.bool.center_align_focal_area_shape))
                .thenReturn(overrideResources.centerAlignFocalArea)
        }
    }
}
+148 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.wallpapers.ui.viewmodel

import android.content.mockedContext
import android.content.res.Resources
import android.graphics.RectF
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.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
import com.android.systemui.testKosmos
import com.android.systemui.wallpapers.data.repository.wallpaperFocalAreaRepository
import com.android.systemui.wallpapers.domain.interactor.WallpaperFocalAreaInteractor
import com.android.systemui.wallpapers.domain.interactor.WallpaperFocalAreaInteractorTest.Companion.overrideMockedResources
import com.android.systemui.wallpapers.domain.interactor.WallpaperFocalAreaInteractorTest.OverrideResources
import com.android.systemui.wallpapers.domain.interactor.wallpaperFocalAreaInteractor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

@ExperimentalCoroutinesApi
@SmallTest
@RunWith(AndroidJUnit4::class)
class WallpaperFocalAreaViewModelTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private lateinit var mockedResources: Resources
    lateinit var underTest: WallpaperFocalAreaViewModel

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)
        mockedResources = mock<Resources>()
        overrideMockedResources(
            mockedResources,
            OverrideResources(screenWidth = 1000, screenHeight = 2000, centerAlignFocalArea = false),
        )
        whenever(kosmos.mockedContext.resources).thenReturn(mockedResources)
        whenever(
                mockedResources.getFloat(
                    Resources.getSystem()
                        .getIdentifier(
                            /* name= */ "config_wallpaperMaxScale",
                            /* defType= */ "dimen",
                            /* defPackage= */ "android",
                        )
                )
            )
            .thenReturn(2f)
        kosmos.wallpaperFocalAreaInteractor =
            WallpaperFocalAreaInteractor(
                context = kosmos.mockedContext,
                wallpaperFocalAreaRepository = kosmos.wallpaperFocalAreaRepository,
                shadeRepository = kosmos.shadeRepository,
            )
        underTest =
            WallpaperFocalAreaViewModel(
                wallpaperFocalAreaInteractor = kosmos.wallpaperFocalAreaInteractor,
                keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
            )
    }

    @Test
    fun focalAreaBoundsSent_whenFinishTransitioningToLockscreen() =
        testScope.runTest {
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 1600,
                    screenHeight = 2000,
                    centerAlignFocalArea = false,
                ),
            )
            val bounds by collectLastValue(underTest.wallpaperFocalAreaBounds)

            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                listOf(
                    TransitionStep(transitionState = TransitionState.STARTED, to = LOCKSCREEN),
                    TransitionStep(transitionState = TransitionState.FINISHED, to = LOCKSCREEN),
                ),
                testScope,
            )

            setTestFocalAreaBounds()

            assertThat(bounds).isEqualTo(RectF(400F, 510F, 1200F, 700F))
        }

    @Test
    fun focalAreaBoundsNotSent_whenNotFinishTransitioningToLockscreen() =
        testScope.runTest {
            overrideMockedResources(
                mockedResources,
                OverrideResources(
                    screenWidth = 1600,
                    screenHeight = 2000,
                    centerAlignFocalArea = false,
                ),
            )
            val bounds by collectLastValue(underTest.wallpaperFocalAreaBounds)

            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                listOf(TransitionStep(transitionState = TransitionState.STARTED, to = LOCKSCREEN)),
                testScope,
            )
            setTestFocalAreaBounds()

            assertThat(bounds).isEqualTo(null)
        }

    private fun setTestFocalAreaBounds() {
        kosmos.shadeRepository.setShadeLayoutWide(false)
        kosmos.activeNotificationListRepository.setActiveNotifs(0)
        kosmos.wallpaperFocalAreaRepository.setShortcutAbsoluteTop(400F)
        kosmos.wallpaperFocalAreaRepository.setNotificationDefaultTop(20F)
        kosmos.wallpaperFocalAreaRepository.setNotificationStackAbsoluteBottom(20F)
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -369,6 +369,14 @@ object KeyguardRootViewBinder {
            view.repeatWhenAttached {
                repeatOnLifecycle(Lifecycle.State.STARTED) {
                    if (wallpaperFocalAreaViewModel.hasFocalArea.value) {
                        launch {
                            wallpaperFocalAreaViewModel.wallpaperFocalAreaBounds.collect {
                                wallpaperFocalAreaBounds ->
                                wallpaperFocalAreaViewModel.setFocalAreaBounds(
                                    wallpaperFocalAreaBounds
                                )
                            }
                        }
                        launch {
                            wallpaperFocalAreaViewModel.wallpaperFocalAreaBounds
                                .filterNotNull()
+6 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.systemui.wallpapers.data.repository

import android.app.WallpaperInfo
import android.graphics.PointF
import android.graphics.RectF
import android.view.View
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
@@ -37,4 +39,8 @@ class NoopWallpaperRepository @Inject constructor() : WallpaperRepository {
    override val wallpaperSupportsAmbientMode = flowOf(false)
    override var rootView: View? = null
    override val shouldSendFocalArea: StateFlow<Boolean> = MutableStateFlow(false).asStateFlow()

    override fun sendLockScreenLayoutChangeCommand(wallpaperFocalAreaBounds: RectF) {}

    override fun sendTapCommand(tapPosition: PointF) {}
}
Loading