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

Commit 9a66753c authored by Brad Hinegardner's avatar Brad Hinegardner Committed by Android Build Coastguard Worker
Browse files

Prevent shortcuts from using the same instance of wallet icon

Quick affordances and quick settings were mutating the same instance
of the wallet Drawable, accidentally modifying one another.

Added tests to explicitly test against this. If we cannot
create a newDrawable, shortcuts will fall back to the resource.

Fixes: b/394282762
Test: atest QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
Flag: EXEMPT BUGFIX
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:de99b6345198375b81d2315a2bfac836265823f3
Merged-In: I227ed8ca8ddfa15e0fc27d3c612b9489626a4a7c
Change-Id: I227ed8ca8ddfa15e0fc27d3c612b9489626a4a7c
parent 284f1ec3
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -79,12 +79,25 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
    fun affordance_keyguardShowing_hasWalletCard_visibleModel() =
        testScope.runTest {
            setUpState()
            val iconCopy: Drawable = mock()
            val constantState: Drawable.ConstantState = mock()
            whenever(ICON.constantState).thenReturn(constantState)
            whenever(constantState.newDrawable()).thenReturn(iconCopy)

            val latest by collectLastValue(underTest.lockScreenState)

            val visibleModel = latest as KeyguardQuickAffordanceConfig.LockScreenState.Visible
            assertThat(visibleModel.icon)
                .isEqualTo(
                    Icon.Loaded(
                        drawable = iconCopy,
                        contentDescription =
                            ContentDescription.Resource(res = R.string.accessibility_wallet_button),
                    )
                )

            assertThat(visibleModel.icon)
                .isNotEqualTo(
                    Icon.Loaded(
                        drawable = ICON,
                        contentDescription =
@@ -107,12 +120,25 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
    fun affordance_keyguardShowing_hasPaymentCard_visibleModel() =
        testScope.runTest {
            setUpState(cardType = WalletCard.CARD_TYPE_PAYMENT)
            val iconCopy: Drawable = mock()
            val constantState: Drawable.ConstantState = mock()
            whenever(ICON.constantState).thenReturn(constantState)
            whenever(constantState.newDrawable()).thenReturn(iconCopy)

            val latest by collectLastValue(underTest.lockScreenState)

            val visibleModel = latest as KeyguardQuickAffordanceConfig.LockScreenState.Visible
            assertThat(visibleModel.icon)
                .isEqualTo(
                    Icon.Loaded(
                        drawable = iconCopy,
                        contentDescription =
                            ContentDescription.Resource(res = R.string.accessibility_wallet_button),
                    )
                )

            assertThat(visibleModel.icon)
                .isNotEqualTo(
                    Icon.Loaded(
                        drawable = ICON,
                        contentDescription =
@@ -121,6 +147,18 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
                )
        }

    @Test
    fun affordance_keyguardShowing_hasPaymentCard_visibleModel_noConstantState_resFallback() =
        testScope.runTest {
            setUpState(cardType = WalletCard.CARD_TYPE_PAYMENT)
            whenever(ICON.constantState).thenReturn(null)

            val latest by collectLastValue(underTest.lockScreenState)

            val visibleModel = latest as KeyguardQuickAffordanceConfig.LockScreenState.Visible
            assertThat(visibleModel.icon).isInstanceOf(Icon.Resource::class.java)
        }

    @Test
    fun affordance_walletFeatureNotEnabled_modelIsNone() =
        testScope.runTest {
+16 −5
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.service.quickaccesswallet.WalletCard
import android.util.Log
import com.android.systemui.animation.Expandable
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
@@ -34,6 +33,7 @@ import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import com.android.systemui.wallet.controller.QuickAccessWalletController
import com.android.systemui.wallet.util.getPaymentCards
import javax.inject.Inject
@@ -117,6 +117,7 @@ constructor(
        return when {
            !walletController.walletClient.isWalletServiceAvailable ->
                KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice

            !isWalletAvailable() ->
                KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
                    explanation =
@@ -124,6 +125,7 @@ constructor(
                            R.string.wallet_quick_affordance_unavailable_install_the_app
                        )
                )

            queryCards().isEmpty() ->
                KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
                    explanation =
@@ -131,6 +133,7 @@ constructor(
                            R.string.wallet_quick_affordance_unavailable_configure_the_app
                        )
                )

            else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default()
        }
    }
@@ -181,14 +184,22 @@ constructor(
        tileIcon: Drawable?,
    ): KeyguardQuickAffordanceConfig.LockScreenState {
        return if (isFeatureEnabled && hasCard && tileIcon != null) {
            KeyguardQuickAffordanceConfig.LockScreenState.Visible(
                icon =
            val drawable = tileIcon.constantState?.newDrawable()
            val icon =
                if (drawable != null) {
                    Icon.Loaded(
                        drawable = tileIcon,
                        drawable = drawable,
                        contentDescription =
                            ContentDescription.Resource(res = R.string.accessibility_wallet_button),
                    )
                } else {
                    Icon.Resource(
                        resId = R.drawable.ic_wallet_lockscreen,
                        contentDescription =
                            ContentDescription.Resource(res = R.string.accessibility_wallet_button),
                    )
                }
            KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = icon)
        } else {
            KeyguardQuickAffordanceConfig.LockScreenState.Hidden
        }