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

Commit 09ae6273 authored by Kevin Chyn's avatar Kevin Chyn Committed by Android (Google) Code Review
Browse files

Merge changes from topic "udfps-transition" into sc-dev

* changes:
  Hide Udfps Overlay together with system transitions
  Slight cleanup for UdfpsController
parents a68ff5dc 4c4961ab
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package android.hardware.fingerprint;

import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;

/**
 * Interface for interacting with the under-display fingerprint sensor (UDFPS) overlay.
 * @hide
@@ -28,7 +30,7 @@ oneway interface IUdfpsOverlayController {
    const int REASON_AUTH_FPM_OTHER = 5; // Other FingerprintManager usage

    // Shows the overlay.
    void showUdfpsOverlay(int sensorId, int reason);
    void showUdfpsOverlay(int sensorId, int reason, IUdfpsOverlayControllerCallback callback);

    // Hides the overlay.
    void hideUdfpsOverlay(int sensorId);
+24 −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;

/**
 * @hide
 */
oneway interface IUdfpsOverlayControllerCallback {
    // Notify system_server if the user cancels a UDFPS-related operation (enroll, auth)
    void onUserCanceled();
}
+83 −37
Original line number Diff line number Diff line
@@ -20,7 +20,10 @@ import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -29,6 +32,8 @@ import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.SystemClock;
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
import android.os.RemoteException;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -91,11 +96,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
    private long mTouchLogTime;

    @Nullable private UdfpsView mView;
    // Indicates whether the overlay has been requested.
    private boolean mIsOverlayRequested;
    // Reason the overlay has been requested. See IUdfpsOverlayController for definitions.
    private int mRequestReason;
    @Nullable UdfpsEnrollHelper mEnrollHelper;
    // The current request from FingerprintService. Null if no current request.
    @Nullable ServerRequest mServerRequest;

    // The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
    // to turn off high brightness mode. To get around this limitation, the state of the AOD
@@ -104,39 +106,84 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
    private boolean mIsAodInterruptActive;
    @Nullable private Runnable mCancelAodTimeoutAction;

    /**
     * Keeps track of state within a single FingerprintService request. Note that this state
     * persists across configuration changes, etc, since it is considered a single request.
     *
     * TODO: Perhaps we can move more global variables into here
     */
    private static class ServerRequest {
        // Reason the overlay has been requested. See IUdfpsOverlayController for definitions.
        final int mRequestReason;
        @NonNull final IUdfpsOverlayControllerCallback mCallback;
        @Nullable final UdfpsEnrollHelper mEnrollHelper;

        ServerRequest(int requestReason, @NonNull IUdfpsOverlayControllerCallback callback,
                @Nullable UdfpsEnrollHelper enrollHelper) {
            mRequestReason = requestReason;
            mCallback = callback;
            mEnrollHelper = enrollHelper;
        }

        void onEnrollmentProgress(int remaining) {
            if (mEnrollHelper != null) {
                mEnrollHelper.onEnrollmentProgress(remaining);
            }
        }

        void onEnrollmentHelp() {
            if (mEnrollHelper != null) {
                mEnrollHelper.onEnrollmentHelp();
            }
        }

        void onUserCanceled() {
            try {
                mCallback.onUserCanceled();
            } catch (RemoteException e) {
                Log.e(TAG, "Remote exception", e);
            }
        }
    }

    public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
        @Override
        public void showUdfpsOverlay(int sensorId, int reason) {
        public void showUdfpsOverlay(int sensorId, int reason,
                @NonNull IUdfpsOverlayControllerCallback callback) {
            final UdfpsEnrollHelper enrollHelper;
            if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR
                    || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) {
                mEnrollHelper = new UdfpsEnrollHelper(mContext, reason);
                enrollHelper = new UdfpsEnrollHelper(mContext, reason);
            } else {
                mEnrollHelper = null;
                enrollHelper = null;
            }
            UdfpsController.this.showOverlay(reason);

            mServerRequest = new ServerRequest(reason, callback, enrollHelper);
            updateOverlay();
        }

        @Override
        public void hideUdfpsOverlay(int sensorId) {
            UdfpsController.this.hideOverlay();
            mServerRequest = null;
            updateOverlay();
        }

        @Override
        public void onEnrollmentProgress(int sensorId, int remaining) {
            if (mEnrollHelper == null) {
                Log.e(TAG, "onEnrollProgress received but helper is null");
            if (mServerRequest == null) {
                Log.e(TAG, "onEnrollProgress received but serverRequest is null");
                return;
            }
            mEnrollHelper.onEnrollmentProgress(remaining);
            mServerRequest.onEnrollmentProgress(remaining);
        }

        @Override
        public void onEnrollmentHelp(int sensorId) {
            if (mEnrollHelper == null) {
                Log.e(TAG, "onEnrollmentHelp received but helper is null");
            if (mServerRequest == null) {
                Log.e(TAG, "onEnrollmentHelp received but serverRequest is null");
                return;
            }
            mEnrollHelper.onEnrollmentHelp();
            mServerRequest.onEnrollmentHelp();
        }

        @Override
@@ -165,6 +212,19 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
        return (float) Math.sqrt(Math.pow(vx, 2.0) + Math.pow(vy, 2.0));
    }

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (mServerRequest != null
                    && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
                Log.d(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
                mServerRequest.onUserCanceled();
                mServerRequest = null;
                updateOverlay();
            }
        }
    };

    @SuppressLint("ClickableViewAccessibility")
    private final UdfpsView.OnTouchListener mOnTouchListener = (view, event) -> {
        UdfpsView udfpsView = (UdfpsView) view;
@@ -280,6 +340,10 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
        mCoreLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;

        mFingerprintManager.setUdfpsOverlayController(new UdfpsOverlayController());

        final IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        context.registerReceiver(mBroadcastReceiver, filter);
    }

    @Nullable
