From fef15ea991ce111e43b165ad5f12dccd6be9f1f2 Mon Sep 17 00:00:00 2001 From: Jae Seo Date: Thu, 5 Nov 2015 00:29:39 -0800 Subject: MediaRouter: Black magic to bring custom media metadata back MediaMetadataCompat and MediaMetadata are internally converted into each other on platform version 21 or higher as the framework (e.g. MediaSession) does not understand MediaMetadataCompat. When this happens, custom key-value pairs are lost. The difficulty here is that the current framework API does not provide a way to tell the type of each custom key-value pair in MediaMetadata making it impossible to extract them while converting. This could've been avoided if there is a way to retrieve data as a generic object such as Object or Bundle but the current design offers get-methods only for specific types. The code change here tries to overcome this problem by copying the underlying Bundle object that represents the whole media metadata as is when performing the conversion hence preserving the entirety of the data. Care was taken to replace RatingCompat values in metadata with Rating values such that the metadata Bundle can be unmarshalled on the framework side. Bug: 25328581 Change-Id: Ic83b73e18e31baf9446ca845b7e49aa508b3f108 --- .../support/v4/media/MediaMetadataCompatApi21.java | 9 +++ .../support/v4/media/MediaMetadataCompat.java | 76 +++++++--------------- 2 files changed, 33 insertions(+), 52 deletions(-) diff --git a/v4/api21/android/support/v4/media/MediaMetadataCompatApi21.java b/v4/api21/android/support/v4/media/MediaMetadataCompatApi21.java index eddcf76944..fd51f783ce 100644 --- a/v4/api21/android/support/v4/media/MediaMetadataCompatApi21.java +++ b/v4/api21/android/support/v4/media/MediaMetadataCompatApi21.java @@ -19,6 +19,7 @@ package android.support.v4.media; import android.graphics.Bitmap; import android.media.MediaMetadata; import android.media.Rating; +import android.os.Parcel; import java.util.Set; @@ -43,6 +44,14 @@ class MediaMetadataCompatApi21 { return ((MediaMetadata) metadataObj).getText(key); } + public static void writeToParcel(Object metadataObj, Parcel dest, int flags) { + ((MediaMetadata) metadataObj).writeToParcel(dest, flags); + } + + public static Object createFromParcel(Parcel in) { + return MediaMetadata.CREATOR.createFromParcel(in); + } + public static class Builder { public static Object newInstance() { return new MediaMetadata.Builder(); diff --git a/v4/java/android/support/v4/media/MediaMetadataCompat.java b/v4/java/android/support/v4/media/MediaMetadataCompat.java index d6ebfa410a..0d078265c9 100644 --- a/v4/java/android/support/v4/media/MediaMetadataCompat.java +++ b/v4/java/android/support/v4/media/MediaMetadataCompat.java @@ -361,7 +361,13 @@ public final class MediaMetadataCompat implements Parcelable { public RatingCompat getRating(@RatingKey String key) { RatingCompat rating = null; try { - rating = mBundle.getParcelable(key); + if (Build.VERSION.SDK_INT >= 21) { + // On platform version 21 or higher, mBundle stores a Rating object. Convert it to + // RatingCompat. + rating = RatingCompat.fromRating(mBundle.getParcelable(key)); + } else { + rating = mBundle.getParcelable(key); + } } catch (Exception e) { // ignore, value was not a bitmap Log.w(TAG, "Failed to retrieve a key as Rating.", e); @@ -510,31 +516,11 @@ public final class MediaMetadataCompat implements Parcelable { return null; } - Builder builder = new Builder(); - for (String key : MediaMetadataCompatApi21.keySet(metadataObj)) { - Integer type = METADATA_KEYS_TYPE.get(key); - if (type != null) { - switch (type) { - case METADATA_TYPE_BITMAP: - builder.putBitmap(key, - MediaMetadataCompatApi21.getBitmap(metadataObj, key)); - break; - case METADATA_TYPE_LONG: - builder.putLong(key, - MediaMetadataCompatApi21.getLong(metadataObj, key)); - break; - case METADATA_TYPE_RATING: - builder.putRating(key, RatingCompat.fromRating( - MediaMetadataCompatApi21.getRating(metadataObj, key))); - break; - case METADATA_TYPE_TEXT: - builder.putText(key, - MediaMetadataCompatApi21.getText(metadataObj, key)); - break; - } - } - } - MediaMetadataCompat metadata = builder.build(); + Parcel p = Parcel.obtain(); + MediaMetadataCompatApi21.writeToParcel(metadataObj, p, 0); + p.setDataPosition(0); + MediaMetadataCompat metadata = MediaMetadataCompat.CREATOR.createFromParcel(p); + p.recycle(); metadata.mMetadataObj = metadataObj; return metadata; } @@ -554,31 +540,11 @@ public final class MediaMetadataCompat implements Parcelable { return mMetadataObj; } - Object builderObj = MediaMetadataCompatApi21.Builder.newInstance(); - for (String key : keySet()) { - Integer type = METADATA_KEYS_TYPE.get(key); - if (type != null) { - switch (type) { - case METADATA_TYPE_BITMAP: - MediaMetadataCompatApi21.Builder.putBitmap(builderObj, key, - getBitmap(key)); - break; - case METADATA_TYPE_LONG: - MediaMetadataCompatApi21.Builder.putLong(builderObj, key, - getLong(key)); - break; - case METADATA_TYPE_RATING: - MediaMetadataCompatApi21.Builder.putRating(builderObj, key, - getRating(key).getRating()); - break; - case METADATA_TYPE_TEXT: - MediaMetadataCompatApi21.Builder.putText(builderObj, key, - getText(key)); - break; - } - } - } - mMetadataObj = MediaMetadataCompatApi21.Builder.build(builderObj); + Parcel p = Parcel.obtain(); + writeToParcel(p, 0); + p.setDataPosition(0); + mMetadataObj = MediaMetadataCompatApi21.createFromParcel(p); + p.recycle(); return mMetadataObj; } @@ -742,7 +708,13 @@ public final class MediaMetadataCompat implements Parcelable { + " key cannot be used to put a Rating"); } } - mBundle.putParcelable(key, value); + if (Build.VERSION.SDK_INT >= 21) { + // On platform version 21 or higher, use Rating instead of RatingCompat so mBundle + // can be unmarshalled. + mBundle.putParcelable(key, (Parcelable) value.getRating()); + } else { + mBundle.putParcelable(key, value); + } return this; } -- cgit v1.2.3