Merge changes Iaef3c67b,I983277fd into tm-qpr-dev

* changes:
  Bouncer - Fix default alignment
  Transitions - Add more source data, refine existing transitions
This commit is contained in:
Matt Pietal
2022-11-03 11:42:13 +00:00
committed by Android (Google) Code Review
21 changed files with 473 additions and 66 deletions

View File

@@ -228,7 +228,7 @@ open class ClockEventController @Inject constructor(
listenForDozing(this)
if (featureFlags.isEnabled(DOZING_MIGRATION_1)) {
listenForDozeAmountTransition(this)
listenForGoneToAodTransition(this)
listenForAnyStateToAodTransition(this)
} else {
listenForDozeAmount(this)
}
@@ -286,10 +286,10 @@ open class ClockEventController @Inject constructor(
* dozing.
*/
@VisibleForTesting
internal fun listenForGoneToAodTransition(scope: CoroutineScope): Job {
internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job {
return scope.launch {
keyguardTransitionInteractor.goneToAodTransition.filter {
it.transitionState == TransitionState.STARTED
keyguardTransitionInteractor.anyStateToAodTransition.filter {
it.transitionState == TransitionState.FINISHED
}.collect {
dozeAmount = 1f
clock?.animations?.doze(dozeAmount)

View File

@@ -106,8 +106,9 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
static final int USER_TYPE_WORK_PROFILE = 2;
static final int USER_TYPE_SECONDARY_USER = 3;
@IntDef({MODE_DEFAULT, MODE_ONE_HANDED, MODE_USER_SWITCHER})
@IntDef({MODE_UNINITIALIZED, MODE_DEFAULT, MODE_ONE_HANDED, MODE_USER_SWITCHER})
public @interface Mode {}
static final int MODE_UNINITIALIZED = -1;
static final int MODE_DEFAULT = 0;
static final int MODE_ONE_HANDED = 1;
static final int MODE_USER_SWITCHER = 2;
@@ -154,7 +155,11 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
private boolean mDisappearAnimRunning;
private SwipeListener mSwipeListener;
private ViewMode mViewMode = new DefaultViewMode();
private @Mode int mCurrentMode = MODE_DEFAULT;
/*
* Using MODE_UNINITIALIZED to mean the view mode is set to DefaultViewMode, but init() has not
* yet been called on it. This will happen when the ViewController is initialized.
*/
private @Mode int mCurrentMode = MODE_UNINITIALIZED;
private int mWidth = -1;
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
@@ -347,6 +352,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
private String modeToString(@Mode int mode) {
switch (mode) {
case MODE_UNINITIALIZED:
return "Uninitialized";
case MODE_DEFAULT:
return "Default";
case MODE_ONE_HANDED:

View File

@@ -318,6 +318,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
@Override
public void onInit() {
mSecurityViewFlipperController.init();
configureMode();
}
@Override

View File

@@ -23,9 +23,12 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.doze.DozeHost
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnlockMode
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
@@ -65,6 +68,9 @@ interface KeyguardRepository {
*/
val isKeyguardShowing: Flow<Boolean>
/** Observable for whether the bouncer is showing. */
val isBouncerShowing: Flow<Boolean>
/**
* Observable for whether we are in doze state.
*
@@ -95,6 +101,9 @@ interface KeyguardRepository {
/** Observable for device wake/sleep state */
val wakefulnessState: Flow<WakefulnessModel>
/** Observable for biometric unlock modes */
val biometricUnlockState: Flow<BiometricUnlockModel>
/**
* Returns `true` if the keyguard is showing; `false` otherwise.
*
@@ -125,6 +134,7 @@ constructor(
private val keyguardStateController: KeyguardStateController,
dozeHost: DozeHost,
wakefulnessLifecycle: WakefulnessLifecycle,
biometricUnlockController: BiometricUnlockController,
) : KeyguardRepository {
private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
override val animateBottomAreaDozingTransitions =
@@ -159,6 +169,29 @@ constructor(
awaitClose { keyguardStateController.removeCallback(callback) }
}
override val isBouncerShowing: Flow<Boolean> = conflatedCallbackFlow {
val callback =
object : KeyguardStateController.Callback {
override fun onBouncerShowingChanged() {
trySendWithFailureLogging(
keyguardStateController.isBouncerShowing,
TAG,
"updated isBouncerShowing"
)
}
}
keyguardStateController.addCallback(callback)
// Adding the callback does not send an initial update.
trySendWithFailureLogging(
keyguardStateController.isBouncerShowing,
TAG,
"initial isBouncerShowing"
)
awaitClose { keyguardStateController.removeCallback(callback) }
}
override val isDozing: Flow<Boolean> =
conflatedCallbackFlow {
val callback =
@@ -248,6 +281,24 @@ constructor(
awaitClose { wakefulnessLifecycle.removeObserver(callback) }
}
override val biometricUnlockState: Flow<BiometricUnlockModel> = conflatedCallbackFlow {
val callback =
object : BiometricUnlockController.BiometricModeListener {
override fun onModeChanged(@WakeAndUnlockMode mode: Int) {
trySendWithFailureLogging(biometricModeIntToObject(mode), TAG, "biometric mode")
}
}
biometricUnlockController.addBiometricModeListener(callback)
trySendWithFailureLogging(
biometricModeIntToObject(biometricUnlockController.getMode()),
TAG,
"initial biometric mode"
)
awaitClose { biometricUnlockController.removeBiometricModeListener(callback) }
}
override fun setAnimateDozingTransitions(animate: Boolean) {
_animateBottomAreaDozingTransitions.value = animate
}
@@ -279,6 +330,20 @@ constructor(
}
}
private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockModel {
return when (value) {
0 -> BiometricUnlockModel.NONE
1 -> BiometricUnlockModel.WAKE_AND_UNLOCK
2 -> BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
3 -> BiometricUnlockModel.SHOW_BOUNCER
4 -> BiometricUnlockModel.ONLY_WAKE
5 -> BiometricUnlockModel.UNLOCK_COLLAPSING
6 -> BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
7 -> BiometricUnlockModel.DISMISS_BOUNCER
else -> throw IllegalArgumentException("Invalid BiometricUnlockModel value: $value")
}
}
companion object {
private const val TAG = "KeyguardRepositoryImpl"
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2022 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.keyguard.domain.interactor
import android.animation.ValueAnimator
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
@SysUISingleton
class AodToGoneTransitionInteractor
@Inject
constructor(
@Application private val scope: CoroutineScope,
private val keyguardInteractor: KeyguardInteractor,
private val keyguardTransitionRepository: KeyguardTransitionRepository,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor("AOD->GONE") {
private val wakeAndUnlockModes =
setOf(WAKE_AND_UNLOCK, WAKE_AND_UNLOCK_FROM_DREAM, WAKE_AND_UNLOCK_PULSING)
override fun start() {
scope.launch {
keyguardInteractor.biometricUnlockState
.sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
.collect { pair ->
val (biometricUnlockState, keyguardState) = pair
if (
keyguardState == KeyguardState.AOD &&
wakeAndUnlockModes.contains(biometricUnlockState)
) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
name,
KeyguardState.AOD,
KeyguardState.GONE,
getAnimator(),
)
)
}
}
}
}
private fun getAnimator(): ValueAnimator {
return ValueAnimator().apply {
setInterpolator(Interpolators.LINEAR)
setDuration(TRANSITION_DURATION_MS)
}
}
companion object {
private const val TRANSITION_DURATION_MS = 500L
}
}

View File

@@ -19,6 +19,8 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -39,10 +41,19 @@ constructor(
val dozeAmount: Flow<Float> = repository.dozeAmount
/** Whether the system is in doze mode. */
val isDozing: Flow<Boolean> = repository.isDozing
/** Whether the keyguard is showing to not. */
/** Whether the keyguard is showing or not. */
val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
/** Whether the bouncer is showing or not. */
val isBouncerShowing: Flow<Boolean> = repository.isBouncerShowing
/** The device wake/sleep state */
val wakefulnessState: Flow<WakefulnessModel> = repository.wakefulnessState
/** Observable for the [StatusBarState] */
val statusBarState: Flow<StatusBarState> = repository.statusBarState
/**
* Observable for [BiometricUnlockModel] when biometrics like face or any fingerprint (rear,
* side, under display) is used to unlock the device.
*/
val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState
fun isKeyguardShowing(): Boolean {
return repository.isKeyguardShowing()

View File

@@ -41,11 +41,13 @@ constructor(
}
scope.launch {
interactor.finishedKeyguardState.collect { logger.i("Finished transition to", it) }
interactor.finishedKeyguardTransitionStep.collect {
logger.i("Finished transition", it)
}
}
scope.launch {
interactor.startedKeyguardState.collect { logger.i("Started transition to", it) }
interactor.startedKeyguardTransitionStep.collect { logger.i("Started transition", it) }
}
}
}

View File

@@ -41,6 +41,7 @@ constructor(
is AodLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
is GoneAodTransitionInteractor -> Log.d(TAG, "Started $it")
is LockscreenGoneTransitionInteractor -> Log.d(TAG, "Started $it")
is AodToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
}
it.start()
}

View File

@@ -21,7 +21,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -44,8 +43,9 @@ constructor(
/** LOCKSCREEN->AOD transition information. */
val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD)
/** GONE->AOD information. */
val goneToAodTransition: Flow<TransitionStep> = repository.transition(GONE, AOD)
/** (any)->AOD transition information */
val anyStateToAodTransition: Flow<TransitionStep> =
repository.transitions.filter { step -> step.to == KeyguardState.AOD }
/**
* AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
@@ -57,15 +57,15 @@ constructor(
lockscreenToAodTransition,
)
/* The last [TransitionStep] with a [TransitionState] of FINISHED */
val finishedKeyguardTransitionStep: Flow<TransitionStep> =
repository.transitions.filter { step -> step.transitionState == TransitionState.FINISHED }
/* The last completed [KeyguardState] transition */
val finishedKeyguardState: Flow<KeyguardState> =
repository.transitions
.filter { step -> step.transitionState == TransitionState.FINISHED }
.map { step -> step.to }
finishedKeyguardTransitionStep.map { step -> step.to }
/* The last started [KeyguardState] transition */
val startedKeyguardState: Flow<KeyguardState> =
repository.transitions
.filter { step -> step.transitionState == TransitionState.STARTED }
.map { step -> step.to }
/* The last [TransitionStep] with a [TransitionState] of STARTED */
val startedKeyguardTransitionStep: Flow<TransitionStep> =
repository.transitions.filter { step -> step.transitionState == TransitionState.STARTED }
}

View File

@@ -16,14 +16,16 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.util.kotlin.sample
import java.util.UUID
@@ -38,7 +40,7 @@ class LockscreenBouncerTransitionInteractor
@Inject
constructor(
@Application private val scope: CoroutineScope,
private val keyguardRepository: KeyguardRepository,
private val keyguardInteractor: KeyguardInteractor,
private val shadeRepository: ShadeRepository,
private val keyguardTransitionRepository: KeyguardTransitionRepository,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor
@@ -47,12 +49,47 @@ constructor(
private var transitionId: UUID? = null
override fun start() {
listenForDraggingUpToBouncer()
listenForBouncerHiding()
}
private fun listenForBouncerHiding() {
scope.launch {
keyguardInteractor.isBouncerShowing
.sample(keyguardInteractor.wakefulnessState, { a, b -> Pair(a, b) })
.collect { pair ->
val (isBouncerShowing, wakefulnessState) = pair
if (!isBouncerShowing) {
val to =
if (
wakefulnessState == WakefulnessModel.STARTING_TO_SLEEP ||
wakefulnessState == WakefulnessModel.ASLEEP
) {
KeyguardState.AOD
} else {
KeyguardState.LOCKSCREEN
}
keyguardTransitionRepository.startTransition(
TransitionInfo(
ownerName = name,
from = KeyguardState.BOUNCER,
to = to,
animator = getAnimator(),
)
)
}
}
}
}
/* Starts transitions when manually dragging up the bouncer from the lockscreen. */
private fun listenForDraggingUpToBouncer() {
scope.launch {
shadeRepository.shadeModel
.sample(
combine(
keyguardTransitionInteractor.finishedKeyguardState,
keyguardRepository.statusBarState,
keyguardInteractor.statusBarState,
) { keyguardState, statusBarState ->
Pair(keyguardState, statusBarState)
},
@@ -100,4 +137,15 @@ constructor(
}
}
}
private fun getAnimator(): ValueAnimator {
return ValueAnimator().apply {
setInterpolator(Interpolators.LINEAR)
setDuration(TRANSITION_DURATION_MS)
}
}
companion object {
private const val TRANSITION_DURATION_MS = 300L
}
}

View File

@@ -42,6 +42,8 @@ abstract class StartKeyguardTransitionModule {
@Binds @IntoSet abstract fun goneAod(impl: GoneAodTransitionInteractor): TransitionInteractor
@Binds @IntoSet abstract fun aodGone(impl: AodToGoneTransitionInteractor): TransitionInteractor
@Binds
@IntoSet
abstract fun lockscreenGone(impl: LockscreenGoneTransitionInteractor): TransitionInteractor

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2022 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.keyguard.shared.model
/** Model device wakefulness states. */
enum class BiometricUnlockModel {
/** Mode in which we don't need to wake up the device when we authenticate. */
NONE,
/**
* Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire a
* fingerprint while the screen is off and the device was sleeping.
*/
WAKE_AND_UNLOCK,
/**
* Mode in which we wake the device up, and fade out the Keyguard contents because they were
* already visible while pulsing in doze mode.
*/
WAKE_AND_UNLOCK_PULSING,
/**
* Mode in which we wake up the device, but play the normal dismiss animation. Active when we
* acquire a fingerprint pulsing in doze mode.
*/
SHOW_BOUNCER,
/**
* Mode in which we only wake up the device, and keyguard was not showing when we authenticated.
*/
ONLY_WAKE,
/**
* Mode in which fingerprint unlocks the device or passive auth (ie face auth) unlocks the
* device while being requested when keyguard is occluded or showing.
*/
UNLOCK_COLLAPSING,
/** When bouncer is visible and will be dismissed. */
DISMISS_BOUNCER,
/** Mode in which fingerprint wakes and unlocks the device from a dream. */
WAKE_AND_UNLOCK_FROM_DREAM,
}

View File

@@ -21,10 +21,11 @@ data class TransitionStep(
val to: KeyguardState = KeyguardState.NONE,
val value: Float = 0f, // constrained [0.0, 1.0]
val transitionState: TransitionState = TransitionState.FINISHED,
val ownerName: String = "",
) {
constructor(
info: TransitionInfo,
value: Float,
transitionState: TransitionState,
) : this(info.from, info.to, value, transitionState)
) : this(info.from, info.to, value, transitionState, info.ownerName)
}

View File

@@ -67,8 +67,10 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;
@@ -167,7 +169,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private PendingAuthenticated mPendingAuthenticated = null;
private boolean mHasScreenTurnedOnSinceAuthenticating;
private boolean mFadedAwayAfterWakeAndUnlock;
private BiometricModeListener mBiometricModeListener;
private Set<BiometricModeListener> mBiometricModeListeners = new HashSet<>();
private final MetricsLogger mMetricsLogger;
private final AuthController mAuthController;
@@ -314,9 +316,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mKeyguardViewController = keyguardViewController;
}
/** Sets a {@link BiometricModeListener}. */
public void setBiometricModeListener(BiometricModeListener biometricModeListener) {
mBiometricModeListener = biometricModeListener;
/** Adds a {@link BiometricModeListener}. */
public void addBiometricModeListener(BiometricModeListener listener) {
mBiometricModeListeners.add(listener);
}
/** Removes a {@link BiometricModeListener}. */
public void removeBiometricModeListener(BiometricModeListener listener) {
mBiometricModeListeners.remove(listener);
}
private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
@@ -499,15 +506,12 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
break;
}
onModeChanged(mMode);
if (mBiometricModeListener != null) {
mBiometricModeListener.notifyBiometricAuthModeChanged();
}
Trace.endSection();
}
private void onModeChanged(@WakeAndUnlockMode int mode) {
if (mBiometricModeListener != null) {
mBiometricModeListener.onModeChanged(mode);
for (BiometricModeListener listener : mBiometricModeListeners) {
listener.onModeChanged(mode);
}
}
@@ -714,9 +718,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mMode = MODE_NONE;
mBiometricType = null;
mNotificationShadeWindowController.setForceDozeBrightness(false);
if (mBiometricModeListener != null) {
mBiometricModeListener.onResetMode();
mBiometricModeListener.notifyBiometricAuthModeChanged();
for (BiometricModeListener listener : mBiometricModeListeners) {
listener.onResetMode();
}
mNumConsecutiveFpFailures = 0;
mLastFpFailureUptimeMillis = 0;
@@ -825,10 +828,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
/** An interface to interact with the {@link BiometricUnlockController}. */
public interface BiometricModeListener {
/** Called when {@code mMode} is reset to {@link #MODE_NONE}. */
void onResetMode();
default void onResetMode() {}
/** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */
void onModeChanged(@WakeAndUnlockMode int mode);
/** Called after processing {@link #onModeChanged(int)}. */
void notifyBiometricAuthModeChanged();
default void onModeChanged(@WakeAndUnlockMode int mode) {}
}
}

View File

@@ -1527,11 +1527,12 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
protected void startKeyguard() {
Trace.beginSection("CentralSurfaces#startKeyguard");
mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
mBiometricUnlockController.setBiometricModeListener(
mBiometricUnlockController.addBiometricModeListener(
new BiometricUnlockController.BiometricModeListener() {
@Override
public void onResetMode() {
setWakeAndUnlocking(false);
notifyBiometricAuthModeChanged();
}
@Override
@@ -1542,11 +1543,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
case BiometricUnlockController.MODE_WAKE_AND_UNLOCK:
setWakeAndUnlocking(true);
}
}
@Override
public void notifyBiometricAuthModeChanged() {
CentralSurfacesImpl.this.notifyBiometricAuthModeChanged();
notifyBiometricAuthModeChanged();
}
private void setWakeAndUnlocking(boolean wakeAndUnlocking) {

View File

@@ -193,6 +193,15 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
mSecurityCallback);
}
@Test
public void onInitConfiguresViewMode() {
mKeyguardSecurityContainerController.onInit();
verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
eq(mUserSwitcherController),
any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class),
eq(mFalsingA11yDelegate));
}
@Test
public void showSecurityScreen_canInflateAllModes() {
SecurityMode[] modes = SecurityMode.values();

View File

@@ -21,8 +21,10 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Position
import com.android.systemui.doze.DozeHost
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever
@@ -46,6 +48,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var dozeHost: DozeHost
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock private lateinit var biometricUnlockController: BiometricUnlockController
private lateinit var underTest: KeyguardRepositoryImpl
@@ -59,6 +62,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
keyguardStateController,
dozeHost,
wakefulnessLifecycle,
biometricUnlockController,
)
}
@@ -190,7 +194,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
}
@Test
fun wakefullness() = runBlockingTest {
fun wakefulness() = runBlockingTest {
val values = mutableListOf<WakefulnessModel>()
val job = underTest.wakefulnessState.onEach(values::add).launchIn(this)
@@ -217,4 +221,63 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
job.cancel()
verify(wakefulnessLifecycle).removeObserver(captor.value)
}
@Test
fun isBouncerShowing() = runBlockingTest {
whenever(keyguardStateController.isBouncerShowing).thenReturn(false)
var latest: Boolean? = null
val job = underTest.isBouncerShowing.onEach { latest = it }.launchIn(this)
assertThat(latest).isFalse()
val captor = argumentCaptor<KeyguardStateController.Callback>()
verify(keyguardStateController).addCallback(captor.capture())
whenever(keyguardStateController.isBouncerShowing).thenReturn(true)
captor.value.onBouncerShowingChanged()
assertThat(latest).isTrue()
whenever(keyguardStateController.isBouncerShowing).thenReturn(false)
captor.value.onBouncerShowingChanged()
assertThat(latest).isFalse()
job.cancel()
}
@Test
fun biometricUnlockState() = runBlockingTest {
val values = mutableListOf<BiometricUnlockModel>()
val job = underTest.biometricUnlockState.onEach(values::add).launchIn(this)
val captor = argumentCaptor<BiometricUnlockController.BiometricModeListener>()
verify(biometricUnlockController).addBiometricModeListener(captor.capture())
captor.value.onModeChanged(BiometricUnlockController.MODE_NONE)
captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK)
captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
captor.value.onModeChanged(BiometricUnlockController.MODE_SHOW_BOUNCER)
captor.value.onModeChanged(BiometricUnlockController.MODE_ONLY_WAKE)
captor.value.onModeChanged(BiometricUnlockController.MODE_UNLOCK_COLLAPSING)
captor.value.onModeChanged(BiometricUnlockController.MODE_DISMISS_BOUNCER)
captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM)
assertThat(values)
.isEqualTo(
listOf(
// Initial value will be NONE, followed by onModeChanged() call
BiometricUnlockModel.NONE,
BiometricUnlockModel.NONE,
BiometricUnlockModel.WAKE_AND_UNLOCK,
BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING,
BiometricUnlockModel.SHOW_BOUNCER,
BiometricUnlockModel.ONLY_WAKE,
BiometricUnlockModel.UNLOCK_COLLAPSING,
BiometricUnlockModel.DISMISS_BOUNCER,
BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM,
)
)
job.cancel()
verify(biometricUnlockController).removeBiometricModeListener(captor.value)
}
}

View File

@@ -128,11 +128,15 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
assertThat(steps.size).isEqualTo(3)
assertThat(steps[0])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED))
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED, OWNER_NAME))
assertThat(steps[1])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0.5f, TransitionState.RUNNING))
.isEqualTo(
TransitionStep(AOD, LOCKSCREEN, 0.5f, TransitionState.RUNNING, OWNER_NAME)
)
assertThat(steps[2])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED))
.isEqualTo(
TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED, OWNER_NAME)
)
job.cancel()
}
@@ -174,15 +178,22 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
}
private fun assertSteps(steps: List<TransitionStep>, fractions: List<BigDecimal>) {
assertThat(steps[0]).isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED))
assertThat(steps[0])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED, OWNER_NAME))
fractions.forEachIndexed { index, fraction ->
assertThat(steps[index + 1])
.isEqualTo(
TransitionStep(AOD, LOCKSCREEN, fraction.toFloat(), TransitionState.RUNNING)
TransitionStep(
AOD,
LOCKSCREEN,
fraction.toFloat(),
TransitionState.RUNNING,
OWNER_NAME
)
)
}
assertThat(steps[steps.size - 1])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED))
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED, OWNER_NAME))
assertThat(wtfHandler.failed).isFalse()
}

