Merge "DO NOT MERGE Update active unlock triggers take #2" into tm-dev

This commit is contained in:
Beverly Tai
2022-05-03 13:47:36 +00:00
committed by Android (Google) Code Review
10 changed files with 444 additions and 98 deletions

View File

@@ -0,0 +1,147 @@
/*
* 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.keyguard
import android.content.ContentResolver
import android.database.ContentObserver
import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL
import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT
import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE
import com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.util.settings.SecureSettings
import java.io.PrintWriter
import javax.inject.Inject
/**
* Handles active unlock settings changes.
*/
@SysUISingleton
class ActiveUnlockConfig @Inject constructor(
@Main private val handler: Handler,
private val secureSettings: SecureSettings,
private val contentResolver: ContentResolver,
dumpManager: DumpManager
) : Dumpable {
/**
* Indicates the origin for an active unlock request.
*/
enum class ACTIVE_UNLOCK_REQUEST_ORIGIN {
WAKE, UNLOCK_INTENT, BIOMETRIC_FAIL, ASSISTANT
}
private var requestActiveUnlockOnWakeup = false
private var requestActiveUnlockOnUnlockIntent = false
private var requestActiveUnlockOnBioFail = false
private val settingsObserver = object : ContentObserver(handler) {
private val wakeUri: Uri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_WAKE)
private val unlockIntentUri: Uri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_UNLOCK_INTENT)
private val bioFailUri: Uri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)
fun register() {
contentResolver.registerContentObserver(
wakeUri,
false,
this,
UserHandle.USER_ALL)
contentResolver.registerContentObserver(
unlockIntentUri,
false,
this,
UserHandle.USER_ALL)
contentResolver.registerContentObserver(
bioFailUri,
false,
this,
UserHandle.USER_ALL)
onChange(true, ArrayList(), 0, getCurrentUser())
}
override fun onChange(
selfChange: Boolean,
uris: Collection<Uri>,
flags: Int,
userId: Int
) {
if (getCurrentUser() != userId) {
return
}
if (selfChange || uris.contains(wakeUri)) {
requestActiveUnlockOnWakeup = secureSettings.getIntForUser(
ACTIVE_UNLOCK_ON_WAKE, 0, getCurrentUser()) == 1
}
if (selfChange || uris.contains(unlockIntentUri)) {
requestActiveUnlockOnUnlockIntent = secureSettings.getIntForUser(
ACTIVE_UNLOCK_ON_UNLOCK_INTENT, 0, getCurrentUser()) == 1
}
if (selfChange || uris.contains(bioFailUri)) {
requestActiveUnlockOnBioFail = secureSettings.getIntForUser(
ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, 0, getCurrentUser()) == 1
}
}
}
init {
settingsObserver.register()
dumpManager.registerDumpable(this)
}
/**
* Whether to trigger active unlock based on where the request is coming from and
* the current settings.
*/
fun shouldAllowActiveUnlockFromOrigin(requestOrigin: ACTIVE_UNLOCK_REQUEST_ORIGIN): Boolean {
return when (requestOrigin) {
ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE -> requestActiveUnlockOnWakeup
ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT ->
requestActiveUnlockOnUnlockIntent || requestActiveUnlockOnWakeup
ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL ->
requestActiveUnlockOnBioFail || requestActiveUnlockOnUnlockIntent ||
requestActiveUnlockOnWakeup
ACTIVE_UNLOCK_REQUEST_ORIGIN.ASSISTANT -> isActiveUnlockEnabled()
}
}
/**
* If any active unlock triggers are enabled.
*/
fun isActiveUnlockEnabled(): Boolean {
return requestActiveUnlockOnWakeup || requestActiveUnlockOnUnlockIntent ||
requestActiveUnlockOnBioFail
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println(" requestActiveUnlockOnWakeup=$requestActiveUnlockOnWakeup")
pw.println(" requestActiveUnlockOnUnlockIntent=$requestActiveUnlockOnUnlockIntent")
pw.println(" requestActiveUnlockOnBioFail=$requestActiveUnlockOnBioFail")
}
}

View File

@@ -221,10 +221,10 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mKeyguardSecurityCallback.userActivity();
showMessage(null, null);
}
if (mUpdateMonitor.isFaceEnrolled()
&& mUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) {
mUpdateMonitor.requestActiveUnlock("unlock-intent, reason=swipeUpOnBouncer",
true);
if (mUpdateMonitor.isFaceEnrolled()) {
mUpdateMonitor.requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
"swipeUpOnBouncer");
}
}
};

