Home | History | Annotate | Download | only in stream
      1 /*
      2  * Copyright (c) 2016, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.car.stream;
     17 
     18 import android.app.PendingIntent;
     19 import android.graphics.Bitmap;
     20 import android.os.Bundle;
     21 import android.util.Log;
     22 
     23 import java.text.SimpleDateFormat;
     24 import java.util.Date;
     25 
     26 /**
     27  * A parcelable that is used for communication between various stream components.
     28  * The card is uniquely identified by the type and id.
     29  */
     30 public class StreamCard extends AbstractBundleable {
     31     private final static String TAG = "StreamCard";
     32 
     33     private final static String TYPE_KEY = "type";
     34     private final static String ID_KEY = "id";
     35     private final static String PRIORITY_KEY = "priority";
     36     private final static String TIMESTAMP_KEY = "timestamp";
     37     private final static String CONTENT_PENDING_INTENT_KEY = "content_pending_intent";
     38     private final static String PRIMARY_ICON_KEY = "primary_icon";
     39     private final static String SECONDARY_ICON_KEY = "secondary_icon";
     40     private final static String PRIMARY_TEXT_KEY = "primary_text";
     41     private final static String SECONDARY_TEXT_KEY = "secondary_text";
     42     private final static String DESCRIPTION_KEY = "description";
     43     private final static String CARD_EXTENSION_BUNDLE_KEY = "extension_bundle";
     44     private final static String CARD_EXTENSION_CLASS_KEY = "extension_key";
     45 
     46     /** The type of the card */
     47     private int mType;
     48     /** The unique id of this card */
     49     private long mId;
     50     /** Priority or rank compared to other cards */
     51     private int mPriority;
     52     /** Time at which the StreamCard was generated */
     53     private long mTimestamp;
     54     /** Primary action to be taken when the entire card is clicked */
     55     private PendingIntent mContentPendingIntent;
     56     /** Primary icon of the stream card */
     57     private Bitmap mPrimaryIcon;
     58     /** Secondary icon of the stream card */
     59     private Bitmap mSecondaryIcon;
     60     /** Primary text of the stream card */
     61     private CharSequence mPrimaryText;
     62     /** Secondary text of the stream card */
     63     private CharSequence mSecondaryText;
     64     /** Additional meta information for the card */
     65     private StreamCardExtension mCardExtension;
     66 
     67     /** String description of the {@link StreamCard} */
     68     private String mDescription;
     69 
     70     public static final Creator<StreamCard> CREATOR = new BundleableCreator<>(StreamCard.class);
     71 
     72     public StreamCard() {
     73     }
     74 
     75     private StreamCard(int type, long id, int priority, long timestamp,
     76             PendingIntent contentPendingIntent, Bitmap primaryIcon, Bitmap secondaryIcon,
     77             CharSequence primaryText, CharSequence secondaryText, String description,
     78             StreamCardExtension cardExtension) {
     79         mType = type;
     80         mId = id;
     81         mPriority = priority;
     82         mTimestamp = timestamp;
     83         mContentPendingIntent = contentPendingIntent;
     84         mPrimaryIcon = primaryIcon;
     85         mSecondaryIcon = secondaryIcon;
     86         mPrimaryText = primaryText;
     87         mSecondaryText = secondaryText;
     88         mDescription = description;
     89         mCardExtension = cardExtension;
     90     }
     91 
     92     @Override
     93     protected void writeToBundle(Bundle bundle) {
     94         bundle.putInt(TYPE_KEY, mType);
     95         bundle.putLong(ID_KEY, mId);
     96         bundle.putInt(PRIORITY_KEY, mPriority);
     97         bundle.putLong(TIMESTAMP_KEY, mTimestamp);
     98         bundle.putParcelable(CONTENT_PENDING_INTENT_KEY, mContentPendingIntent);
     99         // Note there is a 1MB limit on the transaction size of the binder, if the bitmaps
    100         // are too large, pass through a resource or URI
    101         bundle.putParcelable(PRIMARY_ICON_KEY, mPrimaryIcon);
    102         bundle.putParcelable(SECONDARY_ICON_KEY, mSecondaryIcon);
    103         bundle.putString(DESCRIPTION_KEY, mDescription);
    104         bundle.putCharSequence(PRIMARY_TEXT_KEY, mPrimaryText);
    105         bundle.putCharSequence(SECONDARY_TEXT_KEY, mSecondaryText);
    106 
    107         if (mCardExtension != null) {
    108             Bundle extension = new Bundle();
    109             mCardExtension.writeToBundle(extension);
    110             bundle.putString(CARD_EXTENSION_CLASS_KEY, mCardExtension.getClass().getName());
    111             bundle.putBundle(CARD_EXTENSION_BUNDLE_KEY, extension);
    112         }
    113     }
    114 
    115     @Override
    116     protected void readFromBundle(Bundle bundle) {
    117         mType = bundle.getInt(TYPE_KEY);
    118         mId = bundle.getLong(ID_KEY);
    119         mPriority = bundle.getInt(PRIORITY_KEY);
    120         mTimestamp = bundle.getLong(TIMESTAMP_KEY, System.currentTimeMillis());
    121         mContentPendingIntent = bundle.getParcelable(CONTENT_PENDING_INTENT_KEY);
    122         mPrimaryIcon = bundle.getParcelable(PRIMARY_ICON_KEY);
    123         mSecondaryIcon = bundle.getParcelable(SECONDARY_ICON_KEY);
    124         mDescription = bundle.getString(DESCRIPTION_KEY);
    125         mPrimaryText = bundle.getCharSequence(PRIMARY_TEXT_KEY);
    126         mSecondaryText = bundle.getCharSequence(SECONDARY_TEXT_KEY);
    127         mCardExtension = extractExtension(bundle);
    128     }
    129 
    130     private StreamCardExtension extractExtension(Bundle bundle) {
    131         String className = bundle.getString(CARD_EXTENSION_CLASS_KEY);
    132         Bundle extensionBundle = bundle.getBundle(CARD_EXTENSION_BUNDLE_KEY);
    133         if (className == null || extensionBundle == null) {
    134             return null;
    135         }
    136 
    137         StreamCardExtension extension = null;
    138         try {
    139             Class clazz = getClass().getClassLoader().loadClass(className);
    140             extension = (StreamCardExtension) clazz.newInstance();
    141             extension.readFromBundle(extensionBundle);
    142         } catch (Exception e) {
    143             Log.e(TAG, "Failed to instantiate " + className, e);
    144         }
    145         return extension;
    146     }
    147 
    148     @Override
    149     public String toString() {
    150         String extensionName = null;
    151         if (mCardExtension != null) {
    152             extensionName = mCardExtension.getClass().getName();
    153         }
    154 
    155         StringBuilder sb = new StringBuilder();
    156         sb.append("\nType: " + mType);
    157         sb.append("\nId: " + mId);
    158         sb.append("\nContent Pending Intent: " + mContentPendingIntent);
    159         sb.append("\nDescription: " + mDescription);
    160         sb.append("\nCard Extension: " + extensionName);
    161         sb.append("\nTimestamp: "
    162                 + SimpleDateFormat.getDateInstance().format(new Date(mTimestamp)));
    163 
    164         return sb.toString();
    165     }
    166 
    167     public void setPriority(int priority) {
    168         mPriority = priority;
    169     }
    170 
    171     public int getPriority() {
    172         return mPriority;
    173     }
    174 
    175     public String getDescription() {
    176         return mDescription;
    177     }
    178 
    179     public long getId() {
    180         return mId;
    181     }
    182 
    183     public int getType() {
    184         return mType;
    185     }
    186 
    187     public long getTimestamp() {
    188         return mTimestamp;
    189     }
    190 
    191     public CharSequence getPrimaryText() {
    192         return mPrimaryText;
    193     }
    194 
    195     public CharSequence getSecondaryText() {
    196         return mSecondaryText;
    197     }
    198 
    199     public Bitmap getPrimaryIcon() {
    200         return mPrimaryIcon;
    201     }
    202 
    203     public Bitmap getSecondaryIcon() {
    204         return mSecondaryIcon;
    205     }
    206 
    207     public PendingIntent getContentPendingIntent() {
    208         return mContentPendingIntent;
    209     }
    210 
    211     public AbstractBundleable getCardExtension() {
    212         return mCardExtension;
    213     }
    214 
    215     /**
    216      * Builder to generate a {@link StreamCard}
    217      */
    218     public static class Builder {
    219         private int type;
    220         private long id;
    221         private int priority;
    222         private long timestamp;
    223         private Bitmap primaryIcon;
    224         private Bitmap secondaryIcon;
    225         private CharSequence primaryText;
    226         private CharSequence secondaryText;
    227         private String description;
    228         private PendingIntent contentPendingIntent;
    229         private StreamCardExtension cardExtension;
    230 
    231         public Builder(int type, long id, long timestamp) {
    232             this.type = type;
    233             this.id = id;
    234             this.timestamp = timestamp;
    235         }
    236 
    237         public StreamCard build() {
    238             return new StreamCard(type, id, priority, timestamp, contentPendingIntent, primaryIcon,
    239                     secondaryIcon, primaryText, secondaryText, description, cardExtension);
    240         }
    241 
    242         /**
    243          * Set the primary text of this Stream Card.
    244          */
    245         public Builder setPrimaryText(CharSequence text) {
    246             this.primaryText = text;
    247             return this;
    248         }
    249 
    250         /**
    251          * Set the secondary text of this Stream Card.
    252          */
    253         public Builder setSecondaryText(CharSequence text) {
    254             this.secondaryText = text;
    255             return this;
    256         }
    257 
    258         /**
    259          * Set the pending intent to be executed when the card is clicked.
    260          */
    261         public Builder setClickAction(PendingIntent action) {
    262             this.contentPendingIntent = action;
    263             return this;
    264         }
    265 
    266         /**
    267          * Set the bitmap for the primary icon.
    268          */
    269         public Builder setPrimaryIcon(Bitmap bitmap){
    270             this.primaryIcon = bitmap;
    271             return this;
    272         }
    273 
    274         /**
    275          * Set the bitmap for the secondary icon.
    276          */
    277         public Builder setSecondaryIcon(Bitmap bitmap){
    278             this.secondaryIcon = bitmap;
    279             return this;
    280         }
    281 
    282         /**
    283          * Set the description of the card.
    284          */
    285         public Builder setDescription(String description) {
    286             this.description = description;
    287             return this;
    288         }
    289 
    290         /**
    291          * Set the extension of the card.
    292          */
    293         public Builder setCardExtension(StreamCardExtension extension) {
    294             this.cardExtension = extension;
    295             return this;
    296         }
    297     }
    298 }
    299