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

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

Merge "Show directional face auth feedback when unfolded" into main

parents b94588a8 b519f3be
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -720,6 +720,20 @@
        <item>26</item> <!-- MOUTH_COVERING_DETECTED -->
    </integer-array>

    <!-- Which face help messages to surface when fingerprint is enrolled and device is unfolded.
     Message ids correspond with the acquired ids in BiometricFaceConstants -->
    <integer-array name="config_face_help_msgs_when_fingerprint_enrolled_unfolded">
        <item>3</item> <!-- TOO_DARK -->
        <item>4</item> <!-- TOO_CLOSE -->
        <item>5</item> <!-- TOO_FAR -->
        <item>6</item> <!-- TOO_HIGH -->
        <item>7</item> <!-- TOO_LOW -->
        <item>8</item> <!-- TOO_RIGHT -->
        <item>9</item> <!-- TOO_LEFT -->
        <item>25</item> <!-- DARK_GLASSES -->
        <item>26</item> <!-- MOUTH_COVERING_DETECTED -->
    </integer-array>

    <!-- Which device wake-ups will trigger passive auth. These values correspond with
         PowerManager#WakeReason. -->
    <integer-array name="config_face_auth_wake_up_triggers">
+52 −15
Original line number Diff line number Diff line
@@ -30,17 +30,20 @@ import com.android.systemui.deviceentry.shared.model.FingerprintFailureMessage
import com.android.systemui.deviceentry.shared.model.FingerprintLockoutMessage
import com.android.systemui.deviceentry.shared.model.FingerprintMessage
import com.android.systemui.deviceentry.shared.model.HelpFaceAuthenticationStatus
import com.android.systemui.keyguard.domain.interactor.DevicePostureInteractor
import com.android.systemui.keyguard.shared.model.DevicePosture
import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthenticationStatus
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.Utils.Companion.toTriple
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge

