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

Commit 2070b612 authored by Beverly's avatar Beverly
Browse files

Add new device entry icon state "None"

The "none" state shows the device entry icon UI.
This is then used when the device may have
started running UDFPS; however, the device isn't
yet locked yet. This can be from a race condition
between the device starting UDFPS listening and
the isUnlocked state being updated.

This can also be consistently seen after a screen timeout which,
by default, won't lock the device for the first 5s.
During this time, show no device entry icon UI
(previously, the UDFPS icon would show which could
be misleading).

Fixes: 329880412
Flag: ACONFIG com.android.systemui.device_entry_udfps_refactor NEXTFOOD
Test: tap on UDFPS icon in AOD to trigger a successful face unlock.
observe unlock icon on the lockscreen
Test: Enroll UDFPS. Wait for display timeout, see no device entry icon
for first 5s when the device is still unlocked. After 5s, the device is
locked and the UDFPS icon shows.
Test: atest DeviceEntryIconViewModelTest

Change-Id: I59a391c201fad3dd56a015def4306ea120e55361
parent 929ab9fd
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -132,8 +132,12 @@ object DeviceEntryIconViewBinder {
                            view.getIconState(viewModel.type, viewModel.useAodVariant),
                            /* merge */ false
                        )
                        if (viewModel.type.contentDescriptionResId != -1) {
                            fgIconView.contentDescription =
                            fgIconView.resources.getString(viewModel.type.contentDescriptionResId)
                                fgIconView.resources.getString(
                                    viewModel.type.contentDescriptionResId
                                )
                        }
                        fgIconView.imageTintList = ColorStateList.valueOf(viewModel.tint)
                        fgIconView.setPadding(
                            viewModel.padding,
+3 −1
Original line number Diff line number Diff line
@@ -214,7 +214,7 @@ constructor(
            R.id.unlocked,
            R.id.locked_aod,
            context.getDrawable(R.drawable.unlocked_to_aod_lock) as AnimatedVectorDrawable,
            /* reversible */ true,
            /* reversible */ false,
        )
    }

@@ -252,6 +252,7 @@ constructor(
            IconType.LOCK -> lockIconState[0] = android.R.attr.state_first
            IconType.UNLOCK -> lockIconState[0] = android.R.attr.state_last
            IconType.FINGERPRINT -> lockIconState[0] = android.R.attr.state_middle
            IconType.NONE -> return StateSet.NOTHING
        }
        if (aod) {
            lockIconState[1] = android.R.attr.state_single
@@ -265,6 +266,7 @@ constructor(
        LOCK(R.string.accessibility_lock_icon),
        UNLOCK(R.string.accessibility_unlock_button),
        FINGERPRINT(R.string.accessibility_fingerprint_label),
        NONE(-1),
    }

    enum class AccessibilityHintType {
+12 −4
Original line number Diff line number Diff line
@@ -195,7 +195,14 @@ constructor(
            isUnlocked,
        ) { isListeningForUdfps, isUnlocked ->
            if (isListeningForUdfps) {
                if (isUnlocked) {
                    // Don't show any UI until isUnlocked=false. This covers the case
                    // when the "Power button instantly locks > 0s" or the device doesn't lock
                    // immediately after a screen time.
                    DeviceEntryIconView.IconType.NONE
                } else {
                    DeviceEntryIconView.IconType.FINGERPRINT
                }
            } else if (isUnlocked) {
                DeviceEntryIconView.IconType.UNLOCK
            } else {
@@ -211,7 +218,8 @@ constructor(
            when (deviceEntryStatus) {
                DeviceEntryIconView.IconType.LOCK -> isUdfps
                DeviceEntryIconView.IconType.UNLOCK -> true
                DeviceEntryIconView.IconType.FINGERPRINT -> false
                DeviceEntryIconView.IconType.FINGERPRINT,
                DeviceEntryIconView.IconType.NONE -> false
            }
        }

@@ -239,8 +247,8 @@ constructor(
            DeviceEntryIconView.IconType.LOCK ->
                DeviceEntryIconView.AccessibilityHintType.AUTHENTICATE
            DeviceEntryIconView.IconType.UNLOCK -> DeviceEntryIconView.AccessibilityHintType.ENTER
            DeviceEntryIconView.IconType.FINGERPRINT ->
                DeviceEntryIconView.AccessibilityHintType.NONE
            DeviceEntryIconView.IconType.FINGERPRINT,
            DeviceEntryIconView.IconType.NONE -> DeviceEntryIconView.AccessibilityHintType.NONE
        }
    }

+41 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintA
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel.Companion.UNLOCKED_DELAY_MS
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
@@ -110,6 +110,46 @@ class DeviceEntryIconViewModelTest : SysuiTestCase() {
            assertThat(isVisible).isTrue()
        }

    @Test
    fun iconType_fingerprint() =
        testScope.runTest {
            val iconType by collectLastValue(underTest.iconType)
            keyguardRepository.setKeyguardDismissible(false)
            fingerprintPropertyRepository.supportsUdfps()
            fingerprintAuthRepository.setIsRunning(true)
            assertThat(iconType).isEqualTo(DeviceEntryIconView.IconType.FINGERPRINT)
        }

    @Test
    fun iconType_locked() =
        testScope.runTest {
            val iconType by collectLastValue(underTest.iconType)
            keyguardRepository.setKeyguardDismissible(false)
            fingerprintAuthRepository.setIsRunning(false)
            assertThat(iconType).isEqualTo(DeviceEntryIconView.IconType.LOCK)
        }

    @Test
    fun iconType_unlocked() =
        testScope.runTest {
            val iconType by collectLastValue(underTest.iconType)
            keyguardRepository.setKeyguardDismissible(true)
            advanceTimeBy(UNLOCKED_DELAY_MS * 2) // wait for unlocked delay
            fingerprintAuthRepository.setIsRunning(false)
            assertThat(iconType).isEqualTo(DeviceEntryIconView.IconType.UNLOCK)
        }

    @Test
    fun iconType_none() =
        testScope.runTest {
            val iconType by collectLastValue(underTest.iconType)
            keyguardRepository.setKeyguardDismissible(true)
            advanceTimeBy(UNLOCKED_DELAY_MS * 2) // wait for unlocked delay
            fingerprintPropertyRepository.supportsUdfps()
            fingerprintAuthRepository.setIsRunning(true)
            assertThat(iconType).isEqualTo(DeviceEntryIconView.IconType.NONE)
        }

    private fun deviceEntryIconTransitionAlpha(alpha: Float) {
        deviceEntryIconTransition.setDeviceEntryParentViewAlpha(alpha)
    }