diff options
3 files changed, 124 insertions, 27 deletions
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index 6af223b3660a..0f964bb75944 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -78,6 +78,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.function.Function; import java.util.function.Supplier; /** @@ -99,6 +100,9 @@ public class FaceService extends SystemService { mBiometricStateCallback; @NonNull private final FaceProviderFunction mFaceProviderFunction; + @NonNull private final Function<String, FaceProvider> mFaceProvider; + @NonNull + private final Supplier<String[]> mAidlInstanceNameSupplier; interface FaceProviderFunction { FaceProvider getFaceProvider(Pair<String, SensorProps[]> filteredSensorProps, @@ -671,23 +675,9 @@ public class FaceService extends SystemService { final List<ServiceProvider> providers = new ArrayList<>(); for (String instance : instances) { - final String fqName = IFace.DESCRIPTOR + "/" + instance; - final IFace face = IFace.Stub.asInterface( - Binder.allowBlocking(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(), - mBiometricStateCallback, props, instance, mLockoutResetDispatcher, - BiometricContext.getInstance(getContext()), - false /* resetLockoutRequiresChallenge */); - providers.add(provider); - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); - } + final FaceProvider provider = mFaceProvider.apply(instance); + Slog.i(TAG, "Adding AIDL provider: " + instance); + providers.add(provider); } return providers; @@ -700,7 +690,7 @@ public class FaceService extends SystemService { mRegistry.registerAll(() -> { List<String> aidlSensors = new ArrayList<>(); - final String[] instances = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR); + final String[] instances = mAidlInstanceNameSupplier.get(); if (instances != null) { aidlSensors.addAll(Lists.newArrayList(instances)); } @@ -813,11 +803,15 @@ public class FaceService extends SystemService { public FaceService(Context context) { this(context, null /* faceProviderFunction */, () -> IBiometricService.Stub.asInterface( - ServiceManager.getService(Context.BIOMETRIC_SERVICE))); + ServiceManager.getService(Context.BIOMETRIC_SERVICE)), null /* faceProvider */, + () -> ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR)); } - @VisibleForTesting FaceService(Context context, FaceProviderFunction faceProviderFunction, - Supplier<IBiometricService> biometricServiceSupplier) { + @VisibleForTesting FaceService(Context context, + FaceProviderFunction faceProviderFunction, + Supplier<IBiometricService> biometricServiceSupplier, + Function<String, FaceProvider> faceProvider, + Supplier<String[]> aidlInstanceNameSupplier) { super(context); mServiceWrapper = new FaceServiceWrapper(); mLockoutResetDispatcher = new LockoutResetDispatcher(context); @@ -830,6 +824,28 @@ public class FaceService extends SystemService { mBiometricStateCallback.start(mRegistry.getProviders()); } }); + mAidlInstanceNameSupplier = aidlInstanceNameSupplier; + + mFaceProvider = faceProvider != null ? faceProvider : (name) -> { + final String fqName = IFace.DESCRIPTOR + "/" + name; + final IFace face = IFace.Stub.asInterface( + Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName))); + if (face == null) { + Slog.e(TAG, "Unable to get declared service: " + fqName); + return null; + } + try { + final SensorProps[] props = face.getSensorProps(); + return new FaceProvider(getContext(), + mBiometricStateCallback, props, name, mLockoutResetDispatcher, + BiometricContext.getInstance(getContext()), + false /* resetLockoutRequiresChallenge */); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); + } + + return null; + }; if (Flags.deHidl()) { mFaceProviderFunction = faceProviderFunction != null ? faceProviderFunction : diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceTest.java index c9e1c4a8bfc5..3aaac2e9cf1b 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceTest.java @@ -16,21 +16,30 @@ package com.android.server.biometrics.sensors.face; +import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; import static android.hardware.face.FaceSensorProperties.TYPE_UNKNOWN; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.ComponentName; +import android.content.pm.PackageManager; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.face.IFace; import android.hardware.biometrics.face.SensorProps; +import android.hardware.face.FaceAuthenticateOptions; import android.hardware.face.FaceSensorConfigurations; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.face.IFaceAuthenticatorsRegisteredCallback; +import android.hardware.face.IFaceServiceReceiver; +import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsEnabled; @@ -42,6 +51,7 @@ import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.internal.R; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; import com.android.server.biometrics.Flags; @@ -66,6 +76,7 @@ public class FaceServiceTest { private static final int ID_VIRTUAL = 6; private static final String NAME_DEFAULT = "default"; private static final String NAME_VIRTUAL = "virtual"; + private static final String OP_PACKAGE_NAME = "FaceServiceTest/SystemUi"; @Rule public final MockitoRule mMockito = MockitoJUnit.rule(); @@ -78,15 +89,19 @@ public class FaceServiceTest { @Rule public final FakeSettingsProviderRule mSettingsRule = FakeSettingsProvider.rule(); @Mock - FaceProvider mFaceProviderDefault; + private FaceProvider mFaceProviderDefault; + @Mock + private FaceProvider mFaceProviderVirtual; + @Mock + private IFace mDefaultFaceDaemon; @Mock - FaceProvider mFaceProviderVirtual; + private IFace mVirtualFaceDaemon; @Mock - IFace mDefaultFaceDaemon; + private IBiometricService mIBiometricService; @Mock - IFace mVirtualFaceDaemon; + private IBinder mToken; @Mock - IBiometricService mIBiometricService; + private IFaceServiceReceiver mFaceServiceReceiver; private final SensorProps mDefaultSensorProps = new SensorProps(); private final SensorProps mVirtualSensorProps = new SensorProps(); @@ -117,7 +132,13 @@ public class FaceServiceTest { new SensorProps[]{mVirtualSensorProps}); when(mFaceProviderDefault.getSensorProperties()).thenReturn(List.of(mSensorPropsDefault)); when(mFaceProviderVirtual.getSensorProperties()).thenReturn(List.of(mSensorPropsVirtual)); + when(mFaceProviderDefault.containsSensor(anyInt())) + .thenAnswer(i -> i.getArguments()[0].equals(ID_DEFAULT)); + when(mFaceProviderVirtual.containsSensor(anyInt())) + .thenAnswer(i -> i.getArguments()[0].equals(ID_VIRTUAL)); + mContext.getTestablePermissions().setPermission( + USE_BIOMETRIC_INTERNAL, PackageManager.PERMISSION_GRANTED); mFaceSensorConfigurations = new FaceSensorConfigurations(false); mFaceSensorConfigurations.addAidlConfigs(new String[]{NAME_DEFAULT, NAME_VIRTUAL}, (name) -> { @@ -136,7 +157,13 @@ public class FaceServiceTest { if (NAME_DEFAULT.equals(filteredSensorProps.first)) return mFaceProviderDefault; if (NAME_VIRTUAL.equals(filteredSensorProps.first)) return mFaceProviderVirtual; return null; - }, () -> mIBiometricService); + }, () -> mIBiometricService, + (name) -> { + if (NAME_DEFAULT.equals(name)) return mFaceProviderDefault; + if (NAME_VIRTUAL.equals(name)) return mFaceProviderVirtual; + return null; + }, + () -> new String[]{NAME_DEFAULT, NAME_VIRTUAL}); } @Test @@ -191,6 +218,39 @@ public class FaceServiceTest { eq(Utils.propertyStrengthToAuthenticatorStrength(STRENGTH_STRONG)), any()); } + @Test + public void testOptionsForAuthentication() throws Exception { + FaceAuthenticateOptions faceAuthenticateOptions = new FaceAuthenticateOptions.Builder() + .build(); + initService(); + mFaceService.mServiceWrapper.registerAuthenticators(List.of()); + waitForRegistration(); + + final long operationId = 5; + mFaceService.mServiceWrapper.authenticate(mToken, operationId, mFaceServiceReceiver, + faceAuthenticateOptions); + + assertThat(faceAuthenticateOptions.getSensorId()).isEqualTo(ID_DEFAULT); + } + + @Test + public void testOptionsForDetect() throws Exception { + FaceAuthenticateOptions faceAuthenticateOptions = new FaceAuthenticateOptions.Builder() + .setOpPackageName(ComponentName.unflattenFromString(OP_PACKAGE_NAME) + .getPackageName()) + .build(); + mContext.getOrCreateTestableResources().addOverride( + R.string.config_keyguardComponent, + OP_PACKAGE_NAME); + initService(); + mFaceService.mServiceWrapper.registerAuthenticators(List.of()); + waitForRegistration(); + mFaceService.mServiceWrapper.detectFace(mToken, mFaceServiceReceiver, + faceAuthenticateOptions); + + assertThat(faceAuthenticateOptions.getSensorId()).isEqualTo(ID_DEFAULT); + } + private void waitForRegistration() throws Exception { final CountDownLatch latch = new CountDownLatch(1); mFaceService.mServiceWrapper.addAuthenticatorsRegisteredCallback( diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java index f570ba23441d..88956b614eae 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java @@ -40,6 +40,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.AppOpsManager; +import android.content.ComponentName; import android.content.pm.PackageManager; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.fingerprint.IFingerprint; @@ -61,6 +62,7 @@ import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.internal.R; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; import com.android.server.LocalServices; @@ -92,6 +94,7 @@ public class FingerprintServiceTest { private static final String NAME_VIRTUAL = "virtual"; private static final List<FingerprintSensorPropertiesInternal> HIDL_AUTHENTICATORS = List.of(); + private static final String OP_PACKAGE_NAME = "FingerprintServiceTest/SystemUi"; @Rule public final MockitoRule mMockito = MockitoJUnit.rule(); @@ -343,6 +346,24 @@ public class FingerprintServiceTest { assertEquals((int) (uidCaptor.getValue()), Binder.getCallingUid()); } + @Test + public void testOptionsForDetect() throws Exception { + FingerprintAuthenticateOptions fingerprintAuthenticateOptions = + new FingerprintAuthenticateOptions.Builder() + .setOpPackageName(ComponentName.unflattenFromString( + OP_PACKAGE_NAME).getPackageName()) + .build(); + + mContext.getOrCreateTestableResources().addOverride( + R.string.config_keyguardComponent, + OP_PACKAGE_NAME); + initServiceWithAndWait(NAME_DEFAULT); + mService.mServiceWrapper.detectFingerprint(mToken, mServiceReceiver, + fingerprintAuthenticateOptions); + + assertThat(fingerprintAuthenticateOptions.getSensorId()).isEqualTo(ID_DEFAULT); + } + private FingerprintAuthenticateOptions verifyAuthenticateWithNewRequestId( FingerprintProvider provider, long operationId) { |