blob: ae980f58cb3f46362f75e3019ffd941874b4698f [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorProperties;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.telephony.TelephonyListenerManager;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.internal.util.reflection.FieldSetter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private static final String TEST_CARRIER = "TEST_CARRIER";
private static final String TEST_CARRIER_2 = "TEST_CARRIER_2";
private static final int TEST_CARRIER_ID = 1;
private static final String TEST_GROUP_UUID = "59b5c870-fc4c-47a4-a99e-9db826b48b24";
private static final SubscriptionInfo TEST_SUBSCRIPTION = new SubscriptionInfo(1, "", 0,
TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_CARRIER_ID, 0xFFFFFF, "",
DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", false, TEST_GROUP_UUID,
TEST_CARRIER_ID, 0);
private static final SubscriptionInfo TEST_SUBSCRIPTION_2 = new SubscriptionInfo(2, "", 0,
TEST_CARRIER, TEST_CARRIER_2, NAME_SOURCE_CARRIER_ID, 0xFFFFFF, "",
DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID,
TEST_CARRIER_ID, 0);
private static final int FACE_SENSOR_ID = 0;
private static final int FINGERPRINT_SENSOR_ID = 1;
@Mock
private DumpManager mDumpManager;
@Mock
private KeyguardUpdateMonitor.StrongAuthTracker mStrongAuthTracker;
@Mock
private TrustManager mTrustManager;
@Mock
private LockPatternUtils mLockPatternUtils;
@Mock
private ILockSettings mLockSettings;
@Mock
private FingerprintManager mFingerprintManager;
@Mock
private FaceManager mFaceManager;
@Mock
private List<FaceSensorPropertiesInternal> mFaceSensorProperties;
@Mock
private BiometricManager mBiometricManager;
@Mock
private PackageManager mPackageManager;
@Mock
private UserManager mUserManager;
@Mock
private DevicePolicyManager mDevicePolicyManager;
@Mock
private KeyguardBypassController mKeyguardBypassController;
@Mock
private SubscriptionManager mSubscriptionManager;
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
@Mock
private TelephonyManager mTelephonyManager;
@Mock
private StatusBarStateController mStatusBarStateController;
@Mock
private AuthController mAuthController;
@Mock
private TelephonyListenerManager mTelephonyListenerManager;
@Mock
private InteractionJankMonitor mInteractionJankMonitor;
@Mock
private LatencyTracker mLatencyTracker;
@Captor
private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
@Mock
private KeyguardUpdateMonitorCallback mTestCallback;
@Mock
private ActiveUnlockConfig mActiveUnlockConfig;
@Mock
private KeyguardUpdateMonitorLogger mKeyguardUpdateMonitorLogger;
@Mock
private IActivityManager mActivityService;
@Mock
private SessionTracker mSessionTracker;
@Mock
private UiEventLogger mUiEventLogger;
@Mock
private PowerManager mPowerManager;
private final int mCurrentUserId = 100;
private final UserInfo mCurrentUserInfo = new UserInfo(mCurrentUserId, "Test user", 0);
@Captor
private ArgumentCaptor<IBiometricEnabledOnKeyguardCallback>
mBiometricEnabledCallbackArgCaptor;
@Captor
private ArgumentCaptor<FaceManager.AuthenticationCallback> mAuthenticationCallbackCaptor;
@Captor
private ArgumentCaptor<CancellationSignal> mCancellationSignalCaptor;
// Direct executor
private final Executor mBackgroundExecutor = Runnable::run;
private final Executor mMainExecutor = Runnable::run;
private TestableLooper mTestableLooper;
private Handler mHandler;
private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
private TestableContext mSpiedContext;
private MockitoSession mMockitoSession;
private StatusBarStateController.StateListener mStatusBarStateListener;
private IBiometricEnabledOnKeyguardCallback mBiometricEnabledOnKeyguardCallback;
private final InstanceId mKeyguardInstanceId = InstanceId.fakeInstanceId(999);
@Before
public void setup() throws RemoteException {
MockitoAnnotations.initMocks(this);
mSpiedContext = spy(mContext);
when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager);
when(mActivityService.getCurrentUser()).thenReturn(mCurrentUserInfo);
when(mActivityService.getCurrentUserId()).thenReturn(mCurrentUserId);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mFaceManager.getSensorPropertiesInternal()).thenReturn(mFaceSensorProperties);
when(mSessionTracker.getSessionId(SESSION_KEYGUARD)).thenReturn(mKeyguardInstanceId);
// IBiometricsFace@1.0 does not support detection, only authentication.
when(mFaceSensorProperties.isEmpty()).thenReturn(false);
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */,
"vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
"00000001" /* serialNumber */, "" /* softwareVersion */));
componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
"" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
"vendor/version/revision" /* softwareVersion */));
when(mFaceSensorProperties.get(anyInt())).thenReturn(new FaceSensorPropertiesInternal(
0 /* id */,
FaceSensorProperties.STRENGTH_STRONG, 1 /* maxTemplatesAllowed */,
componentInfo, FaceSensorProperties.TYPE_UNKNOWN,
false /* supportsFaceDetection */, true /* supportsSelfIllumination */,
false /* resetLockoutRequiresChallenge */));
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of(
new FingerprintSensorPropertiesInternal(1 /* sensorId */,
FingerprintSensorProperties.STRENGTH_STRONG,
1 /* maxEnrollmentsPerUser */,
List.of(new ComponentInfoInternal("fingerprintSensor" /* componentId */,
"vendor/model/revision" /* hardwareVersion */,
"1.01" /* firmwareVersion */,
"00000001" /* serialNumber */, "" /* softwareVersion */)),
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
false /* resetLockoutRequiresHAT */)));
when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
when(mUserManager.isPrimaryUser()).thenReturn(true);
when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class));
when(mStrongAuthTracker
.isUnlockingWithBiometricAllowed(anyBoolean() /* isStrongBiometric */))
.thenReturn(true);
when(mTelephonyManager.getServiceStateForSubscriber(anyInt()))
.thenReturn(new ServiceState());
when(mLockPatternUtils.getLockSettings()).thenReturn(mLockSettings);
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
mSpiedContext.addMockSystemService(TrustManager.class, mTrustManager);
mSpiedContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
mSpiedContext.addMockSystemService(BiometricManager.class, mBiometricManager);
mSpiedContext.addMockSystemService(FaceManager.class, mFaceManager);
mSpiedContext.addMockSystemService(UserManager.class, mUserManager);
mSpiedContext.addMockSystemService(DevicePolicyManager.class, mDevicePolicyManager);
mSpiedContext.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
mSpiedContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
mMockitoSession = ExtendedMockito.mockitoSession()
.spyStatic(SubscriptionManager.class)
.spyStatic(ActivityManager.class)
.startMocking();
ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
.when(SubscriptionManager::getDefaultSubscriptionId);
KeyguardUpdateMonitor.setCurrentUser(mCurrentUserId);
ExtendedMockito.doReturn(KeyguardUpdateMonitor.getCurrentUser())
.when(ActivityManager::getCurrentUser);
ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService);
mTestableLooper = TestableLooper.get(this);
allowTestableLooperAsMainThread();
mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext);
verify(mBiometricManager)
.registerEnabledOnKeyguardCallback(mBiometricEnabledCallbackArgCaptor.capture());
mBiometricEnabledOnKeyguardCallback = mBiometricEnabledCallbackArgCaptor.getValue();
biometricsEnabledForCurrentUser();
mHandler = spy(mKeyguardUpdateMonitor.getHandler());
try {
FieldSetter.setField(mKeyguardUpdateMonitor,
KeyguardUpdateMonitor.class.getDeclaredField("mHandler"), mHandler);
} catch (NoSuchFieldException e) {
}
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue();
mKeyguardUpdateMonitor.registerCallback(mTestCallback);
mTestableLooper.processAllMessages();
when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(true);
}
@After
public void tearDown() {
mMockitoSession.finishMocking();
cleanupKeyguardUpdateMonitor();
}
@Test
public void testInitialBatteryLevelRequested() {
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mBatteryStatus).isNotNull();
}
@Test
public void testReceiversRegistered() {
verify(mBroadcastDispatcher, atLeastOnce()).registerReceiverWithHandler(
eq(mKeyguardUpdateMonitor.mBroadcastReceiver),
any(IntentFilter.class), any(Handler.class));
verify(mBroadcastDispatcher, atLeastOnce()).registerReceiverWithHandler(
eq(mKeyguardUpdateMonitor.mBroadcastAllReceiver),
any(IntentFilter.class), any(Handler.class), eq(UserHandle.ALL));
}
@Test
public void testSimStateInitialized() {
cleanupKeyguardUpdateMonitor();
final int subId = 3;
final int state = TelephonyManager.SIM_STATE_ABSENT;
when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
when(mTelephonyManager.getSimState(anyInt())).thenReturn(state);
when(mSubscriptionManager.getSubscriptionIds(anyInt())).thenReturn(new int[]{subId});
KeyguardUpdateMonitor testKUM = new TestableKeyguardUpdateMonitor(mSpiedContext);
mTestableLooper.processAllMessages();
assertThat(testKUM.getSimState(subId)).isEqualTo(state);
}
@Test
public void testIgnoresSimStateCallback_rebroadcast() {
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(), intent);
mTestableLooper.processAllMessages();
Assert.assertTrue("onSimStateChanged not called",
mKeyguardUpdateMonitor.hasSimStateJustChanged());
intent.putExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, true);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(), intent);
mTestableLooper.processAllMessages();
Assert.assertFalse("onSimStateChanged should have been skipped",
mKeyguardUpdateMonitor.hasSimStateJustChanged());
}
@Test
public void testTelephonyCapable_BootInitState() {
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
}
@Test
public void testTelephonyCapable_SimState_Absent() {
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intent.putExtra(Intent.EXTRA_SIM_STATE,
Intent.SIM_STATE_ABSENT);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
putPhoneInfo(intent, null, false));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isTrue();
}
@Test
public void testTelephonyCapable_SimState_CardIOError() {
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intent.putExtra(Intent.EXTRA_SIM_STATE,
Intent.SIM_STATE_CARD_IO_ERROR);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
putPhoneInfo(intent, null, false));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isTrue();
}
@Test
public void testTelephonyCapable_SimInvalid_ServiceState_InService() {
// SERVICE_STATE - IN_SERVICE, but SIM_STATE is invalid TelephonyCapable should be False
Intent intent = new Intent(Intent.ACTION_SERVICE_STATE);
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_IN_SERVICE);
state.fillInNotifierBundle(data);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, false));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
}
@Test
public void testTelephonyCapable_SimValid_ServiceState_PowerOff() {
// Simulate AirplaneMode case, SERVICE_STATE - POWER_OFF, check TelephonyCapable False
// Only receive ServiceState callback IN_SERVICE -> OUT_OF_SERVICE -> POWER_OFF
Intent intent = new Intent(Intent.ACTION_SERVICE_STATE);
intent.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_LOADED);
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_POWER_OFF);
state.fillInNotifierBundle(data);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, true));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isTrue();
}
/* Normal SIM inserted flow
* ServiceState: ---OutOfServie----->PowerOff->OutOfServie--->InService
* SimState: ----NOT_READY---->READY----------------------LOADED>>>
* Subscription: --------null---->null--->"Chunghwa Telecom"-------->>>
* System: -------------------------------BOOT_COMPLETED------>>>
* TelephonyCapable:(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)------(T)-(T)>>
*/
@Test
public void testTelephonyCapable_BootInitState_ServiceState_OutOfService() {
Intent intent = new Intent(Intent.ACTION_SERVICE_STATE);
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.fillInNotifierBundle(data);
intent.putExtras(data);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, false));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
}
@Test
public void testTelephonyCapable_BootInitState_SimState_NotReady() {
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.fillInNotifierBundle(data);
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intent.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_NOT_READY);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, false));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
}
@Test
public void testTelephonyCapable_BootInitState_SimState_Ready() {
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.fillInNotifierBundle(data);
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intent.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_READY);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, false));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
}
@Test
public void testTelephonyCapable_BootInitState_ServiceState_PowerOff() {
Intent intent = new Intent(Intent.ACTION_SERVICE_STATE);
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_POWER_OFF);
state.fillInNotifierBundle(data);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, false));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
}
@Test
public void testTelephonyCapable_SimValid_ServiceState_InService() {
Intent intent = new Intent(Intent.ACTION_SERVICE_STATE);
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_IN_SERVICE);
state.fillInNotifierBundle(data);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, true));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isTrue();
}
@Test
public void testTelephonyCapable_SimValid_SimState_Loaded() {
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_IN_SERVICE);
state.fillInNotifierBundle(data);
Intent intentSimState = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intentSimState.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_LOADED);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intentSimState, data, true));
mTestableLooper.processAllMessages();
// Even SimState Loaded, still need ACTION_SERVICE_STATE turn on mTelephonyCapable
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
Intent intentServiceState = new Intent(Intent.ACTION_SERVICE_STATE);
intentSimState.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_LOADED);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intentServiceState, data, true));
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isTrue();
}
@Test
public void testTriesToAuthenticateFingerprint_whenKeyguard() {
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
}
@Test
public void test_doesNotTryToAuthenticateFingerprint_whenAuthenticatorsNotRegistered() {
when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(false);
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyInt(), anyInt());
verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
}
@Test
public void testFingerprintDoesNotAuth_whenEncrypted() {
testFingerprintWhenStrongAuth(
STRONG_AUTH_REQUIRED_AFTER_BOOT);
}
@Test
public void testFingerprintDoesNotAuth_whenDpmLocked() {
testFingerprintWhenStrongAuth(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW);
}
@Test
public void testFingerprintDoesNotAuth_whenUserLockdown() {
testFingerprintWhenStrongAuth(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
}
private void testFingerprintWhenStrongAuth(int strongAuth) {
// Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
// will trigger updateBiometricListeningState();
clearInvocations(mFingerprintManager);
mKeyguardUpdateMonitor.resetBiometricListeningState();
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt());
verify(mFingerprintManager).detectFingerprint(any(), any(), anyInt());
}
@Test
public void testTriesToAuthenticate_whenBouncer() {
fingerprintIsNotEnrolled();
faceAuthEnabled();
setKeyguardBouncerVisibility(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
verify(mFaceManager, atLeastOnce()).isHardwareDetected();
verify(mFaceManager, atLeastOnce()).hasEnrolledTemplates(anyInt());
}
@Test
public void testNoStartAuthenticate_whenAboutToShowBouncer() {
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(
/* bouncerIsOrWillBeShowing */ true, /* bouncerFullyShown */ false);
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test
public void testTriesToAuthenticate_whenKeyguard() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
}
@Test
public void skipsAuthentication_whenStatusBarShadeLocked() {
mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test
public void skipsAuthentication_whenEncryptedKeyguard() {
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
STRONG_AUTH_REQUIRED_AFTER_BOOT);
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test
public void requiresAuthentication_whenEncryptedKeyguard_andBypass() {
testStrongAuthExceptOnBouncer(
STRONG_AUTH_REQUIRED_AFTER_BOOT);
}
@Test
public void requiresAuthentication_whenTimeoutKeyguard_andBypass() {
testStrongAuthExceptOnBouncer(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
}
private void testStrongAuthExceptOnBouncer(int strongAuth) {
when(mKeyguardBypassController.canBypass()).thenReturn(true);
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
// Stop scanning when bouncer becomes visible
setKeyguardBouncerVisibility(true);
clearInvocations(mFaceManager);
mKeyguardUpdateMonitor.requestFaceAuth(true,
FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test
public void testTriesToAuthenticate_whenAssistant() {
mKeyguardUpdateMonitor.setKeyguardOccluded(true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
}
@Test
public void testTriesToAuthenticate_whenTrustOnAgentKeyguard_ifBypass() {
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
when(mKeyguardBypassController.canBypass()).thenReturn(true);
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */,
new ArrayList<>());
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
}
@Test
public void testIgnoresAuth_whenTrustAgentOnKeyguard_withoutBypass() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */, new ArrayList<>());
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test
public void testIgnoresAuth_whenLockdown() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test
public void testTriesToAuthenticate_whenLockout() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
}
@Test
public void testOnFaceAuthenticated_skipsFaceWhenAuthenticated() {
// test whether face will be skipped if authenticated, so the value of isStrongBiometric
// doesn't matter here
mKeyguardUpdateMonitor.onFaceAuthenticated(KeyguardUpdateMonitor.getCurrentUser(),
true /* isStrongBiometric */);
setKeyguardBouncerVisibility(true);
mTestableLooper.processAllMessages();
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test
public void testFaceAndFingerprintLockout_onlyFace() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
faceAuthLockedOut();
verify(mLockPatternUtils, never()).requireStrongAuth(anyInt(), anyInt());
}
@Test
public void testFaceAndFingerprintLockout_onlyFingerprint() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
.onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT_PERMANENT, "");
verify(mLockPatternUtils).requireStrongAuth(anyInt(), anyInt());
}
@Test
public void testFaceAndFingerprintLockout() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
faceAuthLockedOut();
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
.onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT_PERMANENT, "");
verify(mLockPatternUtils).requireStrongAuth(anyInt(), anyInt());
}
@Test
public void testGetUserCanSkipBouncer_whenFace() {
int user = KeyguardUpdateMonitor.getCurrentUser();
mKeyguardUpdateMonitor.onFaceAuthenticated(user, true /* isStrongBiometric */);
assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isTrue();
}
@Test
public void testGetUserCanSkipBouncer_whenFace_nonStrongAndDisallowed() {
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(false /* isStrongBiometric */))
.thenReturn(false);
int user = KeyguardUpdateMonitor.getCurrentUser();
mKeyguardUpdateMonitor.onFaceAuthenticated(user, false /* isStrongBiometric */);
assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isFalse();
}
@Test
public void testGetUserCanSkipBouncer_whenFingerprint() {
int user = KeyguardUpdateMonitor.getCurrentUser();
mKeyguardUpdateMonitor.onFingerprintAuthenticated(user, true /* isStrongBiometric */);
assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isTrue();
}
@Test
public void testGetUserCanSkipBouncer_whenFingerprint_nonStrongAndDisallowed() {
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(false /* isStrongBiometric */))
.thenReturn(false);
int user = KeyguardUpdateMonitor.getCurrentUser();
mKeyguardUpdateMonitor.onFingerprintAuthenticated(user, false /* isStrongBiometric */);
assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isFalse();
}
@Test
public void testBiometricsCleared_whenUserSwitches() throws Exception {
final IRemoteCallback reply = new IRemoteCallback.Stub() {
@Override
public void sendResult(Bundle data) {
} // do nothing
};
final BiometricAuthenticated dummyAuthentication =
new BiometricAuthenticated(true /* authenticated */, true /* strong */);
mKeyguardUpdateMonitor.mUserFaceAuthenticated.put(0 /* user */, dummyAuthentication);
mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.put(0 /* user */, dummyAuthentication);
assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(1);
assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(1);
mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, reply);
assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(0);
assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(0);
}
@Test
public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
final IRemoteCallback reply = new IRemoteCallback.Stub() {
@Override
public void sendResult(Bundle data) {
} // do nothing
};
mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
}
@Test
public void testMultiUserLockoutChanged_whenUserSwitches() {
testMultiUserLockout_whenUserSwitches(BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT,
BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT);
}
@Test
public void testMultiUserLockoutNotChanged_whenUserSwitches() {
testMultiUserLockout_whenUserSwitches(BiometricConstants.BIOMETRIC_LOCKOUT_NONE,
BiometricConstants.BIOMETRIC_LOCKOUT_NONE);
}
private void testMultiUserLockout_whenUserSwitches(
@BiometricConstants.LockoutMode int fingerprintLockoutMode,
@BiometricConstants.LockoutMode int faceLockoutMode) {
final int newUser = 12;
final boolean faceLocked =
faceLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
final boolean fpLocked =
fingerprintLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
.thenReturn(fingerprintLockoutMode);
when(mFaceManager.getLockoutModeForUser(eq(FACE_SENSOR_ID), eq(newUser)))
.thenReturn(faceLockoutMode);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
final CancellationSignal fpCancel = spy(mKeyguardUpdateMonitor.mFingerprintCancelSignal);
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
mKeyguardUpdateMonitor.mFingerprintCancelSignal = fpCancel;
KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
mKeyguardUpdateMonitor.registerCallback(callback);
mKeyguardUpdateMonitor.handleUserSwitchComplete(newUser);
mTestableLooper.processAllMessages();
verify(faceCancel, faceLocked ? times(1) : never()).cancel();
verify(fpCancel, fpLocked ? times(1) : never()).cancel();
verify(callback, faceLocked ? times(1) : never()).onBiometricRunningStateChanged(
eq(false), eq(BiometricSourceType.FACE));
verify(callback, fpLocked ? times(1) : never()).onBiometricRunningStateChanged(
eq(false), eq(BiometricSourceType.FINGERPRINT));
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked);
assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked);
}
@Test
public void testGetUserCanSkipBouncer_whenTrust() {
int user = KeyguardUpdateMonitor.getCurrentUser();
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, user, 0 /* flags */,
new ArrayList<>());
assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isTrue();
}
@Test
public void testGetSubscriptionInfo_whenInGroupedSubWithOpportunistic() {
List<SubscriptionInfo> list = new ArrayList<>();
list.add(TEST_SUBSCRIPTION);
list.add(TEST_SUBSCRIPTION_2);
when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(list);
mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
TEST_SUBSCRIPTION_2.getSubscriptionId());
mTestableLooper.processAllMessages();
List<SubscriptionInfo> listToVerify = mKeyguardUpdateMonitor
.getFilteredSubscriptionInfo(false);
assertThat(listToVerify.size()).isEqualTo(1);
assertThat(listToVerify.get(0)).isEqualTo(TEST_SUBSCRIPTION_2);
}
@Test
public void testActiveSubscriptionBecomesInactive() {
List<SubscriptionInfo> list = new ArrayList<>();
list.add(TEST_SUBSCRIPTION);
when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(list);
mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
TEST_SUBSCRIPTION.getSubscriptionId());
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mSimDatas.get(TEST_SUBSCRIPTION.getSubscriptionId()))
.isNotNull();
when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(null);
mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.mSimDatas.get(TEST_SUBSCRIPTION.getSubscriptionId()))
.isNull();
assertThat(mKeyguardUpdateMonitor.mSimDatas.get(
SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isNull();
}
@Test
public void testIsUserUnlocked() {
// mUserManager will report the user as unlocked on @Before
assertThat(mKeyguardUpdateMonitor.isUserUnlocked(KeyguardUpdateMonitor.getCurrentUser()))
.isTrue();
// Invalid user should not be unlocked.
int randomUser = 99;
assertThat(mKeyguardUpdateMonitor.isUserUnlocked(randomUser)).isFalse();
}
@Test
public void testTrustUsuallyManaged_whenTrustChanges() {
int user = KeyguardUpdateMonitor.getCurrentUser();
when(mTrustManager.isTrustUsuallyManaged(eq(user))).thenReturn(true);
mKeyguardUpdateMonitor.onTrustManagedChanged(false /* managed */, user);
assertThat(mKeyguardUpdateMonitor.isTrustUsuallyManaged(user)).isTrue();
}
@Test
public void testTrustUsuallyManaged_resetWhenUserIsRemoved() {
int user = KeyguardUpdateMonitor.getCurrentUser();
when(mTrustManager.isTrustUsuallyManaged(eq(user))).thenReturn(true);
mKeyguardUpdateMonitor.onTrustManagedChanged(false /* managed */, user);
assertThat(mKeyguardUpdateMonitor.isTrustUsuallyManaged(user)).isTrue();
mKeyguardUpdateMonitor.handleUserRemoved(user);
assertThat(mKeyguardUpdateMonitor.isTrustUsuallyManaged(user)).isFalse();
}
@Test
public void testSecondaryLockscreenRequirement() {
KeyguardUpdateMonitor.setCurrentUser(UserHandle.myUserId());
int user = KeyguardUpdateMonitor.getCurrentUser();
String packageName = "fake.test.package";
String cls = "FakeService";
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.packageName = packageName;
serviceInfo.name = cls;
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.serviceInfo = serviceInfo;
when(mPackageManager.resolveService(any(Intent.class), eq(0))).thenReturn(resolveInfo);
when(mDevicePolicyManager.isSecondaryLockscreenEnabled(eq(UserHandle.of(user))))
.thenReturn(true, false);
when(mDevicePolicyManager.getProfileOwnerOrDeviceOwnerSupervisionComponent(
UserHandle.of(user)))
.thenReturn(new ComponentName(packageName, cls));
// Initially null.
assertThat(mKeyguardUpdateMonitor.getSecondaryLockscreenRequirement(user)).isNull();
// Set non-null after DPM change.
setBroadcastReceiverPendingResult(mKeyguardUpdateMonitor.mBroadcastAllReceiver);
Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
mKeyguardUpdateMonitor.mBroadcastAllReceiver.onReceive(getContext(), intent);
mTestableLooper.processAllMessages();
Intent storedIntent = mKeyguardUpdateMonitor.getSecondaryLockscreenRequirement(user);
assertThat(storedIntent.getComponent().getClassName()).isEqualTo(cls);
assertThat(storedIntent.getComponent().getPackageName()).isEqualTo(packageName);
// Back to null after another DPM change.
mKeyguardUpdateMonitor.mBroadcastAllReceiver.onReceive(getContext(), intent);
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.getSecondaryLockscreenRequirement(user)).isNull();
}
@Test
public void testRegisterAuthControllerCallback() {
assertThat(mKeyguardUpdateMonitor.isUdfpsEnrolled()).isFalse();
// verify AuthController.Callback is added:
ArgumentCaptor<AuthController.Callback> captor = ArgumentCaptor.forClass(
AuthController.Callback.class);
verify(mAuthController).addCallback(captor.capture());
AuthController.Callback callback = captor.getValue();
// WHEN udfps is now enrolled
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
callback.onEnrollmentsChanged();
// THEN isUdfspEnrolled is TRUE
assertThat(mKeyguardUpdateMonitor.isUdfpsEnrolled()).isTrue();
}
@Test
public void testStartUdfpsServiceBeginsOnKeyguard() {
// GIVEN
// - status bar state is on the keyguard
// - user has authenticated since boot
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
// THEN we should listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true);
}
@Test
public void testOccludingAppFingerprintListeningState() {
// GIVEN keyguard isn't visible (app occluding)
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mKeyguardUpdateMonitor.setKeyguardOccluded(true);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false);
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
// THEN we shouldn't listen for fingerprints
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(false);
// THEN we should listen for udfps (hiding of mechanism to actually auth is
// controlled by UdfpsKeyguardViewController)
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true);
}
@Test
public void testOccludingAppRequestsFingerprint() {
// GIVEN keyguard isn't visible (app occluding)
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mKeyguardUpdateMonitor.setKeyguardOccluded(true);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false);
// WHEN an occluding app requests fp
mKeyguardUpdateMonitor.requestFingerprintAuthOnOccludingApp(true);
// THEN we should listen for fingerprints
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(true);
// WHEN an occluding app stops requesting fp
mKeyguardUpdateMonitor.requestFingerprintAuthOnOccludingApp(false);
// THEN we shouldn't listen for fingeprints
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isEqualTo(false);
}
@Test
public void testStartUdfpsServiceNoAuthenticationSinceLastBoot() {
// GIVEN status bar state is on the keyguard
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
// WHEN user hasn't authenticated since last boot
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
// THEN we shouldn't listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
}
@Test
public void testStartUdfpsServiceStrongAuthRequiredAfterTimeout() {
// GIVEN status bar state is on the keyguard
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
// WHEN user loses smart unlock trust
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(SOME_AUTH_REQUIRED_AFTER_USER_REQUEST);
// THEN we should still listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true);
}
@Test
public void testShouldNotListenForUdfps_whenTrustEnabled() {
// GIVEN a "we should listen for udfps" state
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
// WHEN trust is enabled (ie: via smartlock)
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */, new ArrayList<>());
// THEN we shouldn't listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
}
@Test
public void testShouldNotListenForUdfps_whenFaceAuthenticated() {
// GIVEN a "we should listen for udfps" state
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
// WHEN face authenticated
mKeyguardUpdateMonitor.onFaceAuthenticated(
KeyguardUpdateMonitor.getCurrentUser(), false);
// THEN we shouldn't listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
}
@Test
public void testShouldNotListenForUdfps_whenInLockDown() {
// GIVEN a "we should listen for udfps" state
setKeyguardBouncerVisibility(false /* isVisible */);
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
// WHEN device in lock down
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
// THEN we shouldn't listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
}
@Test
public void testShouldNotUpdateBiometricListeningStateOnStatusBarStateChange() {
// GIVEN state for face auth should run aside from StatusBarState
biometricsNotDisabledThroughDevicePolicyManager();
mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
setKeyguardBouncerVisibility(false /* isVisible */);
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
when(mKeyguardBypassController.canBypass()).thenReturn(true);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
// WHEN status bar state reports a change to the keyguard that would normally indicate to
// start running face auth
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isEqualTo(true);
// THEN face unlock is not running b/c status bar state changes don't cause biometric
// listening state to update
assertThat(mKeyguardUpdateMonitor.isFaceDetectionRunning()).isEqualTo(false);
// WHEN biometric listening state is updated
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
// THEN face unlock is running
assertThat(mKeyguardUpdateMonitor.isFaceDetectionRunning()).isEqualTo(true);
}
@Test
public void testRequireUnlockForNfc_Broadcast() {
KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
mKeyguardUpdateMonitor.registerCallback(callback);
Intent intent = new Intent(NfcAdapter.ACTION_REQUIRE_UNLOCK_FOR_NFC);
mKeyguardUpdateMonitor.mBroadcastAllReceiver.onReceive(getContext(), intent);
mTestableLooper.processAllMessages();
verify(callback, atLeastOnce()).onRequireUnlockForNfc();
}
@Test
public void testFaceDoesNotAuth_afterPinAttempt() {
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.setCredentialAttempted();
verify(mFingerprintManager, never()).authenticate(any(), any(), any(),
any(), anyInt());
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test
public void testShowTrustGrantedMessage_onTrustGranted() {
// WHEN trust is enabled (ie: via some trust agent) with a trustGranted string
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */,
Arrays.asList("Unlocked by wearable"));
// THEN the showTrustGrantedMessage should be called with the first message
verify(mTestCallback).showTrustGrantedMessage("Unlocked by wearable");
}
@Test
public void testShouldListenForFace_whenFaceManagerNotAvailable_returnsFalse() {
cleanupKeyguardUpdateMonitor();
mSpiedContext.addMockSystemService(FaceManager.class, null);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(false);
mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext);
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testShouldListenForFace_whenFpIsLockedOut_returnsFalse() throws RemoteException {
// Face auth should run when the following is true.
keyguardNotGoingAway();
occludingAppRequestsFaceAuth();
currentUserIsPrimary();
strongAuthNotRequired();
biometricsEnabledForCurrentUser();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
// Fingerprint is locked out.
fingerprintErrorLockedOut();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testShouldListenForFace_whenFaceIsAlreadyAuthenticated_returnsFalse()
throws RemoteException {
// Face auth should run when the following is true.
faceAuthEnabled();
bouncerFullyVisibleAndNotGoingToSleep();
fingerprintIsNotEnrolled();
keyguardNotGoingAway();
currentUserIsPrimary();
strongAuthNotRequired();
biometricsEnabledForCurrentUser();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
triggerSuccessfulFaceAuth();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testShouldListenForFace_whenUserIsNotPrimary_returnsFalse() throws RemoteException {
cleanupKeyguardUpdateMonitor();
// This disables face auth
when(mUserManager.isPrimaryUser()).thenReturn(false);
mKeyguardUpdateMonitor =
new TestableKeyguardUpdateMonitor(mSpiedContext);
// Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
strongAuthNotRequired();
biometricsEnabledForCurrentUser();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testShouldListenForFace_whenStrongAuthDoesNotAllowScanning_returnsFalse()
throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
currentUserIsPrimary();
biometricsEnabledForCurrentUser();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
userNotCurrentlySwitching();
// This disables face auth
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testShouldListenForFace_whenBiometricsDisabledForUser_returnsFalse()
throws RemoteException {
// Preconditions for face auth to run
faceAuthEnabled();
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
fingerprintIsNotEnrolled();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
// This disables face auth
biometricsDisabledForCurrentUser();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testShouldListenForFace_whenUserCurrentlySwitching_returnsFalse()
throws RemoteException {
// Preconditions for face auth to run
faceAuthEnabled();
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
fingerprintIsNotEnrolled();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
userCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testShouldListenForFace_whenSecureCameraLaunched_returnsFalse()
throws RemoteException {
// Preconditions for face auth to run
faceAuthEnabled();
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
fingerprintIsNotEnrolled();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
secureCameraLaunched();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testShouldListenForFace_whenOccludingAppRequestsFaceAuth_returnsTrue()
throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
secureCameraLaunched();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
occludingAppRequestsFaceAuth();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
}
@Test
public void testShouldListenForFace_whenBouncerShowingAndDeviceIsAwake_returnsTrue()
throws RemoteException {
// Preconditions for face auth to run
faceAuthEnabled();
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
bouncerFullyVisibleAndNotGoingToSleep();
fingerprintIsNotEnrolled();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
}
@Test
public void testShouldListenForFace_whenAuthInterruptIsActive_returnsTrue()
throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
triggerAuthInterrupt();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
}
@Test
public void testShouldListenForFace_whenKeyguardIsAwake_returnsTrue() throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
bouncerFullyVisible();
statusBarShadeIsLocked();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
deviceNotGoingToSleep();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
deviceIsInteractive();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
keyguardIsVisible();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
statusBarShadeIsNotLocked();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
bouncerNotFullyVisible();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
}
@Test
public void testShouldListenForFace_whenUdfpsFingerDown_returnsTrue() throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
when(mAuthController.isUdfpsFingerDown()).thenReturn(false);
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
when(mAuthController.isUdfpsFingerDown()).thenReturn(true);
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
}
@Test
public void testShouldListenForFace_whenUdfpsBouncerIsShowing_returnsTrue()
throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
mKeyguardUpdateMonitor.setUdfpsBouncerShowing(true);
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
}
@Test
public void testShouldListenForFace_whenFaceIsLockedOut_returnsFalse()
throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
mKeyguardUpdateMonitor.setUdfpsBouncerShowing(true);
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
// Face is locked out.
faceAuthLockedOut();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@Test
public void testBouncerVisibility_whenBothFingerprintAndFaceIsEnrolled_stopsFaceAuth()
throws RemoteException {
// Both fingerprint and face are enrolled by default
// Preconditions for face auth to run
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
deviceNotGoingToSleep();
deviceIsInteractive();
statusBarShadeIsNotLocked();
keyguardIsVisible();
mTestableLooper.processAllMessages();
clearInvocations(mUiEventLogger);
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
mKeyguardUpdateMonitor.requestFaceAuth(true,
FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
verify(mFaceManager).authenticate(any(),
mCancellationSignalCaptor.capture(),
mAuthenticationCallbackCaptor.capture(),
any(),
anyInt(),
anyBoolean());
CancellationSignal cancelSignal = mCancellationSignalCaptor.getValue();
bouncerWillBeVisibleSoon();
mTestableLooper.processAllMessages();
assertThat(cancelSignal.isCanceled()).isTrue();
}
@Test
public void testFingerprintCanAuth_whenCancellationNotReceivedAndAuthFailed() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
mKeyguardUpdateMonitor.onFaceAuthenticated(0, false);
// Make sure keyguard is going away after face auth attempt, and that it calls
// updateBiometricStateListeningState.
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false);
mTestableLooper.processAllMessages();
verify(mHandler).postDelayed(mKeyguardUpdateMonitor.mFpCancelNotReceived,
DEFAULT_CANCEL_SIGNAL_TIMEOUT);
mKeyguardUpdateMonitor.onFingerprintAuthenticated(0, true);
mTestableLooper.processAllMessages();
verify(mHandler, times(1)).removeCallbacks(mKeyguardUpdateMonitor.mFpCancelNotReceived);
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(anyBoolean())).isEqualTo(true);
}
@Test
public void testFingerAcquired_wakesUpPowerManager() {
cleanupKeyguardUpdateMonitor();
mSpiedContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.bool.kg_wake_on_acquire_start, true);
mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext);
fingerprintAcquireStart();
verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
}
@Test
public void testFingerAcquired_doesNotWakeUpPowerManager() {
cleanupKeyguardUpdateMonitor();
mSpiedContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.bool.kg_wake_on_acquire_start, false);
mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext);
fingerprintAcquireStart();
verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
}
private void cleanupKeyguardUpdateMonitor() {
if (mKeyguardUpdateMonitor != null) {
mKeyguardUpdateMonitor.removeCallback(mTestCallback);
mKeyguardUpdateMonitor.destroy();
mKeyguardUpdateMonitor = null;
}
}
private void faceAuthLockedOut() {
mKeyguardUpdateMonitor.mFaceAuthenticationCallback
.onAuthenticationError(FaceManager.FACE_ERROR_LOCKOUT_PERMANENT, "");
}
private void faceAuthEnabled() {
// this ensures KeyguardUpdateMonitor updates the cached mIsFaceEnrolled flag using the
// face manager mock wire-up in setup()
mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(mCurrentUserId);
}
private void fingerprintIsNotEnrolled() {
when(mFingerprintManager.hasEnrolledTemplates(mCurrentUserId)).thenReturn(false);
// This updates the cached fingerprint state.
// There is no straightforward API to update the fingerprint state.
// It currently works updates after enrollment changes because something else invokes
// startListeningForFingerprint(), which internally calls this method.
mKeyguardUpdateMonitor.isUnlockWithFingerprintPossible(mCurrentUserId);
}
private void statusBarShadeIsNotLocked() {
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
}
private void statusBarShadeIsLocked() {
mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
}
private void keyguardIsVisible() {
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
}
private void triggerAuthInterrupt() {
mKeyguardUpdateMonitor.onAuthInterruptDetected(true);
}
private void occludingAppRequestsFaceAuth() {
mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(true);
}
private void secureCameraLaunched() {
mKeyguardUpdateMonitor.onCameraLaunched();
}
private void userCurrentlySwitching() {
mKeyguardUpdateMonitor.setSwitchingUser(true);
}
private void fingerprintErrorLockedOut() {
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
.onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT, "Fingerprint locked out");
}
private void fingerprintAcquireStart() {
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
.onAuthenticationAcquired(FINGERPRINT_ACQUIRED_START);
}
private void triggerSuccessfulFaceAuth() {
mKeyguardUpdateMonitor.requestFaceAuth(true, FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
verify(mFaceManager).authenticate(any(),
any(),
mAuthenticationCallbackCaptor.capture(),
any(),
anyInt(),
anyBoolean());
mAuthenticationCallbackCaptor.getValue()
.onAuthenticationSucceeded(
new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false));
}
private void currentUserIsPrimary() {
when(mUserManager.isPrimaryUser()).thenReturn(true);
}
private void biometricsNotDisabledThroughDevicePolicyManager() {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(null,
KeyguardUpdateMonitor.getCurrentUser())).thenReturn(0);
}
private void biometricsEnabledForCurrentUser() throws RemoteException {
mBiometricEnabledOnKeyguardCallback.onChanged(true, KeyguardUpdateMonitor.getCurrentUser());
}
private void biometricsDisabledForCurrentUser() throws RemoteException {
mBiometricEnabledOnKeyguardCallback.onChanged(
false,
KeyguardUpdateMonitor.getCurrentUser()
);
}
private void strongAuthNotRequired() {
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(0);
}
private void currentUserDoesNotHaveTrust() {
mKeyguardUpdateMonitor.onTrustChanged(
false,
KeyguardUpdateMonitor.getCurrentUser(),
-1,
new ArrayList<>()
);
}
private void userNotCurrentlySwitching() {
mKeyguardUpdateMonitor.setSwitchingUser(false);
}
private void keyguardNotGoingAway() {
mKeyguardUpdateMonitor.setKeyguardGoingAway(false);
}
private void bouncerFullyVisibleAndNotGoingToSleep() {
bouncerFullyVisible();
deviceNotGoingToSleep();
}
private void deviceNotGoingToSleep() {
mKeyguardUpdateMonitor.dispatchFinishedGoingToSleep(/* value doesn't matter */1);
}
private void deviceIsInteractive() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
}
private void bouncerNotFullyVisible() {
setKeyguardBouncerVisibility(false);
}
private void bouncerFullyVisible() {
setKeyguardBouncerVisibility(true);
}
private void bouncerWillBeVisibleSoon() {
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true, false);
mTestableLooper.processAllMessages();
}
private void setKeyguardBouncerVisibility(boolean isVisible) {
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(isVisible, isVisible);
mTestableLooper.processAllMessages();
}
private void setBroadcastReceiverPendingResult(BroadcastReceiver receiver) {
BroadcastReceiver.PendingResult pendingResult =
new BroadcastReceiver.PendingResult(Activity.RESULT_OK,
"resultData",
/* resultExtras= */ null,
BroadcastReceiver.PendingResult.TYPE_UNREGISTERED,
/* ordered= */ true,
/* sticky= */ false,
/* token= */ null,
UserHandle.myUserId(),
/* flags= */ 0);
receiver.setPendingResult(pendingResult);
}
private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
int subscription = simInited
? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE;
if (data != null) intent.putExtras(data);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subscription);
intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
return intent;
}
private class TestableKeyguardUpdateMonitor extends KeyguardUpdateMonitor {
AtomicBoolean mSimStateChanged = new AtomicBoolean(false);
protected TestableKeyguardUpdateMonitor(Context context) {
super(context,
TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(),
mBroadcastDispatcher, mDumpManager,
mBackgroundExecutor, mMainExecutor,
mStatusBarStateController, mLockPatternUtils,
mAuthController, mTelephonyListenerManager,
mInteractionJankMonitor, mLatencyTracker, mActiveUnlockConfig,
mKeyguardUpdateMonitorLogger, mUiEventLogger, () -> mSessionTracker,
mPowerManager);
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}
public boolean hasSimStateJustChanged() {
return mSimStateChanged.getAndSet(false);
}
@Override
protected void handleSimStateChange(int subId, int slotId, int state) {
mSimStateChanged.set(true);
super.handleSimStateChange(subId, slotId, state);
}
@Override
protected int getBiometricLockoutDelay() {
return 0;
}
}
}