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

Commit 27ff895b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add active unlock trigger"

parents cd7d4450 3bdab009
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -17,4 +17,5 @@
<resources>
<resources>
    <bool name="kg_show_ime_at_screen_on">true</bool>
    <bool name="kg_show_ime_at_screen_on">true</bool>
    <bool name="kg_use_all_caps">true</bool>
    <bool name="kg_use_all_caps">true</bool>
    <bool name="flag_active_unlock">false</bool>
</resources>
</resources>
+16 −0
Original line number Original line Diff line number Diff line
@@ -64,3 +64,19 @@ data class KeyguardFaceListenModel(
    val secureCameraLaunched: Boolean,
    val secureCameraLaunched: Boolean,
    val switchingUser: Boolean
    val switchingUser: Boolean
) : KeyguardListenModel()
) : KeyguardListenModel()
/**
 * Verbose debug information associated with [KeyguardUpdateMonitor.shouldTriggerActiveUnlock].
 */
data class KeyguardActiveUnlockModel(
    @CurrentTimeMillisLong override val timeMillis: Long,
    override val userId: Int,
    override val listening: Boolean,
    // keep sorted
    val authInterruptActive: Boolean,
    val encryptedOrTimedOut: Boolean,
    val fpLockout: Boolean,
    val lockDown: Boolean,
    val switchingUser: Boolean,
    val triggerActiveUnlockForAssistant: Boolean,
    val userCanDismissLockScreen: Boolean
) : KeyguardListenModel()
+7 −1
Original line number Original line Diff line number Diff line
@@ -32,15 +32,17 @@ class KeyguardListenQueue(
) {
) {
    private val faceQueue = ArrayDeque<KeyguardFaceListenModel>()
    private val faceQueue = ArrayDeque<KeyguardFaceListenModel>()
    private val fingerprintQueue = ArrayDeque<KeyguardFingerprintListenModel>()
    private val fingerprintQueue = ArrayDeque<KeyguardFingerprintListenModel>()
    private val activeUnlockQueue = ArrayDeque<KeyguardActiveUnlockModel>()


    @get:VisibleForTesting val models: List<KeyguardListenModel>
    @get:VisibleForTesting val models: List<KeyguardListenModel>
        get() = faceQueue + fingerprintQueue
        get() = faceQueue + fingerprintQueue + activeUnlockQueue


    /** Push a [model] to the queue (will be logged until the queue exceeds [sizePerModality]). */
    /** Push a [model] to the queue (will be logged until the queue exceeds [sizePerModality]). */
    fun add(model: KeyguardListenModel) {
    fun add(model: KeyguardListenModel) {
        val queue = when (model) {
        val queue = when (model) {
            is KeyguardFaceListenModel -> faceQueue.apply { add(model) }
            is KeyguardFaceListenModel -> faceQueue.apply { add(model) }
            is KeyguardFingerprintListenModel -> fingerprintQueue.apply { add(model) }
            is KeyguardFingerprintListenModel -> fingerprintQueue.apply { add(model) }
            is KeyguardActiveUnlockModel -> activeUnlockQueue.apply { add(model) }
        }
        }


        if (queue.size > sizePerModality) {
        if (queue.size > sizePerModality) {
@@ -63,5 +65,9 @@ class KeyguardListenQueue(
        for (model in fingerprintQueue) {
        for (model in fingerprintQueue) {
            writer.println(stringify(model))
            writer.println(stringify(model))
        }
        }
        writer.println("  Active unlock triggers (last ${activeUnlockQueue.size} calls):")
        for (model in activeUnlockQueue) {
            writer.println(stringify(model))
        }
    }
    }
}
}
+119 −1
Original line number Original line Diff line number Diff line
@@ -37,6 +37,8 @@ import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AlarmManager;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.PendingIntent;
import android.app.UserSwitchObserver;
import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManager;
@@ -102,6 +104,8 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -109,6 +113,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.Assert;
import com.android.systemui.util.NotificationChannels;
import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.RingerModeTracker;


import com.google.android.collect.Lists;
import com.google.android.collect.Lists;
@@ -143,8 +148,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
    private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
    private static final boolean DEBUG_FACE = Build.IS_DEBUGGABLE;
    private static final boolean DEBUG_FACE = Build.IS_DEBUGGABLE;
    private static final boolean DEBUG_FINGERPRINT = Build.IS_DEBUGGABLE;
    private static final boolean DEBUG_FINGERPRINT = Build.IS_DEBUGGABLE;
    private static final boolean DEBUG_ACTIVE_UNLOCK = Build.IS_DEBUGGABLE;
    private static final boolean DEBUG_SPEW = false;
    private static final boolean DEBUG_SPEW = false;
    private static final int BIOMETRIC_LOCKOUT_RESET_DELAY_MS = 600;
    private static final int BIOMETRIC_LOCKOUT_RESET_DELAY_MS = 600;
    private int mNumActiveUnlockTriggers = 0;


    private static final String ACTION_FACE_UNLOCK_STARTED
    private static final String ACTION_FACE_UNLOCK_STARTED
            = "com.android.facelock.FACE_UNLOCK_STARTED";
            = "com.android.facelock.FACE_UNLOCK_STARTED";
@@ -331,6 +338,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private final Executor mBackgroundExecutor;
    private final Executor mBackgroundExecutor;
    private SensorPrivacyManager mSensorPrivacyManager;
    private SensorPrivacyManager mSensorPrivacyManager;
    private FeatureFlags mFeatureFlags;
    private int mFaceAuthUserId;
    private int mFaceAuthUserId;


    /**
    /**
@@ -1312,6 +1320,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    void setAssistantVisible(boolean assistantVisible) {
    void setAssistantVisible(boolean assistantVisible) {
        mAssistantVisible = assistantVisible;
        mAssistantVisible = assistantVisible;
        updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
        updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
        if (mAssistantVisible) {
            requestActiveUnlock();
        }
    }
    }


    static class DisplayClientState {
    static class DisplayClientState {
@@ -1651,6 +1662,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
        Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
        Assert.isMainThread();
        Assert.isMainThread();
        updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
        updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
        requestActiveUnlock();
        for (int i = 0; i < mCallbacks.size(); i++) {
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
            if (cb != null) {
@@ -1778,7 +1790,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            AuthController authController,
            AuthController authController,
            TelephonyListenerManager telephonyListenerManager,
            TelephonyListenerManager telephonyListenerManager,
            InteractionJankMonitor interactionJankMonitor,
            InteractionJankMonitor interactionJankMonitor,
            LatencyTracker latencyTracker) {
            LatencyTracker latencyTracker,
            FeatureFlags featureFlags) {
        mContext = context;
        mContext = context;
        mSubscriptionManager = SubscriptionManager.from(context);
        mSubscriptionManager = SubscriptionManager.from(context);
        mTelephonyListenerManager = telephonyListenerManager;
        mTelephonyListenerManager = telephonyListenerManager;
@@ -1796,6 +1809,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        mAuthController = authController;
        mAuthController = authController;
        dumpManager.registerDumpable(getClass().getName(), this);
        dumpManager.registerDumpable(getClass().getName(), this);
        mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
        mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
        mFeatureFlags = featureFlags;


        mHandler = new Handler(mainLooper) {
        mHandler = new Handler(mainLooper) {
            @Override
            @Override
@@ -2181,6 +2195,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }
        }
        mAuthInterruptActive = active;
        mAuthInterruptActive = active;
        updateFaceListeningState(BIOMETRIC_ACTION_UPDATE);
        updateFaceListeningState(BIOMETRIC_ACTION_UPDATE);
        requestActiveUnlock();
    }
    }


    /**
    /**
@@ -2229,6 +2244,97 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        }
        }
    }
    }


    /**
     * Attempts to trigger active unlock.
     */
    public void requestActiveUnlock() {
        // If this message exists, FP has already authenticated, so wait until that is handled
        if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
            return;
        }

        if (shouldTriggerActiveUnlock() && mFeatureFlags.isEnabled(Flags.ACTIVE_UNLOCK)) {
            // TODO (b/192405661): call new TrustManager API
            mNumActiveUnlockTriggers++;
            Log.d("ActiveUnlock", "would have triggered times=" + mNumActiveUnlockTriggers);
            showActiveUnlockNotification(mNumActiveUnlockTriggers);
        }
    }

    /**
     * TODO (b/192405661): Only for testing. Remove before release.
     */
    private void showActiveUnlockNotification(int times) {
        final String message = "Active unlock triggered "  + times + " times.";
        final Notification.Builder nb =
                new Notification.Builder(mContext, NotificationChannels.GENERAL)
                        .setSmallIcon(R.drawable.ic_volume_ringer)
                        .setContentTitle(message)
                        .setStyle(new Notification.BigTextStyle().bigText(message));
        mContext.getSystemService(NotificationManager.class).notifyAsUser(
                "active_unlock",
                0,
                nb.build(),
                UserHandle.ALL);
    }

    private boolean shouldTriggerActiveUnlock() {
        // TODO: check if active unlock is ENABLED / AVAILABLE

        // Triggers:
        final boolean triggerActiveUnlockForAssistant = shouldTriggerActiveUnlockForAssistant();
        final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep
                && mStatusBarState != StatusBarState.SHADE_LOCKED;

        // Gates:
        final int user = getCurrentUser();

        // No need to trigger active unlock if we're already unlocked or don't have
        // pin/pattern/password setup
        final boolean userCanDismissLockScreen = getUserCanSkipBouncer(user)
                || !mLockPatternUtils.isSecure(user);

        // Don't trigger active unlock if fp is locked out TODO: confirm this one
        final boolean fpLockedout = mFingerprintLockedOut || mFingerprintLockedOutPermanent;

        // Don't trigger active unlock if primary auth is required
        final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
        final boolean isLockDown =
                containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
                        || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
        final boolean isEncryptedOrTimedOut =
                containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
                        || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);

        final boolean shouldTriggerActiveUnlock =
                (mAuthInterruptActive || triggerActiveUnlockForAssistant || awakeKeyguard)
                        && !mSwitchingUser
                        && !userCanDismissLockScreen
                        && !fpLockedout
                        && !isLockDown
                        && !isEncryptedOrTimedOut
                        && !mKeyguardGoingAway
                        && !mSecureCameraLaunched;

        // Aggregate relevant fields for debug logging.
        if (DEBUG_ACTIVE_UNLOCK || DEBUG_SPEW) {
            maybeLogListenerModelData(
                    new KeyguardActiveUnlockModel(
                            System.currentTimeMillis(),
                            user,
                            shouldTriggerActiveUnlock,
                            mAuthInterruptActive,
                            isEncryptedOrTimedOut,
                            fpLockedout,
                            isLockDown,
                            mSwitchingUser,
                            triggerActiveUnlockForAssistant,
                            userCanDismissLockScreen));
        }

        return shouldTriggerActiveUnlock;
    }

    private boolean shouldListenForFingerprintAssistant() {
    private boolean shouldListenForFingerprintAssistant() {
        BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(getCurrentUser());
        BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(getCurrentUser());
        return mAssistantVisible && mKeyguardOccluded
        return mAssistantVisible && mKeyguardOccluded
@@ -2243,6 +2349,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                && !mUserHasTrust.get(getCurrentUser(), false);
                && !mUserHasTrust.get(getCurrentUser(), false);
    }
    }


    private boolean shouldTriggerActiveUnlockForAssistant() {
        return mAssistantVisible && mKeyguardOccluded
                && !mUserHasTrust.get(getCurrentUser(), false);
    }

    @VisibleForTesting
    @VisibleForTesting
    protected boolean shouldListenForFingerprint(boolean isUdfps) {
    protected boolean shouldListenForFingerprint(boolean isUdfps) {
        final int user = getCurrentUser();
        final int user = getCurrentUser();
@@ -2407,6 +2518,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            Log.v(TAG, model.toString());
            Log.v(TAG, model.toString());
        }
        }


        if (DEBUG_ACTIVE_UNLOCK
                && model instanceof KeyguardActiveUnlockModel
                && model.getListening()) {
            mListenModels.add(model);
            return;
        }

        // Add model data to the historical buffer.
        // Add model data to the historical buffer.
        final boolean notYetRunning =
        final boolean notYetRunning =
                (DEBUG_FACE
                (DEBUG_FACE
+3 −0
Original line number Original line Diff line number Diff line
@@ -74,6 +74,9 @@ public class Flags {
    public static final ResourceBooleanFlag BOUNCER_USER_SWITCHER =
    public static final ResourceBooleanFlag BOUNCER_USER_SWITCHER =
            new ResourceBooleanFlag(204, R.bool.config_enableBouncerUserSwitcher);
            new ResourceBooleanFlag(204, R.bool.config_enableBouncerUserSwitcher);


    public static final ResourceBooleanFlag ACTIVE_UNLOCK =
            new ResourceBooleanFlag(205, R.bool.flag_active_unlock);

    /***************************************/
    /***************************************/
    // 300 - power menu
    // 300 - power menu
    public static final BooleanFlag POWER_MENU_LITE =
    public static final BooleanFlag POWER_MENU_LITE =
Loading