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);
}
}