Add and use ServiceProvider interface on fingerprint2.1
This interface should allow easy support for multiple HAL interfaces.
For example,
for (ServiceProvider p : providers) {
if (p.containsSensor(sensorId)) {
p.authenticate(sensorId, ...)
}
}
or,
ServiceProvider provider = getProviderFor(sensorId)
if (provider != null) provider.authenticate(sensorId, ...)
This should reduce lots of repeated null checks, sensorId checks,
etc. and give FingerprintService a easy way to perform operations
on providers, given a sensorId.
Some of the FingerprintManager code is not sensorId-specific,
but we can update those in the future. Otherwise we have to
touch multiple projects (settings, etc). For now, all client-side
code assumes only a single sensor, so that's what we'll support
from FingerprintService.
Bug: 168843828
Test: No effect on existing devices
Test: atest com.android.server.biometrics
Test: atest com.android.systemui.biometrics
Change-Id: Icca5bc1e128afa1bb7b2c05227e87567e564e4cf
This commit is contained in:
@@ -746,7 +746,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||
public void setUdfpsOverlayController(IUdfpsOverlayController controller) {
|
||||
public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
|
||||
if (mService == null) {
|
||||
Slog.w(TAG, "setUdfpsOverlayController: no fingerprint service");
|
||||
return;
|
||||
@@ -763,14 +763,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||
public void onFingerDown(int x, int y, float minor, float major) {
|
||||
public void onFingerDown(int sensorId, int x, int y, float minor, float major) {
|
||||
if (mService == null) {
|
||||
Slog.w(TAG, "onFingerDown: no fingerprint service");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mService.onFingerDown(x, y, minor, major);
|
||||
mService.onFingerDown(sensorId, x, y, minor, major);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -780,14 +780,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||
public void onFingerUp() {
|
||||
public void onFingerUp(int sensorId) {
|
||||
if (mService == null) {
|
||||
Slog.w(TAG, "onFingerDown: no fingerprint service");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mService.onFingerUp();
|
||||
mService.onFingerUp(sensorId);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -18,9 +18,7 @@ package android.hardware.fingerprint;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.face.FaceSensorProperties;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@@ -121,10 +121,10 @@ interface IFingerprintService {
|
||||
void initializeConfiguration(int sensorId, int strength);
|
||||
|
||||
// Notifies about a finger touching the sensor area.
|
||||
void onFingerDown(int x, int y, float minor, float major);
|
||||
void onFingerDown(int sensorId, int x, int y, float minor, float major);
|
||||
|
||||
// Notifies about a finger leaving the sensor area.
|
||||
void onFingerUp();
|
||||
void onFingerUp(int sensorId);
|
||||
|
||||
// Sets the controller for managing the UDFPS overlay.
|
||||
void setUdfpsOverlayController(in IUdfpsOverlayController controller);
|
||||
|
||||
@@ -21,11 +21,11 @@ package android.hardware.fingerprint;
|
||||
*/
|
||||
oneway interface IUdfpsOverlayController {
|
||||
// Shows the overlay.
|
||||
void showUdfpsOverlay();
|
||||
void showUdfpsOverlay(int sensorId);
|
||||
|
||||
// Hides the overlay.
|
||||
void hideUdfpsOverlay();
|
||||
void hideUdfpsOverlay(int sensorId);
|
||||
|
||||
// Shows debug messages on the UDFPS overlay.
|
||||
void setDebugMessage(String message);
|
||||
void setDebugMessage(int sensorId, String message);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import static com.android.internal.util.Preconditions.checkArgument;
|
||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -25,6 +26,7 @@ import android.content.res.TypedArray;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.os.PowerManager;
|
||||
import android.os.UserHandle;
|
||||
@@ -41,6 +43,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.BrightnessSynchronizer;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.doze.DozeReceiver;
|
||||
@@ -50,13 +53,22 @@ import com.android.systemui.util.settings.SystemSettings;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Shows and hides the under-display fingerprint sensor (UDFPS) overlay, handles UDFPS touch events,
|
||||
* and coordinates triggering of the high-brightness mode (HBM).
|
||||
*
|
||||
* Note that the current architecture is designed so that a single {@link UdfpsController}
|
||||
* controls/manages all UDFPS sensors. In other words, a single controller is registered with
|
||||
* {@link com.android.server.biometrics.sensors.fingerprint.FingerprintService}, and interfaces such
|
||||
* as {@link FingerprintManager#onFingerDown(int, int, int, float, float)} or
|
||||
* {@link IUdfpsOverlayController#showUdfpsOverlay(int)}should all have
|
||||
* {@code sensorId} parameters.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
class UdfpsController implements DozeReceiver {
|
||||
private static final String TAG = "UdfpsController";
|
||||
// Gamma approximation for the sRGB color space.
|
||||
@@ -64,6 +76,10 @@ class UdfpsController implements DozeReceiver {
|
||||
private static final long AOD_INTERRUPT_TIMEOUT_MILLIS = 1000;
|
||||
|
||||
private final FingerprintManager mFingerprintManager;
|
||||
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
|
||||
// sensors, this, in addition to a lot of the code here, will be updated.
|
||||
@VisibleForTesting
|
||||
final int mUdfpsSensorId;
|
||||
private final WindowManager mWindowManager;
|
||||
private final SystemSettings mSystemSettings;
|
||||
private final DelayableExecutor mFgExecutor;
|
||||
@@ -103,17 +119,17 @@ class UdfpsController implements DozeReceiver {
|
||||
|
||||
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
|
||||
@Override
|
||||
public void showUdfpsOverlay() {
|
||||
public void showUdfpsOverlay(int sensorId) {
|
||||
UdfpsController.this.setShowOverlay(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideUdfpsOverlay() {
|
||||
public void hideUdfpsOverlay(int sensorId) {
|
||||
UdfpsController.this.setShowOverlay(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDebugMessage(String message) {
|
||||
public void setDebugMessage(int sensorId, String message) {
|
||||
mView.setDebugMessage(message);
|
||||
}
|
||||
}
|
||||
@@ -165,6 +181,17 @@ class UdfpsController implements DozeReceiver {
|
||||
mFgExecutor = fgExecutor;
|
||||
mLayoutParams = createLayoutParams(context);
|
||||
|
||||
int udfpsSensorId = -1;
|
||||
for (FingerprintSensorProperties props : mFingerprintManager.getSensorProperties()) {
|
||||
if (props.isAnyUdfpsType()) {
|
||||
udfpsSensorId = props.sensorId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At least one UDFPS sensor exists
|
||||
checkArgument(udfpsSensorId != -1);
|
||||
mUdfpsSensorId = udfpsSensorId;
|
||||
|
||||
mView = (UdfpsView) inflater.inflate(R.layout.udfps_view, null, false);
|
||||
|
||||
mHbmPath = resources.getString(R.string.udfps_hbm_sysfs_path);
|
||||
@@ -347,7 +374,7 @@ class UdfpsController implements DozeReceiver {
|
||||
fw.write(mHbmEnableCommand);
|
||||
fw.close();
|
||||
}
|
||||
mFingerprintManager.onFingerDown(x, y, minor, major);
|
||||
mFingerprintManager.onFingerDown(mUdfpsSensorId, x, y, minor, major);
|
||||
} catch (IOException e) {
|
||||
mView.hideScrimAndDot();
|
||||
Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage());
|
||||
@@ -355,7 +382,7 @@ class UdfpsController implements DozeReceiver {
|
||||
}
|
||||
|
||||
private void onFingerUp() {
|
||||
mFingerprintManager.onFingerUp();
|
||||
mFingerprintManager.onFingerUp(mUdfpsSensorId);
|
||||
// Hiding the scrim before disabling HBM results in less noticeable flicker.
|
||||
mView.hideScrimAndDot();
|
||||
if (mHbmSupported) {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -25,7 +27,9 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
@@ -54,11 +58,18 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@RunWithLooper
|
||||
public class UdfpsControllerTest extends SysuiTestCase {
|
||||
|
||||
// Use this for inputs going into SystemUI. Use UdfpsController.mUdfpsSensorId for things
|
||||
// leaving SystemUI.
|
||||
private static final int TEST_UDFPS_SENSOR_ID = 1;
|
||||
|
||||
@Rule
|
||||
public MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
@@ -98,6 +109,13 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
public void setUp() {
|
||||
setUpResources();
|
||||
when(mLayoutInflater.inflate(R.layout.udfps_view, null, false)).thenReturn(mUdfpsView);
|
||||
final List<FingerprintSensorProperties> props = new ArrayList<>();
|
||||
props.add(new FingerprintSensorProperties(TEST_UDFPS_SENSOR_ID,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */));
|
||||
when(mFingerprintManager.getSensorProperties()).thenReturn(props);
|
||||
mSystemSettings = new FakeSettings();
|
||||
mFgExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
mUdfpsController = new UdfpsController(
|
||||
@@ -112,6 +130,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
mFgExecutor);
|
||||
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
|
||||
mOverlayController = mOverlayCaptor.getValue();
|
||||
|
||||
assertEquals(TEST_UDFPS_SENSOR_ID, mUdfpsController.mUdfpsSensorId);
|
||||
}
|
||||
|
||||
private void setUpResources() {
|
||||
@@ -138,15 +158,15 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void showUdfpsOverlay_addsViewToWindow() throws RemoteException {
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
verify(mWindowManager).addView(eq(mUdfpsView), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException {
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.hideUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
verify(mWindowManager).removeView(eq(mUdfpsView));
|
||||
}
|
||||
@@ -156,7 +176,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
// GIVEN that the bouncer is showing
|
||||
mUdfpsController.setBouncerVisibility(/* isShowing */ true);
|
||||
// WHEN a request to show the overlay is received
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
// THEN the overlay is not attached
|
||||
verify(mWindowManager, never()).addView(eq(mUdfpsView), any());
|
||||
@@ -165,7 +185,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void setBouncerVisibility_overlayDetached() throws RemoteException {
|
||||
// GIVEN that the overlay has been requested
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
// WHEN the bouncer becomes visible
|
||||
mUdfpsController.setBouncerVisibility(/* isShowing */ true);
|
||||
mFgExecutor.runAllReady();
|
||||
@@ -178,7 +198,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
// GIVEN that the bouncer is visible
|
||||
mUdfpsController.setBouncerVisibility(/* isShowing */ true);
|
||||
// AND the overlay has been requested
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
// WHEN the bouncer is closed
|
||||
mUdfpsController.setBouncerVisibility(/* isShowing */ false);
|
||||
mFgExecutor.runAllReady();
|
||||
@@ -193,7 +213,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
when(mUdfpsView.isValidTouch(anyFloat(), anyFloat(), anyFloat())).thenReturn(true);
|
||||
|
||||
// GIVEN that the overlay is showing
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
// WHEN ACTION_DOWN is received
|
||||
verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
|
||||
@@ -201,7 +221,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
|
||||
event.recycle();
|
||||
// THEN the event is passed to the FingerprintManager
|
||||
verify(mFingerprintManager).onFingerDown(eq(0), eq(0), eq(0f), eq(0f));
|
||||
verify(mFingerprintManager).onFingerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0),
|
||||
eq(0f), eq(0f));
|
||||
// AND the scrim and dot is shown
|
||||
verify(mUdfpsView).showScrimAndDot();
|
||||
}
|
||||
@@ -209,12 +230,13 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void aodInterrupt() throws RemoteException {
|
||||
// GIVEN that the overlay is showing
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
// WHEN fingerprint is requested because of AOD interrupt
|
||||
mUdfpsController.onAodInterrupt(0, 0);
|
||||
// THEN the event is passed to the FingerprintManager
|
||||
verify(mFingerprintManager).onFingerDown(eq(0), eq(0), anyFloat(), anyFloat());
|
||||
verify(mFingerprintManager).onFingerDown(eq(mUdfpsController.mUdfpsSensorId), eq(0), eq(0),
|
||||
anyFloat(), anyFloat());
|
||||
// AND the scrim and dot is shown
|
||||
verify(mUdfpsView).showScrimAndDot();
|
||||
}
|
||||
@@ -222,7 +244,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void cancelAodInterrupt() throws RemoteException {
|
||||
// GIVEN AOD interrupt
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
mUdfpsController.onAodInterrupt(0, 0);
|
||||
// WHEN it is cancelled
|
||||
@@ -234,7 +256,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void aodInterruptTimeout() throws RemoteException {
|
||||
// GIVEN AOD interrupt
|
||||
mOverlayController.showUdfpsOverlay();
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
mUdfpsController.onAodInterrupt(0, 0);
|
||||
// WHEN it times out
|
||||
|
||||
@@ -46,6 +46,7 @@ import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.EventLog;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.view.Surface;
|
||||
|
||||
@@ -79,7 +80,7 @@ public class FingerprintService extends SystemService {
|
||||
private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private Fingerprint21 mFingerprint21;
|
||||
@NonNull private List<ServiceProvider> mServiceProviders;
|
||||
|
||||
/**
|
||||
* Receives the incoming binder calls from FingerprintManager.
|
||||
@@ -88,11 +89,8 @@ public class FingerprintService extends SystemService {
|
||||
@Override // Binder call
|
||||
public List<FingerprintSensorProperties> getSensorProperties(String opPackageName) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
final List<FingerprintSensorProperties> properties = new ArrayList<>();
|
||||
|
||||
if (mFingerprint21 != null) {
|
||||
properties.add(mFingerprint21.getFingerprintSensorProperties());
|
||||
}
|
||||
final List<FingerprintSensorProperties> properties =
|
||||
FingerprintService.this.getSensorProperties();
|
||||
|
||||
Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName
|
||||
+ ", sensors: " + properties.size());
|
||||
@@ -104,18 +102,26 @@ public class FingerprintService extends SystemService {
|
||||
IFingerprintServiceReceiver receiver, String opPackageName) {
|
||||
Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
|
||||
|
||||
if (sensorId == mFingerprint21.getFingerprintSensorProperties().sensorId) {
|
||||
mFingerprint21.scheduleGenerateChallenge(token, receiver, opPackageName);
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
|
||||
return;
|
||||
}
|
||||
|
||||
Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
|
||||
provider.scheduleGenerateChallenge(sensorId, token, receiver, opPackageName);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void revokeChallenge(IBinder token, String owner) {
|
||||
public void revokeChallenge(IBinder token, String opPackageName) {
|
||||
Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
|
||||
mFingerprint21.scheduleRevokeChallenge(token, owner);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for revokeChallenge");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.scheduleRevokeChallenge(provider.first, token, opPackageName);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -123,14 +129,28 @@ public class FingerprintService extends SystemService {
|
||||
final IFingerprintServiceReceiver receiver, final String opPackageName,
|
||||
Surface surface) {
|
||||
Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
|
||||
mFingerprint21.scheduleEnroll(token, hardwareAuthToken, userId, receiver, opPackageName,
|
||||
surface);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for enroll");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
|
||||
receiver, opPackageName, surface);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void cancelEnrollment(final IBinder token) {
|
||||
Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
|
||||
mFingerprint21.cancelEnrollment(token);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelEnrollment");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.cancelEnrollment(provider.first, token);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -169,8 +189,15 @@ public class FingerprintService extends SystemService {
|
||||
!= PackageManager.PERMISSION_GRANTED;
|
||||
final int statsClient = isKeyguard ? BiometricsProtoEnums.CLIENT_KEYGUARD
|
||||
: BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;
|
||||
mFingerprint21.scheduleAuthenticate(token, operationId, userId, 0 /* cookie */,
|
||||
new ClientMonitorCallbackConverter(receiver), opPackageName,
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for authenticate");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
|
||||
0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName,
|
||||
restricted, statsClient, isKeyguard);
|
||||
}
|
||||
|
||||
@@ -191,7 +218,13 @@ public class FingerprintService extends SystemService {
|
||||
return;
|
||||
}
|
||||
|
||||
mFingerprint21.scheduleFingerDetect(token, userId,
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for detectFingerprint");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.scheduleFingerDetect(provider.first, token, userId,
|
||||
new ClientMonitorCallbackConverter(receiver), opPackageName, surface,
|
||||
BiometricsProtoEnums.CLIENT_KEYGUARD);
|
||||
}
|
||||
@@ -203,8 +236,14 @@ public class FingerprintService extends SystemService {
|
||||
Surface surface) {
|
||||
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for prepareForAuthentication");
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean restricted = true; // BiometricPrompt is always restricted
|
||||
mFingerprint21.scheduleAuthenticate(token, operationId, userId, cookie,
|
||||
provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, cookie,
|
||||
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
|
||||
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, false /* isKeyguard */);
|
||||
}
|
||||
@@ -212,7 +251,14 @@ public class FingerprintService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void startPreparedClient(int cookie) {
|
||||
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
|
||||
mFingerprint21.startPreparedClient(cookie);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for startPreparedClient");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.startPreparedClient(provider.first, cookie);
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +274,13 @@ public class FingerprintService extends SystemService {
|
||||
return;
|
||||
}
|
||||
|
||||
mFingerprint21.cancelAuthentication(token);
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelAuthentication");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.cancelAuthentication(provider.first, token);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -242,21 +294,41 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
// For IBiometricsFingerprint2.1, cancelling fingerprint detect is the same as
|
||||
// cancelling authentication.
|
||||
mFingerprint21.cancelAuthentication(token);
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelFingerprintDetect");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.cancelAuthentication(provider.first, token);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void cancelAuthenticationFromService(final IBinder token, final String opPackageName,
|
||||
int callingUid, int callingPid, int callingUserId) {
|
||||
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
|
||||
mFingerprint21.cancelAuthentication(token);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelAuthenticationFromService");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.cancelAuthentication(provider.first, token);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void remove(final IBinder token, final int fingerId, final int userId,
|
||||
final IFingerprintServiceReceiver receiver, final String opPackageName) {
|
||||
Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
|
||||
mFingerprint21.scheduleRemove(token, receiver, fingerId, userId, opPackageName);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for remove");
|
||||
return;
|
||||
}
|
||||
provider.second.scheduleRemove(provider.first, token, receiver, fingerId, userId,
|
||||
opPackageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -274,10 +346,14 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (args.length > 0 && "--proto".equals(args[0])) {
|
||||
mFingerprint21.dumpProto(fd);
|
||||
} else {
|
||||
mFingerprint21.dumpInternal(pw);
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FingerprintSensorProperties props : provider.getSensorProperties()) {
|
||||
if (args.length > 0 && "--proto".equals(args[0])) {
|
||||
provider.dumpProto(props.sensorId, fd);
|
||||
} else {
|
||||
provider.dumpInternal(props.sensorId, pw);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
@@ -294,11 +370,12 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (mFingerprint21 == null) {
|
||||
Slog.e(TAG, "No HAL, caller: " + opPackageName);
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName);
|
||||
return false;
|
||||
}
|
||||
return mFingerprint21.isHardwareDetected();
|
||||
return provider.second.isHardwareDetected(provider.first);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -311,7 +388,13 @@ public class FingerprintService extends SystemService {
|
||||
return;
|
||||
}
|
||||
|
||||
mFingerprint21.rename(fingerId, userId, name);
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for rename");
|
||||
return;
|
||||
}
|
||||
|
||||
provider.second.rename(provider.first, fingerId, userId, name);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -325,7 +408,8 @@ public class FingerprintService extends SystemService {
|
||||
if (userId != UserHandle.getCallingUserId()) {
|
||||
Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
|
||||
}
|
||||
return mFingerprint21.getEnrolledFingerprints(userId);
|
||||
|
||||
return FingerprintService.this.getEnrolledFingerprints(userId, opPackageName);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -339,19 +423,32 @@ public class FingerprintService extends SystemService {
|
||||
if (userId != UserHandle.getCallingUserId()) {
|
||||
Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
|
||||
}
|
||||
return mFingerprint21.getEnrolledFingerprints(userId).size() > 0;
|
||||
return !FingerprintService.this.getEnrolledFingerprints(userId, opPackageName)
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
return mFingerprint21.getLockoutModeForUser(userId);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getLockoutModeForUser");
|
||||
return LockoutTracker.LOCKOUT_NONE;
|
||||
}
|
||||
return provider.second.getLockoutModeForUser(provider.first, userId);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public long getAuthenticatorId(int userId) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
return mFingerprint21.getAuthenticatorId(userId);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getAuthenticatorId");
|
||||
return 0;
|
||||
}
|
||||
return provider.second.getAuthenticatorId(provider.first, userId);
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
@@ -359,12 +456,13 @@ public class FingerprintService extends SystemService {
|
||||
@Nullable byte [] hardwareAuthToken, String opPackageName) {
|
||||
Utils.checkPermission(getContext(), RESET_FINGERPRINT_LOCKOUT);
|
||||
|
||||
if (sensorId == mFingerprint21.getFingerprintSensorProperties().sensorId) {
|
||||
mFingerprint21.scheduleResetLockout(userId);
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName);
|
||||
return;
|
||||
}
|
||||
|
||||
Slog.w(TAG, "No matching sensor for resetLockout, sensorId: " + sensorId);
|
||||
provider.second.scheduleResetLockout(sensorId, userId, hardwareAuthToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -389,35 +487,52 @@ public class FingerprintService extends SystemService {
|
||||
public void initializeConfiguration(int sensorId, int strength) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
final Fingerprint21 fingerprint21;
|
||||
if ((Build.IS_USERDEBUG || Build.IS_ENG)
|
||||
&& getContext().getResources().getBoolean(R.bool.allow_test_udfps)
|
||||
&& Settings.Secure.getIntForUser(getContext().getContentResolver(),
|
||||
Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
|
||||
UserHandle.USER_CURRENT) != 0) {
|
||||
mFingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), sensorId,
|
||||
fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), sensorId,
|
||||
strength, mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
} else {
|
||||
mFingerprint21 = Fingerprint21.newInstance(getContext(), sensorId, strength,
|
||||
fingerprint21 = Fingerprint21.newInstance(getContext(), sensorId, strength,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
}
|
||||
mServiceProviders.add(fingerprint21);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerDown(int x, int y, float minor, float major) {
|
||||
public void onFingerDown(int sensorId, int x, int y, float minor, float major) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
mFingerprint21.onFingerDown(x, y, minor, major);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId);
|
||||
return;
|
||||
}
|
||||
provider.onFingerDown(sensorId, x, y, minor, major);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerUp() {
|
||||
public void onFingerUp(int sensorId) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
mFingerprint21.onFingerUp();
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId);
|
||||
return;
|
||||
}
|
||||
provider.onFingerUp(sensorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUdfpsOverlayController(IUdfpsOverlayController controller) {
|
||||
public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
mFingerprint21.setUdfpsOverlayController(controller);
|
||||
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
provider.setUdfpsOverlayController(controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,6 +542,7 @@ public class FingerprintService extends SystemService {
|
||||
mGestureAvailabilityDispatcher = new GestureAvailabilityDispatcher();
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
|
||||
mLockPatternUtils = new LockPatternUtils(context);
|
||||
mServiceProviders = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -434,6 +550,61 @@ public class FingerprintService extends SystemService {
|
||||
publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ServiceProvider getProviderForSensor(int sensorId) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
if (provider.containsSensor(sensorId)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* For devices with only a single provider, returns that provider. If no providers, or multiple
|
||||
* providers exist, returns null.
|
||||
*/
|
||||
@Nullable
|
||||
private Pair<Integer, ServiceProvider> getSingleProvider() {
|
||||
final List<FingerprintSensorProperties> properties = getSensorProperties();
|
||||
if (properties.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Theoretically we can just return the first provider, but maybe this is easier to
|
||||
// understand.
|
||||
final int sensorId = properties.get(0).sensorId;
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
if (provider.containsSensor(sensorId)) {
|
||||
return new Pair<>(sensorId, provider);
|
||||
}
|
||||
}
|
||||
|
||||
Slog.e(TAG, "Single sensor, but provider not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<FingerprintSensorProperties> getSensorProperties() {
|
||||
final List<FingerprintSensorProperties> properties = new ArrayList<>();
|
||||
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
properties.addAll(provider.getSensorProperties());
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getEnrolledFingerprints, caller: " + opPackageName);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return provider.second.getEnrolledFingerprints(provider.first, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for public API invocations to ensure that permissions, etc are granted/correct.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.IFingerprintServiceReceiver;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.os.IBinder;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Superset of features/functionalities that HALs provide to the rest of the framework. This is
|
||||
* more or less mapped to the public and private APIs that {@link FingerprintManager} provide, and
|
||||
* is used at the system server layer to provide easy mapping between request and provider.
|
||||
*
|
||||
* Note that providers support both single-sensor and multi-sensor HALs. In either case,
|
||||
* {@link FingerprintService} must ensure that providers are only requested to perform operations
|
||||
* on sensors that they own.
|
||||
*
|
||||
* For methods other than {@link #containsSensor(int)}, the caller must ensure that the sensorId
|
||||
* passed in is supported by the provider. For example,
|
||||
* if (serviceProvider.containsSensor(sensorId)) {
|
||||
* serviceProvider.operation(sensorId, ...);
|
||||
* }
|
||||
*
|
||||
* For operations that are supported by some providers but not others, clients are required
|
||||
* to check (e.g. via {@link FingerprintManager#getSensorProperties()}) to ensure that the code
|
||||
* path isn't taken. ServiceProviders will provide a no-op for unsupported operations to
|
||||
* fail safely.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public interface ServiceProvider {
|
||||
/**
|
||||
* Checks if the specified sensor is owned by this provider.
|
||||
*/
|
||||
boolean containsSensor(int sensorId);
|
||||
|
||||
@NonNull List<FingerprintSensorProperties> getSensorProperties();
|
||||
|
||||
void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken);
|
||||
|
||||
void scheduleGenerateChallenge(int sensorId, @NonNull IBinder token,
|
||||
@NonNull IFingerprintServiceReceiver receiver, String opPackageName);
|
||||
|
||||
void scheduleRevokeChallenge(int sensorId, @NonNull IBinder token,
|
||||
@NonNull String opPackageName);
|
||||
|
||||
void scheduleEnroll(int sensorId, @NonNull IBinder token, byte[] hardwareAuthToken, int userId,
|
||||
@NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
|
||||
@Nullable Surface surface);
|
||||
|
||||
void cancelEnrollment(int sensorId, @NonNull IBinder token);
|
||||
|
||||
void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
|
||||
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
|
||||
@Nullable Surface surface, int statsClient);
|
||||
|
||||
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
|
||||
int cookie, @NonNull ClientMonitorCallbackConverter callback,
|
||||
@NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard);
|
||||
|
||||
void startPreparedClient(int sensorId, int cookie);
|
||||
|
||||
void cancelAuthentication(int sensorId, @NonNull IBinder token);
|
||||
|
||||
void scheduleRemove(int sensorId, @NonNull IBinder token,
|
||||
@NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
|
||||
@NonNull String opPackageName);
|
||||
|
||||
boolean isHardwareDetected(int sensorId);
|
||||
|
||||
void rename(int sensorId, int fingerId, int userId, @NonNull String name);
|
||||
|
||||
@NonNull List<Fingerprint> getEnrolledFingerprints(int sensorId, int userId);
|
||||
|
||||
@LockoutTracker.LockoutMode int getLockoutModeForUser(int sensorId, int userId);
|
||||
|
||||
long getAuthenticatorId(int sensorId, int userId);
|
||||
|
||||
void onFingerDown(int sensorId, int x, int y, float minor, float major);
|
||||
|
||||
void onFingerUp(int sensorId);
|
||||
|
||||
void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller);
|
||||
|
||||
void dumpProto(int sensorId, @NonNull FileDescriptor fd);
|
||||
|
||||
void dumpInternal(int sensorId, @NonNull PrintWriter pw);
|
||||
}
|
||||
@@ -66,6 +66,7 @@ import com.android.server.biometrics.sensors.PerformanceTracker;
|
||||
import com.android.server.biometrics.sensors.RemovalConsumer;
|
||||
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
|
||||
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
|
||||
import com.android.server.biometrics.sensors.fingerprint.ServiceProvider;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@@ -83,14 +84,14 @@ import java.util.Map;
|
||||
* Supports a single instance of the {@link android.hardware.biometrics.fingerprint.V2_1} or
|
||||
* its extended minor versions.
|
||||
*/
|
||||
public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
|
||||
private static final String TAG = "Fingerprint21";
|
||||
private static final int ENROLL_TIMEOUT_SEC = 60;
|
||||
|
||||
final Context mContext;
|
||||
private final IActivityTaskManager mActivityTaskManager;
|
||||
private final FingerprintSensorProperties mSensorProperties;
|
||||
@NonNull private final FingerprintSensorProperties mSensorProperties;
|
||||
private final BiometricScheduler mScheduler;
|
||||
private final Handler mHandler;
|
||||
private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
@@ -435,9 +436,6 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
@Nullable IUdfpsOverlayController getUdfpsOverlayController() {
|
||||
return mUdfpsOverlayController;
|
||||
}
|
||||
@LockoutTracker.LockoutMode public int getLockoutModeForUser(int userId) {
|
||||
return mLockoutTracker.getLockoutModeForUser(userId);
|
||||
}
|
||||
|
||||
private void scheduleLoadAuthenticatorIds() {
|
||||
// Note that this can be performed on the scheduler (as opposed to being done immediately
|
||||
@@ -466,7 +464,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
* correct.
|
||||
*/
|
||||
private void scheduleUpdateActiveUserWithoutHandler(int targetUserId) {
|
||||
final boolean hasEnrolled = !getEnrolledFingerprints(targetUserId).isEmpty();
|
||||
final boolean hasEnrolled =
|
||||
!getEnrolledFingerprints(mSensorProperties.sensorId, targetUserId).isEmpty();
|
||||
final FingerprintUpdateActiveUserClient client =
|
||||
new FingerprintUpdateActiveUserClient(mContext, mLazyDaemon, targetUserId,
|
||||
mContext.getOpPackageName(), mSensorProperties.sensorId, mCurrentUserId,
|
||||
@@ -481,7 +480,21 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleResetLockout(int userId) {
|
||||
@Override
|
||||
public boolean containsSensor(int sensorId) {
|
||||
return mSensorProperties.sensorId == sensorId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public List<FingerprintSensorProperties> getSensorProperties() {
|
||||
final List<FingerprintSensorProperties> properties = new ArrayList<>();
|
||||
properties.add(mSensorProperties);
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) {
|
||||
// Fingerprint2.1 keeps track of lockout in the framework. Let's just do it on the handler
|
||||
// thread.
|
||||
mHandler.post(() -> {
|
||||
@@ -489,7 +502,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleGenerateChallenge(@NonNull IBinder token,
|
||||
@Override
|
||||
public void scheduleGenerateChallenge(int sensorId, @NonNull IBinder token,
|
||||
@NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName) {
|
||||
mHandler.post(() -> {
|
||||
final FingerprintGenerateChallengeClient client =
|
||||
@@ -500,7 +514,9 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleRevokeChallenge(@NonNull IBinder token, @NonNull String opPackageName) {
|
||||
@Override
|
||||
public void scheduleRevokeChallenge(int sensorId, @NonNull IBinder token,
|
||||
@NonNull String opPackageName) {
|
||||
mHandler.post(() -> {
|
||||
final FingerprintRevokeChallengeClient client = new FingerprintRevokeChallengeClient(
|
||||
mContext, mLazyDaemon, token, opPackageName, mSensorProperties.sensorId);
|
||||
@@ -508,7 +524,9 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleEnroll(@NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId,
|
||||
@Override
|
||||
public void scheduleEnroll(int sensorId, @NonNull IBinder token,
|
||||
@NonNull byte[] hardwareAuthToken, int userId,
|
||||
@NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
|
||||
@Nullable Surface surface) {
|
||||
mHandler.post(() -> {
|
||||
@@ -531,13 +549,15 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
});
|
||||
}
|
||||
|
||||
public void cancelEnrollment(@NonNull IBinder token) {
|
||||
@Override
|
||||
public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
|
||||
mHandler.post(() -> {
|
||||
mScheduler.cancelEnrollment(token);
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleFingerDetect(@NonNull IBinder token, int userId,
|
||||
@Override
|
||||
public void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
|
||||
@NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName,
|
||||
@Nullable Surface surface, int statsClient) {
|
||||
mHandler.post(() -> {
|
||||
@@ -552,8 +572,9 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleAuthenticate(@NonNull IBinder token, long operationId, int userId,
|
||||
int cookie, @NonNull ClientMonitorCallbackConverter listener,
|
||||
@Override
|
||||
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
|
||||
int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
|
||||
@NonNull String opPackageName, boolean restricted, int statsClient,
|
||||
boolean isKeyguard) {
|
||||
mHandler.post(() -> {
|
||||
@@ -569,19 +590,22 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
});
|
||||
}
|
||||
|
||||
public void startPreparedClient(int cookie) {
|
||||
@Override
|
||||
public void startPreparedClient(int sensorId, int cookie) {
|
||||
mHandler.post(() -> {
|
||||
mScheduler.startPreparedClient(cookie);
|
||||
});
|
||||
}
|
||||
|
||||
public void cancelAuthentication(@NonNull IBinder token) {
|
||||
@Override
|
||||
public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
|
||||
mHandler.post(() -> {
|
||||
mScheduler.cancelAuthentication(token);
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleRemove(@NonNull IBinder token,
|
||||
@Override
|
||||
public void scheduleRemove(int sensorId, @NonNull IBinder token,
|
||||
@NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
|
||||
@NonNull String opPackageName) {
|
||||
mHandler.post(() -> {
|
||||
@@ -599,7 +623,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
mHandler.post(() -> {
|
||||
scheduleUpdateActiveUserWithoutHandler(userId);
|
||||
|
||||
final List<Fingerprint> enrolledList = getEnrolledFingerprints(userId);
|
||||
final List<Fingerprint> enrolledList = getEnrolledFingerprints(
|
||||
mSensorProperties.sensorId, userId);
|
||||
final FingerprintInternalCleanupClient client = new FingerprintInternalCleanupClient(
|
||||
mContext, mLazyDaemon, userId, mContext.getOpPackageName(),
|
||||
mSensorProperties.sensorId, enrolledList, FingerprintUtils.getInstance(),
|
||||
@@ -608,30 +633,37 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isHardwareDetected() {
|
||||
@Override
|
||||
public boolean isHardwareDetected(int sensorId) {
|
||||
final IBiometricsFingerprint daemon = getDaemon();
|
||||
return daemon != null;
|
||||
}
|
||||
|
||||
@NonNull public FingerprintSensorProperties getFingerprintSensorProperties() {
|
||||
return mSensorProperties;
|
||||
}
|
||||
|
||||
public void rename(int fingerId, int userId, String name) {
|
||||
@Override
|
||||
public void rename(int sensorId, int fingerId, int userId, @NonNull String name) {
|
||||
mHandler.post(() -> {
|
||||
FingerprintUtils.getInstance().renameBiometricForUser(mContext, userId, fingerId, name);
|
||||
});
|
||||
}
|
||||
|
||||
public List<Fingerprint> getEnrolledFingerprints(int userId) {
|
||||
@Override
|
||||
@NonNull
|
||||
public List<Fingerprint> getEnrolledFingerprints(int sensorId, int userId) {
|
||||
return FingerprintUtils.getInstance().getBiometricsForUser(mContext, userId);
|
||||
}
|
||||
|
||||
public long getAuthenticatorId(int userId) {
|
||||
@Override
|
||||
@LockoutTracker.LockoutMode public int getLockoutModeForUser(int sensorId, int userId) {
|
||||
return mLockoutTracker.getLockoutModeForUser(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAuthenticatorId(int sensorId, int userId) {
|
||||
return mAuthenticatorIds.get(userId);
|
||||
}
|
||||
|
||||
public void onFingerDown(int x, int y, float minor, float major) {
|
||||
@Override
|
||||
public void onFingerDown(int sensorId, int x, int y, float minor, float major) {
|
||||
final ClientMonitor<?> client = mScheduler.getCurrentClient();
|
||||
if (!(client instanceof Udfps)) {
|
||||
Slog.w(TAG, "onFingerDown received during client: " + client);
|
||||
@@ -641,7 +673,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
udfps.onFingerDown(x, y, minor, major);
|
||||
}
|
||||
|
||||
public void onFingerUp() {
|
||||
@Override
|
||||
public void onFingerUp(int sensorId) {
|
||||
final ClientMonitor<?> client = mScheduler.getCurrentClient();
|
||||
if (!(client instanceof Udfps)) {
|
||||
Slog.w(TAG, "onFingerDown received during client: " + client);
|
||||
@@ -651,11 +684,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
udfps.onFingerUp();
|
||||
}
|
||||
|
||||
public void setUdfpsOverlayController(IUdfpsOverlayController controller) {
|
||||
@Override
|
||||
public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
|
||||
mUdfpsOverlayController = controller;
|
||||
}
|
||||
|
||||
public void dumpProto(FileDescriptor fd) {
|
||||
@Override
|
||||
public void dumpProto(int sensorId, FileDescriptor fd) {
|
||||
PerformanceTracker tracker =
|
||||
PerformanceTracker.getInstanceForSensorId(mSensorProperties.sensorId);
|
||||
|
||||
@@ -695,7 +730,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient {
|
||||
tracker.clear();
|
||||
}
|
||||
|
||||
public void dumpInternal(@NonNull PrintWriter pw) {
|
||||
@Override
|
||||
public void dumpInternal(int sensorId, @NonNull PrintWriter pw) {
|
||||
PerformanceTracker performanceTracker =
|
||||
PerformanceTracker.getInstanceForSensorId(mSensorProperties.sensorId);
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
@@ -397,8 +398,9 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
|
||||
// Schedule this only after we invoke onClientFinished for the previous client, so that
|
||||
// internal preemption logic is not run.
|
||||
mFingerprint21.scheduleAuthenticate(token, operationId, user, cookie,
|
||||
listener, opPackageName, restricted, statsClient, isKeyguard);
|
||||
mFingerprint21.scheduleAuthenticate(mFingerprint21.mSensorProperties.sensorId, token,
|
||||
operationId, user, cookie, listener, opPackageName, restricted, statsClient,
|
||||
isKeyguard);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,12 +453,14 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public FingerprintSensorProperties getFingerprintSensorProperties() {
|
||||
return mSensorProperties;
|
||||
public List<FingerprintSensorProperties> getSensorProperties() {
|
||||
final List<FingerprintSensorProperties> properties = new ArrayList<>();
|
||||
properties.add(mSensorProperties);
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerDown(int x, int y, float minor, float major) {
|
||||
public void onFingerDown(int sensorId, int x, int y, float minor, float major) {
|
||||
mHandler.post(() -> {
|
||||
Slog.d(TAG, "onFingerDown");
|
||||
final AuthenticationConsumer lastAuthenticatedConsumer =
|
||||
@@ -503,7 +507,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerUp() {
|
||||
public void onFingerUp(int sensorId) {
|
||||
mHandler.post(() -> {
|
||||
Slog.d(TAG, "onFingerUp");
|
||||
|
||||
@@ -558,7 +562,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
// Things can happen before SysUI loads and sets the controller.
|
||||
if (controller != null) {
|
||||
Slog.d(TAG, "setDebugMessage: " + message);
|
||||
controller.setDebugMessage(message);
|
||||
controller.setDebugMessage(mSensorProperties.sensorId, message);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when sending message: " + message, e);
|
||||
|
||||
@@ -79,7 +79,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
|
||||
if (authenticated) {
|
||||
resetFailedAttempts(getTargetUserId());
|
||||
UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
mCallback.onClientFinished(this, true /* success */);
|
||||
} else {
|
||||
final @LockoutTracker.LockoutMode int lockoutMode =
|
||||
@@ -92,7 +92,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
// Send the error, but do not invoke the FinishCallback yet. Since lockout is not
|
||||
// controlled by the HAL, the framework must stop the sensor before finishing the
|
||||
// client.
|
||||
UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
onErrorInternal(errorCode, 0 /* vendorCode */, false /* finish */);
|
||||
cancel();
|
||||
}
|
||||
@@ -111,7 +111,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
try {
|
||||
// GroupId was never used. In fact, groupId is always the same as userId.
|
||||
getFreshDaemon().authenticate(mOperationId, getTargetUserId());
|
||||
@@ -119,14 +119,14 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
Slog.e(TAG, "Remote exception when requesting auth", e);
|
||||
onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
|
||||
0 /* vendorCode */);
|
||||
UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
mCallback.onClientFinished(this, false /* success */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopHalOperation() {
|
||||
UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
try {
|
||||
getFreshDaemon().cancel();
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -61,7 +61,7 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
|
||||
|
||||
@Override
|
||||
protected void stopHalOperation() {
|
||||
UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
try {
|
||||
getFreshDaemon().cancel();
|
||||
} catch (RemoteException e) {
|
||||
@@ -80,14 +80,14 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
try {
|
||||
getFreshDaemon().authenticate(0 /* operationId */, getTargetUserId());
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when requesting auth", e);
|
||||
onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
|
||||
0 /* vendorCode */);
|
||||
UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
mCallback.onClientFinished(this, false /* success */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
try {
|
||||
// GroupId was never used. In fact, groupId is always the same as userId.
|
||||
getFreshDaemon().enroll(mHardwareAuthToken, getTargetUserId(), mTimeoutSec);
|
||||
@@ -78,14 +78,14 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
|
||||
Slog.e(TAG, "Remote exception when requesting enroll", e);
|
||||
onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
|
||||
0 /* vendorCode */);
|
||||
UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
mCallback.onClientFinished(this, false /* success */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopHalOperation() {
|
||||
UdfpsHelper.hideUdfpsOverlay(mUdfpsOverlayController);
|
||||
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
try {
|
||||
getFreshDaemon().cancel();
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -62,23 +62,25 @@ public class UdfpsHelper {
|
||||
}
|
||||
}
|
||||
|
||||
static void showUdfpsOverlay(@Nullable IUdfpsOverlayController udfpsOverlayController) {
|
||||
static void showUdfpsOverlay(int sensorId,
|
||||
@Nullable IUdfpsOverlayController udfpsOverlayController) {
|
||||
if (udfpsOverlayController == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
udfpsOverlayController.showUdfpsOverlay();
|
||||
udfpsOverlayController.showUdfpsOverlay(sensorId);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when showing the UDFPS overlay", e);
|
||||
}
|
||||
}
|
||||
|
||||
static void hideUdfpsOverlay(@Nullable IUdfpsOverlayController udfpsOverlayController) {
|
||||
static void hideUdfpsOverlay(int sensorId,
|
||||
@Nullable IUdfpsOverlayController udfpsOverlayController) {
|
||||
if (udfpsOverlayController == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
udfpsOverlayController.hideUdfpsOverlay();
|
||||
udfpsOverlayController.hideUdfpsOverlay(sensorId);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when hiding the UDFPS overlay", e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user