Merge "Initialize AIDL biometric HALs after BiometricService is started"

This commit is contained in:
TreeHugger Robot
2020-11-12 02:41:49 +00:00
committed by Android (Google) Code Review
14 changed files with 147 additions and 56 deletions

View File

@@ -22,5 +22,5 @@ package android.hardware.iris;
*/
interface IIrisService {
// Give IrisService its ID. See AuthService.java
void initializeConfiguration(int sensorId);
void initializeConfiguration(int sensorId, int strength);
}

View File

@@ -333,7 +333,7 @@ public class AuthService extends SystemService {
// 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);
authenticator = new FingerprintAuthenticator(fingerprintService, config.id);
break;
case TYPE_FACE:
@@ -348,7 +348,7 @@ public class AuthService extends SystemService {
// 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);
authenticator = new FaceAuthenticator(faceService, config.id);
break;
case TYPE_IRIS:
@@ -359,7 +359,8 @@ public class AuthService extends SystemService {
return;
}
authenticator = new IrisAuthenticator(irisService, config);
irisService.initializeConfiguration(config.id, config.strength);
authenticator = new IrisAuthenticator(irisService, config.id);
break;
default:

View File

@@ -594,20 +594,6 @@ public class BiometricService extends SystemService {
}
}
// This happens infrequently enough, not worth caching.
final String[] configs = mInjector.getConfiguration(getContext());
boolean idFound = false;
for (int i = 0; i < configs.length; i++) {
SensorConfig config = new SensorConfig(configs[i]);
if (config.id == id) {
idFound = true;
break;
}
}
if (!idFound) {
throw new IllegalStateException("Cannot register unknown id");
}
mSensors.add(new BiometricSensor(id, modality, strength, authenticator) {
@Override
boolean confirmationAlwaysRequired(int userId) {

View File

@@ -453,7 +453,7 @@ public class Utils {
* {@link SensorPropertiesInternal} strength.
*/
public static @SensorProperties.Strength int authenticatorStrengthToPropertyStrength(
@BiometricManager.Authenticators.Types int strength) {
@Authenticators.Types int strength) {
switch (strength) {
case BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE:
return SensorProperties.STRENGTH_CONVENIENCE;
@@ -465,4 +465,18 @@ public class Utils {
throw new IllegalArgumentException("Unknown strength: " + strength);
}
}
public static @Authenticators.Types int propertyStrengthToAuthenticatorStrength(
@SensorProperties.Strength int strength) {
switch (strength) {
case SensorProperties.STRENGTH_CONVENIENCE:
return Authenticators.BIOMETRIC_CONVENIENCE;
case SensorProperties.STRENGTH_WEAK:
return Authenticators.BIOMETRIC_WEAK;
case SensorProperties.STRENGTH_STRONG:
return Authenticators.BIOMETRIC_STRONG;
default:
throw new IllegalArgumentException("Unknown strength: " + strength);
}
}
}

View File

@@ -0,0 +1,28 @@
/*
* 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();
}

View File

@@ -32,10 +32,10 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
private final IFaceService mFaceService;
private final int mSensorId;
public FaceAuthenticator(IFaceService faceService, SensorConfig config)
public FaceAuthenticator(IFaceService faceService, int sensorId)
throws RemoteException {
mFaceService = faceService;
mSensorId = config.id;
mSensorId = sensorId;
}
@Override

View File

@@ -19,6 +19,7 @@ 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.USE_BIOMETRIC_INTERNAL;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,6 +27,7 @@ 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.face.IFace;
import android.hardware.biometrics.face.SensorProps;
@@ -54,7 +56,9 @@ import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.BiometricServiceCallback;
import com.android.server.biometrics.sensors.face.aidl.FaceProvider;
import com.android.server.biometrics.sensors.face.hidl.Face10;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -67,10 +71,11 @@ 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 {
public class FaceService extends SystemService implements BiometricServiceCallback {
protected static final String TAG = "FaceService";
private final FaceServiceWrapper mServiceWrapper;
private final LockoutResetDispatcher mLockoutResetDispatcher;
private final LockPatternUtils mLockPatternUtils;
@NonNull
@@ -506,21 +511,23 @@ public class FaceService extends SystemService {
@BiometricManager.Authenticators.Types int strength) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
mServiceProviders.add(
new com.android.server.biometrics.sensors.face.hidl.Face10(getContext(),
sensorId, strength, mLockoutResetDispatcher));
new Face10(getContext(), sensorId, strength, mLockoutResetDispatcher));
}
}
public FaceService(Context context) {
super(context);
mServiceWrapper = new FaceServiceWrapper();
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
mLockPatternUtils = new LockPatternUtils(context);
mServiceProviders = new ArrayList<>();
initializeAidlHals();
}
private void initializeAidlHals() {
@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;
@@ -543,6 +550,23 @@ public class FaceService extends SystemService {
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);
}
@@ -552,7 +576,7 @@ public class FaceService extends SystemService {
@Override
public void onStart() {
publishBinderService(Context.FACE_SERVICE, new FaceServiceWrapper());
publishBinderService(Context.FACE_SERVICE, mServiceWrapper);
}
private native NativeHandle convertSurfaceToNativeHandle(Surface surface);

View File

@@ -32,10 +32,10 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
private final IFingerprintService mFingerprintService;
private final int mSensorId;
public FingerprintAuthenticator(IFingerprintService fingerprintService, SensorConfig config)
public FingerprintAuthenticator(IFingerprintService fingerprintService, int sensorId)
throws RemoteException {
mFingerprintService = fingerprintService;
mSensorId = config.id;
mSensorId = sensorId;
}
@Override

View File

@@ -24,14 +24,17 @@ 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 android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
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.ITestSession;
import android.hardware.biometrics.fingerprint.IFingerprint;
@@ -65,6 +68,7 @@ import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.BiometricServiceCallback;
import com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintProvider;
import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21;
import com.android.server.biometrics.sensors.fingerprint.hidl.Fingerprint21UdfpsMock;
@@ -80,7 +84,7 @@ import java.util.List;
* The service is responsible for maintaining a list of clients and dispatching all
* fingerprint-related events.
*/
public class FingerprintService extends SystemService {
public class FingerprintService extends SystemService implements BiometricServiceCallback {
protected static final String TAG = "FingerprintService";
@@ -88,6 +92,7 @@ public class FingerprintService extends SystemService {
private final LockoutResetDispatcher mLockoutResetDispatcher;
private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
private final LockPatternUtils mLockPatternUtils;
private final FingerprintServiceWrapper mServiceWrapper;
@NonNull private List<ServiceProvider> mServiceProviders;
/**
@@ -572,7 +577,8 @@ public class FingerprintService extends SystemService {
}
@Override // Binder call
public void initializeConfiguration(int sensorId, int strength) {
public void initializeConfiguration(int sensorId,
@BiometricManager.Authenticators.Types int strength) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final Fingerprint21 fingerprint21;
@@ -626,16 +632,19 @@ public class FingerprintService extends SystemService {
public FingerprintService(Context context) {
super(context);
mServiceWrapper = new FingerprintServiceWrapper();
mAppOps = context.getSystemService(AppOpsManager.class);
mGestureAvailabilityDispatcher = new GestureAvailabilityDispatcher();
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
mLockPatternUtils = new LockPatternUtils(context);
mServiceProviders = new ArrayList<>();
initializeAidlHals();
}
private void initializeAidlHals() {
@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;
@@ -659,6 +668,23 @@ public class FingerprintService extends SystemService {
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);
}
@@ -668,7 +694,7 @@ public class FingerprintService extends SystemService {
@Override
public void onStart() {
publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper);
}
@Nullable

View File

@@ -31,10 +31,8 @@ import com.android.server.biometrics.sensors.LockoutTracker;
public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
private final IIrisService mIrisService;
public IrisAuthenticator(IIrisService irisService, SensorConfig config) throws
RemoteException {
public IrisAuthenticator(IIrisService irisService, int sensorId) throws RemoteException {
mIrisService = irisService;
mIrisService.initializeConfiguration(config.id);
}
@Override

View File

@@ -42,7 +42,7 @@ public class IrisService extends SystemService {
*/
private final class IrisServiceWrapper extends IIrisService.Stub {
@Override // Binder call
public void initializeConfiguration(int sensorId) {
public void initializeConfiguration(int sensorId, int strength) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
}
}

View File

@@ -102,6 +102,7 @@ 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;
@@ -196,8 +197,10 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.concurrent.CountDownLatch;
@@ -2093,9 +2096,12 @@ 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");
mSystemServiceManager.startService(FaceService.class);
final FaceService faceService =
mSystemServiceManager.startService(FaceService.class);
biometricServiceCallback.add(faceService);
t.traceEnd();
}
@@ -2107,13 +2113,20 @@ public final class SystemServer implements Dumpable {
if (hasFeatureFingerprint) {
t.traceBegin("StartFingerprintSensor");
mSystemServiceManager.startService(FingerprintService.class);
final FingerprintService fingerprintService =
mSystemServiceManager.startService(FingerprintService.class);
biometricServiceCallback.add(fingerprintService);
t.traceEnd();
}
// Start this service after all biometric services.
// 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");

View File

@@ -1456,16 +1456,6 @@ public class BiometricServiceTest {
mFingerprintAuthenticator);
}
@Test(expected = IllegalStateException.class)
public void testRegistrationWithUnknownId_throwsIllegalStateException() throws Exception {
mBiometricService = new BiometricService(mContext, mInjector);
mBiometricService.onStart();
mBiometricService.mImpl.registerAuthenticator(
100 /* id */, 2 /* modality */, 15 /* strength */,
mFingerprintAuthenticator);
}
@Test(expected = IllegalArgumentException.class)
public void testRegistrationWithNullAuthenticator_throwsIllegalArgumentException()
throws Exception {

View File

@@ -16,22 +16,28 @@
package com.android.server.biometrics.sensors.face;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.biometrics.BiometricManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.face.hidl.Face10;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@Presubmit
@SmallTest
public class Face10Test {
@@ -41,6 +47,8 @@ public class Face10Test {
@Mock
private Context mContext;
@Mock
private UserManager mUserManager;
private LockoutResetDispatcher mLockoutResetDispatcher;
private com.android.server.biometrics.sensors.face.hidl.Face10 mFace10;
@@ -54,10 +62,13 @@ public class Face10Test {
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>());
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
mFace10 = new com.android.server.biometrics.sensors.face.hidl.Face10(mContext, SENSOR_ID,
BiometricManager.Authenticators.BIOMETRIC_STRONG, mLockoutResetDispatcher,
false /* supportsSelfIllumination */, 1 /* maxTemplatesAllowed */);
mFace10 = new Face10(mContext, SENSOR_ID, BiometricManager.Authenticators.BIOMETRIC_STRONG,
mLockoutResetDispatcher, false /* supportsSelfIllumination */,
1 /* maxTemplatesAllowed */);
mBinder = new Binder();
}