Notify AuthController when fingerprint providers are ready
This change introduces a callback that AuthController can provide to FingerprintService to get notified when all of the fingerprint providers are available. This fixes the bug where UDFPS overlay is not available if SystemUI starts before the fingerprint HAL, because SystemUI would query the fingerprint providers on startup. Bug: 184677066 Test: atest AuthControllerTest Test: on device Change-Id: I165d67bdda09ea10dd5aac539c4155e6b158227d
This commit is contained in:
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
@@ -149,6 +150,10 @@ interface IFingerprintService {
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,6 +73,7 @@ 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;
|
||||
@@ -99,14 +102,22 @@ 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
|
||||
@@ -744,7 +755,7 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
@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);
|
||||
@@ -856,9 +867,39 @@ public class FingerprintService extends SystemService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
@@ -870,6 +911,7 @@ public class FingerprintService extends SystemService {
|
||||
}
|
||||
provider.onPointerDown(sensorId, x, y, minor, major);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerUp(int sensorId) {
|
||||
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
|
||||
@@ -906,6 +948,40 @@ public class FingerprintService extends SystemService {
|
||||
mLockPatternUtils = new LockPatternUtils(context);
|
||||
mServiceProviders = new ArrayList<>();
|
||||
mFingerprintStateCallback = new FingerprintStateCallback();
|
||||
mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>();
|
||||
mSensorProps = new ArrayList<>();
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -950,12 +1026,9 @@ public class FingerprintService extends SystemService {
|
||||
|
||||
@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
|
||||
|
||||
Reference in New Issue
Block a user