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

Commit a7164fa9 authored by Chandru S's avatar Chandru S Committed by Android (Google) Code Review
Browse files

Merge changes Id35e3914,I48b3a90d,Iee8df016,I60b52eba into main

* changes:
  Use a no-op implementation of face auth interactor whenever FaceManager is not present
  Consider face/fingerprint locked out state changes only when the biometrics are enrolled
  Add additional logging for state that bouncer messages rely on
  Remove redundant methods and change existing flows to StateFlows
parents f8c2e115 260882b5
Loading
Loading
Loading
Loading
+37 −1
Original line number Diff line number Diff line
@@ -263,7 +263,7 @@ class BouncerMessageInteractorTest : SysuiTestCase() {
        testScope.runTest {
            init()
            val lockoutMessage by collectLastValue(underTest.bouncerMessage)

            kosmos.fakeBiometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true)
            kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true)
            runCurrent()

@@ -280,6 +280,23 @@ class BouncerMessageInteractorTest : SysuiTestCase() {
            assertThat(lockoutMessage?.secondaryMessage?.message).isNull()
        }

    @Test
    fun onFaceLockoutStateChange_whenFaceIsNotEnrolled_isANoop() =
        testScope.runTest {
            init()
            val lockoutMessage by collectLastValue(underTest.bouncerMessage)

            kosmos.fakeBiometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(false)
            runCurrent()
            kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true)
            runCurrent()

            assertThat(primaryResMessage(lockoutMessage))
                .isEqualTo("Unlock with PIN or fingerprint")
            assertThat(lockoutMessage?.secondaryMessage?.message).isNull()
            assertThat(lockoutMessage?.secondaryMessage?.messageResId).isEqualTo(0)
        }

    @Test
    fun onFaceLockout_whenItIsClass3_propagatesState() =
        testScope.runTest {
@@ -288,6 +305,7 @@ class BouncerMessageInteractorTest : SysuiTestCase() {
            kosmos.fakeFacePropertyRepository.setSensorInfo(
                FaceSensorInfo(1, SensorStrength.STRONG)
            )
            kosmos.fakeBiometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true)
            kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true)
            runCurrent()

