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

Commit 77df401b authored by Beverly's avatar Beverly
Browse files

New method showDismissibleKeyguard: shows keyguard without locking

Show a message on the keyguard when the keyguard
is kept unlocked after a fold event. Inform
the user to swipe up to continue.

Respect lockdown and biometric lockouts. Don't allow
the keyguard to show unlocked in these cases.

This feature is guarded behind the fold grace period flag.

Bug: 308417021
Flag: ACONFIG com.android.internal.foldables.flags.fold_grace_period_enabled DEVELOPMENT
Test: atest KeyguardViewMediatorTest KeyguardUpdateMonitorTest
Test: manual (adb root && adb shell setprop persist.fold_grace_period_enabled true && adb reboot)
Change-Id: I70a39932cf2e9097df7267c2c6b73e7323de73be
parent eff48da6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -130,4 +130,10 @@ oneway interface IKeyguardService {
     * Note that it's called only if the device is interactive.
     */
    void onSystemKeyPressed(int keycode);

    /**
     * Requests to show the keyguard immediately without locking the device. Keyguard will show
     * whether a screen lock was configured or not (including if screen lock is SWIPE or NONE).
     */
    void showDismissibleKeyguard();
}
+3 −0
Original line number Diff line number Diff line
@@ -3262,6 +3262,9 @@
    <!-- Label for a button that, when clicked, sends the user to the app store to install an app. [CHAR LIMIT=64]. -->
    <string name="install_app">Install app</string>

    <!-- Instructions informing the user they can swipe up on the lockscreen to dismiss [CHAR LIMIT=48]-->
    <string name="dismissible_keyguard_swipe">Swipe to continue</string>

    <!--- Title of the dialog appearing when an external display is connected, asking whether to start mirroring [CHAR LIMIT=NONE]-->
    <string name="connected_display_dialog_start_mirroring">Mirror to external display?</string>
    <!--- Body of the mirroring dialog, shown when dual display is enabled. This signals that enabling mirroring will stop concurrent displays on a foldable device. [CHAR LIMIT=NONE]-->
+2 −1
Original line number Diff line number Diff line
@@ -133,7 +133,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
    static final int BOUNCER_DISMISS_EXTENDED_ACCESS = 3;
    // Bouncer is dismissed due to sim card unlock code entered.
    static final int BOUNCER_DISMISS_SIM = 4;

    // Bouncer dismissed after being allowed to dismiss by forceDismissiblekeyguard
    static final int BOUNCER_DISMISSIBLE_KEYGUARD = 5;
    private static final String TAG = "KeyguardSecurityView";

    // Make the view move slower than the finger, as if the spring were applying force.
+6 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;