View File

@@ -54,9 +54,11 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
@Test
fun `transition collectors receives only appropriate events`() =
runBlocking(IMMEDIATE) {
var goneToAodSteps = mutableListOf<TransitionStep>()
var lockscreenToAodSteps = mutableListOf<TransitionStep>()
val job1 =
underTest.goneToAodTransition.onEach { goneToAodSteps.add(it) }.launchIn(this)
underTest.lockscreenToAodTransition
.onEach { lockscreenToAodSteps.add(it) }
.launchIn(this)
var aodToLockscreenSteps = mutableListOf<TransitionStep>()
val job2 =
@@ -70,14 +72,14 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
steps.add(TransitionStep(GONE, AOD, 0f, STARTED))
steps.add(TransitionStep(GONE, AOD, 0.1f, RUNNING))
steps.add(TransitionStep(GONE, AOD, 0.2f, RUNNING))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0.1f, RUNNING))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0.2f, RUNNING))
steps.forEach { repository.sendTransitionStep(it) }
assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5))
assertThat(goneToAodSteps).isEqualTo(steps.subList(5, 8))
assertThat(lockscreenToAodSteps).isEqualTo(steps.subList(5, 8))
job1.cancel()
job2.cancel()
@@ -119,10 +121,8 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
fun keyguardStateTests() =
runBlocking(IMMEDIATE) {
var finishedSteps = mutableListOf<KeyguardState>()
val job1 =
val job =
underTest.finishedKeyguardState.onEach { finishedSteps.add(it) }.launchIn(this)
var startedSteps = mutableListOf<KeyguardState>()
val job2 = underTest.startedKeyguardState.onEach { startedSteps.add(it) }.launchIn(this)
val steps = mutableListOf<TransitionStep>()
@@ -137,10 +137,60 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
steps.forEach { repository.sendTransitionStep(it) }
assertThat(finishedSteps).isEqualTo(listOf(LOCKSCREEN, AOD))
assertThat(startedSteps).isEqualTo(listOf(LOCKSCREEN, AOD, GONE))
job1.cancel()
job2.cancel()
job.cancel()
}
@Test
fun finishedKeyguardTransitionStepTests() =
runBlocking(IMMEDIATE) {
var finishedSteps = mutableListOf<TransitionStep>()
val job =
underTest.finishedKeyguardTransitionStep
.onEach { finishedSteps.add(it) }
.launchIn(this)
val steps = mutableListOf<TransitionStep>()
steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
steps.forEach { repository.sendTransitionStep(it) }
assertThat(finishedSteps).isEqualTo(listOf(steps[2], steps[5]))
job.cancel()
}
@Test
fun startedKeyguardTransitionStepTests() =
runBlocking(IMMEDIATE) {
var startedSteps = mutableListOf<TransitionStep>()
val job =
underTest.startedKeyguardTransitionStep
.onEach { startedSteps.add(it) }
.launchIn(this)
val steps = mutableListOf<TransitionStep>()
steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
steps.forEach { repository.sendTransitionStep(it) }
assertThat(startedSteps).isEqualTo(listOf(steps[0], steps[3], steps[6]))
job.cancel()
}
companion object {

View File

@@ -143,7 +143,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
mAuthController, mStatusBarStateController, mKeyguardUnlockAnimationController,
mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener);
mBiometricUnlockController.addBiometricModeListener(mBiometricModeListener);
}
@Test

View File

@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.data.repository
import com.android.systemui.common.shared.model.Position
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import kotlinx.coroutines.flow.Flow
@@ -52,6 +53,12 @@ class FakeKeyguardRepository : KeyguardRepository {
private val _wakefulnessState = MutableStateFlow(WakefulnessModel.ASLEEP)
override val wakefulnessState: Flow<WakefulnessModel> = _wakefulnessState
private val _isBouncerShowing = MutableStateFlow(false)
override val isBouncerShowing: Flow<Boolean> = _isBouncerShowing
private val _biometricUnlockState = MutableStateFlow(BiometricUnlockModel.NONE)
override val biometricUnlockState: Flow<BiometricUnlockModel> = _biometricUnlockState
override fun isKeyguardShowing(): Boolean {
return _isKeyguardShowing.value
}