Begin disconnecting KeyguardStatusViewController from NPVC

As the status view will (eventually) no longer be in the shade, begin
disconnecting it from NotificationPanelViewController piece by
piece. First, remove dozeTimeTick and onScreenTurningOn calls from
NPVC. This rewires the flow of events but does not change any functionality.

Also, refactor burn in to use KeyguardRepository as the source of
truth for dozeTimeTick information

Bug: 288242803
Test: atest KeyguardStatusViewControllerTest
KeyguardStatusViewControllerWithCoroutinesTest BurnInInteractorTest
UdfpsFingerprintViewModelTest UdfpsKeyguardInteractorTest

Change-Id: Ic9061bd67eb78995eb38ff88315dd9e0c4899e6b
This commit is contained in:
Matt Pietal
2023-07-20 12:48:58 +00:00
parent b9520816c6
commit a3933a7d14
18 changed files with 318 additions and 192 deletions

View File

@@ -20,6 +20,7 @@ import static androidx.constraintlayout.widget.ConstraintSet.END;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.animation.Animator;
import android.animation.ValueAnimator;
@@ -51,6 +52,10 @@ import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.shared.model.ScreenModel;
import com.android.systemui.keyguard.shared.model.ScreenState;
import com.android.systemui.plugins.ClockController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -62,6 +67,9 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
import kotlin.coroutines.CoroutineContext;
import kotlin.coroutines.EmptyCoroutineContext;
import java.io.PrintWriter;
import javax.inject.Inject;
@@ -91,6 +99,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
private final FeatureFlags mFeatureFlags;
private final InteractionJankMonitor mInteractionJankMonitor;
private final Rect mClipBounds = new Rect();
private final KeyguardInteractor mKeyguardInteractor;
private Boolean mStatusViewCentered = true;
@@ -122,6 +131,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
KeyguardLogger logger,
FeatureFlags featureFlags,
InteractionJankMonitor interactionJankMonitor,
KeyguardInteractor keyguardInteractor,
DumpManager dumpManager) {
super(keyguardStatusView);
mKeyguardSliceViewController = keyguardSliceViewController;
@@ -134,12 +144,34 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
mInteractionJankMonitor = interactionJankMonitor;
mFeatureFlags = featureFlags;
mDumpManager = dumpManager;
mKeyguardInteractor = keyguardInteractor;
}
@Override
public void onInit() {
mKeyguardClockSwitchController.init();
mDumpManager.registerDumpable(this);
if (mFeatureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
startCoroutines(EmptyCoroutineContext.INSTANCE);
}
}
void startCoroutines(CoroutineContext context) {
collectFlow(mView, mKeyguardInteractor.getDozeTimeTick(),
(Long millis) -> {
dozeTimeTick();
}, context);
collectFlow(mView, mKeyguardInteractor.getScreenModel(),
(ScreenModel model) -> {
if (model.getState() == ScreenState.SCREEN_TURNING_ON) {
dozeTimeTick();
}
}, context);
}
public KeyguardStatusView getView() {
return mView;
}
@Override

View File

