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

Commit d9803be1 authored by Beverly Tai's avatar Beverly Tai Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE Update active unlock triggers take #2" into tm-dev

parents 597b031c fe7e9e9a
Loading
Loading
Loading
Loading
+147 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 com.android.keyguard

import android.content.ContentResolver
import android.database.ContentObserver
import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL
import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT
import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE
import com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.util.settings.SecureSettings
import java.io.PrintWriter
import javax.inject.Inject

/**
 * Handles active unlock settings changes.
 */
@SysUISingleton
class ActiveUnlockConfig @Inject constructor(
    @Main private val handler: Handler,
    private val secureSettings: SecureSettings,
    private val contentResolver: ContentResolver,
    dumpManager: DumpManager
) : Dumpable {

    /**
     * Indicates the origin for an active unlock request.
     */
    enum class ACTIVE_UNLOCK_REQUEST_ORIGIN {
        WAKE, UNLOCK_INTENT, BIOMETRIC_FAIL, ASSISTANT
    }

    private var requestActiveUnlockOnWakeup = false
    private var requestActiveUnlockOnUnlockIntent = false
    private var requestActiveUnlockOnBioFail = false

    private val settingsObserver = object : ContentObserver(handler) {
        private val wakeUri: Uri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_WAKE)
        private val unlockIntentUri: Uri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_UNLOCK_INTENT)
        private val bioFailUri: Uri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)

        fun register() {
            contentResolver.registerContentObserver(
                    wakeUri,
                    false,
                    this,
                    UserHandle.USER_ALL)
            contentResolver.registerContentObserver(
                    unlockIntentUri,
                    false,
                    this,
                    UserHandle.USER_ALL)
            contentResolver.registerContentObserver(
                    bioFailUri,
                    false,
                    this,
                    UserHandle.USER_ALL)

            onChange(true, ArrayList(), 0, getCurrentUser())
        }

        override fun onChange(
            selfChange: Boolean,
            uris: Collection<Uri>,
            flags: Int,
            userId: Int
        ) {
            if (getCurrentUser() != userId) {
                return
            }

            if (selfChange || uris.contains(wakeUri)) {
                requestActiveUnlockOnWakeup = secureSettings.getIntForUser(
                        ACTIVE_UNLOCK_ON_WAKE, 0, getCurrentUser()) == 1
            }

            if (selfChange || uris.contains(unlockIntentUri)) {
                requestActiveUnlockOnUnlockIntent = secureSettings.getIntForUser(
                        ACTIVE_UNLOCK_ON_UNLOCK_INTENT, 0, getCurrentUser()) == 1
            }

            if (selfChange || uris.contains(bioFailUri)) {
                requestActiveUnlockOnBioFail = secureSettings.getIntForUser(
                        ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, 0, getCurrentUser()) == 1
            }
        }
    }

    init {
        settingsObserver.register()
        dumpManager.registerDumpable(this)
    }

    /**
     * Whether to trigger active unlock based on where the request is coming from and
     * the current settings.
     */
    fun shouldAllowActiveUnlockFromOrigin(requestOrigin: ACTIVE_UNLOCK_REQUEST_ORIGIN): Boolean {
        return when (requestOrigin) {
            ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE -> requestActiveUnlockOnWakeup

            ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT ->
                requestActiveUnlockOnUnlockIntent || requestActiveUnlockOnWakeup

            ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL ->
                requestActiveUnlockOnBioFail || requestActiveUnlockOnUnlockIntent ||
                        requestActiveUnlockOnWakeup

            ACTIVE_UNLOCK_REQUEST_ORIGIN.ASSISTANT -> isActiveUnlockEnabled()
        }
    }

    /**
     * If any active unlock triggers are enabled.
     */
    fun isActiveUnlockEnabled(): Boolean {
        return requestActiveUnlockOnWakeup || requestActiveUnlockOnUnlockIntent ||
                requestActiveUnlockOnBioFail
    }

    override fun dump(pw: PrintWriter, args: Array<out String>) {
        pw.println("   requestActiveUnlockOnWakeup=$requestActiveUnlockOnWakeup")
        pw.println("   requestActiveUnlockOnUnlockIntent=$requestActiveUnlockOnUnlockIntent")
        pw.println("   requestActiveUnlockOnBioFail=$requestActiveUnlockOnBioFail")
    }
}
 No newline at end of file
