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

Commit 19bc1909 authored by Charles Wang's avatar Charles Wang Committed by Automerger Merge Worker
Browse files

Merge "Fixes bug where loyalty card is showing on quick access wallet screen....

Merge "Fixes bug where loyalty card is showing on quick access wallet screen. Before/after screenshots of change: http://shortn/_BYxp8yQ9uo" into udc-qpr-dev am: e82396f1

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/24620489



Change-Id: Ide67f003122f53ca347744211c50071774d01b5a
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents d9c52c95 e82396f1
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.wallet.controller.QuickAccessWalletController
import com.android.systemui.wallet.controller.QuickAccessWalletController
import com.android.systemui.wallet.util.getPaymentCards
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
@@ -60,7 +61,7 @@ constructor(
            val callback =
            val callback =
                object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
                object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
                    override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) {
                    override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) {
                        val hasCards = response?.walletCards?.isNotEmpty() == true
                        val hasCards = getPaymentCards(response.walletCards)?.isNotEmpty() == true
                        trySendWithFailureLogging(
                        trySendWithFailureLogging(
                            state(
                            state(
                                isFeatureEnabled = isWalletAvailable(),
                                isFeatureEnabled = isWalletAvailable(),
@@ -135,7 +136,7 @@ constructor(
                object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
                object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
                    override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) {
                    override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) {
                        continuation.resumeWith(
                        continuation.resumeWith(
                            Result.success(response?.walletCards ?: emptyList())
                            Result.success(getPaymentCards(response.walletCards) ?: emptyList())
                        )
                        )
                    }
                    }


+2 −1
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.graphics.drawable.Icon.TYPE_URI;
import static android.provider.Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT;
import static android.provider.Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT;


import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE;
import static com.android.systemui.wallet.util.WalletCardUtilsKt.getPaymentCards;


import android.content.Intent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
@@ -210,7 +211,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
        public void onWalletCardsRetrieved(@NonNull GetWalletCardsResponse response) {
        public void onWalletCardsRetrieved(@NonNull GetWalletCardsResponse response) {
            Log.i(TAG, "Successfully retrieved wallet cards.");
            Log.i(TAG, "Successfully retrieved wallet cards.");
            mIsWalletUpdating = false;
            mIsWalletUpdating = false;
            List<WalletCard> cards = response.getWalletCards();
            List<WalletCard> cards = getPaymentCards(response.getWalletCards());
            if (cards.isEmpty()) {
            if (cards.isEmpty()) {
                Log.d(TAG, "No wallet cards exist.");
                Log.d(TAG, "No wallet cards exist.");
                mCardViewDrawable = null;
                mCardViewDrawable = null;
+7 −16
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package com.android.systemui.wallet.ui;
package com.android.systemui.wallet.ui;


import static com.android.systemui.wallet.util.WalletCardUtilsKt.getPaymentCards;

import android.app.PendingIntent;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
@@ -47,10 +49,10 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardStateController;


import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/** Controller for the wallet card carousel screen. */
/** Controller for the wallet card carousel screen. */
public class WalletScreenController implements
public class WalletScreenController implements
@@ -126,22 +128,11 @@ public class WalletScreenController implements
            return;
            return;
        }
        }
        Log.i(TAG, "Successfully retrieved wallet cards.");
        Log.i(TAG, "Successfully retrieved wallet cards.");
        List<WalletCard> walletCards = response.getWalletCards();
        List<WalletCard> walletCards = getPaymentCards(response.getWalletCards());

        boolean allUnknown = true;
        for (WalletCard card : walletCards) {
            if (card.getCardType() != WalletCard.CARD_TYPE_UNKNOWN) {
                allUnknown = false;
                break;
            }
        }


        List<WalletCardViewInfo> paymentCardData = new ArrayList<>();
        List<WalletCardViewInfo> paymentCardData = walletCards.stream().map(
        for (WalletCard card : walletCards) {
                card -> new QAWalletCardViewInfo(mContext, card)
            if (allUnknown || card.getCardType() == WalletCard.CARD_TYPE_PAYMENT) {
        ).collect(Collectors.toList());
                paymentCardData.add(new QAWalletCardViewInfo(mContext, card));
            }
        }


        // Get on main thread for UI updates.
        // Get on main thread for UI updates.
        mHandler.post(() -> {
        mHandler.post(() -> {
+34 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 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.wallet.util

import android.service.quickaccesswallet.WalletCard

/**
 * Filters wallet cards to only those of [WalletCard.CARD_TYPE_PAYMENT], or returns all cards if
 * they are all of [WalletCard.CARD_TYPE_UNKNOWN] (maintaining pre-U behavior). Used by the wallet
 * card carousel, quick settings tile, and lock screen.
 */
fun getPaymentCards(walletCards: List<WalletCard>): List<WalletCard> {
    val atLeastOneKnownCardType = walletCards.any { it.cardType != WalletCard.CARD_TYPE_UNKNOWN }

    return if (atLeastOneKnownCardType) {
        walletCards.filter { it.cardType == WalletCard.CARD_TYPE_PAYMENT }
    } else {
        walletCards
    }
}
+52 −1
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ package com.android.systemui.keyguard.data.quickaffordance
import android.graphics.drawable.Drawable
import android.graphics.drawable.Drawable
import android.service.quickaccesswallet.GetWalletCardsResponse
import android.service.quickaccesswallet.GetWalletCardsResponse
import android.service.quickaccesswallet.QuickAccessWalletClient
import android.service.quickaccesswallet.QuickAccessWalletClient
import android.service.quickaccesswallet.WalletCard
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.R
@@ -38,6 +39,7 @@ import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Before
@@ -91,6 +93,40 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
        job.cancel()
        job.cancel()
    }
    }


    @Test
    fun affordance_keyguardShowing_hasNonPaymentCard_modelIsNone() =
        runTest(UnconfinedTestDispatcher()) {
            setUpState(cardType = WalletCard.CARD_TYPE_NON_PAYMENT)
            var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null

            val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)

            assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
            job.cancel()
        }

    @Test
    fun affordance_keyguardShowing_hasPaymentCard_visibleModel() =
        runTest(UnconfinedTestDispatcher()) {
            setUpState(cardType = WalletCard.CARD_TYPE_PAYMENT)
            var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null

            val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)

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

    @Test
    @Test
    fun affordance_walletFeatureNotEnabled_modelIsNone() = runBlockingTest {
    fun affordance_walletFeatureNotEnabled_modelIsNone() = runBlockingTest {
        setUpState(isWalletFeatureAvailable = false)
        setUpState(isWalletFeatureAvailable = false)
@@ -187,6 +223,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
        isWalletServiceAvailable: Boolean = true,
        isWalletServiceAvailable: Boolean = true,
        isWalletQuerySuccessful: Boolean = true,
        isWalletQuerySuccessful: Boolean = true,
        hasSelectedCard: Boolean = true,
        hasSelectedCard: Boolean = true,
        cardType: Int = WalletCard.CARD_TYPE_UNKNOWN
    ) {
    ) {
        val walletClient: QuickAccessWalletClient = mock()
        val walletClient: QuickAccessWalletClient = mock()
        whenever(walletClient.tileIcon).thenReturn(ICON)
        whenever(walletClient.tileIcon).thenReturn(ICON)
@@ -202,7 +239,19 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
                if (isWalletQuerySuccessful) {
                if (isWalletQuerySuccessful) {
                    onWalletCardsRetrieved(
                    onWalletCardsRetrieved(
                        if (hasSelectedCard) {
                        if (hasSelectedCard) {
                            GetWalletCardsResponse(listOf(mock()), 0)
                            GetWalletCardsResponse(
                                listOf(
                                    WalletCard.Builder(
                                            /*cardId= */ CARD_ID,
                                            /*cardType= */ cardType,
                                            /*cardImage= */ mock(),
                                            /*contentDescription=  */ CARD_DESCRIPTION,
                                            /*pendingIntent= */ mock()
                                        )
                                        .build()
                                ),
                                0
                            )
                        } else {
                        } else {
                            GetWalletCardsResponse(emptyList(), 0)
                            GetWalletCardsResponse(emptyList(), 0)
                        }
                        }
@@ -216,5 +265,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {


    companion object {
    companion object {
        private val ICON: Drawable = mock()
        private val ICON: Drawable = mock()
        private const val CARD_ID: String = "Id"
        private const val CARD_DESCRIPTION: String = "Description"
    }
    }
}
}
Loading