diff options
| author | 2025-02-13 22:58:12 +0000 | |
|---|---|---|
| committer | 2025-02-14 02:02:37 +0000 | |
| commit | 8b62f6551fab8ab9a0477cd5b5da967d3011f37f (patch) | |
| tree | 4c2a19a57adf22b546410b737f1f66f5fa9d359a | |
| parent | 2fb1425dc6ed630275f5c6b667ad132e01f3dfc4 (diff) | |
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
14 files changed, 301 insertions, 149 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt index 7c166de81502..cc6a7b93eef3 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt @@ -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 { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractorTest.kt index 31afc298951b..31a611cc984b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractorTest.kt @@ -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) + } + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModelTest.kt new file mode 100644 index 000000000000..3cd20721a15b --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModelTest.kt @@ -0,0 +1,148 @@ +/* + * 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) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt index 8e385385b8c4..da87e38daa9b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt @@ -370,6 +370,14 @@ object KeyguardRootViewBinder { repeatOnLifecycle(Lifecycle.State.STARTED) { if (wallpaperFocalAreaViewModel.hasFocalArea.value) { launch { + wallpaperFocalAreaViewModel.wallpaperFocalAreaBounds.collect { + wallpaperFocalAreaBounds -> + wallpaperFocalAreaViewModel.setFocalAreaBounds( + wallpaperFocalAreaBounds + ) + } + } + launch { wallpaperFocalAreaViewModel.wallpaperFocalAreaBounds .filterNotNull() .collect { wallpaperFocalAreaViewModel.setFocalAreaBounds(it) } diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt index ec74f4f47bc9..300a7e070b6c 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt @@ -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) {} } diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperFocalAreaRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperFocalAreaRepository.kt index 2c3491b06a90..974468c16578 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperFocalAreaRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperFocalAreaRepository.kt @@ -33,7 +33,8 @@ interface WallpaperFocalAreaRepository { val wallpaperFocalAreaBounds: StateFlow<RectF> - val wallpaperFocalAreaTapPosition: StateFlow<PointF> + /** It will be true when wallpaper requires focal area info. */ + val hasFocalArea: StateFlow<Boolean> /** top of notifications without bcsmartspace in small clock settings */ val notificationDefaultTop: StateFlow<Float> @@ -51,7 +52,9 @@ interface WallpaperFocalAreaRepository { } @SysUISingleton -class WallpaperFocalAreaRepositoryImpl @Inject constructor() : WallpaperFocalAreaRepository { +class WallpaperFocalAreaRepositoryImpl +@Inject +constructor(val wallpaperRepository: WallpaperRepository) : WallpaperFocalAreaRepository { private val _shortcutAbsoluteTop = MutableStateFlow(0F) override val shortcutAbsoluteTop = _shortcutAbsoluteTop.asStateFlow() @@ -63,13 +66,11 @@ class WallpaperFocalAreaRepositoryImpl @Inject constructor() : WallpaperFocalAre override val wallpaperFocalAreaBounds: StateFlow<RectF> = _wallpaperFocalAreaBounds.asStateFlow() - private val _wallpaperFocalAreaTapPosition = MutableStateFlow(PointF(0F, 0F)) - override val wallpaperFocalAreaTapPosition: StateFlow<PointF> = - _wallpaperFocalAreaTapPosition.asStateFlow() - private val _notificationDefaultTop = MutableStateFlow(0F) override val notificationDefaultTop: StateFlow<Float> = _notificationDefaultTop.asStateFlow() + override val hasFocalArea = wallpaperRepository.shouldSendFocalArea + override fun setShortcutAbsoluteTop(top: Float) { _shortcutAbsoluteTop.value = top } @@ -84,9 +85,10 @@ class WallpaperFocalAreaRepositoryImpl @Inject constructor() : WallpaperFocalAre override fun setWallpaperFocalAreaBounds(bounds: RectF) { _wallpaperFocalAreaBounds.value = bounds + wallpaperRepository.sendLockScreenLayoutChangeCommand(bounds) } - override fun setTapPosition(point: PointF) { - _wallpaperFocalAreaTapPosition.value = point + override fun setTapPosition(tapPosition: PointF) { + wallpaperRepository.sendTapCommand(tapPosition) } } diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt index a55f76b333d9..b07342c4c76d 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt @@ -21,22 +21,18 @@ import android.app.WallpaperManager import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.graphics.PointF +import android.graphics.RectF import android.os.Bundle import android.os.UserHandle import android.provider.Settings +import android.util.Log import android.view.View -import androidx.annotation.VisibleForTesting -import com.android.app.tracing.coroutines.launchTraced as launch import com.android.internal.R import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background -import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor -import com.android.systemui.keyguard.shared.model.Edge -import com.android.systemui.keyguard.shared.model.KeyguardState -import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.res.R as SysUIR -import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shared.Flags.ambientAod import com.android.systemui.shared.Flags.extendedWallpaperEffects import com.android.systemui.user.data.model.SelectedUserModel @@ -48,7 +44,6 @@ import com.android.systemui.utils.coroutines.flow.mapLatestConflated import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -76,6 +71,10 @@ interface WallpaperRepository { /** some wallpapers require bounds to be sent from keyguard */ val shouldSendFocalArea: StateFlow<Boolean> + + fun sendLockScreenLayoutChangeCommand(wallpaperFocalAreaBounds: RectF) + + fun sendTapCommand(tapPosition: PointF) } @SysUISingleton @@ -86,10 +85,8 @@ constructor( @Background private val bgDispatcher: CoroutineDispatcher, broadcastDispatcher: BroadcastDispatcher, userRepository: UserRepository, - wallpaperFocalAreaRepository: WallpaperFocalAreaRepository, private val wallpaperManager: WallpaperManager, private val context: Context, - keyguardTransitionInteractor: KeyguardTransitionInteractor, private val secureSettings: SecureSettings, ) : WallpaperRepository { private val wallpaperChanged: Flow<Unit> = @@ -109,9 +106,6 @@ constructor( // Only update the wallpaper status once the user selection has finished. .filter { it.selectionStatus == SelectionStatus.SELECTION_COMPLETE } - @VisibleForTesting var sendLockscreenLayoutJob: Job? = null - @VisibleForTesting var sendTapInShapeEffectsJob: Job? = null - override val wallpaperInfo: StateFlow<WallpaperInfo?> = if (!wallpaperManager.isWallpaperSupported) { MutableStateFlow(null).asStateFlow() @@ -143,77 +137,45 @@ constructor( override var rootView: View? = null + override fun sendLockScreenLayoutChangeCommand(wallpaperFocalAreaBounds: RectF) { + if (DEBUG) { + Log.d(TAG, "sendLockScreenLayoutChangeCommand $wallpaperFocalAreaBounds") + } + wallpaperManager.sendWallpaperCommand( + /* windowToken = */ rootView?.windowToken, + /* action = */ WallpaperManager.COMMAND_LOCKSCREEN_LAYOUT_CHANGED, + /* x = */ 0, + /* y = */ 0, + /* z = */ 0, + /* extras = */ Bundle().apply { + putFloat("wallpaperFocalAreaLeft", wallpaperFocalAreaBounds.left) + putFloat("wallpaperFocalAreaRight", wallpaperFocalAreaBounds.right) + putFloat("wallpaperFocalAreaTop", wallpaperFocalAreaBounds.top) + putFloat("wallpaperFocalAreaBottom", wallpaperFocalAreaBounds.bottom) + }, + ) + } + + override fun sendTapCommand(tapPosition: PointF) { + if (DEBUG) { + Log.d(TAG, "sendTapCommand $tapPosition") + } + + wallpaperManager.sendWallpaperCommand( + /* windowToken = */ rootView?.windowToken, + /* action = */ WallpaperManager.COMMAND_LOCKSCREEN_TAP, + /* x = */ tapPosition.x.toInt(), + /* y = */ tapPosition.y.toInt(), + /* z = */ 0, + /* extras = */ Bundle(), + ) + } + override val shouldSendFocalArea = wallpaperInfo .map { val focalAreaTarget = context.resources.getString(SysUIR.string.focal_area_target) val shouldSendNotificationLayout = it?.component?.className == focalAreaTarget - if (shouldSendNotificationLayout) { - sendLockscreenLayoutJob = - scope.launch { - combine( - wallpaperFocalAreaRepository.wallpaperFocalAreaBounds, - keyguardTransitionInteractor - .transition( - edge = Edge.create(to = Scenes.Lockscreen), - edgeWithoutSceneContainer = - Edge.create(to = KeyguardState.LOCKSCREEN), - ) - .filter { transitionStep -> - transitionStep.transitionState == - TransitionState.STARTED - }, - ::Pair, - ) - .map { (bounds, _) -> bounds } - .collect { wallpaperFocalAreaBounds -> - wallpaperManager.sendWallpaperCommand( - /* windowToken = */ rootView?.windowToken, - /* action = */ WallpaperManager - .COMMAND_LOCKSCREEN_LAYOUT_CHANGED, - /* x = */ 0, - /* y = */ 0, - /* z = */ 0, - /* extras = */ Bundle().apply { - putFloat( - "wallpaperFocalAreaLeft", - wallpaperFocalAreaBounds.left, - ) - putFloat( - "wallpaperFocalAreaRight", - wallpaperFocalAreaBounds.right, - ) - putFloat( - "wallpaperFocalAreaTop", - wallpaperFocalAreaBounds.top, - ) - putFloat( - "wallpaperFocalAreaBottom", - wallpaperFocalAreaBounds.bottom, - ) - }, - ) - } - } - - sendTapInShapeEffectsJob = - scope.launch { - wallpaperFocalAreaRepository.wallpaperFocalAreaTapPosition.collect { - wallpaperFocalAreaTapPosition -> - wallpaperManager.sendWallpaperCommand( - /* windowToken = */ rootView?.windowToken, - /* action = */ WallpaperManager.COMMAND_LOCKSCREEN_TAP, - /* x = */ wallpaperFocalAreaTapPosition.x.toInt(), - /* y = */ wallpaperFocalAreaTapPosition.y.toInt(), - /* z = */ 0, - /* extras = */ null, - ) - } - } - } else { - sendLockscreenLayoutJob?.cancel() - sendTapInShapeEffectsJob?.cancel() - } shouldSendNotificationLayout } .stateIn( @@ -227,4 +189,9 @@ constructor( wallpaperManager.getWallpaperInfoForUser(selectedUser.userInfo.id) } } + + companion object { + private val TAG = WallpaperRepositoryImpl::class.simpleName + private val DEBUG = true + } } diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractor.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractor.kt index 9b0f8280cab2..09c6cdf0ce22 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractor.kt @@ -24,31 +24,25 @@ import android.util.Log import android.util.TypedValue import com.android.app.animation.MathUtils import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.res.R import com.android.systemui.shade.data.repository.ShadeRepository -import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor import com.android.systemui.wallpapers.data.repository.WallpaperFocalAreaRepository -import com.android.systemui.wallpapers.data.repository.WallpaperRepository import javax.inject.Inject import kotlin.math.min -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter @SysUISingleton class WallpaperFocalAreaInteractor @Inject constructor( - @Application private val applicationScope: CoroutineScope, private val context: Context, private val wallpaperFocalAreaRepository: WallpaperFocalAreaRepository, shadeRepository: ShadeRepository, - activeNotificationsInteractor: ActiveNotificationsInteractor, - val wallpaperRepository: WallpaperRepository, ) { - val hasFocalArea = wallpaperRepository.shouldSendFocalArea + val hasFocalArea = wallpaperFocalAreaRepository.hasFocalArea val wallpaperFocalAreaBounds: Flow<RectF> = combine( @@ -126,6 +120,8 @@ constructor( val bottom = scaledBounds.bottom - scaledBottomMargin RectF(left, top, right, bottom).also { Log.d(TAG, "Focal area changes to $it") } } + // Make sure a valid rec + .filter { it.width() >= 0 && it.height() >= 0 } .distinctUntilChanged() fun setFocalAreaBounds(bounds: RectF) { diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModel.kt index 70a97d473c49..4cd49d03ad36 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModel.kt @@ -17,15 +17,41 @@ package com.android.systemui.wallpapers.ui.viewmodel import android.graphics.RectF +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.Edge +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.wallpapers.domain.interactor.WallpaperFocalAreaInteractor import javax.inject.Inject +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map class WallpaperFocalAreaViewModel @Inject -constructor(private val wallpaperFocalAreaInteractor: WallpaperFocalAreaInteractor) { +constructor( + private val wallpaperFocalAreaInteractor: WallpaperFocalAreaInteractor, + val keyguardTransitionInteractor: KeyguardTransitionInteractor, +) { val hasFocalArea = wallpaperFocalAreaInteractor.hasFocalArea - val wallpaperFocalAreaBounds = wallpaperFocalAreaInteractor.wallpaperFocalAreaBounds + val wallpaperFocalAreaBounds = + combine( + wallpaperFocalAreaInteractor.wallpaperFocalAreaBounds, + keyguardTransitionInteractor + .transition( + edge = Edge.create(to = Scenes.Lockscreen), + edgeWithoutSceneContainer = Edge.create(to = KeyguardState.LOCKSCREEN), + ) + .filter { transitionStep -> + // Should not filter by TransitionState.STARTED, it may race with + // wakingup command, causing layout change command not be received. + transitionStep.transitionState == TransitionState.FINISHED + }, + ::Pair, + ) + .map { (bounds, _) -> bounds } fun setFocalAreaBounds(bounds: RectF) { wallpaperFocalAreaInteractor.setFocalAreaBounds(bounds) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperFocalAreaRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperFocalAreaRepository.kt index aeff86ed89bb..24d2f1f0d901 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperFocalAreaRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperFocalAreaRepository.kt @@ -34,12 +34,15 @@ class FakeWallpaperFocalAreaRepository : WallpaperFocalAreaRepository { _wallpaperFocalAreaBounds.asStateFlow() private val _wallpaperFocalAreaTapPosition = MutableStateFlow(PointF(0F, 0F)) - override val wallpaperFocalAreaTapPosition: StateFlow<PointF> = + val wallpaperFocalAreaTapPosition: StateFlow<PointF> = _wallpaperFocalAreaTapPosition.asStateFlow() private val _notificationDefaultTop = MutableStateFlow(0F) override val notificationDefaultTop: StateFlow<Float> = _notificationDefaultTop.asStateFlow() + private val _hasFocalArea = MutableStateFlow(false) + override val hasFocalArea: StateFlow<Boolean> = _hasFocalArea.asStateFlow() + override fun setShortcutAbsoluteTop(top: Float) { _shortcutAbsoluteTop.value = top } @@ -56,7 +59,7 @@ class FakeWallpaperFocalAreaRepository : WallpaperFocalAreaRepository { _wallpaperFocalAreaBounds.value = bounds } - override fun setTapPosition(point: PointF) { - _wallpaperFocalAreaTapPosition.value = point + override fun setTapPosition(tapPosition: PointF) { + _wallpaperFocalAreaTapPosition.value = tapPosition } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt index 8689e04e62dd..66bb803c182d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt @@ -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 kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -34,9 +36,9 @@ class FakeWallpaperRepository : WallpaperRepository { private val _shouldSendFocalArea = MutableStateFlow(false) override val shouldSendFocalArea: StateFlow<Boolean> = _shouldSendFocalArea.asStateFlow() - fun setShouldSendFocalArea(shouldSendFocalArea: Boolean) { - _shouldSendFocalArea.value = shouldSendFocalArea - } + override fun sendLockScreenLayoutChangeCommand(wallpaperFocalAreaBounds: RectF) {} + + override fun sendTapCommand(tapPosition: PointF) {} fun setWallpaperInfo(wallpaperInfo: WallpaperInfo?) { _wallpaperInfo.value = wallpaperInfo diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt index 7ebec6c3a7b9..1761503b2cc9 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt @@ -19,7 +19,6 @@ package com.android.systemui.wallpapers.data.repository import android.content.applicationContext import com.android.app.wallpaperManager import com.android.systemui.broadcast.broadcastDispatcher -import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.testDispatcher @@ -34,8 +33,6 @@ val Kosmos.wallpaperRepository by Fixture { bgDispatcher = testDispatcher, broadcastDispatcher = broadcastDispatcher, userRepository = userRepository, - keyguardTransitionInteractor = keyguardTransitionInteractor, - wallpaperFocalAreaRepository = wallpaperFocalAreaRepository, wallpaperManager = wallpaperManager, secureSettings = fakeSettings, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractor.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractor.kt index 88eb5511160b..eaf55a72be93 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractor.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperFocalAreaInteractor.kt @@ -18,20 +18,14 @@ package com.android.systemui.wallpapers.domain.interactor import android.content.applicationContext import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.shade.data.repository.shadeRepository -import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor import com.android.systemui.wallpapers.data.repository.wallpaperFocalAreaRepository -import com.android.systemui.wallpapers.data.repository.wallpaperRepository -val Kosmos.wallpaperFocalAreaInteractor by +var Kosmos.wallpaperFocalAreaInteractor by Kosmos.Fixture { WallpaperFocalAreaInteractor( - applicationScope = applicationCoroutineScope, context = applicationContext, wallpaperFocalAreaRepository = wallpaperFocalAreaRepository, shadeRepository = shadeRepository, - activeNotificationsInteractor = activeNotificationsInteractor, - wallpaperRepository = wallpaperRepository, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModel.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModel.kt index 7e232c526732..4032503d04c1 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModel.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/ui/viewmodel/WallpaperFocalAreaViewModel.kt @@ -16,10 +16,14 @@ package com.android.systemui.wallpapers.ui.viewmodel +import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.wallpapers.domain.interactor.wallpaperFocalAreaInteractor var Kosmos.wallpaperFocalAreaViewModel by Kosmos.Fixture { - WallpaperFocalAreaViewModel(wallpaperFocalAreaInteractor = wallpaperFocalAreaInteractor) + WallpaperFocalAreaViewModel( + wallpaperFocalAreaInteractor = wallpaperFocalAreaInteractor, + keyguardTransitionInteractor = keyguardTransitionInteractor, + ) } |