Merge changes I165d67bd,I4442db15 into sc-dev
* changes: Notify AuthController when fingerprint providers are ready Consolidate registration of HIDL and AIDL HALs
This commit is contained in:
committed by
Android (Google) Code Review
commit
bbddf477af
@@ -44,7 +44,7 @@ public class SensorPropertiesInternal implements Parcelable {
|
||||
prop.resetLockoutRequiresHardwareAuthToken, prop.resetLockoutRequiresChallenge);
|
||||
}
|
||||
|
||||
protected SensorPropertiesInternal(int sensorId, @SensorProperties.Strength int sensorStrength,
|
||||
public SensorPropertiesInternal(int sensorId, @SensorProperties.Strength int sensorStrength,
|
||||
int maxEnrollmentsPerUser, @NonNull List<ComponentInfoInternal> componentInfo,
|
||||
boolean resetLockoutRequiresHardwareAuthToken, boolean resetLockoutRequiresChallenge) {
|
||||
this.sensorId = sensorId;
|
||||
|
||||
@@ -127,6 +127,8 @@ interface IFaceService {
|
||||
void getFeature(IBinder token, int userId, int feature, IFaceServiceReceiver receiver,
|
||||
String opPackageName);
|
||||
|
||||
// Give FaceService its ID. See AuthService.java
|
||||
void initializeConfiguration(int sensorId, int strength);
|
||||
// Registers all HIDL and AIDL sensors. Only HIDL sensor properties need to be provided, because
|
||||
// AIDL sensor properties are retrieved directly from the available HALs. If no HIDL HALs exist,
|
||||
// hidlSensors must be non-null and empty. See AuthService.java
|
||||
void registerAuthenticators(in List<FaceSensorPropertiesInternal> hidlSensors);
|
||||
}
|
||||
|
||||
@@ -1012,6 +1012,31 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
||||
return sensorProps.sensorType == TYPE_POWER_BUTTON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a callback that gets called when the service registers all of the fingerprint
|
||||
* authenticators (HALs).
|
||||
*
|
||||
* If the fingerprint 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(
|
||||
IFingerprintAuthenticatorsRegisteredCallback callback) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.addAuthenticatorsRegisteredCallback(callback);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
} else {
|
||||
Slog.w(TAG, "addProvidersAvailableCallback(): Service not connected!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,6 @@ import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFP
|
||||
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
@@ -92,34 +91,6 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna
|
||||
1636 /* sensorLocationY */, 130 /* sensorRadius */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes SensorProperties with specified values and values obtained from resources using
|
||||
* context.
|
||||
*/
|
||||
// TODO(b/179175438): Remove this constructor once all HALs move to AIDL.
|
||||
public FingerprintSensorPropertiesInternal(@NonNull Context context, int sensorId,
|
||||
@SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
|
||||
@NonNull List<ComponentInfoInternal> componentInfo,
|
||||
@FingerprintSensorProperties.SensorType int sensorType,
|
||||
boolean resetLockoutRequiresHardwareAuthToken) {
|
||||
super(sensorId, strength, maxEnrollmentsPerUser, componentInfo,
|
||||
resetLockoutRequiresHardwareAuthToken, false /* resetLockoutRequiresChallenge */);
|
||||
this.sensorType = sensorType;
|
||||
|
||||
int[] props = context.getResources().getIntArray(
|
||||
com.android.internal.R.array.config_udfps_sensor_props);
|
||||
if (props != null && props.length == 3) {
|
||||
this.sensorLocationX = props[0];
|
||||
this.sensorLocationY = props[1];
|
||||
this.sensorRadius = props[2];
|
||||
} else {
|
||||
// Fake coordinates that could be used for the fake UDFPS mode.
|
||||
this.sensorLocationX = 540;
|
||||
this.sensorLocationY = 1636;
|
||||
this.sensorRadius = 130;
|
||||
}
|
||||
}
|
||||
|
||||
protected FingerprintSensorPropertiesInternal(Parcel in) {
|
||||
super(in);
|
||||
sensorType = in.readInt();
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.fingerprint;
|
||||
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Callback to notify FingerprintManager that FingerprintService has registered all of the
|
||||
* fingerprint authenticators (HALs).
|
||||
* See {@link android.hardware.fingerprint.IFingerprintService#registerAuthenticators}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IFingerprintAuthenticatorsRegisteredCallback {
|
||||
/**
|
||||
* Notifies FingerprintManager that all of the fingerprint authenticators have been registered.
|
||||
*
|
||||
* @param sensors A consolidated list of sensor properties for all of the authenticators.
|
||||
*/
|
||||
void onAllAuthenticatorsRegistered(in List<FingerprintSensorPropertiesInternal> sensors);
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.ITestSessionCallback;
|
||||
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.fingerprint.IFingerprintServiceReceiver;
|
||||
import android.hardware.fingerprint.IFingerprintStateListener;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
@@ -144,8 +145,14 @@ interface IFingerprintService {
|
||||
// Removes a callback set by addClientActiveCallback
|
||||
void removeClientActiveCallback(IFingerprintClientActiveCallback callback);
|
||||
|
||||
// Give FingerprintService its ID. See AuthService.java
|
||||
void initializeConfiguration(int sensorId, int strength);
|
||||
// Registers all HIDL and AIDL sensors. Only HIDL sensor properties need to be provided, because
|
||||
// AIDL sensor properties are retrieved directly from the available HALs. If no HIDL HALs exist,
|
||||
// hidlSensors must be non-null and empty. See AuthService.java
|
||||
void registerAuthenticators(in List<FingerprintSensorPropertiesInternal> hidlSensors);
|
||||
|
||||
// Adds a callback which gets called when the service registers all of the fingerprint
|
||||
// authenticators. The callback is automatically removed after it's invoked.
|
||||
void addAuthenticatorsRegisteredCallback(IFingerprintAuthenticatorsRegisteredCallback callback);
|
||||
|
||||
// Notifies about a finger touching the sensor area.
|
||||
void onPointerDown(int sensorId, int x, int y, float minor, float major);
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package android.hardware.iris;
|
||||
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
|
||||
/**
|
||||
* Communication channel from client to the iris service. These methods are all require the
|
||||
* MANAGE_BIOMETRIC signature permission.
|
||||
* @hide
|
||||
*/
|
||||
interface IIrisService {
|
||||
// Give IrisService its ID. See AuthService.java
|
||||
void initializeConfiguration(int sensorId, int strength);
|
||||
// Registers all HIDL and AIDL sensors. Only HIDL sensor properties need to be provided, because
|
||||
// AIDL sensor properties are retrieved directly from the available HALs. If no HIDL HALs exist,
|
||||
// hidlSensors must be non-null and empty. See AuthService.java
|
||||
void registerAuthenticators(in List<SensorPropertiesInternal> hidlSensors);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityTaskManager;
|
||||
@@ -39,6 +40,7 @@ import android.hardware.face.FaceManager;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -57,6 +59,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -73,16 +76,13 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
private static final String TAG = "AuthController";
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final StatusBarStateController mStatusBarStateController;
|
||||
private final ActivityTaskManager mActivityTaskManager;
|
||||
@Nullable private final FingerprintManager mFingerprintManager;
|
||||
@Nullable private final FaceManager mFaceManager;
|
||||
private final Provider<UdfpsController> mUdfpsControllerFactory;
|
||||
|
||||
@Nullable private final List<FingerprintSensorPropertiesInternal> mFpProps;
|
||||
@Nullable private final List<FaceSensorPropertiesInternal> mFaceProps;
|
||||
@Nullable private final List<FingerprintSensorPropertiesInternal> mUdfpsProps;
|
||||
@Nullable private final PointF mFaceAuthSensorLocation;
|
||||
|
||||
// TODO: These should just be saved from onSaveState
|
||||
@@ -90,7 +90,6 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
@VisibleForTesting
|
||||
AuthDialog mCurrentDialog;
|
||||
|
||||
private Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private WindowManager mWindowManager;
|
||||
@Nullable
|
||||
private UdfpsController mUdfpsController;
|
||||
@@ -98,6 +97,9 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
TaskStackListener mTaskStackListener;
|
||||
@VisibleForTesting
|
||||
IBiometricSysuiReceiver mReceiver;
|
||||
@Nullable private final List<FaceSensorPropertiesInternal> mFaceProps;
|
||||
@Nullable private List<FingerprintSensorPropertiesInternal> mFpProps;
|
||||
@Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps;
|
||||
|
||||
private class BiometricTaskStackListener extends TaskStackListener {
|
||||
@Override
|
||||
@@ -106,8 +108,31 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@NonNull
|
||||
private final IFingerprintAuthenticatorsRegisteredCallback
|
||||
mFingerprintAuthenticatorsRegisteredCallback =
|
||||
new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
|
||||
@Override public void onAllAuthenticatorsRegistered(
|
||||
List<FingerprintSensorPropertiesInternal> sensors) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onFingerprintProvidersAvailable | sensors: " + Arrays.toString(
|
||||
sensors.toArray()));
|
||||
}
|
||||
mFpProps = sensors;
|
||||
List<FingerprintSensorPropertiesInternal> udfpsProps = new ArrayList<>();
|
||||
for (FingerprintSensorPropertiesInternal props : mFpProps) {
|
||||
if (props.isAnyUdfpsType()) {
|
||||
udfpsProps.add(props);
|
||||
}
|
||||
}
|
||||
mUdfpsProps = !udfpsProps.isEmpty() ? udfpsProps : null;
|
||||
if (mUdfpsProps != null) {
|
||||
mUdfpsController = mUdfpsControllerFactory.get();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@VisibleForTesting final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (mCurrentDialog != null
|
||||
@@ -348,19 +373,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
mFaceManager = faceManager;
|
||||
mUdfpsControllerFactory = udfpsControllerFactory;
|
||||
|
||||
mFpProps = mFingerprintManager != null ? mFingerprintManager.getSensorPropertiesInternal()
|
||||
: null;
|
||||
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
|
||||
|
||||
List<FingerprintSensorPropertiesInternal> udfpsProps = new ArrayList<>();
|
||||
if (mFpProps != null) {
|
||||
for (FingerprintSensorPropertiesInternal props : mFpProps) {
|
||||
if (props.isAnyUdfpsType()) {
|
||||
udfpsProps.add(props);
|
||||
}
|
||||
}
|
||||
}
|
||||
mUdfpsProps = !udfpsProps.isEmpty() ? udfpsProps : null;
|
||||
int[] faceAuthLocation = context.getResources().getIntArray(
|
||||
com.android.systemui.R.array.config_face_auth_props);
|
||||
if (faceAuthLocation == null || faceAuthLocation.length < 2) {
|
||||
@@ -383,9 +397,9 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
mCommandQueue.addCallback(this);
|
||||
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
|
||||
|
||||
if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()
|
||||
&& mUdfpsProps != null) {
|
||||
mUdfpsController = mUdfpsControllerFactory.get();
|
||||
if (mFingerprintManager != null) {
|
||||
mFingerprintManager.addAuthenticatorsRegisteredCallback(
|
||||
mFingerprintAuthenticatorsRegisteredCallback);
|
||||
}
|
||||
|
||||
mTaskStackListener = new BiometricTaskStackListener();
|
||||
@@ -527,7 +541,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
return mFaceManager.hasEnrolledTemplates(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Whether the passed userId has enrolled UDFPS.
|
||||
*/
|
||||
public boolean isUdfpsEnrolled(int userId) {
|
||||
|
||||
@@ -50,7 +50,9 @@ import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableContext;
|
||||
@@ -66,6 +68,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.AdditionalMatchers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@@ -100,12 +103,13 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
private FaceManager mFaceManager;
|
||||
@Mock
|
||||
private UdfpsController mUdfpsController;
|
||||
@Captor
|
||||
ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
|
||||
|
||||
private TestableAuthController mAuthController;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
public void setup() throws RemoteException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
TestableContext context = spy(mContext);
|
||||
@@ -148,6 +152,9 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
() -> mUdfpsController);
|
||||
|
||||
mAuthController.start();
|
||||
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
|
||||
mAuthenticatorsRegisteredCaptor.capture());
|
||||
mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props);
|
||||
}
|
||||
|
||||
// Callback tests
|
||||
|
||||
@@ -30,12 +30,14 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.IAuthService;
|
||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.IBiometricServiceReceiver;
|
||||
@@ -44,7 +46,11 @@ import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.ITestSessionCallback;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.hardware.face.FaceSensorProperties;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceService;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintService;
|
||||
import android.hardware.iris.IIrisService;
|
||||
import android.os.Binder;
|
||||
@@ -58,11 +64,10 @@ import android.util.Slog;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.biometrics.sensors.face.FaceAuthenticator;
|
||||
import com.android.server.biometrics.sensors.fingerprint.FingerprintAuthenticator;
|
||||
import com.android.server.biometrics.sensors.iris.IrisAuthenticator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -578,81 +583,119 @@ public class AuthService extends SystemService {
|
||||
mImpl = new AuthServiceImpl();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registration of all HIDL and AIDL biometric HALs starts here.
|
||||
* The flow looks like this:
|
||||
* AuthService
|
||||
* └── .onStart()
|
||||
* └── .registerAuthenticators(...)
|
||||
* ├── FaceService.registerAuthenticators(...)
|
||||
* │ └── for (p : serviceProviders)
|
||||
* │ └── for (s : p.sensors)
|
||||
* │ └── BiometricService.registerAuthenticator(s)
|
||||
* │
|
||||
* ├── FingerprintService.registerAuthenticators(...)
|
||||
* │ └── for (p : serviceProviders)
|
||||
* │ └── for (s : p.sensors)
|
||||
* │ └── BiometricService.registerAuthenticator(s)
|
||||
* │
|
||||
* └── IrisService.registerAuthenticators(...)
|
||||
* └── for (p : serviceProviders)
|
||||
* └── for (s : p.sensors)
|
||||
* └── BiometricService.registerAuthenticator(s)
|
||||
*/
|
||||
@Override
|
||||
public void onStart() {
|
||||
mBiometricService = mInjector.getBiometricService();
|
||||
|
||||
final SensorConfig[] hidlConfigs;
|
||||
if (!mInjector.isHidlDisabled(getContext())) {
|
||||
final String[] configs = mInjector.getConfiguration(getContext());
|
||||
for (String config : configs) {
|
||||
try {
|
||||
registerAuthenticator(new SensorConfig(config));
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception", e);
|
||||
}
|
||||
final String[] configStrings = mInjector.getConfiguration(getContext());
|
||||
hidlConfigs = new SensorConfig[configStrings.length];
|
||||
for (int i = 0; i < configStrings.length; ++i) {
|
||||
hidlConfigs[i] = new SensorConfig(configStrings[i]);
|
||||
}
|
||||
} else {
|
||||
hidlConfigs = null;
|
||||
}
|
||||
|
||||
// Registers HIDL and AIDL authenticators, but only HIDL configs need to be provided.
|
||||
registerAuthenticators(hidlConfigs);
|
||||
|
||||
mInjector.publishBinderService(this, mImpl);
|
||||
}
|
||||
|
||||
private void registerAuthenticator(SensorConfig config) throws RemoteException {
|
||||
Slog.d(TAG, "Registering ID: " + config.id
|
||||
+ " Modality: " + config.modality
|
||||
+ " Strength: " + config.strength);
|
||||
/**
|
||||
* Registers HIDL and AIDL authenticators for all of the available modalities.
|
||||
*
|
||||
* @param hidlSensors Array of {@link SensorConfig} configuration for all of the HIDL sensors
|
||||
* available on the device. This array may contain configuration for
|
||||
* different modalities and different sensors of the same modality in
|
||||
* arbitrary order. Can be null if no HIDL sensors exist on the device.
|
||||
*/
|
||||
private void registerAuthenticators(@Nullable SensorConfig[] hidlSensors) {
|
||||
List<FingerprintSensorPropertiesInternal> hidlFingerprintSensors = new ArrayList<>();
|
||||
List<FaceSensorPropertiesInternal> hidlFaceSensors = new ArrayList<>();
|
||||
// Iris doesn't have IrisSensorPropertiesInternal, using SensorPropertiesInternal instead.
|
||||
List<SensorPropertiesInternal> hidlIrisSensors = new ArrayList<>();
|
||||
|
||||
final IBiometricAuthenticator.Stub authenticator;
|
||||
if (hidlSensors != null) {
|
||||
for (SensorConfig sensor : hidlSensors) {
|
||||
Slog.d(TAG, "Registering HIDL ID: " + sensor.id + " Modality: " + sensor.modality
|
||||
+ " Strength: " + sensor.strength);
|
||||
switch (sensor.modality) {
|
||||
case TYPE_FINGERPRINT:
|
||||
hidlFingerprintSensors.add(
|
||||
getHidlFingerprintSensorProps(sensor.id, sensor.strength));
|
||||
break;
|
||||
|
||||
switch (config.modality) {
|
||||
case TYPE_FINGERPRINT:
|
||||
final IFingerprintService fingerprintService = mInjector.getFingerprintService();
|
||||
if (fingerprintService == null) {
|
||||
Slog.e(TAG, "Attempting to register with null FingerprintService."
|
||||
+ " Please check your device configuration.");
|
||||
return;
|
||||
case TYPE_FACE:
|
||||
hidlFaceSensors.add(getHidlFaceSensorProps(sensor.id, sensor.strength));
|
||||
break;
|
||||
|
||||
case TYPE_IRIS:
|
||||
hidlIrisSensors.add(getHidlIrisSensorProps(sensor.id, sensor.strength));
|
||||
break;
|
||||
|
||||
default:
|
||||
Slog.e(TAG, "Unknown modality: " + sensor.modality);
|
||||
}
|
||||
|
||||
// Initialize this outside of FingerprintAuthenticator. Only HIDL HALs require
|
||||
// initialization from here. AIDL HALs are initialized by FingerprintService since
|
||||
// the HAL interface provides ID, strength, and other configuration information.
|
||||
fingerprintService.initializeConfiguration(config.id, config.strength);
|
||||
authenticator = new FingerprintAuthenticator(fingerprintService, config.id);
|
||||
break;
|
||||
|
||||
case TYPE_FACE:
|
||||
final IFaceService faceService = mInjector.getFaceService();
|
||||
if (faceService == null) {
|
||||
Slog.e(TAG, "Attempting to register with null FaceService. Please check "
|
||||
+ " your device configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize this outside of FingerprintAuthenticator. Only HIDL HALs require
|
||||
// initialization from here. AIDL HALs are initialized by FaceService since
|
||||
// the HAL interface provides ID, strength, and other configuration information.
|
||||
faceService.initializeConfiguration(config.id, config.strength);
|
||||
authenticator = new FaceAuthenticator(faceService, config.id);
|
||||
break;
|
||||
|
||||
case TYPE_IRIS:
|
||||
final IIrisService irisService = mInjector.getIrisService();
|
||||
if (irisService == null) {
|
||||
Slog.e(TAG, "Attempting to register with null IrisService. Please check"
|
||||
+ " your device configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
irisService.initializeConfiguration(config.id, config.strength);
|
||||
authenticator = new IrisAuthenticator(irisService, config.id);
|
||||
break;
|
||||
|
||||
default:
|
||||
Slog.e(TAG, "Unknown modality: " + config.modality);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mBiometricService.registerAuthenticator(config.id, config.modality, config.strength,
|
||||
authenticator);
|
||||
final IFingerprintService fingerprintService = mInjector.getFingerprintService();
|
||||
if (fingerprintService != null) {
|
||||
try {
|
||||
fingerprintService.registerAuthenticators(hidlFingerprintSensors);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "RemoteException when registering fingerprint authenticators", e);
|
||||
}
|
||||
} else if (hidlFingerprintSensors.size() > 0) {
|
||||
Slog.e(TAG, "HIDL fingerprint configuration exists, but FingerprintService is null.");
|
||||
}
|
||||
|
||||
final IFaceService faceService = mInjector.getFaceService();
|
||||
if (faceService != null) {
|
||||
try {
|
||||
faceService.registerAuthenticators(hidlFaceSensors);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "RemoteException when registering face authenticators", e);
|
||||
}
|
||||
} else if (hidlFaceSensors.size() > 0) {
|
||||
Slog.e(TAG, "HIDL face configuration exists, but FaceService is null.");
|
||||
}
|
||||
|
||||
final IIrisService irisService = mInjector.getIrisService();
|
||||
if (irisService != null) {
|
||||
try {
|
||||
irisService.registerAuthenticators(hidlIrisSensors);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "RemoteException when registering iris authenticators", e);
|
||||
}
|
||||
} else if (hidlIrisSensors.size() > 0) {
|
||||
Slog.e(TAG, "HIDL iris configuration exists, but IrisService is null.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkInternalPermission() {
|
||||
@@ -678,4 +721,72 @@ public class AuthService extends SystemService {
|
||||
return modality == BiometricAuthenticator.TYPE_CREDENTIAL
|
||||
? modality : (modality & ~BiometricAuthenticator.TYPE_CREDENTIAL);
|
||||
}
|
||||
|
||||
|
||||
private FingerprintSensorPropertiesInternal getHidlFingerprintSensorProps(int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength) {
|
||||
// The existence of config_udfps_sensor_props indicates that the sensor is UDFPS.
|
||||
final int[] udfpsProps = getContext().getResources().getIntArray(
|
||||
com.android.internal.R.array.config_udfps_sensor_props);
|
||||
|
||||
final boolean isUdfps = !ArrayUtils.isEmpty(udfpsProps);
|
||||
|
||||
// config_is_powerbutton_fps indicates whether device has a power button fingerprint sensor.
|
||||
final boolean isPowerbuttonFps = getContext().getResources().getBoolean(
|
||||
R.bool.config_is_powerbutton_fps);
|
||||
|
||||
final @FingerprintSensorProperties.SensorType int sensorType;
|
||||
if (isUdfps) {
|
||||
sensorType = FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||
} else if (isPowerbuttonFps) {
|
||||
sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON;
|
||||
} else {
|
||||
sensorType = FingerprintSensorProperties.TYPE_REAR;
|
||||
}
|
||||
|
||||
// IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT
|
||||
// cannot be checked.
|
||||
final boolean resetLockoutRequiresHardwareAuthToken = false;
|
||||
final int maxEnrollmentsPerUser = getContext().getResources().getInteger(
|
||||
R.integer.config_fingerprintMaxTemplatesPerUser);
|
||||
|
||||
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
|
||||
if (isUdfps && udfpsProps.length == 3) {
|
||||
return new FingerprintSensorPropertiesInternal(sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser,
|
||||
componentInfo, sensorType, resetLockoutRequiresHardwareAuthToken, udfpsProps[0],
|
||||
udfpsProps[1], udfpsProps[2]);
|
||||
} else {
|
||||
return new FingerprintSensorPropertiesInternal(sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser,
|
||||
componentInfo, sensorType, resetLockoutRequiresHardwareAuthToken);
|
||||
}
|
||||
}
|
||||
|
||||
private FaceSensorPropertiesInternal getHidlFaceSensorProps(int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength) {
|
||||
final boolean supportsSelfIllumination = getContext().getResources().getBoolean(
|
||||
R.bool.config_faceAuthSupportsSelfIllumination);
|
||||
final int maxTemplatesAllowed = getContext().getResources().getInteger(
|
||||
R.integer.config_faceMaxTemplatesPerUser);
|
||||
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
|
||||
final boolean supportsFaceDetect = false;
|
||||
final boolean resetLockoutRequiresChallenge = true;
|
||||
return new FaceSensorPropertiesInternal(sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength), maxTemplatesAllowed,
|
||||
componentInfo, FaceSensorProperties.TYPE_UNKNOWN, supportsFaceDetect,
|
||||
supportsSelfIllumination, resetLockoutRequiresChallenge);
|
||||
}
|
||||
|
||||
private SensorPropertiesInternal getHidlIrisSensorProps(int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength) {
|
||||
final int maxEnrollmentsPerUser = 1;
|
||||
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
|
||||
final boolean resetLockoutRequiresHardwareAuthToken = false;
|
||||
final boolean resetLockoutRequiresChallenge = false;
|
||||
return new SensorPropertiesInternal(sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser,
|
||||
componentInfo, resetLockoutRequiresHardwareAuthToken,
|
||||
resetLockoutRequiresChallenge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.sensors;
|
||||
|
||||
/**
|
||||
* System_server services that require BiometricService to load before finishing initialization
|
||||
* should implement this interface.
|
||||
*/
|
||||
public interface BiometricServiceCallback {
|
||||
/**
|
||||
* Notifies the service that BiometricService is initialized.
|
||||
*/
|
||||
void onBiometricServiceReady();
|
||||
}
|
||||
@@ -36,7 +36,7 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
|
||||
private final IFaceService mFaceService;
|
||||
private final int mSensorId;
|
||||
|
||||
public FaceAuthenticator(IFaceService faceService, int sensorId) throws RemoteException {
|
||||
public FaceAuthenticator(IFaceService faceService, int sensorId) {
|
||||
mFaceService = faceService;
|
||||
mSensorId = sensorId;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ 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.sensors.BiometricServiceCallback;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
@@ -76,7 +75,7 @@ import java.util.List;
|
||||
* The service is responsible for maintaining a list of clients and dispatching all
|
||||
* face-related events.
|
||||
*/
|
||||
public class FaceService extends SystemService implements BiometricServiceCallback {
|
||||
public class FaceService extends SystemService {
|
||||
|
||||
protected static final String TAG = "FaceService";
|
||||
|
||||
@@ -618,12 +617,76 @@ public class FaceService extends SystemService implements BiometricServiceCallba
|
||||
new ClientMonitorCallbackConverter(receiver), opPackageName);
|
||||
}
|
||||
|
||||
private void addHidlProviders(@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
|
||||
for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
|
||||
mServiceProviders.add(
|
||||
new Face10(getContext(), hidlSensor, mLockoutResetDispatcher));
|
||||
}
|
||||
}
|
||||
|
||||
private void addAidlProviders() {
|
||||
final String[] instances = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR);
|
||||
if (instances == null || instances.length == 0) {
|
||||
return;
|
||||
}
|
||||
for (String instance : instances) {
|
||||
final String fqName = IFace.DESCRIPTOR + "/" + instance;
|
||||
final IFace face = IFace.Stub.asInterface(
|
||||
ServiceManager.waitForDeclaredService(fqName));
|
||||
if (face == null) {
|
||||
Slog.e(TAG, "Unable to get declared service: " + fqName);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
final SensorProps[] props = face.getSensorProps();
|
||||
final FaceProvider provider = new FaceProvider(getContext(), props, instance,
|
||||
mLockoutResetDispatcher);
|
||||
mServiceProviders.add(provider);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void initializeConfiguration(int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength) {
|
||||
public void registerAuthenticators(
|
||||
@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
mServiceProviders.add(
|
||||
new Face10(getContext(), sensorId, strength, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,57 +698,6 @@ public class FaceService extends SystemService implements BiometricServiceCallba
|
||||
mServiceProviders = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBiometricServiceReady() {
|
||||
final IBiometricService biometricService = IBiometricService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.BIOMETRIC_SERVICE));
|
||||
|
||||
final String[] instances = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR);
|
||||
if (instances == null || instances.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If for some reason the HAL is not started before the system service, do not block
|
||||
// the rest of system server. 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(() -> {
|
||||
for (String instance : instances) {
|
||||
final String fqName = IFace.DESCRIPTOR + "/" + instance;
|
||||
final IFace face = IFace.Stub.asInterface(
|
||||
ServiceManager.waitForDeclaredService(fqName));
|
||||
try {
|
||||
final SensorProps[] props = face.getSensorProps();
|
||||
final FaceProvider provider = new FaceProvider(getContext(), props, instance,
|
||||
mLockoutResetDispatcher);
|
||||
mServiceProviders.add(provider);
|
||||
|
||||
// Register each sensor individually with BiometricService
|
||||
for (SensorProps prop : props) {
|
||||
final int sensorId = prop.commonProps.sensorId;
|
||||
@BiometricManager.Authenticators.Types int strength =
|
||||
Utils.propertyStrengthToAuthenticatorStrength(
|
||||
prop.commonProps.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);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when initializing instance: " + fqName);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
publishBinderService(Context.FACE_SERVICE, mServiceWrapper);
|
||||
|
||||
@@ -25,15 +25,12 @@ import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.hardware.biometrics.BiometricConstants;
|
||||
import android.hardware.biometrics.BiometricFaceConstants;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.ITestSessionCallback;
|
||||
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
|
||||
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
|
||||
import android.hardware.face.Face;
|
||||
import android.hardware.face.FaceSensorProperties;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceServiceReceiver;
|
||||
import android.os.Binder;
|
||||
@@ -51,7 +48,6 @@ import android.provider.Settings;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.biometrics.SensorServiceStateProto;
|
||||
@@ -66,7 +62,6 @@ import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.EnumerateConsumer;
|
||||
import com.android.server.biometrics.sensors.ErrorConsumer;
|
||||
import com.android.server.biometrics.sensors.HalClientMonitor;
|
||||
import com.android.server.biometrics.sensors.Interruptable;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
import com.android.server.biometrics.sensors.PerformanceTracker;
|
||||
@@ -327,19 +322,13 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Face10(@NonNull Context context, int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength,
|
||||
@VisibleForTesting Face10(@NonNull Context context,
|
||||
@NonNull FaceSensorPropertiesInternal sensorProps,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
boolean supportsSelfIllumination, int maxTemplatesAllowed,
|
||||
@NonNull BiometricScheduler scheduler) {
|
||||
mSensorProperties = new FaceSensorPropertiesInternal(sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength),
|
||||
maxTemplatesAllowed, new ArrayList<ComponentInfoInternal>() /* componentInfo */,
|
||||
FaceSensorProperties.TYPE_UNKNOWN, false /* supportsFaceDetect */,
|
||||
supportsSelfIllumination, true /* resetLockoutRequiresChallenge */);
|
||||
mSensorProperties = sensorProps;
|
||||
mContext = context;
|
||||
mSensorId = sensorId;
|
||||
mSensorId = sensorProps.sensorId;
|
||||
mScheduler = scheduler;
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mUsageStats = new UsageStats(context);
|
||||
@@ -347,8 +336,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
mLazyDaemon = Face10.this::getDaemon;
|
||||
mLockoutTracker = new LockoutHalImpl();
|
||||
mLockoutResetDispatcher = lockoutResetDispatcher;
|
||||
mHalResultController = new HalResultController(sensorId, context, mHandler, mScheduler,
|
||||
mLockoutTracker, lockoutResetDispatcher);
|
||||
mHalResultController = new HalResultController(sensorProps.sensorId, context, mHandler,
|
||||
mScheduler, mLockoutTracker, lockoutResetDispatcher);
|
||||
mHalResultController.setCallback(() -> {
|
||||
mDaemon = null;
|
||||
mCurrentUserId = UserHandle.USER_NULL;
|
||||
@@ -361,12 +350,9 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public Face10(@NonNull Context context, int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength,
|
||||
public Face10(@NonNull Context context, @NonNull FaceSensorPropertiesInternal sensorProps,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
|
||||
this(context, sensorId, strength, lockoutResetDispatcher,
|
||||
context.getResources().getBoolean(R.bool.config_faceAuthSupportsSelfIllumination),
|
||||
context.getResources().getInteger(R.integer.config_faceMaxTemplatesPerUser),
|
||||
this(context, sensorProps, lockoutResetDispatcher,
|
||||
new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */));
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
|
||||
private final IFingerprintService mFingerprintService;
|
||||
private final int mSensorId;
|
||||
|
||||
public FingerprintAuthenticator(IFingerprintService fingerprintService, int sensorId)
|
||||
throws RemoteException {
|
||||
public FingerprintAuthenticator(IFingerprintService fingerprintService, int sensorId) {
|
||||
mFingerprintService = fingerprintService;
|
||||
mSensorId = sensorId;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.hardware.fingerprint.Fingerprint;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.FingerprintServiceReceiver;
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
|
||||
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
|
||||
import android.hardware.fingerprint.IFingerprintService;
|
||||
import android.hardware.fingerprint.IFingerprintServiceReceiver;
|
||||
@@ -61,6 +62,7 @@ import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
@@ -71,12 +73,12 @@ import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
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.sensors.BiometricServiceCallback;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
|
||||
import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
@@ -96,18 +98,26 @@ import java.util.concurrent.Executor;
|
||||
* The service is responsible for maintaining a list of clients and dispatching all
|
||||
* fingerprint-related events.
|
||||
*/
|
||||
public class FingerprintService extends SystemService implements BiometricServiceCallback {
|
||||
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;
|
||||
private final FingerprintServiceWrapper mServiceWrapper;
|
||||
@NonNull private List<ServiceProvider> mServiceProviders;
|
||||
@NonNull private final List<ServiceProvider> mServiceProviders;
|
||||
@NonNull private final FingerprintStateCallback mFingerprintStateCallback;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@NonNull private final RemoteCallbackList<IFingerprintAuthenticatorsRegisteredCallback>
|
||||
mAuthenticatorsRegisteredCallbacks;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@NonNull private final List<FingerprintSensorPropertiesInternal> mSensorProps;
|
||||
|
||||
/**
|
||||
* Registers FingerprintStateListener in list stored by FingerprintService
|
||||
* @param listener new FingerprintStateListener being added
|
||||
@@ -745,7 +755,7 @@ public class FingerprintService extends SystemService implements BiometricServic
|
||||
|
||||
@Override // Binder call
|
||||
public void resetLockout(IBinder token, int sensorId, int userId,
|
||||
@Nullable byte [] hardwareAuthToken, String opPackageName) {
|
||||
@Nullable byte[] hardwareAuthToken, String opPackageName) {
|
||||
Utils.checkPermission(getContext(), RESET_FINGERPRINT_LOCKOUT);
|
||||
|
||||
final ServiceProvider provider = getProviderForSensor(sensorId);
|
||||
@@ -775,24 +785,119 @@ public class FingerprintService extends SystemService implements BiometricServic
|
||||
mGestureAvailabilityDispatcher.removeCallback(callback);
|
||||
}
|
||||
|
||||
private void addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors) {
|
||||
for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) {
|
||||
final Fingerprint21 fingerprint21;
|
||||
if ((Build.IS_USERDEBUG || Build.IS_ENG)
|
||||
&& getContext().getResources().getBoolean(R.bool.allow_test_udfps)
|
||||
&& Settings.Secure.getIntForUser(getContext().getContentResolver(),
|
||||
Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
|
||||
UserHandle.USER_CURRENT) != 0) {
|
||||
fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), hidlSensor,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
} else {
|
||||
fingerprint21 = Fingerprint21.newInstance(getContext(), hidlSensor,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
}
|
||||
mServiceProviders.add(fingerprint21);
|
||||
}
|
||||
}
|
||||
|
||||
private void addAidlProviders() {
|
||||
final String[] instances = ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR);
|
||||
if (instances == null || instances.length == 0) {
|
||||
return;
|
||||
}
|
||||
for (String instance : instances) {
|
||||
final String fqName = IFingerprint.DESCRIPTOR + "/" + instance;
|
||||
final IFingerprint fp = IFingerprint.Stub.asInterface(
|
||||
ServiceManager.waitForDeclaredService(fqName));
|
||||
if (fp == null) {
|
||||
Slog.e(TAG, "Unable to get declared service: " + fqName);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
final SensorProps[] props = fp.getSensorProps();
|
||||
final FingerprintProvider provider =
|
||||
new FingerprintProvider(getContext(), props, instance,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
mServiceProviders.add(provider);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void initializeConfiguration(int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength) {
|
||||
public void registerAuthenticators(
|
||||
@NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
final Fingerprint21 fingerprint21;
|
||||
if ((Build.IS_USERDEBUG || Build.IS_ENG)
|
||||
&& getContext().getResources().getBoolean(R.bool.allow_test_udfps)
|
||||
&& Settings.Secure.getIntForUser(getContext().getContentResolver(),
|
||||
Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
|
||||
UserHandle.USER_CURRENT) != 0) {
|
||||
fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), sensorId,
|
||||
strength, mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
} else {
|
||||
fingerprint21 = Fingerprint21.newInstance(getContext(), sensorId, strength,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
// 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<FingerprintSensorPropertiesInternal> props =
|
||||
provider.getSensorProperties();
|
||||
for (FingerprintSensorPropertiesInternal prop : props) {
|
||||
final int sensorId = prop.sensorId;
|
||||
final @BiometricManager.Authenticators.Types 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());
|
||||
}
|
||||
}
|
||||
|
||||
broadcastAllAuthenticatorsRegistered();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuthenticatorsRegisteredCallback(
|
||||
IFingerprintAuthenticatorsRegisteredCallback callback) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
if (callback == null) {
|
||||
Slog.e(TAG, "addAuthenticatorsRegisteredCallback, callback is null");
|
||||
return;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
mServiceProviders.add(fingerprint21);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -843,58 +948,40 @@ public class FingerprintService extends SystemService implements BiometricServic
|
||||
mLockPatternUtils = new LockPatternUtils(context);
|
||||
mServiceProviders = new ArrayList<>();
|
||||
mFingerprintStateCallback = new FingerprintStateCallback();
|
||||
mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>();
|
||||
mSensorProps = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBiometricServiceReady() {
|
||||
final IBiometricService biometricService = IBiometricService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.BIOMETRIC_SERVICE));
|
||||
|
||||
final String[] instances = ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR);
|
||||
if (instances == null || instances.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If for some reason the HAL is not started before the system service, do not block
|
||||
// the rest of system server. 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(() -> {
|
||||
for (String instance : instances) {
|
||||
final String fqName = IFingerprint.DESCRIPTOR + "/" + instance;
|
||||
final IFingerprint fp = IFingerprint.Stub.asInterface(
|
||||
ServiceManager.waitForDeclaredService(fqName));
|
||||
try {
|
||||
final SensorProps[] props = fp.getSensorProps();
|
||||
final FingerprintProvider provider =
|
||||
new FingerprintProvider(getContext(), props, instance,
|
||||
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
|
||||
mServiceProviders.add(provider);
|
||||
|
||||
// Register each sensor individually with BiometricService
|
||||
for (SensorProps prop : props) {
|
||||
final int sensorId = prop.commonProps.sensorId;
|
||||
@BiometricManager.Authenticators.Types int strength =
|
||||
Utils.propertyStrengthToAuthenticatorStrength(
|
||||
prop.commonProps.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);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when initializing instance: " + fqName);
|
||||
}
|
||||
// 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
|
||||
@@ -939,12 +1026,9 @@ public class FingerprintService extends SystemService implements BiometricServic
|
||||
|
||||
@NonNull
|
||||
private List<FingerprintSensorPropertiesInternal> getSensorProperties() {
|
||||
final List<FingerprintSensorPropertiesInternal> properties = new ArrayList<>();
|
||||
|
||||
for (ServiceProvider provider : mServiceProviders) {
|
||||
properties.addAll(provider.getSensorProperties());
|
||||
synchronized (mLock) {
|
||||
return mSensorProps;
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -26,9 +26,7 @@ import android.app.UserSwitchObserver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.hardware.biometrics.BiometricConstants;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.IInvalidationCallback;
|
||||
import android.hardware.biometrics.ITestSession;
|
||||
import android.hardware.biometrics.ITestSessionCallback;
|
||||
@@ -50,9 +48,7 @@ import android.os.UserManager;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.biometrics.SensorServiceStateProto;
|
||||
import com.android.server.biometrics.SensorStateProto;
|
||||
@@ -314,17 +310,22 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
}
|
||||
}
|
||||
|
||||
Fingerprint21(@NonNull Context context, @NonNull BiometricScheduler scheduler,
|
||||
@NonNull Handler handler, int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength,
|
||||
Fingerprint21(@NonNull Context context,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull BiometricScheduler scheduler, @NonNull Handler handler,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull HalResultController controller) {
|
||||
mContext = context;
|
||||
mSensorId = sensorId;
|
||||
|
||||
mSensorProperties = sensorProps;
|
||||
mSensorId = sensorProps.sensorId;
|
||||
mIsUdfps = sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
|
||||
|| sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
|
||||
mIsPowerbuttonFps = sensorProps.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON;
|
||||
|
||||
mScheduler = scheduler;
|
||||
mHandler = handler;
|
||||
mActivityTaskManager = ActivityTaskManager.getInstance();
|
||||
|
||||
mTaskStackListener = new BiometricTaskStackListener();
|
||||
mAuthenticatorIds = Collections.synchronizedMap(new HashMap<>());
|
||||
mLazyDaemon = Fingerprint21.this::getDaemon;
|
||||
@@ -341,46 +342,20 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Unable to register user switch observer");
|
||||
}
|
||||
|
||||
// TODO(b/179175438): Remove this code block after transition to AIDL.
|
||||
// The existence of config_udfps_sensor_props indicates that the sensor is UDFPS.
|
||||
mIsUdfps = !ArrayUtils.isEmpty(
|
||||
mContext.getResources().getIntArray(R.array.config_udfps_sensor_props));
|
||||
|
||||
// config_is_powerbutton_fps indicates whether device has a power button fingerprint sensor.
|
||||
mIsPowerbuttonFps = mContext.getResources().getBoolean(R.bool.config_is_powerbutton_fps);
|
||||
|
||||
final @FingerprintSensorProperties.SensorType int sensorType;
|
||||
if (mIsUdfps) {
|
||||
sensorType = FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
|
||||
} else if (mIsPowerbuttonFps) {
|
||||
sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON;
|
||||
} else {
|
||||
sensorType = FingerprintSensorProperties.TYPE_REAR;
|
||||
}
|
||||
|
||||
// IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT
|
||||
// cannot be checked
|
||||
final boolean resetLockoutRequiresHardwareAuthToken = false;
|
||||
final int maxEnrollmentsPerUser = mContext.getResources()
|
||||
.getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
|
||||
|
||||
mSensorProperties = new FingerprintSensorPropertiesInternal(context, sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser,
|
||||
new ArrayList<ComponentInfoInternal>() /* componentInfo */, sensorType,
|
||||
resetLockoutRequiresHardwareAuthToken);
|
||||
}
|
||||
|
||||
public static Fingerprint21 newInstance(@NonNull Context context, int sensorId, int strength,
|
||||
public static Fingerprint21 newInstance(@NonNull Context context,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
|
||||
final Handler handler = new Handler(Looper.getMainLooper());
|
||||
final BiometricScheduler scheduler =
|
||||
new BiometricScheduler(TAG, gestureAvailabilityDispatcher);
|
||||
final HalResultController controller = new HalResultController(sensorId, context, handler,
|
||||
final HalResultController controller = new HalResultController(sensorProps.sensorId,
|
||||
context, handler,
|
||||
scheduler);
|
||||
return new Fingerprint21(context, scheduler, handler, sensorId, strength,
|
||||
lockoutResetDispatcher, controller);
|
||||
return new Fingerprint21(context, sensorProps, scheduler, handler, lockoutResetDispatcher,
|
||||
controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,8 +21,6 @@ import android.annotation.Nullable;
|
||||
import android.app.trust.TrustManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
|
||||
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
|
||||
@@ -39,7 +37,6 @@ import android.util.Slog;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.sensors.AuthenticationConsumer;
|
||||
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||
import com.android.server.biometrics.sensors.BiometricScheduler;
|
||||
@@ -271,8 +268,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
}
|
||||
}
|
||||
|
||||
public static Fingerprint21UdfpsMock newInstance(@NonNull Context context, int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength,
|
||||
public static Fingerprint21UdfpsMock newInstance(@NonNull Context context,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
|
||||
Slog.d(TAG, "Creating Fingerprint23Mock!");
|
||||
@@ -281,8 +278,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
final TestableBiometricScheduler scheduler =
|
||||
new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher);
|
||||
final MockHalResultController controller =
|
||||
new MockHalResultController(sensorId, context, handler, scheduler);
|
||||
return new Fingerprint21UdfpsMock(context, scheduler, handler, sensorId, strength,
|
||||
new MockHalResultController(sensorProps.sensorId, context, handler, scheduler);
|
||||
return new Fingerprint21UdfpsMock(context, sensorProps, scheduler, handler,
|
||||
lockoutResetDispatcher, controller);
|
||||
}
|
||||
|
||||
@@ -407,12 +404,12 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
}
|
||||
|
||||
private Fingerprint21UdfpsMock(@NonNull Context context,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull TestableBiometricScheduler scheduler,
|
||||
@NonNull Handler handler, int sensorId,
|
||||
@BiometricManager.Authenticators.Types int strength,
|
||||
@NonNull Handler handler,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull MockHalResultController controller) {
|
||||
super(context, scheduler, handler, sensorId, strength, lockoutResetDispatcher, controller);
|
||||
super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller);
|
||||
mScheduler = scheduler;
|
||||
mScheduler.init(this);
|
||||
mHandler = handler;
|
||||
@@ -420,11 +417,11 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
final boolean resetLockoutRequiresHardwareAuthToken = false;
|
||||
final int maxTemplatesAllowed = mContext.getResources()
|
||||
.getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
|
||||
mSensorProperties = new FingerprintSensorPropertiesInternal(sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength), maxTemplatesAllowed,
|
||||
new ArrayList<ComponentInfoInternal>() /* componentInfo */,
|
||||
mSensorProperties = new FingerprintSensorPropertiesInternal(sensorProps.sensorId,
|
||||
sensorProps.sensorStrength, maxTemplatesAllowed, sensorProps.componentInfo,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
resetLockoutRequiresHardwareAuthToken);
|
||||
resetLockoutRequiresHardwareAuthToken, sensorProps.sensorLocationX,
|
||||
sensorProps.sensorLocationY, sensorProps.sensorRadius);
|
||||
mMockHalResultController = controller;
|
||||
mUserHasTrust = new SparseBooleanArray();
|
||||
mTrustManager = context.getSystemService(TrustManager.class);
|
||||
|
||||
@@ -35,7 +35,7 @@ import com.android.server.biometrics.sensors.LockoutTracker;
|
||||
public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
|
||||
private final IIrisService mIrisService;
|
||||
|
||||
public IrisAuthenticator(IIrisService irisService, int sensorId) throws RemoteException {
|
||||
public IrisAuthenticator(IIrisService irisService, int sensorId) {
|
||||
mIrisService = irisService;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,26 @@
|
||||
package com.android.server.biometrics.sensors.iris;
|
||||
|
||||
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.hardware.iris.IIrisService;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.ServiceThread;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.biometrics.Utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A service to manage multiple clients that want to access the Iris HAL API.
|
||||
* The service is responsible for maintaining a list of clients and dispatching all
|
||||
@@ -37,22 +49,54 @@ public class IrisService extends SystemService {
|
||||
|
||||
private static final String TAG = "IrisService";
|
||||
|
||||
private final IrisServiceWrapper mServiceWrapper;
|
||||
|
||||
/**
|
||||
* Receives the incoming binder calls from IrisManager.
|
||||
*/
|
||||
private final class IrisServiceWrapper extends IIrisService.Stub {
|
||||
@Override // Binder call
|
||||
public void initializeConfiguration(int sensorId, int strength) {
|
||||
public void registerAuthenticators(@NonNull List<SensorPropertiesInternal> hidlSensors) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
|
||||
// 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(() -> {
|
||||
final IBiometricService biometricService = IBiometricService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.BIOMETRIC_SERVICE));
|
||||
|
||||
for (SensorPropertiesInternal hidlSensor : hidlSensors) {
|
||||
final int sensorId = hidlSensor.sensorId;
|
||||
final @BiometricManager.Authenticators.Types int strength =
|
||||
Utils.propertyStrengthToAuthenticatorStrength(
|
||||
hidlSensor.sensorStrength);
|
||||
final IrisAuthenticator authenticator = new IrisAuthenticator(mServiceWrapper,
|
||||
sensorId);
|
||||
try {
|
||||
biometricService.registerAuthenticator(sensorId, TYPE_IRIS, strength,
|
||||
authenticator);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public IrisService(@NonNull Context context) {
|
||||
super(context);
|
||||
mServiceWrapper = new IrisServiceWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
publishBinderService(Context.IRIS_SERVICE, new IrisServiceWrapper());
|
||||
publishBinderService(Context.IRIS_SERVICE, mServiceWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,6 @@ import com.android.server.attention.AttentionManagerService;
|
||||
import com.android.server.audio.AudioService;
|
||||
import com.android.server.biometrics.AuthService;
|
||||
import com.android.server.biometrics.BiometricService;
|
||||
import com.android.server.biometrics.sensors.BiometricServiceCallback;
|
||||
import com.android.server.biometrics.sensors.face.FaceService;
|
||||
import com.android.server.biometrics.sensors.fingerprint.FingerprintService;
|
||||
import com.android.server.biometrics.sensors.iris.IrisService;
|
||||
@@ -214,11 +213,9 @@ import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Timer;
|
||||
import java.util.TreeSet;
|
||||
@@ -2334,12 +2331,10 @@ public final class SystemServer implements Dumpable {
|
||||
final boolean hasFeatureFingerprint
|
||||
= mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
|
||||
|
||||
final List<BiometricServiceCallback> biometricServiceCallback = new ArrayList<>();
|
||||
if (hasFeatureFace) {
|
||||
t.traceBegin("StartFaceSensor");
|
||||
final FaceService faceService =
|
||||
mSystemServiceManager.startService(FaceService.class);
|
||||
biometricServiceCallback.add(faceService);
|
||||
t.traceEnd();
|
||||
}
|
||||
|
||||
@@ -2353,18 +2348,12 @@ public final class SystemServer implements Dumpable {
|
||||
t.traceBegin("StartFingerprintSensor");
|
||||
final FingerprintService fingerprintService =
|
||||
mSystemServiceManager.startService(FingerprintService.class);
|
||||
biometricServiceCallback.add(fingerprintService);
|
||||
t.traceEnd();
|
||||
}
|
||||
|
||||
// Start this service after all biometric sensor services are started.
|
||||
t.traceBegin("StartBiometricService");
|
||||
mSystemServiceManager.startService(BiometricService.class);
|
||||
for (BiometricServiceCallback service : biometricServiceCallback) {
|
||||
Slog.d(TAG, "Notifying onBiometricServiceReady for: "
|
||||
+ service.getClass().getSimpleName());
|
||||
service.onBiometricServiceReady();
|
||||
}
|
||||
t.traceEnd();
|
||||
|
||||
t.traceBegin("StartAuthService");
|
||||
|
||||
@@ -31,11 +31,14 @@ import static org.mockito.Mockito.when;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
|
||||
import android.hardware.biometrics.IBiometricService;
|
||||
import android.hardware.biometrics.IBiometricServiceReceiver;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.hardware.face.IFaceService;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IFingerprintService;
|
||||
import android.hardware.iris.IIrisService;
|
||||
import android.os.Binder;
|
||||
@@ -45,11 +48,17 @@ import android.platform.test.annotations.Presubmit;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class AuthServiceTest {
|
||||
@@ -62,6 +71,8 @@ public class AuthServiceTest {
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
IBiometricServiceReceiver mReceiver;
|
||||
@@ -77,6 +88,10 @@ public class AuthServiceTest {
|
||||
IFaceService mFaceService;
|
||||
@Mock
|
||||
AppOpsManager mAppOpsManager;
|
||||
@Captor
|
||||
private ArgumentCaptor<List<FingerprintSensorPropertiesInternal>> mFingerprintPropsCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<List<FaceSensorPropertiesInternal>> mFacePropsCaptor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -89,7 +104,16 @@ public class AuthServiceTest {
|
||||
"2:8:15", // ID2:Face:Strong
|
||||
};
|
||||
|
||||
when(mResources.getIntArray(eq(R.array.config_udfps_sensor_props))).thenReturn(new int[0]);
|
||||
when(mResources.getBoolean(eq(R.bool.config_is_powerbutton_fps))).thenReturn(false);
|
||||
when(mResources.getInteger(eq(R.integer.config_fingerprintMaxTemplatesPerUser))).thenReturn(
|
||||
1);
|
||||
when(mResources.getBoolean(eq(R.bool.config_faceAuthSupportsSelfIllumination))).thenReturn(
|
||||
false);
|
||||
when(mResources.getInteger(eq(R.integer.config_faceMaxTemplatesPerUser))).thenReturn(1);
|
||||
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mInjector.getBiometricService()).thenReturn(mBiometricService);
|
||||
when(mInjector.getConfiguration(any())).thenReturn(config);
|
||||
when(mInjector.getFingerprintService()).thenReturn(mFingerprintService);
|
||||
@@ -119,11 +143,18 @@ public class AuthServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterAuthenticator_initializesConfiguration() throws Exception {
|
||||
public void testRegisterAuthenticator_registerAuthenticators() throws Exception {
|
||||
final int fingerprintId = 0;
|
||||
final int fingerprintStrength = 15;
|
||||
|
||||
final int faceId = 1;
|
||||
final int faceStrength = 4095;
|
||||
|
||||
final String[] config = {
|
||||
"0:2:15", // ID0:Fingerprint:Strong
|
||||
"1:8:4095", // ID2:Face:Convenience
|
||||
// ID0:Fingerprint:Strong
|
||||
String.format("%d:2:%d", fingerprintId, fingerprintStrength),
|
||||
// ID2:Face:Convenience
|
||||
String.format("%d:8:%d", faceId, faceStrength)
|
||||
};
|
||||
|
||||
when(mInjector.getConfiguration(any())).thenReturn(config);
|
||||
@@ -131,15 +162,18 @@ public class AuthServiceTest {
|
||||
mAuthService = new AuthService(mContext, mInjector);
|
||||
mAuthService.onStart();
|
||||
|
||||
final int fingerprintId = 0;
|
||||
final int faceId = 1;
|
||||
verify(mFingerprintService).registerAuthenticators(mFingerprintPropsCaptor.capture());
|
||||
final FingerprintSensorPropertiesInternal fingerprintProp =
|
||||
mFingerprintPropsCaptor.getValue().get(0);
|
||||
assertEquals(fingerprintProp.sensorId, fingerprintId);
|
||||
assertEquals(fingerprintProp.sensorStrength,
|
||||
Utils.authenticatorStrengthToPropertyStrength(fingerprintStrength));
|
||||
|
||||
final int fingerprintStrength = 15;
|
||||
final int faceStrength = 4095;
|
||||
|
||||
verify(mFingerprintService).initializeConfiguration(eq(fingerprintId),
|
||||
eq(fingerprintStrength));
|
||||
verify(mFaceService).initializeConfiguration(eq(faceId), eq(faceStrength));
|
||||
verify(mFaceService).registerAuthenticators(mFacePropsCaptor.capture());
|
||||
final FaceSensorPropertiesInternal faceProp = mFacePropsCaptor.getValue().get(0);
|
||||
assertEquals(faceProp.sensorId, faceId);
|
||||
assertEquals(faceProp.sensorStrength,
|
||||
Utils.authenticatorStrengthToPropertyStrength(faceStrength));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,10 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.SensorProperties;
|
||||
import android.hardware.face.FaceSensorProperties;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.UserManager;
|
||||
@@ -40,6 +43,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@@ -71,9 +75,18 @@ public class Face10Test {
|
||||
when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>());
|
||||
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
|
||||
mFace10 = new Face10(mContext, SENSOR_ID, BiometricManager.Authenticators.BIOMETRIC_STRONG,
|
||||
mLockoutResetDispatcher, false /* supportsSelfIllumination */,
|
||||
1 /* maxTemplatesAllowed */, mScheduler);
|
||||
|
||||
final int maxEnrollmentsPerUser = 1;
|
||||
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
|
||||
final boolean supportsFaceDetection = false;
|
||||
final boolean supportsSelfIllumination = false;
|
||||
final boolean resetLockoutRequiresChallenge = false;
|
||||
final FaceSensorPropertiesInternal sensorProps = new FaceSensorPropertiesInternal(SENSOR_ID,
|
||||
SensorProperties.STRENGTH_STRONG, maxEnrollmentsPerUser, componentInfo,
|
||||
FaceSensorProperties.TYPE_UNKNOWN, supportsFaceDetection, supportsSelfIllumination,
|
||||
resetLockoutRequiresChallenge);
|
||||
|
||||
mFace10 = new Face10(mContext, sensorProps, mLockoutResetDispatcher, mScheduler);
|
||||
mBinder = new Binder();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,10 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.UserManager;
|
||||
@@ -46,6 +48,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@@ -83,10 +86,18 @@ public class Fingerprint21Test {
|
||||
.thenReturn(5);
|
||||
|
||||
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
|
||||
mFingerprint21 = new TestableFingerprint21(mContext, mScheduler,
|
||||
new Handler(Looper.getMainLooper()), SENSOR_ID,
|
||||
BiometricManager.Authenticators.BIOMETRIC_WEAK, mLockoutResetDispatcher,
|
||||
mHalResultController);
|
||||
|
||||
final int maxEnrollmentsPerUser = 1;
|
||||
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
|
||||
final boolean resetLockoutRequiresHardwareAuthToken = false;
|
||||
final FingerprintSensorPropertiesInternal sensorProps =
|
||||
new FingerprintSensorPropertiesInternal(SENSOR_ID,
|
||||
FingerprintSensorProperties.STRENGTH_WEAK, maxEnrollmentsPerUser,
|
||||
componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN,
|
||||
resetLockoutRequiresHardwareAuthToken);
|
||||
|
||||
mFingerprint21 = new TestableFingerprint21(mContext, sensorProps, mScheduler,
|
||||
new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, mHalResultController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -107,12 +118,11 @@ public class Fingerprint21Test {
|
||||
private static class TestableFingerprint21 extends Fingerprint21 {
|
||||
|
||||
TestableFingerprint21(@NonNull Context context,
|
||||
@NonNull BiometricScheduler scheduler,
|
||||
@NonNull Handler handler, int sensorId, int strength,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps,
|
||||
@NonNull BiometricScheduler scheduler, @NonNull Handler handler,
|
||||
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
|
||||
@NonNull HalResultController controller) {
|
||||
super(context, scheduler, handler, sensorId, strength, lockoutResetDispatcher,
|
||||
controller);
|
||||
super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user