Cancel non interruptable clients when binder dies
Test: atest com.android.server.biometrics.sensors.face.aidl.SensorTest Test: atest com.android.server.biometrics.sensors.fingerprint.aidl.SensorTest Bug: 282695338 Change-Id: Ia8d8beb93c57716bfcc863f2198cdddaf849f349
This commit is contained in:
@@ -70,9 +70,11 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
|
||||
|
||||
// Set mStopUserClient to null when StopUserClient fails. Otherwise it's possible
|
||||
// for that the queue will wait indefinitely until the field is cleared.
|
||||
if (clientMonitor instanceof StopUserClient<?> && !success) {
|
||||
Slog.w(getTag(),
|
||||
"StopUserClient failed(), is the HAL stuck? Clearing mStopUserClient");
|
||||
if (clientMonitor instanceof StopUserClient<?>) {
|
||||
if (!success) {
|
||||
Slog.w(getTag(), "StopUserClient failed(), is the HAL stuck? "
|
||||
+ "Clearing mStopUserClient");
|
||||
}
|
||||
mStopUserClient = null;
|
||||
}
|
||||
if (mCurrentOperation != null && mCurrentOperation.isFor(mOwner)) {
|
||||
|
||||
@@ -89,7 +89,7 @@ public class Sensor {
|
||||
@NonNull private final Map<Integer, Long> mAuthenticatorIds;
|
||||
|
||||
@NonNull private final Supplier<AidlSession> mLazySession;
|
||||
@Nullable private AidlSession mCurrentSession;
|
||||
@Nullable AidlSession mCurrentSession;
|
||||
|
||||
@VisibleForTesting
|
||||
public static class HalSessionCallback extends ISessionCallback.Stub {
|
||||
@@ -486,7 +486,7 @@ public class Sensor {
|
||||
Sensor(@NonNull String tag, @NonNull FaceProvider provider, @NonNull Context context,
|
||||
@NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull BiometricContext biometricContext) {
|
||||
@NonNull BiometricContext biometricContext, AidlSession session) {
|
||||
mTag = tag;
|
||||
mProvider = provider;
|
||||
mContext = context;
|
||||
@@ -549,6 +549,14 @@ public class Sensor {
|
||||
mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
|
||||
}
|
||||
|
||||
Sensor(@NonNull String tag, @NonNull FaceProvider provider, @NonNull Context context,
|
||||
@NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull BiometricContext biometricContext) {
|
||||
this(tag, provider, context, handler, sensorProperties, lockoutResetDispatcher,
|
||||
biometricContext, null);
|
||||
}
|
||||
|
||||
@NonNull Supplier<AidlSession> getLazySession() {
|
||||
return mLazySession;
|
||||
}
|
||||
@@ -557,7 +565,7 @@ public class Sensor {
|
||||
return mSensorProperties;
|
||||
}
|
||||
|
||||
@Nullable AidlSession getSessionForUser(int userId) {
|
||||
@VisibleForTesting @Nullable AidlSession getSessionForUser(int userId) {
|
||||
if (mCurrentSession != null && mCurrentSession.getUserId() == userId) {
|
||||
return mCurrentSession;
|
||||
} else {
|
||||
@@ -641,6 +649,8 @@ public class Sensor {
|
||||
BiometricsProtoEnums.MODALITY_FACE,
|
||||
BiometricsProtoEnums.ISSUE_HAL_DEATH,
|
||||
-1 /* sensorId */);
|
||||
} else if (client != null) {
|
||||
client.cancel();
|
||||
}
|
||||
|
||||
mScheduler.recordCrashState();
|
||||
|
||||
@@ -90,7 +90,7 @@ public class Sensor {
|
||||
@NonNull private final LockoutCache mLockoutCache;
|
||||
@NonNull private final Map<Integer, Long> mAuthenticatorIds;
|
||||
|
||||
@Nullable private AidlSession mCurrentSession;
|
||||
@Nullable AidlSession mCurrentSession;
|
||||
@NonNull private final Supplier<AidlSession> mLazySession;
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -439,7 +439,7 @@ public class Sensor {
|
||||
@NonNull Handler handler, @NonNull FingerprintSensorPropertiesInternal sensorProperties,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
|
||||
@NonNull BiometricContext biometricContext) {
|
||||
@NonNull BiometricContext biometricContext, AidlSession session) {
|
||||
mTag = tag;
|
||||
mProvider = provider;
|
||||
mContext = context;
|
||||
@@ -501,6 +501,16 @@ public class Sensor {
|
||||
});
|
||||
mAuthenticatorIds = new HashMap<>();
|
||||
mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
|
||||
mCurrentSession = session;
|
||||
}
|
||||
|
||||
Sensor(@NonNull String tag, @NonNull FingerprintProvider provider, @NonNull Context context,
|
||||
@NonNull Handler handler, @NonNull FingerprintSensorPropertiesInternal sensorProperties,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
|
||||
@NonNull BiometricContext biometricContext) {
|
||||
this(tag, provider, context, handler, sensorProperties, lockoutResetDispatcher,
|
||||
gestureAvailabilityDispatcher, biometricContext, null);
|
||||
}
|
||||
|
||||
@NonNull Supplier<AidlSession> getLazySession() {
|
||||
@@ -599,6 +609,8 @@ public class Sensor {
|
||||
BiometricsProtoEnums.MODALITY_FINGERPRINT,
|
||||
BiometricsProtoEnums.ISSUE_HAL_DEATH,
|
||||
-1 /* sensorId */);
|
||||
} else if (client != null) {
|
||||
client.cancel();
|
||||
}
|
||||
|
||||
mScheduler.recordCrashState();
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
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.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -41,6 +43,7 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.server.biometrics.log.BiometricContext;
|
||||
import com.android.server.biometrics.log.BiometricLogger;
|
||||
import com.android.server.biometrics.sensors.AuthSessionCoordinator;
|
||||
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
import com.android.server.biometrics.sensors.LockoutCache;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
@@ -82,6 +85,10 @@ public class SensorTest {
|
||||
private AuthSessionCoordinator mAuthSessionCoordinator;
|
||||
@Mock
|
||||
FaceProvider mFaceProvider;
|
||||
@Mock
|
||||
BaseClientMonitor mClientMonitor;
|
||||
@Mock
|
||||
AidlSession mCurrentSession;
|
||||
|
||||
private final TestLooper mLooper = new TestLooper();
|
||||
private final LockoutCache mLockoutCache = new LockoutCache();
|
||||
@@ -161,6 +168,39 @@ public class SensorTest {
|
||||
assertNull(sensor.getSessionForUser(USER_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBinderDied_cancelNonInterruptableClient() {
|
||||
mLooper.dispatchAll();
|
||||
|
||||
when(mCurrentSession.getUserId()).thenReturn(USER_ID);
|
||||
when(mClientMonitor.getTargetUserId()).thenReturn(USER_ID);
|
||||
when(mClientMonitor.isInterruptable()).thenReturn(false);
|
||||
|
||||
final SensorProps sensorProps = new SensorProps();
|
||||
sensorProps.commonProps = new CommonProps();
|
||||
sensorProps.commonProps.sensorId = 1;
|
||||
final FaceSensorPropertiesInternal internalProp = new FaceSensorPropertiesInternal(
|
||||
sensorProps.commonProps.sensorId, sensorProps.commonProps.sensorStrength,
|
||||
sensorProps.commonProps.maxEnrollmentsPerUser, null,
|
||||
sensorProps.sensorType, sensorProps.supportsDetectInteraction,
|
||||
sensorProps.halControlsPreview, false /* resetLockoutRequiresChallenge */);
|
||||
final Sensor sensor = new Sensor("SensorTest", mFaceProvider, mContext, null,
|
||||
internalProp, mLockoutResetDispatcher, mBiometricContext, mCurrentSession);
|
||||
mScheduler = (UserAwareBiometricScheduler) sensor.getScheduler();
|
||||
sensor.mCurrentSession = new AidlSession(0, mock(ISession.class),
|
||||
USER_ID, mHalCallback);
|
||||
|
||||
mScheduler.scheduleClientMonitor(mClientMonitor);
|
||||
|
||||
assertNotNull(mScheduler.getCurrentClient());
|
||||
|
||||
sensor.onBinderDied();
|
||||
|
||||
verify(mClientMonitor).cancel();
|
||||
assertNull(sensor.getSessionForUser(USER_ID));
|
||||
assertNull(mScheduler.getCurrentClient());
|
||||
}
|
||||
|
||||
private void verifyNotLocked() {
|
||||
assertEquals(LockoutTracker.LOCKOUT_NONE, mLockoutCache.getLockoutModeForUser(USER_ID));
|
||||
verify(mLockoutResetDispatcher).notifyLockoutResetCallbacks(eq(SENSOR_ID));
|
||||
|
||||
@@ -17,17 +17,23 @@
|
||||
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.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
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.common.CommonProps;
|
||||
import android.hardware.biometrics.face.SensorProps;
|
||||
import android.hardware.biometrics.fingerprint.ISession;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.os.Handler;
|
||||
import android.os.test.TestLooper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -37,11 +43,13 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.server.biometrics.log.BiometricContext;
|
||||
import com.android.server.biometrics.log.BiometricLogger;
|
||||
import com.android.server.biometrics.sensors.AuthSessionCoordinator;
|
||||
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
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 com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -76,6 +84,14 @@ public class SensorTest {
|
||||
private BiometricContext mBiometricContext;
|
||||
@Mock
|
||||
private AuthSessionCoordinator mAuthSessionCoordinator;
|
||||
@Mock
|
||||
FingerprintProvider mFingerprintProvider;
|
||||
@Mock
|
||||
GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
|
||||
@Mock
|
||||
private AidlSession mCurrentSession;
|
||||
@Mock
|
||||
private BaseClientMonitor mClientMonitor;
|
||||
|
||||
private final TestLooper mLooper = new TestLooper();
|
||||
private final LockoutCache mLockoutCache = new LockoutCache();
|
||||
@@ -130,6 +146,40 @@ public class SensorTest {
|
||||
verifyNotLocked();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBinderDied_cancelNonInterruptableClient() {
|
||||
mLooper.dispatchAll();
|
||||
|
||||
when(mCurrentSession.getUserId()).thenReturn(USER_ID);
|
||||
when(mClientMonitor.getTargetUserId()).thenReturn(USER_ID);
|
||||
when(mClientMonitor.isInterruptable()).thenReturn(false);
|
||||
|
||||
final SensorProps sensorProps = new SensorProps();
|
||||
sensorProps.commonProps = new CommonProps();
|
||||
sensorProps.commonProps.sensorId = 1;
|
||||
final FingerprintSensorPropertiesInternal internalProp = new
|
||||
FingerprintSensorPropertiesInternal(
|
||||
sensorProps.commonProps.sensorId, sensorProps.commonProps.sensorStrength,
|
||||
sensorProps.commonProps.maxEnrollmentsPerUser, null,
|
||||
sensorProps.sensorType, false /* resetLockoutRequiresHardwareAuthToken */);
|
||||
final Sensor sensor = new Sensor("SensorTest", mFingerprintProvider, mContext,
|
||||
null /* handler */, internalProp, mLockoutResetDispatcher,
|
||||
mGestureAvailabilityDispatcher, mBiometricContext, mCurrentSession);
|
||||
mScheduler = (UserAwareBiometricScheduler) sensor.getScheduler();
|
||||
sensor.mCurrentSession = new AidlSession(0, mock(ISession.class),
|
||||
USER_ID, mHalCallback);
|
||||
|
||||
mScheduler.scheduleClientMonitor(mClientMonitor);
|
||||
|
||||
assertNotNull(mScheduler.getCurrentClient());
|
||||
|
||||
sensor.onBinderDied();
|
||||
|
||||
verify(mClientMonitor).cancel();
|
||||
assertNull(sensor.getSessionForUser(USER_ID));
|
||||
assertNull(mScheduler.getCurrentClient());
|
||||
}
|
||||
|
||||
private void verifyNotLocked() {
|
||||
assertEquals(LockoutTracker.LOCKOUT_NONE, mLockoutCache.getLockoutModeForUser(USER_ID));
|
||||
verify(mLockoutResetDispatcher).notifyLockoutResetCallbacks(eq(SENSOR_ID));
|
||||
|
||||
Reference in New Issue
Block a user