Merge "Support non-active tokens in QuickAccessWallet." into sc-dev
diff --git a/packages/SystemUI/res/drawable/circle_wallet_secondary_56dp.xml b/packages/SystemUI/res/drawable/circle_wallet_secondary_56dp.xml
deleted file mode 100644
index 1634e2d..0000000
--- a/packages/SystemUI/res/drawable/circle_wallet_secondary_56dp.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <size
-        android:height="56dp"
-        android:width="56dp" />
-    <solid android:color="@android:color/transparent" />
-    <stroke android:width="2dp" android:color="@color/GM2_grey_300" />
-</shape>
diff --git a/packages/SystemUI/res/layout/wallet_fullscreen.xml b/packages/SystemUI/res/layout/wallet_fullscreen.xml
index b47c2f2..bbb180f 100644
--- a/packages/SystemUI/res/layout/wallet_fullscreen.xml
+++ b/packages/SystemUI/res/layout/wallet_fullscreen.xml
@@ -19,6 +19,13 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:clipChildren="false">
+    <Toolbar
+      android:id="@+id/action_bar"
+      style="?android:attr/actionBarStyle"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:background="@android:color/transparent"
+      android:navigationContentDescription="@null" />
     <LinearLayout
         android:id="@+id/card_carousel_container"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/drawable/circle_wallet_primary_56dp.xml b/packages/SystemUI/res/menu/wallet_activity_options_menu.xml
similarity index 63%
rename from packages/SystemUI/res/drawable/circle_wallet_primary_56dp.xml
rename to packages/SystemUI/res/menu/wallet_activity_options_menu.xml
index 3d4c233..278924a 100644
--- a/packages/SystemUI/res/drawable/circle_wallet_primary_56dp.xml
+++ b/packages/SystemUI/res/menu/wallet_activity_options_menu.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+     Copyright (C) 2021 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.
@@ -13,11 +14,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <size
-        android:height="56dp"
-        android:width="56dp" />
-    <solid android:color="@android:color/transparent" />
-    <stroke android:width="2dp" android:color="#AECBFA" />
-</shape>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+  <item
+    android:id="@+id/wallet_lockscreen_settings"
+    android:enabled="true"
+    android:showAsAction="never"
+    android:title="@string/wallet_lockscreen_settings_label"
+    android:visible="true" />
+</menu>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index edd8486..073913d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1483,6 +1483,7 @@
 
     <!-- Wallet activity screen specs -->
     <dimen name="wallet_icon_size">36sp</dimen>
+    <dimen name="wallet_view_header_icon_size">56dp</dimen>
     <dimen name="card_margin">16dp</dimen>
     <dimen name="card_carousel_dot_offset">24dp</dimen>
     <dimen name="card_carousel_dot_unselected_radius">2dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d9cc24f..3480d10 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1656,14 +1656,14 @@
     <string name="wallet_app_button_label">Show all</string>
     <!-- Label of the button underneath the card carousel prompting user unlock device. [CHAR LIMIT=NONE] -->
     <string name="wallet_action_button_label_unlock">Unlock to pay</string>
-    <!-- Secondary label of the quick access wallet tile if active. [CHAR LIMIT=32] -->
-    <string name="wallet_secondary_label_active">Ready</string>
     <!-- Secondary label of the quick access wallet tile if no card. [CHAR LIMIT=NONE] -->
-    <string name="wallet_secondary_label_no_card">Set up payment</string>
+    <string name="wallet_secondary_label_no_card">Not set up</string>
     <!-- Secondary label of the quick access wallet tile if device locked. [CHAR LIMIT=NONE] -->
     <string name="wallet_secondary_label_device_locked">Unlock to use</string>
     <!-- Message shown when an unknown failure occurred when fetching cards. [CHAR LIMIT=NONE] -->
     <string name="wallet_error_generic">There was a problem getting your cards, please try again later</string>
+    <!-- Overflow menu item label to open the lockscreen settings in wallet activity. [CHAR LIMIT=NONE] -->
+    <string name="wallet_lockscreen_settings_label">Lock screen settings</string>
 
     <!-- Name of the work status bar icon. -->
     <string name="status_bar_work">Work profile</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index be40423..d1b74cd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -75,7 +75,7 @@
     private final FeatureFlags mFeatureFlags;
 
     @VisibleForTesting Drawable mCardViewDrawable;