@@ -314,27 +378,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
                mSensorProps.sensorLocationY + mSensorProps.sensorRadius);
    }

    private void showOverlay(int reason) {
        if (mIsOverlayRequested) {
            return;
        }
        mIsOverlayRequested = true;
        mRequestReason = reason;
        updateOverlay();
    }

    private void hideOverlay() {
        if (!mIsOverlayRequested) {
            return;
        }
        mIsOverlayRequested = false;
        mRequestReason = IUdfpsOverlayController.REASON_UNKNOWN;
        updateOverlay();
    }

    private void updateOverlay() {
        if (mIsOverlayRequested) {
            showUdfpsOverlay(mRequestReason);
        if (mServerRequest != null) {
            showUdfpsOverlay(mServerRequest.mRequestReason);
        } else {
            hideUdfpsOverlay();
        }
@@ -427,7 +473,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
            case IUdfpsOverlayController.REASON_ENROLL_ENROLLING: {
                final UdfpsAnimationViewEnroll view = (UdfpsAnimationViewEnroll)
                        inflater.inflate(R.layout.udfps_animation_view_enroll, null, false);
                view.setEnrollHelper(mEnrollHelper);
                view.setEnrollHelper(mServerRequest.mEnrollHelper);
                return view;
            }

+11 −8
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
import android.os.PowerManager;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
@@ -89,6 +90,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
    private StatusBarStateController mStatusBarStateController;
    @Mock
    private StatusBar mStatusBar;
    @Mock
    private IUdfpsOverlayControllerCallback mUdfpsOverlayControllerCallback;

    private FakeExecutor mFgExecutor;

@@ -152,7 +155,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
    @Test
    public void dozeTimeTick() throws RemoteException {
        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
        mFgExecutor.runAllReady();
        mUdfpsController.dozeTimeTick();
        verify(mUdfpsView).dozeTimeTick();
@@ -161,7 +164,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
    @Test
    public void showUdfpsOverlay_addsViewToWindow() throws RemoteException {
        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
        mFgExecutor.runAllReady();
        verify(mWindowManager).addView(eq(mUdfpsView), any());
    }
@@ -169,7 +172,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
    @Test
    public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException {
        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
        mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
        mFgExecutor.runAllReady();
        verify(mWindowManager).removeView(eq(mUdfpsView));
@@ -183,7 +186,7 @@ public class UdfpsControllerTest extends SysuiTestCase {

        // GIVEN that the overlay is showing
        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
        mFgExecutor.runAllReady();
        // WHEN ACTION_DOWN is received
        verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
@@ -205,7 +208,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
    public void aodInterrupt() throws RemoteException {
        // GIVEN that the overlay is showing
        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
        mFgExecutor.runAllReady();
        // WHEN fingerprint is requested because of AOD interrupt
        mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
@@ -221,7 +224,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
    public void cancelAodInterrupt() throws RemoteException {
        // GIVEN AOD interrupt
        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
        mFgExecutor.runAllReady();
        mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
        // WHEN it is cancelled
@@ -234,7 +237,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
    public void aodInterruptTimeout() throws RemoteException {
        // GIVEN AOD interrupt
        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
        mFgExecutor.runAllReady();
        mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
        // WHEN it times out
@@ -247,7 +250,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
    @Test
    public void registersAndUnregistersViewForCallbacks() throws RemoteException {
        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
                IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
        mFgExecutor.runAllReady();
        verify(mStatusBarStateController).addCallback(mUdfpsController.mStatusBarStateListener);
        verify(mStatusBar).addExpansionChangedListener(
+12 −0
Original line number Diff line number Diff line
@@ -80,6 +80,18 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
        onErrorInternal(errorCode, vendorCode, true /* finish */);
    }

    /**
     * Notifies the caller that the operation was canceled by the user. Note that the actual
     * operation still needs to wait for the HAL to send ERROR_CANCELED.
     */
    public void onUserCanceled() {
        // Send USER_CANCELED, but do not finish. Wait for the HAL to respond with ERROR_CANCELED,
        // which then finishes the AcquisitionClient's lifecycle.
        onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED, 0 /* vendorCode */,
                false /* finish */);
        stopHalOperation();
    }

    protected void onErrorInternal(int errorCode, int vendorCode, boolean finish) {
        // In some cases, the framework will send an error to the caller before a true terminal
        // case (success, failure, or error) is received from the HAL (e.g. versions of fingerprint
Loading