Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 06f04c04 authored by Ilya Matyukhin's avatar Ilya Matyukhin
Browse files

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
parent e1b53af4
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -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
     */
+35 −0
Original line number Diff line number Diff line
/*
 * 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);
}
+5 −0
Original line number Diff line number Diff line
@@ -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);

+36 −22
Original line number Diff line number Diff line
@@ -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();
+9 −2
Original line number Diff line number Diff line
@@ -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
Loading