-    private boolean mHasCard;
+    private WalletCard mSelectedCard;
 
     @Inject
     public QuickAccessWalletTile(
@@ -125,7 +125,7 @@
                 view == null ? null : ActivityLaunchAnimator.Controller.fromView(view);
 
         mUiHandler.post(() -> {
-            if (mHasCard) {
+            if (mSelectedCard != null) {
                 Intent intent = new Intent(mContext, WalletActivity.class)
                         .setAction(Intent.ACTION_VIEW)
                         .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -157,15 +157,14 @@
         state.icon = ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
         boolean isDeviceLocked = !mKeyguardStateController.isUnlocked();
         if (mQuickAccessWalletClient.isWalletServiceAvailable()) {
-            if (mHasCard) {
+            if (mSelectedCard != null) {
                 if (isDeviceLocked) {
                     state.state = Tile.STATE_INACTIVE;
                     state.secondaryLabel =
                             mContext.getString(R.string.wallet_secondary_label_device_locked);
                 } else {
                     state.state = Tile.STATE_ACTIVE;
-                    state.secondaryLabel =
-                            mContext.getString(R.string.wallet_secondary_label_active);
+                    state.secondaryLabel = mSelectedCard.getContentDescription();
                 }
             } else {
                 state.state = Tile.STATE_INACTIVE;
@@ -208,7 +207,7 @@
                 mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height);
         int iconSizePx = mContext.getResources().getDimensionPixelSize(R.dimen.wallet_icon_size);
         GetWalletCardsRequest request =
-                new GetWalletCardsRequest(cardWidth, cardHeight, iconSizePx, /* maxCards= */ 2);
+                new GetWalletCardsRequest(cardWidth, cardHeight, iconSizePx, /* maxCards= */ 1);
         mQuickAccessWalletClient.getWalletCards(mExecutor, request, mCardRetriever);
     }
 
@@ -222,7 +221,7 @@
             if (cards.isEmpty()) {
                 Log.d(TAG, "No wallet cards exist.");
                 mCardViewDrawable = null;
-                mHasCard = false;
+                mSelectedCard = null;
                 refreshState();
                 return;
             }
@@ -231,8 +230,8 @@
                 Log.d(TAG, "Selected card index out of bounds.");
                 return;
             }
-            mCardViewDrawable = cards.get(selectedIndex).getCardImage().loadDrawable(mContext);
-            mHasCard = true;
+            mSelectedCard = cards.get(selectedIndex);
+            mCardViewDrawable = mSelectedCard.getCardImage().loadDrawable(mContext);
             refreshState();
         }
 
@@ -240,7 +239,7 @@
         public void onWalletCardRetrievalError(@NonNull GetWalletCardsError error) {
             Log.w(TAG, "Error retrieve wallet cards");
             mCardViewDrawable = null;
-            mHasCard = false;
+            mSelectedCard = null;
             refreshState();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
index f884687..92e68f3 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
@@ -16,13 +16,14 @@
 
 package com.android.systemui.wallet.ui;
 
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.service.quickaccesswallet.QuickAccessWalletClient;
+import android.view.Menu;
 import android.view.MenuItem;
 import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Toolbar;
 
 import androidx.annotation.NonNull;
 
@@ -30,6 +31,7 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -50,6 +52,7 @@
     private final ActivityStarter mActivityStarter;
     private final Executor mExecutor;
     private final Handler mHandler;
+    private final FalsingManager mFalsingManager;
     private final UserTracker mUserTracker;
     private WalletScreenController mWalletScreenController;
 
@@ -61,6 +64,7 @@
             ActivityStarter activityStarter,
             @Background Executor executor,
             @Main Handler handler,
+            FalsingManager falsingManager,
             UserTracker userTracker) {
         mQuickAccessWalletClient = quickAccessWalletClient;
         mKeyguardStateController = keyguardStateController;
@@ -68,19 +72,23 @@
         mActivityStarter = activityStarter;
         mExecutor = executor;
         mHandler = handler;
+        mFalsingManager = falsingManager;
         mUserTracker = userTracker;
     }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
         super.onCreate(savedInstanceState);
 
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
         setContentView(R.layout.quick_access_wallet);
 
-        getWindow().getDecorView().setBackgroundColor(getColor(R.color.wallet_white));
+        Toolbar toolbar = findViewById(R.id.action_bar);
+        if (toolbar != null) {
+            setActionBar(toolbar);
+        }
         setTitle("");
-        getActionBar().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
         getActionBar().setDisplayHomeAsUpEnabled(true);
         getActionBar().setHomeAsUpIndicator(R.drawable.ic_close);
         getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close);
@@ -93,15 +101,28 @@
                 mExecutor,
                 mHandler,
                 mUserTracker,
+                mFalsingManager,
                 mKeyguardStateController);
 
         walletView.getAppButton().setOnClickListener(
-                v -> mActivityStarter.startActivity(
-                        mQuickAccessWalletClient.createWalletIntent(), true));
+                v -> {
+                    if (!mKeyguardStateController.isUnlocked()
+                            && mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                        return;
+                    }
+                    mActivityStarter.startActivity(
+                            mQuickAccessWalletClient.createWalletIntent(), true);
+                    finish();
+                });
         // Click the action button to re-render the screen when the device is unlocked.
         if (!mKeyguardStateController.isUnlocked()) {
             walletView.getActionButton().setOnClickListener(
-                    v -> mKeyguardDismissUtil.executeWhenUnlocked(() -> false, false));
+                    v -> {
+                        if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                            return;
+                        }
+                        mKeyguardDismissUtil.executeWhenUnlocked(() -> false, false);
+                    });
         }
     }
 
