Added subscription to binder death which removes dead callbacks

Test: atest BiometricStateCallbackTest
Bug: 237439972
Change-Id: I4fad4c5f1042edb27e20c9f916f999092afed0e0
This commit is contained in:
Austin Delgado
2022-08-11 18:21:57 +00:00
parent a833d0f25b
commit 47ac147667
2 changed files with 34 additions and 2 deletions

View File

@@ -28,6 +28,7 @@ import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.IBiometricStateListener;
import android.hardware.biometrics.SensorPropertiesInternal;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserManager;
import android.util.Slog;
@@ -45,7 +46,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @param <P> internal property type
*/
public class BiometricStateCallback<T extends BiometricServiceProvider<P>,
P extends SensorPropertiesInternal> implements ClientMonitorCallback {
P extends SensorPropertiesInternal>
implements ClientMonitorCallback, IBinder.DeathRecipient {
private static final String TAG = "BiometricStateCallback";
@@ -161,6 +163,11 @@ public class BiometricStateCallback<T extends BiometricServiceProvider<P>,
@NonNull IBiometricStateListener listener) {
mBiometricStateListeners.add(listener);
broadcastCurrentEnrollmentState(listener);
try {
listener.asBinder().linkToDeath(this, 0 /* flags */);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to link to death", e);
}
}
private synchronized void broadcastCurrentEnrollmentState(
@@ -196,4 +203,19 @@ public class BiometricStateCallback<T extends BiometricServiceProvider<P>,
Slog.e(TAG, "Remote exception", e);
}
}
}
@Override
public void binderDied() {
// Do nothing, handled below
}
@Override
public void binderDied(IBinder who) {
Slog.w(TAG, "Callback binder died: " + who);
if (mBiometricStateListeners.removeIf(listener -> listener.asBinder().equals(who))) {
Slog.w(TAG, "Removed dead listener for " + who);
} else {
Slog.w(TAG, "No dead listeners found");
}
}
}

View File

@@ -80,6 +80,8 @@ public class BiometricStateCallbackTest {
when(mFakeProvider.hasEnrollments(eq(SENSOR_ID), eq(USER_ID))).thenReturn(true);
when(mUserManager.getAliveUsers()).thenReturn(
List.of(new UserInfo(USER_ID, "name", 0)));
when(mBiometricStateListener.asBinder()).thenReturn(mBiometricStateListener);
mCallback = new BiometricStateCallback<>(mUserManager);
mCallback.registerBiometricStateListener(mBiometricStateListener);
@@ -110,6 +112,14 @@ public class BiometricStateCallbackTest {
false /* expectCallback */, false /* expectedCallbackValue */);
}
@Test
public void testBinderDeath() {
mCallback.binderDied(mBiometricStateListener.asBinder());
testEnrollmentCallback(true /* changed */, false /* isNowEnrolled */,
false /* expectCallback */, false /* expectedCallbackValue */);
}
private void testEnrollmentCallback(boolean changed, boolean isNowEnrolled,
boolean expectCallback, boolean expectedCallbackValue) {
EnrollClient<?> client = mock(EnrollClient.class);