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

Commit c169366f authored by Brian Colonna's avatar Brian Colonna
Browse files

Moved biometric sensor selected check into LPKV

This change moves all of the mBiometricUnlock.installedAndSelected()
checks from inside the biometric sensor implementation to
LockPatternKeyguardView.  There are several reasons for this change:

1) Instead of constructing a BiometricUnlock object and asking it if
it's enabled, LPKV can check this for itself and not even bother
constructing it if it's not enabled.

2) Since mBiometricUnlock will not be constructed if biometric unlock
isn't enabled, LPKV can simply do null checks to see if it should call
biometric unlock functions.  So it serves the dual-purpose of ensuring
there will be no null-pointer exceptions with regards to using the
biometric unlock.

3) This greatly reduces the chance of bugs being introduced into
non-biometric unlock methods because no biometric unlock calls will be
attempted if biometric unlock is not enabled.  Previously, the calls
would be made and then the biometric unlock would check if it was
enabled and return, which was not only bug-prone, but also
inefficient.

4) This simplifies the biometric unlock interface by removing an
unnecessary function call.

5) The biometric unlock implementations do not have to check if they
are installed every time they do something, which greatly cleans up
biometric unlock implementations.  It makes much more sense for the
biometric unlock functions to be able to assume that they aren't
being called unless they should be.

6) Eventually when there is more than one possible biometric unlock
method, it will make much more sense for LPKV to be in charge of
what is constructed and what isn't.

Change-Id: I5437ac05d8ceb2b182fe372cd6c75ad944ade28f
parent 8c44c181
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -19,9 +19,6 @@ package com.android.internal.policy.impl;
import android.view.View;

interface BiometricSensorUnlock {
    // Returns 'true' if the biometric sensor is available and is selected by user.
    public boolean installedAndSelected();

    // Returns 'true' if the biometric sensor has started its unlock procedure but has not yet
    // accepted or rejected the user.
    public boolean isRunning();
+55 −74
Original line number Diff line number Diff line
@@ -77,12 +77,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
        mHandler = new Handler(this);
    }

    // Indicates whether FaceLock is in use
    public boolean installedAndSelected() {
        return (mLockPatternUtils.usingBiometricWeak() &&
                mLockPatternUtils.isBiometricWeakInstalled());
    }

    public boolean isRunning() {
        return mServiceRunning;
    }
@@ -106,7 +100,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
    // Tells FaceLock to stop and then unbinds from the FaceLock service
    public boolean stop() {
        boolean wasRunning = false;
        if (installedAndSelected()) {
        stopUi();

        if (mBoundToService) {
@@ -128,7 +121,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
            // onDetachedFromWindow.
            if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound");
        }
        }

        return wasRunning;
    }