@@ -118,11 +139,20 @@
     }
 
     @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.wallet_activity_options_menu, menu);
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
     public boolean onOptionsItemSelected(@NonNull MenuItem item) {
         int itemId = item.getItemId();
         if (itemId == android.R.id.home) {
             finish();
             return true;
+        } else if (itemId == R.id.wallet_lockscreen_settings) {
+            // TODO(b/186496392): Navigate to Lock Screen Settings page when the item is clicked.
+            return true;
         }
         return super.onOptionsItemSelected(item);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardCarousel.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardCarousel.java
index 21e5549..4200241 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardCarousel.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardCarousel.java
@@ -205,8 +205,8 @@
     boolean setData(List<WalletCardViewInfo> data, int selectedIndex) {
         boolean wasEmpty = mWalletCardCarouselAdapter.getItemCount() == 0;
         mWalletCardCarouselAdapter.setData(data);
+        scrollToPosition(selectedIndex);
         if (wasEmpty) {
-            scrollToPosition(selectedIndex);
             mNumCardsToAnimate = numCardsOnScreen(data.size(), selectedIndex);
             mCardAnimationStartPosition = Math.max(selectedIndex - 1, 0);
         }
@@ -427,15 +427,6 @@
                             mSelectionListener.onCardClicked(cardViewInfo);
                         }
                     });