View File

@@ -248,12 +248,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
public final boolean mRequestActiveUnlockOnAssistant;
public final boolean mRequestActiveUnlockOnWakeup;
public final boolean mInitiateActiveUnlockOnWakeup;
public final boolean mRequestActiveUnlockOnUnlockIntent;
public final boolean mRequestActiveUnlockOnBioFail;
private final Context mContext;
private final boolean mIsPrimaryUser;
private final boolean mIsAutomotive;
@@ -340,6 +334,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private final Executor mBackgroundExecutor;
private SensorPrivacyManager mSensorPrivacyManager;
private final ActiveUnlockConfig mActiveUnlockConfig;
/**
* Short delay before restarting fingerprint authentication after a successful try. This should
@@ -441,12 +436,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Assert.isMainThread();
boolean wasTrusted = mUserHasTrust.get(userId, false);
mUserHasTrust.put(userId, enabled);
// If there was no change in trusted state, make sure we are not authenticating.
// TrustManager sends an onTrustChanged whenever a user unlocks keyguard, for
// this reason we need to make sure to not authenticate.
if (wasTrusted == enabled) {
// If there was no change in trusted state or trust granted, make sure we are not
// authenticating. TrustManager sends an onTrustChanged whenever a user unlocks keyguard,
// for this reason we need to make sure to not authenticate.
if (wasTrusted == enabled || enabled) {
updateBiometricListeningState(BIOMETRIC_ACTION_STOP);
} else if (!enabled) {
} else {
updateBiometricListeningState(BIOMETRIC_ACTION_START);
}
@@ -1364,14 +1359,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
cb.onTrustAgentErrorMessage(message);
}
}
}
@VisibleForTesting
void setAssistantVisible(boolean assistantVisible) {
mAssistantVisible = assistantVisible;
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
if (mAssistantVisible && mRequestActiveUnlockOnAssistant) {
requestActiveUnlock("assistant", false);
if (mAssistantVisible) {
requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.ASSISTANT,
"assistant",
false);
}
}
@@ -1518,10 +1517,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@Override
public void onAuthenticationFailed() {
if (mRequestActiveUnlockOnBioFail) {
requestActiveUnlock("biometric-failure, extra=fingerprintFailure",
true);
}
requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
"fingerprintFailure");
handleFingerprintAuthFailed();
}
@@ -1580,14 +1578,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@Override
public void onAuthenticationFailed() {
if (shouldRequestActiveUnlockOnFaceError()) {
String reason =
mKeyguardBypassController.canBypass() ? "bypass"
: mUdfpsBouncerShowing ? "udfpsBouncer" :
mBouncerFullyShown ? "bouncer" : "udfpsFpDown";
requestActiveUnlock("biometric-failure"
+ ", extra=faceFailure-" + reason, true);
}
requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
"faceFailure-" + reason);
handleFaceAuthFailed();
if (mKeyguardBypassController != null) {
@@ -1617,10 +1614,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (mKeyguardBypassController != null) {
mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
}
if (errMsgId == BiometricFaceConstants.FACE_ERROR_TIMEOUT
&& shouldRequestActiveUnlockOnFaceError()) {
requestActiveUnlock("biometric-failure"
+ ", extra=faceError-" + errMsgId, true);
if (errMsgId == BiometricFaceConstants.FACE_ERROR_TIMEOUT) {
requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
"faceError-" + errMsgId);
}
}
@@ -1628,12 +1626,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
public void onAuthenticationAcquired(int acquireInfo) {
handleFaceAcquired(acquireInfo);
}
private boolean shouldRequestActiveUnlockOnFaceError() {
return mRequestActiveUnlockOnBioFail
&& (mKeyguardBypassController.canBypass() || mBouncerFullyShown
|| mUdfpsBouncerShowing || mAuthController.isUdfpsFingerDown());
}
};
@VisibleForTesting
@@ -1749,11 +1741,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
Assert.isMainThread();
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
if (mRequestActiveUnlockOnWakeup) {
requestActiveUnlock("wake-unlock");
} else if (mInitiateActiveUnlockOnWakeup) {
initiateActiveUnlock("wake-initiate");
}
requestActiveUnlock(ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE, "wakingUp");
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1882,7 +1870,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
AuthController authController,
TelephonyListenerManager telephonyListenerManager,
InteractionJankMonitor interactionJankMonitor,
LatencyTracker latencyTracker) {
LatencyTracker latencyTracker,
ActiveUnlockConfig activeUnlockConfiguration) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
mTelephonyListenerManager = telephonyListenerManager;
@@ -1899,18 +1888,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mAuthController = authController;
dumpManager.registerDumpable(getClass().getName(), this);
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
// TODO, b/222459888: add official configurable names to Settings.java
mRequestActiveUnlockOnWakeup = Settings.Global.getInt(
mContext.getContentResolver(), "wake-unlock", 0) == 1;
mInitiateActiveUnlockOnWakeup = Settings.Global.getInt(
mContext.getContentResolver(), "wake-initiate", 1) == 1;
mRequestActiveUnlockOnUnlockIntent = Settings.Global.getInt(
mContext.getContentResolver(), "unlock-intent", 0) == 1;
mRequestActiveUnlockOnBioFail = Settings.Global.getInt(
mContext.getContentResolver(), "bio-fail", 0) == 1;
mRequestActiveUnlockOnAssistant = Settings.Global.getInt(
mContext.getContentResolver(), "assistant", 0) == 1;
mActiveUnlockConfig = activeUnlockConfiguration;
mHandler = new Handler(mainLooper) {
@Override
@@ -2292,11 +2270,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
mAuthInterruptActive = active;
updateFaceListeningState(BIOMETRIC_ACTION_UPDATE);
if (mRequestActiveUnlockOnWakeup) {
requestActiveUnlock("wake-unlock, extra=onReach");
} else if (mInitiateActiveUnlockOnWakeup) {
initiateActiveUnlock("wake-initiate, extra=onReach");
}
requestActiveUnlock(ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE, "onReach");
}
/**
@@ -2348,7 +2322,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
/**
* Initiates active unlock to get the unlock token ready.
*/
public void initiateActiveUnlock(String reason) {
private void initiateActiveUnlock(String reason) {
// If this message exists, FP has already authenticated, so wait until that is handled
if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
return;
@@ -2365,15 +2339,30 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
/**
* Attempts to trigger active unlock from trust agent.
*/
public void requestActiveUnlock(String reason, boolean dismissKeyguard) {
private void requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN requestOrigin,
String reason,
boolean dismissKeyguard
) {
// If this message exists, FP has already authenticated, so wait until that is handled
if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
return;
}
if (shouldTriggerActiveUnlock()) {
final boolean allowRequest =
mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(requestOrigin);
if (requestOrigin == ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE
&& !allowRequest && mActiveUnlockConfig.isActiveUnlockEnabled()) {
// instead of requesting the active unlock, initiate the unlock
initiateActiveUnlock(reason);
return;
}
if (allowRequest && shouldTriggerActiveUnlock()) {
if (DEBUG) {
Log.d("ActiveUnlock", "reportUserRequestedUnlock triggerReason=" + reason
Log.d("ActiveUnlock", "reportUserRequestedUnlock"
+ " origin=" + requestOrigin.name()
+ " reason=" + reason
+ " dismissKeyguard=" + dismissKeyguard);
}
mTrustManager.reportUserRequestedUnlock(KeyguardUpdateMonitor.getCurrentUser(),
@@ -2383,11 +2372,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
/**
* Attempts to trigger active unlock from trust agent.
* Only dismisses the keyguard if only face is enrolled (no FP) and bypass is enabled.
* Only dismisses the keyguard under certain conditions.
*/
public void requestActiveUnlock(String reason) {
requestActiveUnlock(reason, isFaceEnrolled() && !isUdfpsEnrolled()
&& mKeyguardBypassController.getBypassEnabled());
public void requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN requestOrigin,
String extraReason
) {
final boolean canFaceBypass = isFaceEnrolled() && mKeyguardBypassController != null
&& mKeyguardBypassController.canBypass();
requestActiveUnlock(
requestOrigin,
extraReason, canFaceBypass
|| mUdfpsBouncerShowing
|| mBouncerFullyShown
|| mAuthController.isUdfpsFingerDown());
}
/**
@@ -2397,9 +2395,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mUdfpsBouncerShowing = showing;
if (mUdfpsBouncerShowing) {
updateFaceListeningState(BIOMETRIC_ACTION_START);
if (mRequestActiveUnlockOnUnlockIntent) {
requestActiveUnlock("unlock-intent, extra=udfpsBouncer", true);
}
requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
"udfpsBouncer");
}
}
@@ -3233,8 +3231,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
if (wasBouncerFullyShown != mBouncerFullyShown) {
if (mBouncerFullyShown && mRequestActiveUnlockOnUnlockIntent) {
requestActiveUnlock("unlock-intent, reason=bouncerFullyShown", true);
if (mBouncerFullyShown) {
requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
"bouncerFullyShown");
}
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -3771,13 +3771,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
mListenModels.print(pw);
pw.println("Enabled active unlock triggers:");
pw.println(" mRequestActiveUnlockOnWakeup=" + mRequestActiveUnlockOnWakeup);
pw.println(" mInitiateActiveUnlockOnWakeup=" + mInitiateActiveUnlockOnWakeup);
pw.println(" mRequestActiveUnlockOnUnlockIntent=" + mRequestActiveUnlockOnUnlockIntent);
pw.println(" mRequestActiveUnlockOnBiometricFail=" + mRequestActiveUnlockOnBioFail);
pw.println(" mRequestActiveUnlockOnAssistant=" + mRequestActiveUnlockOnAssistant);
if (mIsAutomotive) {
pw.println(" Running on Automotive build");
}

View File

@@ -51,6 +51,7 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.ActiveUnlockConfig;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dagger.SysUISingleton;
@@ -658,9 +659,15 @@ public class UdfpsController implements DozeReceiver {
mExecution.assertIsMainThread();
mOverlay = overlay;
final int requestReason = overlay.getRequestReason();
if (requestReason == REASON_AUTH_KEYGUARD
&& !mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
Log.d(TAG, "Attempting to showUdfpsOverlay when fingerprint detection"
+ " isn't running on keyguard. Skip show.");
return;
}
if (overlay.show(this, mOverlayParams)) {
Log.v(TAG, "showUdfpsOverlay | adding window reason="
+ overlay.getRequestReason());
Log.v(TAG, "showUdfpsOverlay | adding window reason=" + requestReason);
mOnFingerDown = false;
mAttemptedToDismissKeyguard = false;
mOrientationListener.enable();
@@ -791,10 +798,9 @@ public class UdfpsController implements DozeReceiver {
mKeyguardUpdateMonitor.requestFaceAuth(/* userInitiatedRequest */ false);
}
if (mKeyguardUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) {
mKeyguardUpdateMonitor.requestActiveUnlock("unlock-intent extra=udfpsFingerDown",
true);
}
mKeyguardUpdateMonitor.requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
"udfpsFingerDown");
}
mOnFingerDown = true;
if (mAlternateTouchProvider != null) {

View File

@@ -510,7 +510,8 @@ public class KeyguardIndicationController {
.setMessage(trustGrantedIndication)
.setTextColor(mInitialTextColorState)
.build(),
false);
true);
hideBiometricMessage();
} else if (!TextUtils.isEmpty(trustManagedIndication)
&& mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
&& !userHasTrust) {

View File

@@ -21,6 +21,7 @@ import android.content.pm.PackageManager
import android.hardware.Sensor
import android.hardware.TriggerEvent
import android.hardware.TriggerEventListener
import com.android.keyguard.ActiveUnlockConfig
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.CoreStartable
@@ -71,13 +72,9 @@ class KeyguardLiftController @Inject constructor(
isListening = false
updateListeningState()
keyguardUpdateMonitor.requestFaceAuth(true)
if (keyguardUpdateMonitor.mRequestActiveUnlockOnWakeup) {
keyguardUpdateMonitor.requestActiveUnlock("wake-unlock," +
" extra=KeyguardLiftController")
} else if (keyguardUpdateMonitor.mInitiateActiveUnlockOnWakeup) {
keyguardUpdateMonitor.initiateActiveUnlock("wake-initiate," +
" extra=KeyguardLiftController")
}
keyguardUpdateMonitor.requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE,
"KeyguardLiftController")
}
}