+4 −4
Original line number Diff line number Diff line
@@ -221,10 +221,10 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
                mKeyguardSecurityCallback.userActivity();
                showMessage(null, null);
            }
            if (mUpdateMonitor.isFaceEnrolled()
                    && mUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) {
                mUpdateMonitor.requestActiveUnlock("unlock-intent, reason=swipeUpOnBouncer",
                        true);
            if (mUpdateMonitor.isFaceEnrolled()) {
                mUpdateMonitor.requestActiveUnlock(
                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
                        "swipeUpOnBouncer");
            }
        }
    };
+67 −74
Original line number Diff line number Diff line
@@ -248,12 +248,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }
    }

    public final boolean mRequestActiveUnlockOnAssistant;
    public final boolean mRequestActiveUnlockOnWakeup;
    public final boolean mInitiateActiveUnlockOnWakeup;
    public final boolean mRequestActiveUnlockOnUnlockIntent;
    public final boolean mRequestActiveUnlockOnBioFail;

    private final Context mContext;
    private final boolean mIsPrimaryUser;
    private final boolean mIsAutomotive;
@@ -340,6 +334,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private final Executor mBackgroundExecutor;
    private SensorPrivacyManager mSensorPrivacyManager;
    private final ActiveUnlockConfig mActiveUnlockConfig;

    /**
     * Short delay before restarting fingerprint authentication after a successful try. This should
@@ -441,12 +436,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        Assert.isMainThread();
        boolean wasTrusted = mUserHasTrust.get(userId, false);
        mUserHasTrust.put(userId, enabled);
        // If there was no change in trusted state, make sure we are not authenticating.
        // TrustManager sends an onTrustChanged whenever a user unlocks keyguard, for
        // this reason we need to make sure to not authenticate.
        if (wasTrusted == enabled) {
        // If there was no change in trusted state or trust granted, make sure we are not
        // authenticating.  TrustManager sends an onTrustChanged whenever a user unlocks keyguard,
        // for this reason we need to make sure to not authenticate.
        if (wasTrusted == enabled || enabled) {
            updateBiometricListeningState(BIOMETRIC_ACTION_STOP);
        } else if (!enabled) {
        } else {
            updateBiometricListeningState(BIOMETRIC_ACTION_START);
        }

@@ -1364,14 +1359,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                cb.onTrustAgentErrorMessage(message);
            }
        }

    }

    @VisibleForTesting
    void setAssistantVisible(boolean assistantVisible) {
        mAssistantVisible = assistantVisible;
        updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
        if (mAssistantVisible && mRequestActiveUnlockOnAssistant) {
            requestActiveUnlock("assistant", false);
        if (mAssistantVisible) {
            requestActiveUnlock(
                    ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.ASSISTANT,
                    "assistant",
                    false);
        }
    }

@@ -1518,10 +1517,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab

                @Override
                public void onAuthenticationFailed() {
                    if (mRequestActiveUnlockOnBioFail) {
                        requestActiveUnlock("biometric-failure, extra=fingerprintFailure",
                                true);
                    }
                    requestActiveUnlock(
                            ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
                            "fingerprintFailure");
                    handleFingerprintAuthFailed();
                }

@@ -1580,14 +1578,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab

                @Override
                public void onAuthenticationFailed() {
                    if (shouldRequestActiveUnlockOnFaceError()) {
                        String reason =
                                mKeyguardBypassController.canBypass() ? "bypass"
                                        : mUdfpsBouncerShowing ? "udfpsBouncer" :
                                                mBouncerFullyShown ? "bouncer" : "udfpsFpDown";
                        requestActiveUnlock("biometric-failure"
                                + ", extra=faceFailure-" + reason, true);
                    }
                        requestActiveUnlock(
                                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
                                "faceFailure-" + reason);

                    handleFaceAuthFailed();
                    if (mKeyguardBypassController != null) {
@@ -1617,10 +1614,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                    if (mKeyguardBypassController != null) {
                        mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
                    }
                    if (errMsgId == BiometricFaceConstants.FACE_ERROR_TIMEOUT
                            && shouldRequestActiveUnlockOnFaceError()) {
                        requestActiveUnlock("biometric-failure"
                                + ", extra=faceError-" + errMsgId, true);

                    if (errMsgId == BiometricFaceConstants.FACE_ERROR_TIMEOUT) {
                        requestActiveUnlock(
                                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
                                "faceError-" + errMsgId);
                    }
                }

@@ -1628,12 +1626,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                public void onAuthenticationAcquired(int acquireInfo) {
                    handleFaceAcquired(acquireInfo);
                }

                private boolean shouldRequestActiveUnlockOnFaceError() {
                    return mRequestActiveUnlockOnBioFail
                            && (mKeyguardBypassController.canBypass() || mBouncerFullyShown
                            || mUdfpsBouncerShowing || mAuthController.isUdfpsFingerDown());
                }
    };

    @VisibleForTesting
@@ -1749,11 +1741,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
        Assert.isMainThread();
        updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
        if (mRequestActiveUnlockOnWakeup) {
            requestActiveUnlock("wake-unlock");
        } else if (mInitiateActiveUnlockOnWakeup) {
            initiateActiveUnlock("wake-initiate");
        }
        requestActiveUnlock(ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE, "wakingUp");
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
@@ -1882,7 +1870,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            AuthController authController,
            TelephonyListenerManager telephonyListenerManager,
            InteractionJankMonitor interactionJankMonitor,
            LatencyTracker latencyTracker) {
            LatencyTracker latencyTracker,
            ActiveUnlockConfig activeUnlockConfiguration) {
        mContext = context;
        mSubscriptionManager = SubscriptionManager.from(context);
        mTelephonyListenerManager = telephonyListenerManager;
@@ -1899,18 +1888,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        mAuthController = authController;
        dumpManager.registerDumpable(getClass().getName(), this);
        mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);

        // TODO, b/222459888: add official configurable names to Settings.java
        mRequestActiveUnlockOnWakeup = Settings.Global.getInt(
                mContext.getContentResolver(), "wake-unlock", 0) == 1;
        mInitiateActiveUnlockOnWakeup = Settings.Global.getInt(
                mContext.getContentResolver(), "wake-initiate", 1) == 1;
        mRequestActiveUnlockOnUnlockIntent = Settings.Global.getInt(
                mContext.getContentResolver(), "unlock-intent", 0) == 1;
        mRequestActiveUnlockOnBioFail = Settings.Global.getInt(
                mContext.getContentResolver(), "bio-fail", 0) == 1;
        mRequestActiveUnlockOnAssistant = Settings.Global.getInt(
                mContext.getContentResolver(), "assistant", 0) == 1;
        mActiveUnlockConfig = activeUnlockConfiguration;

        mHandler = new Handler(mainLooper) {
            @Override
@@ -2292,11 +2270,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }
        mAuthInterruptActive = active;
        updateFaceListeningState(BIOMETRIC_ACTION_UPDATE);
        if (mRequestActiveUnlockOnWakeup) {
            requestActiveUnlock("wake-unlock, extra=onReach");
        } else if (mInitiateActiveUnlockOnWakeup) {
            initiateActiveUnlock("wake-initiate, extra=onReach");
        }
        requestActiveUnlock(ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE, "onReach");
    }

    /**
@@ -2348,7 +2322,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    /**
     * Initiates active unlock to get the unlock token ready.
     */
    public void initiateActiveUnlock(String reason) {
    private void initiateActiveUnlock(String reason) {
        // If this message exists, FP has already authenticated, so wait until that is handled
        if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
            return;
@@ -2365,15 +2339,30 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    /**
     * Attempts to trigger active unlock from trust agent.
     */
    public void requestActiveUnlock(String reason, boolean dismissKeyguard) {
    private void requestActiveUnlock(
            ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN requestOrigin,
            String reason,
            boolean dismissKeyguard
    ) {
        // If this message exists, FP has already authenticated, so wait until that is handled
        if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
            return;
        }

        if (shouldTriggerActiveUnlock()) {
        final boolean allowRequest =
                mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(requestOrigin);
        if (requestOrigin == ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE
                && !allowRequest && mActiveUnlockConfig.isActiveUnlockEnabled()) {
            // instead of requesting the active unlock, initiate the unlock
            initiateActiveUnlock(reason);
            return;
        }

        if (allowRequest && shouldTriggerActiveUnlock()) {
            if (DEBUG) {
                Log.d("ActiveUnlock", "reportUserRequestedUnlock triggerReason=" + reason
                Log.d("ActiveUnlock", "reportUserRequestedUnlock"
                        + " origin=" + requestOrigin.name()
                        + " reason=" + reason
                        + " dismissKeyguard=" + dismissKeyguard);
            }
            mTrustManager.reportUserRequestedUnlock(KeyguardUpdateMonitor.getCurrentUser(),
@@ -2383,11 +2372,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab

    /**
     * Attempts to trigger active unlock from trust agent.
     * Only dismisses the keyguard if only face is enrolled (no FP) and bypass is enabled.
     * Only dismisses the keyguard under certain conditions.
     */
    public void requestActiveUnlock(String reason) {
        requestActiveUnlock(reason, isFaceEnrolled() && !isUdfpsEnrolled()
                && mKeyguardBypassController.getBypassEnabled());
    public void requestActiveUnlock(
            ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN requestOrigin,
            String extraReason
    ) {
        final boolean canFaceBypass = isFaceEnrolled() && mKeyguardBypassController != null
                && mKeyguardBypassController.canBypass();
        requestActiveUnlock(
                requestOrigin,
                extraReason, canFaceBypass
                        || mUdfpsBouncerShowing
                        || mBouncerFullyShown
                        || mAuthController.isUdfpsFingerDown());
    }

    /**
@@ -2397,9 +2395,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        mUdfpsBouncerShowing = showing;
        if (mUdfpsBouncerShowing) {
            updateFaceListeningState(BIOMETRIC_ACTION_START);
            if (mRequestActiveUnlockOnUnlockIntent) {
                requestActiveUnlock("unlock-intent, extra=udfpsBouncer", true);
            }
            requestActiveUnlock(
                    ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
                    "udfpsBouncer");
        }
    }

@@ -3233,8 +3231,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }

        if (wasBouncerFullyShown != mBouncerFullyShown) {
            if (mBouncerFullyShown && mRequestActiveUnlockOnUnlockIntent) {
                requestActiveUnlock("unlock-intent, reason=bouncerFullyShown", true);
            if (mBouncerFullyShown) {
                requestActiveUnlock(
                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
                        "bouncerFullyShown");
            }
            for (int i = 0; i < mCallbacks.size(); i++) {
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -3771,13 +3771,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }
        mListenModels.print(pw);

        pw.println("Enabled active unlock triggers:");
        pw.println("   mRequestActiveUnlockOnWakeup=" + mRequestActiveUnlockOnWakeup);
        pw.println("   mInitiateActiveUnlockOnWakeup=" + mInitiateActiveUnlockOnWakeup);
        pw.println("   mRequestActiveUnlockOnUnlockIntent=" + mRequestActiveUnlockOnUnlockIntent);
        pw.println("   mRequestActiveUnlockOnBiometricFail=" + mRequestActiveUnlockOnBioFail);
        pw.println("   mRequestActiveUnlockOnAssistant=" + mRequestActiveUnlockOnAssistant);

        if (mIsAutomotive) {
            pw.println("  Running on Automotive build");
        }
+12 −6
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.view.accessibility.AccessibilityManager;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.ActiveUnlockConfig;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dagger.SysUISingleton;
@@ -658,9 +659,15 @@ public class UdfpsController implements DozeReceiver {
        mExecution.assertIsMainThread();

        mOverlay = overlay;
        final int requestReason = overlay.getRequestReason();
        if (requestReason == REASON_AUTH_KEYGUARD
                && !mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
            Log.d(TAG, "Attempting to showUdfpsOverlay when fingerprint detection"
                    + " isn't running on keyguard. Skip show.");
            return;
        }
        if (overlay.show(this, mOverlayParams)) {
            Log.v(TAG, "showUdfpsOverlay | adding window reason="
                    + overlay.getRequestReason());
            Log.v(TAG, "showUdfpsOverlay | adding window reason=" + requestReason);
            mOnFingerDown = false;
            mAttemptedToDismissKeyguard = false;
            mOrientationListener.enable();
@@ -791,10 +798,9 @@ public class UdfpsController implements DozeReceiver {
                mKeyguardUpdateMonitor.requestFaceAuth(/* userInitiatedRequest */ false);
            }

            if (mKeyguardUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) {
                mKeyguardUpdateMonitor.requestActiveUnlock("unlock-intent extra=udfpsFingerDown",
                        true);
            }
            mKeyguardUpdateMonitor.requestActiveUnlock(
                    ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
                    "udfpsFingerDown");
        }
        mOnFingerDown = true;
        if (mAlternateTouchProvider != null) {
+2 −1
Original line number Diff line number Diff line
@@ -510,7 +510,8 @@ public class KeyguardIndicationController {
                            .setMessage(trustGrantedIndication)
                            .setTextColor(mInitialTextColorState)
                            .build(),
                    false);
                    true);
            hideBiometricMessage();
        } else if (!TextUtils.isEmpty(trustManagedIndication)
                && mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
                && !userHasTrust) {
Loading