From 16f873f18a7a8fc948850d94054a4fec3a51cb77 Mon Sep 17 00:00:00 2001 From: Charles Wang Date: Wed, 4 Jan 2023 18:55:15 +0000 Subject: [PATCH] DO NOT MERGE Adds fields to WalletCard to allow storage of valuables. Added @hide to changes from master + removed cts test and current.txt changes. Bug: b/263156366 Test: atest CtsQuickAccessWalletTestCases Change-Id: I4bdc88fe721404c495c3807d3826d4c24c190c13 --- .../service/quickaccesswallet/WalletCard.java | 139 ++++++++++++++++-- 1 file changed, 126 insertions(+), 13 deletions(-) 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. *