View File

@@ -98,6 +98,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.policy.SystemBarUtils;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.ActiveUnlockConfig;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardStatusViewController;
import com.android.keyguard.KeyguardUnfoldTransition;
@@ -3383,11 +3384,10 @@ public class NotificationPanelViewController extends PanelViewController {
.log(LockscreenUiEvent.LOCKSCREEN_LOCK_SHOW_HINT);
startUnlockHintAnimation();
}
if (mUpdateMonitor.isFaceEnrolled()
&& mUpdateMonitor.mRequestActiveUnlockOnUnlockIntent
&& mKeyguardBypassController.canBypass()) {
mUpdateMonitor.requestActiveUnlock("unlock-intent,"
+ " extra=lockScreenEmptySpaceTap", true);
if (mUpdateMonitor.isFaceEnrolled()) {
mUpdateMonitor.requestActiveUnlock(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
"lockScreenEmptySpaceTap");
}
}
return true;

View File

@@ -0,0 +1,199 @@
/*
* 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.keyguard
import android.content.ContentResolver
import android.database.ContentObserver
import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.settings.SecureSettings
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
class ActiveUnlockConfigTest : SysuiTestCase() {
private val fakeWakeUri = Uri.Builder().appendPath("wake").build()
private val fakeUnlockIntentUri = Uri.Builder().appendPath("unlock-intent").build()
private val fakeBioFailUri = Uri.Builder().appendPath("bio-fail").build()
@Mock
private lateinit var secureSettings: SecureSettings
@Mock
private lateinit var contentResolver: ContentResolver
@Mock
private lateinit var handler: Handler
@Mock
private lateinit var dumpManager: DumpManager
@Captor
private lateinit var settingsObserverCaptor: ArgumentCaptor<ContentObserver>
private lateinit var activeUnlockConfig: ActiveUnlockConfig
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
`when`(secureSettings.getUriFor(Settings.Secure.ACTIVE_UNLOCK_ON_WAKE))
.thenReturn(fakeWakeUri)
`when`(secureSettings.getUriFor(Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT))
.thenReturn(fakeUnlockIntentUri)
`when`(secureSettings.getUriFor(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL))
.thenReturn(fakeBioFailUri)
activeUnlockConfig = ActiveUnlockConfig(
handler,
secureSettings,
contentResolver,
dumpManager
)
}
@Test
fun testRegsitersForSettingsChanges() {
verifyRegisterSettingObserver()
}
@Test
fun testOnWakeupSettingChanged() {
verifyRegisterSettingObserver()
// GIVEN no active unlock settings enabled
assertFalse(
activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE)
)
// WHEN unlock on wake is allowed
`when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_WAKE,
0, 0)).thenReturn(1)
settingsObserverCaptor.value.onChange(
false,
listOf(fakeWakeUri),
0,
0
)
// THEN active unlock triggers allowed on: wake, unlock-intent, and biometric failure
assertTrue(
activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE)
)
assertTrue(
activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT)
)
assertTrue(
activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL)
)
}
@Test
fun testOnUnlockIntentSettingChanged() {
verifyRegisterSettingObserver()
// GIVEN no active unlock settings enabled
assertFalse(
activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT)
)
// WHEN unlock on biometric failed is allowed
`when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT,
0, 0)).thenReturn(1)
settingsObserverCaptor.value.onChange(
false,
listOf(fakeUnlockIntentUri),
0,
0
)
// THEN active unlock triggers allowed on: biometric failure ONLY
assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE))
assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT))
assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
}
@Test
fun testOnBioFailSettingChanged() {
verifyRegisterSettingObserver()
// GIVEN no active unlock settings enabled
assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
// WHEN unlock on biometric failed is allowed
`when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL,
0, 0)).thenReturn(1)
settingsObserverCaptor.value.onChange(
false,
listOf(fakeBioFailUri),
0,
0
)
// THEN active unlock triggers allowed on: biometric failure ONLY
assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE))
assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT))
assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
}
private fun verifyRegisterSettingObserver() {
verify(contentResolver).registerContentObserver(
eq(fakeWakeUri),
eq(false),
capture(settingsObserverCaptor),
eq(UserHandle.USER_ALL))
verify(contentResolver).registerContentObserver(
eq(fakeUnlockIntentUri),
eq(false),
capture(settingsObserverCaptor),
eq(UserHandle.USER_ALL))
verify(contentResolver).registerContentObserver(
eq(fakeBioFailUri),
eq(false),
capture(settingsObserverCaptor),
eq(UserHandle.USER_ALL))
}
}

View File

@@ -177,6 +177,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
@Mock
private KeyguardUpdateMonitorCallback mTestCallback;
@Mock
private ActiveUnlockConfig mActiveUnlockConfig;
// Direct executor
private Executor mBackgroundExecutor = Runnable::run;
private Executor mMainExecutor = Runnable::run;
@@ -1188,7 +1190,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mBackgroundExecutor, mMainExecutor,
mStatusBarStateController, mLockPatternUtils,
mAuthController, mTelephonyListenerManager,
mInteractionJankMonitor, mLatencyTracker);
mInteractionJankMonitor, mLatencyTracker, mActiveUnlockConfig);
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}

View File

@@ -212,6 +212,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
.thenReturn(mFpmOtherView);
when(mEnrollView.getContext()).thenReturn(mContext);
when(mKeyguardStateController.isOccluded()).thenReturn(false);
when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true);
final List<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();