-            if (mNumCardsToAnimate > 0 && (position - mCardAnimationStartPosition < 2)) {
-                mNumCardsToAnimate--;
-                int startDelay = (position - mCardAnimationStartPosition) * CARD_ANIM_ALPHA_DELAY
-                        + mExtraAnimationDelay;
-                viewHolder.itemView.setAlpha(0f);
-                viewHolder.itemView.animate().alpha(1f)
-                        .setStartDelay(Math.max(0, startDelay))
-                        .setDuration(CARD_ANIM_ALPHA_DURATION).start();
-            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardViewInfo.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardViewInfo.java
index 669d666..3d37320 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardViewInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardViewInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.wallet.ui;
 
+import android.app.PendingIntent;
 import android.graphics.drawable.Drawable;
 
 import androidx.annotation.NonNull;
@@ -47,4 +48,10 @@
      */
     @NonNull
     CharSequence getLabel();
+
+    /**
+     * Pending intent upon the card is clicked.
+     */
+    @NonNull
+    PendingIntent getPendingIntent();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
index d1a2c8a..ec62981 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.wallet.ui;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -41,6 +42,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -57,7 +59,6 @@
         KeyguardStateController.Callback {
 
     private static final String TAG = "WalletScreenCtrl";
-    private static final String PREFS_HAS_CARDS = "has_cards";
     private static final String PREFS_WALLET_VIEW_HEIGHT = "wallet_view_height";
     private static final int MAX_CARDS = 10;
     private static final long SELECTION_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(30);
@@ -72,6 +73,7 @@
     private final SharedPreferences mPrefs;
     private final WalletView mWalletView;
     private final WalletCardCarousel mCardCarousel;
+    private final FalsingManager mFalsingManager;
 
     @VisibleForTesting String mSelectedCardId;
     @VisibleForTesting boolean mIsDismissed;
@@ -85,12 +87,14 @@
             Executor executor,
             Handler handler,
             UserTracker userTracker,
+            FalsingManager falsingManager,
             KeyguardStateController keyguardStateController) {
         mContext = context;
         mWalletClient = walletClient;
         mActivityStarter = activityStarter;
         mExecutor = executor;
         mHandler = handler;
+        mFalsingManager = falsingManager;
         mKeyguardStateController = keyguardStateController;
         mPrefs = userTracker.getUserContext().getSharedPreferences(TAG, Context.MODE_PRIVATE);
         mWalletView = walletView;
@@ -102,12 +106,6 @@
         if (mCardCarousel != null) {
             mCardCarousel.setSelectionListener(this);
         }
-
-        if (!mPrefs.getBoolean(PREFS_HAS_CARDS, false)) {
-            // The empty state view is shown preemptively when cards were not returned last time
-            // to decrease perceived latency.
-            showEmptyStateView();
-        }
     }
 
     /**
@@ -136,8 +134,6 @@
                 mWalletView.showCardCarousel(
                         data, response.getSelectedIndex(), !mKeyguardStateController.isUnlocked());
             }
-            // The empty state view will not be shown preemptively next time if cards were returned
-            mPrefs.edit().putBoolean(PREFS_HAS_CARDS, !data.isEmpty()).apply();
             removeMinHeightAndRecordHeightOnLayout();
         });
     }
@@ -167,7 +163,6 @@
         }
         switch (event.getEventType()) {
             case WalletServiceEvent.TYPE_NFC_PAYMENT_STARTED:
-                onDismissed();
                 break;
             case WalletServiceEvent.TYPE_WALLET_CARDS_UPDATED:
                 queryWalletCards();
@@ -207,14 +202,17 @@
 
     @Override
     public void onCardClicked(@NonNull WalletCardViewInfo cardInfo) {
+        if (!mKeyguardStateController.isUnlocked()
+                && mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+            return;
+        }
         if (!(cardInfo instanceof QAWalletCardViewInfo)
                 || ((QAWalletCardViewInfo) cardInfo).mWalletCard == null
                 || ((QAWalletCardViewInfo) cardInfo).mWalletCard.getPendingIntent() == null) {
             return;
         }
         mActivityStarter.startActivity(
-                ((QAWalletCardViewInfo) cardInfo).mWalletCard.getPendingIntent().getIntent(),
-                true);
+                ((QAWalletCardViewInfo) cardInfo).mWalletCard.getPendingIntent().getIntent(), true);
     }
 
     @Override
@@ -235,7 +233,8 @@
 
         mWalletView.show();
         mWalletView.hideErrorMessage();
-        int iconSizePx = mContext.getResources().getDimensionPixelSize(R.dimen.wallet_icon_size);
+        int iconSizePx =
+                mContext.getResources().getDimensionPixelSize(R.dimen.wallet_view_header_icon_size);
         GetWalletCardsRequest request =
                 new GetWalletCardsRequest(cardWidthPx, cardHeightPx, iconSizePx, MAX_CARDS);
         mWalletClient.getWalletCards(mExecutor, request, this);
@@ -248,6 +247,7 @@
         mIsDismissed = true;
         mSelectedCardId = null;
         mHandler.removeCallbacks(mSelectionRunnable);
+        mFalsingManager.cleanup();
         mWalletClient.notifyWalletDismissed();
         mWalletClient.removeWalletServiceEventListener(this);
         mWalletView.animateDismissal();
@@ -342,5 +342,10 @@
         public CharSequence getLabel() {
             return mWalletCard.getCardLabel();
         }
+
+        @Override
+        public PendingIntent getPendingIntent() {
+            return mWalletCard.getPendingIntent();
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
index a3c2699..44074f70 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
@@ -22,13 +22,12 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.annotation.Nullable;
+import android.app.PendingIntent;
 import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.ViewGroup;
 import android.view.animation.AnimationUtils;
@@ -46,10 +45,10 @@
 /** Layout for the wallet screen. */
 public class WalletView extends FrameLayout implements WalletCardCarousel.OnCardScrollListener {
 
+    private static final String TAG = "WalletView";
     private static final int CAROUSEL_IN_ANIMATION_DURATION = 300;
     private static final int CAROUSEL_OUT_ANIMATION_DURATION = 200;
     private static final int CARD_LABEL_ANIM_DELAY = 133;
-    private static final int CONTACTLESS_ICON_SIZE = 90;
 
     private final WalletCardCarousel mCardCarousel;
     private final ImageView mIcon;
@@ -65,6 +64,8 @@
     private final TextView mErrorView;
     private final ViewGroup mEmptyStateView;
     private CharSequence mCenterCardText;
+    private Drawable mCenterCardIcon;
+    private boolean mIsDeviceLocked = false;
 
     public WalletView(Context context) {
         this(context, null);
@@ -104,16 +105,21 @@
     @Override
     public void onCardScroll(WalletCardViewInfo centerCard, WalletCardViewInfo nextCard,
             float percentDistanceFromCenter) {
-        CharSequence centerCardText = centerCard.getLabel();
+        CharSequence centerCardText = getLabelText(centerCard);
+        Drawable centerCardIcon = centerCard.getIcon();
         if (!TextUtils.equals(mCenterCardText, centerCardText)) {
             mCenterCardText = centerCardText;
+            mCenterCardIcon = centerCardIcon;
             mCardLabel.setText(centerCardText);
+            mIcon.setImageDrawable(centerCardIcon);
         }
-        if (TextUtils.equals(centerCardText, nextCard.getLabel())) {
+        renderActionButton(centerCard, mIsDeviceLocked);
+        if (TextUtils.equals(centerCardText, getLabelText(nextCard))) {
             mCardLabel.setAlpha(1f);
         } else {
             mCardLabel.setAlpha(percentDistanceFromCenter);
             mIcon.setAlpha(percentDistanceFromCenter);
+            mActionButton.setAlpha(percentDistanceFromCenter);
         }
     }
 
@@ -128,10 +134,11 @@
      */
     void showCardCarousel(
             List<WalletCardViewInfo> data, int selectedIndex, boolean isDeviceLocked) {
+        mIsDeviceLocked = isDeviceLocked;
         boolean shouldAnimate = mCardCarousel.setData(data, selectedIndex);
         mCardCarouselContainer.setVisibility(VISIBLE);
         mErrorView.setVisibility(GONE);
-        renderHeaderIconAndActionButton(data.get(0), isDeviceLocked);
+        renderHeaderIconAndActionButton(data.get(selectedIndex), isDeviceLocked);
         if (shouldAnimate) {
             // If the empty state is visible, animate it away and delay the card carousel animation
             int emptyStateAnimDelay = 0;
@@ -239,39 +246,45 @@
         return mCardCarouselContainer;
     }
 
+    @VisibleForTesting
+    TextView getCardLabel() {
+        return mCardLabel;
+    }
+
     private void renderHeaderIconAndActionButton(WalletCardViewInfo walletCard, boolean isLocked) {
-        Drawable icon = resizeDrawable(getResources(), walletCard.getIcon());
-        renderHeaderIcon(icon, isLocked);
-        if (isLocked) {
+        mIcon.setImageDrawable(walletCard.getIcon());
+        mIcon.setVisibility(VISIBLE);
+        renderActionButton(walletCard, isLocked);
+    }
+
+    private void renderActionButton(WalletCardViewInfo walletCard, boolean isDeviceLocked) {
+        CharSequence actionButtonText = getActionButtonText(walletCard);
+        if (isDeviceLocked) {
             mActionButton.setVisibility(VISIBLE);
             mActionButton.setText(R.string.wallet_action_button_label_unlock);
+        } else if (actionButtonText != null) {
+            mActionButton.setText(actionButtonText);
+            mActionButton.setVisibility(VISIBLE);
+            mActionButton.setOnClickListener(v -> {
+                try {
+                    walletCard.getPendingIntent().send();
+                } catch (PendingIntent.CanceledException e) {
+                    Log.w(TAG, "Error sending pending intent for wallet card");
+                }
+            });
         } else {
             mActionButton.setVisibility(GONE);
         }
     }
 
-    private void renderHeaderIcon(@Nullable Drawable icon, boolean isLocked) {
-        if (icon == null) {
-            mIcon.setVisibility(INVISIBLE);
-            return;
-        }
-        icon.setTint(mContext.getColor(isLocked ? R.color.GM2_grey_800 : R.color.GM2_blue_600));
-        mIcon.setImageDrawable(icon);
-        mIcon.setVisibility(VISIBLE);
-        mIcon.setBackground(
-                mContext.getDrawable(
-                        isLocked
-                                ? R.drawable.circle_wallet_secondary_56dp
-                                : R.drawable.circle_wallet_primary_56dp));
+    private static CharSequence getLabelText(WalletCardViewInfo card) {
+        String[] rawLabel = card.getLabel().toString().split("\\n");
+        return rawLabel.length == 2 ? rawLabel[0] : card.getLabel();
     }
 
     @Nullable
-    private static Drawable resizeDrawable(Resources resources, @Nullable Drawable drawable) {
-        if (drawable == null) {
-            return null;
-        }
-        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
-        return new BitmapDrawable(resources, Bitmap.createScaledBitmap(
-                bitmap, CONTACTLESS_ICON_SIZE, CONTACTLESS_ICON_SIZE, true));
+    private static CharSequence getActionButtonText(WalletCardViewInfo card) {
+        String[] rawLabel = card.getLabel().toString().split("\\n");
+        return rawLabel.length == 2 ? rawLabel[1] : null;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 5cdad05..9d463d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -284,7 +284,7 @@
 
         assertEquals(Tile.STATE_ACTIVE, state.state);
         assertEquals(
-                mContext.getString(R.string.wallet_secondary_label_active),
+                "•••• 1234",
                 state.secondaryLabel);
         assertNotNull(state.stateDescription);
         assertNotNull(state.sideViewDrawable);
@@ -332,7 +332,7 @@
         assertEquals(
                 mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height),
                 request.getCardHeightPx());
-        assertEquals(2, request.getMaxCards());
+        assertEquals(1, request.getMaxCards());
         assertThat(mCallbackCaptor.getValue()).isInstanceOf(
                 QuickAccessWalletClient.OnWalletCardsRetrievedCallback.class);
     }
@@ -423,6 +423,6 @@
     private WalletCard createWalletCard(Context context) {
         PendingIntent pendingIntent =
                 PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
-        return new WalletCard.Builder(CARD_ID, CARD_IMAGE, "description", pendingIntent).build();
+        return new WalletCard.Builder(CARD_ID, CARD_IMAGE, "•••• 1234", pendingIntent).build();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
index 6f6ef72..ac5da17 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
@@ -20,12 +20,13 @@
 import static android.view.View.VISIBLE;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.app.PendingIntent;
@@ -50,6 +51,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -72,7 +74,8 @@
 
     private static final int MAX_CARDS = 10;
     private static final int CARD_CAROUSEL_WIDTH = 10;
-    private static final String CARD_ID = "card_id";
+    private static final String CARD_ID_1 = "card_id_1";
+    private static final String CARD_ID_2 = "card_id_2";
     private static final CharSequence SHORTCUT_SHORT_LABEL = "View all";
     private static final CharSequence SHORTCUT_LONG_LABEL = "Add a payment method";
     private static final CharSequence SERVICE_LABEL = "Wallet app";
@@ -89,6 +92,8 @@
     @Mock
     UserTracker mUserTracker;
     @Mock
+    FalsingManager mFalsingManager;
+    @Mock
     KeyguardStateController mKeyguardStateController;
     @Captor
     ArgumentCaptor<Intent> mIntentCaptor;
@@ -122,11 +127,12 @@
                 MoreExecutors.directExecutor(),
                 new Handler(mTestableLooper.getLooper()),
                 mUserTracker,
+                mFalsingManager,
                 mKeyguardStateController);
     }
 
     @Test
-    public void queryCards_hasCards_showCarousel() {
+    public void queryCards_hasCards_showCarousel_activeCard() {
         GetWalletCardsResponse response =
                 new GetWalletCardsResponse(
                         Collections.singletonList(createWalletCard(mContext)), 0);
@@ -145,6 +151,33 @@
         mTestableLooper.processAllMessages();
 
         assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
+        assertEquals("Hold to reader", mWalletView.getCardLabel().getText().toString());
+        assertEquals(GONE, mWalletView.getErrorView().getVisibility());
+    }
+
+    @Test
+    public void queryCards_hasCards_showCarousel_pendingActivationCard_parseLabel() {
+        GetWalletCardsResponse response =
+                new GetWalletCardsResponse(
+                        Collections.singletonList(createNonActiveWalletCard(mContext)), 0);
+
+        mController.queryWalletCards();
+        mTestableLooper.processAllMessages();
+
+        verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
+
+        QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
+                mCallbackCaptor.getValue();
+
+        assertEquals(mController, callback);
+
+        callback.onWalletCardsRetrieved(response);
+        mTestableLooper.processAllMessages();
+
+        assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
+        assertEquals("Not set up", mWalletView.getCardLabel().getText().toString());
+        assertEquals("Verify now", mWalletView.getActionButton().getText().toString());
+        assertEquals(VISIBLE, mWalletView.getActionButton().getVisibility());
         assertEquals(GONE, mWalletView.getErrorView().getVisibility());
     }
 
@@ -185,7 +218,7 @@
     }
 
     @Test
-    public void onWalletServiceEvent_nfcPaymentStart_dismiss() {
+    public void onWalletServiceEvent_nfcPaymentStart_doNothing() {
         WalletServiceEvent event =
                 new WalletServiceEvent(WalletServiceEvent.TYPE_NFC_PAYMENT_STARTED);
 
@@ -193,8 +226,8 @@
         mTestableLooper.processAllMessages();
 
         assertNull(mController.mSelectedCardId);
-        assertTrue(mController.mIsDismissed);
-        verify(mWalletClient).notifyWalletDismissed();
+        assertFalse(mController.mIsDismissed);
+        verifyZeroInteractions(mWalletClient);
     }
 
     @Test
@@ -228,14 +261,14 @@
 
     @Test
     public void onCardSelected() {
-        mController.onCardSelected(createCardViewInfo());
+        mController.onCardSelected(createCardViewInfo(createWalletCard(mContext)));
 
-        assertEquals(CARD_ID, mController.mSelectedCardId);
+        assertEquals(CARD_ID_1, mController.mSelectedCardId);
     }
 
     @Test
     public void onCardClicked_startIntent() {
-        WalletCardViewInfo walletCardViewInfo = createCardViewInfo();
+        WalletCardViewInfo walletCardViewInfo = createCardViewInfo(createWalletCard(mContext));
 
         mController.onCardClicked(walletCardViewInfo);
 
@@ -278,18 +311,30 @@
         assertEquals(GONE, mWalletView.getVisibility());
     }
 
+    private WalletCard createNonActiveWalletCard(Context context) {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+        return new WalletCard.Builder(CARD_ID_2, createIcon(), "•••• 5678", pendingIntent)
+                .setCardIcon(createIcon())
+                .setCardLabel("Not set up\nVerify now")
+                .build();
+    }
+
     private WalletCard createWalletCard(Context context) {
         PendingIntent pendingIntent =
                 PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
-        return new WalletCard.Builder(CARD_ID, createIcon(), "description", pendingIntent).build();
+        return new WalletCard.Builder(CARD_ID_1, createIcon(), "•••• 1234", pendingIntent)
+                .setCardIcon(createIcon())
+                .setCardLabel("Hold to reader")
+                .build();
     }
 
     private static Icon createIcon() {
         return Icon.createWithBitmap(Bitmap.createBitmap(70, 44, Bitmap.Config.ARGB_8888));
     }
 
-    private WalletCardViewInfo createCardViewInfo() {
+    private WalletCardViewInfo createCardViewInfo(WalletCard walletCard) {
         return new WalletScreenController.QAWalletCardViewInfo(
-                mContext, createWalletCard(mContext));
+                mContext, walletCard);
     }
 }