Merge "Clear BiometricScheduler when biometric HAL dies"
This commit is contained in:
@@ -543,6 +543,10 @@ public class BiometricScheduler {
|
||||
return mCurrentOperation.clientMonitor;
|
||||
}
|
||||
|
||||
public int getCurrentPendingCount() {
|
||||
return mPendingOperations.size();
|
||||
}
|
||||
|
||||
public void recordCrashState() {
|
||||
if (mCrashStates.size() >= CrashState.NUM_ENTRIES) {
|
||||
mCrashStates.removeFirst();
|
||||
@@ -573,4 +577,13 @@ public class BiometricScheduler {
|
||||
pw.println("Crash State " + crashState);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the scheduler of anything work-related. This should be used for example when the
|
||||
* HAL dies.
|
||||
*/
|
||||
public void reset() {
|
||||
mPendingOperations.clear();
|
||||
mCurrentOperation = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinde
|
||||
return mSensorId;
|
||||
}
|
||||
|
||||
public final T getFreshDaemon() {
|
||||
public T getFreshDaemon() {
|
||||
return mLazyDaemon.getDaemon();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.ClientMonitor;
|
||||
@@ -71,7 +72,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final String mHalInstanceName;
|
||||
@NonNull private final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
|
||||
@NonNull @VisibleForTesting
|
||||
final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
|
||||
@NonNull private final ClientMonitor.LazyDaemon<IFace> mLazyDaemon;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
@@ -596,8 +598,11 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
||||
mHandler.post(() -> {
|
||||
mDaemon = null;
|
||||
for (int i = 0; i < mSensors.size(); i++) {
|
||||
final Sensor sensor = mSensors.valueAt(i);
|
||||
final int sensorId = mSensors.keyAt(i);
|
||||
PerformanceTracker.getInstanceForSensorId(sensorId).incrementHALDeathCount();
|
||||
sensor.getScheduler().recordCrashState();
|
||||
sensor.getScheduler().reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -333,16 +333,17 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public Face10(@NonNull Context context, int sensorId,
|
||||
Face10(@NonNull Context context, int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
boolean supportsSelfIllumination, int maxTemplatesAllowed) {
|
||||
boolean supportsSelfIllumination, int maxTemplatesAllowed,
|
||||
@NonNull BiometricScheduler scheduler) {
|
||||
mSensorProperties = new FaceSensorPropertiesInternal(sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength),
|
||||
maxTemplatesAllowed, false /* supportsFaceDetect */, supportsSelfIllumination);
|
||||
mContext = context;
|
||||
mSensorId = sensorId;
|
||||
mScheduler = new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */);
|
||||
mScheduler = scheduler;
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mUsageStats = new UsageStats(context);
|
||||
mAuthenticatorIds = new HashMap<>();
|
||||
@@ -369,7 +370,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
|
||||
this(context, sensorId, strength, lockoutResetDispatcher,
|
||||
context.getResources().getBoolean(R.bool.config_faceAuthSupportsSelfIllumination),
|
||||
context.getResources().getInteger(R.integer.config_faceMaxTemplatesPerUser));
|
||||
context.getResources().getInteger(R.integer.config_faceMaxTemplatesPerUser),
|
||||
new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -388,12 +390,13 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
interruptable.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
|
||||
0 /* vendorCode */);
|
||||
|
||||
mScheduler.recordCrashState();
|
||||
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
|
||||
BiometricsProtoEnums.MODALITY_FACE,
|
||||
BiometricsProtoEnums.ISSUE_HAL_DEATH);
|
||||
}
|
||||
|
||||
mScheduler.recordCrashState();
|
||||
mScheduler.reset();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.ClientMonitor;
|
||||
@@ -67,7 +68,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final String mHalInstanceName;
|
||||
@NonNull private final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
|
||||
@NonNull @VisibleForTesting
|
||||
final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
|
||||
@NonNull private final ClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
@@ -607,8 +609,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
mDaemon = null;
|
||||
|
||||
for (int i = 0; i < mSensors.size(); i++) {
|
||||
final Sensor sensor = mSensors.valueAt(i);
|
||||
final int sensorId = mSensors.keyAt(i);
|
||||
PerformanceTracker.getInstanceForSensorId(sensorId).incrementHALDeathCount();
|
||||
sensor.getScheduler().recordCrashState();
|
||||
sensor.getScheduler().reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -386,12 +386,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
interruptable.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
|
||||
0 /* vendorCode */);
|
||||
|
||||
mScheduler.recordCrashState();
|
||||
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
|
||||
BiometricsProtoEnums.MODALITY_FINGERPRINT,
|
||||
BiometricsProtoEnums.ISSUE_HAL_DEATH);
|
||||
}
|
||||
|
||||
mScheduler.recordCrashState();
|
||||
mScheduler.reset();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.common.CommonProps;
|
||||
import android.hardware.biometrics.face.SensorProps;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.ClientMonitor;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class FaceProviderTest {
|
||||
|
||||
private static final String TAG = "FaceProviderTest";
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
private SensorProps[] mSensorProps;
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private FaceProvider mFaceProvider;
|
||||
|
||||
private static void waitForIdle() {
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>());
|
||||
|
||||
final SensorProps sensor1 = new SensorProps();
|
||||
sensor1.commonProps = new CommonProps();
|
||||
sensor1.commonProps.sensorId = 0;
|
||||
final SensorProps sensor2 = new SensorProps();
|
||||
sensor2.commonProps = new CommonProps();
|
||||
sensor2.commonProps.sensorId = 1;
|
||||
|
||||
mSensorProps = new SensorProps[] {sensor1, sensor2};
|
||||
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
|
||||
|
||||
mFaceProvider = new FaceProvider(mContext, mSensorProps, TAG,
|
||||
mLockoutResetDispatcher);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
public void halServiceDied_resetsAllSchedulers() {
|
||||
assertEquals(mSensorProps.length, mFaceProvider.getSensorProperties().size());
|
||||
|
||||
// Schedule N operations on each sensor
|
||||
final int numFakeOperations = 10;
|
||||
for (SensorProps prop : mSensorProps) {
|
||||
final BiometricScheduler scheduler =
|
||||
mFaceProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
|
||||
for (int i = 0; i < numFakeOperations; i++) {
|
||||
final ClientMonitor testMonitor = mock(ClientMonitor.class);
|
||||
when(testMonitor.getFreshDaemon()).thenReturn(new Object());
|
||||
scheduler.scheduleClientMonitor(testMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
waitForIdle();
|
||||
// The right amount of pending and current operations are scheduled
|
||||
for (SensorProps prop : mSensorProps) {
|
||||
final BiometricScheduler scheduler =
|
||||
mFaceProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
|
||||
assertEquals(numFakeOperations - 1, scheduler.getCurrentPendingCount());
|
||||
assertNotNull(scheduler.getCurrentClient());
|
||||
}
|
||||
|
||||
// It's difficult to test the linkToDeath --> serviceDied path, so let's just invoke
|
||||
// serviceDied directly.
|
||||
mFaceProvider.binderDied();
|
||||
waitForIdle();
|
||||
|
||||
// No pending operations, no current operation.
|
||||
for (SensorProps prop : mSensorProps) {
|
||||
final BiometricScheduler scheduler =
|
||||
mFaceProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
|
||||
assertNull(scheduler.getCurrentClient());
|
||||
assertEquals(0, scheduler.getCurrentPendingCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.sensors.face;
|
||||
package com.android.server.biometrics.sensors.face.hidl;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -28,8 +29,8 @@ import android.platform.test.annotations.Presubmit;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.face.hidl.Face10;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -49,6 +50,8 @@ public class Face10Test {
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private BiometricScheduler mScheduler;
|
||||
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private com.android.server.biometrics.sensors.face.hidl.Face10 mFace10;
|
||||
@@ -68,7 +71,7 @@ public class Face10Test {
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
|
||||
mFace10 = new Face10(mContext, SENSOR_ID, BiometricManager.Authenticators.BIOMETRIC_STRONG,
|
||||
mLockoutResetDispatcher, false /* supportsSelfIllumination */,
|
||||
1 /* maxTemplatesAllowed */);
|
||||
1 /* maxTemplatesAllowed */, mScheduler);
|
||||
mBinder = new Binder();
|
||||
}
|
||||
|
||||
@@ -78,4 +81,13 @@ public class Face10Test {
|
||||
0 /* challenge */);
|
||||
waitForIdle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halServiceDied_resetsScheduler() {
|
||||
// It's difficult to test the linkToDeath --> serviceDied path, so let's just invoke
|
||||
// serviceDied directly.
|
||||
mFace10.serviceDied(0 /* cookie */);
|
||||
waitForIdle();
|
||||
verify(mScheduler).reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.common.CommonProps;
|
||||
import android.hardware.biometrics.fingerprint.SensorProps;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.ClientMonitor;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class FingerprintProviderTest {
|
||||
|
||||
private static final String TAG = "FingerprintProviderTest";
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
|
||||
|
||||
private SensorProps[] mSensorProps;
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private FingerprintProvider mFingerprintProvider;
|
||||
|
||||
private static void waitForIdle() {
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>());
|
||||
|
||||
final SensorProps sensor1 = new SensorProps();
|
||||
sensor1.commonProps = new CommonProps();
|
||||
sensor1.commonProps.sensorId = 0;
|
||||
final SensorProps sensor2 = new SensorProps();
|
||||
sensor2.commonProps = new CommonProps();
|
||||
sensor2.commonProps.sensorId = 1;
|
||||
|
||||
mSensorProps = new SensorProps[] {sensor1, sensor2};
|
||||
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
|
||||
|
||||
mFingerprintProvider = new FingerprintProvider(mContext, mSensorProps, TAG,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
public void halServiceDied_resetsAllSchedulers() {
|
||||
assertEquals(mSensorProps.length, mFingerprintProvider.getSensorProperties().size());
|
||||
|
||||
// Schedule N operations on each sensor
|
||||
final int numFakeOperations = 10;
|
||||
for (SensorProps prop : mSensorProps) {
|
||||
final BiometricScheduler scheduler =
|
||||
mFingerprintProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
|
||||
for (int i = 0; i < numFakeOperations; i++) {
|
||||
final ClientMonitor testMonitor = mock(ClientMonitor.class);
|
||||
when(testMonitor.getFreshDaemon()).thenReturn(new Object());
|
||||
scheduler.scheduleClientMonitor(testMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
waitForIdle();
|
||||
// The right amount of pending and current operations are scheduled
|
||||
for (SensorProps prop : mSensorProps) {
|
||||
final BiometricScheduler scheduler =
|
||||
mFingerprintProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
|
||||
assertEquals(numFakeOperations - 1, scheduler.getCurrentPendingCount());
|
||||
assertNotNull(scheduler.getCurrentClient());
|
||||
}
|
||||
|
||||
// It's difficult to test the linkToDeath --> serviceDied path, so let's just invoke
|
||||
// serviceDied directly.
|
||||
mFingerprintProvider.binderDied();
|
||||
waitForIdle();
|
||||
|
||||
// No pending operations, no current operation.
|
||||
for (SensorProps prop : mSensorProps) {
|
||||
final BiometricScheduler scheduler =
|
||||
mFingerprintProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
|
||||
assertNull(scheduler.getCurrentClient());
|
||||
assertEquals(0, scheduler.getCurrentPendingCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.hidl;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class Fingerprint21Test {
|
||||
|
||||
private static final String TAG = "Fingerprint21Test";
|
||||
private static final int SENSOR_ID = 1;
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
Fingerprint21.HalResultController mHalResultController;
|
||||
@Mock
|
||||
private BiometricScheduler mScheduler;
|
||||
|
||||
private LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private Fingerprint21 mFingerprint21;
|
||||
|
||||
private static void waitForIdle() {
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>());
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mResources.getInteger(eq(R.integer.config_fingerprintMaxTemplatesPerUser)))
|
||||
.thenReturn(5);
|
||||
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
|
||||
mFingerprint21 = new Fingerprint21(mContext, mScheduler,
|
||||
new Handler(Looper.getMainLooper()), SENSOR_ID,
|
||||
BiometricManager.Authenticators.BIOMETRIC_WEAK, mLockoutResetDispatcher,
|
||||
mHalResultController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halServiceDied_resetsScheduler() {
|
||||
// It's difficult to test the linkToDeath --> serviceDied path, so let's just invoke
|
||||
// serviceDied directly.
|
||||
mFingerprint21.serviceDied(0 /* cookie */);
|
||||
waitForIdle();
|
||||
verify(mScheduler).reset();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user