@@ -308,6 +326,7 @@ class BouncerMessageInteractorTest : SysuiTestCase() {
        testScope.runTest {
            init()
            val lockedOutMessage by collectLastValue(underTest.bouncerMessage)
            kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)

            kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(true)
            runCurrent()
@@ -324,6 +343,23 @@ class BouncerMessageInteractorTest : SysuiTestCase() {
            assertThat(lockedOutMessage?.secondaryMessage?.message).isNull()
        }

    @Test
    fun onFingerprintLockoutStateChange_whenFingerprintIsNotEnrolled_isANoop() =
        testScope.runTest {
            init()
            val lockoutMessage by collectLastValue(underTest.bouncerMessage)

            kosmos.fakeBiometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true)
            kosmos.fakeBiometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
            runCurrent()
            kosmos.fakeDeviceEntryFingerprintAuthRepository.setLockedOut(true)
            runCurrent()

            assertThat(primaryResMessage(lockoutMessage)).isEqualTo("Enter PIN")
            assertThat(lockoutMessage?.secondaryMessage?.message).isNull()
            assertThat(lockoutMessage?.secondaryMessage?.messageResId).isEqualTo(0)
        }

    @Test
    fun onUdfpsFingerprint_DoesNotShowFingerprintMessage() =
        testScope.runTest {
+6 −4
Original line number Diff line number Diff line
@@ -1384,7 +1384,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
     */
    @Deprecated
    public boolean getIsFaceAuthenticated() {
        return getFaceAuthInteractor() != null && getFaceAuthInteractor().isAuthenticated();
        return getFaceAuthInteractor() != null
                && getFaceAuthInteractor().isAuthenticated().getValue();
    }

    public boolean getUserCanSkipBouncer(int userId) {
@@ -1426,7 +1427,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
     */
    @Deprecated
    public boolean isCurrentUserUnlockedWithFace() {
        return getFaceAuthInteractor() != null && getFaceAuthInteractor().isAuthenticated();
        return getFaceAuthInteractor() != null
                && getFaceAuthInteractor().isAuthenticated().getValue();
    }

    /**
@@ -1516,7 +1518,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            return false;
        }
        boolean isFaceLockedOut =
                getFaceAuthInteractor() != null && getFaceAuthInteractor().isLockedOut();
                getFaceAuthInteractor() != null && getFaceAuthInteractor().isLockedOut().getValue();
        boolean isFaceAuthStrong =
                getFaceAuthInteractor() != null && getFaceAuthInteractor().isFaceAuthStrong();
        boolean isFingerprintLockedOut = isFingerprintLockedOut();
@@ -2967,7 +2969,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
     */
    @Deprecated
    public boolean isFaceLockedOut() {
        return getFaceAuthInteractor() != null && getFaceAuthInteractor().isLockedOut();
        return getFaceAuthInteractor() != null && getFaceAuthInteractor().isLockedOut().getValue();
    }

    /**
+33 −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.bouncer.dagger

import com.android.systemui.CoreStartable
import com.android.systemui.bouncer.log.BouncerLoggerStartable
import dagger.Binds
import dagger.Module
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap

@Module
interface BouncerLoggerModule {

    @Binds
    @IntoMap
    @ClassKey(BouncerLoggerStartable::class)
    fun bindBouncerLoggerStartable(impl: BouncerLoggerStartable): CoreStartable
}
+6 −2
Original line number Diff line number Diff line
@@ -189,10 +189,14 @@ constructor(
                            currentSecurityMode.toAuthModel()
                        )
                        .toMessage()
                } else if (fpLockedOut) {
                } else if (
                    biometricSettingsRepository.isFingerprintEnrolledAndEnabled.value && fpLockedOut
                ) {
                    BouncerMessageStrings.class3AuthLockedOut(currentSecurityMode.toAuthModel())
                        .toMessage()
                } else if (faceLockedOut) {
                } else if (
                    biometricSettingsRepository.isFaceAuthEnrolledAndEnabled.value && faceLockedOut
                ) {
                    if (isFaceAuthClass3) {
                        BouncerMessageStrings.class3AuthLockedOut(currentSecurityMode.toAuthModel())
                            .toMessage()
+81 −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.bouncer.log

import android.os.Build
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricSettingsInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.log.BouncerLogger
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

/** Startable that logs the flows that bouncer depends on. */
@OptIn(ExperimentalCoroutinesApi::class)
class BouncerLoggerStartable
@Inject
constructor(
    @Application private val applicationScope: CoroutineScope,
    private val biometricSettingsInteractor: DeviceEntryBiometricSettingsInteractor,
    private val faceAuthInteractor: DeviceEntryFaceAuthInteractor,
    private val fingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
    private val bouncerLogger: BouncerLogger,
) : CoreStartable {
    override fun start() {
        if (!Build.isDebuggable()) {
            return
        }
        applicationScope.launch {
            biometricSettingsInteractor.isFaceAuthEnrolledAndEnabled.collectLatest { newValue ->
                bouncerLogger.interestedStateChanged("isFaceAuthEnrolledAndEnabled", newValue)
            }
        }
        applicationScope.launch {
            biometricSettingsInteractor.isFingerprintAuthEnrolledAndEnabled.collectLatest { newValue
                ->
                bouncerLogger.interestedStateChanged(
                    "isFingerprintAuthEnrolledAndEnabled",
                    newValue
                )
            }
        }
        applicationScope.launch {
            faceAuthInteractor.isLockedOut.collectLatest { newValue ->
                bouncerLogger.interestedStateChanged("faceAuthLockedOut", newValue)
            }
        }
        applicationScope.launch {
            fingerprintAuthInteractor.isLockedOut.collectLatest { newValue ->
                bouncerLogger.interestedStateChanged("fingerprintLockedOut", newValue)
            }
        }
        applicationScope.launch {
            fingerprintAuthInteractor.isFingerprintCurrentlyAllowedOnBouncer.collectLatest {
                newValue ->
                bouncerLogger.interestedStateChanged(
                    "fingerprintCurrentlyAllowedOnBouncer",
                    newValue
                )
            }
        }
    }
}
Loading