@@ -145,7 +137,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
                (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
        if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries);
        if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
                && installedAndSelected()
                && !suppressBiometricUnlock
                && !tooManyFaceUnlockTries
                && !backupIsTimedOut) {
@@ -170,16 +161,12 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {

    // Takes care of FaceLock area when layout is created
    public void initializeAreaView(View topView) {
        if (installedAndSelected()) {
        mAreaView = topView.findViewById(R.id.faceLockAreaView);
        if (mAreaView == null) {
            Log.e(TAG, "Layout does not have areaView and FaceLock is enabled");
        } else {
            show(0);
        }
        } else {
            mAreaView = null; // Set to null if not using FaceLock
        }
    }

    public void cleanUp() {
@@ -236,7 +223,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
    // Binds to FaceLock service.  This call does not tell it to start, but it causes the service
    // to call the onServiceConnected callback, which then starts FaceLock.
    private void bind() {
        if (installedAndSelected()) {
        if (!mBoundToService) {
            if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
            mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
@@ -249,7 +235,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
            Log.w(TAG, "Attempt to bind to FaceLock when already bound");
        }
    }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        // Completes connection, registers callback and starts FaceLock when service is bound
@@ -289,7 +274,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {

    // Tells the FaceLock service to start displaying its UI and perform recognition
    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
        if (installedAndSelected()) {
        synchronized (mServiceRunningLock) {
            if (!mServiceRunning) {
                if (DEBUG) Log.d(TAG, "Starting FaceLock");
@@ -306,11 +290,9 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
            }
        }
    }
    }

    // Tells the FaceLock service to stop displaying its UI and stop recognition
    private void stopUi() {
        if (installedAndSelected()) {
        // Note that attempting to stop FaceLock when it's not running is not an issue.
        // FaceLock can return, which stops it and then we try to stop it when the
        // screen is turned off.  That's why we check.
@@ -326,7 +308,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
            }
        }
    }
    }

    // Implements the FaceLock service callback interface defined in AIDL
    private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() {
+72 −35
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
    private boolean mRequiresSim;
    // True if the biometric unlock should not be displayed.  For example, if there is an overlay on
    // lockscreen or the user is plugging in / unplugging the device.
    private boolean mSupressBiometricUnlock;
    private boolean mSuppressBiometricUnlock;
    //True if a dialog is currently displaying on top of this window
    //Unlike other overlays, this does not close with a power button cycle
    private boolean mHasDialog = false;
@@ -310,15 +310,17 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
        }

        public void takeEmergencyCallAction() {
            mSupressBiometricUnlock = true;
            mSuppressBiometricUnlock = true;

            if (mBiometricUnlock.installedAndSelected() && mBiometricUnlock.isRunning()) {
            if (mBiometricUnlock != null) {
                if (mBiometricUnlock.isRunning()) {
                    // Continue covering backup lock until dialer comes up or call is resumed
                    mBiometricUnlock.show(BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT);
                }

            // The biometric unlock must be stopped if it is running when emergency call is pressed
                // We must ensure the biometric unlock is stopped when emergency call is pressed
                mBiometricUnlock.stop();
            }

            pokeWakelock(EMERGENCY_CALL_TIMEOUT);
            if (TelephonyManager.getDefault().getCallState()
@@ -410,6 +412,12 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
        }
    };

    // Indicates whether a biometric unlock method is in use
    private boolean isBiometricUnlockInstalledAndSelected() {
        return (mLockPatternUtils.usingBiometricWeak() &&
                mLockPatternUtils.isBiometricWeakInstalled());
    }

    /**
     * @param context Used to inflate, and create views.
     * @param callback Keyguard callback object for pokewakelock(), etc.
@@ -423,18 +431,23 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
            LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
        super(context, callback);

        mBiometricUnlock = new FaceUnlock(context, updateMonitor, lockPatternUtils,
                mKeyguardScreenCallback);
        mConfiguration = context.getResources().getConfiguration();
        mEnableFallback = false;
        mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
        mUpdateMonitor = updateMonitor;
        mLockPatternUtils = lockPatternUtils;
        mWindowController = controller;
        mSupressBiometricUnlock = false;
        mSuppressBiometricUnlock = false;
        mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
        mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();

        // If the biometric unlock is not being used, we don't bother constructing it.  Then we can
        // simply check if it is null when deciding whether we should make calls to it.
        if (isBiometricUnlockInstalledAndSelected()) {
            mBiometricUnlock = new FaceUnlock(context, updateMonitor, lockPatternUtils,
                    mKeyguardScreenCallback);
        }

        mUpdateMonitor.registerInfoCallback(mInfoCallback);

        /**
@@ -530,8 +543,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
        if (DEBUG) Log.d(TAG, "screen off");
        mScreenOn = false;
        mForgotPattern = false;
        mSupressBiometricUnlock =
                mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE || mHasDialog;
        if (mBiometricUnlock != null) {
            mSuppressBiometricUnlock =
                    mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE
                    || mHasDialog;
        }

        // Emulate activity life-cycle for both lock and unlock screen.
        if (mLockScreen != null) {
@@ -543,9 +559,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase {

        saveWidgetState();

        if (mBiometricUnlock != null) {
            // The biometric unlock must stop when screen turns off.
            mBiometricUnlock.stop();
        }
    }

    @Override
    public void onScreenTurnedOn() {
@@ -561,7 +579,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase {

        restoreWidgetState();

        if (startBiometricUnlock) mBiometricUnlock.start(mSupressBiometricUnlock);
        if (mBiometricUnlock != null && startBiometricUnlock) {
            mBiometricUnlock.start(mSuppressBiometricUnlock);
        }
    }

    private void saveWidgetState() {
@@ -587,6 +607,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
    @Override
    public void onWindowFocusChanged (boolean hasWindowFocus) {
        if (DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused");

        boolean startBiometricUnlock = false;
        // Start the biometric unlock if and only if the screen is both on and focused
        synchronized(mBiometricUnlockStartupLock) {
@@ -594,12 +615,16 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
            mWindowFocused = hasWindowFocus;
        }
        if (!hasWindowFocus) {
            mSupressBiometricUnlock = true;
            if (mBiometricUnlock != null) {
                mSuppressBiometricUnlock = true;
                mBiometricUnlock.stop();
                mBiometricUnlock.hide();
            }
        } else {
            mHasDialog = false;
            if (startBiometricUnlock) mBiometricUnlock.start(mSupressBiometricUnlock);
            if (mBiometricUnlock != null && startBiometricUnlock) {
                mBiometricUnlock.start(mSuppressBiometricUnlock);
            }
        }
    }

@@ -613,7 +638,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
            ((KeyguardScreen) mUnlockScreen).onResume();
        }

        if (!mBiometricUnlock.installedAndSelected() || mSupressBiometricUnlock) {
        if (mBiometricUnlock != null && mSuppressBiometricUnlock) {
            mBiometricUnlock.hide();
        }
    }
@@ -648,9 +673,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase {

        removeCallbacks(mRecreateRunnable);

        if (mBiometricUnlock != null) {
            // When view is hidden, we need to stop the biometric unlock
            // e.g., when device becomes unlocked
            mBiometricUnlock.stop();
        }

        super.onDetachedFromWindow();
    }
@@ -676,10 +703,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
            // suppressed.
            //
            // However, if the biometric unlock is already running, we do not want to interrupt it.
            if (mPluggedIn != pluggedIn && !mBiometricUnlock.isRunning()) {
            if (mBiometricUnlock != null && mPluggedIn != pluggedIn
                    && !mBiometricUnlock.isRunning()) {
                mBiometricUnlock.stop();
                mBiometricUnlock.hide();
                mSupressBiometricUnlock = true;
                mSuppressBiometricUnlock = true;
            }
            mPluggedIn = pluggedIn;
        }
@@ -695,8 +723,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
        @Override
        public void onPhoneStateChanged(int phoneState) {
            if (DEBUG) Log.d(TAG, "phone state: " + phoneState);
            if(phoneState == TelephonyManager.CALL_STATE_RINGING) {
                mSupressBiometricUnlock = true;
            if (mBiometricUnlock != null && phoneState == TelephonyManager.CALL_STATE_RINGING) {
                mSuppressBiometricUnlock = true;
                mBiometricUnlock.stop();
                mBiometricUnlock.hide();
            }
@@ -704,7 +732,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase {

        @Override
        public void onUserChanged(int userId) {
            if (mBiometricUnlock != null) {
                mBiometricUnlock.stop();
            }
            mLockPatternUtils.setCurrentUser(userId);
            updateScreen(getInitialMode(), true);
        }
@@ -767,8 +797,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
            mUnlockScreen = null;
        }
        mUpdateMonitor.removeCallback(this);
        if (mBiometricUnlock != null) {
            mBiometricUnlock.cleanUp();
        }
    }

    private boolean isSecure() {
        UnlockMode unlockMode = getUnlockMode();
@@ -817,10 +849,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
        final UnlockMode unlockMode = getUnlockMode();
        if (mode == Mode.UnlockScreen && unlockMode != UnlockMode.Unknown) {
            if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
                boolean restartBiometricUnlock = mBiometricUnlock.stop();
                boolean restartBiometricUnlock = false;
                if (mBiometricUnlock != null) {
                    restartBiometricUnlock = mBiometricUnlock.stop();
                }
                recreateUnlockScreen(unlockMode);
                if (restartBiometricUnlock) {
                    mBiometricUnlock.start(mSupressBiometricUnlock);
                if (mBiometricUnlock != null && restartBiometricUnlock) {
                    mBiometricUnlock.start(mSuppressBiometricUnlock);
                }
            }
        }
@@ -934,8 +969,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
            throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
        }
        initializeTransportControlView(unlockView);
        // Only shows view if the biometric unlock is enabled

        if (mBiometricUnlock != null) {
            mBiometricUnlock.initializeAreaView(unlockView);
        }

        mUnlockScreenMode = unlockMode;
        return unlockView;