Merge "Respond to lockout reset requests from the HAL." into sc-dev
This commit is contained in:
@@ -149,7 +149,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
||||
prop.supportsDetectInteraction, prop.halControlsPreview,
|
||||
false /* resetLockoutRequiresChallenge */);
|
||||
final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler,
|
||||
internalProp);
|
||||
internalProp, lockoutResetDispatcher);
|
||||
|
||||
mSensors.put(sensorId, sensor);
|
||||
Slog.d(getTag(), "Added: " + internalProp);
|
||||
|
||||
@@ -80,11 +80,26 @@ public class FaceResetLockoutClient extends HalClientMonitor<ISession> implement
|
||||
}
|
||||
|
||||
void onLockoutCleared() {
|
||||
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_NONE);
|
||||
mLockoutResetDispatcher.notifyLockoutResetCallbacks(getSensorId());
|
||||
resetLocalLockoutStateToNone(getSensorId(), getTargetUserId(), mLockoutCache,
|
||||
mLockoutResetDispatcher);
|
||||
mCallback.onClientFinished(this, true /* success */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the local lockout state and notify any listeners.
|
||||
*
|
||||
* This should only be called when the HAL sends a reset request directly to the
|
||||
* framework (i.e. time based reset, etc.). When the HAL is responding to a
|
||||
* resetLockout request from an instance of this client {@link #onLockoutCleared()} should
|
||||
* be used instead.
|
||||
*/
|
||||
static void resetLocalLockoutStateToNone(int sensorId, int userId,
|
||||
@NonNull LockoutCache lockoutTracker,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
|
||||
lockoutTracker.setLockoutModeForUser(userId, LockoutTracker.LOCKOUT_NONE);
|
||||
lockoutResetDispatcher.notifyLockoutResetCallbacks(sensorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtoEnum() {
|
||||
return BiometricsProto.CM_RESET_LOCKOUT;
|
||||
|
||||
@@ -57,6 +57,7 @@ import com.android.server.biometrics.sensors.HalClientMonitor;
|
||||
import com.android.server.biometrics.sensors.Interruptable;
|
||||
import com.android.server.biometrics.sensors.LockoutCache;
|
||||
import com.android.server.biometrics.sensors.LockoutConsumer;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.RemovalConsumer;
|
||||
import com.android.server.biometrics.sensors.StartUserClient;
|
||||
import com.android.server.biometrics.sensors.StopUserClient;
|
||||
@@ -124,10 +125,16 @@ public class Sensor {
|
||||
private final int mSensorId;
|
||||
private final int mUserId;
|
||||
@NonNull
|
||||
private final LockoutCache mLockoutCache;
|
||||
@NonNull
|
||||
private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
@NonNull
|
||||
private final Callback mCallback;
|
||||
|
||||
HalSessionCallback(@NonNull Context context, @NonNull Handler handler, @NonNull String tag,
|
||||
@NonNull UserAwareBiometricScheduler scheduler, int sensorId, int userId,
|
||||
@NonNull LockoutCache lockoutTracker,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull Callback callback) {
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
@@ -135,6 +142,8 @@ public class Sensor {
|
||||
mScheduler = scheduler;
|
||||
mSensorId = sensorId;
|
||||
mUserId = userId;
|
||||
mLockoutCache = lockoutTracker;
|
||||
mLockoutResetDispatcher = lockoutResetDispatcher;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@@ -327,13 +336,15 @@ public class Sensor {
|
||||
mHandler.post(() -> {
|
||||
final BaseClientMonitor client = mScheduler.getCurrentClient();
|
||||
if (!(client instanceof FaceResetLockoutClient)) {
|
||||
Slog.e(mTag, "onLockoutCleared for non-resetLockout client: "
|
||||
+ Utils.getClientName(client));
|
||||
return;
|
||||
Slog.d(mTag, "onLockoutCleared outside of resetLockout by HAL");
|
||||
FaceResetLockoutClient.resetLocalLockoutStateToNone(mSensorId, mUserId,
|
||||
mLockoutCache, mLockoutResetDispatcher);
|
||||
} else {
|
||||
Slog.d(mTag, "onLockoutCleared after resetLockout");
|
||||
final FaceResetLockoutClient resetLockoutClient =
|
||||
(FaceResetLockoutClient) client;
|
||||
resetLockoutClient.onLockoutCleared();
|
||||
}
|
||||
|
||||
final FaceResetLockoutClient resetLockoutClient = (FaceResetLockoutClient) client;
|
||||
resetLockoutClient.onLockoutCleared();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -465,7 +476,8 @@ public class Sensor {
|
||||
}
|
||||
|
||||
Sensor(@NonNull String tag, @NonNull FaceProvider provider, @NonNull Context context,
|
||||
@NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties) {
|
||||
@NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
|
||||
mTag = tag;
|
||||
mProvider = provider;
|
||||
mContext = context;
|
||||
@@ -493,7 +505,8 @@ public class Sensor {
|
||||
final int sensorId = mSensorProperties.sensorId;
|
||||
|
||||
final HalSessionCallback resultController = new HalSessionCallback(mContext,
|
||||
mHandler, mTag, mScheduler, sensorId, newUserId, callback);
|
||||
mHandler, mTag, mScheduler, sensorId, newUserId, mLockoutCache,
|
||||
lockoutResetDispatcher, callback);
|
||||
|
||||
final StartUserClient.UserStartedCallback<ISession> userStartedCallback =
|
||||
(userIdStarted, newSession) -> {
|
||||
|
||||
@@ -159,7 +159,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
prop.sensorLocations[0].sensorLocationY,
|
||||
prop.sensorLocations[0].sensorRadius);
|
||||
final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler,
|
||||
internalProp, gestureAvailabilityDispatcher);
|
||||
internalProp, lockoutResetDispatcher, gestureAvailabilityDispatcher);
|
||||
|
||||
mSensors.put(sensorId, sensor);
|
||||
Slog.d(getTag(), "Added: " + internalProp);
|
||||
|
||||
@@ -80,11 +80,26 @@ class FingerprintResetLockoutClient extends HalClientMonitor<ISession> implement
|
||||
}
|
||||
|
||||
void onLockoutCleared() {
|
||||
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_NONE);
|
||||
mLockoutResetDispatcher.notifyLockoutResetCallbacks(getSensorId());
|
||||
resetLocalLockoutStateToNone(getSensorId(), getTargetUserId(), mLockoutCache,
|
||||
mLockoutResetDispatcher);
|
||||
mCallback.onClientFinished(this, true /* success */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the local lockout state and notify any listeners.
|
||||
*
|
||||
* This should only be called when the HAL sends a reset request directly to the
|
||||
* framework (i.e. time based reset, etc.). When the HAL is responding to a
|
||||
* resetLockout request from an instance of this client {@link #onLockoutCleared()} should
|
||||
* be used instead.
|
||||
*/
|
||||
static void resetLocalLockoutStateToNone(int sensorId, int userId,
|
||||
@NonNull LockoutCache lockoutTracker,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
|
||||
lockoutTracker.setLockoutModeForUser(userId, LockoutTracker.LOCKOUT_NONE);
|
||||
lockoutResetDispatcher.notifyLockoutResetCallbacks(sensorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtoEnum() {
|
||||
return BiometricsProto.CM_RESET_LOCKOUT;
|
||||
|
||||
@@ -54,6 +54,7 @@ import com.android.server.biometrics.sensors.ErrorConsumer;
|
||||
import com.android.server.biometrics.sensors.HalClientMonitor;
|
||||
import com.android.server.biometrics.sensors.LockoutCache;
|
||||
import com.android.server.biometrics.sensors.LockoutConsumer;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.RemovalConsumer;
|
||||
import com.android.server.biometrics.sensors.StartUserClient;
|
||||
import com.android.server.biometrics.sensors.StopUserClient;
|
||||
@@ -116,16 +117,27 @@ class Sensor {
|
||||
void onHardwareUnavailable();
|
||||
}
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final String mTag;
|
||||
@NonNull private final UserAwareBiometricScheduler mScheduler;
|
||||
@NonNull
|
||||
private final Context mContext;
|
||||
@NonNull
|
||||
private final Handler mHandler;
|
||||
@NonNull
|
||||
private final String mTag;
|
||||
@NonNull
|
||||
private final UserAwareBiometricScheduler mScheduler;
|
||||
private final int mSensorId;
|
||||
private final int mUserId;
|
||||
@NonNull private final Callback mCallback;
|
||||
@NonNull
|
||||
private final LockoutCache mLockoutCache;
|
||||
@NonNull
|
||||
private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
@NonNull
|
||||
private final Callback mCallback;
|
||||
|
||||
HalSessionCallback(@NonNull Context context, @NonNull Handler handler, @NonNull String tag,
|
||||
@NonNull UserAwareBiometricScheduler scheduler, int sensorId, int userId,
|
||||
@NonNull LockoutCache lockoutTracker,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull Callback callback) {
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
@@ -133,6 +145,8 @@ class Sensor {
|
||||
mScheduler = scheduler;
|
||||
mSensorId = sensorId;
|
||||
mUserId = userId;
|
||||
mLockoutCache = lockoutTracker;
|
||||
mLockoutResetDispatcher = lockoutResetDispatcher;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@@ -303,14 +317,15 @@ class Sensor {
|
||||
mHandler.post(() -> {
|
||||
final BaseClientMonitor client = mScheduler.getCurrentClient();
|
||||
if (!(client instanceof FingerprintResetLockoutClient)) {
|
||||
Slog.e(mTag, "onLockoutCleared for non-resetLockout client: "
|
||||
+ Utils.getClientName(client));
|
||||
return;
|
||||
Slog.d(mTag, "onLockoutCleared outside of resetLockout by HAL");
|
||||
FingerprintResetLockoutClient.resetLocalLockoutStateToNone(mSensorId, mUserId,
|
||||
mLockoutCache, mLockoutResetDispatcher);
|
||||
} else {
|
||||
Slog.d(mTag, "onLockoutCleared after resetLockout");
|
||||
final FingerprintResetLockoutClient resetLockoutClient =
|
||||
(FingerprintResetLockoutClient) client;
|
||||
resetLockoutClient.onLockoutCleared();
|
||||
}
|
||||
|
||||
final FingerprintResetLockoutClient resetLockoutClient =
|
||||
(FingerprintResetLockoutClient) client;
|
||||
resetLockoutClient.onLockoutCleared();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -415,6 +430,7 @@ class Sensor {
|
||||
|
||||
Sensor(@NonNull String tag, @NonNull FingerprintProvider provider, @NonNull Context context,
|
||||
@NonNull Handler handler, @NonNull FingerprintSensorPropertiesInternal sensorProperties,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
|
||||
mTag = tag;
|
||||
mProvider = provider;
|
||||
@@ -422,6 +438,7 @@ class Sensor {
|
||||
mToken = new Binder();
|
||||
mHandler = handler;
|
||||
mSensorProperties = sensorProperties;
|
||||
mLockoutCache = new LockoutCache();
|
||||
mScheduler = new UserAwareBiometricScheduler(tag, gestureAvailabilityDispatcher,
|
||||
() -> mCurrentSession != null ? mCurrentSession.mUserId : UserHandle.USER_NULL,
|
||||
new UserAwareBiometricScheduler.UserSwitchCallback() {
|
||||
@@ -443,7 +460,8 @@ class Sensor {
|
||||
final int sensorId = mSensorProperties.sensorId;
|
||||
|
||||
final HalSessionCallback resultController = new HalSessionCallback(mContext,
|
||||
mHandler, mTag, mScheduler, sensorId, newUserId, callback);
|
||||
mHandler, mTag, mScheduler, sensorId, newUserId, mLockoutCache,
|
||||
lockoutResetDispatcher, callback);
|
||||
|
||||
final StartUserClient.UserStartedCallback<ISession> userStartedCallback =
|
||||
(userIdStarted, newSession) -> {
|
||||
@@ -466,7 +484,6 @@ class Sensor {
|
||||
resultController, userStartedCallback);
|
||||
}
|
||||
});
|
||||
mLockoutCache = new LockoutCache();
|
||||
mAuthenticatorIds = new HashMap<>();
|
||||
mLazySession = () -> mCurrentSession != null ? mCurrentSession.mSession : null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.server.biometrics.sensors.face.aidl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.face.ISession;
|
||||
import android.os.Handler;
|
||||
import android.os.test.TestLooper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.biometrics.sensors.LockoutCache;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class SensorTest {
|
||||
|
||||
private static final String TAG = "SensorTest";
|
||||
private static final int USER_ID = 2;
|
||||
private static final int SENSOR_ID = 4;
|
||||
private static final byte[] HAT = new byte[69];
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private IBiometricService mBiometricService;
|
||||
@Mock
|
||||
private ISession mSession;
|
||||
@Mock
|
||||
private UserAwareBiometricScheduler.UserSwitchCallback mUserSwitchCallback;
|
||||
@Mock
|
||||
private Sensor.HalSessionCallback.Callback mHalSessionCallback;
|
||||
@Mock
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
|
||||
private final TestLooper mLooper = new TestLooper();
|
||||
private final LockoutCache mLockoutCache = new LockoutCache();
|
||||
|
||||
private UserAwareBiometricScheduler mScheduler;
|
||||
private Sensor.HalSessionCallback mHalCallback;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(mContext.getSystemService(Context.BIOMETRIC_SERVICE)).thenReturn(mBiometricService);
|
||||
|
||||
mScheduler = new UserAwareBiometricScheduler(TAG,
|
||||
null /* gestureAvailabilityDispatcher */,
|
||||
() -> USER_ID,
|
||||
mUserSwitchCallback);
|
||||
mHalCallback = new Sensor.HalSessionCallback(mContext, new Handler(mLooper.getLooper()),
|
||||
TAG, mScheduler, SENSOR_ID,
|
||||
USER_ID, mLockoutCache, mLockoutResetDispatcher, mHalSessionCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halSessionCallback_respondsToResetLockout() throws Exception {
|
||||
doAnswer((Answer<Void>) invocationOnMock -> {
|
||||
mHalCallback.onLockoutCleared();
|
||||
return null;
|
||||
}).when(mSession).resetLockout(any());
|
||||
mLockoutCache.setLockoutModeForUser(USER_ID, LockoutTracker.LOCKOUT_TIMED);
|
||||
|
||||
mScheduler.scheduleClientMonitor(new FaceResetLockoutClient(mContext,
|
||||
() -> mSession, USER_ID, TAG, SENSOR_ID, HAT, mLockoutCache,
|
||||
mLockoutResetDispatcher));
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verifyNotLocked();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halSessionCallback_respondsToUnprovokedResetLockout() {
|
||||
mLockoutCache.setLockoutModeForUser(USER_ID, LockoutTracker.LOCKOUT_TIMED);
|
||||
|
||||
mHalCallback.onLockoutCleared();
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verifyNotLocked();
|
||||
}
|
||||
|
||||
private void verifyNotLocked() {
|
||||
assertEquals(LockoutTracker.LOCKOUT_NONE, mLockoutCache.getLockoutModeForUser(USER_ID));
|
||||
verify(mLockoutResetDispatcher).notifyLockoutResetCallbacks(eq(SENSOR_ID));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.server.biometrics.sensors.fingerprint.aidl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.fingerprint.ISession;
|
||||
import android.os.Handler;
|
||||
import android.os.test.TestLooper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.biometrics.sensors.LockoutCache;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class SensorTest {
|
||||
|
||||
private static final String TAG = "SensorTest";
|
||||
private static final int USER_ID = 2;
|
||||
private static final int SENSOR_ID = 4;
|
||||
private static final byte[] HAT = new byte[69];
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private IBiometricService mBiometricService;
|
||||
@Mock
|
||||
private ISession mSession;
|
||||
@Mock
|
||||
private UserAwareBiometricScheduler.UserSwitchCallback mUserSwitchCallback;
|
||||
@Mock
|
||||
private Sensor.HalSessionCallback.Callback mHalSessionCallback;
|
||||
@Mock
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
|
||||
private final TestLooper mLooper = new TestLooper();
|
||||
private final LockoutCache mLockoutCache = new LockoutCache();
|
||||
|
||||
private UserAwareBiometricScheduler mScheduler;
|
||||
private Sensor.HalSessionCallback mHalCallback;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(mContext.getSystemService(Context.BIOMETRIC_SERVICE)).thenReturn(mBiometricService);
|
||||
|
||||
mScheduler = new UserAwareBiometricScheduler(TAG,
|
||||
null /* gestureAvailabilityDispatcher */,
|
||||
() -> USER_ID,
|
||||
mUserSwitchCallback);
|
||||
mHalCallback = new Sensor.HalSessionCallback(mContext, new Handler(mLooper.getLooper()),
|
||||
TAG, mScheduler, SENSOR_ID,
|
||||
USER_ID, mLockoutCache, mLockoutResetDispatcher, mHalSessionCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halSessionCallback_respondsToResetLockout() throws Exception {
|
||||
doAnswer((Answer<Void>) invocationOnMock -> {
|
||||
mHalCallback.onLockoutCleared();
|
||||
return null;
|
||||
}).when(mSession).resetLockout(any());
|
||||
mLockoutCache.setLockoutModeForUser(USER_ID, LockoutTracker.LOCKOUT_TIMED);
|
||||
|
||||
mScheduler.scheduleClientMonitor(new FingerprintResetLockoutClient(mContext,
|
||||
() -> mSession, USER_ID, TAG, SENSOR_ID, HAT, mLockoutCache,
|
||||
mLockoutResetDispatcher));
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verifyNotLocked();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halSessionCallback_respondsToUnprovokedResetLockout() {
|
||||
mLockoutCache.setLockoutModeForUser(USER_ID, LockoutTracker.LOCKOUT_TIMED);
|
||||
|
||||
mHalCallback.onLockoutCleared();
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verifyNotLocked();
|
||||
}
|
||||
|
||||
private void verifyNotLocked() {
|
||||
assertEquals(LockoutTracker.LOCKOUT_NONE, mLockoutCache.getLockoutModeForUser(USER_ID));
|
||||
verify(mLockoutResetDispatcher).notifyLockoutResetCallbacks(eq(SENSOR_ID));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user