1 /*
2  * Copyright 2019 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 
17 package android.media;
18 
19 import android.annotation.Nullable;
20 import android.graphics.Bitmap;
21 import android.media.browse.MediaBrowser;
22 import android.net.Uri;
23 import android.os.Bundle;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.text.TextUtils;
27 
28 /**
29  * A simple set of metadata for a media item suitable for display. This can be
30  * created using the Builder or retrieved from existing metadata using
31  * {@link MediaMetadata#getDescription()}.
32  */
33 public class MediaDescription implements Parcelable {
34     /**
35      * A unique persistent id for the content or null.
36      */
37     private final String mMediaId;
38     /**
39      * A primary title suitable for display or null.
40      */
41     private final CharSequence mTitle;
42     /**
43      * A subtitle suitable for display or null.
44      */
45     private final CharSequence mSubtitle;
46     /**
47      * A description suitable for display or null.
48      */
49     private final CharSequence mDescription;
50     /**
51      * A bitmap icon suitable for display or null.
52      */
53     private final Bitmap mIcon;
54     /**
55      * A Uri for an icon suitable for display or null.
56      */
57     private final Uri mIconUri;
58     /**
59      * Extras for opaque use by apps/system.
60      */
61     private final Bundle mExtras;
62     /**
63      * A Uri to identify this content.
64      */
65     private final Uri mMediaUri;
66 
67     /**
68      * Used as a long extra field to indicate the bluetooth folder type of the media item as
69      * specified in the section 6.10.2.2 of the Bluetooth AVRCP 1.5. This is valid only for
70      * {@link MediaBrowser.MediaItem} with {@link MediaBrowser.MediaItem#FLAG_BROWSABLE}. The value
71      * should be one of the following:
72      * <ul>
73      * <li>{@link #BT_FOLDER_TYPE_MIXED}</li>
74      * <li>{@link #BT_FOLDER_TYPE_TITLES}</li>
75      * <li>{@link #BT_FOLDER_TYPE_ALBUMS}</li>
76      * <li>{@link #BT_FOLDER_TYPE_ARTISTS}</li>
77      * <li>{@link #BT_FOLDER_TYPE_GENRES}</li>
78      * <li>{@link #BT_FOLDER_TYPE_PLAYLISTS}</li>
79      * <li>{@link #BT_FOLDER_TYPE_YEARS}</li>
80      * </ul>
81      *
82      * @see #getExtras()
83      */
84     public static final String EXTRA_BT_FOLDER_TYPE = "android.media.extra.BT_FOLDER_TYPE";
85 
86     /**
87      * The type of folder that is unknown or contains media elements of mixed types as specified in
88      * the section 6.10.2.2 of the Bluetooth AVRCP 1.5.
89      */
90     public static final long BT_FOLDER_TYPE_MIXED = 0;
91 
92     /**
93      * The type of folder that contains media elements only as specified in the section 6.10.2.2 of
94      * the Bluetooth AVRCP 1.5.
95      */
96     public static final long BT_FOLDER_TYPE_TITLES = 1;
97 
98     /**
99      * The type of folder that contains folders categorized by album as specified in the section
100      * 6.10.2.2 of the Bluetooth AVRCP 1.5.
101      */
102     public static final long BT_FOLDER_TYPE_ALBUMS = 2;
103 
104     /**
105      * The type of folder that contains folders categorized by artist as specified in the section
106      * 6.10.2.2 of the Bluetooth AVRCP 1.5.
107      */
108     public static final long BT_FOLDER_TYPE_ARTISTS = 3;
109 
110     /**
111      * The type of folder that contains folders categorized by genre as specified in the section
112      * 6.10.2.2 of the Bluetooth AVRCP 1.5.
113      */
114     public static final long BT_FOLDER_TYPE_GENRES = 4;
115 
116     /**
117      * The type of folder that contains folders categorized by playlist as specified in the section
118      * 6.10.2.2 of the Bluetooth AVRCP 1.5.
119      */
120     public static final long BT_FOLDER_TYPE_PLAYLISTS = 5;
121 
122     /**
123      * The type of folder that contains folders categorized by year as specified in the section
124      * 6.10.2.2 of the Bluetooth AVRCP 1.5.
125      */
126     public static final long BT_FOLDER_TYPE_YEARS = 6;
127 
MediaDescription(String mediaId, CharSequence title, CharSequence subtitle, CharSequence description, Bitmap icon, Uri iconUri, Bundle extras, Uri mediaUri)128     private MediaDescription(String mediaId, CharSequence title, CharSequence subtitle,
129             CharSequence description, Bitmap icon, Uri iconUri, Bundle extras, Uri mediaUri) {
130         mMediaId = mediaId;
131         mTitle = title;
132         mSubtitle = subtitle;
133         mDescription = description;
134         mIcon = icon;
135         mIconUri = iconUri;
136         mExtras = extras;
137         mMediaUri = mediaUri;
138     }
139 
MediaDescription(Parcel in)140     private MediaDescription(Parcel in) {
141         mMediaId = in.readString();
142         mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
143         mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
144         mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
145         mIcon = in.readParcelable(null);
146         mIconUri = in.readParcelable(null);
147         mExtras = in.readBundle();
148         mMediaUri = in.readParcelable(null);
149     }
150 
151     /**
152      * Returns the media id or null. See
153      * {@link MediaMetadata#METADATA_KEY_MEDIA_ID}.
154      */
getMediaId()155     public @Nullable String getMediaId() {
156         return mMediaId;
157     }
158 
159     /**
160      * Returns a title suitable for display or null.
161      *
162      * @return A title or null.
163      */
getTitle()164     public @Nullable CharSequence getTitle() {
165         return mTitle;
166     }
167 
168     /**
169      * Returns a subtitle suitable for display or null.
170      *
171      * @return A subtitle or null.
172      */
getSubtitle()173     public @Nullable CharSequence getSubtitle() {
174         return mSubtitle;
175     }
176 
177     /**
178      * Returns a description suitable for display or null.
179      *
180      * @return A description or null.
181      */
getDescription()182     public @Nullable CharSequence getDescription() {
183         return mDescription;
184     }
185 
186     /**
187      * Returns a bitmap icon suitable for display or null.
188      *
189      * @return An icon or null.
190      */
getIconBitmap()191     public @Nullable Bitmap getIconBitmap() {
192         return mIcon;
193     }
194 
195     /**
196      * Returns a Uri for an icon suitable for display or null.
197      *
198      * @return An icon uri or null.
199      */
getIconUri()200     public @Nullable Uri getIconUri() {
201         return mIconUri;
202     }
203 
204     /**
205      * Returns any extras that were added to the description.
206      *
207      * @return A bundle of extras or null.
208      */
getExtras()209     public @Nullable Bundle getExtras() {
210         return mExtras;
211     }
212 
213     /**
214      * Returns a Uri representing this content or null.
215      *
216      * @return A media Uri or null.
217      */
getMediaUri()218     public @Nullable Uri getMediaUri() {
219         return mMediaUri;
220     }
221 
222     @Override
describeContents()223     public int describeContents() {
224         return 0;
225     }
226 
227     @Override
writeToParcel(Parcel dest, int flags)228     public void writeToParcel(Parcel dest, int flags) {
229         dest.writeString(mMediaId);
230         TextUtils.writeToParcel(mTitle, dest, 0);
231         TextUtils.writeToParcel(mSubtitle, dest, 0);
232         TextUtils.writeToParcel(mDescription, dest, 0);
233         dest.writeParcelable(mIcon, flags);
234         dest.writeParcelable(mIconUri, flags);
235         dest.writeBundle(mExtras);
236         dest.writeParcelable(mMediaUri, flags);
237     }
238 
239     @Override
equals(Object o)240     public boolean equals(Object o) {
241         if (o == null) {
242             return false;
243         }
244 
245         if (!(o instanceof MediaDescription)) {
246             return false;
247         }
248 
249         final MediaDescription d = (MediaDescription) o;
250 
251         if (!String.valueOf(mTitle).equals(String.valueOf(d.mTitle))) {
252             return false;
253         }
254 
255         if (!String.valueOf(mSubtitle).equals(String.valueOf(d.mSubtitle))) {
256             return false;
257         }
258 
259         if (!String.valueOf(mDescription).equals(String.valueOf(d.mDescription))) {
260             return false;
261         }
262 
263         return true;
264     }
265 
266     @Override
toString()267     public String toString() {
268         return mTitle + ", " + mSubtitle + ", " + mDescription;
269     }
270 
271     public static final @android.annotation.NonNull Parcelable.Creator<MediaDescription> CREATOR =
272             new Parcelable.Creator<MediaDescription>() {
273                 @Override
274                 public MediaDescription createFromParcel(Parcel in) {
275                     return new MediaDescription(in);
276                 }
277 
278                 @Override
279                 public MediaDescription[] newArray(int size) {
280                     return new MediaDescription[size];
281                 }
282             };
283 
284     /**
285      * Builder for {@link MediaDescription} objects.
286      */
287     public static class Builder {
288         private String mMediaId;
289         private CharSequence mTitle;
290         private CharSequence mSubtitle;
291         private CharSequence mDescription;
292         private Bitmap mIcon;
293         private Uri mIconUri;
294         private Bundle mExtras;
295         private Uri mMediaUri;
296 
297         /**
298          * Creates an initially empty builder.
299          */
Builder()300         public Builder() {
301         }
302 
303         /**
304          * Sets the media id.
305          *
306          * @param mediaId The unique id for the item or null.
307          * @return this
308          */
setMediaId(@ullable String mediaId)309         public Builder setMediaId(@Nullable String mediaId) {
310             mMediaId = mediaId;
311             return this;
312         }
313 
314         /**
315          * Sets the title.
316          *
317          * @param title A title suitable for display to the user or null.
318          * @return this
319          */
setTitle(@ullable CharSequence title)320         public Builder setTitle(@Nullable CharSequence title) {
321             mTitle = title;
322             return this;
323         }
324 
325         /**
326          * Sets the subtitle.
327          *
328          * @param subtitle A subtitle suitable for display to the user or null.
329          * @return this
330          */
setSubtitle(@ullable CharSequence subtitle)331         public Builder setSubtitle(@Nullable CharSequence subtitle) {
332             mSubtitle = subtitle;
333             return this;
334         }
335 
336         /**
337          * Sets the description.
338          *
339          * @param description A description suitable for display to the user or
340          *            null.
341          * @return this
342          */
setDescription(@ullable CharSequence description)343         public Builder setDescription(@Nullable CharSequence description) {
344             mDescription = description;
345             return this;
346         }
347 
348         /**
349          * Sets the icon.
350          *
351          * @param icon A {@link Bitmap} icon suitable for display to the user or
352          *            null.
353          * @return this
354          */
setIconBitmap(@ullable Bitmap icon)355         public Builder setIconBitmap(@Nullable Bitmap icon) {
356             mIcon = icon;
357             return this;
358         }
359 
360         /**
361          * Sets the icon uri.
362          *
363          * @param iconUri A {@link Uri} for an icon suitable for display to the
364          *            user or null.
365          * @return this
366          */
setIconUri(@ullable Uri iconUri)367         public Builder setIconUri(@Nullable Uri iconUri) {
368             mIconUri = iconUri;
369             return this;
370         }
371 
372         /**
373          * Sets a bundle of extras.
374          *
375          * @param extras The extras to include with this description or null.
376          * @return this
377          */
setExtras(@ullable Bundle extras)378         public Builder setExtras(@Nullable Bundle extras) {
379             mExtras = extras;
380             return this;
381         }
382 
383         /**
384          * Sets the media uri.
385          *
386          * @param mediaUri The content's {@link Uri} for the item or null.
387          * @return this
388          */
setMediaUri(@ullable Uri mediaUri)389         public Builder setMediaUri(@Nullable Uri mediaUri) {
390             mMediaUri = mediaUri;
391             return this;
392         }
393 
394         /**
395          * Build {@link MediaDescription}.
396          *
397          * @return a new media description.
398          */
build()399         public MediaDescription build() {
400             return new MediaDescription(mMediaId, mTitle, mSubtitle, mDescription, mIcon, mIconUri,
401                     mExtras, mMediaUri);
402         }
403     }
404 }
405