diff options
12 files changed, 317 insertions, 17 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt index a98d1a2ea4a5..d3ba3dceb4cf 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt @@ -22,10 +22,13 @@ import android.view.Display import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.scene.ui.view.mockShadeRootView import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository import com.android.systemui.testKosmos +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -41,6 +44,7 @@ import org.mockito.kotlin.whenever class ShadeDisplaysInteractorTest : SysuiTestCase() { val kosmos = testKosmos().useUnconfinedTestDispatcher() + private val testScope = kosmos.testScope private val shadeRootview = kosmos.mockShadeRootView private val positionRepository = kosmos.fakeShadeDisplaysRepository private val shadeContext = kosmos.mockedWindowContext @@ -49,7 +53,7 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { private val configuration = mock<Configuration>() private val display = mock<Display>() - private val underTest = kosmos.shadeDisplaysInteractor + private val underTest by lazy { kosmos.shadeDisplaysInteractor } @Before fun setup() { @@ -84,12 +88,14 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { } @Test - fun start_shadeInWrongPosition_logsStartToLatencyTracker() { - whenever(display.displayId).thenReturn(0) - positionRepository.setDisplayId(1) + fun start_shadeInWrongPosition_logsStartToLatencyTracker() = + testScope.runTest { + whenever(display.displayId).thenReturn(0) + positionRepository.setDisplayId(1) - underTest.start() + underTest.start() + advanceUntilIdle() - verify(latencyTracker).onShadeDisplayChanging(eq(1)) - } + verify(latencyTracker).onShadeDisplayChanging(eq(1)) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeExpandedStateInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeExpandedStateInteractorTest.kt new file mode 100644 index 000000000000..58396e7cef82 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeExpandedStateInteractorTest.kt @@ -0,0 +1,77 @@ +/* + * 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.shade.domain.interactor + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.useUnconfinedTestDispatcher +import com.android.systemui.shade.domain.interactor.ShadeExpandedStateInteractorImpl.NotificationElement +import com.android.systemui.shade.domain.interactor.ShadeExpandedStateInteractorImpl.QSElement +import com.android.systemui.shade.shadeTestUtil +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +@SmallTest +@EnableSceneContainer +class ShadeExpandedStateInteractorTest : SysuiTestCase() { + private val kosmos = testKosmos().useUnconfinedTestDispatcher() + + private val testScope = kosmos.testScope + private val shadeTestUtil by lazy { kosmos.shadeTestUtil } + + private val underTest: ShadeExpandedStateInteractor by lazy { + kosmos.shadeExpandedStateInteractor + } + + @Test + fun expandedElement_qsExpanded_returnsQSElement() = + testScope.runTest { + shadeTestUtil.setShadeAndQsExpansion(shadeExpansion = 0f, qsExpansion = 1f) + val currentlyExpandedElement = underTest.currentlyExpandedElement + + val element = currentlyExpandedElement.value + + assertThat(element).isInstanceOf(QSElement::class.java) + } + + @Test + fun expandedElement_shadeExpanded_returnsShade() = + testScope.runTest { + shadeTestUtil.setShadeAndQsExpansion(shadeExpansion = 1f, qsExpansion = 0f) + + val element = underTest.currentlyExpandedElement.value + + assertThat(element).isInstanceOf(NotificationElement::class.java) + } + + @Test + fun expandedElement_noneExpanded_returnsNull() = + testScope.runTest { + shadeTestUtil.setShadeAndQsExpansion(shadeExpansion = 0f, qsExpansion = 0f) + + val element = underTest.currentlyExpandedElement.value + + assertThat(element).isNull() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt index 63e8ba8f65cd..747642097327 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt @@ -37,12 +37,13 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.res.R import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.data.repository.MutableShadeDisplaysRepository -import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor -import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractorImpl import com.android.systemui.shade.data.repository.ShadeDisplaysRepository import com.android.systemui.shade.data.repository.ShadeDisplaysRepositoryImpl import com.android.systemui.shade.display.ShadeDisplayPolicyModule +import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor +import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractorImpl import com.android.systemui.shade.domain.interactor.ShadeDisplaysInteractor +import com.android.systemui.shade.domain.interactor.ShadeExpandedStateInteractor import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround import com.android.systemui.statusbar.phone.ConfigurationControllerImpl import com.android.systemui.statusbar.phone.ConfigurationForwarder @@ -276,6 +277,8 @@ object ShadeDisplayAwareModule { @Module internal interface OptionalShadeDisplayAwareBindings { @BindsOptionalOf fun bindOptionalOfWindowRootView(): WindowRootView + + @BindsOptionalOf fun bindOptionalOShadeExpandedStateInteractor(): ShadeExpandedStateInteractor } /** diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt index 2348a110eb3a..b9df9f868dc3 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt @@ -35,6 +35,8 @@ import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLega import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorSceneContainerImpl import com.android.systemui.shade.domain.interactor.ShadeBackActionInteractor import com.android.systemui.shade.domain.interactor.ShadeBackActionInteractorImpl +import com.android.systemui.shade.domain.interactor.ShadeExpandedStateInteractor +import com.android.systemui.shade.domain.interactor.ShadeExpandedStateInteractorImpl import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl import com.android.systemui.shade.domain.interactor.ShadeInteractorLegacyImpl @@ -176,4 +178,10 @@ abstract class ShadeModule { @Binds @SysUISingleton abstract fun bindShadeModeInteractor(impl: ShadeModeInteractorImpl): ShadeModeInteractor + + @Binds + @SysUISingleton + abstract fun bindShadeExpandedStateInteractor( + impl: ShadeExpandedStateInteractorImpl + ): ShadeExpandedStateInteractor } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeTraceLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeTraceLogger.kt index 11805992fd6a..9a9fc467c53f 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeTraceLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeTraceLogger.kt @@ -27,7 +27,7 @@ import com.android.app.tracing.coroutines.TrackTracer * them across various threads' logs. */ object ShadeTraceLogger { - private val t = TrackTracer(trackName = "ShadeTraceLogger", trackGroup = "shade") + val t = TrackTracer(trackName = "ShadeTraceLogger", trackGroup = "shade") @JvmStatic fun logOnMovedToDisplay(displayId: Int, config: Configuration) { @@ -44,8 +44,11 @@ object ShadeTraceLogger { t.instant { "moveShadeWindowTo(displayId=$displayId)" } } - @JvmStatic - fun traceReparenting(r: () -> Unit) { + suspend fun traceReparenting(r: suspend () -> Unit) { t.traceAsync({ "reparenting" }) { r() } } + + inline fun traceWaitForExpansion(expansion: Float, r: () -> Unit) { + t.traceAsync({ "waiting for shade expansion to match $expansion" }) { r() } + } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/FakeShadeExpandedStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/FakeShadeExpandedStateInteractor.kt new file mode 100644 index 000000000000..eab00166c8ef --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/FakeShadeExpandedStateInteractor.kt @@ -0,0 +1,33 @@ +/* + * 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.shade.domain.interactor + +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +/** Fake [ShadeExpandedStateInteractor] for tests. */ +class FakeShadeExpandedStateInteractor : ShadeExpandedStateInteractor { + + private val mutableExpandedElement = + MutableStateFlow<ShadeExpandedStateInteractor.ShadeElement?>(null) + override val currentlyExpandedElement: StateFlow<ShadeExpandedStateInteractor.ShadeElement?> + get() = mutableExpandedElement + + fun setState(state: ShadeExpandedStateInteractor.ShadeElement?) { + mutableExpandedElement.value = state + } +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt index be561b178136..691a383cb338 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt @@ -32,6 +32,7 @@ import com.android.systemui.shade.ShadeTraceLogger.traceReparenting import com.android.systemui.shade.data.repository.ShadeDisplaysRepository import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround import com.android.window.flags.Flags +import java.util.Optional import javax.inject.Inject import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope @@ -47,8 +48,19 @@ constructor( @Background private val bgScope: CoroutineScope, @Main private val mainThreadContext: CoroutineContext, private val shadeDisplayChangeLatencyTracker: ShadeDisplayChangeLatencyTracker, + shadeExpandedInteractor: Optional<ShadeExpandedStateInteractor>, ) : CoreStartable { + private val shadeExpandedInteractor = + shadeExpandedInteractor.orElse(null) + ?: error( + """ + ShadeExpandedStateInteractor must be provided for ShadeDisplaysInteractor to work. + If it is not, it means this is being instantiated in a SystemUI variant that shouldn't. + """ + .trimIndent() + ) + override fun start() { ShadeWindowGoesAround.isUnexpectedlyInLegacyMode() bgScope.launchTraced(TAG) { @@ -78,9 +90,12 @@ constructor( withContext(mainThreadContext) { traceReparenting { shadeDisplayChangeLatencyTracker.onShadeDisplayChanging(destinationId) + val expandedElement = shadeExpandedInteractor.currentlyExpandedElement.value + expandedElement?.collapse(reason = "Shade window move") reparentToDisplayId(id = destinationId) + expandedElement?.expand(reason = "Shade window move") + checkContextDisplayMatchesExpected(destinationId) } - checkContextDisplayMatchesExpected(destinationId) } } catch (e: IllegalStateException) { Log.e( diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeExpandedStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeExpandedStateInteractor.kt new file mode 100644 index 000000000000..dd3abeec5a72 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeExpandedStateInteractor.kt @@ -0,0 +1,118 @@ +/* + * 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.shade.domain.interactor + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.shade.ShadeTraceLogger.traceWaitForExpansion +import com.android.systemui.shade.domain.interactor.ShadeExpandedStateInteractor.ShadeElement +import com.android.systemui.shade.shared.flag.DualShade +import com.android.systemui.util.kotlin.Utils.Companion.combineState +import javax.inject.Inject +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.withContext +import kotlinx.coroutines.withTimeout + +/** + * Wrapper around [ShadeInteractor] to facilitate expansion and collapse of Notifications and quick + * settings. + * + * Specifially created to simplify [ShadeDisplaysInteractor] logic. + * + * NOTE: with [SceneContainerFlag] or [DualShade] disabled, [currentlyExpandedElement] will always + * return null! + */ +interface ShadeExpandedStateInteractor { + /** Returns the expanded [ShadeElement]. If none is, returns null. */ + val currentlyExpandedElement: StateFlow<ShadeElement?> + + /** An element from the shade window that can be expanded or collapsed. */ + abstract class ShadeElement { + /** Expands the shade element, returning when the expansion is done */ + abstract suspend fun expand(reason: String) + + /** Collapses the shade element, returning when the collapse is done. */ + abstract suspend fun collapse(reason: String) + } +} + +@SysUISingleton +class ShadeExpandedStateInteractorImpl +@Inject +constructor( + private val shadeInteractor: ShadeInteractor, + @Background private val bgScope: CoroutineScope, +) : ShadeExpandedStateInteractor { + + private val notificationElement = NotificationElement() + private val qsElement = QSElement() + + override val currentlyExpandedElement: StateFlow<ShadeElement?> = + if (SceneContainerFlag.isEnabled) { + combineState( + shadeInteractor.isShadeAnyExpanded, + shadeInteractor.isQsExpanded, + bgScope, + SharingStarted.Eagerly, + ) { isShadeAnyExpanded, isQsExpanded -> + when { + isShadeAnyExpanded -> notificationElement + isQsExpanded -> qsElement + else -> null + } + } + } else { + MutableStateFlow(null) + } + + inner class NotificationElement : ShadeElement() { + override suspend fun expand(reason: String) { + shadeInteractor.expandNotificationsShade(reason) + shadeInteractor.shadeExpansion.waitUntil(1f) + } + + override suspend fun collapse(reason: String) { + shadeInteractor.collapseNotificationsShade(reason) + shadeInteractor.shadeExpansion.waitUntil(0f) + } + } + + inner class QSElement : ShadeElement() { + override suspend fun expand(reason: String) { + shadeInteractor.expandQuickSettingsShade(reason) + shadeInteractor.qsExpansion.waitUntil(1f) + } + + override suspend fun collapse(reason: String) { + shadeInteractor.collapseQuickSettingsShade(reason) + shadeInteractor.qsExpansion.waitUntil(0f) + } + } + + private suspend fun StateFlow<Float>.waitUntil(f: Float) { + // it's important to not do this in the main thread otherwise it will block any rendering. + withContext(bgScope.coroutineContext) { + withTimeout(1.seconds) { traceWaitForExpansion(expansion = f) { first { it == f } } } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt index d9a2e956cc86..a88b127ae157 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt @@ -17,10 +17,14 @@ package com.android.systemui.util.kotlin import android.content.Context +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn class Utils { companion object { @@ -32,6 +36,7 @@ class Utils { fun <A, B, C, D> toQuad(a: A, bcd: Triple<B, C, D>) = Quad(a, bcd.first, bcd.second, bcd.third) + fun <A, B, C, D> toQuad(abc: Triple<A, B, C>, d: D) = Quad(abc.first, abc.second, abc.third, d) @@ -51,7 +56,7 @@ class Utils { bcdefg.third, bcdefg.fourth, bcdefg.fifth, - bcdefg.sixth + bcdefg.sixth, ) /** @@ -81,7 +86,7 @@ class Utils { fun <A, B, C, D> Flow<A>.sample( b: Flow<B>, c: Flow<C>, - d: Flow<D> + d: Flow<D>, ): Flow<Quad<A, B, C, D>> { return this.sample(combine(b, c, d, ::Triple), ::toQuad) } @@ -134,6 +139,20 @@ class Utils { ): Flow<Septuple<A, B, C, D, E, F, G>> { return this.sample(combine(b, c, d, e, f, g, ::Sextuple), ::toSeptuple) } + + /** + * Combines 2 state flows, applying [transform] between the initial values to set the + * initial value of the resulting StateFlow. + */ + fun <A, B, R> combineState( + f1: StateFlow<A>, + f2: StateFlow<B>, + scope: CoroutineScope, + sharingStarted: SharingStarted, + transform: (A, B) -> R, + ): StateFlow<R> = + combine(f1, f2) { a, b -> transform(a, b) } + .stateIn(scope, sharingStarted, transform(f1.value, f2.value)) } } @@ -144,7 +163,7 @@ data class Quint<A, B, C, D, E>( val second: B, val third: C, val fourth: D, - val fifth: E + val fifth: E, ) data class Sextuple<A, B, C, D, E, F>( diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt index ab193d294b8c..b3d89dbb834d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt @@ -203,6 +203,7 @@ class ShadeTestUtilSceneImpl( val isUserInputOngoing = MutableStateFlow(true) override fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float) { + shadeRepository.setLegacyIsQsExpanded(qsExpansion > 0f) if (shadeExpansion == 1f) { setIdleScene(Scenes.Shade) } else if (qsExpansion == 1f) { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt index 4af5e7d9d725..6e44df833582 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt @@ -23,11 +23,21 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.shade.ShadeDisplayChangeLatencyTracker import com.android.systemui.shade.ShadeWindowLayoutParams import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository +import java.util.Optional +import org.mockito.kotlin.any import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever val Kosmos.shadeLayoutParams by Kosmos.Fixture { ShadeWindowLayoutParams.create(mockedContext) } -val Kosmos.mockedWindowContext by Kosmos.Fixture { mock<WindowContext>() } +val Kosmos.mockedWindowContext by + Kosmos.Fixture { + mock<WindowContext>().apply { + whenever(reparentToDisplay(any())).thenAnswer { displayIdParam -> + whenever(displayId).thenReturn(displayIdParam.arguments[0] as Int) + } + } + } val Kosmos.mockedShadeDisplayChangeLatencyTracker by Kosmos.Fixture { mock<ShadeDisplayChangeLatencyTracker>() } val Kosmos.shadeDisplaysInteractor by @@ -38,5 +48,6 @@ val Kosmos.shadeDisplaysInteractor by testScope.backgroundScope, testScope.backgroundScope.coroutineContext, mockedShadeDisplayChangeLatencyTracker, + Optional.of(shadeExpandedStateInteractor), ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt index af6d6249b4a8..1dc7229a6506 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt @@ -21,6 +21,7 @@ import com.android.systemui.keyguard.data.repository.keyguardRepository import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.shade.ShadeModule @@ -30,6 +31,7 @@ import com.android.systemui.statusbar.phone.dozeParameters import com.android.systemui.statusbar.policy.data.repository.userSetupRepository import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor import com.android.systemui.user.domain.interactor.userSwitcherInteractor +import org.mockito.kotlin.mock var Kosmos.baseShadeInteractor: BaseShadeInteractor by Kosmos.Fixture { @@ -71,3 +73,7 @@ val Kosmos.shadeInteractorImpl by shadeModeInteractor = shadeModeInteractor, ) } +var Kosmos.mockShadeInteractor: ShadeInteractor by Kosmos.Fixture { mock() } +val Kosmos.shadeExpandedStateInteractor by + Kosmos.Fixture { ShadeExpandedStateInteractorImpl(shadeInteractor, testScope.backgroundScope) } +val Kosmos.fakeShadeExpandedStateInteractor by Kosmos.Fixture { FakeShadeExpandedStateInteractor() } |