Merge "Rewire setDozing() to use repositories" into tm-qpr-dev am: 3b625dece1

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19732716

Change-Id: I2ec6f8f912e4bb9ba3f2938c5a747e6140538723
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-09-09 14:22:36 +00:00
committed by Automerger Merge Worker
7 changed files with 166 additions and 97 deletions

View File

@@ -101,6 +101,11 @@ public interface DozeHost {
* Called when the always on suppression state changes. See {@link #isAlwaysOnSuppressed()}. * Called when the always on suppression state changes. See {@link #isAlwaysOnSuppressed()}.
*/ */
default void onAlwaysOnSuppressedChanged(boolean suppressed) {} default void onAlwaysOnSuppressedChanged(boolean suppressed) {}
/**
* Called when the dozing state may have been updated.
*/
default void onDozingChanged(boolean isDozing) {}
} }
interface PulseCallback { interface PulseCallback {

View File

@@ -20,6 +20,7 @@ import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLoggin
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.common.shared.model.Position import com.android.systemui.common.shared.model.Position
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.doze.DozeHost
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject import javax.inject.Inject
@@ -28,6 +29,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
/** Defines interface for classes that encapsulate application state for the keyguard. */ /** Defines interface for classes that encapsulate application state for the keyguard. */
interface KeyguardRepository { interface KeyguardRepository {
@@ -102,6 +104,7 @@ class KeyguardRepositoryImpl
constructor( constructor(
statusBarStateController: StatusBarStateController, statusBarStateController: StatusBarStateController,
keyguardStateController: KeyguardStateController, keyguardStateController: KeyguardStateController,
dozeHost: DozeHost,
) : KeyguardRepository { ) : KeyguardRepository {
private val _animateBottomAreaDozingTransitions = MutableStateFlow(false) private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
override val animateBottomAreaDozingTransitions = override val animateBottomAreaDozingTransitions =
@@ -136,19 +139,21 @@ constructor(
awaitClose { keyguardStateController.removeCallback(callback) } awaitClose { keyguardStateController.removeCallback(callback) }
} }
override val isDozing: Flow<Boolean> = conflatedCallbackFlow { override val isDozing: Flow<Boolean> =
val callback = conflatedCallbackFlow {
object : StatusBarStateController.StateListener { val callback =
override fun onDozingChanged(isDozing: Boolean) { object : DozeHost.Callback {
trySendWithFailureLogging(isDozing, TAG, "updated isDozing") override fun onDozingChanged(isDozing: Boolean) {
} trySendWithFailureLogging(isDozing, TAG, "updated isDozing")
}
}
dozeHost.addCallback(callback)
trySendWithFailureLogging(false, TAG, "initial isDozing: false")
awaitClose { dozeHost.removeCallback(callback) }
} }
.distinctUntilChanged()
statusBarStateController.addCallback(callback)
trySendWithFailureLogging(statusBarStateController.isDozing, TAG, "initial isDozing")
awaitClose { statusBarStateController.removeCallback(callback) }
}
override val dozeAmount: Flow<Float> = conflatedCallbackFlow { override val dozeAmount: Flow<Float> = conflatedCallbackFlow {
val callback = val callback =
object : StatusBarStateController.StateListener { object : StatusBarStateController.StateListener {

View File

@@ -28,8 +28,6 @@ import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.assist.AssistManager; import com.android.systemui.assist.AssistManager;
@@ -50,11 +48,9 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.unfold.FoldAodAnimationController; import com.android.systemui.util.Assert;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Optional;
import javax.inject.Inject; import javax.inject.Inject;
@@ -80,8 +76,6 @@ public final class DozeServiceHost implements DozeHost {
private final WakefulnessLifecycle mWakefulnessLifecycle; private final WakefulnessLifecycle mWakefulnessLifecycle;
private final SysuiStatusBarStateController mStatusBarStateController; private final SysuiStatusBarStateController mStatusBarStateController;
private final DeviceProvisionedController mDeviceProvisionedController; private final DeviceProvisionedController mDeviceProvisionedController;
@Nullable
private final FoldAodAnimationController mFoldAodAnimationController;
private final HeadsUpManagerPhone mHeadsUpManagerPhone; private final HeadsUpManagerPhone mHeadsUpManagerPhone;
private final BatteryController mBatteryController; private final BatteryController mBatteryController;
private final ScrimController mScrimController; private final ScrimController mScrimController;
@@ -114,7 +108,6 @@ public final class DozeServiceHost implements DozeHost {
Lazy<AssistManager> assistManagerLazy, Lazy<AssistManager> assistManagerLazy,
DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor, DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor,
PulseExpansionHandler pulseExpansionHandler, PulseExpansionHandler pulseExpansionHandler,
Optional<SysUIUnfoldComponent> sysUIUnfoldComponent,
NotificationShadeWindowController notificationShadeWindowController, NotificationShadeWindowController notificationShadeWindowController,
NotificationWakeUpCoordinator notificationWakeUpCoordinator, NotificationWakeUpCoordinator notificationWakeUpCoordinator,
AuthController authController, AuthController authController,
@@ -138,8 +131,6 @@ public final class DozeServiceHost implements DozeHost {
mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
mAuthController = authController; mAuthController = authController;
mNotificationIconAreaController = notificationIconAreaController; mNotificationIconAreaController = notificationIconAreaController;
mFoldAodAnimationController = sysUIUnfoldComponent
.map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
} }
// TODO: we should try to not pass status bar in here if we can avoid it. // TODO: we should try to not pass status bar in here if we can avoid it.
@@ -167,6 +158,7 @@ public final class DozeServiceHost implements DozeHost {
} }
void firePowerSaveChanged(boolean active) { void firePowerSaveChanged(boolean active) {
Assert.isMainThread();
for (Callback callback : mCallbacks) { for (Callback callback : mCallbacks) {
callback.onPowerSaveChanged(active); callback.onPowerSaveChanged(active);
} }
@@ -177,6 +169,7 @@ public final class DozeServiceHost implements DozeHost {
entry.setPulseSuppressed(true); entry.setPulseSuppressed(true);
mNotificationIconAreaController.updateAodNotificationIcons(); mNotificationIconAreaController.updateAodNotificationIcons();
}; };
Assert.isMainThread();
for (Callback callback : mCallbacks) { for (Callback callback : mCallbacks) {
callback.onNotificationAlerted(pulseSuppressedListener); callback.onNotificationAlerted(pulseSuppressedListener);
} }
@@ -193,11 +186,13 @@ public final class DozeServiceHost implements DozeHost {
@Override @Override
public void addCallback(@NonNull Callback callback) { public void addCallback(@NonNull Callback callback) {
Assert.isMainThread();
mCallbacks.add(callback); mCallbacks.add(callback);
} }
@Override @Override
public void removeCallback(@NonNull Callback callback) { public void removeCallback(@NonNull Callback callback) {
Assert.isMainThread();
mCallbacks.remove(callback); mCallbacks.remove(callback);
} }
@@ -212,6 +207,8 @@ public final class DozeServiceHost implements DozeHost {
} }
void updateDozing() { void updateDozing() {
Assert.isMainThread();
// When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
boolean boolean
dozing = dozing =
@@ -225,10 +222,10 @@ public final class DozeServiceHost implements DozeHost {
dozing = false; dozing = false;
} }
mStatusBarStateController.setIsDozing(dozing); for (Callback callback : mCallbacks) {
if (mFoldAodAnimationController != null) { callback.onDozingChanged(dozing);
mFoldAodAnimationController.setIsDozing(dozing);
} }
mStatusBarStateController.setIsDozing(dozing);
} }
@Override @Override
@@ -452,6 +449,7 @@ public final class DozeServiceHost implements DozeHost {
return; return;
} }
mAlwaysOnSuppressed = suppressed; mAlwaysOnSuppressed = suppressed;
Assert.isMainThread();
for (Callback callback : mCallbacks) { for (Callback callback : mCallbacks) {
callback.onAlwaysOnSuppressedChanged(suppressed); callback.onAlwaysOnSuppressedChanged(suppressed);
} }

View File

@@ -18,22 +18,31 @@ package com.android.systemui.unfold
import android.content.Context import android.content.Context
import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
import android.os.PowerManager import android.os.PowerManager
import android.provider.Settings import android.provider.Settings
import androidx.annotation.VisibleForTesting
import androidx.core.view.OneShotPreDrawListener import androidx.core.view.OneShotPreDrawListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.internal.util.LatencyTracker import com.android.internal.util.LatencyTracker
import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.ScreenOffAnimation import com.android.systemui.statusbar.phone.ScreenOffAnimation
import com.android.systemui.statusbar.policy.CallbackController import com.android.systemui.statusbar.policy.CallbackController
import com.android.systemui.unfold.FoldAodAnimationController.FoldAodAnimationStatus import com.android.systemui.unfold.FoldAodAnimationController.FoldAodAnimationStatus
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.settings.GlobalSettings import com.android.systemui.util.settings.GlobalSettings
import java.util.concurrent.Executor import dagger.Lazy
import java.util.function.Consumer import java.util.function.Consumer
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
/** /**
* Controls folding to AOD animation: when AOD is enabled and foldable device is folded we play a * Controls folding to AOD animation: when AOD is enabled and foldable device is folded we play a
@@ -43,16 +52,16 @@ import javax.inject.Inject
class FoldAodAnimationController class FoldAodAnimationController
@Inject @Inject
constructor( constructor(
@Main private val handler: Handler, @Main private val executor: DelayableExecutor,
@Main private val executor: Executor,
private val context: Context, private val context: Context,
private val deviceStateManager: DeviceStateManager, private val deviceStateManager: DeviceStateManager,
private val wakefulnessLifecycle: WakefulnessLifecycle, private val wakefulnessLifecycle: WakefulnessLifecycle,
private val globalSettings: GlobalSettings, private val globalSettings: GlobalSettings,
private val latencyTracker: LatencyTracker, private val latencyTracker: LatencyTracker,
private val keyguardInteractor: Lazy<KeyguardInteractor>,
) : CallbackController<FoldAodAnimationStatus>, ScreenOffAnimation, WakefulnessLifecycle.Observer { ) : CallbackController<FoldAodAnimationStatus>, ScreenOffAnimation, WakefulnessLifecycle.Observer {
private lateinit var mCentralSurfaces: CentralSurfaces private lateinit var centralSurfaces: CentralSurfaces
private var isFolded = false private var isFolded = false
private var isFoldHandled = true private var isFoldHandled = true
@@ -64,12 +73,13 @@ constructor(
private var shouldPlayAnimation = false private var shouldPlayAnimation = false
private var isAnimationPlaying = false private var isAnimationPlaying = false
private var cancelAnimation: Runnable? = null
private val statusListeners = arrayListOf<FoldAodAnimationStatus>() private val statusListeners = arrayListOf<FoldAodAnimationStatus>()
private val foldToAodLatencyTracker = FoldToAodLatencyTracker() private val foldToAodLatencyTracker = FoldToAodLatencyTracker()
private val startAnimationRunnable = Runnable { private val startAnimationRunnable = Runnable {
mCentralSurfaces.notificationPanelViewController.startFoldToAodAnimation( centralSurfaces.notificationPanelViewController.startFoldToAodAnimation(
/* startAction= */ { foldToAodLatencyTracker.onAnimationStarted() }, /* startAction= */ { foldToAodLatencyTracker.onAnimationStarted() },
/* endAction= */ { setAnimationState(playing = false) }, /* endAction= */ { setAnimationState(playing = false) },
/* cancelAction= */ { setAnimationState(playing = false) }, /* cancelAction= */ { setAnimationState(playing = false) },
@@ -77,10 +87,14 @@ constructor(
} }
override fun initialize(centralSurfaces: CentralSurfaces, lightRevealScrim: LightRevealScrim) { override fun initialize(centralSurfaces: CentralSurfaces, lightRevealScrim: LightRevealScrim) {
this.mCentralSurfaces = centralSurfaces this.centralSurfaces = centralSurfaces
deviceStateManager.registerCallback(executor, FoldListener()) deviceStateManager.registerCallback(executor, FoldListener())
wakefulnessLifecycle.addObserver(this) wakefulnessLifecycle.addObserver(this)
centralSurfaces.notificationPanelViewController.view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) { listenForDozing(this) }
}
} }
/** Returns true if we should run fold to AOD animation */ /** Returns true if we should run fold to AOD animation */
@@ -94,7 +108,7 @@ constructor(
override fun startAnimation(): Boolean = override fun startAnimation(): Boolean =
if (shouldStartAnimation()) { if (shouldStartAnimation()) {
setAnimationState(playing = true) setAnimationState(playing = true)
mCentralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation() centralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation()
true true
} else { } else {
setAnimationState(playing = false) setAnimationState(playing = false)
@@ -104,8 +118,8 @@ constructor(
override fun onStartedWakingUp() { override fun onStartedWakingUp() {
if (isAnimationPlaying) { if (isAnimationPlaying) {
foldToAodLatencyTracker.cancel() foldToAodLatencyTracker.cancel()
handler.removeCallbacks(startAnimationRunnable) cancelAnimation?.run()
mCentralSurfaces.notificationPanelViewController.cancelFoldToAodAnimation() centralSurfaces.notificationPanelViewController.cancelFoldToAodAnimation()
} }
setAnimationState(playing = false) setAnimationState(playing = false)
@@ -138,13 +152,13 @@ constructor(
// We should play the folding to AOD animation // We should play the folding to AOD animation
setAnimationState(playing = true) setAnimationState(playing = true)
mCentralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation() centralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation()
// We don't need to wait for the scrim as it is already displayed // We don't need to wait for the scrim as it is already displayed
// but we should wait for the initial animation preparations to be drawn // but we should wait for the initial animation preparations to be drawn
// (setting initial alpha/translation) // (setting initial alpha/translation)
OneShotPreDrawListener.add( OneShotPreDrawListener.add(
mCentralSurfaces.notificationPanelViewController.view, centralSurfaces.notificationPanelViewController.view,
onReady onReady
) )
} else { } else {
@@ -165,18 +179,14 @@ constructor(
fun onScreenTurnedOn() { fun onScreenTurnedOn() {
if (shouldPlayAnimation) { if (shouldPlayAnimation) {
handler.removeCallbacks(startAnimationRunnable) cancelAnimation?.run()
// Post starting the animation to the next frame to avoid junk due to inset changes // Post starting the animation to the next frame to avoid junk due to inset changes
handler.post(startAnimationRunnable) cancelAnimation = executor.executeDelayed(startAnimationRunnable, /* delayMillis= */ 0)
shouldPlayAnimation = false shouldPlayAnimation = false
} }
} }
fun setIsDozing(dozing: Boolean) {
isDozing = dozing
}
override fun isAnimationPlaying(): Boolean = isAnimationPlaying override fun isAnimationPlaying(): Boolean = isAnimationPlaying
override fun isKeyguardHideDelayed(): Boolean = isAnimationPlaying() override fun isKeyguardHideDelayed(): Boolean = isAnimationPlaying()
@@ -204,6 +214,11 @@ constructor(
statusListeners.remove(listener) statusListeners.remove(listener)
} }
@VisibleForTesting
internal suspend fun listenForDozing(scope: CoroutineScope): Job {
return scope.launch { keyguardInteractor.get().isDozing.collect { isDozing = it } }
}
interface FoldAodAnimationStatus { interface FoldAodAnimationStatus {
fun onFoldToAodAnimationChanged() fun onFoldToAodAnimationChanged()
} }

View File

@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.data.repository
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Position import com.android.systemui.common.shared.model.Position
import com.android.systemui.doze.DozeHost
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.argumentCaptor
@@ -40,6 +41,7 @@ import org.mockito.MockitoAnnotations
class KeyguardRepositoryImplTest : SysuiTestCase() { class KeyguardRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var statusBarStateController: StatusBarStateController @Mock private lateinit var statusBarStateController: StatusBarStateController
@Mock private lateinit var dozeHost: DozeHost
@Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var keyguardStateController: KeyguardStateController
private lateinit var underTest: KeyguardRepositoryImpl private lateinit var underTest: KeyguardRepositoryImpl
@@ -48,7 +50,12 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
fun setUp() { fun setUp() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
underTest = KeyguardRepositoryImpl(statusBarStateController, keyguardStateController) underTest =
KeyguardRepositoryImpl(
statusBarStateController,
keyguardStateController,
dozeHost,
)
} }
@Test @Test
@@ -129,8 +136,8 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
var latest: Boolean? = null var latest: Boolean? = null
val job = underTest.isDozing.onEach { latest = it }.launchIn(this) val job = underTest.isDozing.onEach { latest = it }.launchIn(this)
val captor = argumentCaptor<StatusBarStateController.StateListener>() val captor = argumentCaptor<DozeHost.Callback>()
verify(statusBarStateController).addCallback(captor.capture()) verify(dozeHost).addCallback(captor.capture())
captor.value.onDozingChanged(true) captor.value.onDozingChanged(true)
assertThat(latest).isTrue() assertThat(latest).isTrue()
@@ -139,7 +146,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
assertThat(latest).isFalse() assertThat(latest).isFalse()
job.cancel() job.cancel()
verify(statusBarStateController).removeCallback(captor.value) verify(dozeHost).removeCallback(captor.value)
} }
@Test @Test

View File

@@ -29,6 +29,7 @@ import static org.mockito.Mockito.when;
import android.os.PowerManager; import android.os.PowerManager;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.View; import android.view.View;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -61,10 +62,10 @@ import org.mockito.MockitoAnnotations;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Optional;
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
public class DozeServiceHostTest extends SysuiTestCase { public class DozeServiceHostTest extends SysuiTestCase {
private DozeServiceHost mDozeServiceHost; private DozeServiceHost mDozeServiceHost;
@@ -92,6 +93,7 @@ public class DozeServiceHostTest extends SysuiTestCase {
@Mock private View mAmbientIndicationContainer; @Mock private View mAmbientIndicationContainer;
@Mock private BiometricUnlockController mBiometricUnlockController; @Mock private BiometricUnlockController mBiometricUnlockController;
@Mock private AuthController mAuthController; @Mock private AuthController mAuthController;
@Mock private DozeHost.Callback mCallback;
@Before @Before
public void setup() { public void setup() {
@@ -100,7 +102,7 @@ public class DozeServiceHostTest extends SysuiTestCase {
mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager, mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager,
mBatteryController, mScrimController, () -> mBiometricUnlockController, mBatteryController, mScrimController, () -> mBiometricUnlockController,
mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController, mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController,
mKeyguardUpdateMonitor, mPulseExpansionHandler, Optional.empty(), mKeyguardUpdateMonitor, mPulseExpansionHandler,
mNotificationShadeWindowController, mNotificationWakeUpCoordinator, mNotificationShadeWindowController, mNotificationWakeUpCoordinator,
mAuthController, mNotificationIconAreaController); mAuthController, mNotificationIconAreaController);
@@ -114,16 +116,19 @@ public class DozeServiceHostTest extends SysuiTestCase {
@Test @Test
public void testStartStopDozing() { public void testStartStopDozing() {
mDozeServiceHost.addCallback(mCallback);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
assertFalse(mDozeServiceHost.getDozingRequested()); assertFalse(mDozeServiceHost.getDozingRequested());
mDozeServiceHost.startDozing(); mDozeServiceHost.startDozing();
verify(mCallback).onDozingChanged(eq(true));
verify(mStatusBarStateController).setIsDozing(eq(true)); verify(mStatusBarStateController).setIsDozing(eq(true));
verify(mCentralSurfaces).updateIsKeyguard(); verify(mCentralSurfaces).updateIsKeyguard();
mDozeServiceHost.stopDozing(); mDozeServiceHost.stopDozing();
verify(mCallback).onDozingChanged(eq(false));
verify(mStatusBarStateController).setIsDozing(eq(false)); verify(mStatusBarStateController).setIsDozing(eq(false));
} }

View File

@@ -18,24 +18,28 @@ package com.android.systemui.unfold
import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.DeviceStateManager
import android.hardware.devicestate.DeviceStateManager.FoldStateListener import android.hardware.devicestate.DeviceStateManager.FoldStateListener
import android.os.Handler
import android.os.PowerManager import android.os.PowerManager
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.internal.util.LatencyTracker import com.android.internal.util.LatencyTracker
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.shade.NotificationPanelViewController import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.unfold.util.FoldableDeviceStates import com.android.systemui.unfold.util.FoldableDeviceStates
import com.android.systemui.unfold.util.FoldableTestUtils import com.android.systemui.unfold.util.FoldableTestUtils
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.any
import com.android.systemui.util.settings.GlobalSettings import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.time.FakeSystemClock
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.yield
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -49,7 +53,6 @@ import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
@SmallTest @SmallTest
@RunWithLooper
class FoldAodAnimationControllerTest : SysuiTestCase() { class FoldAodAnimationControllerTest : SysuiTestCase() {
@Mock lateinit var deviceStateManager: DeviceStateManager @Mock lateinit var deviceStateManager: DeviceStateManager
@@ -74,26 +77,15 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
private lateinit var deviceStates: FoldableDeviceStates private lateinit var deviceStates: FoldableDeviceStates
private lateinit var testableLooper: TestableLooper lateinit var keyguardRepository: FakeKeyguardRepository
lateinit var foldAodAnimationController: FoldAodAnimationController lateinit var underTest: FoldAodAnimationController
private val fakeExecutor = FakeExecutor(FakeSystemClock())
@Before @Before
fun setup() { fun setup() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
testableLooper = TestableLooper.get(this)
foldAodAnimationController =
FoldAodAnimationController(
Handler(testableLooper.looper),
context.mainExecutor,
context,
deviceStateManager,
wakefulnessLifecycle,
globalSettings,
latencyTracker,
)
.apply { initialize(centralSurfaces, lightRevealScrim) }
deviceStates = FoldableTestUtils.findDeviceStates(context) deviceStates = FoldableTestUtils.findDeviceStates(context)
whenever(notificationPanelViewController.view).thenReturn(viewGroup) whenever(notificationPanelViewController.view).thenReturn(viewGroup)
@@ -107,60 +99,102 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
val onActionStarted = it.arguments[0] as Runnable val onActionStarted = it.arguments[0] as Runnable
onActionStarted.run() onActionStarted.run()
} }
verify(deviceStateManager).registerCallback(any(), foldStateListenerCaptor.capture())
foldAodAnimationController.setIsDozing(dozing = true) keyguardRepository = FakeKeyguardRepository()
setAodEnabled(enabled = true) val keyguardInteractor = KeyguardInteractor(repository = keyguardRepository)
sendFoldEvent(folded = false)
// Needs to be run on the main thread
runBlocking(IMMEDIATE) {
underTest =
FoldAodAnimationController(
fakeExecutor,
context,
deviceStateManager,
wakefulnessLifecycle,
globalSettings,
latencyTracker,
{ keyguardInteractor },
)
.apply { initialize(centralSurfaces, lightRevealScrim) }
verify(deviceStateManager).registerCallback(any(), foldStateListenerCaptor.capture())
setAodEnabled(enabled = true)
sendFoldEvent(folded = false)
}
} }
@Test @Test
fun onFolded_aodDisabled_doesNotLogLatency() { fun onFolded_aodDisabled_doesNotLogLatency() =
setAodEnabled(enabled = false) runBlocking(IMMEDIATE) {
val job = underTest.listenForDozing(this)
keyguardRepository.setDozing(true)
setAodEnabled(enabled = false)
fold() yield()
simulateScreenTurningOn()
verifyNoMoreInteractions(latencyTracker) fold()
} simulateScreenTurningOn()
verifyNoMoreInteractions(latencyTracker)
job.cancel()
}
@Test @Test
fun onFolded_aodEnabled_logsLatency() { fun onFolded_aodEnabled_logsLatency() =
setAodEnabled(enabled = true) runBlocking(IMMEDIATE) {
val job = underTest.listenForDozing(this)
keyguardRepository.setDozing(true)
setAodEnabled(enabled = true)
fold() yield()
simulateScreenTurningOn()
verify(latencyTracker).onActionStart(any()) fold()
verify(latencyTracker).onActionEnd(any()) simulateScreenTurningOn()
}
verify(latencyTracker).onActionStart(any())
verify(latencyTracker).onActionEnd(any())
job.cancel()
}
@Test @Test
fun onFolded_animationCancelled_doesNotLogLatency() { fun onFolded_animationCancelled_doesNotLogLatency() =
setAodEnabled(enabled = true) runBlocking(IMMEDIATE) {
val job = underTest.listenForDozing(this)
keyguardRepository.setDozing(true)
setAodEnabled(enabled = true)
fold() yield()
foldAodAnimationController.onScreenTurningOn({})
foldAodAnimationController.onStartedWakingUp()
testableLooper.processAllMessages()
verify(latencyTracker).onActionStart(any()) fold()
verify(latencyTracker).onActionCancel(any()) underTest.onScreenTurningOn({})
} underTest.onStartedWakingUp()
fakeExecutor.runAllReady()
verify(latencyTracker).onActionStart(any())
verify(latencyTracker).onActionCancel(any())
job.cancel()
}
private fun simulateScreenTurningOn() { private fun simulateScreenTurningOn() {
foldAodAnimationController.onScreenTurningOn({}) underTest.onScreenTurningOn({})
foldAodAnimationController.onScreenTurnedOn() underTest.onScreenTurnedOn()
testableLooper.processAllMessages() fakeExecutor.runAllReady()
} }
private fun fold() = sendFoldEvent(folded = true) private fun fold() = sendFoldEvent(folded = true)
private fun setAodEnabled(enabled: Boolean) = private fun setAodEnabled(enabled: Boolean) = underTest.onAlwaysOnChanged(alwaysOn = enabled)
foldAodAnimationController.onAlwaysOnChanged(alwaysOn = enabled)
private fun sendFoldEvent(folded: Boolean) { private fun sendFoldEvent(folded: Boolean) {
val state = if (folded) deviceStates.folded else deviceStates.unfolded val state = if (folded) deviceStates.folded else deviceStates.unfolded
foldStateListenerCaptor.value.onStateChanged(state) foldStateListenerCaptor.value.onStateChanged(state)
} }
companion object {
private val IMMEDIATE = Dispatchers.Main.immediate
}
} }