import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISSIBLE_KEYGUARD;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_NONE_SECURITY;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_PASSWORD;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_SIM;
@@ -862,7 +863,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
        boolean finish = false;
        int eventSubtype = -1;
        BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;
        if (mUpdateMonitor.getUserHasTrust(targetUserId)) {
        if (mUpdateMonitor.forceIsDismissibleIsKeepingDeviceUnlocked()) {
            finish = true;
            eventSubtype = BOUNCER_DISMISSIBLE_KEYGUARD;
            // TODO: b/308417021 add UI event
        } else if (mUpdateMonitor.getUserHasTrust(targetUserId)) {
            finish = true;
            eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS;
            uiEvent = BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS;
+62 −1
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.foldables.FoldGracePeriodProvider;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
@@ -308,6 +309,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private boolean mKeyguardOccluded;
    private boolean mCredentialAttempted;
    private boolean mKeyguardGoingAway;
    /**
     * Whether the keyguard is forced into a dismissible state.
     */
    private boolean mForceIsDismissible;
    private boolean mGoingToSleep;
    private boolean mPrimaryBouncerFullyShown;
    private boolean mPrimaryBouncerIsOrWillBeShowing;
@@ -362,6 +367,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private final BiometricManager mBiometricManager;
    @Nullable
    private DeviceEntryFaceAuthInteractor mFaceAuthInteractor;
    @VisibleForTesting
    protected FoldGracePeriodProvider mFoldGracePeriodProvider =
            new FoldGracePeriodProvider();
    private final DevicePostureController mDevicePostureController;
    private final TaskStackChangeListeners mTaskStackChangeListeners;
    private final IActivityTaskManager mActivityTaskManager;
@@ -727,6 +735,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
    }

    /**
     * Updates KeyguardUpdateMonitor's internal state to know the device should remain unlocked
     * until the next signal to lock. Does nothing if the keyguard is already showing.
     */
    public void tryForceIsDismissibleKeyguard() {
        setForceIsDismissibleKeyguard(true);
    }

    /**
     * Updates KeyguardUpdateMonitor's internal state to know if keyguard is going away.
     */
@@ -1371,7 +1387,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    }

    public boolean getUserCanSkipBouncer(int userId) {
        return getUserHasTrust(userId) || getUserUnlockedWithBiometric(userId);
        return getUserHasTrust(userId) || getUserUnlockedWithBiometric(userId)
                || forceIsDismissibleIsKeepingDeviceUnlocked();
    }

    /**
     * Whether the keyguard should be kept unlocked for the folding grace period.
     */
    public boolean forceIsDismissibleIsKeepingDeviceUnlocked() {
        if (mFoldGracePeriodProvider.isEnabled()) {
            return mForceIsDismissible && isUnlockingWithForceKeyguardDismissibleAllowed();
        }
        return false;
    }

    public boolean getUserHasTrust(int userId) {
@@ -1475,6 +1502,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        return isUnlockingWithBiometricAllowed(true);
    }

    private boolean isUnlockingWithForceKeyguardDismissibleAllowed() {
        return isUnlockingWithBiometricAllowed(false);
    }

    public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
        // StrongAuthTracker#isUnlockingWithBiometricAllowed includes
        // STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent;
@@ -1986,6 +2017,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab

    protected void handleStartedGoingToSleep(int arg1) {
        Assert.isMainThread();
        setForceIsDismissibleKeyguard(false);
        clearFingerprintRecognized();
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -3058,6 +3090,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    void handleUserSwitching(int userId, Runnable resultCallback) {
        mLogger.logUserSwitching(userId, "from UserTracker");
        Assert.isMainThread();
        setForceIsDismissibleKeyguard(false);
        clearFingerprintRecognized();
        boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
        mLogger.logTrustUsuallyManagedUpdated(userId, mUserTrustIsUsuallyManaged.get(userId),
@@ -3636,6 +3669,31 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }
    }

    private void setForceIsDismissibleKeyguard(boolean forceIsDismissible) {
        Assert.isMainThread();
        if (!mFoldGracePeriodProvider.isEnabled()) {
            // never send updates if the feature isn't enabled
            return;
        }
        if (mKeyguardShowing && forceIsDismissible) {
            // never keep the device unlocked if the keyguard was already showing
            mLogger.d("Skip setting forceIsDismissibleKeyguard to true. "
                    + "Keyguard already showing.");
            return;
        }
        if (mForceIsDismissible != forceIsDismissible) {
            mForceIsDismissible = forceIsDismissible;
            mLogger.logForceIsDismissibleKeyguard(mForceIsDismissible);
            for (int i = 0; i < mCallbacks.size(); i++) {
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
                if (cb != null) {
                    cb.onForceIsDismissibleChanged(forceIsDismissibleIsKeepingDeviceUnlocked());
                }
            }
        }

    }

    public boolean isSimPinVoiceSecure() {
        // TODO: only count SIMs that handle voice
        return isSimPinSecure();
@@ -3897,6 +3955,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    @Override
    public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
        pw.println("KeyguardUpdateMonitor state:");
        pw.println("  forceIsDismissible=" + mForceIsDismissible);
        pw.println("  forceIsDismissibleIsKeepingDeviceUnlocked="
                + forceIsDismissibleIsKeepingDeviceUnlocked());
        pw.println("  getUserHasTrust()=" + getUserHasTrust(
                mSelectedUserInteractor.getSelectedUserId()));
        pw.println("  getUserUnlockedWithBiometric()="
Loading