@@ -59,6 +62,7 @@ constructor(
    faceAuthInteractor: DeviceEntryFaceAuthInteractor,
    private val biometricSettingsInteractor: DeviceEntryBiometricSettingsInteractor,
    faceHelpMessageDeferralInteractor: FaceHelpMessageDeferralInteractor,
    devicePostureInteractor: DevicePostureInteractor,
) {
    private val faceHelp: Flow<HelpFaceAuthenticationStatus> =
        faceAuthInteractor.authenticationStatus.filterIsInstance<HelpFaceAuthenticationStatus>()
@@ -71,9 +75,18 @@ constructor(
     * The acquisition message ids to show message when both fingerprint and face are enrolled and
     * enabled for device entry.
     */
    private val coExFaceAcquisitionMsgIdsToShow: Set<Int> =
    private val coExFaceAcquisitionMsgIdsToShowDefault: Set<Int> =
        resources.getIntArray(R.array.config_face_help_msgs_when_fingerprint_enrolled).toSet()

    /**
     * The acquisition message ids to show message when both fingerprint and face are enrolled and
     * enabled for device entry and the device is unfolded.
     */
    private val coExFaceAcquisitionMsgIdsToShowUnfolded: Set<Int> =
        resources
            .getIntArray(R.array.config_face_help_msgs_when_fingerprint_enrolled_unfolded)
            .toSet()

    private fun ErrorFingerprintAuthenticationStatus.shouldSuppressError(): Boolean {
        return isCancellationError() || isPowerPressedError()
    }
@@ -122,6 +135,17 @@ constructor(
                }
        }

    val coExFaceAcquisitionMsgIdsToShow: Flow<Set<Int>> =
        devicePostureInteractor.posture.map { devicePosture ->
            when (devicePosture) {
                DevicePosture.OPENED -> coExFaceAcquisitionMsgIdsToShowUnfolded
                DevicePosture.UNKNOWN, // Devices without posture support (non-foldable) use UNKNOWN
                DevicePosture.CLOSED,
                DevicePosture.HALF_OPENED,
                DevicePosture.FLIPPED -> coExFaceAcquisitionMsgIdsToShowDefault
            }
        }

    val fingerprintMessage: Flow<FingerprintMessage> =
        merge(
            fingerprintErrorMessage,
@@ -129,25 +153,38 @@ constructor(
            fingerprintHelpMessage,
        )

    private val filterConditionForFaceHelpMessages:
        Flow<(HelpFaceAuthenticationStatus) -> Boolean> =
        combine(
                biometricSettingsInteractor.isFingerprintAuthEnrolledAndEnabled,
                biometricSettingsInteractor.faceAuthCurrentlyAllowed,
                ::Pair
            )
            .flatMapLatest { (fingerprintEnrolled, faceAuthCurrentlyAllowed) ->
                if (fingerprintEnrolled && faceAuthCurrentlyAllowed) {
                    // Show only some face help messages if fingerprint is also enrolled
                    coExFaceAcquisitionMsgIdsToShow.map { msgIdsToShow ->
                        { helpStatus: HelpFaceAuthenticationStatus ->
                            msgIdsToShow.contains(helpStatus.msgId)
                        }
                    }
                } else if (faceAuthCurrentlyAllowed) {
                    // Show all face help messages if only face is enrolled and currently allowed
                    flowOf { _: HelpFaceAuthenticationStatus -> true }
                } else {
                    flowOf { _: HelpFaceAuthenticationStatus -> false }
                }
            }

    private val faceHelpMessage: Flow<FaceMessage> =
        faceHelp
            .filterNot {
                // Message deferred to potentially show at face timeout error instead
                faceHelpMessageDeferralInteractor.shouldDefer(it.msgId)
            }
            .sample(biometricSettingsInteractor.fingerprintAndFaceEnrolledAndEnabled, ::Pair)
            .filter { (faceAuthHelpStatus, fingerprintAndFaceEnrolledAndEnabled) ->
                if (fingerprintAndFaceEnrolledAndEnabled) {
                    // Show only some face help messages if fingerprint is also enrolled
                    coExFaceAcquisitionMsgIdsToShow.contains(faceAuthHelpStatus.msgId)
                } else {
                    // Show all face help messages if only face is enrolled
                    true
                }
            }
            .sample(biometricSettingsInteractor.faceAuthCurrentlyAllowed, ::toTriple)
            .filter { (_, _, faceAuthCurrentlyAllowed) -> faceAuthCurrentlyAllowed }
            .map { (status, _, _) -> FaceMessage(status.msg) }
            .sample(filterConditionForFaceHelpMessages, ::Pair)
            .filter { (helpMessage, filterCondition) -> filterCondition(helpMessage) }
            .map { (status, _) -> FaceMessage(status.msg) }

    private val faceFailureMessage: Flow<FaceMessage> =
        faceFailure
+31 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.systemui.keyguard.domain.interactor

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.DevicePostureRepository
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi

/** DevicePosture business logic. */
@ExperimentalCoroutinesApi
@SysUISingleton
class DevicePostureInteractor
@Inject
constructor(devicePostureRepository: DevicePostureRepository) {
    val posture = devicePostureRepository.currentDevicePosture
}
+15 −10
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.deviceentry.domain.interactor.BiometricMessageInteractor;
import com.android.systemui.dock.DockManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardIndication;
@@ -120,7 +121,6 @@ import com.android.systemui.util.wakelock.WakeLock;

import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;

@@ -182,6 +182,7 @@ public class KeyguardIndicationController {
    private BroadcastReceiver mBroadcastReceiver;
    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
    private KeyguardInteractor mKeyguardInteractor;
    private final BiometricMessageInteractor mBiometricMessageInteractor;
    private String mPersistentUnlockMessage;
    private String mAlignmentIndication;
    private boolean mForceIsDismissible;
@@ -212,7 +213,7 @@ public class KeyguardIndicationController {
    private boolean mBatteryPresent = true;
    protected long mChargingTimeRemaining;
    private Pair<String, BiometricSourceType> mBiometricErrorMessageToShowOnScreenOn;
    private final Set<Integer> mCoExFaceAcquisitionMsgIdsToShow;
    private Set<Integer> mCoExFaceAcquisitionMsgIdsToShow;
    private final FaceHelpMessageDeferral mFaceAcquiredMessageDeferral;
    private boolean mInited;

@@ -230,6 +231,10 @@ public class KeyguardIndicationController {
                mIsActiveDreamLockscreenHosted = isLockscreenHosted;
                updateDeviceEntryIndication(false);
            };
    @VisibleForTesting
    final Consumer<Set<Integer>> mCoExAcquisitionMsgIdsToShowCallback =
            (Set<Integer> coExFaceAcquisitionMsgIdsToShow) -> mCoExFaceAcquisitionMsgIdsToShow =
                    coExFaceAcquisitionMsgIdsToShow;
    private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
        @Override
        public void onScreenTurnedOn() {
@@ -289,7 +294,8 @@ public class KeyguardIndicationController {
            BouncerMessageInteractor bouncerMessageInteractor,
            FeatureFlags flags,
            IndicationHelper indicationHelper,
            KeyguardInteractor keyguardInteractor
            KeyguardInteractor keyguardInteractor,
            BiometricMessageInteractor biometricMessageInteractor
    ) {
        mContext = context;
        mBroadcastDispatcher = broadcastDispatcher;
@@ -318,14 +324,9 @@ public class KeyguardIndicationController {
        mFeatureFlags = flags;
        mIndicationHelper = indicationHelper;
        mKeyguardInteractor = keyguardInteractor;
        mBiometricMessageInteractor = biometricMessageInteractor;

        mFaceAcquiredMessageDeferral = faceHelpMessageDeferral.create();
        mCoExFaceAcquisitionMsgIdsToShow = new HashSet<>();
        int[] msgIds = context.getResources().getIntArray(
                com.android.systemui.res.R.array.config_face_help_msgs_when_fingerprint_enrolled);
        for (int msgId : msgIds) {
            mCoExFaceAcquisitionMsgIdsToShow.add(msgId);
        }

        mHandler = new Handler(mainLooper) {
            @Override
@@ -404,6 +405,10 @@ public class KeyguardIndicationController {
            collectFlow(mIndicationArea, mKeyguardInteractor.isActiveDreamLockscreenHosted(),
                    mIsActiveDreamLockscreenHostedCallback);
        }

        collectFlow(mIndicationArea,
                mBiometricMessageInteractor.getCoExFaceAcquisitionMsgIdsToShow(),
                mCoExAcquisitionMsgIdsToShowCallback);
    }

    /**
+2 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ class Utils {
        fun <A, B, C, D> toQuad(a: A, b: B, c: C, d: D) = Quad(a, b, c, d)
        fun <A, B, C, D> toQuad(a: A, bcd: Triple<B, C, D>) =
            Quad(a, bcd.first, bcd.second, bcd.third)
        fun <A, B, C, D> toQuad(abc: Triple<A, B, C>, d: D) =
            Quad(abc.first, abc.second, abc.third, d)

        fun <A, B, C, D, E> toQuint(a: A, b: B, c: C, d: D, e: E) = Quint(a, b, c, d, e)
        fun <A, B, C, D, E> toQuint(a: A, bcde: Quad<B, C, D, E>) =
Loading