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, android.graphics.Bitmap.class); 146 mIconUri = in.readParcelable(null, android.net.Uri.class); 147 mExtras = in.readBundle(); 148 mMediaUri = in.readParcelable(null, android.net.Uri.class); 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