diff --git a/core/java/android/service/quickaccesswallet/WalletCard.java b/core/java/android/service/quickaccesswallet/WalletCard.java
index b09d2e9e7f139..7aacb9b4d11a1 100644
--- a/core/java/android/service/quickaccesswallet/WalletCard.java
+++ b/core/java/android/service/quickaccesswallet/WalletCard.java
@@ -16,6 +16,7 @@
package android.service.quickaccesswallet;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -24,28 +25,73 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
/**
* A {@link WalletCard} can represent anything that a user might carry in their wallet -- a credit
* card, library card, transit pass, etc. Cards are identified by a String identifier and contain a
- * card image, card image content description, and a {@link PendingIntent} to be used if the user
- * clicks on the card. Cards may be displayed with an icon and label, though these are optional.
+ * card type, card image, card image content description, and a {@link PendingIntent} to be used if
+ * the user clicks on the card. Cards may be displayed with an icon and label, though these are
+ * optional. Valuable cards will also have a second image that will be displayed when the card is
+ * tapped.
*/
+
public final class WalletCard implements Parcelable {
+ /**
+ * Unknown cards refer to cards whose types are unspecified.
+ * @hide
+ */
+ public static final int CARD_TYPE_UNKNOWN = 0;
+
+ /**
+ * Payment cards refer to credit cards, debit cards or any other cards in the wallet used to
+ * make cash-equivalent payments.
+ * @hide
+ */
+ public static final int CARD_TYPE_PAYMENT = 1;
+
+ /**
+ * Valuable cards refer to any cards that are not used for cash-equivalent payment.
+ * This includes event tickets, flights, offers, loyalty cards, gift cards and transit tickets.
+ * @hide
+ */
+ public static final int CARD_TYPE_VALUABLE = 2;
+
private final String mCardId;
+ private final int mCardType;
private final Icon mCardImage;
private final CharSequence mContentDescription;
private final PendingIntent mPendingIntent;
private final Icon mCardIcon;
private final CharSequence mCardLabel;
+ private final Icon mValuableCardSecondaryImage;
private WalletCard(Builder builder) {
this.mCardId = builder.mCardId;
+ this.mCardType = builder.mCardType;
this.mCardImage = builder.mCardImage;
this.mContentDescription = builder.mContentDescription;
this.mPendingIntent = builder.mPendingIntent;
this.mCardIcon = builder.mCardIcon;
this.mCardLabel = builder.mCardLabel;
+ this.mValuableCardSecondaryImage = builder.mValuableCardSecondaryImage;
+ }
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"CARD_TYPE_"}, value = {
+ CARD_TYPE_UNKNOWN,
+ CARD_TYPE_PAYMENT,
+ CARD_TYPE_VALUABLE
+ })
+ public @interface CardType {
}
@Override
@@ -56,29 +102,44 @@ public final class WalletCard implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mCardId);
+ dest.writeInt(mCardType);
mCardImage.writeToParcel(dest, flags);
TextUtils.writeToParcel(mContentDescription, dest, flags);
PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, dest);
- if (mCardIcon == null) {
+ writeIconIfNonNull(mCardIcon, dest, flags);
+ TextUtils.writeToParcel(mCardLabel, dest, flags);
+ writeIconIfNonNull(mValuableCardSecondaryImage, dest, flags);
+
+ }
+
+ /** Utility function called by writeToParcel
+ */
+ private void writeIconIfNonNull(Icon icon, Parcel dest, int flags) {
+ if (icon == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
- mCardIcon.writeToParcel(dest, flags);
+ icon.writeToParcel(dest, flags);
}
- TextUtils.writeToParcel(mCardLabel, dest, flags);
}
private static WalletCard readFromParcel(Parcel source) {
String cardId = source.readString();
+ int cardType = source.readInt();
Icon cardImage = Icon.CREATOR.createFromParcel(source);
CharSequence contentDesc = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
PendingIntent pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(source);
Icon cardIcon = source.readByte() == 0 ? null : Icon.CREATOR.createFromParcel(source);
CharSequence cardLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- return new Builder(cardId, cardImage, contentDesc, pendingIntent)
+ Icon valuableCardSecondaryImage = source.readByte() == 0 ? null :
+ Icon.CREATOR.createFromParcel(source);
+ Builder builder = new Builder(cardId, cardType, cardImage, contentDesc, pendingIntent)
.setCardIcon(cardIcon)
- .setCardLabel(cardLabel)
- .build();
+ .setCardLabel(cardLabel);
+
+ return cardType == CARD_TYPE_VALUABLE
+ ? builder.setValuableCardSecondaryImage(valuableCardSecondaryImage).build() :
+ builder.build();
}
@NonNull
@@ -103,6 +164,16 @@ public final class WalletCard implements Parcelable {
return mCardId;
}
+ /**
+ * Returns the card type.
+ * @hide
+ */
+ @NonNull
+ @CardType
+ public int getCardType() {
+ return mCardType;
+ }
+
/**
* The visual representation of the card. If the card image Icon is a bitmap, it should have a
* width of {@link GetWalletCardsRequest#getCardWidthPx()} and a height of {@link
@@ -158,23 +229,37 @@ public final class WalletCard implements Parcelable {
}
/**
- * Builder for {@link WalletCard} objects. You must to provide cardId, cardImage,
+ * Visual representation of the card when it is tapped. Includes a barcode to scan the card in
+ * addition to the information in the primary image.
+ * @hide
+ */
+ @Nullable
+ public Icon getValuableCardSecondaryImage() {
+ return mValuableCardSecondaryImage;
+ }
+
+ /**
+ * Builder for {@link WalletCard} objects. You must provide cardId, cardImage,
* contentDescription, and pendingIntent. If the card is opaque and should be shown with
* elevation, set hasShadow to true. cardIcon and cardLabel are optional.
*/
public static final class Builder {
private String mCardId;
+ private int mCardType;
private Icon mCardImage;
private CharSequence mContentDescription;
private PendingIntent mPendingIntent;
private Icon mCardIcon;
private CharSequence mCardLabel;
+ private Icon mValuableCardSecondaryImage;
/**
* @param cardId The card id must be non-null and unique within the list of
* cards returned. Note:
* this card ID should not contain PII (Personally
* Identifiable Information, such as username or email address).
+ * @param cardType Integer representing the card type. The card type must be
+ * non-null. If not provided, it defaults to unknown.
* @param cardImage The visual representation of the card. If the card image Icon
* is a bitmap, it should have a width of {@link
* GetWalletCardsRequest#getCardWidthPx()} and a height of {@link
@@ -193,15 +278,30 @@ public final class WalletCard implements Parcelable {
* request device unlock before sending the pending intent. It is
* recommended that the pending intent be immutable (use {@link
* PendingIntent#FLAG_IMMUTABLE}).
+ * @hide
+ */
+ public Builder(@NonNull String cardId,
+ @NonNull @CardType int cardType,
+ @NonNull Icon cardImage,
+ @NonNull CharSequence contentDescription,
+ @NonNull PendingIntent pendingIntent
+ ) {
+ mCardId = cardId;
+ mCardType = cardType;
+ mCardImage = cardImage;
+ mContentDescription = contentDescription;
+ mPendingIntent = pendingIntent;
+ }
+
+ /**
+ * Called when a card type is not provided.
*/
public Builder(@NonNull String cardId,
@NonNull Icon cardImage,
@NonNull CharSequence contentDescription,
@NonNull PendingIntent pendingIntent) {
- mCardId = cardId;
- mCardImage = cardImage;
- mContentDescription = contentDescription;
- mPendingIntent = pendingIntent;
+ this(cardId, WalletCard.CARD_TYPE_UNKNOWN, cardImage, contentDescription,
+ pendingIntent);
}
/**
@@ -235,6 +335,19 @@ public final class WalletCard implements Parcelable {
return this;
}
+ /**
+ * Visual representation of the card when it is tapped. Includes a barcode to scan the card
+ * in addition to the information in the primary image.
+ * @hide
+ */
+ @NonNull
+ public Builder setValuableCardSecondaryImage(@Nullable Icon valuableCardSecondaryImage) {
+ Preconditions.checkState(mCardType == CARD_TYPE_VALUABLE,
+ "This field can only be set on valuable cards");
+ mValuableCardSecondaryImage = valuableCardSecondaryImage;
+ return this;
+ }
+
/**
* Builds a new {@link WalletCard} instance.
*