@@ -47,16 +47,15 @@ import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnl
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
@@ -177,7 +176,7 @@ interface KeyguardRepository {
val keyguardRootViewVisibility: Flow<KeyguardRootViewVisibilityState>
/** Receive an event for doze time tick */
val dozeTimeTick: Flow<Unit>
val dozeTimeTick: Flow<Long>
/**
* Returns `true` if the keyguard is showing; `false` otherwise.
@@ -248,6 +247,7 @@ constructor(
private val dreamOverlayCallbackController: DreamOverlayCallbackController,
@Main private val mainDispatcher: CoroutineDispatcher,
@Application private val scope: CoroutineScope,
private val systemClock: SystemClock,
) : KeyguardRepository {
private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
override val animateBottomAreaDozingTransitions =
@@ -398,11 +398,11 @@ constructor(
_isDozing.value = isDozing
}
private val _dozeTimeTick = MutableSharedFlow<Unit>()
override val dozeTimeTick = _dozeTimeTick.asSharedFlow()
private val _dozeTimeTick = MutableStateFlow<Long>(0)
override val dozeTimeTick = _dozeTimeTick.asStateFlow()
override fun dozeTimeTick() {
_dozeTimeTick.tryEmit(Unit)
_dozeTimeTick.value = systemClock.uptimeMillis()
}
private val _lastDozeTapToWakePosition = MutableStateFlow<Point?>(null)

View File

@@ -24,14 +24,11 @@ import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
@@ -46,24 +43,17 @@ constructor(
private val burnInHelperWrapper: BurnInHelperWrapper,
@Application private val scope: CoroutineScope,
private val configurationRepository: ConfigurationRepository,
private val systemClock: SystemClock,
private val keyguardInteractor: KeyguardInteractor,
) {
private val _dozeTimeTick = MutableStateFlow<Long>(0)
val dozeTimeTick: StateFlow<Long> = _dozeTimeTick.asStateFlow()
val udfpsBurnInXOffset: StateFlow<Int> =
burnInOffsetDefinedInPixels(R.dimen.udfps_burn_in_offset_x, isXAxis = true)
val udfpsBurnInYOffset: StateFlow<Int> =
burnInOffsetDefinedInPixels(R.dimen.udfps_burn_in_offset_y, isXAxis = false)
val udfpsBurnInProgress: StateFlow<Float> =
dozeTimeTick
keyguardInteractor.dozeTimeTick
.mapLatest { burnInHelperWrapper.burnInProgressOffset() }
.stateIn(scope, SharingStarted.Lazily, burnInHelperWrapper.burnInProgressOffset())
fun dozeTimeTick() {
_dozeTimeTick.value = systemClock.uptimeMillis()
}
/**
* Use for max burn-in offsets that are NOT specified in pixels. This flow will recalculate the
* max burn-in offset on any configuration changes. If the max burn-in offset is specified in
@@ -77,7 +67,9 @@ constructor(
.flatMapLatest {
val maxBurnInOffsetPixels =
context.resources.getDimensionPixelSize(maxBurnInOffsetResourceId)
dozeTimeTick.mapLatest { calculateOffset(maxBurnInOffsetPixels, isXAxis) }
keyguardInteractor.dozeTimeTick.mapLatest {
calculateOffset(maxBurnInOffsetPixels, isXAxis)
}
}
.stateIn(
scope,
@@ -102,7 +94,9 @@ constructor(
.flatMapLatest { scale ->
val maxBurnInOffsetPixels =
context.resources.getDimensionPixelSize(maxBurnInOffsetResourceId)
dozeTimeTick.mapLatest { calculateOffset(maxBurnInOffsetPixels, isXAxis, scale) }
keyguardInteractor.dozeTimeTick.mapLatest {
calculateOffset(maxBurnInOffsetPixels, isXAxis, scale)
}
}
.stateIn(
scope,

View File

@@ -34,6 +34,7 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardRootViewVisibilityState
import com.android.systemui.keyguard.shared.model.ScreenModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
@@ -87,7 +88,7 @@ constructor(
/** Whether the system is in doze mode. */
val isDozing: Flow<Boolean> = repository.isDozing
/** Receive an event for doze time tick */
val dozeTimeTick: Flow<Unit> = repository.dozeTimeTick
val dozeTimeTick: Flow<Long> = repository.dozeTimeTick
/** Whether Always-on Display mode is available. */
val isAodAvailable: Flow<Boolean> = repository.isAodAvailable
/** Doze transition information. */
@@ -122,6 +123,9 @@ constructor(
/** The device wake/sleep state */
val wakefulnessModel: StateFlow<WakefulnessModel> = repository.wakefulness
/** The device screen state */
val screenModel: StateFlow<ScreenModel> = repository.screenModel
/**
* Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
* that doze mode is not running and DREAMING is ok to commence.

View File

@@ -2820,7 +2820,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
@Override
public void onScreenTurningOn() {
mKeyguardStatusViewController.dozeTimeTick();
if (!mFeatureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
mKeyguardStatusViewController.dozeTimeTick();
}
}
private void onMiddleClicked() {
@@ -3070,10 +3072,11 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
}
@Override
public void dozeTimeTick() {
mLockIconViewController.dozeTimeTick();
mKeyguardStatusViewController.dozeTimeTick();
if (!mFeatureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
mKeyguardStatusViewController.dozeTimeTick();
}
if (mInterpolatedDarkAmount > 0) {
positionClockAndNotifications();
}

View File

@@ -38,7 +38,6 @@ import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor;
import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.ShadeViewController;
@@ -94,7 +93,6 @@ public final class DozeServiceHost implements DozeHost {
private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
private final AuthController mAuthController;
private final NotificationIconAreaController mNotificationIconAreaController;
private final BurnInInteractor mBurnInInteractor;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private ShadeViewController mNotificationPanel;
private View mAmbientIndicationContainer;
@@ -118,8 +116,7 @@ public final class DozeServiceHost implements DozeHost {
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
AuthController authController,
NotificationIconAreaController notificationIconAreaController,
DozeInteractor dozeInteractor,
BurnInInteractor burnInInteractor) {
DozeInteractor dozeInteractor) {
super();
mDozeLog = dozeLog;
mPowerManager = powerManager;
@@ -138,7 +135,6 @@ public final class DozeServiceHost implements DozeHost {
mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
mAuthController = authController;
mNotificationIconAreaController = notificationIconAreaController;
mBurnInInteractor = burnInInteractor;
mHeadsUpManagerPhone.addListener(mOnHeadsUpChangedListener);
mDozeInteractor = dozeInteractor;
}
@@ -317,7 +313,6 @@ public final class DozeServiceHost implements DozeHost {
if (mAmbientIndicationContainer instanceof DozeReceiver) {
((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
}
mBurnInInteractor.dozeTimeTick();
}
@Override

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2020 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.keyguard;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.view.View;
import android.view.ViewTreeObserver;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class KeyguardStatusViewControllerBaseTest extends SysuiTestCase {
@Mock protected KeyguardStatusView mKeyguardStatusView;
@Mock protected KeyguardSliceViewController mKeyguardSliceViewController;
@Mock protected KeyguardClockSwitchController mKeyguardClockSwitchController;
@Mock protected KeyguardStateController mKeyguardStateController;
@Mock protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock protected ConfigurationController mConfigurationController;
@Mock protected DozeParameters mDozeParameters;
@Mock protected ScreenOffAnimationController mScreenOffAnimationController;
@Mock protected KeyguardLogger mKeyguardLogger;
@Mock protected KeyguardStatusViewController mControllerMock;
@Mock protected FeatureFlags mFeatureFlags;
@Mock protected InteractionJankMonitor mInteractionJankMonitor;
@Mock protected ViewTreeObserver mViewTreeObserver;
@Mock protected DumpManager mDumpManager;
protected FakeKeyguardRepository mFakeKeyguardRepository;
protected KeyguardStatusViewController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
KeyguardInteractorFactory.WithDependencies deps = KeyguardInteractorFactory.create();
mFakeKeyguardRepository = deps.getRepository();
mController = new KeyguardStatusViewController(
mKeyguardStatusView,
mKeyguardSliceViewController,
mKeyguardClockSwitchController,
mKeyguardStateController,
mKeyguardUpdateMonitor,
mConfigurationController,
mDozeParameters,
mScreenOffAnimationController,
mKeyguardLogger,
mFeatureFlags,
mInteractionJankMonitor,
deps.getKeyguardInteractor(),
mDumpManager) {
@Override
void setProperty(
AnimatableProperty property,
float value,
boolean animate) {
// Route into the mock version for verification
mControllerMock.setProperty(property, value, animate);
}
};
when(mKeyguardStatusView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
}
protected void givenViewAttached() {
ArgumentCaptor<View.OnAttachStateChangeListener> captor =
ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
verify(mKeyguardStatusView, atLeast(1)).addOnAttachStateChangeListener(captor.capture());
for (View.OnAttachStateChangeListener listener : captor.getAllValues()) {
listener.onViewAttachedToWindow(mKeyguardStatusView);
}
}
}

View File

@@ -23,80 +23,21 @@ import static org.mockito.Mockito.when;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ClockConfig;
import com.android.systemui.plugins.ClockController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner.class)
public class KeyguardStatusViewControllerTest extends SysuiTestCase {
@Mock private KeyguardStatusView mKeyguardStatusView;
@Mock private KeyguardSliceViewController mKeyguardSliceViewController;
@Mock private KeyguardClockSwitchController mKeyguardClockSwitchController;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock private ConfigurationController mConfigurationController;
@Mock private DozeParameters mDozeParameters;
@Mock private ScreenOffAnimationController mScreenOffAnimationController;
@Mock private KeyguardLogger mKeyguardLogger;
@Mock private KeyguardStatusViewController mControllerMock;
@Mock private FeatureFlags mFeatureFlags;
@Mock private InteractionJankMonitor mInteractionJankMonitor;
@Mock private DumpManager mDumpManager;
@Captor
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
private KeyguardStatusViewController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mController = new KeyguardStatusViewController(
mKeyguardStatusView,
mKeyguardSliceViewController,
mKeyguardClockSwitchController,
mKeyguardStateController,
mKeyguardUpdateMonitor,
mConfigurationController,
mDozeParameters,
mScreenOffAnimationController,
mKeyguardLogger,
mFeatureFlags,
mInteractionJankMonitor,
mDumpManager) {
@Override
void setProperty(
AnimatableProperty property,
float value,
boolean animate) {
// Route into the mock version for verification
mControllerMock.setProperty(property, value, animate);
}
};
}
public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControllerBaseTest {
@Test
public void dozeTimeTick_updatesSlice() {

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2023 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.keyguard
import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import com.android.systemui.keyguard.shared.model.ScreenModel
import com.android.systemui.keyguard.shared.model.ScreenState
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
class KeyguardStatusViewControllerWithCoroutinesTest : KeyguardStatusViewControllerBaseTest() {
@Test
fun dozeTimeTickUpdatesSlices() = runTest {
mController.startCoroutines(coroutineContext)
givenViewAttached()
runCurrent()
clearInvocations(mKeyguardSliceViewController)
mFakeKeyguardRepository.dozeTimeTick()
runCurrent()
verify(mKeyguardSliceViewController).refresh()
coroutineContext.cancelChildren()
}
@Test
fun onScreenTurningOnUpdatesSlices() = runTest {
mController.startCoroutines(coroutineContext)
givenViewAttached()
runCurrent()
clearInvocations(mKeyguardSliceViewController)
mFakeKeyguardRepository.setScreenModel(ScreenModel(ScreenState.SCREEN_ON))
runCurrent()
verify(mKeyguardSliceViewController, never()).refresh()
// Should only be called during a 'turning on' event
mFakeKeyguardRepository.setScreenModel(ScreenModel(ScreenState.SCREEN_TURNING_ON))
runCurrent()
verify(mKeyguardSliceViewController).refresh()
coroutineContext.cancelChildren()
}
}

View File

@@ -49,6 +49,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
@@ -85,13 +86,14 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
private val mainDispatcher = StandardTestDispatcher()
private val testDispatcher = StandardTestDispatcher()
private val testScope = TestScope(testDispatcher)
private lateinit var systemClock: FakeSystemClock
private lateinit var underTest: KeyguardRepositoryImpl
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
systemClock = FakeSystemClock()
underTest =
KeyguardRepositoryImpl(
statusBarStateController,
@@ -107,6 +109,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
dreamOverlayCallbackController,
mainDispatcher,
testScope.backgroundScope,
systemClock,
)
}
@@ -167,11 +170,15 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
@Test
fun dozeTimeTick() =
testScope.runTest {
var dozeTimeTickValue = collectLastValue(underTest.dozeTimeTick)
underTest.dozeTimeTick()
runCurrent()
val lastDozeTimeTick by collectLastValue(underTest.dozeTimeTick)
assertThat(lastDozeTimeTick).isEqualTo(0L)
assertThat(dozeTimeTickValue()).isNull()
// WHEN dozeTimeTick updated
systemClock.setUptimeMillis(systemClock.uptimeMillis() + 5)
underTest.dozeTimeTick()
// THEN listeners were updated to the latest uptime millis
assertThat(systemClock.uptimeMillis()).isEqualTo(lastDozeTimeTick)
}
@Test

View File

@@ -23,10 +23,9 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
@@ -48,7 +47,8 @@ class BurnInInteractorTest : SysuiTestCase() {
@Mock private lateinit var burnInHelperWrapper: BurnInHelperWrapper
private lateinit var configurationRepository: FakeConfigurationRepository
private lateinit var systemClock: FakeSystemClock
private lateinit var keyguardInteractor: KeyguardInteractor
private lateinit var fakeKeyguardRepository: FakeKeyguardRepository
private lateinit var testScope: TestScope
private lateinit var underTest: BurnInInteractor
@@ -56,8 +56,10 @@ class BurnInInteractorTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
configurationRepository = FakeConfigurationRepository()
systemClock = FakeSystemClock()
KeyguardInteractorFactory.create().let {
keyguardInteractor = it.keyguardInteractor
fakeKeyguardRepository = it.repository
}
whenever(burnInHelperWrapper.burnInOffset(anyInt(), anyBoolean())).thenReturn(burnInOffset)
setBurnInProgress(.65f)
@@ -68,25 +70,10 @@ class BurnInInteractorTest : SysuiTestCase() {
burnInHelperWrapper,
testScope.backgroundScope,
configurationRepository,
systemClock,
keyguardInteractor,
)
}
@Test
fun dozeTimeTick_updatesOnDozeTimeTick() =
testScope.runTest {
// Initial state set to 0
val lastDozeTimeTick by collectLastValue(underTest.dozeTimeTick)
assertEquals(0L, lastDozeTimeTick)
// WHEN dozeTimeTick updated
incrementUptimeMillis()
underTest.dozeTimeTick()
// THEN listeners were updated to the latest uptime millis
assertThat(systemClock.uptimeMillis()).isEqualTo(lastDozeTimeTick)
}
@Test
fun udfpsBurnInOffset_updatesOnResolutionScaleChange() =
testScope.runTest {
@@ -111,25 +98,18 @@ class BurnInInteractorTest : SysuiTestCase() {
assertThat(udfpsBurnInProgress).isEqualTo(burnInProgress)
setBurnInProgress(.88f)
incrementUptimeMillis()
underTest.dozeTimeTick()
fakeKeyguardRepository.dozeTimeTick(10)
assertThat(udfpsBurnInProgress).isEqualTo(burnInProgress)
setBurnInProgress(.92f)
incrementUptimeMillis()
underTest.dozeTimeTick()
fakeKeyguardRepository.dozeTimeTick(20)
assertThat(udfpsBurnInProgress).isEqualTo(burnInProgress)
setBurnInProgress(.32f)
incrementUptimeMillis()
underTest.dozeTimeTick()
fakeKeyguardRepository.dozeTimeTick(30)
assertThat(udfpsBurnInProgress).isEqualTo(burnInProgress)
}
private fun incrementUptimeMillis() {
systemClock.setUptimeMillis(systemClock.uptimeMillis() + 5)
}
private fun setBurnInProgress(progress: Float) {
burnInProgress = progress
whenever(burnInHelperWrapper.burnInProgressOffset()).thenReturn(burnInProgress)

View File

@@ -38,7 +38,6 @@ import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@@ -68,6 +67,7 @@ class UdfpsKeyguardInteractorTest : SysuiTestCase() {
private lateinit var featureFlags: FakeFeatureFlags
private lateinit var burnInInteractor: BurnInInteractor
private lateinit var shadeRepository: FakeShadeRepository
private lateinit var keyguardInteractor: KeyguardInteractor
@Mock private lateinit var burnInHelper: BurnInHelperWrapper
@Mock private lateinit var dialogManager: SystemUIDialogManager
@@ -79,35 +79,32 @@ class UdfpsKeyguardInteractorTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
testScope = TestScope()
configRepository = FakeConfigurationRepository()
keyguardRepository = FakeKeyguardRepository()
bouncerRepository = FakeKeyguardBouncerRepository()
shadeRepository = FakeShadeRepository()
fakeCommandQueue = FakeCommandQueue()
featureFlags =
FakeFeatureFlags().apply {
set(Flags.REFACTOR_UDFPS_KEYGUARD_VIEWS, true)
set(Flags.FACE_AUTH_REFACTOR, false)
}
KeyguardInteractorFactory.create(featureFlags = featureFlags).let {
keyguardInteractor = it.keyguardInteractor
keyguardRepository = it.repository
}
bouncerRepository = FakeKeyguardBouncerRepository()
shadeRepository = FakeShadeRepository()
fakeCommandQueue = FakeCommandQueue()
burnInInteractor =
BurnInInteractor(
context,
burnInHelper,
testScope.backgroundScope,
configRepository,
FakeSystemClock(),
keyguardInteractor
)
underTest =
UdfpsKeyguardInteractor(
configRepository,
burnInInteractor,
KeyguardInteractor(
keyguardRepository,
fakeCommandQueue,
featureFlags,
bouncerRepository,
configRepository,
),
keyguardInteractor,
shadeRepository,
dialogManager,
)
@@ -215,7 +212,7 @@ class UdfpsKeyguardInteractorTest : SysuiTestCase() {
private fun setAwake() {
keyguardRepository.setDozeAmount(0f)
burnInInteractor.dozeTimeTick()
keyguardRepository.dozeTimeTick()
bouncerRepository.setAlternateVisible(false)
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)

View File

@@ -20,21 +20,19 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@@ -58,9 +56,9 @@ class UdfpsAodViewModelTest : SysuiTestCase() {
private lateinit var configRepository: FakeConfigurationRepository
private lateinit var bouncerRepository: KeyguardBouncerRepository
private lateinit var keyguardRepository: FakeKeyguardRepository
private lateinit var fakeCommandQueue: FakeCommandQueue
private lateinit var featureFlags: FakeFeatureFlags
private lateinit var shadeRepository: FakeShadeRepository
private lateinit var keyguardInteractor: KeyguardInteractor
@Mock private lateinit var dialogManager: SystemUIDialogManager
@Mock private lateinit var burnInHelper: BurnInHelperWrapper
@@ -70,17 +68,21 @@ class UdfpsAodViewModelTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
overrideResource(com.android.systemui.R.dimen.lock_icon_padding, defaultPadding)
testScope = TestScope()
configRepository = FakeConfigurationRepository()
keyguardRepository = FakeKeyguardRepository()
bouncerRepository = FakeKeyguardBouncerRepository()
fakeCommandQueue = FakeCommandQueue()
shadeRepository = FakeShadeRepository()
featureFlags =
FakeFeatureFlags().apply {
set(Flags.REFACTOR_UDFPS_KEYGUARD_VIEWS, true)
set(Flags.FACE_AUTH_REFACTOR, false)
}
KeyguardInteractorFactory.create(
featureFlags = featureFlags,
)
.also {
keyguardInteractor = it.keyguardInteractor
keyguardRepository = it.repository
configRepository = it.configurationRepository
bouncerRepository = it.bouncerRepository
}
val udfpsKeyguardInteractor =
UdfpsKeyguardInteractor(
configRepository,
@@ -89,15 +91,9 @@ class UdfpsAodViewModelTest : SysuiTestCase() {
burnInHelper,
testScope.backgroundScope,
configRepository,
FakeSystemClock(),
),
KeyguardInteractor(
keyguardRepository,
fakeCommandQueue,
featureFlags,
bouncerRepository,
configRepository,
keyguardInteractor,
),
keyguardInteractor,
shadeRepository,
dialogManager,
)

View File

@@ -30,12 +30,11 @@ import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@@ -90,14 +89,10 @@ class UdfpsFingerprintViewModelTest : SysuiTestCase() {
testScope.backgroundScope,
)
val keyguardInteractor =
KeyguardInteractor(
keyguardRepository,
fakeCommandQueue,
featureFlags,
bouncerRepository,
configRepository,
)
KeyguardInteractorFactory.create(
featureFlags = featureFlags,
)
.keyguardInteractor
underTest =
FingerprintViewModel(
context,
@@ -109,7 +104,7 @@ class UdfpsFingerprintViewModelTest : SysuiTestCase() {
burnInHelper,
testScope.backgroundScope,
configRepository,
FakeSystemClock(),
keyguardInteractor,
),
keyguardInteractor,
shadeRepository,

View File

@@ -29,6 +29,7 @@ import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -39,7 +40,6 @@ import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.android.wm.shell.animation.Interpolators
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
@@ -72,6 +72,7 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
private lateinit var configRepository: FakeConfigurationRepository
private lateinit var keyguardRepository: FakeKeyguardRepository
private lateinit var keyguardInteractor: KeyguardInteractor
private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
private lateinit var shadeRepository: FakeShadeRepository
private lateinit var featureFlags: FakeFeatureFlags
@@ -81,23 +82,21 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
testScope = TestScope()
transitionRepository = FakeKeyguardTransitionRepository()
configRepository = FakeConfigurationRepository()
keyguardRepository = FakeKeyguardRepository()
bouncerRepository = FakeKeyguardBouncerRepository()
shadeRepository = FakeShadeRepository()
featureFlags =
FakeFeatureFlags().apply {
set(Flags.REFACTOR_UDFPS_KEYGUARD_VIEWS, true)
set(Flags.FACE_AUTH_REFACTOR, false)
}
val keyguardInteractor =
KeyguardInteractor(
keyguardRepository,
commandQueue = mock(),
featureFlags,
bouncerRepository,
configRepository,
KeyguardInteractorFactory.create(
featureFlags = featureFlags,
)
.also {
keyguardInteractor = it.keyguardInteractor
keyguardRepository = it.repository
configRepository = it.configurationRepository
bouncerRepository = it.bouncerRepository
}
underTest =
UdfpsLockscreenViewModel(
@@ -115,7 +114,7 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
burnInHelperWrapper = mock(),
testScope.backgroundScope,
configRepository,
FakeSystemClock(),
keyguardInteractor,
),
keyguardInteractor,
shadeRepository,

View File

@@ -371,6 +371,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mKeyguardLogger,
mFeatureFlags,
mInteractionJankMonitor,
mKeyguardInteractor,
mDumpManager));
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);

View File

@@ -43,7 +43,6 @@ import com.android.systemui.biometrics.AuthController;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor;
import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.ShadeViewController;
@@ -96,7 +95,6 @@ public class DozeServiceHostTest extends SysuiTestCase {
@Mock private BiometricUnlockController mBiometricUnlockController;
@Mock private AuthController mAuthController;
@Mock private DozeHost.Callback mCallback;
@Mock private BurnInInteractor mBurnInInteractor;
@Mock private DozeInteractor mDozeInteractor;
@Before
@@ -108,8 +106,7 @@ public class DozeServiceHostTest extends SysuiTestCase {
() -> mAssistManager, mDozeScrimController,
mKeyguardUpdateMonitor, mPulseExpansionHandler,
mNotificationShadeWindowController, mNotificationWakeUpCoordinator,
mAuthController, mNotificationIconAreaController, mDozeInteractor,
mBurnInInteractor);
mAuthController, mNotificationIconAreaController, mDozeInteractor);
mDozeServiceHost.initialize(
mCentralSurfaces,
@@ -234,11 +231,11 @@ public class DozeServiceHostTest extends SysuiTestCase {
verifyZeroInteractions(mDozeInteractor);
}
@Test
public void dozeTimeTickSentTBurnInInteractor() {
public void dozeTimeTickSentToDozeInteractor() {
// WHEN dozeTimeTick
mDozeServiceHost.dozeTimeTick();
// THEN burnInInteractor's dozeTimeTick is updated
verify(mBurnInInteractor).dozeTimeTick();
// THEN dozeInteractor's dozeTimeTick is updated
verify(mDozeInteractor).dozeTimeTick();
}
}

View File

@@ -30,7 +30,6 @@ import com.android.systemui.keyguard.shared.model.WakeSleepReason
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -60,7 +59,7 @@ class FakeKeyguardRepository : KeyguardRepository {
private val _isDozing = MutableStateFlow(false)
override val isDozing: StateFlow<Boolean> = _isDozing
private val _dozeTimeTick = MutableSharedFlow<Unit>()
private val _dozeTimeTick = MutableStateFlow<Long>(0L)
override val dozeTimeTick = _dozeTimeTick
private val _lastDozeTapToWakePosition = MutableStateFlow<Point?>(null)
@@ -174,7 +173,11 @@ class FakeKeyguardRepository : KeyguardRepository {
}
override fun dozeTimeTick() {
_dozeTimeTick.tryEmit(Unit)
_dozeTimeTick.value = _dozeTimeTick.value + 1
}
fun dozeTimeTick(millis: Long) {
_dozeTimeTick.value = millis
}
override fun setLastDozeTapToWakePosition(position: Point) {
@@ -237,6 +240,10 @@ class FakeKeyguardRepository : KeyguardRepository {
_isBypassEnabled = isEnabled
}
fun setScreenModel(screenModel: ScreenModel) {
_screenModel.value = screenModel
}
override fun isUdfpsSupported(): Boolean {
return _isUdfpsSupported.value
}