Merge "Revert "Copy startup & callback mechanism from fingerprint to face service.""
This commit is contained in:
@@ -29,7 +29,6 @@ import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.biometrics.BiometricConstants;
|
||||
import android.hardware.biometrics.BiometricFaceConstants;
|
||||
import android.hardware.biometrics.BiometricStateListener;
|
||||
import android.hardware.biometrics.CryptoObject;
|
||||
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
|
||||
import android.os.Binder;
|
||||
@@ -674,45 +673,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards BiometricStateListener to FaceService.
|
||||
*
|
||||
* @param listener new BiometricStateListener being added
|
||||
* @hide
|
||||
*/
|
||||
public void registerBiometricStateListener(@NonNull BiometricStateListener listener) {
|
||||
try {
|
||||
mService.registerBiometricStateListener(listener);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a callback that gets called when the service registers all of the face
|
||||
* authenticators (HALs).
|
||||
*
|
||||
* If the face authenticators are already registered when the callback is added, the
|
||||
* callback is invoked immediately.
|
||||
*
|
||||
* The callback is automatically removed after it's invoked.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||
public void addAuthenticatorsRegisteredCallback(
|
||||
IFaceAuthenticatorsRegisteredCallback callback) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.addAuthenticatorsRegisteredCallback(callback);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
} else {
|
||||
Slog.w(TAG, "addAuthenticatorsRegisteredCallback(): Service not connected!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 android.hardware.face;
|
||||
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Callback to notify FaceManager that FaceService has registered all of the
|
||||
* face authenticators (HALs).
|
||||
* See {@link android.hardware.face.IFaceService#registerAuthenticators}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IFaceAuthenticatorsRegisteredCallback {
|
||||
/**
|
||||
* Notifies FaceManager that all of the face authenticators have been registered.
|
||||
*
|
||||
* @param sensors A consolidated list of sensor properties for all of the authenticators.
|
||||
*/
|
||||
void onAllAuthenticatorsRegistered(in List<FaceSensorPropertiesInternal> sensors);
|
||||
}
|
||||
@@ -17,11 +17,9 @@ package android.hardware.face;
|
||||
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
|
||||
import android.hardware.biometrics.IBiometricStateListener;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.ITestSessionCallback;
|
||||
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.face.IFaceServiceReceiver;
|
||||
import android.hardware.face.Face;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
@@ -165,11 +163,4 @@ interface IFaceService {
|
||||
// hidlSensors must be non-null and empty. See AuthService.java
|
||||
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
|
||||
void registerAuthenticators(in List<FaceSensorPropertiesInternal> hidlSensors);
|
||||
|
||||
// Adds a callback which gets called when the service registers all of the face
|
||||
// authenticators. The callback is automatically removed after it's invoked.
|
||||
void addAuthenticatorsRegisteredCallback(IFaceAuthenticatorsRegisteredCallback callback);
|
||||
|
||||
// Registers BiometricStateListener.
|
||||
void registerBiometricStateListener(IBiometricStateListener listener);
|
||||
}
|
||||
|
||||
@@ -202,10 +202,8 @@ interface IFingerprintService {
|
||||
void setSidefpsController(in ISidefpsController controller);
|
||||
|
||||
// Registers BiometricStateListener.
|
||||
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
|
||||
void registerBiometricStateListener(IBiometricStateListener listener);
|
||||
|
||||
// Sends a power button pressed event to all listeners.
|
||||
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
|
||||
oneway void onPowerPressed();
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.biometrics.BiometricFingerprintConstants;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.BiometricSourceType;
|
||||
@@ -2019,13 +2018,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
// in case authenticators aren't registered yet at this point:
|
||||
mAuthController.addCallback(new AuthController.Callback() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
@BiometricAuthenticator.Modality int modality) {
|
||||
public void onAllAuthenticatorsRegistered() {
|
||||
mainExecutor.execute(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) {
|
||||
public void onEnrollmentsChanged() {
|
||||
mainExecutor.execute(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
|
||||
|
||||
import static com.android.keyguard.LockIconView.ICON_FINGERPRINT;
|
||||
@@ -30,7 +29,6 @@ import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.AnimatedStateListDrawable;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.biometrics.BiometricSourceType;
|
||||
import android.os.Process;
|
||||
import android.os.VibrationAttributes;
|
||||
@@ -703,17 +701,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
|
||||
|
||||
private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) {
|
||||
if (modality == TYPE_FINGERPRINT) {
|
||||
updateUdfpsConfig();
|
||||
}
|
||||
public void onAllAuthenticatorsRegistered() {
|
||||
updateUdfpsConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) {
|
||||
if (modality == TYPE_FINGERPRINT) {
|
||||
updateUdfpsConfig();
|
||||
}
|
||||
public void onEnrollmentsChanged() {
|
||||
updateUdfpsConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -46,7 +46,6 @@ import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
@@ -157,6 +156,25 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
}
|
||||
};
|
||||
|
||||
private final IFingerprintAuthenticatorsRegisteredCallback
|
||||
mFingerprintAuthenticatorsRegisteredCallback =
|
||||
new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
mHandler.post(() -> handleAllFingerprintAuthenticatorsRegistered(sensors));
|
||||
}
|
||||
};
|
||||
|
||||
private final BiometricStateListener mBiometricStateListener =
|
||||
new BiometricStateListener() {
|
||||
@Override
|
||||
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
|
||||
mHandler.post(
|
||||
() -> handleEnrollmentsChanged(userId, sensorId, hasEnrollments));
|
||||
}
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@@ -231,8 +249,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
mExecution.assertIsMainThread();
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "handleAllFingerprintAuthenticatorsRegistered | sensors: "
|
||||
+ Arrays.toString(sensors.toArray()));
|
||||
Log.d(TAG, "handleAllAuthenticatorsRegistered | sensors: " + Arrays.toString(
|
||||
sensors.toArray()));
|
||||
}
|
||||
mAllFingerprintAuthenticatorsRegistered = true;
|
||||
mFpProps = sensors;
|
||||
@@ -274,42 +292,15 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
mSidefpsController = mSidefpsControllerFactory.get();
|
||||
}
|
||||
|
||||
mFingerprintManager.registerBiometricStateListener(new BiometricStateListener() {
|
||||
@Override
|
||||
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
|
||||
mHandler.post(() -> handleEnrollmentsChanged(
|
||||
TYPE_FINGERPRINT, userId, sensorId, hasEnrollments));
|
||||
}
|
||||
});
|
||||
mFingerprintManager.registerBiometricStateListener(mBiometricStateListener);
|
||||
updateFingerprintLocation();
|
||||
|
||||
for (Callback cb : mCallbacks) {
|
||||
cb.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT);
|
||||
cb.onAllAuthenticatorsRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAllFaceAuthenticatorsRegistered(List<FaceSensorPropertiesInternal> sensors) {
|
||||
mExecution.assertIsMainThread();
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "handleAllFaceAuthenticatorsRegistered | sensors: " + Arrays.toString(
|
||||
sensors.toArray()));
|
||||
}
|
||||
|
||||
mFaceManager.registerBiometricStateListener(new BiometricStateListener() {
|
||||
@Override
|
||||
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
|
||||
mHandler.post(() -> handleEnrollmentsChanged(
|
||||
TYPE_FACE, userId, sensorId, hasEnrollments));
|
||||
}
|
||||
});
|
||||
|
||||
for (Callback cb : mCallbacks) {
|
||||
cb.onAllAuthenticatorsRegistered(TYPE_FACE);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEnrollmentsChanged(@Modality int modality, int userId, int sensorId,
|
||||
boolean hasEnrollments) {
|
||||
private void handleEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
|
||||
mExecution.assertIsMainThread();
|
||||
Log.d(TAG, "handleEnrollmentsChanged, userId: " + userId + ", sensorId: " + sensorId
|
||||
+ ", hasEnrollments: " + hasEnrollments);
|
||||
@@ -323,7 +314,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
}
|
||||
}
|
||||
for (Callback cb : mCallbacks) {
|
||||
cb.onEnrollmentsChanged(modality);
|
||||
cb.onEnrollmentsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,26 +700,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
|
||||
if (mFingerprintManager != null) {
|
||||
mFingerprintManager.addAuthenticatorsRegisteredCallback(
|
||||
new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
mHandler.post(() ->
|
||||
handleAllFingerprintAuthenticatorsRegistered(sensors));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mFaceManager != null) {
|
||||
mFaceManager.addAuthenticatorsRegisteredCallback(
|
||||
new IFaceAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FaceSensorPropertiesInternal> sensors) {
|
||||
mHandler.post(() ->
|
||||
handleAllFaceAuthenticatorsRegistered(sensors));
|
||||
}
|
||||
}
|
||||
);
|
||||
mFingerprintAuthenticatorsRegisteredCallback);
|
||||
}
|
||||
|
||||
mStableDisplaySize = mDisplayManager.getStableDisplaySize();
|
||||
@@ -1144,13 +1116,13 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
|
||||
* Called when authenticators are registered. If authenticators are already
|
||||
* registered before this call, this callback will never be triggered.
|
||||
*/
|
||||
default void onAllAuthenticatorsRegistered(@Modality int modality) {}
|
||||
default void onAllAuthenticatorsRegistered() {}
|
||||
|
||||
/**
|
||||
* Called when enrollments have changed. This is called after boot and on changes to
|
||||
* Called when UDFPS enrollments have changed. This is called after boot and on changes to
|
||||
* enrollment.
|
||||
*/
|
||||
default void onEnrollmentsChanged(@Modality int modality) {}
|
||||
default void onEnrollmentsChanged() {}
|
||||
|
||||
/**
|
||||
* Called when the biometric prompt starts showing.
|
||||
|
||||
@@ -308,7 +308,7 @@ class AuthRippleController @Inject constructor(
|
||||
|
||||
private val authControllerCallback =
|
||||
object : AuthController.Callback {
|
||||
override fun onAllAuthenticatorsRegistered(modality: Int) {
|
||||
override fun onAllAuthenticatorsRegistered() {
|
||||
updateUdfpsDependentParams()
|
||||
updateSensorLocation()
|
||||
}
|
||||
|
||||
@@ -16,15 +16,12 @@
|
||||
|
||||
package com.android.systemui.doze;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
|
||||
import static com.android.systemui.doze.DozeMachine.State.DOZE;
|
||||
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
|
||||
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
|
||||
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING;
|
||||
import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
|
||||
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
@@ -235,17 +232,13 @@ public class DozeScreenState implements DozeMachine.Part {
|
||||
|
||||
private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) {
|
||||
if (modality == TYPE_FINGERPRINT) {
|
||||
updateUdfpsController();
|
||||
}
|
||||
public void onAllAuthenticatorsRegistered() {
|
||||
updateUdfpsController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) {
|
||||
if (modality == TYPE_FINGERPRINT) {
|
||||
updateUdfpsController();
|
||||
}
|
||||
public void onEnrollmentsChanged() {
|
||||
updateUdfpsController();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.systemui.doze;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
|
||||
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_QUICK_PICKUP;
|
||||
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
|
||||
import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_DISPLAY;
|
||||
@@ -31,7 +29,6 @@ import android.hardware.Sensor;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.TriggerEvent;
|
||||
import android.hardware.TriggerEventListener;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.display.AmbientDisplayConfiguration;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
@@ -838,17 +835,13 @@ public class DozeSensors {
|
||||
|
||||
private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) {
|
||||
if (modality == TYPE_FINGERPRINT) {
|
||||
updateUdfpsEnrolled();
|
||||
}
|
||||
public void onAllAuthenticatorsRegistered() {
|
||||
updateUdfpsEnrolled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) {
|
||||
if (modality == TYPE_FINGERPRINT) {
|
||||
updateUdfpsEnrolled();
|
||||
}
|
||||
public void onEnrollmentsChanged() {
|
||||
updateUdfpsEnrolled();
|
||||
}
|
||||
|
||||
private void updateUdfpsEnrolled() {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
|
||||
import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
|
||||
import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
|
||||
@@ -1007,7 +1006,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
|
||||
// WHEN udfps is now enrolled
|
||||
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
|
||||
callback.onEnrollmentsChanged(TYPE_FINGERPRINT);
|
||||
callback.onEnrollmentsChanged();
|
||||
|
||||
// THEN isUdfspEnrolled is TRUE
|
||||
assertThat(mKeyguardUpdateMonitor.isUdfpsEnrolled()).isTrue();
|
||||
|
||||
@@ -60,9 +60,6 @@ import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.face.FaceSensorProperties;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
@@ -157,9 +154,7 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private InteractionJankMonitor mInteractionJankMonitor;
|
||||
@Captor
|
||||
ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mFpAuthenticatorsRegisteredCaptor;
|
||||
@Captor
|
||||
ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mFaceAuthenticatorsRegisteredCaptor;
|
||||
ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
|
||||
@Captor
|
||||
ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor;
|
||||
@Captor
|
||||
@@ -198,38 +193,25 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
when(mDisplayManager.getStableDisplaySize()).thenReturn(new Point());
|
||||
|
||||
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||
when(mFaceManager.isHardwareDetected()).thenReturn(true);
|
||||
|
||||
final List<ComponentInfoInternal> fpComponentInfo = List.of(
|
||||
new ComponentInfoInternal("faceSensor" /* componentId */,
|
||||
"vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
|
||||
"00000001" /* serialNumber */, "" /* softwareVersion */));
|
||||
final List<ComponentInfoInternal> faceComponentInfo = List.of(
|
||||
new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
|
||||
"" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
|
||||
"vendor/version/revision" /* softwareVersion */));
|
||||
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
|
||||
componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */,
|
||||
"vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
|
||||
"00000001" /* serialNumber */, "" /* softwareVersion */));
|
||||
componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
|
||||
"" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
|
||||
"vendor/version/revision" /* softwareVersion */));
|
||||
|
||||
final List<FingerprintSensorPropertiesInternal> fpProps = List.of(
|
||||
new FingerprintSensorPropertiesInternal(
|
||||
1 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
1 /* maxEnrollmentsPerUser */,
|
||||
fpComponentInfo,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
true /* resetLockoutRequireHardwareAuthToken */));
|
||||
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(fpProps);
|
||||
|
||||
final List<FaceSensorPropertiesInternal> faceProps = List.of(
|
||||
new FaceSensorPropertiesInternal(
|
||||
2 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
1 /* maxEnrollmentsPerUser */,
|
||||
fpComponentInfo,
|
||||
FaceSensorProperties.TYPE_RGB,
|
||||
true /* supportsFaceDetection */,
|
||||
true /* supportsSelfIllumination */,
|
||||
true /* resetLockoutRequireHardwareAuthToken */));
|
||||
when(mFaceManager.getSensorPropertiesInternal()).thenReturn(faceProps);
|
||||
FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal(
|
||||
1 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
1 /* maxEnrollmentsPerUser */,
|
||||
componentInfo,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
true /* resetLockoutRequireHardwareAuthToken */);
|
||||
List<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
|
||||
props.add(prop);
|
||||
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props);
|
||||
|
||||
mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue,
|
||||
mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager,
|
||||
@@ -237,15 +219,12 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
|
||||
mAuthController.start();
|
||||
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
|
||||
mFpAuthenticatorsRegisteredCaptor.capture());
|
||||
verify(mFaceManager).addAuthenticatorsRegisteredCallback(
|
||||
mFaceAuthenticatorsRegisteredCaptor.capture());
|
||||
mAuthenticatorsRegisteredCaptor.capture());
|
||||
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
|
||||
|
||||
mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(fpProps);
|
||||
mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(faceProps);
|
||||
mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props);
|
||||
|
||||
// Ensures that the operations posted on the handler get executed.
|
||||
mTestableLooper.processAllMessages();
|
||||
@@ -258,7 +237,6 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
throws RemoteException {
|
||||
// This test is sensitive to prior FingerprintManager interactions.
|
||||
reset(mFingerprintManager);
|
||||
reset(mFaceManager);
|
||||
|
||||
// This test requires an uninitialized AuthController.
|
||||
AuthController authController = new TestableAuthController(mContextSpy, mExecution,
|
||||
@@ -268,27 +246,21 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
authController.start();
|
||||
|
||||
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
|
||||
mFpAuthenticatorsRegisteredCaptor.capture());
|
||||
verify(mFaceManager).addAuthenticatorsRegisteredCallback(
|
||||
mFaceAuthenticatorsRegisteredCaptor.capture());
|
||||
mAuthenticatorsRegisteredCaptor.capture());
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mFingerprintManager, never()).registerBiometricStateListener(any());
|
||||
verify(mFaceManager, never()).registerBiometricStateListener(any());
|
||||
|
||||
mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of());
|
||||
mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of());
|
||||
mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>());
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mFingerprintManager).registerBiometricStateListener(any());
|
||||
verify(mFaceManager).registerBiometricStateListener(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotCrash_afterEnrollmentsChangedForUnknownSensor() throws RemoteException {
|
||||
// This test is sensitive to prior FingerprintManager interactions.
|
||||
reset(mFingerprintManager);
|
||||
reset(mFaceManager);
|
||||
|
||||
// This test requires an uninitialized AuthController.
|
||||
AuthController authController = new TestableAuthController(mContextSpy, mExecution,
|
||||
@@ -298,25 +270,18 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
authController.start();
|
||||
|
||||
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
|
||||
mFpAuthenticatorsRegisteredCaptor.capture());
|
||||
verify(mFaceManager).addAuthenticatorsRegisteredCallback(
|
||||
mFaceAuthenticatorsRegisteredCaptor.capture());
|
||||
mAuthenticatorsRegisteredCaptor.capture());
|
||||
|
||||
// Emulates a device with no authenticators (empty list).
|
||||
mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of());
|
||||
mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of());
|
||||
mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>());
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mFingerprintManager).registerBiometricStateListener(
|
||||
mBiometricStateCaptor.capture());
|
||||
verify(mFaceManager).registerBiometricStateListener(
|
||||
mBiometricStateCaptor.capture());
|
||||
|
||||
// Enrollments changed for an unknown sensor.
|
||||
for (BiometricStateListener listener : mBiometricStateCaptor.getAllValues()) {
|
||||
listener.onEnrollmentsChanged(0 /* userId */,
|
||||
0xbeef /* sensorId */, true /* hasEnrollments */);
|
||||
}
|
||||
mBiometricStateCaptor.getValue().onEnrollmentsChanged(0 /* userId */,
|
||||
0xbeef /* sensorId */, true /* hasEnrollments */);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
// Nothing should crash.
|
||||
@@ -862,3 +827,4 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.systemui.doze;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
|
||||
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_TAP;
|
||||
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
|
||||
import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
|
||||
@@ -414,7 +412,7 @@ public class DozeSensorsTest extends SysuiTestCase {
|
||||
|
||||
// WHEN enrollment changes to TRUE
|
||||
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
|
||||
mAuthControllerCallback.onEnrollmentsChanged(TYPE_FINGERPRINT);
|
||||
mAuthControllerCallback.onEnrollmentsChanged();
|
||||
|
||||
// THEN mConfigured = TRUE
|
||||
assertTrue(triggerSensor.mConfigured);
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.systemui.keyguard;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||
import static com.android.keyguard.LockIconView.ICON_LOCK;
|
||||
import static com.android.keyguard.LockIconView.ICON_UNLOCK;
|
||||
@@ -221,7 +219,7 @@ public class LockIconViewControllerTest extends SysuiTestCase {
|
||||
Pair<Float, PointF> udfps = setupUdfps();
|
||||
|
||||
// WHEN all authenticators are registered
|
||||
mAuthControllerCallback.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT);
|
||||
mAuthControllerCallback.onAllAuthenticatorsRegistered();
|
||||
mDelayableExecutor.runAllReady();
|
||||
|
||||
// THEN lock icon view location is updated with the same coordinates as auth controller vals
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Common attributes for all biometric service providers.
|
||||
*
|
||||
* @param <T> Internal settings type.
|
||||
*/
|
||||
public interface BiometricServiceProvider<T extends SensorPropertiesInternal> {
|
||||
|
||||
/** Checks if the specified sensor is owned by this provider. */
|
||||
boolean containsSensor(int sensorId);
|
||||
|
||||
/** All sensor properties. */
|
||||
@NonNull
|
||||
List<T> getSensorProperties();
|
||||
|
||||
/** Properties for the given sensor id. */
|
||||
@NonNull
|
||||
T getSensorProperties(int sensorId);
|
||||
|
||||
boolean isHardwareDetected(int sensorId);
|
||||
|
||||
/** If the user has any enrollments for the given sensor. */
|
||||
boolean hasEnrollments(int sensorId, int userId);
|
||||
|
||||
long getAuthenticatorId(int sensorId, int userId);
|
||||
|
||||
@LockoutTracker.LockoutMode
|
||||
int getLockoutModeForUser(int sensorId, int userId);
|
||||
|
||||
void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
|
||||
boolean clearSchedulerBuffer);
|
||||
|
||||
void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);
|
||||
|
||||
void dumpInternal(int sensorId, @NonNull PrintWriter pw);
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.os.Handler;
|
||||
import android.os.IInterface;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.ServiceThread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Container for all BiometricServiceProvider implementations.
|
||||
*
|
||||
* @param <T> The service provider type.
|
||||
* @param <P> The internal properties type.
|
||||
* @param <C> The registration callback for {@link #invokeRegisteredCallback(IInterface, List)}.
|
||||
*/
|
||||
public abstract class BiometricServiceRegistry<T extends BiometricServiceProvider<P>,
|
||||
P extends SensorPropertiesInternal,
|
||||
C extends IInterface> {
|
||||
|
||||
private static final String TAG = "BiometricServiceRegistry";
|
||||
|
||||
// Volatile so they can be read without a lock once all services are registered.
|
||||
// But, ideally remove this and provide immutable copies via the callback instead.
|
||||
@Nullable
|
||||
private volatile List<T> mServiceProviders;
|
||||
@Nullable
|
||||
private volatile List<P> mAllProps;
|
||||
|
||||
@NonNull
|
||||
private final Supplier<IBiometricService> mBiometricServiceSupplier;
|
||||
@NonNull
|
||||
private final RemoteCallbackList<C> mRegisteredCallbacks = new RemoteCallbackList<>();
|
||||
|
||||
public BiometricServiceRegistry(@NonNull Supplier<IBiometricService> biometricSupplier) {
|
||||
mBiometricServiceSupplier = biometricSupplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an implementation by creating a new authenticator and initializing it via
|
||||
* {@link IBiometricService#registerAuthenticator(int, int, int, IBiometricAuthenticator)}
|
||||
* using the given properties.
|
||||
*
|
||||
* @param service service to register with
|
||||
* @param props internal properties to initialize the authenticator
|
||||
*/
|
||||
protected abstract void registerService(@NonNull IBiometricService service, @NonNull P props);
|
||||
|
||||
/**
|
||||
* Invoke the callback to notify clients that all authenticators have been registered.
|
||||
*
|
||||
* @param callback callback to invoke
|
||||
* @param allProps properties of all authenticators
|
||||
*/
|
||||
protected abstract void invokeRegisteredCallback(@NonNull C callback,
|
||||
@NonNull List<P> allProps) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Register all authenticators in a background thread.
|
||||
*
|
||||
* @param serviceProvider Supplier function that will be invoked on the background thread.
|
||||
*/
|
||||
public void registerAll(Supplier<List<T>> serviceProvider) {
|
||||
// Some HAL might not be started before the system service and will cause the code below
|
||||
// to wait, and some of the operations below might take a significant amount of time to
|
||||
// complete (calls to the HALs). To avoid blocking the rest of system server we put
|
||||
// this on a background thread.
|
||||
final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
|
||||
true /* allowIo */);
|
||||
thread.start();
|
||||
final Handler handler = new Handler(thread.getLooper());
|
||||
handler.post(() -> registerAllInBackground(serviceProvider));
|
||||
thread.quitSafely();
|
||||
}
|
||||
|
||||
/** Register authenticators now, only called by {@link #registerAll(Supplier).} */
|
||||
@VisibleForTesting
|
||||
public void registerAllInBackground(Supplier<List<T>> serviceProvider) {
|
||||
List<T> providers = serviceProvider.get();
|
||||
if (providers == null) {
|
||||
providers = new ArrayList<>();
|
||||
}
|
||||
|
||||
final IBiometricService biometricService = mBiometricServiceSupplier.get();
|
||||
if (biometricService == null) {
|
||||
throw new IllegalStateException("biometric service cannot be null");
|
||||
}
|
||||
|
||||
// Register each sensor individually with BiometricService
|
||||
final List<P> allProps = new ArrayList<>();
|
||||
for (T provider : providers) {
|
||||
final List<P> props = provider.getSensorProperties();
|
||||
for (P prop : props) {
|
||||
registerService(biometricService, prop);
|
||||
}
|
||||
allProps.addAll(props);
|
||||
}
|
||||
|
||||
finishRegistration(providers, allProps);
|
||||
}
|
||||
|
||||
private synchronized void finishRegistration(
|
||||
@NonNull List<T> providers, @NonNull List<P> allProps) {
|
||||
mServiceProviders = Collections.unmodifiableList(providers);
|
||||
mAllProps = Collections.unmodifiableList(allProps);
|
||||
broadcastAllAuthenticatorsRegistered();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback that will be invoked once the work from {@link #registerAll(Supplier)}
|
||||
* has finished registering all providers (executes immediately if already done).
|
||||
*
|
||||
* @param callback registration callback
|
||||
*/
|
||||
public synchronized void addAllRegisteredCallback(@Nullable C callback) {
|
||||
if (callback == null) {
|
||||
Slog.e(TAG, "addAllRegisteredCallback, callback is null");
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean registered = mRegisteredCallbacks.register(callback);
|
||||
final boolean allRegistered = mServiceProviders != null;
|
||||
if (registered && allRegistered) {
|
||||
broadcastAllAuthenticatorsRegistered();
|
||||
} else if (!registered) {
|
||||
Slog.e(TAG, "addAllRegisteredCallback failed to register callback");
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void broadcastAllAuthenticatorsRegistered() {
|
||||
final int n = mRegisteredCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
final C cb = mRegisteredCallbacks.getBroadcastItem(i);
|
||||
try {
|
||||
invokeRegisteredCallback(cb, mAllProps);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception in broadcastAllAuthenticatorsRegistered", e);
|
||||
} finally {
|
||||
mRegisteredCallbacks.unregister(cb);
|
||||
}
|
||||
}
|
||||
mRegisteredCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of registered providers.
|
||||
*
|
||||
* Undefined until {@link #registerAll(Supplier)} has fired the completion callback.
|
||||
*/
|
||||
@NonNull
|
||||
public List<T> getProviders() {
|
||||
return mServiceProviders != null ? mServiceProviders : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the provider for given sensor id or null if not registered.
|
||||
*
|
||||
* Undefined until {@link #registerAll(Supplier)} has fired the completion callback.
|
||||
*/
|
||||
@Nullable
|
||||
public T getProviderForSensor(int sensorId) {
|
||||
if (mServiceProviders != null) {
|
||||
for (T 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.
|
||||
*
|
||||
* Undefined until {@link #registerAll(Supplier)} has fired the completion callback.
|
||||
*/
|
||||
@Nullable
|
||||
public Pair<Integer, T> getSingleProvider() {
|
||||
if (mAllProps == null || mAllProps.size() != 1) {
|
||||
Slog.e(TAG, "Multiple sensors found: " + mAllProps.size());
|
||||
return null;
|
||||
}
|
||||
|
||||
final int sensorId = mAllProps.get(0).sensorId;
|
||||
final T provider = getProviderForSensor(sensorId);
|
||||
if (provider != null) {
|
||||
return new Pair<>(sensorId, provider);
|
||||
}
|
||||
|
||||
Slog.e(TAG, "Single sensor, but provider not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the properties for all providers.
|
||||
*
|
||||
* Undefined until {@link #registerAll(Supplier)} has fired the completion callback.
|
||||
*/
|
||||
@NonNull
|
||||
public List<P> getAllProperties() {
|
||||
return mAllProps != null ? mAllProps : Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -23,64 +23,32 @@ import static android.hardware.biometrics.BiometricStateListener.STATE_IDLE;
|
||||
import static android.hardware.biometrics.BiometricStateListener.STATE_KEYGUARD_AUTH;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.hardware.biometrics.BiometricStateListener;
|
||||
import android.hardware.biometrics.IBiometricStateListener;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.Utils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* A callback for receiving notifications about biometric sensor state changes.
|
||||
*
|
||||
* @param <T> service provider type
|
||||
* @param <P> internal property type
|
||||
*/
|
||||
public class BiometricStateCallback<T extends BiometricServiceProvider<P>,
|
||||
P extends SensorPropertiesInternal> implements ClientMonitorCallback {
|
||||
public class BiometricStateCallback implements ClientMonitorCallback {
|
||||
|
||||
private static final String TAG = "BiometricStateCallback";
|
||||
|
||||
@NonNull
|
||||
private final CopyOnWriteArrayList<IBiometricStateListener> mBiometricStateListeners =
|
||||
new CopyOnWriteArrayList<>();
|
||||
@NonNull
|
||||
private final UserManager mUserManager;
|
||||
@BiometricStateListener.State
|
||||
private int mBiometricState;
|
||||
@NonNull
|
||||
private List<T> mProviders = List.of();
|
||||
private final CopyOnWriteArrayList<IBiometricStateListener>
|
||||
mBiometricStateListeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
/**
|
||||
* Create a new callback that must be {@link #start(List)}ed.
|
||||
*
|
||||
* @param userManager user manager
|
||||
*/
|
||||
public BiometricStateCallback(@NonNull UserManager userManager) {
|
||||
private @BiometricStateListener.State int mBiometricState;
|
||||
|
||||
public BiometricStateCallback() {
|
||||
mBiometricState = STATE_IDLE;
|
||||
mUserManager = userManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be called when the service has been initialized and all providers are ready.
|
||||
*
|
||||
* @param allProviders all registered biometric service providers
|
||||
*/
|
||||
public synchronized void start(@NonNull List<T> allProviders) {
|
||||
mProviders = Collections.unmodifiableList(allProviders);
|
||||
broadcastCurrentEnrollmentState(null /* listener */);
|
||||
}
|
||||
|
||||
/** Get the current state. */
|
||||
@BiometricStateListener.State
|
||||
public int getBiometricState() {
|
||||
return mBiometricState;
|
||||
}
|
||||
@@ -152,43 +120,23 @@ public class BiometricStateCallback<T extends BiometricServiceProvider<P>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables clients to register a BiometricStateListener. For example, this is used to forward
|
||||
* fingerprint sensor state changes to SideFpsEventHandler.
|
||||
*
|
||||
* @param listener listener to register
|
||||
* This should be invoked when:
|
||||
* 1) Enrolled --> None-enrolled
|
||||
* 2) None-enrolled --> enrolled
|
||||
* 3) HAL becomes ready
|
||||
* 4) Listener is registered
|
||||
*/
|
||||
public synchronized void registerBiometricStateListener(
|
||||
@NonNull IBiometricStateListener listener) {
|
||||
mBiometricStateListeners.add(listener);
|
||||
broadcastCurrentEnrollmentState(listener);
|
||||
}
|
||||
|
||||
private synchronized void broadcastCurrentEnrollmentState(
|
||||
@Nullable IBiometricStateListener listener) {
|
||||
for (T provider : mProviders) {
|
||||
for (SensorPropertiesInternal prop : provider.getSensorProperties()) {
|
||||
for (UserInfo userInfo : mUserManager.getAliveUsers()) {
|
||||
final boolean enrolled = provider.hasEnrollments(prop.sensorId, userInfo.id);
|
||||
if (listener != null) {
|
||||
notifyEnrollmentStateChanged(
|
||||
listener, userInfo.id, prop.sensorId, enrolled);
|
||||
} else {
|
||||
notifyAllEnrollmentStateChanged(
|
||||
userInfo.id, prop.sensorId, enrolled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyAllEnrollmentStateChanged(int userId, int sensorId,
|
||||
public void notifyAllEnrollmentStateChanged(int userId, int sensorId,
|
||||
boolean hasEnrollments) {
|
||||
for (IBiometricStateListener listener : mBiometricStateListeners) {
|
||||
notifyEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyEnrollmentStateChanged(@NonNull IBiometricStateListener listener,
|
||||
/**
|
||||
* Notifies the listener of enrollment state changes.
|
||||
*/
|
||||
public void notifyEnrollmentStateChanged(@NonNull IBiometricStateListener listener,
|
||||
int userId, int sensorId, boolean hasEnrollments) {
|
||||
try {
|
||||
listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments);
|
||||
@@ -196,4 +144,14 @@ public class BiometricStateCallback<T extends BiometricServiceProvider<P>,
|
||||
Slog.e(TAG, "Remote exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables clients to register a BiometricStateListener. For example, this is used to forward
|
||||
* fingerprint sensor state changes to SideFpsEventHandler.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
|
||||
mBiometricStateListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,20 @@
|
||||
package com.android.server.biometrics.sensors.face;
|
||||
|
||||
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
|
||||
import static android.Manifest.permission.MANAGE_BIOMETRIC;
|
||||
import static android.Manifest.permission.MANAGE_FACE;
|
||||
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
|
||||
import android.hardware.biometrics.IBiometricStateListener;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.ITestSessionCallback;
|
||||
@@ -37,18 +39,18 @@ import android.hardware.biometrics.face.SensorProps;
|
||||
import android.hardware.face.Face;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.FaceServiceReceiver;
|
||||
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.face.IFaceService;
|
||||
import android.hardware.face.IFaceServiceReceiver;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.NativeHandle;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.ShellCallback;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -56,10 +58,10 @@ import android.view.Surface;
|
||||
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.ServiceThread;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.log.BiometricContext;
|
||||
import com.android.server.biometrics.sensors.BiometricStateCallback;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
@@ -86,10 +88,51 @@ public class FaceService extends SystemService {
|
||||
private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
@NonNull
|
||||
private final FaceServiceRegistry mRegistry;
|
||||
private final List<ServiceProvider> mServiceProviders;
|
||||
|
||||
@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<FaceSensorPropertiesInternal> properties = getSensorProperties();
|
||||
if (properties.size() != 1) {
|
||||
Slog.e(TAG, "Multiple sensors found: " + properties.size());
|
||||
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 final BiometricStateCallback<ServiceProvider, FaceSensorPropertiesInternal>
|
||||
mBiometricStateCallback;
|
||||
private List<FaceSensorPropertiesInternal> getSensorProperties() {
|
||||
final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
properties.addAll(provider.getSensorProperties());
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives the incoming binder calls from FaceManager.
|
||||
@@ -99,7 +142,8 @@ public class FaceService extends SystemService {
|
||||
@Override
|
||||
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
|
||||
@NonNull String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for createTestSession, sensorId: " + sensorId);
|
||||
@@ -112,8 +156,9 @@ public class FaceService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer) {
|
||||
|
||||
final ProtoOutputStream proto = new ProtoOutputStream();
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider != null) {
|
||||
provider.dumpProtoState(sensorId, proto, clearSchedulerBuffer);
|
||||
}
|
||||
@@ -125,14 +170,16 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(
|
||||
String opPackageName) {
|
||||
return mRegistry.getAllProperties();
|
||||
|
||||
return FaceService.this.getSensorProperties();
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public FaceSensorPropertiesInternal getSensorProperties(int sensorId,
|
||||
@NonNull String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching sensor for getSensorProperties, sensorId: " + sensorId
|
||||
+ ", caller: " + opPackageName);
|
||||
@@ -146,7 +193,8 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void generateChallenge(IBinder token, int sensorId, int userId,
|
||||
IFaceServiceReceiver receiver, String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
|
||||
return;
|
||||
@@ -159,7 +207,8 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName,
|
||||
long challenge) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId);
|
||||
return;
|
||||
@@ -173,7 +222,8 @@ public class FaceService extends SystemService {
|
||||
public long enroll(int userId, final IBinder token, final byte[] hardwareAuthToken,
|
||||
final IFaceServiceReceiver receiver, final String opPackageName,
|
||||
final int[] disabledFeatures, Surface previewSurface, boolean debugConsent) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for enroll");
|
||||
return -1;
|
||||
@@ -195,7 +245,8 @@ public class FaceService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_BIOMETRIC)
|
||||
@Override // Binder call
|
||||
public void cancelEnrollment(final IBinder token, long requestId) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelEnrollment");
|
||||
return;
|
||||
@@ -209,6 +260,7 @@ public class FaceService extends SystemService {
|
||||
public long authenticate(final IBinder token, final long operationId, int userId,
|
||||
final IFaceServiceReceiver receiver, final String opPackageName,
|
||||
boolean isKeyguardBypassEnabled) {
|
||||
|
||||
// TODO(b/152413782): If the sensor supports face detect and the device is encrypted or
|
||||
// lockdown, something wrong happened. See similar path in FingerprintService.
|
||||
|
||||
@@ -221,7 +273,7 @@ public class FaceService extends SystemService {
|
||||
// permission.
|
||||
final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName);
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for authenticate");
|
||||
return -1;
|
||||
@@ -249,7 +301,7 @@ public class FaceService extends SystemService {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for detectFace");
|
||||
return -1;
|
||||
@@ -266,7 +318,8 @@ public class FaceService extends SystemService {
|
||||
IBinder token, long operationId, int userId,
|
||||
IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId,
|
||||
int cookie, boolean allowBackgroundAuthentication) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for prepareForAuthentication");
|
||||
return;
|
||||
@@ -283,7 +336,8 @@ public class FaceService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public void startPreparedClient(int sensorId, int cookie) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for startPreparedClient");
|
||||
return;
|
||||
@@ -296,7 +350,8 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void cancelAuthentication(final IBinder token, final String opPackageName,
|
||||
final long requestId) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelAuthentication");
|
||||
return;
|
||||
@@ -315,7 +370,7 @@ public class FaceService extends SystemService {
|
||||
return;
|
||||
}
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelFaceDetect");
|
||||
return;
|
||||
@@ -328,7 +383,8 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void cancelAuthenticationFromService(int sensorId, final IBinder token,
|
||||
final String opPackageName, final long requestId) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelAuthenticationFromService");
|
||||
return;
|
||||
@@ -341,7 +397,8 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void remove(final IBinder token, final int faceId, final int userId,
|
||||
final IFaceServiceReceiver receiver, final String opPackageName) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for remove");
|
||||
return;
|
||||
@@ -355,6 +412,7 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void removeAll(final IBinder token, final int userId,
|
||||
final IFaceServiceReceiver receiver, final String opPackageName) {
|
||||
|
||||
final FaceServiceReceiver internalReceiver = new FaceServiceReceiver() {
|
||||
int sensorsFinishedRemoving = 0;
|
||||
final int numSensors = getSensorPropertiesInternal(
|
||||
@@ -374,7 +432,7 @@ public class FaceService extends SystemService {
|
||||
|
||||
// This effectively iterates through all sensors, but has to do so by finding all
|
||||
// sensors under each provider.
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
List<FaceSensorPropertiesInternal> props = provider.getSensorProperties();
|
||||
for (FaceSensorPropertiesInternal prop : props) {
|
||||
provider.scheduleRemoveAll(prop.sensorId, token, userId, internalReceiver,
|
||||
@@ -409,27 +467,27 @@ public class FaceService extends SystemService {
|
||||
try {
|
||||
if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) {
|
||||
final ProtoOutputStream proto = new ProtoOutputStream(fd);
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
|
||||
provider.dumpProtoState(props.sensorId, proto, false);
|
||||
}
|
||||
}
|
||||
proto.flush();
|
||||
} else if (args.length > 0 && "--proto".equals(args[0])) {
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
|
||||
provider.dumpProtoMetrics(props.sensorId, fd);
|
||||
}
|
||||
}
|
||||
} else if (args.length > 1 && "--hal".equals(args[0])) {
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
|
||||
provider.dumpHal(props.sensorId, fd,
|
||||
Arrays.copyOfRange(args, 1, args.length, args.getClass()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
|
||||
pw.println("Dumping for sensorId: " + props.sensorId
|
||||
+ ", provider: " + provider.getClass().getSimpleName());
|
||||
@@ -446,9 +504,10 @@ public class FaceService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public boolean isHardwareDetected(int sensorId, String opPackageName) {
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName);
|
||||
return false;
|
||||
@@ -462,11 +521,12 @@ public class FaceService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public List<Face> getEnrolledFaces(int sensorId, int userId, String opPackageName) {
|
||||
|
||||
if (userId != UserHandle.getCallingUserId()) {
|
||||
Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
|
||||
}
|
||||
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getEnrolledFaces, caller: " + opPackageName);
|
||||
return Collections.emptyList();
|
||||
@@ -478,11 +538,12 @@ public class FaceService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public boolean hasEnrolledFaces(int sensorId, int userId, String opPackageName) {
|
||||
|
||||
if (userId != UserHandle.getCallingUserId()) {
|
||||
Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
|
||||
}
|
||||
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for hasEnrolledFaces, caller: " + opPackageName);
|
||||
return false;
|
||||
@@ -494,7 +555,8 @@ public class FaceService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public @LockoutTracker.LockoutMode int getLockoutModeForUser(int sensorId, int userId) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getLockoutModeForUser");
|
||||
return LockoutTracker.LOCKOUT_NONE;
|
||||
@@ -507,7 +569,8 @@ public class FaceService extends SystemService {
|
||||
@Override
|
||||
public void invalidateAuthenticatorId(int sensorId, int userId,
|
||||
IInvalidationCallback callback) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for invalidateAuthenticatorId");
|
||||
return;
|
||||
@@ -519,7 +582,7 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public long getAuthenticatorId(int sensorId, int userId) {
|
||||
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getAuthenticatorId");
|
||||
return 0;
|
||||
@@ -532,7 +595,8 @@ public class FaceService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void resetLockout(IBinder token, int sensorId, int userId, byte[] hardwareAuthToken,
|
||||
String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName);
|
||||
return;
|
||||
@@ -546,7 +610,8 @@ public class FaceService extends SystemService {
|
||||
public void setFeature(final IBinder token, int userId, int feature, boolean enabled,
|
||||
final byte[] hardwareAuthToken, IFaceServiceReceiver receiver,
|
||||
final String opPackageName) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for setFeature");
|
||||
return;
|
||||
@@ -560,7 +625,8 @@ public class FaceService extends SystemService {
|
||||
@Override
|
||||
public void getFeature(final IBinder token, int userId, int feature,
|
||||
IFaceServiceReceiver receiver, final String opPackageName) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getFeature");
|
||||
return;
|
||||
@@ -570,14 +636,18 @@ public class FaceService extends SystemService {
|
||||
new ClientMonitorCallbackConverter(receiver), opPackageName);
|
||||
}
|
||||
|
||||
private List<ServiceProvider> getAidlProviders() {
|
||||
final List<ServiceProvider> providers = new ArrayList<>();
|
||||
private void addHidlProviders(@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
|
||||
for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
|
||||
mServiceProviders.add(
|
||||
Face10.newInstance(getContext(), hidlSensor, mLockoutResetDispatcher));
|
||||
}
|
||||
}
|
||||
|
||||
private void addAidlProviders() {
|
||||
final String[] instances = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR);
|
||||
if (instances == null || instances.length == 0) {
|
||||
return providers;
|
||||
return;
|
||||
}
|
||||
|
||||
for (String instance : instances) {
|
||||
final String fqName = IFace.DESCRIPTOR + "/" + instance;
|
||||
final IFace face = IFace.Stub.asInterface(
|
||||
@@ -590,41 +660,53 @@ public class FaceService extends SystemService {
|
||||
final SensorProps[] props = face.getSensorProps();
|
||||
final FaceProvider provider = new FaceProvider(getContext(), props, instance,
|
||||
mLockoutResetDispatcher, BiometricContext.getInstance(getContext()));
|
||||
providers.add(provider);
|
||||
mServiceProviders.add(provider);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
|
||||
}
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public void registerAuthenticators(
|
||||
@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
|
||||
mRegistry.registerAll(() -> {
|
||||
final List<ServiceProvider> providers = new ArrayList<>();
|
||||
for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
|
||||
providers.add(
|
||||
Face10.newInstance(getContext(), hidlSensor, mLockoutResetDispatcher));
|
||||
|
||||
// Some HAL might not be started before the system service and will cause the code below
|
||||
// to wait, and some of the operations below might take a significant amount of time to
|
||||
// complete (calls to the HALs). To avoid blocking the rest of system server we put
|
||||
// this on a background thread.
|
||||
final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
|
||||
true /* allowIo */);
|
||||
thread.start();
|
||||
final Handler handler = new Handler(thread.getLooper());
|
||||
|
||||
handler.post(() -> {
|
||||
addHidlProviders(hidlSensors);
|
||||
addAidlProviders();
|
||||
|
||||
final IBiometricService biometricService = IBiometricService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.BIOMETRIC_SERVICE));
|
||||
|
||||
// Register each sensor individually with BiometricService
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
final List<FaceSensorPropertiesInternal> props = provider.getSensorProperties();
|
||||
for (FaceSensorPropertiesInternal prop : props) {
|
||||
final int sensorId = prop.sensorId;
|
||||
final @BiometricManager.Authenticators.Types int strength =
|
||||
Utils.propertyStrengthToAuthenticatorStrength(prop.sensorStrength);
|
||||
final FaceAuthenticator authenticator = new FaceAuthenticator(
|
||||
mServiceWrapper, sensorId);
|
||||
try {
|
||||
biometricService.registerAuthenticator(sensorId, TYPE_FACE, strength,
|
||||
authenticator);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId);
|
||||
}
|
||||
}
|
||||
}
|
||||
providers.addAll(getAidlProviders());
|
||||
return providers;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuthenticatorsRegisteredCallback(
|
||||
IFaceAuthenticatorsRegisteredCallback callback) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
mRegistry.addAllRegisteredCallback(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
|
||||
mBiometricStateCallback.registerBiometricStateListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public FaceService(Context context) {
|
||||
@@ -632,16 +714,7 @@ public class FaceService extends SystemService {
|
||||
mServiceWrapper = new FaceServiceWrapper();
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
|
||||
mLockPatternUtils = new LockPatternUtils(context);
|
||||
mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context));
|
||||
mRegistry = new FaceServiceRegistry(mServiceWrapper,
|
||||
() -> IBiometricService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.BIOMETRIC_SERVICE)));
|
||||
mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(List<FaceSensorPropertiesInternal> sensors) {
|
||||
mBiometricStateCallback.start(mRegistry.getProviders());
|
||||
}
|
||||
});
|
||||
mServiceProviders = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -679,7 +752,7 @@ public class FaceService extends SystemService {
|
||||
if (Utils.isVirtualEnabled(getContext())) {
|
||||
Slog.i(TAG, "Sync virtual enrollments");
|
||||
final int userId = ActivityManager.getCurrentUser();
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
|
||||
provider.scheduleInternalCleanup(props.sensorId, userId, null /* callback */,
|
||||
true /* favorHalEnrollments */);
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.face.IFaceService;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.BiometricServiceRegistry;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/** Registry for {@link IFaceService} providers. */
|
||||
public class FaceServiceRegistry extends BiometricServiceRegistry<ServiceProvider,
|
||||
FaceSensorPropertiesInternal, IFaceAuthenticatorsRegisteredCallback> {
|
||||
|
||||
private static final String TAG = "FaceServiceRegistry";
|
||||
|
||||
@NonNull
|
||||
private final IFaceService mService;
|
||||
|
||||
/** Creates a new registry tied to the given service. */
|
||||
public FaceServiceRegistry(@NonNull IFaceService service,
|
||||
@Nullable Supplier<IBiometricService> biometricSupplier) {
|
||||
super(biometricSupplier);
|
||||
mService = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerService(@NonNull IBiometricService service,
|
||||
@NonNull FaceSensorPropertiesInternal props) {
|
||||
@BiometricManager.Authenticators.Types final int strength =
|
||||
Utils.propertyStrengthToAuthenticatorStrength(props.sensorStrength);
|
||||
try {
|
||||
service.registerAuthenticator(props.sensorId, TYPE_FACE, strength,
|
||||
new FaceAuthenticator(mService, props.sensorId));
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when registering sensorId: " + props.sensorId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invokeRegisteredCallback(@NonNull IFaceAuthenticatorsRegisteredCallback callback,
|
||||
@NonNull List<FaceSensorPropertiesInternal> allProps) throws RemoteException {
|
||||
callback.onAllAuthenticatorsRegistered(allProps);
|
||||
}
|
||||
}
|
||||
@@ -26,13 +26,15 @@ import android.hardware.face.FaceManager;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceServiceReceiver;
|
||||
import android.os.IBinder;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.server.biometrics.sensors.BiometricServiceProvider;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallback;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -54,11 +56,24 @@ import java.util.List;
|
||||
* to check (e.g. via {@link FaceManager#getSensorPropertiesInternal()}) that the code path isn't
|
||||
* taken. ServiceProviders will provide a no-op for unsupported operations to fail safely.
|
||||
*/
|
||||
public interface ServiceProvider extends BiometricServiceProvider<FaceSensorPropertiesInternal> {
|
||||
public interface ServiceProvider {
|
||||
/**
|
||||
* Checks if the specified sensor is owned by this provider.
|
||||
*/
|
||||
boolean containsSensor(int sensorId);
|
||||
|
||||
@NonNull
|
||||
List<FaceSensorPropertiesInternal> getSensorProperties();
|
||||
|
||||
@NonNull
|
||||
FaceSensorPropertiesInternal getSensorProperties(int sensorId);
|
||||
|
||||
@NonNull
|
||||
List<Face> getEnrolledFaces(int sensorId, int userId);
|
||||
|
||||
@LockoutTracker.LockoutMode
|
||||
int getLockoutModeForUser(int sensorId, int userId);
|
||||
|
||||
/**
|
||||
* Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to be
|
||||
* invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
|
||||
@@ -69,6 +84,10 @@ public interface ServiceProvider extends BiometricServiceProvider<FaceSensorProp
|
||||
+ " this method");
|
||||
}
|
||||
|
||||
long getAuthenticatorId(int sensorId, int userId);
|
||||
|
||||
boolean isHardwareDetected(int sensorId);
|
||||
|
||||
void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
|
||||
@NonNull IFaceServiceReceiver receiver, String opPackageName);
|
||||
|
||||
@@ -123,6 +142,13 @@ public interface ServiceProvider extends BiometricServiceProvider<FaceSensorProp
|
||||
void scheduleInternalCleanup(int sensorId, int userId,
|
||||
@Nullable ClientMonitorCallback callback, boolean favorHalEnrollments);
|
||||
|
||||
void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
|
||||
boolean clearSchedulerBuffer);
|
||||
|
||||
void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);
|
||||
|
||||
void dumpInternal(int sensorId, @NonNull PrintWriter pw);
|
||||
|
||||
@NonNull
|
||||
ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
|
||||
@NonNull String opPackageName);
|
||||
|
||||
@@ -284,11 +284,6 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
||||
return FaceUtils.getInstance(sensorId).getBiometricsForUser(mContext, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollments(int sensorId, int userId) {
|
||||
return !getEnrolledFaces(sensorId, userId).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
|
||||
@NonNull IInvalidationCallback callback) {
|
||||
|
||||
@@ -483,11 +483,6 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
return FaceUtils.getLegacyInstance(mSensorId).getBiometricsForUser(mContext, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollments(int sensorId, int userId) {
|
||||
return !getEnrolledFaces(sensorId, userId).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@LockoutTracker.LockoutMode
|
||||
public int getLockoutModeForUser(int sensorId, int userId) {
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package com.android.server.biometrics.sensors.fingerprint;
|
||||
|
||||
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
|
||||
import static android.Manifest.permission.MANAGE_BIOMETRIC;
|
||||
import static android.Manifest.permission.MANAGE_FINGERPRINT;
|
||||
import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
|
||||
import static android.Manifest.permission.TEST_BIOMETRIC;
|
||||
import static android.Manifest.permission.USE_BIOMETRIC;
|
||||
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
||||
import static android.Manifest.permission.USE_FINGERPRINT;
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
|
||||
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_USER_CANCELED;
|
||||
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR;
|
||||
@@ -33,6 +36,8 @@ import android.app.ActivityManager;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.BiometricPrompt;
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
@@ -60,6 +65,7 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ServiceManager;
|
||||
@@ -73,9 +79,11 @@ import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.ServiceThread;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.log.BiometricContext;
|
||||
@@ -107,32 +115,74 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
protected static final String TAG = "FingerprintService";
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private final AppOpsManager mAppOps;
|
||||
private final LockoutResetDispatcher mLockoutResetDispatcher;
|
||||
private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
@NonNull
|
||||
private final BiometricContext mBiometricContext;
|
||||
@NonNull
|
||||
private final Supplier<String[]> mAidlInstanceNameSupplier;
|
||||
@NonNull
|
||||
private final Function<String, IFingerprint> mIFingerprintProvider;
|
||||
@NonNull
|
||||
private final BiometricStateCallback<ServiceProvider, FingerprintSensorPropertiesInternal>
|
||||
mBiometricStateCallback;
|
||||
@NonNull
|
||||
private final Handler mHandler;
|
||||
@NonNull
|
||||
private final FingerprintServiceRegistry mRegistry;
|
||||
@NonNull private final List<ServiceProvider> mServiceProviders;
|
||||
@NonNull private final BiometricStateCallback mBiometricStateCallback;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final BiometricContext mBiometricContext;
|
||||
@NonNull private final Supplier<IBiometricService> mBiometricServiceSupplier;
|
||||
@NonNull private final Function<String, IFingerprint> mIFingerprintProvider;
|
||||
|
||||
/** Receives the incoming binder calls from FingerprintManager. */
|
||||
@VisibleForTesting
|
||||
final IFingerprintService.Stub mServiceWrapper = new IFingerprintService.Stub() {
|
||||
@GuardedBy("mLock")
|
||||
@NonNull private final RemoteCallbackList<IFingerprintAuthenticatorsRegisteredCallback>
|
||||
mAuthenticatorsRegisteredCallbacks;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@NonNull private final List<FingerprintSensorPropertiesInternal> mSensorProps;
|
||||
|
||||
/**
|
||||
* Registers BiometricStateListener in list stored by FingerprintService
|
||||
* @param listener new BiometricStateListener being added
|
||||
*/
|
||||
public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
|
||||
mBiometricStateCallback.registerBiometricStateListener(listener);
|
||||
broadcastCurrentEnrollmentState(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param listener if non-null, notifies only this listener. if null, notifies all listeners
|
||||
* in {@link BiometricStateCallback}. This is slightly ugly, but reduces
|
||||
* redundant code.
|
||||
*/
|
||||
private void broadcastCurrentEnrollmentState(@Nullable IBiometricStateListener listener) {
|
||||
final UserManager um = UserManager.get(getContext());
|
||||
synchronized (mLock) {
|
||||
// Update the new listener with current state of all sensors
|
||||
for (FingerprintSensorPropertiesInternal prop : mSensorProps) {
|
||||
final ServiceProvider provider = getProviderForSensor(prop.sensorId);
|
||||
for (UserInfo userInfo : um.getAliveUsers()) {
|
||||
final boolean enrolled = !provider
|
||||
.getEnrolledFingerprints(prop.sensorId, userInfo.id).isEmpty();
|
||||
|
||||
// Defer this work and allow the loop to release the lock sooner
|
||||
mHandler.post(() -> {
|
||||
if (listener != null) {
|
||||
mBiometricStateCallback.notifyEnrollmentStateChanged(
|
||||
listener, userInfo.id, prop.sensorId, enrolled);
|
||||
} else {
|
||||
mBiometricStateCallback.notifyAllEnrollmentStateChanged(
|
||||
userInfo.id, prop.sensorId, enrolled);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives the incoming binder calls from FingerprintManager.
|
||||
*/
|
||||
private final IFingerprintService.Stub mServiceWrapper = new IFingerprintService.Stub() {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
|
||||
@Override
|
||||
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
|
||||
@NonNull String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for createTestSession, sensorId: " + sensorId);
|
||||
@@ -145,8 +195,9 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer) {
|
||||
|
||||
final ProtoOutputStream proto = new ProtoOutputStream();
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider != null) {
|
||||
provider.dumpProtoState(sensorId, proto, clearSchedulerBuffer);
|
||||
}
|
||||
@@ -161,14 +212,16 @@ public class FingerprintService extends SystemService {
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
Utils.checkPermission(getContext(), TEST_BIOMETRIC);
|
||||
}
|
||||
return mRegistry.getAllProperties();
|
||||
|
||||
return FingerprintService.this.getSensorProperties();
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public FingerprintSensorPropertiesInternal getSensorProperties(int sensorId,
|
||||
@NonNull String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching sensor for getSensorProperties, sensorId: " + sensorId
|
||||
+ ", caller: " + opPackageName);
|
||||
@@ -181,7 +234,8 @@ public class FingerprintService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void generateChallenge(IBinder token, int sensorId, int userId,
|
||||
IFingerprintServiceReceiver receiver, String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
|
||||
return;
|
||||
@@ -194,7 +248,8 @@ public class FingerprintService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName,
|
||||
long challenge) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId);
|
||||
return;
|
||||
@@ -209,7 +264,8 @@ public class FingerprintService extends SystemService {
|
||||
public long enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken,
|
||||
final int userId, final IFingerprintServiceReceiver receiver,
|
||||
final String opPackageName, @FingerprintManager.EnrollReason int enrollReason) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for enroll");
|
||||
return -1;
|
||||
@@ -222,7 +278,8 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_FINGERPRINT)
|
||||
@Override // Binder call
|
||||
public void cancelEnrollment(final IBinder token, long requestId) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelEnrollment");
|
||||
return;
|
||||
@@ -282,10 +339,10 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider;
|
||||
if (sensorId == FingerprintManager.SENSOR_ID_ANY) {
|
||||
provider = mRegistry.getSingleProvider();
|
||||
provider = getSingleProvider();
|
||||
} else {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
provider = new Pair<>(sensorId, mRegistry.getProviderForSensor(sensorId));
|
||||
provider = new Pair<>(sensorId, getProviderForSensor(sensorId));
|
||||
}
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for authenticate");
|
||||
@@ -317,6 +374,7 @@ public class FingerprintService extends SystemService {
|
||||
final IFingerprintServiceReceiver receiver,
|
||||
final String opPackageName,
|
||||
boolean ignoreEnrollmentState) throws PackageManager.NameNotFoundException {
|
||||
|
||||
final Context context = getUiContext();
|
||||
final Context promptContext = context.createPackageContextAsUser(
|
||||
opPackageName, 0 /* flags */, UserHandle.getUserHandleForUid(uId));
|
||||
@@ -410,7 +468,7 @@ public class FingerprintService extends SystemService {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for detectFingerprint");
|
||||
return -1;
|
||||
@@ -426,7 +484,8 @@ public class FingerprintService extends SystemService {
|
||||
public void prepareForAuthentication(int sensorId, IBinder token, long operationId,
|
||||
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
|
||||
long requestId, int cookie, boolean allowBackgroundAuthentication) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for prepareForAuthentication");
|
||||
return;
|
||||
@@ -442,7 +501,8 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_BIOMETRIC)
|
||||
@Override // Binder call
|
||||
public void startPreparedClient(int sensorId, int cookie) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for startPreparedClient");
|
||||
return;
|
||||
@@ -472,7 +532,7 @@ public class FingerprintService extends SystemService {
|
||||
return;
|
||||
}
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelAuthentication");
|
||||
return;
|
||||
@@ -493,7 +553,7 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
// For IBiometricsFingerprint2.1, cancelling fingerprint detect is the same as
|
||||
// cancelling authentication.
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelFingerprintDetect");
|
||||
return;
|
||||
@@ -506,9 +566,11 @@ public class FingerprintService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void cancelAuthenticationFromService(final int sensorId, final IBinder token,
|
||||
final String opPackageName, final long requestId) {
|
||||
|
||||
|
||||
Slog.d(TAG, "cancelAuthenticationFromService, sensorId: " + sensorId);
|
||||
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for cancelAuthenticationFromService");
|
||||
return;
|
||||
@@ -521,7 +583,8 @@ public class FingerprintService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void remove(final IBinder token, final int fingerId, final int userId,
|
||||
final IFingerprintServiceReceiver receiver, final String opPackageName) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for remove");
|
||||
return;
|
||||
@@ -554,7 +617,7 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
// This effectively iterates through all sensors, but has to do so by finding all
|
||||
// sensors under each provider.
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
List<FingerprintSensorPropertiesInternal> props = provider.getSensorProperties();
|
||||
for (FingerprintSensorPropertiesInternal prop : props) {
|
||||
provider.scheduleRemoveAll(prop.sensorId, token, internalReceiver, userId,
|
||||
@@ -589,7 +652,7 @@ public class FingerprintService extends SystemService {
|
||||
try {
|
||||
if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) {
|
||||
final ProtoOutputStream proto = new ProtoOutputStream(fd);
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FingerprintSensorPropertiesInternal props
|
||||
: provider.getSensorProperties()) {
|
||||
provider.dumpProtoState(props.sensorId, proto, false);
|
||||
@@ -597,14 +660,14 @@ public class FingerprintService extends SystemService {
|
||||
}
|
||||
proto.flush();
|
||||
} else if (args.length > 0 && "--proto".equals(args[0])) {
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FingerprintSensorPropertiesInternal props
|
||||
: provider.getSensorProperties()) {
|
||||
provider.dumpProtoMetrics(props.sensorId, fd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FingerprintSensorPropertiesInternal props
|
||||
: provider.getSensorProperties()) {
|
||||
pw.println("Dumping for sensorId: " + props.sensorId
|
||||
@@ -635,7 +698,7 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for isHardwareDetectedDeprecated, caller: "
|
||||
+ opPackageName);
|
||||
@@ -650,7 +713,8 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public boolean isHardwareDetected(int sensorId, String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName);
|
||||
return false;
|
||||
@@ -666,7 +730,7 @@ public class FingerprintService extends SystemService {
|
||||
return;
|
||||
}
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for rename");
|
||||
return;
|
||||
@@ -717,7 +781,8 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
public boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for hasEnrolledFingerprints, caller: " + opPackageName);
|
||||
return false;
|
||||
@@ -729,7 +794,8 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public @LockoutTracker.LockoutMode int getLockoutModeForUser(int sensorId, int userId) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getLockoutModeForUser");
|
||||
return LockoutTracker.LOCKOUT_NONE;
|
||||
@@ -741,7 +807,8 @@ public class FingerprintService extends SystemService {
|
||||
@Override
|
||||
public void invalidateAuthenticatorId(int sensorId, int userId,
|
||||
IInvalidationCallback callback) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for invalidateAuthenticatorId");
|
||||
return;
|
||||
@@ -752,7 +819,8 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override // Binder call
|
||||
public long getAuthenticatorId(int sensorId, int userId) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getAuthenticatorId");
|
||||
return 0;
|
||||
@@ -764,7 +832,8 @@ public class FingerprintService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void resetLockout(IBinder token, int sensorId, int userId,
|
||||
@Nullable byte[] hardwareAuthToken, String opPackageName) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName);
|
||||
return;
|
||||
@@ -795,38 +864,55 @@ public class FingerprintService extends SystemService {
|
||||
@Override // Binder call
|
||||
public void registerAuthenticators(
|
||||
@NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
|
||||
mRegistry.registerAll(() -> {
|
||||
final List<ServiceProvider> providers = new ArrayList<>();
|
||||
providers.addAll(getHidlProviders(hidlSensors));
|
||||
|
||||
// Some HAL might not be started before the system service and will cause the code below
|
||||
// to wait, and some of the operations below might take a significant amount of time to
|
||||
// complete (calls to the HALs). To avoid blocking the rest of system server we put
|
||||
// this on a background thread.
|
||||
final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
|
||||
true /* allowIo */);
|
||||
thread.start();
|
||||
final Handler handler = new Handler(thread.getLooper());
|
||||
handler.post(() -> {
|
||||
List<String> aidlSensors = new ArrayList<>();
|
||||
final String[] instances = mAidlInstanceNameSupplier.get();
|
||||
final String[] instances =
|
||||
ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR);
|
||||
if (instances != null) {
|
||||
aidlSensors.addAll(Lists.newArrayList(instances));
|
||||
}
|
||||
providers.addAll(getAidlProviders(
|
||||
Utils.filterAvailableHalInstances(getContext(), aidlSensors)));
|
||||
return providers;
|
||||
registerAuthenticatorsForService(aidlSensors, hidlSensors);
|
||||
});
|
||||
thread.quitSafely();
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public void addAuthenticatorsRegisteredCallback(
|
||||
IFingerprintAuthenticatorsRegisteredCallback callback) {
|
||||
mRegistry.addAllRegisteredCallback(callback);
|
||||
}
|
||||
if (callback == null) {
|
||||
Slog.e(TAG, "addAuthenticatorsRegisteredCallback, callback is null");
|
||||
return;
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
|
||||
mBiometricStateCallback.registerBiometricStateListener(listener);
|
||||
final boolean registered;
|
||||
final boolean hasSensorProps;
|
||||
synchronized (mLock) {
|
||||
registered = mAuthenticatorsRegisteredCallbacks.register(callback);
|
||||
hasSensorProps = !mSensorProps.isEmpty();
|
||||
}
|
||||
if (registered && hasSensorProps) {
|
||||
broadcastAllAuthenticatorsRegistered();
|
||||
} else if (!registered) {
|
||||
Slog.e(TAG, "addAuthenticatorsRegisteredCallback failed to register callback");
|
||||
}
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public void onPointerDown(long requestId, int sensorId, int x, int y,
|
||||
float minor, float major) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId);
|
||||
return;
|
||||
@@ -837,7 +923,8 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public void onPointerUp(long requestId, int sensorId) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId);
|
||||
return;
|
||||
@@ -848,7 +935,8 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public void onUiReady(long requestId, int sensorId) {
|
||||
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "No matching provider for onUiReady, sensorId: " + sensorId);
|
||||
return;
|
||||
@@ -859,7 +947,8 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
provider.setUdfpsOverlayController(controller);
|
||||
}
|
||||
}
|
||||
@@ -867,15 +956,22 @@ public class FingerprintService extends SystemService {
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public void setSidefpsController(@NonNull ISidefpsController controller) {
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
provider.setSidefpsController(controller);
|
||||
}
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
|
||||
@Override
|
||||
public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
FingerprintService.this.registerBiometricStateListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPowerPressed() {
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
provider.onPowerPressed();
|
||||
}
|
||||
}
|
||||
@@ -885,7 +981,6 @@ public class FingerprintService extends SystemService {
|
||||
this(context, BiometricContext.getInstance(context),
|
||||
() -> IBiometricService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
|
||||
() -> ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR),
|
||||
(fqName) -> IFingerprint.Stub.asInterface(
|
||||
Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName))));
|
||||
}
|
||||
@@ -893,34 +988,61 @@ public class FingerprintService extends SystemService {
|
||||
@VisibleForTesting
|
||||
FingerprintService(Context context,
|
||||
BiometricContext biometricContext,
|
||||
Supplier<IBiometricService> biometricServiceSupplier,
|
||||
Supplier<String[]> aidlInstanceNameSupplier,
|
||||
Supplier<IBiometricService> biometricServiceProvider,
|
||||
Function<String, IFingerprint> fingerprintProvider) {
|
||||
super(context);
|
||||
mBiometricContext = biometricContext;
|
||||
mAidlInstanceNameSupplier = aidlInstanceNameSupplier;
|
||||
mBiometricServiceSupplier = biometricServiceProvider;
|
||||
mIFingerprintProvider = fingerprintProvider;
|
||||
mAppOps = context.getSystemService(AppOpsManager.class);
|
||||
mGestureAvailabilityDispatcher = new GestureAvailabilityDispatcher();
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
|
||||
mLockPatternUtils = new LockPatternUtils(context);
|
||||
mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context));
|
||||
mServiceProviders = new ArrayList<>();
|
||||
mBiometricStateCallback = new BiometricStateCallback();
|
||||
mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>();
|
||||
mSensorProps = new ArrayList<>();
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mRegistry = new FingerprintServiceRegistry(mServiceWrapper, biometricServiceSupplier);
|
||||
mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
mBiometricStateCallback.start(mRegistry.getProviders());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<ServiceProvider> getHidlProviders(
|
||||
@VisibleForTesting
|
||||
void registerAuthenticatorsForService(@NonNull List<String> aidlInstanceNames,
|
||||
@NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
|
||||
final List<ServiceProvider> providers = new ArrayList<>();
|
||||
addHidlProviders(hidlSensors);
|
||||
addAidlProviders(Utils.filterAvailableHalInstances(getContext(), aidlInstanceNames));
|
||||
|
||||
final IBiometricService biometricService = mBiometricServiceSupplier.get();
|
||||
|
||||
// Register each sensor individually with BiometricService
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
final List<FingerprintSensorPropertiesInternal> props =
|
||||
provider.getSensorProperties();
|
||||
for (FingerprintSensorPropertiesInternal prop : props) {
|
||||
final int sensorId = prop.sensorId;
|
||||
@BiometricManager.Authenticators.Types final int strength =
|
||||
Utils.propertyStrengthToAuthenticatorStrength(prop.sensorStrength);
|
||||
final FingerprintAuthenticator authenticator = new FingerprintAuthenticator(
|
||||
mServiceWrapper, sensorId);
|
||||
try {
|
||||
biometricService.registerAuthenticator(sensorId, TYPE_FINGERPRINT,
|
||||
strength, authenticator);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
mSensorProps.addAll(provider.getSensorProperties());
|
||||
}
|
||||
}
|
||||
|
||||
broadcastCurrentEnrollmentState(null); // broadcasts to all listeners
|
||||
broadcastAllAuthenticatorsRegistered();
|
||||
}
|
||||
|
||||
private void addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors) {
|
||||
for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) {
|
||||
final Fingerprint21 fingerprint21;
|
||||
if ((Build.IS_USERDEBUG || Build.IS_ENG)
|
||||
@@ -937,16 +1059,11 @@ public class FingerprintService extends SystemService {
|
||||
mBiometricStateCallback, hidlSensor, mHandler,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
}
|
||||
providers.add(fingerprint21);
|
||||
mServiceProviders.add(fingerprint21);
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<ServiceProvider> getAidlProviders(@NonNull List<String> instances) {
|
||||
final List<ServiceProvider> providers = new ArrayList<>();
|
||||
|
||||
private void addAidlProviders(List<String> instances) {
|
||||
for (String instance : instances) {
|
||||
final String fqName = IFingerprint.DESCRIPTOR + "/" + instance;
|
||||
final IFingerprint fp = mIFingerprintProvider.apply(fqName);
|
||||
@@ -958,7 +1075,7 @@ public class FingerprintService extends SystemService {
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
|
||||
mBiometricContext);
|
||||
Slog.i(TAG, "Adding AIDL provider: " + fqName);
|
||||
providers.add(provider);
|
||||
mServiceProviders.add(provider);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
|
||||
}
|
||||
@@ -966,8 +1083,38 @@ public class FingerprintService extends SystemService {
|
||||
Slog.e(TAG, "Unable to get declared service: " + fqName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return providers;
|
||||
// Notifies the callbacks that all of the authenticators have been registered and removes the
|
||||
// invoked callbacks from the callback list.
|
||||
private void broadcastAllAuthenticatorsRegistered() {
|
||||
// Make a local copy of the data so it can be used outside of the synchronized block when
|
||||
// making Binder calls.
|
||||
final List<IFingerprintAuthenticatorsRegisteredCallback> callbacks = new ArrayList<>();
|
||||
final List<FingerprintSensorPropertiesInternal> props;
|
||||
synchronized (mLock) {
|
||||
if (!mSensorProps.isEmpty()) {
|
||||
props = new ArrayList<>(mSensorProps);
|
||||
} else {
|
||||
Slog.e(TAG, "mSensorProps is empty");
|
||||
return;
|
||||
}
|
||||
final int n = mAuthenticatorsRegisteredCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
final IFingerprintAuthenticatorsRegisteredCallback cb =
|
||||
mAuthenticatorsRegisteredCallbacks.getBroadcastItem(i);
|
||||
callbacks.add(cb);
|
||||
mAuthenticatorsRegisteredCallbacks.unregister(cb);
|
||||
}
|
||||
mAuthenticatorsRegisteredCallbacks.finishBroadcast();
|
||||
}
|
||||
for (IFingerprintAuthenticatorsRegisteredCallback cb : callbacks) {
|
||||
try {
|
||||
cb.onAllAuthenticatorsRegistered(props);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception in onAllAuthenticatorsRegistered", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -975,9 +1122,51 @@ public class FingerprintService extends SystemService {
|
||||
publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper);
|
||||
}
|
||||
|
||||
@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 multiple providers,
|
||||
* returns the first one. If no providers, returns null.
|
||||
*/
|
||||
@Nullable
|
||||
private Pair<Integer, ServiceProvider> getSingleProvider() {
|
||||
final List<FingerprintSensorPropertiesInternal> properties = getSensorProperties();
|
||||
if (properties.isEmpty()) {
|
||||
Slog.e(TAG, "No providers found");
|
||||
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, "Provider not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<FingerprintSensorPropertiesInternal> getSensorProperties() {
|
||||
synchronized (mLock) {
|
||||
return mSensorProps;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<Fingerprint> getEnrolledFingerprintsDeprecated(int userId, String opPackageName) {
|
||||
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for getEnrolledFingerprintsDeprecated, caller: "
|
||||
+ opPackageName);
|
||||
@@ -1040,7 +1229,7 @@ public class FingerprintService extends SystemService {
|
||||
if (Utils.isVirtualEnabled(getContext())) {
|
||||
Slog.i(TAG, "Sync virtual enrollments");
|
||||
final int userId = ActivityManager.getCurrentUser();
|
||||
for (ServiceProvider provider : mRegistry.getProviders()) {
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
for (FingerprintSensorPropertiesInternal props : provider.getSensorProperties()) {
|
||||
provider.scheduleInternalCleanup(props.sensorId, userId, null /* callback */,
|
||||
true /* favorHalEnrollments */);
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.fingerprint.IFingerprintService;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.BiometricServiceRegistry;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/** Registry for {@link IFingerprintService} providers. */
|
||||
public class FingerprintServiceRegistry extends BiometricServiceRegistry<ServiceProvider,
|
||||
FingerprintSensorPropertiesInternal, IFingerprintAuthenticatorsRegisteredCallback> {
|
||||
|
||||
private static final String TAG = "FingerprintServiceRegistry";
|
||||
|
||||
@NonNull
|
||||
private final IFingerprintService mService;
|
||||
|
||||
/** Creates a new registry tied to the given service. */
|
||||
public FingerprintServiceRegistry(@NonNull IFingerprintService service,
|
||||
@Nullable Supplier<IBiometricService> biometricSupplier) {
|
||||
super(biometricSupplier);
|
||||
mService = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerService(@NonNull IBiometricService service,
|
||||
@NonNull FingerprintSensorPropertiesInternal props) {
|
||||
@BiometricManager.Authenticators.Types final int strength =
|
||||
Utils.propertyStrengthToAuthenticatorStrength(props.sensorStrength);
|
||||
try {
|
||||
service.registerAuthenticator(props.sensorId, TYPE_FINGERPRINT, strength,
|
||||
new FingerprintAuthenticator(mService, props.sensorId));
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when registering sensorId: " + props.sensorId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invokeRegisteredCallback(
|
||||
@NonNull IFingerprintAuthenticatorsRegisteredCallback callback,
|
||||
@NonNull List<FingerprintSensorPropertiesInternal> allProps) throws RemoteException {
|
||||
callback.onAllAuthenticatorsRegistered(allProps);
|
||||
}
|
||||
}
|
||||
@@ -28,11 +28,14 @@ import android.hardware.fingerprint.IFingerprintServiceReceiver;
|
||||
import android.hardware.fingerprint.ISidefpsController;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.os.IBinder;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.server.biometrics.sensors.BiometricServiceProvider;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallback;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -56,8 +59,23 @@ import java.util.List;
|
||||
* fail safely.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public interface ServiceProvider extends
|
||||
BiometricServiceProvider<FingerprintSensorPropertiesInternal> {
|
||||
public interface ServiceProvider {
|
||||
/**
|
||||
* Checks if the specified sensor is owned by this provider.
|
||||
*/
|
||||
boolean containsSensor(int sensorId);
|
||||
|
||||
@NonNull
|
||||
List<FingerprintSensorPropertiesInternal> getSensorProperties();
|
||||
|
||||
/**
|
||||
* Returns the internal properties of the specified sensor, if owned by this provider.
|
||||
*
|
||||
* @param sensorId The ID of a fingerprint sensor, or -1 for any sensor.
|
||||
* @return An object representing the internal properties of the specified sensor.
|
||||
*/
|
||||
@Nullable
|
||||
FingerprintSensorPropertiesInternal getSensorProperties(int sensorId);
|
||||
|
||||
void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken);
|
||||
|
||||
@@ -108,11 +126,16 @@ public interface ServiceProvider extends
|
||||
void scheduleInternalCleanup(int sensorId, int userId,
|
||||
@Nullable ClientMonitorCallback callback, boolean favorHalEnrollments);
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to
|
||||
* be invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
|
||||
@@ -120,6 +143,7 @@ public interface ServiceProvider extends
|
||||
void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
|
||||
@NonNull IInvalidationCallback callback);
|
||||
|
||||
long getAuthenticatorId(int sensorId, int userId);
|
||||
|
||||
void onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major);
|
||||
|
||||
@@ -137,6 +161,13 @@ public interface ServiceProvider extends
|
||||
*/
|
||||
void setSidefpsController(@NonNull ISidefpsController controller);
|
||||
|
||||
void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
|
||||
boolean clearSchedulerBuffer);
|
||||
|
||||
void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);
|
||||
|
||||
void dumpInternal(int sensorId, @NonNull PrintWriter pw);
|
||||
|
||||
@NonNull
|
||||
ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
|
||||
@NonNull String opPackageName);
|
||||
|
||||
@@ -564,11 +564,6 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
return FingerprintUtils.getInstance(sensorId).getBiometricsForUser(mContext, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollments(int sensorId, int userId) {
|
||||
return !getEnrolledFingerprints(sensorId, userId).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
|
||||
@NonNull IInvalidationCallback callback) {
|
||||
|
||||
@@ -788,11 +788,6 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
return FingerprintUtils.getLegacyInstance(mSensorId).getBiometricsForUser(mContext, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnrollments(int sensorId, int userId) {
|
||||
return !getEnrolledFingerprints(sensorId, userId).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@LockoutTracker.LockoutMode public int getLockoutModeForUser(int sensorId, int userId) {
|
||||
return mLockoutTracker.getLockoutModeForUser(userId);
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK;
|
||||
import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
|
||||
import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.face.FaceSensorProperties;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.face.IFaceService;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class FaceServiceRegistryTest {
|
||||
|
||||
private static final int SENSOR_ID_1 = 1;
|
||||
private static final int SENSOR_ID_2 = 2;
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
private IBiometricService mBiometricService;
|
||||
@Mock
|
||||
private IFaceService mFaceService;
|
||||
@Mock
|
||||
private ServiceProvider mProvider1;
|
||||
@Mock
|
||||
private ServiceProvider mProvider2;
|
||||
@Captor
|
||||
private ArgumentCaptor<Integer> mIdCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<Integer> mStrengthCaptor;
|
||||
|
||||
private FaceSensorPropertiesInternal mProvider1Props;
|
||||
private FaceSensorPropertiesInternal mProvider2Props;
|
||||
private FaceServiceRegistry mRegistry;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mProvider1Props = new FaceSensorPropertiesInternal(SENSOR_ID_1,
|
||||
STRENGTH_WEAK, 5 /* maxEnrollmentsPerUser */,
|
||||
List.of(), FaceSensorProperties.TYPE_RGB,
|
||||
true /* supportsFace Detection */,
|
||||
true /* supportsSelfIllumination */,
|
||||
false /* resetLockoutRequiresHardwareAuthToken */);
|
||||
mProvider2Props = new FaceSensorPropertiesInternal(SENSOR_ID_2,
|
||||
STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */,
|
||||
List.of(), FaceSensorProperties.TYPE_IR,
|
||||
true /* supportsFace Detection */,
|
||||
true /* supportsSelfIllumination */,
|
||||
false /* resetLockoutRequiresHardwareAuthToken */);
|
||||
|
||||
when(mProvider1.getSensorProperties()).thenReturn(List.of(mProvider1Props));
|
||||
when(mProvider1.containsSensor(eq(SENSOR_ID_1))).thenReturn(true);
|
||||
when(mProvider2.getSensorProperties()).thenReturn(List.of(mProvider2Props));
|
||||
when(mProvider2.containsSensor(eq(SENSOR_ID_2))).thenReturn(true);
|
||||
mRegistry = new FaceServiceRegistry(mFaceService, () -> mBiometricService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersAllProviders() throws Exception {
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
|
||||
|
||||
assertThat(mRegistry.getProviders()).containsExactly(mProvider1, mProvider2);
|
||||
assertThat(mRegistry.getAllProperties()).containsExactly(mProvider1Props, mProvider2Props);
|
||||
verify(mBiometricService, times(2)).registerAuthenticator(
|
||||
mIdCaptor.capture(), eq(TYPE_FACE), mStrengthCaptor.capture(), any());
|
||||
assertThat(mIdCaptor.getAllValues()).containsExactly(SENSOR_ID_1, SENSOR_ID_2);
|
||||
assertThat(mStrengthCaptor.getAllValues())
|
||||
.containsExactly(BIOMETRIC_WEAK, BIOMETRIC_STRONG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsProviderById() {
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
|
||||
|
||||
assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1);
|
||||
assertThat(mRegistry.getProviderForSensor(SENSOR_ID_2)).isSameInstanceAs(mProvider2);
|
||||
assertThat(mRegistry.getProviderForSensor(500)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsSingleProvider() {
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1));
|
||||
|
||||
assertThat(mRegistry.getSingleProvider().second).isSameInstanceAs(mProvider1);
|
||||
assertThat(mRegistry.getProviders()).containsExactly(mProvider1);
|
||||
assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersListenerBeforeAllRegistered() {
|
||||
final List<FaceSensorPropertiesInternal> all = new ArrayList<>();
|
||||
mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FaceSensorPropertiesInternal> sensors) {
|
||||
all.addAll(sensors);
|
||||
}
|
||||
});
|
||||
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
|
||||
|
||||
assertThat(all).containsExactly(mProvider1Props, mProvider2Props);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersListenerAfterAllRegistered() {
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
|
||||
|
||||
final List<FaceSensorPropertiesInternal> all = new ArrayList<>();
|
||||
mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FaceSensorPropertiesInternal> sensors) {
|
||||
all.addAll(sensors);
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(all).containsExactly(mProvider1Props, mProvider2Props);
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.server.biometrics.sensors.fingerprint;
|
||||
|
||||
import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -26,72 +24,37 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.pm.UserInfo;
|
||||
import android.hardware.biometrics.BiometricStateListener;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.BiometricServiceProvider;
|
||||
import com.android.server.biometrics.sensors.BiometricStateCallback;
|
||||
import com.android.server.biometrics.sensors.EnrollClient;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.List;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class BiometricStateCallbackTest {
|
||||
|
||||
private static final int USER_ID = 10;
|
||||
private static final int SENSOR_ID = 2;
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
private BiometricStateCallback<FakeProvider, SensorPropertiesInternal> mCallback;
|
||||
private BiometricStateCallback mCallback;
|
||||
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private BiometricStateListener mBiometricStateListener;
|
||||
@Mock
|
||||
private FakeProvider mFakeProvider;
|
||||
|
||||
private SensorPropertiesInternal mFakeProviderProps;
|
||||
BiometricStateListener mBiometricStateListener;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mFakeProviderProps = new SensorPropertiesInternal(SENSOR_ID, STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */, List.of(),
|
||||
false /* resetLockoutRequiresHardwareAuthToken */,
|
||||
false /* resetLockoutRequiresChallenge */);
|
||||
when(mFakeProvider.getSensorProperties()).thenReturn(List.of(mFakeProviderProps));
|
||||
when(mFakeProvider.getSensorProperties(eq(SENSOR_ID))).thenReturn(mFakeProviderProps);
|
||||
when(mFakeProvider.hasEnrollments(eq(SENSOR_ID), eq(USER_ID))).thenReturn(true);
|
||||
when(mUserManager.getAliveUsers()).thenReturn(
|
||||
List.of(new UserInfo(USER_ID, "name", 0)));
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mCallback = new BiometricStateCallback<>(mUserManager);
|
||||
mCallback = new BiometricStateCallback();
|
||||
mCallback.registerBiometricStateListener(mBiometricStateListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startNotifiesEnrollments() {
|
||||
mCallback.start(List.of(mFakeProvider));
|
||||
|
||||
verify(mBiometricStateListener).onEnrollmentsChanged(eq(USER_ID), eq(SENSOR_ID), eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoEnrollmentsToEnrollments_callbackNotified() {
|
||||
testEnrollmentCallback(true /* changed */, true /* isNowEnrolled */,
|
||||
@@ -139,6 +102,4 @@ public class BiometricStateCallbackTest {
|
||||
verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
|
||||
anyBoolean());
|
||||
}
|
||||
|
||||
private interface FakeProvider extends BiometricServiceProvider<SensorPropertiesInternal> {}
|
||||
}
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK;
|
||||
import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
|
||||
import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.fingerprint.IFingerprintService;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class FingerprintServiceRegistryTest {
|
||||
|
||||
private static final int SENSOR_ID_1 = 1;
|
||||
private static final int SENSOR_ID_2 = 2;
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
private IBiometricService mBiometricService;
|
||||
@Mock
|
||||
private IFingerprintService mFingerprintService;
|
||||
@Mock
|
||||
private ServiceProvider mProvider1;
|
||||
@Mock
|
||||
private ServiceProvider mProvider2;
|
||||
@Captor
|
||||
private ArgumentCaptor<Integer> mIdCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<Integer> mStrengthCaptor;
|
||||
|
||||
private FingerprintSensorPropertiesInternal mProvider1Props;
|
||||
private FingerprintSensorPropertiesInternal mProvider2Props;
|
||||
private FingerprintServiceRegistry mRegistry;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mProvider1Props = new FingerprintSensorPropertiesInternal(SENSOR_ID_1,
|
||||
STRENGTH_WEAK, 5 /* maxEnrollmentsPerUser */,
|
||||
List.of(), FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
false /* resetLockoutRequiresHardwareAuthToken */);
|
||||
mProvider2Props = new FingerprintSensorPropertiesInternal(SENSOR_ID_2,
|
||||
STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */,
|
||||
List.of(), FingerprintSensorProperties.TYPE_UNKNOWN,
|
||||
false /* resetLockoutRequiresHardwareAuthToken */);
|
||||
|
||||
when(mProvider1.getSensorProperties()).thenReturn(List.of(mProvider1Props));
|
||||
when(mProvider1.containsSensor(eq(SENSOR_ID_1))).thenReturn(true);
|
||||
when(mProvider2.getSensorProperties()).thenReturn(List.of(mProvider2Props));
|
||||
when(mProvider2.containsSensor(eq(SENSOR_ID_2))).thenReturn(true);
|
||||
mRegistry = new FingerprintServiceRegistry(mFingerprintService, () -> mBiometricService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersAllProviders() throws Exception {
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
|
||||
|
||||
assertThat(mRegistry.getProviders()).containsExactly(mProvider1, mProvider2);
|
||||
assertThat(mRegistry.getAllProperties()).containsExactly(mProvider1Props, mProvider2Props);
|
||||
verify(mBiometricService, times(2)).registerAuthenticator(
|
||||
mIdCaptor.capture(), eq(TYPE_FINGERPRINT), mStrengthCaptor.capture(), any());
|
||||
assertThat(mIdCaptor.getAllValues()).containsExactly(SENSOR_ID_1, SENSOR_ID_2);
|
||||
assertThat(mStrengthCaptor.getAllValues())
|
||||
.containsExactly(BIOMETRIC_WEAK, BIOMETRIC_STRONG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsProviderById() {
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
|
||||
|
||||
assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1);
|
||||
assertThat(mRegistry.getProviderForSensor(SENSOR_ID_2)).isSameInstanceAs(mProvider2);
|
||||
assertThat(mRegistry.getProviderForSensor(500)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsSingleProvider() {
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1));
|
||||
|
||||
assertThat(mRegistry.getSingleProvider().second).isSameInstanceAs(mProvider1);
|
||||
assertThat(mRegistry.getProviders()).containsExactly(mProvider1);
|
||||
assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersListenerBeforeAllRegistered() {
|
||||
final List<FingerprintSensorPropertiesInternal> all = new ArrayList<>();
|
||||
mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
all.addAll(sensors);
|
||||
}
|
||||
});
|
||||
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
|
||||
|
||||
assertThat(all).containsExactly(mProvider1Props, mProvider2Props);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersListenerAfterAllRegistered() {
|
||||
mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2));
|
||||
|
||||
final List<FingerprintSensorPropertiesInternal> all = new ArrayList<>();
|
||||
mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
all.addAll(sensors);
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(all).containsExactly(mProvider1Props, mProvider2Props);
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,7 @@ import android.hardware.biometrics.fingerprint.FingerprintSensorType;
|
||||
import android.hardware.biometrics.fingerprint.IFingerprint;
|
||||
import android.hardware.biometrics.fingerprint.SensorLocation;
|
||||
import android.hardware.biometrics.fingerprint.SensorProps;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.provider.Settings;
|
||||
import android.testing.TestableContext;
|
||||
@@ -53,8 +52,6 @@ import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@@ -97,12 +94,9 @@ public class FingerprintServiceTest {
|
||||
|
||||
mContext.getTestablePermissions().setPermission(
|
||||
USE_BIOMETRIC_INTERNAL, PackageManager.PERMISSION_GRANTED);
|
||||
}
|
||||
|
||||
private void initServiceWith(String... aidlInstances) {
|
||||
mService = new FingerprintService(mContext, mBiometricContext,
|
||||
() -> mIBiometricService,
|
||||
() -> aidlInstances,
|
||||
(fqName) -> {
|
||||
if (fqName.endsWith(NAME_DEFAULT)) return mIFingerprintDefault;
|
||||
if (fqName.endsWith(NAME_VIRTUAL)) return mIFingerprintVirtual;
|
||||
@@ -111,50 +105,29 @@ public class FingerprintServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerAuthenticators_defaultOnly() throws Exception {
|
||||
initServiceWith(NAME_DEFAULT, NAME_VIRTUAL);
|
||||
|
||||
mService.mServiceWrapper.registerAuthenticators(List.of());
|
||||
waitForRegistration();
|
||||
public void registerAuthenticators_defaultOnly() throws RemoteException {
|
||||
mService.registerAuthenticatorsForService(List.of(NAME_DEFAULT, NAME_VIRTUAL), List.of());
|
||||
|
||||
verify(mIBiometricService).registerAuthenticator(eq(ID_DEFAULT), anyInt(), anyInt(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerAuthenticators_virtualOnly() throws Exception {
|
||||
initServiceWith(NAME_DEFAULT, NAME_VIRTUAL);
|
||||
public void registerAuthenticators_virtualOnly() throws RemoteException {
|
||||
Settings.Secure.putInt(mSettingsRule.mockContentResolver(mContext),
|
||||
Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 1);
|
||||
|
||||
mService.mServiceWrapper.registerAuthenticators(List.of());
|
||||
waitForRegistration();
|
||||
mService.registerAuthenticatorsForService(List.of(NAME_DEFAULT, NAME_VIRTUAL), List.of());
|
||||
|
||||
verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerAuthenticators_virtualAlwaysWhenNoOther() throws Exception {
|
||||
initServiceWith(NAME_VIRTUAL);
|
||||
|
||||
mService.mServiceWrapper.registerAuthenticators(List.of());
|
||||
waitForRegistration();
|
||||
public void registerAuthenticators_virtualAlwaysWhenNoOther() throws RemoteException {
|
||||
mService.registerAuthenticatorsForService(List.of(NAME_VIRTUAL), List.of());
|
||||
|
||||
verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
|
||||
}
|
||||
|
||||
private void waitForRegistration() throws Exception {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
mService.mServiceWrapper.addAuthenticatorsRegisteredCallback(
|
||||
new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override
|
||||
public void onAllAuthenticatorsRegistered(
|
||||
List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
latch.await(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private static SensorProps createProps(int id, byte strength, byte type) {
|
||||
final SensorProps props = new SensorProps();
|
||||
props.commonProps = new CommonProps();
|
||||
|
||||
Reference in New Issue
Block a user