Merge "[Keyguard Bouncer] Add new data flow." into tm-qpr-dev am: d316c7d45c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19418880 Change-Id: I27d369e256f054d320b80b3e57062b830eeefd96 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -103,6 +103,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
|
android:visibility="invisible"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false" />
|
android:clipToPadding="false" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -1096,6 +1096,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mView.setAlpha(1f);
|
||||||
mUserSwitcherViewGroup.setAlpha(0f);
|
mUserSwitcherViewGroup.setAlpha(0f);
|
||||||
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mUserSwitcherViewGroup, View.ALPHA,
|
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mUserSwitcherViewGroup, View.ALPHA,
|
||||||
1f);
|
1f);
|
||||||
|
|||||||
@@ -106,6 +106,14 @@ public class KeyguardSimPukViewController
|
|||||||
mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
|
mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume(int reason) {
|
||||||
|
super.onResume(reason);
|
||||||
|
if (mShowDefaultMessage) {
|
||||||
|
showDefaultMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void resetState() {
|
void resetState() {
|
||||||
super.resetState();
|
super.resetState();
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import com.android.systemui.dreams.dagger.DreamModule;
|
|||||||
import com.android.systemui.dump.DumpManager;
|
import com.android.systemui.dump.DumpManager;
|
||||||
import com.android.systemui.flags.FlagsModule;
|
import com.android.systemui.flags.FlagsModule;
|
||||||
import com.android.systemui.fragments.FragmentService;
|
import com.android.systemui.fragments.FragmentService;
|
||||||
|
import com.android.systemui.keyguard.data.BouncerViewModule;
|
||||||
import com.android.systemui.log.dagger.LogModule;
|
import com.android.systemui.log.dagger.LogModule;
|
||||||
import com.android.systemui.media.dagger.MediaProjectionModule;
|
import com.android.systemui.media.dagger.MediaProjectionModule;
|
||||||
import com.android.systemui.model.SysUiState;
|
import com.android.systemui.model.SysUiState;
|
||||||
@@ -116,6 +117,7 @@ import dagger.Provides;
|
|||||||
AppOpsModule.class,
|
AppOpsModule.class,
|
||||||
AssistModule.class,
|
AssistModule.class,
|
||||||
BiometricsModule.class,
|
BiometricsModule.class,
|
||||||
|
BouncerViewModule.class,
|
||||||
ClockModule.class,
|
ClockModule.class,
|
||||||
CoroutinesModule.class,
|
CoroutinesModule.class,
|
||||||
DreamModule.class,
|
DreamModule.class,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import com.android.systemui.dagger.qualifiers.Main;
|
|||||||
import com.android.systemui.dreams.complication.ComplicationHostViewController;
|
import com.android.systemui.dreams.complication.ComplicationHostViewController;
|
||||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||||
import com.android.systemui.dreams.dagger.DreamOverlayModule;
|
import com.android.systemui.dreams.dagger.DreamOverlayModule;
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.BouncerCallbackInteractor;
|
||||||
import com.android.systemui.statusbar.BlurUtils;
|
import com.android.systemui.statusbar.BlurUtils;
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBouncer;
|
import com.android.systemui.statusbar.phone.KeyguardBouncer;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||||
@@ -73,6 +74,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
|||||||
// Main thread handler used to schedule periodic tasks (e.g. burn-in protection updates).
|
// Main thread handler used to schedule periodic tasks (e.g. burn-in protection updates).
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final int mDreamOverlayMaxTranslationY;
|
private final int mDreamOverlayMaxTranslationY;
|
||||||
|
private final BouncerCallbackInteractor mBouncerCallbackInteractor;
|
||||||
|
|
||||||
private long mJitterStartTimeMillis;
|
private long mJitterStartTimeMillis;
|
||||||
|
|
||||||
@@ -131,7 +133,8 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
|||||||
@Named(DreamOverlayModule.MAX_BURN_IN_OFFSET) int maxBurnInOffset,
|
@Named(DreamOverlayModule.MAX_BURN_IN_OFFSET) int maxBurnInOffset,
|
||||||
@Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
|
@Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
|
||||||
burnInProtectionUpdateInterval,
|
burnInProtectionUpdateInterval,
|
||||||
@Named(DreamOverlayModule.MILLIS_UNTIL_FULL_JITTER) long millisUntilFullJitter) {
|
@Named(DreamOverlayModule.MILLIS_UNTIL_FULL_JITTER) long millisUntilFullJitter,
|
||||||
|
BouncerCallbackInteractor bouncerCallbackInteractor) {
|
||||||
super(containerView);
|
super(containerView);
|
||||||
mDreamOverlayContentView = contentView;
|
mDreamOverlayContentView = contentView;
|
||||||
mStatusBarViewController = statusBarViewController;
|
mStatusBarViewController = statusBarViewController;
|
||||||
@@ -151,6 +154,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
|||||||
mMaxBurnInOffset = maxBurnInOffset;
|
mMaxBurnInOffset = maxBurnInOffset;
|
||||||
mBurnInProtectionUpdateInterval = burnInProtectionUpdateInterval;
|
mBurnInProtectionUpdateInterval = burnInProtectionUpdateInterval;
|
||||||
mMillisUntilFullJitter = millisUntilFullJitter;
|
mMillisUntilFullJitter = millisUntilFullJitter;
|
||||||
|
mBouncerCallbackInteractor = bouncerCallbackInteractor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -167,6 +171,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
|||||||
if (bouncer != null) {
|
if (bouncer != null) {
|
||||||
bouncer.addBouncerExpansionCallback(mBouncerExpansionCallback);
|
bouncer.addBouncerExpansionCallback(mBouncerExpansionCallback);
|
||||||
}
|
}
|
||||||
|
mBouncerCallbackInteractor.addBouncerExpansionCallback(mBouncerExpansionCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -176,6 +181,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
|||||||
if (bouncer != null) {
|
if (bouncer != null) {
|
||||||
bouncer.removeBouncerExpansionCallback(mBouncerExpansionCallback);
|
bouncer.removeBouncerExpansionCallback(mBouncerExpansionCallback);
|
||||||
}
|
}
|
||||||
|
mBouncerCallbackInteractor.removeBouncerExpansionCallback(mBouncerExpansionCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
View getContainerView() {
|
View getContainerView() {
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.data
|
||||||
|
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/** An abstraction to interface with the ui layer, without changing state. */
|
||||||
|
interface BouncerView {
|
||||||
|
var delegate: BouncerViewDelegate?
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A lightweight class to hold reference to the ui delegate. */
|
||||||
|
@SysUISingleton
|
||||||
|
class BouncerViewImpl @Inject constructor() : BouncerView {
|
||||||
|
private var _delegate: WeakReference<BouncerViewDelegate?> = WeakReference(null)
|
||||||
|
override var delegate: BouncerViewDelegate?
|
||||||
|
get() = _delegate.get()
|
||||||
|
set(value) {
|
||||||
|
_delegate = WeakReference(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An abstraction that implements view logic. */
|
||||||
|
interface BouncerViewDelegate {
|
||||||
|
fun isFullScreenBouncer(): Boolean
|
||||||
|
fun shouldDismissOnMenuPressed(): Boolean
|
||||||
|
fun interceptMediaKey(event: KeyEvent?): Boolean
|
||||||
|
fun dispatchBackKeyEventPreIme(): Boolean
|
||||||
|
fun showNextSecurityScreenOrFinish(): Boolean
|
||||||
|
fun resume()
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.data
|
||||||
|
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
|
||||||
|
@Module
|
||||||
|
interface BouncerViewModule {
|
||||||
|
/** Binds BouncerView to BouncerViewImpl and makes it injectable. */
|
||||||
|
@Binds fun bindBouncerView(bouncerViewImpl: BouncerViewImpl): BouncerView
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* 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.data.repository
|
||||||
|
|
||||||
|
import android.hardware.biometrics.BiometricSourceType
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitorCallback
|
||||||
|
import com.android.keyguard.ViewMediatorCallback
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.keyguard.shared.model.BouncerCallbackActionsModel
|
||||||
|
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
|
||||||
|
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_HIDDEN
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
|
||||||
|
/** Encapsulates app state for the lock screen bouncer. */
|
||||||
|
@SysUISingleton
|
||||||
|
class KeyguardBouncerRepository
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
private val viewMediatorCallback: ViewMediatorCallback,
|
||||||
|
keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||||
|
) {
|
||||||
|
var bouncerPromptReason: Int? = null
|
||||||
|
/** Determines if we want to instantaneously show the bouncer instead of translating. */
|
||||||
|
private val _isScrimmed = MutableStateFlow(false)
|
||||||
|
val isScrimmed = _isScrimmed.asStateFlow()
|
||||||
|
/** Set amount of how much of the bouncer is showing on the screen */
|
||||||
|
private val _expansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
|
||||||
|
val expansionAmount = _expansionAmount.asStateFlow()
|
||||||
|
private val _isVisible = MutableStateFlow(false)
|
||||||
|
val isVisible = _isVisible.asStateFlow()
|
||||||
|
private val _show = MutableStateFlow<KeyguardBouncerModel?>(null)
|
||||||
|
val show = _show.asStateFlow()
|
||||||
|
private val _showingSoon = MutableStateFlow(false)
|
||||||
|
val showingSoon = _showingSoon.asStateFlow()
|
||||||
|
private val _hide = MutableStateFlow(false)
|
||||||
|
val hide = _hide.asStateFlow()
|
||||||
|
private val _startingToHide = MutableStateFlow(false)
|
||||||
|
val startingToHide = _startingToHide.asStateFlow()
|
||||||
|
private val _onDismissAction = MutableStateFlow<BouncerCallbackActionsModel?>(null)
|
||||||
|
val onDismissAction = _onDismissAction.asStateFlow()
|
||||||
|
private val _disappearAnimation = MutableStateFlow<Runnable?>(null)
|
||||||
|
val startingDisappearAnimation = _disappearAnimation.asStateFlow()
|
||||||
|
private val _keyguardPosition = MutableStateFlow(0f)
|
||||||
|
val keyguardPosition = _keyguardPosition.asStateFlow()
|
||||||
|
private val _resourceUpdateRequests = MutableStateFlow(false)
|
||||||
|
val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
|
||||||
|
private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
|
||||||
|
val showMessage = _showMessage.asStateFlow()
|
||||||
|
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
|
||||||
|
/** Determines if user is already unlocked */
|
||||||
|
val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
|
||||||
|
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
|
||||||
|
val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
|
||||||
|
private val _onScreenTurnedOff = MutableStateFlow(false)
|
||||||
|
val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
|
||||||
|
|
||||||
|
val bouncerErrorMessage: CharSequence?
|
||||||
|
get() = viewMediatorCallback.consumeCustomMessage()
|
||||||
|
|
||||||
|
init {
|
||||||
|
val callback =
|
||||||
|
object : KeyguardUpdateMonitorCallback() {
|
||||||
|
override fun onStrongAuthStateChanged(userId: Int) {
|
||||||
|
bouncerPromptReason = viewMediatorCallback.bouncerPromptReason
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLockedOutStateChanged(type: BiometricSourceType) {
|
||||||
|
if (type == BiometricSourceType.FINGERPRINT) {
|
||||||
|
bouncerPromptReason = viewMediatorCallback.bouncerPromptReason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyguardUpdateMonitor.registerCallback(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setScrimmed(isScrimmed: Boolean) {
|
||||||
|
_isScrimmed.value = isScrimmed
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setExpansion(expansion: Float) {
|
||||||
|
_expansionAmount.value = expansion
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setVisible(isVisible: Boolean) {
|
||||||
|
_isVisible.value = isVisible
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setShow(keyguardBouncerModel: KeyguardBouncerModel?) {
|
||||||
|
_show.value = keyguardBouncerModel
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setShowingSoon(showingSoon: Boolean) {
|
||||||
|
_showingSoon.value = showingSoon
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setHide(hide: Boolean) {
|
||||||
|
_hide.value = hide
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setStartingToHide(startingToHide: Boolean) {
|
||||||
|
_startingToHide.value = startingToHide
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnDismissAction(bouncerCallbackActionsModel: BouncerCallbackActionsModel?) {
|
||||||
|
_onDismissAction.value = bouncerCallbackActionsModel
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setStartDisappearAnimation(runnable: Runnable?) {
|
||||||
|
_disappearAnimation.value = runnable
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setKeyguardPosition(keyguardPosition: Float) {
|
||||||
|
_keyguardPosition.value = keyguardPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setResourceUpdateRequests(willUpdateResources: Boolean) {
|
||||||
|
_resourceUpdateRequests.value = willUpdateResources
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
|
||||||
|
_showMessage.value = bouncerShowMessageModel
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
|
||||||
|
_keyguardAuthenticated.value = keyguardAuthenticated
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
|
||||||
|
_isBackButtonEnabled.value = isBackButtonEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
|
||||||
|
_onScreenTurnedOff.value = onScreenTurnedOff
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* 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.view.View
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBouncer
|
||||||
|
import com.android.systemui.util.ListenerSet
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/** Interactor to add and remove callbacks for the bouncer. */
|
||||||
|
@SysUISingleton
|
||||||
|
class BouncerCallbackInteractor @Inject constructor() {
|
||||||
|
private var resetCallbacks = ListenerSet<KeyguardBouncer.KeyguardResetCallback>()
|
||||||
|
private var expansionCallbacks = ArrayList<KeyguardBouncer.BouncerExpansionCallback>()
|
||||||
|
/** Add a KeyguardResetCallback. */
|
||||||
|
fun addKeyguardResetCallback(callback: KeyguardBouncer.KeyguardResetCallback) {
|
||||||
|
resetCallbacks.addIfAbsent(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove a KeyguardResetCallback. */
|
||||||
|
fun removeKeyguardResetCallback(callback: KeyguardBouncer.KeyguardResetCallback) {
|
||||||
|
resetCallbacks.remove(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a callback to listen to bouncer expansion updates. */
|
||||||
|
fun addBouncerExpansionCallback(callback: KeyguardBouncer.BouncerExpansionCallback) {
|
||||||
|
if (!expansionCallbacks.contains(callback)) {
|
||||||
|
expansionCallbacks.add(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a previously added callback. If the callback was never added, this method does
|
||||||
|
* nothing.
|
||||||
|
*/
|
||||||
|
fun removeBouncerExpansionCallback(callback: KeyguardBouncer.BouncerExpansionCallback) {
|
||||||
|
expansionCallbacks.remove(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Propagate fully shown to bouncer expansion callbacks. */
|
||||||
|
fun dispatchFullyShown() {
|
||||||
|
for (callback in expansionCallbacks) {
|
||||||
|
callback.onFullyShown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Propagate starting to hide to bouncer expansion callbacks. */
|
||||||
|
fun dispatchStartingToHide() {
|
||||||
|
for (callback in expansionCallbacks) {
|
||||||
|
callback.onStartingToHide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Propagate starting to show to bouncer expansion callbacks. */
|
||||||
|
fun dispatchStartingToShow() {
|
||||||
|
for (callback in expansionCallbacks) {
|
||||||
|
callback.onStartingToShow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Propagate fully hidden to bouncer expansion callbacks. */
|
||||||
|
fun dispatchFullyHidden() {
|
||||||
|
for (callback in expansionCallbacks) {
|
||||||
|
callback.onFullyHidden()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Propagate expansion changes to bouncer expansion callbacks. */
|
||||||
|
fun dispatchExpansionChanged(expansion: Float) {
|
||||||
|
for (callback in expansionCallbacks) {
|
||||||
|
callback.onExpansionChanged(expansion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Propagate visibility changes to bouncer expansion callbacks. */
|
||||||
|
fun dispatchVisibilityChanged(visibility: Int) {
|
||||||
|
for (callback in expansionCallbacks) {
|
||||||
|
callback.onVisibilityChanged(visibility == View.VISIBLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Propagate keyguard reset. */
|
||||||
|
fun dispatchReset() {
|
||||||
|
for (callback in resetCallbacks) {
|
||||||
|
callback.onKeyguardReset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,324 @@
|
|||||||
|
/*
|
||||||
|
* 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.content.res.ColorStateList
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Trace
|
||||||
|
import android.os.UserHandle
|
||||||
|
import android.os.UserManager
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
|
import com.android.systemui.DejankUtils
|
||||||
|
import com.android.systemui.classifier.FalsingCollector
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main
|
||||||
|
import com.android.systemui.keyguard.DismissCallbackRegistry
|
||||||
|
import com.android.systemui.keyguard.data.BouncerView
|
||||||
|
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
|
||||||
|
import com.android.systemui.keyguard.shared.model.BouncerCallbackActionsModel
|
||||||
|
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
|
||||||
|
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
|
||||||
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
|
import com.android.systemui.shared.system.SysUiStatsLog
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBouncer
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||||
|
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
|
/** Encapsulates business logic for interacting with the lock-screen bouncer. */
|
||||||
|
@SysUISingleton
|
||||||
|
class BouncerInteractor
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
private val repository: KeyguardBouncerRepository,
|
||||||
|
private val bouncerView: BouncerView,
|
||||||
|
@Main private val mainHandler: Handler,
|
||||||
|
private val keyguardStateController: KeyguardStateController,
|
||||||
|
private val keyguardSecurityModel: KeyguardSecurityModel,
|
||||||
|
private val callbackInteractor: BouncerCallbackInteractor,
|
||||||
|
private val falsingCollector: FalsingCollector,
|
||||||
|
private val dismissCallbackRegistry: DismissCallbackRegistry,
|
||||||
|
keyguardBypassController: KeyguardBypassController,
|
||||||
|
keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||||
|
) {
|
||||||
|
/** Whether we want to wait for face auth. */
|
||||||
|
private val bouncerFaceDelay =
|
||||||
|
keyguardStateController.isFaceAuthEnabled &&
|
||||||
|
!keyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
|
||||||
|
KeyguardUpdateMonitor.getCurrentUser()
|
||||||
|
) &&
|
||||||
|
!needsFullscreenBouncer() &&
|
||||||
|
!keyguardUpdateMonitor.userNeedsStrongAuth() &&
|
||||||
|
!keyguardBypassController.bypassEnabled
|
||||||
|
|
||||||
|
/** Runnable to show the bouncer. */
|
||||||
|
val showRunnable = Runnable {
|
||||||
|
repository.setVisible(true)
|
||||||
|
repository.setShow(
|
||||||
|
KeyguardBouncerModel(
|
||||||
|
promptReason = repository.bouncerPromptReason ?: 0,
|
||||||
|
errorMessage = repository.bouncerErrorMessage,
|
||||||
|
expansionAmount = repository.expansionAmount.value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
repository.setShowingSoon(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
|
||||||
|
val screenTurnedOff: Flow<Unit> = repository.onScreenTurnedOff.filter { it }.map {}
|
||||||
|
val show: Flow<KeyguardBouncerModel> = repository.show.filterNotNull()
|
||||||
|
val hide: Flow<Unit> = repository.hide.filter { it }.map {}
|
||||||
|
val startingToHide: Flow<Unit> = repository.startingToHide.filter { it }.map {}
|
||||||
|
val isVisible: Flow<Boolean> = repository.isVisible
|
||||||
|
val isBackButtonEnabled: Flow<Boolean> = repository.isBackButtonEnabled.filterNotNull()
|
||||||
|
val expansionAmount: Flow<Float> = repository.expansionAmount
|
||||||
|
val showMessage: Flow<BouncerShowMessageModel> = repository.showMessage.filterNotNull()
|
||||||
|
val startingDisappearAnimation: Flow<Runnable> =
|
||||||
|
repository.startingDisappearAnimation.filterNotNull()
|
||||||
|
val onDismissAction: Flow<BouncerCallbackActionsModel> =
|
||||||
|
repository.onDismissAction.filterNotNull()
|
||||||
|
val resourceUpdateRequests: Flow<Boolean> = repository.resourceUpdateRequests.filter { it }
|
||||||
|
val keyguardPosition: Flow<Float> = repository.keyguardPosition
|
||||||
|
|
||||||
|
// TODO(b/243685699): Move isScrimmed logic to data layer.
|
||||||
|
// TODO(b/243695312): Encapsulate all of the show logic for the bouncer.
|
||||||
|
/** Show the bouncer if necessary and set the relevant states. */
|
||||||
|
@JvmOverloads
|
||||||
|
fun show(isScrimmed: Boolean) {
|
||||||
|
// Reset some states as we show the bouncer.
|
||||||
|
repository.setShowMessage(null)
|
||||||
|
repository.setOnScreenTurnedOff(false)
|
||||||
|
repository.setKeyguardAuthenticated(null)
|
||||||
|
repository.setHide(false)
|
||||||
|
repository.setStartingToHide(false)
|
||||||
|
|
||||||
|
val resumeBouncer =
|
||||||
|
(repository.isVisible.value || repository.showingSoon.value) && needsFullscreenBouncer()
|
||||||
|
|
||||||
|
if (!resumeBouncer && repository.show.value != null) {
|
||||||
|
// If bouncer is visible, the bouncer is already showing.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val keyguardUserId = KeyguardUpdateMonitor.getCurrentUser()
|
||||||
|
if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
|
||||||
|
// In split system user mode, we never unlock system user.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace.beginSection("KeyguardBouncer#show")
|
||||||
|
repository.setScrimmed(isScrimmed)
|
||||||
|
if (isScrimmed) {
|
||||||
|
setExpansion(KeyguardBouncer.EXPANSION_VISIBLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resumeBouncer) {
|
||||||
|
bouncerView.delegate?.resume()
|
||||||
|
// Bouncer is showing the next security screen and we just need to prompt a resume.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (bouncerView.delegate?.showNextSecurityScreenOrFinish() == true) {
|
||||||
|
// Keyguard is done.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
repository.setShowingSoon(true)
|
||||||
|
if (bouncerFaceDelay) {
|
||||||
|
mainHandler.postDelayed(showRunnable, 1200L)
|
||||||
|
} else {
|
||||||
|
DejankUtils.postAfterTraversal(showRunnable)
|
||||||
|
}
|
||||||
|
keyguardStateController.notifyBouncerShowing(true)
|
||||||
|
callbackInteractor.dispatchStartingToShow()
|
||||||
|
|
||||||
|
Trace.endSection()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the correct bouncer states to hide the bouncer. */
|
||||||
|
fun hide() {
|
||||||
|
Trace.beginSection("KeyguardBouncer#hide")
|
||||||
|
if (isFullyShowing()) {
|
||||||
|
SysUiStatsLog.write(
|
||||||
|
SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
|
||||||
|
SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN
|
||||||
|
)
|
||||||
|
dismissCallbackRegistry.notifyDismissCancelled()
|
||||||
|
}
|
||||||
|
|
||||||
|
falsingCollector.onBouncerHidden()
|
||||||
|
keyguardStateController.notifyBouncerShowing(false /* showing */)
|
||||||
|
cancelShowRunnable()
|
||||||
|
repository.setShowingSoon(false)
|
||||||
|
repository.setOnDismissAction(null)
|
||||||
|
repository.setVisible(false)
|
||||||
|
repository.setHide(true)
|
||||||
|
repository.setShow(null)
|
||||||
|
Trace.endSection()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the panel expansion which is calculated further upstream. Expansion is from 0f to 1f
|
||||||
|
* where 0f => showing and 1f => hiding
|
||||||
|
*/
|
||||||
|
fun setExpansion(expansion: Float) {
|
||||||
|
val oldExpansion = repository.expansionAmount.value
|
||||||
|
val expansionChanged = oldExpansion != expansion
|
||||||
|
if (repository.startingDisappearAnimation.value == null) {
|
||||||
|
repository.setExpansion(expansion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
expansion == KeyguardBouncer.EXPANSION_VISIBLE &&
|
||||||
|
oldExpansion != KeyguardBouncer.EXPANSION_VISIBLE
|
||||||
|
) {
|
||||||
|
falsingCollector.onBouncerShown()
|
||||||
|
callbackInteractor.dispatchFullyShown()
|
||||||
|
} else if (
|
||||||
|
expansion == KeyguardBouncer.EXPANSION_HIDDEN &&
|
||||||
|
oldExpansion != KeyguardBouncer.EXPANSION_HIDDEN
|
||||||
|
) {
|
||||||
|
repository.setVisible(false)
|
||||||
|
repository.setShow(null)
|
||||||
|
falsingCollector.onBouncerHidden()
|
||||||
|
DejankUtils.postAfterTraversal { callbackInteractor.dispatchReset() }
|
||||||
|
callbackInteractor.dispatchFullyHidden()
|
||||||
|
} else if (
|
||||||
|
expansion != KeyguardBouncer.EXPANSION_VISIBLE &&
|
||||||
|
oldExpansion == KeyguardBouncer.EXPANSION_VISIBLE
|
||||||
|
) {
|
||||||
|
callbackInteractor.dispatchStartingToHide()
|
||||||
|
repository.setStartingToHide(true)
|
||||||
|
}
|
||||||
|
if (expansionChanged) {
|
||||||
|
callbackInteractor.dispatchExpansionChanged(expansion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the initial keyguard message to show when bouncer is shown. */
|
||||||
|
fun showMessage(message: String?, colorStateList: ColorStateList?) {
|
||||||
|
repository.setShowMessage(BouncerShowMessageModel(message, colorStateList))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets actions to the bouncer based on how the bouncer is dismissed. If the bouncer is
|
||||||
|
* unlocked, we will run the onDismissAction. If the bouncer is existed before unlocking, we
|
||||||
|
* call cancelAction.
|
||||||
|
*/
|
||||||
|
fun setDismissAction(
|
||||||
|
onDismissAction: ActivityStarter.OnDismissAction?,
|
||||||
|
cancelAction: Runnable?
|
||||||
|
) {
|
||||||
|
repository.setOnDismissAction(BouncerCallbackActionsModel(onDismissAction, cancelAction))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update the resources of the views. */
|
||||||
|
fun updateResources() {
|
||||||
|
repository.setResourceUpdateRequests(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tell the bouncer that keyguard is authenticated. */
|
||||||
|
fun notifyKeyguardAuthenticated(strongAuth: Boolean) {
|
||||||
|
repository.setKeyguardAuthenticated(strongAuth)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tell the bouncer the screen has turned off. */
|
||||||
|
fun onScreenTurnedOff() {
|
||||||
|
repository.setOnScreenTurnedOff(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update the position of the bouncer when showing. */
|
||||||
|
fun setKeyguardPosition(position: Float) {
|
||||||
|
repository.setKeyguardPosition(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Notifies that the state change was handled. */
|
||||||
|
fun notifyKeyguardAuthenticatedHandled() {
|
||||||
|
repository.setKeyguardAuthenticated(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Notify that view visibility has changed. */
|
||||||
|
fun notifyBouncerVisibilityHasChanged(visibility: Int) {
|
||||||
|
callbackInteractor.dispatchVisibilityChanged(visibility)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Notify that the resources have been updated */
|
||||||
|
fun notifyUpdatedResources() {
|
||||||
|
repository.setResourceUpdateRequests(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set whether back button is enabled when on the bouncer screen. */
|
||||||
|
fun setBackButtonEnabled(enabled: Boolean) {
|
||||||
|
repository.setIsBackButtonEnabled(enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tell the bouncer to start the pre hide animation. */
|
||||||
|
fun startDisappearAnimation(runnable: Runnable) {
|
||||||
|
val finishRunnable = Runnable {
|
||||||
|
repository.setStartDisappearAnimation(null)
|
||||||
|
runnable.run()
|
||||||
|
}
|
||||||
|
repository.setStartDisappearAnimation(finishRunnable)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether bouncer is fully showing. */
|
||||||
|
fun isFullyShowing(): Boolean {
|
||||||
|
return (repository.showingSoon.value || repository.isVisible.value) &&
|
||||||
|
repository.expansionAmount.value == KeyguardBouncer.EXPANSION_VISIBLE &&
|
||||||
|
repository.startingDisappearAnimation.value == null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether bouncer is scrimmed. */
|
||||||
|
fun isScrimmed(): Boolean {
|
||||||
|
return repository.isScrimmed.value
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If bouncer expansion is between 0f and 1f non-inclusive. */
|
||||||
|
fun isInTransit(): Boolean {
|
||||||
|
return repository.showingSoon.value ||
|
||||||
|
repository.expansionAmount.value != KeyguardBouncer.EXPANSION_HIDDEN &&
|
||||||
|
repository.expansionAmount.value != KeyguardBouncer.EXPANSION_VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return whether bouncer is animating away. */
|
||||||
|
fun isAnimatingAway(): Boolean {
|
||||||
|
return repository.startingDisappearAnimation.value != null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return whether bouncer will dismiss with actions */
|
||||||
|
fun willDismissWithAction(): Boolean {
|
||||||
|
return repository.onDismissAction.value?.onDismissAction != null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether the bouncer should be full screen. */
|
||||||
|
private fun needsFullscreenBouncer(): Boolean {
|
||||||
|
val mode: KeyguardSecurityModel.SecurityMode =
|
||||||
|
keyguardSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser())
|
||||||
|
return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
|
||||||
|
mode == KeyguardSecurityModel.SecurityMode.SimPuk
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove the show runnable from the main handler queue to improve performance. */
|
||||||
|
private fun cancelShowRunnable() {
|
||||||
|
DejankUtils.removeCallbacks(showRunnable)
|
||||||
|
mainHandler.removeCallbacks(showRunnable)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
|
|
||||||
|
/** Encapsulates callbacks to be invoked by the bouncer logic. */
|
||||||
|
// TODO(b/243683121): Move dismiss logic from view controllers
|
||||||
|
data class BouncerCallbackActionsModel(
|
||||||
|
val onDismissAction: ActivityStarter.OnDismissAction?,
|
||||||
|
val cancelAction: Runnable?
|
||||||
|
)
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
|
||||||
|
/** Show a keyguard message to the bouncer. */
|
||||||
|
data class BouncerShowMessageModel(val message: String?, val colorStateList: ColorStateList?)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
/** Models the state of the lock-screen bouncer */
|
||||||
|
data class KeyguardBouncerModel(
|
||||||
|
val promptReason: Int = 0,
|
||||||
|
val errorMessage: CharSequence? = null,
|
||||||
|
val expansionAmount: Float = 0f,
|
||||||
|
)
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* 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.ui.binder
|
||||||
|
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import com.android.internal.policy.SystemBarUtils
|
||||||
|
import com.android.keyguard.KeyguardHostViewController
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
|
import com.android.keyguard.dagger.KeyguardBouncerComponent
|
||||||
|
import com.android.systemui.keyguard.data.BouncerViewDelegate
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
||||||
|
import com.android.systemui.lifecycle.repeatWhenAttached
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_VISIBLE
|
||||||
|
import kotlinx.coroutines.awaitCancellation
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
/** Binds the bouncer container to its view model. */
|
||||||
|
object KeyguardBouncerViewBinder {
|
||||||
|
@JvmStatic
|
||||||
|
fun bind(
|
||||||
|
view: ViewGroup,
|
||||||
|
viewModel: KeyguardBouncerViewModel,
|
||||||
|
componentFactory: KeyguardBouncerComponent.Factory
|
||||||
|
) {
|
||||||
|
// Builds the KeyguardHostViewController from bouncer view group.
|
||||||
|
val hostViewController: KeyguardHostViewController =
|
||||||
|
componentFactory.create(view).keyguardHostViewController
|
||||||
|
hostViewController.init()
|
||||||
|
val delegate =
|
||||||
|
object : BouncerViewDelegate {
|
||||||
|
override fun isFullScreenBouncer(): Boolean {
|
||||||
|
val mode = hostViewController.currentSecurityMode
|
||||||
|
return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
|
||||||
|
mode == KeyguardSecurityModel.SecurityMode.SimPuk
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldDismissOnMenuPressed(): Boolean {
|
||||||
|
return hostViewController.shouldEnableMenuKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun interceptMediaKey(event: KeyEvent?): Boolean {
|
||||||
|
return hostViewController.interceptMediaKey(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispatchBackKeyEventPreIme(): Boolean {
|
||||||
|
return hostViewController.dispatchBackKeyEventPreIme()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showNextSecurityScreenOrFinish(): Boolean {
|
||||||
|
return hostViewController.dismiss(KeyguardUpdateMonitor.getCurrentUser())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resume() {
|
||||||
|
hostViewController.showPrimarySecurityScreen()
|
||||||
|
hostViewController.onResume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.repeatWhenAttached {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
|
try {
|
||||||
|
viewModel.setBouncerViewDelegate(delegate)
|
||||||
|
launch {
|
||||||
|
viewModel.show.collect {
|
||||||
|
hostViewController.showPrimarySecurityScreen()
|
||||||
|
hostViewController.appear(
|
||||||
|
SystemBarUtils.getStatusBarHeight(view.context)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.showPromptReason.collect { prompt ->
|
||||||
|
hostViewController.showPromptReason(prompt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.showBouncerErrorMessage.collect { errorMessage ->
|
||||||
|
hostViewController.showErrorMessage(errorMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.showWithFullExpansion.collect { model ->
|
||||||
|
hostViewController.resetSecurityContainer()
|
||||||
|
hostViewController.showPromptReason(model.promptReason)
|
||||||
|
hostViewController.onResume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.hide.collect {
|
||||||
|
hostViewController.cancelDismissAction()
|
||||||
|
hostViewController.cleanUp()
|
||||||
|
hostViewController.resetSecurityContainer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.startingToHide.collect { hostViewController.onStartingToHide() }
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.setDismissAction.collect {
|
||||||
|
hostViewController.setOnDismissAction(
|
||||||
|
it.onDismissAction,
|
||||||
|
it.cancelAction
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.startDisappearAnimation.collect {
|
||||||
|
hostViewController.startDisappearAnimation(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.bouncerExpansionAmount.collect { expansion ->
|
||||||
|
hostViewController.setExpansion(expansion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.bouncerExpansionAmount
|
||||||
|
.filter { it == EXPANSION_VISIBLE }
|
||||||
|
.collect {
|
||||||
|
hostViewController.onResume()
|
||||||
|
view.announceForAccessibility(
|
||||||
|
hostViewController.accessibilityTitleForCurrentMode
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.isBouncerVisible.collect { isVisible ->
|
||||||
|
val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
|
||||||
|
view.visibility = visibility
|
||||||
|
hostViewController.onBouncerVisibilityChanged(visibility)
|
||||||
|
viewModel.notifyBouncerVisibilityHasChanged(visibility)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.isBouncerVisible
|
||||||
|
.filter { !it }
|
||||||
|
.collect {
|
||||||
|
// Remove existing input for security reasons.
|
||||||
|
hostViewController.resetSecurityContainer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.keyguardPosition.collect { position ->
|
||||||
|
hostViewController.updateKeyguardPosition(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.updateResources.collect {
|
||||||
|
hostViewController.updateResources()
|
||||||
|
viewModel.notifyUpdateResources()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.bouncerShowMessage.collect {
|
||||||
|
hostViewController.showMessage(it.message, it.colorStateList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.keyguardAuthenticated.collect {
|
||||||
|
hostViewController.finish(it, KeyguardUpdateMonitor.getCurrentUser())
|
||||||
|
viewModel.notifyKeyguardAuthenticated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel
|
||||||
|
.observeOnIsBackButtonEnabled { view.systemUiVisibility }
|
||||||
|
.collect { view.systemUiVisibility = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.screenTurnedOff.collect {
|
||||||
|
if (view.visibility == View.VISIBLE) {
|
||||||
|
hostViewController.onPause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
awaitCancellation()
|
||||||
|
} finally {
|
||||||
|
viewModel.setBouncerViewDelegate(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* 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.ui.viewmodel
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.android.systemui.keyguard.data.BouncerView
|
||||||
|
import com.android.systemui.keyguard.data.BouncerViewDelegate
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.BouncerInteractor
|
||||||
|
import com.android.systemui.keyguard.shared.model.BouncerCallbackActionsModel
|
||||||
|
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
|
||||||
|
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_VISIBLE
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
|
/** Models UI state for the lock screen bouncer; handles user input. */
|
||||||
|
class KeyguardBouncerViewModel
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
private val view: BouncerView,
|
||||||
|
private val interactor: BouncerInteractor,
|
||||||
|
) {
|
||||||
|
/** Observe on bouncer expansion amount. */
|
||||||
|
val bouncerExpansionAmount: Flow<Float> = interactor.expansionAmount
|
||||||
|
|
||||||
|
/** Observe on bouncer visibility. */
|
||||||
|
val isBouncerVisible: Flow<Boolean> = interactor.isVisible
|
||||||
|
|
||||||
|
/** Observe whether bouncer is showing. */
|
||||||
|
val show: Flow<KeyguardBouncerModel> = interactor.show
|
||||||
|
|
||||||
|
/** Observe bouncer prompt when bouncer is showing. */
|
||||||
|
val showPromptReason: Flow<Int> = interactor.show.map { it.promptReason }
|
||||||
|
|
||||||
|
/** Observe bouncer error message when bouncer is showing. */
|
||||||
|
val showBouncerErrorMessage: Flow<CharSequence> =
|
||||||
|
interactor.show.map { it.errorMessage }.filterNotNull()
|
||||||
|
|
||||||
|
/** Observe visible expansion when bouncer is showing. */
|
||||||
|
val showWithFullExpansion: Flow<KeyguardBouncerModel> =
|
||||||
|
interactor.show.filter { it.expansionAmount == EXPANSION_VISIBLE }
|
||||||
|
|
||||||
|
/** Observe whether bouncer is hiding. */
|
||||||
|
val hide: Flow<Unit> = interactor.hide
|
||||||
|
|
||||||
|
/** Observe whether bouncer is starting to hide. */
|
||||||
|
val startingToHide: Flow<Unit> = interactor.startingToHide
|
||||||
|
|
||||||
|
/** Observe whether we want to set the dismiss action to the bouncer. */
|
||||||
|
val setDismissAction: Flow<BouncerCallbackActionsModel> = interactor.onDismissAction
|
||||||
|
|
||||||
|
/** Observe whether we want to start the disappear animation. */
|
||||||
|
val startDisappearAnimation: Flow<Runnable> = interactor.startingDisappearAnimation
|
||||||
|
|
||||||
|
/** Observe whether we want to update keyguard position. */
|
||||||
|
val keyguardPosition: Flow<Float> = interactor.keyguardPosition
|
||||||
|
|
||||||
|
/** Observe whether we want to update resources. */
|
||||||
|
val updateResources: Flow<Boolean> = interactor.resourceUpdateRequests
|
||||||
|
|
||||||
|
/** Observe whether we want to set a keyguard message when the bouncer shows. */
|
||||||
|
val bouncerShowMessage: Flow<BouncerShowMessageModel> = interactor.showMessage
|
||||||
|
|
||||||
|
/** Observe whether keyguard is authenticated already. */
|
||||||
|
val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticated
|
||||||
|
|
||||||
|
/** Observe whether screen is turned off. */
|
||||||
|
val screenTurnedOff: Flow<Unit> = interactor.screenTurnedOff
|
||||||
|
|
||||||
|
/** Notify that view visibility has changed. */
|
||||||
|
fun notifyBouncerVisibilityHasChanged(visibility: Int) {
|
||||||
|
return interactor.notifyBouncerVisibilityHasChanged(visibility)
|
||||||
|
}
|
||||||
|
/** Observe whether we want to update resources. */
|
||||||
|
fun notifyUpdateResources() {
|
||||||
|
interactor.notifyUpdatedResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Notify that keyguard authenticated was handled */
|
||||||
|
fun notifyKeyguardAuthenticated() {
|
||||||
|
interactor.notifyKeyguardAuthenticatedHandled()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Observe whether back button is enabled. */
|
||||||
|
fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> {
|
||||||
|
return interactor.isBackButtonEnabled.map { enabled ->
|
||||||
|
var vis: Int = systemUiVisibility()
|
||||||
|
vis =
|
||||||
|
if (enabled) {
|
||||||
|
vis and View.STATUS_BAR_DISABLE_BACK.inv()
|
||||||
|
} else {
|
||||||
|
vis or View.STATUS_BAR_DISABLE_BACK
|
||||||
|
}
|
||||||
|
vis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set an abstraction that will hold reference to the ui delegate for the bouncer view. */
|
||||||
|
fun setBouncerViewDelegate(delegate: BouncerViewDelegate?) {
|
||||||
|
view.delegate = delegate
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,10 +31,15 @@ import android.view.ViewGroup;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.keyguard.AuthKeyguardMessageArea;
|
import com.android.keyguard.AuthKeyguardMessageArea;
|
||||||
import com.android.keyguard.LockIconViewController;
|
import com.android.keyguard.LockIconViewController;
|
||||||
|
import com.android.keyguard.dagger.KeyguardBouncerComponent;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.classifier.FalsingCollector;
|
import com.android.systemui.classifier.FalsingCollector;
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
|
import com.android.systemui.flags.Flags;
|
||||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||||
|
import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
|
||||||
import com.android.systemui.statusbar.DragDownHelper;
|
import com.android.systemui.statusbar.DragDownHelper;
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
@@ -108,7 +113,10 @@ public class NotificationShadeWindowViewController {
|
|||||||
NotificationShadeWindowController controller,
|
NotificationShadeWindowController controller,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||||
AmbientState ambientState,
|
AmbientState ambientState,
|
||||||
PulsingGestureListener pulsingGestureListener
|
PulsingGestureListener pulsingGestureListener,
|
||||||
|
FeatureFlags featureFlags,
|
||||||
|
KeyguardBouncerViewModel keyguardBouncerViewModel,
|
||||||
|
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory
|
||||||
) {
|
) {
|
||||||
mLockscreenShadeTransitionController = transitionController;
|
mLockscreenShadeTransitionController = transitionController;
|
||||||
mFalsingCollector = falsingCollector;
|
mFalsingCollector = falsingCollector;
|
||||||
@@ -130,6 +138,12 @@ public class NotificationShadeWindowViewController {
|
|||||||
|
|
||||||
// This view is not part of the newly inflated expanded status bar.
|
// This view is not part of the newly inflated expanded status bar.
|
||||||
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
|
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
|
||||||
|
if (featureFlags.isEnabled(Flags.MODERN_BOUNCER)) {
|
||||||
|
KeyguardBouncerViewBinder.bind(
|
||||||
|
mView.findViewById(R.id.keyguard_bouncer_container),
|
||||||
|
keyguardBouncerViewModel,
|
||||||
|
keyguardBouncerComponentFactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -56,7 +56,9 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A class which manages the bouncer on the lockscreen.
|
* A class which manages the bouncer on the lockscreen.
|
||||||
|
* @deprecated Use KeyguardBouncerRepository
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class KeyguardBouncer {
|
public class KeyguardBouncer {
|
||||||
|
|
||||||
private static final String TAG = "KeyguardBouncer";
|
private static final String TAG = "KeyguardBouncer";
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import com.android.internal.util.LatencyTracker;
|
|||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
import com.android.keyguard.AuthKeyguardMessageArea;
|
import com.android.keyguard.AuthKeyguardMessageArea;
|
||||||
import com.android.keyguard.KeyguardMessageAreaController;
|
import com.android.keyguard.KeyguardMessageAreaController;
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel;
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||||
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||||
import com.android.keyguard.KeyguardViewController;
|
import com.android.keyguard.KeyguardViewController;
|
||||||
@@ -53,6 +54,12 @@ import com.android.keyguard.ViewMediatorCallback;
|
|||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
import com.android.systemui.dreams.DreamOverlayStateController;
|
import com.android.systemui.dreams.DreamOverlayStateController;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
|
import com.android.systemui.flags.Flags;
|
||||||
|
import com.android.systemui.keyguard.data.BouncerView;
|
||||||
|
import com.android.systemui.keyguard.data.BouncerViewDelegate;
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.BouncerCallbackInteractor;
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.BouncerInteractor;
|
||||||
import com.android.systemui.navigationbar.NavigationBarView;
|
import com.android.systemui.navigationbar.NavigationBarView;
|
||||||
import com.android.systemui.navigationbar.NavigationModeController;
|
import com.android.systemui.navigationbar.NavigationModeController;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
@@ -123,6 +130,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final FoldAodAnimationController mFoldAodAnimationController;
|
private final FoldAodAnimationController mFoldAodAnimationController;
|
||||||
private KeyguardMessageAreaController<AuthKeyguardMessageArea> mKeyguardMessageAreaController;
|
private KeyguardMessageAreaController<AuthKeyguardMessageArea> mKeyguardMessageAreaController;
|
||||||
|
private final BouncerCallbackInteractor mBouncerCallbackInteractor;
|
||||||
|
private final BouncerInteractor mBouncerInteractor;
|
||||||
|
private final BouncerViewDelegate mBouncerViewDelegate;
|
||||||
private final Lazy<com.android.systemui.shade.ShadeController> mShadeController;
|
private final Lazy<com.android.systemui.shade.ShadeController> mShadeController;
|
||||||
|
|
||||||
private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
|
private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
|
||||||
@@ -197,7 +207,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
|
|
||||||
private View mNotificationContainer;
|
private View mNotificationContainer;
|
||||||
|
|
||||||
protected KeyguardBouncer mBouncer;
|
@Nullable protected KeyguardBouncer mBouncer;
|
||||||
protected boolean mShowing;
|
protected boolean mShowing;
|
||||||
protected boolean mOccluded;
|
protected boolean mOccluded;
|
||||||
protected boolean mRemoteInputActive;
|
protected boolean mRemoteInputActive;
|
||||||
@@ -223,6 +233,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
private int mLastBiometricMode;
|
private int mLastBiometricMode;
|
||||||
private boolean mLastScreenOffAnimationPlaying;
|
private boolean mLastScreenOffAnimationPlaying;
|
||||||
private float mQsExpansion;
|
private float mQsExpansion;
|
||||||
|
private boolean mIsModernBouncerEnabled;
|
||||||
|
|
||||||
private OnDismissAction mAfterKeyguardGoneAction;
|
private OnDismissAction mAfterKeyguardGoneAction;
|
||||||
private Runnable mKeyguardGoneCancelAction;
|
private Runnable mKeyguardGoneCancelAction;
|
||||||
@@ -237,6 +248,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
private final DockManager mDockManager;
|
private final DockManager mDockManager;
|
||||||
private final KeyguardUpdateMonitor mKeyguardUpdateManager;
|
private final KeyguardUpdateMonitor mKeyguardUpdateManager;
|
||||||
private final LatencyTracker mLatencyTracker;
|
private final LatencyTracker mLatencyTracker;
|
||||||
|
private final KeyguardSecurityModel mKeyguardSecurityModel;
|
||||||
private KeyguardBypassController mBypassController;
|
private KeyguardBypassController mBypassController;
|
||||||
@Nullable private AlternateAuthInterceptor mAlternateAuthInterceptor;
|
@Nullable private AlternateAuthInterceptor mAlternateAuthInterceptor;
|
||||||
|
|
||||||
@@ -271,7 +283,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
KeyguardMessageAreaController.Factory keyguardMessageAreaFactory,
|
KeyguardMessageAreaController.Factory keyguardMessageAreaFactory,
|
||||||
Optional<SysUIUnfoldComponent> sysUIUnfoldComponent,
|
Optional<SysUIUnfoldComponent> sysUIUnfoldComponent,
|
||||||
Lazy<ShadeController> shadeController,
|
Lazy<ShadeController> shadeController,
|
||||||
LatencyTracker latencyTracker) {
|
LatencyTracker latencyTracker,
|
||||||
|
KeyguardSecurityModel keyguardSecurityModel,
|
||||||
|
FeatureFlags featureFlags,
|
||||||
|
BouncerCallbackInteractor bouncerCallbackInteractor,
|
||||||
|
BouncerInteractor bouncerInteractor,
|
||||||
|
BouncerView bouncerView) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mViewMediatorCallback = callback;
|
mViewMediatorCallback = callback;
|
||||||
mLockPatternUtils = lockPatternUtils;
|
mLockPatternUtils = lockPatternUtils;
|
||||||
@@ -288,8 +305,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
mKeyguardMessageAreaFactory = keyguardMessageAreaFactory;
|
mKeyguardMessageAreaFactory = keyguardMessageAreaFactory;
|
||||||
mShadeController = shadeController;
|
mShadeController = shadeController;
|
||||||
mLatencyTracker = latencyTracker;
|
mLatencyTracker = latencyTracker;
|
||||||
|
mKeyguardSecurityModel = keyguardSecurityModel;
|
||||||
|
mBouncerCallbackInteractor = bouncerCallbackInteractor;
|
||||||
|
mBouncerInteractor = bouncerInteractor;
|
||||||
|
mBouncerViewDelegate = bouncerView.getDelegate();
|
||||||
mFoldAodAnimationController = sysUIUnfoldComponent
|
mFoldAodAnimationController = sysUIUnfoldComponent
|
||||||
.map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
|
.map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
|
||||||
|
mIsModernBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_BOUNCER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -303,7 +325,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
mBiometricUnlockController = biometricUnlockController;
|
mBiometricUnlockController = biometricUnlockController;
|
||||||
|
|
||||||
ViewGroup container = mCentralSurfaces.getBouncerContainer();
|
ViewGroup container = mCentralSurfaces.getBouncerContainer();
|
||||||
mBouncer = mKeyguardBouncerFactory.create(container, mExpansionCallback);
|
if (mIsModernBouncerEnabled) {
|
||||||
|
mBouncerCallbackInteractor.addBouncerExpansionCallback(mExpansionCallback);
|
||||||
|
} else {
|
||||||
|
mBouncer = mKeyguardBouncerFactory.create(container, mExpansionCallback);
|
||||||
|
}
|
||||||
mNotificationPanelViewController = notificationPanelViewController;
|
mNotificationPanelViewController = notificationPanelViewController;
|
||||||
if (panelExpansionStateManager != null) {
|
if (panelExpansionStateManager != null) {
|
||||||
panelExpansionStateManager.addExpansionListener(this);
|
panelExpansionStateManager.addExpansionListener(this);
|
||||||
@@ -377,29 +403,45 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
if (mDozing && !mPulsing) {
|
if (mDozing && !mPulsing) {
|
||||||
return;
|
return;
|
||||||
} else if (mNotificationPanelViewController.isUnlockHintRunning()) {
|
} else if (mNotificationPanelViewController.isUnlockHintRunning()) {
|
||||||
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
|
||||||
} else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) {
|
} else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) {
|
||||||
// Don't expand to the bouncer. Instead transition back to the lock screen (see
|
// Don't expand to the bouncer. Instead transition back to the lock screen (see
|
||||||
// CentralSurfaces#showBouncerOrLockScreenIfKeyguard)
|
// CentralSurfaces#showBouncerOrLockScreenIfKeyguard)
|
||||||
return;
|
return;
|
||||||
} else if (bouncerNeedsScrimming()) {
|
} else if (bouncerNeedsScrimming()) {
|
||||||
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
|
||||||
} else if (mShowing && !hideBouncerOverDream) {
|
} else if (mShowing && !hideBouncerOverDream) {
|
||||||
if (!isWakeAndUnlocking()
|
if (!isWakeAndUnlocking()
|
||||||
&& !(mBiometricUnlockController.getMode() == MODE_DISMISS_BOUNCER)
|
&& !(mBiometricUnlockController.getMode() == MODE_DISMISS_BOUNCER)
|
||||||
&& !mCentralSurfaces.isInLaunchTransition()
|
&& !mCentralSurfaces.isInLaunchTransition()
|
||||||
&& !isUnlockCollapsing()) {
|
&& !isUnlockCollapsing()) {
|
||||||
mBouncer.setExpansion(fraction);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.setExpansion(fraction);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.setExpansion(fraction);
|
||||||
}
|
}
|
||||||
if (fraction != KeyguardBouncer.EXPANSION_HIDDEN && tracking
|
if (fraction != KeyguardBouncer.EXPANSION_HIDDEN && tracking
|
||||||
&& !mKeyguardStateController.canDismissLockScreen()
|
&& !mKeyguardStateController.canDismissLockScreen()
|
||||||
&& !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
|
&& !bouncerIsShowing()
|
||||||
mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
|
&& !bouncerIsAnimatingAway()) {
|
||||||
|
if (mBouncer != null) {
|
||||||
|
mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.show(/* isScrimmed= */false);
|
||||||
}
|
}
|
||||||
} else if (!mShowing && mBouncer.inTransit()) {
|
} else if (!mShowing && isBouncerInTransit()) {
|
||||||
// Keyguard is not visible anymore, but expansion animation was still running.
|
// Keyguard is not visible anymore, but expansion animation was still running.
|
||||||
// We need to hide the bouncer, otherwise it will be stuck in transit.
|
// We need to hide the bouncer, otherwise it will be stuck in transit.
|
||||||
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
|
||||||
} else if (mPulsing && fraction == KeyguardBouncer.EXPANSION_VISIBLE) {
|
} else if (mPulsing && fraction == KeyguardBouncer.EXPANSION_VISIBLE) {
|
||||||
// Panel expanded while pulsing but didn't translate the bouncer (because we are
|
// Panel expanded while pulsing but didn't translate the bouncer (because we are
|
||||||
// unlocked.) Let's simply wake-up to dismiss the lock screen.
|
// unlocked.) Let's simply wake-up to dismiss the lock screen.
|
||||||
@@ -440,15 +482,20 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
* {@link KeyguardBouncer#needsFullscreenBouncer()}.
|
* {@link KeyguardBouncer#needsFullscreenBouncer()}.
|
||||||
*/
|
*/
|
||||||
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
|
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
|
||||||
if (mBouncer.needsFullscreenBouncer() && !mDozing) {
|
if (needsFullscreenBouncer() && !mDozing) {
|
||||||
// The keyguard might be showing (already). So we need to hide it.
|
// The keyguard might be showing (already). So we need to hide it.
|
||||||
mCentralSurfaces.hideKeyguard();
|
mCentralSurfaces.hideKeyguard();
|
||||||
mBouncer.show(true /* resetSecuritySelection */);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.show(true /* resetSecuritySelection */);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.show(true);
|
||||||
} else {
|
} else {
|
||||||
mCentralSurfaces.showKeyguard();
|
mCentralSurfaces.showKeyguard();
|
||||||
if (hideBouncerWhenShowing) {
|
if (hideBouncerWhenShowing) {
|
||||||
hideBouncer(false /* destroyView */);
|
hideBouncer(false /* destroyView */);
|
||||||
mBouncer.prepare();
|
if (mBouncer != null) {
|
||||||
|
mBouncer.prepare();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateStates();
|
updateStates();
|
||||||
@@ -480,10 +527,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void hideBouncer(boolean destroyView) {
|
void hideBouncer(boolean destroyView) {
|
||||||
if (mBouncer == null) {
|
if (mBouncer != null) {
|
||||||
return;
|
mBouncer.hide(destroyView);
|
||||||
}
|
}
|
||||||
mBouncer.hide(destroyView);
|
mBouncerInteractor.hide();
|
||||||
if (mShowing) {
|
if (mShowing) {
|
||||||
// If we were showing the bouncer and then aborting, we need to also clear out any
|
// If we were showing the bouncer and then aborting, we need to also clear out any
|
||||||
// potential actions unless we actually unlocked.
|
// potential actions unless we actually unlocked.
|
||||||
@@ -501,8 +548,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
public void showBouncer(boolean scrimmed) {
|
public void showBouncer(boolean scrimmed) {
|
||||||
resetAlternateAuth(false);
|
resetAlternateAuth(false);
|
||||||
|
|
||||||
if (mShowing && !mBouncer.isShowing()) {
|
if (mShowing && !isBouncerShowing()) {
|
||||||
mBouncer.show(false /* resetSecuritySelection */, scrimmed);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.show(false /* resetSecuritySelection */, scrimmed);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.show(scrimmed);
|
||||||
}
|
}
|
||||||
updateStates();
|
updateStates();
|
||||||
}
|
}
|
||||||
@@ -535,7 +585,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
// instead of the bouncer.
|
// instead of the bouncer.
|
||||||
if (shouldShowAltAuth()) {
|
if (shouldShowAltAuth()) {
|
||||||
if (!afterKeyguardGone) {
|
if (!afterKeyguardGone) {
|
||||||
mBouncer.setDismissAction(mAfterKeyguardGoneAction,
|
if (mBouncer != null) {
|
||||||
|
mBouncer.setDismissAction(mAfterKeyguardGoneAction,
|
||||||
|
mKeyguardGoneCancelAction);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.setDismissAction(mAfterKeyguardGoneAction,
|
||||||
mKeyguardGoneCancelAction);
|
mKeyguardGoneCancelAction);
|
||||||
mAfterKeyguardGoneAction = null;
|
mAfterKeyguardGoneAction = null;
|
||||||
mKeyguardGoneCancelAction = null;
|
mKeyguardGoneCancelAction = null;
|
||||||
@@ -549,12 +603,18 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
if (afterKeyguardGone) {
|
if (afterKeyguardGone) {
|
||||||
// we'll handle the dismiss action after keyguard is gone, so just show the
|
// we'll handle the dismiss action after keyguard is gone, so just show the
|
||||||
// bouncer
|
// bouncer
|
||||||
mBouncer.show(false /* resetSecuritySelection */);
|
mBouncerInteractor.show(/* isScrimmed= */true);
|
||||||
|
if (mBouncer != null) mBouncer.show(false /* resetSecuritySelection */);
|
||||||
} else {
|
} else {
|
||||||
// after authentication success, run dismiss action with the option to defer
|
// after authentication success, run dismiss action with the option to defer
|
||||||
// hiding the keyguard based on the return value of the OnDismissAction
|
// hiding the keyguard based on the return value of the OnDismissAction
|
||||||
mBouncer.showWithDismissAction(mAfterKeyguardGoneAction,
|
mBouncerInteractor.setDismissAction(
|
||||||
mKeyguardGoneCancelAction);
|
mAfterKeyguardGoneAction, mKeyguardGoneCancelAction);
|
||||||
|
mBouncerInteractor.show(/* isScrimmed= */true);
|
||||||
|
if (mBouncer != null) {
|
||||||
|
mBouncer.showWithDismissAction(mAfterKeyguardGoneAction,
|
||||||
|
mKeyguardGoneCancelAction);
|
||||||
|
}
|
||||||
// bouncer will handle the dismiss action, so we no longer need to track it here
|
// bouncer will handle the dismiss action, so we no longer need to track it here
|
||||||
mAfterKeyguardGoneAction = null;
|
mAfterKeyguardGoneAction = null;
|
||||||
mKeyguardGoneCancelAction = null;
|
mKeyguardGoneCancelAction = null;
|
||||||
@@ -591,7 +651,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
// Hide bouncer and quick-quick settings.
|
// Hide bouncer and quick-quick settings.
|
||||||
if (mOccluded && !mDozing) {
|
if (mOccluded && !mDozing) {
|
||||||
mCentralSurfaces.hideKeyguard();
|
mCentralSurfaces.hideKeyguard();
|
||||||
if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
|
if (hideBouncerWhenShowing || needsFullscreenBouncer()) {
|
||||||
hideBouncer(false /* destroyView */);
|
hideBouncer(false /* destroyView */);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -655,7 +715,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinishedGoingToSleep() {
|
public void onFinishedGoingToSleep() {
|
||||||
mBouncer.onScreenTurnedOff();
|
if (mBouncer != null) {
|
||||||
|
mBouncer.onScreenTurnedOff();
|
||||||
|
}
|
||||||
|
mBouncerInteractor.onScreenTurnedOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -746,7 +809,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
// by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
|
// by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
|
||||||
reset(isOccluding /* hideBouncerWhenShowing*/);
|
reset(isOccluding /* hideBouncerWhenShowing*/);
|
||||||
}
|
}
|
||||||
if (animate && !mOccluded && mShowing && !mBouncer.isShowing()) {
|
if (animate && !mOccluded && mShowing && !bouncerIsShowing()) {
|
||||||
mCentralSurfaces.animateKeyguardUnoccluding();
|
mCentralSurfaces.animateKeyguardUnoccluding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -762,8 +825,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startPreHideAnimation(Runnable finishRunnable) {
|
public void startPreHideAnimation(Runnable finishRunnable) {
|
||||||
if (mBouncer.isShowing()) {
|
if (bouncerIsShowing()) {
|
||||||
mBouncer.startPreHideAnimation(finishRunnable);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.startPreHideAnimation(finishRunnable);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.startDisappearAnimation(finishRunnable);
|
||||||
mCentralSurfaces.onBouncerPreHideAnimation();
|
mCentralSurfaces.onBouncerPreHideAnimation();
|
||||||
|
|
||||||
// We update the state (which will show the keyguard) only if an animation will run on
|
// We update the state (which will show the keyguard) only if an animation will run on
|
||||||
@@ -873,8 +939,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onThemeChanged() {
|
public void onThemeChanged() {
|
||||||
boolean wasShowing = mBouncer.isShowing();
|
if (mIsModernBouncerEnabled) {
|
||||||
boolean wasScrimmed = mBouncer.isScrimmed();
|
updateResources();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean wasShowing = bouncerIsShowing();
|
||||||
|
boolean wasScrimmed = bouncerIsScrimmed();
|
||||||
|
|
||||||
hideBouncer(true /* destroyView */);
|
hideBouncer(true /* destroyView */);
|
||||||
mBouncer.prepare();
|
mBouncer.prepare();
|
||||||
@@ -924,7 +994,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
* WARNING: This method might cause Binder calls.
|
* WARNING: This method might cause Binder calls.
|
||||||
*/
|
*/
|
||||||
public boolean isSecure() {
|
public boolean isSecure() {
|
||||||
return mBouncer.isSecure();
|
if (mBouncer != null) {
|
||||||
|
return mBouncer.isSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mKeyguardSecurityModel.getSecurityMode(
|
||||||
|
KeyguardUpdateMonitor.getCurrentUser()) != KeyguardSecurityModel.SecurityMode.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -941,10 +1016,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
* @return whether the back press has been handled
|
* @return whether the back press has been handled
|
||||||
*/
|
*/
|
||||||
public boolean onBackPressed(boolean hideImmediately) {
|
public boolean onBackPressed(boolean hideImmediately) {
|
||||||
if (mBouncer.isShowing()) {
|
if (bouncerIsShowing()) {
|
||||||
mCentralSurfaces.endAffordanceLaunch();
|
mCentralSurfaces.endAffordanceLaunch();
|
||||||
// The second condition is for SIM card locked bouncer
|
// The second condition is for SIM card locked bouncer
|
||||||
if (mBouncer.isScrimmed() && !mBouncer.needsFullscreenBouncer()) {
|
if (bouncerIsScrimmed()
|
||||||
|
&& !needsFullscreenBouncer()) {
|
||||||
hideBouncer(false);
|
hideBouncer(false);
|
||||||
updateStates();
|
updateStates();
|
||||||
} else {
|
} else {
|
||||||
@@ -957,16 +1033,19 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBouncerShowing() {
|
public boolean isBouncerShowing() {
|
||||||
return mBouncer.isShowing() || isShowingAlternateAuth();
|
return bouncerIsShowing() || isShowingAlternateAuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean bouncerIsOrWillBeShowing() {
|
public boolean bouncerIsOrWillBeShowing() {
|
||||||
return isBouncerShowing() || mBouncer.inTransit();
|
return isBouncerShowing() || isBouncerInTransit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFullscreenBouncer() {
|
public boolean isFullscreenBouncer() {
|
||||||
return mBouncer.isFullscreenBouncer();
|
if (mBouncerViewDelegate != null) {
|
||||||
|
return mBouncerViewDelegate.isFullScreenBouncer();
|
||||||
|
}
|
||||||
|
return mBouncer != null && mBouncer.isFullscreenBouncer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -987,7 +1066,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
private long getNavBarShowDelay() {
|
private long getNavBarShowDelay() {
|
||||||
if (mKeyguardStateController.isKeyguardFadingAway()) {
|
if (mKeyguardStateController.isKeyguardFadingAway()) {
|
||||||
return mKeyguardStateController.getKeyguardFadingAwayDelay();
|
return mKeyguardStateController.getKeyguardFadingAwayDelay();
|
||||||
} else if (mBouncer.isShowing()) {
|
} else if (isBouncerShowing()) {
|
||||||
return NAV_BAR_SHOW_DELAY_BOUNCER;
|
return NAV_BAR_SHOW_DELAY_BOUNCER;
|
||||||
} else {
|
} else {
|
||||||
// No longer dozing, or remote input is active. No delay.
|
// No longer dozing, or remote input is active. No delay.
|
||||||
@@ -1010,18 +1089,24 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
protected void updateStates() {
|
protected void updateStates() {
|
||||||
boolean showing = mShowing;
|
boolean showing = mShowing;
|
||||||
boolean occluded = mOccluded;
|
boolean occluded = mOccluded;
|
||||||
boolean bouncerShowing = mBouncer.isShowing();
|
boolean bouncerShowing = bouncerIsShowing();
|
||||||
boolean bouncerIsOrWillBeShowing = bouncerIsOrWillBeShowing();
|
boolean bouncerIsOrWillBeShowing = bouncerIsOrWillBeShowing();
|
||||||
boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
|
boolean bouncerDismissible = !isFullscreenBouncer();
|
||||||
boolean remoteInputActive = mRemoteInputActive;
|
boolean remoteInputActive = mRemoteInputActive;
|
||||||
|
|
||||||
if ((bouncerDismissible || !showing || remoteInputActive) !=
|
if ((bouncerDismissible || !showing || remoteInputActive) !=
|
||||||
(mLastBouncerDismissible || !mLastShowing || mLastRemoteInputActive)
|
(mLastBouncerDismissible || !mLastShowing || mLastRemoteInputActive)
|
||||||
|| mFirstUpdate) {
|
|| mFirstUpdate) {
|
||||||
if (bouncerDismissible || !showing || remoteInputActive) {
|
if (bouncerDismissible || !showing || remoteInputActive) {
|
||||||
mBouncer.setBackButtonEnabled(true);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.setBackButtonEnabled(true);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.setBackButtonEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
mBouncer.setBackButtonEnabled(false);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.setBackButtonEnabled(false);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.setBackButtonEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1098,7 +1183,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
|| mPulsing && !mIsDocked)
|
|| mPulsing && !mIsDocked)
|
||||||
&& mGesturalNav;
|
&& mGesturalNav;
|
||||||
return (!keyguardShowing && !hideWhileDozing && !mScreenOffAnimationPlaying
|
return (!keyguardShowing && !hideWhileDozing && !mScreenOffAnimationPlaying
|
||||||
|| mBouncer.isShowing() || mRemoteInputActive || keyguardWithGestureNav
|
|| bouncerIsShowing()
|
||||||
|
|| mRemoteInputActive
|
||||||
|
|| keyguardWithGestureNav
|
||||||
|| mGlobalActionsVisible);
|
|| mGlobalActionsVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1117,18 +1204,27 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldDismissOnMenuPressed() {
|
public boolean shouldDismissOnMenuPressed() {
|
||||||
return mBouncer.shouldDismissOnMenuPressed();
|
if (mBouncerViewDelegate != null) {
|
||||||
|
return mBouncerViewDelegate.shouldDismissOnMenuPressed();
|
||||||
|
}
|
||||||
|
return mBouncer != null && mBouncer.shouldDismissOnMenuPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean interceptMediaKey(KeyEvent event) {
|
public boolean interceptMediaKey(KeyEvent event) {
|
||||||
return mBouncer.interceptMediaKey(event);
|
if (mBouncerViewDelegate != null) {
|
||||||
|
return mBouncerViewDelegate.interceptMediaKey(event);
|
||||||
|
}
|
||||||
|
return mBouncer != null && mBouncer.interceptMediaKey(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the pre IME back event should be handled
|
* @return true if the pre IME back event should be handled
|
||||||
*/
|
*/
|
||||||
public boolean dispatchBackKeyEventPreIme() {
|
public boolean dispatchBackKeyEventPreIme() {
|
||||||
return mBouncer.dispatchBackKeyEventPreIme();
|
if (mBouncerViewDelegate != null) {
|
||||||
|
return mBouncerViewDelegate.dispatchBackKeyEventPreIme();
|
||||||
|
}
|
||||||
|
return mBouncer != null && mBouncer.dispatchBackKeyEventPreIme();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readyForKeyguardDone() {
|
public void readyForKeyguardDone() {
|
||||||
@@ -1151,7 +1247,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSecure(int userId) {
|
public boolean isSecure(int userId) {
|
||||||
return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);
|
return isSecure() || mLockPatternUtils.isSecure(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1174,7 +1270,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
* fingerprint.
|
* fingerprint.
|
||||||
*/
|
*/
|
||||||
public void notifyKeyguardAuthenticated(boolean strongAuth) {
|
public void notifyKeyguardAuthenticated(boolean strongAuth) {
|
||||||
mBouncer.notifyKeyguardAuthenticated(strongAuth);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.notifyKeyguardAuthenticated(strongAuth);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.notifyKeyguardAuthenticated(strongAuth);
|
||||||
|
|
||||||
if (mAlternateAuthInterceptor != null && isShowingAlternateAuthOrAnimating()) {
|
if (mAlternateAuthInterceptor != null && isShowingAlternateAuthOrAnimating()) {
|
||||||
resetAlternateAuth(false);
|
resetAlternateAuth(false);
|
||||||
@@ -1189,7 +1288,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
mKeyguardMessageAreaController.setMessage(message);
|
mKeyguardMessageAreaController.setMessage(message);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mBouncer.showMessage(message, colorState);
|
if (mBouncer != null) {
|
||||||
|
mBouncer.showMessage(message, colorState);
|
||||||
|
}
|
||||||
|
mBouncerInteractor.showMessage(message, colorState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1222,9 +1324,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
public boolean bouncerNeedsScrimming() {
|
public boolean bouncerNeedsScrimming() {
|
||||||
// When a dream overlay is active, scrimming will cause any expansion to immediately expand.
|
// When a dream overlay is active, scrimming will cause any expansion to immediately expand.
|
||||||
return (mOccluded && !mDreamOverlayStateController.isOverlayActive())
|
return (mOccluded && !mDreamOverlayStateController.isOverlayActive())
|
||||||
|| mBouncer.willDismissWithAction()
|
|| bouncerWillDismissWithAction()
|
||||||
|| (mBouncer.isShowing() && mBouncer.isScrimmed())
|
|| (bouncerIsShowing()
|
||||||
|| mBouncer.isFullscreenBouncer();
|
&& bouncerIsScrimmed())
|
||||||
|
|| isFullscreenBouncer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1236,6 +1339,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
if (mBouncer != null) {
|
if (mBouncer != null) {
|
||||||
mBouncer.updateResources();
|
mBouncer.updateResources();
|
||||||
}
|
}
|
||||||
|
mBouncerInteractor.updateResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump(PrintWriter pw) {
|
public void dump(PrintWriter pw) {
|
||||||
@@ -1289,6 +1393,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public KeyguardBouncer getBouncer() {
|
public KeyguardBouncer getBouncer() {
|
||||||
return mBouncer;
|
return mBouncer;
|
||||||
}
|
}
|
||||||
@@ -1320,6 +1425,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
if (mBouncer != null) {
|
if (mBouncer != null) {
|
||||||
mBouncer.updateKeyguardPosition(x);
|
mBouncer.updateKeyguardPosition(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBouncerInteractor.setKeyguardPosition(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DismissWithActionRequest {
|
private static class DismissWithActionRequest {
|
||||||
@@ -1359,9 +1466,65 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
|||||||
* Returns if bouncer expansion is between 0 and 1 non-inclusive.
|
* Returns if bouncer expansion is between 0 and 1 non-inclusive.
|
||||||
*/
|
*/
|
||||||
public boolean isBouncerInTransit() {
|
public boolean isBouncerInTransit() {
|
||||||
if (mBouncer == null) return false;
|
if (mBouncer != null) {
|
||||||
|
return mBouncer.inTransit();
|
||||||
|
}
|
||||||
|
|
||||||
return mBouncer.inTransit();
|
return mBouncerInteractor.isInTransit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if bouncer is showing
|
||||||
|
*/
|
||||||
|
public boolean bouncerIsShowing() {
|
||||||
|
if (mBouncer != null) {
|
||||||
|
return mBouncer.isShowing();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mBouncerInteractor.isFullyShowing();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if bouncer is scrimmed
|
||||||
|
*/
|
||||||
|
public boolean bouncerIsScrimmed() {
|
||||||
|
if (mBouncer != null) {
|
||||||
|
return mBouncer.isScrimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mBouncerInteractor.isScrimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if bouncer is animating away
|
||||||
|
*/
|
||||||
|
public boolean bouncerIsAnimatingAway() {
|
||||||
|
if (mBouncer != null) {
|
||||||
|
return mBouncer.isAnimatingAway();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mBouncerInteractor.isAnimatingAway();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if bouncer will dismiss with action
|
||||||
|
*/
|
||||||
|
public boolean bouncerWillDismissWithAction() {
|
||||||
|
if (mBouncer != null) {
|
||||||
|
return mBouncer.willDismissWithAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mBouncerInteractor.willDismissWithAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if bouncer needs fullscreen bouncer. i.e. sim pin security method
|
||||||
|
*/
|
||||||
|
public boolean needsFullscreenBouncer() {
|
||||||
|
KeyguardSecurityModel.SecurityMode mode = mKeyguardSecurityModel.getSecurityMode(
|
||||||
|
KeyguardUpdateMonitor.getCurrentUser());
|
||||||
|
return mode == KeyguardSecurityModel.SecurityMode.SimPin
|
||||||
|
|| mode == KeyguardSecurityModel.SecurityMode.SimPuk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import androidx.test.filters.SmallTest;
|
|||||||
import com.android.keyguard.BouncerPanelExpansionCalculator;
|
import com.android.keyguard.BouncerPanelExpansionCalculator;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.dreams.complication.ComplicationHostViewController;
|
import com.android.systemui.dreams.complication.ComplicationHostViewController;
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.BouncerCallbackInteractor;
|
||||||
import com.android.systemui.statusbar.BlurUtils;
|
import com.android.systemui.statusbar.BlurUtils;
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBouncer;
|
import com.android.systemui.statusbar.phone.KeyguardBouncer;
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
|
import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
|
||||||
@@ -88,6 +89,9 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
ViewRootImpl mViewRoot;
|
ViewRootImpl mViewRoot;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
BouncerCallbackInteractor mBouncerCallbackInteractor;
|
||||||
|
|
||||||
DreamOverlayContainerViewController mController;
|
DreamOverlayContainerViewController mController;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -110,7 +114,8 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
|||||||
mResources,
|
mResources,
|
||||||
MAX_BURN_IN_OFFSET,
|
MAX_BURN_IN_OFFSET,
|
||||||
BURN_IN_PROTECTION_UPDATE_INTERVAL,
|
BURN_IN_PROTECTION_UPDATE_INTERVAL,
|
||||||
MILLIS_UNTIL_FULL_JITTER);
|
MILLIS_UNTIL_FULL_JITTER,
|
||||||
|
mBouncerCallbackInteractor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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.view.View
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBouncer
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.JUnit4
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(JUnit4::class)
|
||||||
|
class BouncerCallbackInteractorTest : SysuiTestCase() {
|
||||||
|
private val bouncerCallbackInteractor = BouncerCallbackInteractor()
|
||||||
|
@Mock private lateinit var bouncerExpansionCallback: KeyguardBouncer.BouncerExpansionCallback
|
||||||
|
@Mock private lateinit var keyguardResetCallback: KeyguardBouncer.KeyguardResetCallback
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
bouncerCallbackInteractor.addBouncerExpansionCallback(bouncerExpansionCallback)
|
||||||
|
bouncerCallbackInteractor.addKeyguardResetCallback(keyguardResetCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnFullyShown() {
|
||||||
|
bouncerCallbackInteractor.dispatchFullyShown()
|
||||||
|
verify(bouncerExpansionCallback).onFullyShown()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnFullyHidden() {
|
||||||
|
bouncerCallbackInteractor.dispatchFullyHidden()
|
||||||
|
verify(bouncerExpansionCallback).onFullyHidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnExpansionChanged() {
|
||||||
|
bouncerCallbackInteractor.dispatchExpansionChanged(5f)
|
||||||
|
verify(bouncerExpansionCallback).onExpansionChanged(5f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnVisibilityChanged() {
|
||||||
|
bouncerCallbackInteractor.dispatchVisibilityChanged(View.INVISIBLE)
|
||||||
|
verify(bouncerExpansionCallback).onVisibilityChanged(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnStartingToHide() {
|
||||||
|
bouncerCallbackInteractor.dispatchStartingToHide()
|
||||||
|
verify(bouncerExpansionCallback).onStartingToHide()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnStartingToShow() {
|
||||||
|
bouncerCallbackInteractor.dispatchStartingToShow()
|
||||||
|
verify(bouncerExpansionCallback).onStartingToShow()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnKeyguardReset() {
|
||||||
|
bouncerCallbackInteractor.dispatchReset()
|
||||||
|
verify(keyguardResetCallback).onKeyguardReset()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,278 @@
|
|||||||
|
/*
|
||||||
|
* 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.os.Looper
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
|
import com.android.systemui.DejankUtils
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.classifier.FalsingCollector
|
||||||
|
import com.android.systemui.keyguard.DismissCallbackRegistry
|
||||||
|
import com.android.systemui.keyguard.data.BouncerView
|
||||||
|
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
|
||||||
|
import com.android.systemui.keyguard.shared.model.BouncerCallbackActionsModel
|
||||||
|
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
|
||||||
|
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
|
||||||
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_HIDDEN
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_VISIBLE
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||||
|
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||||
|
import com.android.systemui.util.mockito.any
|
||||||
|
import com.android.systemui.utils.os.FakeHandler
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Answers
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.mock
|
||||||
|
import org.mockito.Mockito.never
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWithLooper(setAsMainLooper = true)
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
class BouncerInteractorTest : SysuiTestCase() {
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private lateinit var repository: KeyguardBouncerRepository
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var bouncerView: BouncerView
|
||||||
|
@Mock private lateinit var keyguardStateController: KeyguardStateController
|
||||||
|
@Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
|
||||||
|
@Mock private lateinit var bouncerCallbackInteractor: BouncerCallbackInteractor
|
||||||
|
@Mock private lateinit var falsingCollector: FalsingCollector
|
||||||
|
@Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
|
||||||
|
@Mock private lateinit var keyguardBypassController: KeyguardBypassController
|
||||||
|
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||||
|
private val mainHandler = FakeHandler(Looper.getMainLooper())
|
||||||
|
private lateinit var bouncerInteractor: BouncerInteractor
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
DejankUtils.setImmediate(true)
|
||||||
|
bouncerInteractor =
|
||||||
|
BouncerInteractor(
|
||||||
|
repository,
|
||||||
|
bouncerView,
|
||||||
|
mainHandler,
|
||||||
|
keyguardStateController,
|
||||||
|
keyguardSecurityModel,
|
||||||
|
bouncerCallbackInteractor,
|
||||||
|
falsingCollector,
|
||||||
|
dismissCallbackRegistry,
|
||||||
|
keyguardBypassController,
|
||||||
|
keyguardUpdateMonitor,
|
||||||
|
)
|
||||||
|
`when`(repository.startingDisappearAnimation.value).thenReturn(null)
|
||||||
|
`when`(repository.show.value).thenReturn(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testShow_isScrimmed() {
|
||||||
|
bouncerInteractor.show(true)
|
||||||
|
verify(repository).setShowMessage(null)
|
||||||
|
verify(repository).setOnScreenTurnedOff(false)
|
||||||
|
verify(repository).setKeyguardAuthenticated(null)
|
||||||
|
verify(repository).setHide(false)
|
||||||
|
verify(repository).setStartingToHide(false)
|
||||||
|
verify(repository).setScrimmed(true)
|
||||||
|
verify(repository).setExpansion(EXPANSION_VISIBLE)
|
||||||
|
verify(repository).setShowingSoon(true)
|
||||||
|
verify(keyguardStateController).notifyBouncerShowing(true)
|
||||||
|
verify(bouncerCallbackInteractor).dispatchStartingToShow()
|
||||||
|
verify(repository).setVisible(true)
|
||||||
|
verify(repository).setShow(any(KeyguardBouncerModel::class.java))
|
||||||
|
verify(repository).setShowingSoon(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testShow_isNotScrimmed() {
|
||||||
|
verify(repository, never()).setExpansion(EXPANSION_VISIBLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testShow_keyguardIsDone() {
|
||||||
|
`when`(bouncerView.delegate?.showNextSecurityScreenOrFinish()).thenReturn(true)
|
||||||
|
verify(keyguardStateController, never()).notifyBouncerShowing(true)
|
||||||
|
verify(bouncerCallbackInteractor, never()).dispatchStartingToShow()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHide() {
|
||||||
|
bouncerInteractor.hide()
|
||||||
|
verify(falsingCollector).onBouncerHidden()
|
||||||
|
verify(keyguardStateController).notifyBouncerShowing(false)
|
||||||
|
verify(repository).setShowingSoon(false)
|
||||||
|
verify(repository).setOnDismissAction(null)
|
||||||
|
verify(repository).setVisible(false)
|
||||||
|
verify(repository).setHide(true)
|
||||||
|
verify(repository).setShow(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testExpansion() {
|
||||||
|
`when`(repository.expansionAmount.value).thenReturn(0.5f)
|
||||||
|
bouncerInteractor.setExpansion(0.6f)
|
||||||
|
verify(repository).setExpansion(0.6f)
|
||||||
|
verify(bouncerCallbackInteractor).dispatchExpansionChanged(0.6f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testExpansion_fullyShown() {
|
||||||
|
`when`(repository.expansionAmount.value).thenReturn(0.5f)
|
||||||
|
`when`(repository.startingDisappearAnimation.value).thenReturn(null)
|
||||||
|
bouncerInteractor.setExpansion(EXPANSION_VISIBLE)
|
||||||
|
verify(falsingCollector).onBouncerShown()
|
||||||
|
verify(bouncerCallbackInteractor).dispatchFullyShown()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testExpansion_fullyHidden() {
|
||||||
|
`when`(repository.expansionAmount.value).thenReturn(0.5f)
|
||||||
|
`when`(repository.startingDisappearAnimation.value).thenReturn(null)
|
||||||
|
bouncerInteractor.setExpansion(EXPANSION_HIDDEN)
|
||||||
|
verify(repository).setVisible(false)
|
||||||
|
verify(repository).setShow(null)
|
||||||
|
verify(falsingCollector).onBouncerHidden()
|
||||||
|
verify(bouncerCallbackInteractor).dispatchReset()
|
||||||
|
verify(bouncerCallbackInteractor).dispatchFullyHidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testExpansion_startingToHide() {
|
||||||
|
`when`(repository.expansionAmount.value).thenReturn(EXPANSION_VISIBLE)
|
||||||
|
bouncerInteractor.setExpansion(0.1f)
|
||||||
|
verify(repository).setStartingToHide(true)
|
||||||
|
verify(bouncerCallbackInteractor).dispatchStartingToHide()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testShowMessage() {
|
||||||
|
bouncerInteractor.showMessage("abc", null)
|
||||||
|
verify(repository).setShowMessage(BouncerShowMessageModel("abc", null))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDismissAction() {
|
||||||
|
val onDismissAction = mock(ActivityStarter.OnDismissAction::class.java)
|
||||||
|
val cancelAction = mock(Runnable::class.java)
|
||||||
|
bouncerInteractor.setDismissAction(onDismissAction, cancelAction)
|
||||||
|
verify(repository)
|
||||||
|
.setOnDismissAction(BouncerCallbackActionsModel(onDismissAction, cancelAction))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUpdateResources() {
|
||||||
|
bouncerInteractor.updateResources()
|
||||||
|
verify(repository).setResourceUpdateRequests(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNotifyKeyguardAuthenticated() {
|
||||||
|
bouncerInteractor.notifyKeyguardAuthenticated(true)
|
||||||
|
verify(repository).setKeyguardAuthenticated(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnScreenTurnedOff() {
|
||||||
|
bouncerInteractor.onScreenTurnedOff()
|
||||||
|
verify(repository).setOnScreenTurnedOff(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSetKeyguardPosition() {
|
||||||
|
bouncerInteractor.setKeyguardPosition(0f)
|
||||||
|
verify(repository).setKeyguardPosition(0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNotifyKeyguardAuthenticatedHandled() {
|
||||||
|
bouncerInteractor.notifyKeyguardAuthenticatedHandled()
|
||||||
|
verify(repository).setKeyguardAuthenticated(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNotifyUpdatedResources() {
|
||||||
|
bouncerInteractor.notifyUpdatedResources()
|
||||||
|
verify(repository).setResourceUpdateRequests(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSetBackButtonEnabled() {
|
||||||
|
bouncerInteractor.setBackButtonEnabled(true)
|
||||||
|
verify(repository).setIsBackButtonEnabled(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testStartDisappearAnimation() {
|
||||||
|
val runnable = mock(Runnable::class.java)
|
||||||
|
bouncerInteractor.startDisappearAnimation(runnable)
|
||||||
|
verify(repository).setStartDisappearAnimation(any(Runnable::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIsFullShowing() {
|
||||||
|
`when`(repository.isVisible.value).thenReturn(true)
|
||||||
|
`when`(repository.expansionAmount.value).thenReturn(EXPANSION_VISIBLE)
|
||||||
|
`when`(repository.startingDisappearAnimation.value).thenReturn(null)
|
||||||
|
assertThat(bouncerInteractor.isFullyShowing()).isTrue()
|
||||||
|
`when`(repository.isVisible.value).thenReturn(false)
|
||||||
|
assertThat(bouncerInteractor.isFullyShowing()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIsScrimmed() {
|
||||||
|
`when`(repository.isScrimmed.value).thenReturn(true)
|
||||||
|
assertThat(bouncerInteractor.isScrimmed()).isTrue()
|
||||||
|
`when`(repository.isScrimmed.value).thenReturn(false)
|
||||||
|
assertThat(bouncerInteractor.isScrimmed()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIsInTransit() {
|
||||||
|
`when`(repository.showingSoon.value).thenReturn(true)
|
||||||
|
assertThat(bouncerInteractor.isInTransit()).isTrue()
|
||||||
|
`when`(repository.showingSoon.value).thenReturn(false)
|
||||||
|
assertThat(bouncerInteractor.isInTransit()).isFalse()
|
||||||
|
`when`(repository.expansionAmount.value).thenReturn(0.5f)
|
||||||
|
assertThat(bouncerInteractor.isInTransit()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIsAnimatingAway() {
|
||||||
|
`when`(repository.startingDisappearAnimation.value).thenReturn(Runnable {})
|
||||||
|
assertThat(bouncerInteractor.isAnimatingAway()).isTrue()
|
||||||
|
`when`(repository.startingDisappearAnimation.value).thenReturn(null)
|
||||||
|
assertThat(bouncerInteractor.isAnimatingAway()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testWillDismissWithAction() {
|
||||||
|
`when`(repository.onDismissAction.value?.onDismissAction)
|
||||||
|
.thenReturn(mock(ActivityStarter.OnDismissAction::class.java))
|
||||||
|
assertThat(bouncerInteractor.willDismissWithAction()).isTrue()
|
||||||
|
`when`(repository.onDismissAction.value?.onDismissAction).thenReturn(null)
|
||||||
|
assertThat(bouncerInteractor.willDismissWithAction()).isFalse()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,12 +21,16 @@ import android.testing.TestableLooper.RunWithLooper
|
|||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.keyguard.KeyguardHostViewController
|
||||||
import com.android.keyguard.LockIconViewController
|
import com.android.keyguard.LockIconViewController
|
||||||
|
import com.android.keyguard.dagger.KeyguardBouncerComponent
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.classifier.FalsingCollectorFake
|
import com.android.systemui.classifier.FalsingCollectorFake
|
||||||
import com.android.systemui.dock.DockManager
|
import com.android.systemui.dock.DockManager
|
||||||
|
import com.android.systemui.flags.FeatureFlags
|
||||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
|
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
||||||
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
|
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController
|
import com.android.systemui.statusbar.NotificationShadeDepthController
|
||||||
@@ -51,9 +55,9 @@ import org.mockito.Mockito.verify
|
|||||||
import org.mockito.Mockito.`when` as whenever
|
import org.mockito.Mockito.`when` as whenever
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@RunWithLooper(setAsMainLooper = true)
|
@RunWithLooper(setAsMainLooper = true)
|
||||||
@SmallTest
|
|
||||||
class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var view: NotificationShadeWindowView
|
private lateinit var view: NotificationShadeWindowView
|
||||||
@@ -72,8 +76,12 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
|
private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
|
||||||
@Mock
|
@Mock
|
||||||
|
private lateinit var featureFlags: FeatureFlags
|
||||||
|
@Mock
|
||||||
private lateinit var ambientState: AmbientState
|
private lateinit var ambientState: AmbientState
|
||||||
@Mock
|
@Mock
|
||||||
|
private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
|
||||||
|
@Mock
|
||||||
private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
|
private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
||||||
@@ -87,6 +95,10 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
|
private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var pulsingGestureListener: PulsingGestureListener
|
private lateinit var pulsingGestureListener: PulsingGestureListener
|
||||||
|
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
|
||||||
|
@Mock lateinit var keyguardBouncerContainer: ViewGroup
|
||||||
|
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
|
||||||
|
@Mock lateinit var keyguardHostViewController: KeyguardHostViewController
|
||||||
|
|
||||||
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
||||||
private lateinit var interactionEventHandler: InteractionEventHandler
|
private lateinit var interactionEventHandler: InteractionEventHandler
|
||||||
@@ -97,7 +109,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
whenever(view.bottom).thenReturn(VIEW_BOTTOM)
|
whenever(view.bottom).thenReturn(VIEW_BOTTOM)
|
||||||
|
|
||||||
underTest = NotificationShadeWindowViewController(
|
underTest = NotificationShadeWindowViewController(
|
||||||
lockscreenShadeTransitionController,
|
lockscreenShadeTransitionController,
|
||||||
FalsingCollectorFake(),
|
FalsingCollectorFake(),
|
||||||
@@ -115,7 +126,10 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
notificationShadeWindowController,
|
notificationShadeWindowController,
|
||||||
keyguardUnlockAnimationController,
|
keyguardUnlockAnimationController,
|
||||||
ambientState,
|
ambientState,
|
||||||
pulsingGestureListener
|
pulsingGestureListener,
|
||||||
|
featureFlags,
|
||||||
|
keyguardBouncerViewModel,
|
||||||
|
keyguardBouncerComponentFactory
|
||||||
)
|
)
|
||||||
underTest.setupExpandedStatusBar()
|
underTest.setupExpandedStatusBar()
|
||||||
|
|
||||||
|
|||||||
@@ -33,11 +33,14 @@ import android.view.MotionEvent;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.keyguard.LockIconViewController;
|
import com.android.keyguard.LockIconViewController;
|
||||||
|
import com.android.keyguard.dagger.KeyguardBouncerComponent;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.classifier.FalsingCollectorFake;
|
import com.android.systemui.classifier.FalsingCollectorFake;
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
|
||||||
import com.android.systemui.statusbar.DragDownHelper;
|
import com.android.systemui.statusbar.DragDownHelper;
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
@@ -86,6 +89,9 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||||
@Mock private AmbientState mAmbientState;
|
@Mock private AmbientState mAmbientState;
|
||||||
@Mock private PulsingGestureListener mPulsingGestureListener;
|
@Mock private PulsingGestureListener mPulsingGestureListener;
|
||||||
|
@Mock private FeatureFlags mFeatureFlags;
|
||||||
|
@Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
|
||||||
|
@Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
|
||||||
|
|
||||||
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
|
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
|
||||||
mInteractionEventHandlerCaptor;
|
mInteractionEventHandlerCaptor;
|
||||||
@@ -121,7 +127,10 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
mNotificationShadeWindowController,
|
mNotificationShadeWindowController,
|
||||||
mKeyguardUnlockAnimationController,
|
mKeyguardUnlockAnimationController,
|
||||||
mAmbientState,
|
mAmbientState,
|
||||||
mPulsingGestureListener
|
mPulsingGestureListener,
|
||||||
|
mFeatureFlags,
|
||||||
|
mKeyguardBouncerViewModel,
|
||||||
|
mKeyguardBouncerComponentFactory
|
||||||
);
|
);
|
||||||
mController.setupExpandedStatusBar();
|
mController.setupExpandedStatusBar();
|
||||||
mController.setDragDownHelper(mDragDownHelper);
|
mController.setDragDownHelper(mDragDownHelper);
|
||||||
|
|||||||
@@ -41,11 +41,17 @@ import com.android.internal.util.LatencyTracker;
|
|||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
import com.android.keyguard.KeyguardMessageArea;
|
import com.android.keyguard.KeyguardMessageArea;
|
||||||
import com.android.keyguard.KeyguardMessageAreaController;
|
import com.android.keyguard.KeyguardMessageAreaController;
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel;
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||||
import com.android.keyguard.ViewMediatorCallback;
|
import com.android.keyguard.ViewMediatorCallback;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
import com.android.systemui.dreams.DreamOverlayStateController;
|
import com.android.systemui.dreams.DreamOverlayStateController;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
|
import com.android.systemui.keyguard.data.BouncerView;
|
||||||
|
import com.android.systemui.keyguard.data.BouncerViewDelegate;
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.BouncerCallbackInteractor;
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.BouncerInteractor;
|
||||||
import com.android.systemui.navigationbar.NavigationModeController;
|
import com.android.systemui.navigationbar.NavigationModeController;
|
||||||
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
|
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
|
||||||
import com.android.systemui.shade.NotificationPanelViewController;
|
import com.android.systemui.shade.NotificationPanelViewController;
|
||||||
@@ -101,6 +107,13 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
|||||||
@Mock private SysUIUnfoldComponent mSysUiUnfoldComponent;
|
@Mock private SysUIUnfoldComponent mSysUiUnfoldComponent;
|
||||||
@Mock private DreamOverlayStateController mDreamOverlayStateController;
|
@Mock private DreamOverlayStateController mDreamOverlayStateController;
|
||||||
@Mock private LatencyTracker mLatencyTracker;
|
@Mock private LatencyTracker mLatencyTracker;
|
||||||
|
@Mock private FeatureFlags mFeatureFlags;
|
||||||
|
@Mock private KeyguardSecurityModel mKeyguardSecurityModel;
|
||||||
|
@Mock private BouncerCallbackInteractor mBouncerCallbackInteractor;
|
||||||
|
@Mock private BouncerInteractor mBouncerInteractor;
|
||||||
|
@Mock private BouncerView mBouncerView;
|
||||||
|
// @Mock private WeakReference<BouncerViewDelegate> mBouncerViewDelegateWeakReference;
|
||||||
|
@Mock private BouncerViewDelegate mBouncerViewDelegate;
|
||||||
|
|
||||||
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||||
private KeyguardBouncer.BouncerExpansionCallback mBouncerExpansionCallback;
|
private KeyguardBouncer.BouncerExpansionCallback mBouncerExpansionCallback;
|
||||||
@@ -115,6 +128,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
|||||||
when(mContainer.findViewById(anyInt())).thenReturn(mKeyguardMessageArea);
|
when(mContainer.findViewById(anyInt())).thenReturn(mKeyguardMessageArea);
|
||||||
when(mKeyguardMessageAreaFactory.create(any(KeyguardMessageArea.class)))
|
when(mKeyguardMessageAreaFactory.create(any(KeyguardMessageArea.class)))
|
||||||
.thenReturn(mKeyguardMessageAreaController);
|
.thenReturn(mKeyguardMessageAreaController);
|
||||||
|
when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate);
|
||||||
|
|
||||||
mStatusBarKeyguardViewManager =
|
mStatusBarKeyguardViewManager =
|
||||||
new StatusBarKeyguardViewManager(
|
new StatusBarKeyguardViewManager(
|
||||||
getContext(),
|
getContext(),
|
||||||
@@ -133,7 +148,12 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
|||||||
mKeyguardMessageAreaFactory,
|
mKeyguardMessageAreaFactory,
|
||||||
Optional.of(mSysUiUnfoldComponent),
|
Optional.of(mSysUiUnfoldComponent),
|
||||||
() -> mShadeController,
|
() -> mShadeController,
|
||||||
mLatencyTracker);
|
mLatencyTracker,
|
||||||
|
mKeyguardSecurityModel,
|
||||||
|
mFeatureFlags,
|
||||||
|
mBouncerCallbackInteractor,
|
||||||
|
mBouncerInteractor,
|
||||||
|
mBouncerView);
|
||||||
mStatusBarKeyguardViewManager.registerCentralSurfaces(
|
mStatusBarKeyguardViewManager.registerCentralSurfaces(
|
||||||
mCentralSurfaces,
|
mCentralSurfaces,
|
||||||
mNotificationPanelView,
|
mNotificationPanelView,
|
||||||
|
|||||||
Reference in New Issue
Block a user