Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83730674 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topics "rating2_updatable", "mediasession2_playlistparams",...

Merge changes from topics "rating2_updatable", "mediasession2_playlistparams", "mediametadata2_updatable"

* changes:
  MediaSession2: Move Rating2 to updatable
  MediaSession2: Move MediaSession2.PlaylistParams to updatable
  MediaSession2: Move MediaMetadata2 to updatable
parents 9111804e 24f525c3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -595,7 +595,8 @@ public class MediaController2Impl implements MediaController2Provider {
                Log.w(TAG, "Don't fail silently here. Highly likely a bug");
                return;
            }
            controller.pushPlaylistParamsChanges(PlaylistParams.fromBundle(params));
            controller.pushPlaylistParamsChanges(
                    PlaylistParams.fromBundle(controller.getContext(), params));
        }

        @Override
+2 −2
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ public class MediaItem2Impl implements MediaItem2Provider {
        bundle.putString(KEY_ID, mId);
        bundle.putInt(KEY_FLAGS, mFlags);
        if (mMetadata != null) {
            bundle.putBundle(KEY_METADATA, mMetadata.getBundle());
            bundle.putBundle(KEY_METADATA, mMetadata.toBundle());
        }
        return bundle;
    }
@@ -102,7 +102,7 @@ public class MediaItem2Impl implements MediaItem2Provider {
        final String id = bundle.getString(KEY_ID);
        final Bundle metadataBundle = bundle.getBundle(KEY_METADATA);
        final MediaMetadata2 metadata = metadataBundle != null
                ? new MediaMetadata2(metadataBundle) : null;
                ? MediaMetadata2.fromBundle(context, metadataBundle) : null;
        final int flags = bundle.getInt(KEY_FLAGS);
        return new MediaItem2Impl(context, id, metadata, flags).getInstance();
    }
+328 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.media;

import static android.media.MediaMetadata2.*;

import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaMetadata2;
import android.media.MediaMetadata2.BitmapKey;
import android.media.MediaMetadata2.Builder;
import android.media.MediaMetadata2.LongKey;
import android.media.MediaMetadata2.RatingKey;
import android.media.MediaMetadata2.TextKey;
import android.media.Rating2;
import android.media.update.MediaMetadata2Provider;
import android.os.Bundle;
import android.util.ArrayMap;
import android.util.Log;

import java.util.Set;

public class MediaMetadata2Impl implements MediaMetadata2Provider {
    private static final String TAG = "MediaMetadata2";

    /**
     * A {@link Bundle} extra.
     * @hide
     */
    public static final String METADATA_KEY_EXTRA = "android.media.metadata.EXTRA";

    static final int METADATA_TYPE_LONG = 0;
    static final int METADATA_TYPE_TEXT = 1;
    static final int METADATA_TYPE_BITMAP = 2;
    static final int METADATA_TYPE_RATING = 3;
    static final ArrayMap<String, Integer> METADATA_KEYS_TYPE;

    static {
        METADATA_KEYS_TYPE = new ArrayMap<String, Integer>();
        METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DURATION, METADATA_TYPE_LONG);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG);
        METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG);
        METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ARTIST, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ART_URI, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART, METADATA_TYPE_BITMAP);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART_URI, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING);
        METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_TITLE, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_SUBTITLE, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON, METADATA_TYPE_BITMAP);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON_URI, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_ID, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_BT_FOLDER_TYPE, METADATA_TYPE_LONG);
        METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_URI, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ADVERTISEMENT, METADATA_TYPE_LONG);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DOWNLOAD_STATUS, METADATA_TYPE_LONG);
    }

    private static final @TextKey
    String[] PREFERRED_DESCRIPTION_ORDER = {
            METADATA_KEY_TITLE,
            METADATA_KEY_ARTIST,
            METADATA_KEY_ALBUM,
            METADATA_KEY_ALBUM_ARTIST,
            METADATA_KEY_WRITER,
            METADATA_KEY_AUTHOR,
            METADATA_KEY_COMPOSER
    };

    private static final @BitmapKey
    String[] PREFERRED_BITMAP_ORDER = {
            METADATA_KEY_DISPLAY_ICON,
            METADATA_KEY_ART,
            METADATA_KEY_ALBUM_ART
    };

    private static final @TextKey
    String[] PREFERRED_URI_ORDER = {
            METADATA_KEY_DISPLAY_ICON_URI,
            METADATA_KEY_ART_URI,
            METADATA_KEY_ALBUM_ART_URI
    };

    private final Context mContext;
    private final MediaMetadata2 mInstance;
    private final Bundle mBundle;

    public MediaMetadata2Impl(Context context, Bundle bundle) {
        mContext = context;
        mInstance = new MediaMetadata2(this);
        mBundle = bundle;
    }

    public MediaMetadata2 getInstance() {
        return mInstance;
    }

    @Override
    public boolean containsKey_impl(String key) {
        return mBundle.containsKey(key);
    }

    @Override
    public CharSequence getText_impl(@TextKey String key) {
        return mBundle.getCharSequence(key);
    }

    @Override
    public @Nullable String getMediaId_impl() {
        return mInstance.getString(METADATA_KEY_MEDIA_ID);
    }

    @Override
    public String getString_impl(@TextKey String key) {
        CharSequence text = mBundle.getCharSequence(key);
        if (text != null) {
            return text.toString();
        }
        return null;
    }

    @Override
    public long getLong_impl(@LongKey String key) {
        return mBundle.getLong(key, 0);
    }

    @Override
    public Rating2 getRating_impl(@RatingKey String key) {
        // TODO(jaewan): Add backward compatibility
        Rating2 rating = null;
        try {
            rating = Rating2.fromBundle(mContext, mBundle.getBundle(key));
        } catch (Exception e) {
            // ignore, value was not a rating
            Log.w(TAG, "Failed to retrieve a key as Rating.", e);
        }
        return rating;
    }

    @Override
    public Bitmap getBitmap_impl(@BitmapKey String key) {
        Bitmap bmp = null;
        try {
            bmp = mBundle.getParcelable(key);
        } catch (Exception e) {
            // ignore, value was not a bitmap
            Log.w(TAG, "Failed to retrieve a key as Bitmap.", e);
        }
        return bmp;
    }

    @Override
    public Bundle getExtra_impl() {
        try {
            return mBundle.getBundle(METADATA_KEY_EXTRA);
        } catch (Exception e) {
            // ignore, value was not an bundle
            Log.w(TAG, "Failed to retrieve an extra");
        }
        return null;
    }

    @Override
    public int size_impl() {
        return mBundle.size();
    }

    @Override
    public Set<String> keySet_impl() {
        return mBundle.keySet();
    }

    @Override
    public Bundle toBundle_impl() {
        return mBundle;
    }

    public static MediaMetadata2 fromBundle(Context context, Bundle bundle) {
        return new MediaMetadata2Impl(context, bundle).getInstance();
    }

    public static final class BuilderImpl implements MediaMetadata2Provider.BuilderProvider {
        private final Context mContext;
        private final MediaMetadata2.Builder mInstance;
        private final Bundle mBundle;

        public BuilderImpl(Context context, MediaMetadata2.Builder instance) {
            mContext = context;
            mInstance = instance;
            mBundle = new Bundle();
        }

        public BuilderImpl(Context context, MediaMetadata2.Builder instance, MediaMetadata2 source) {
            if (source == null) {
                throw new IllegalArgumentException("source shouldn't be null");
            }
            mContext = context;
            mInstance = instance;
            mBundle = new Bundle(source.toBundle());
        }

        public BuilderImpl(Context context, int maxBitmapSize) {
            mContext = context;
            mInstance = new MediaMetadata2.Builder(this);
            mBundle = new Bundle();

            for (String key : mBundle.keySet()) {
                Object value = mBundle.get(key);
                if (value instanceof Bitmap) {
                    Bitmap bmp = (Bitmap) value;
                    if (bmp.getHeight() > maxBitmapSize || bmp.getWidth() > maxBitmapSize) {
                        mInstance.putBitmap(key, scaleBitmap(bmp, maxBitmapSize));
                    }
                }
            }
        }

        @Override
        public Builder putText_impl(@TextKey String key, CharSequence value) {
            if (METADATA_KEYS_TYPE.containsKey(key)) {
                if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
                    throw new IllegalArgumentException("The " + key
                            + " key cannot be used to put a CharSequence");
                }
            }
            mBundle.putCharSequence(key, value);
            return mInstance;
        }

        @Override
        public Builder putString_impl(@TextKey String key, String value) {
            if (METADATA_KEYS_TYPE.containsKey(key)) {
                if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
                    throw new IllegalArgumentException("The " + key
                            + " key cannot be used to put a String");
                }
            }
            mBundle.putCharSequence(key, value);
            return mInstance;
        }

        @Override
        public Builder putLong_impl(@LongKey String key, long value) {
            if (METADATA_KEYS_TYPE.containsKey(key)) {
                if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) {
                    throw new IllegalArgumentException("The " + key
                            + " key cannot be used to put a long");
                }
            }
            mBundle.putLong(key, value);
            return mInstance;
        }

        @Override
        public Builder putRating_impl(@RatingKey String key, Rating2 value) {
            if (METADATA_KEYS_TYPE.containsKey(key)) {
                if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) {
                    throw new IllegalArgumentException("The " + key
                            + " key cannot be used to put a Rating");
                }
            }
            mBundle.putBundle(key, value.toBundle());
            return mInstance;
        }

        @Override
        public Builder putBitmap_impl(@BitmapKey String key, Bitmap value) {
            if (METADATA_KEYS_TYPE.containsKey(key)) {
                if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
                    throw new IllegalArgumentException("The " + key
                            + " key cannot be used to put a Bitmap");
                }
            }
            mBundle.putParcelable(key, value);
            return mInstance;
        }

        @Override
        public Builder setExtra_impl(Bundle bundle) {
            mBundle.putBundle(METADATA_KEY_EXTRA, bundle);
            return mInstance;
        }

        @Override
        public MediaMetadata2 build_impl() {
            return new MediaMetadata2Impl(mContext, mBundle).getInstance();
        }

        private Bitmap scaleBitmap(Bitmap bmp, int maxSize) { float maxSizeF = maxSize;
            float widthScale = maxSizeF / bmp.getWidth();
            float heightScale = maxSizeF / bmp.getHeight();
            float scale = Math.min(widthScale, heightScale);
            int height = (int) (bmp.getHeight() * scale);
            int width = (int) (bmp.getWidth() * scale);
            return Bitmap.createScaledBitmap(bmp, width, height, true);
        }
    }
}
+73 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.media.MediaItem2;
import android.media.MediaLibraryService2;
import android.media.MediaMetadata2;
import android.media.MediaPlayerInterface;
import android.media.MediaPlayerInterface.PlaybackListener;
import android.media.MediaSession2;
@@ -40,6 +41,8 @@ import android.media.MediaSession2.CommandButton;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.PlaylistParams;
import android.media.MediaSession2.PlaylistParams.RepeatMode;
import android.media.MediaSession2.PlaylistParams.ShuffleMode;
import android.media.MediaSession2.SessionCallback;
import android.media.MediaSessionService2;
import android.media.PlaybackState2;
@@ -814,4 +817,74 @@ public class MediaSession2Impl implements MediaSession2Provider {
            return (ControllerInfoImpl) controller.getProvider();
        }
    }

    public static class PlaylistParamsImpl implements PlaylistParamsProvider {
        /**
         * Keys used for converting a PlaylistParams object to a bundle object and vice versa.
         */
        private static final String KEY_REPEAT_MODE =
                "android.media.session2.playlistparams2.repeat_mode";
        private static final String KEY_SHUFFLE_MODE =
                "android.media.session2.playlistparams2.shuffle_mode";
        private static final String KEY_MEDIA_METADATA2_BUNDLE =
                "android.media.session2.playlistparams2.metadata2_bundle";

        private Context mContext;
        private PlaylistParams mInstance;
        private @RepeatMode int mRepeatMode;
        private @ShuffleMode int mShuffleMode;
        private MediaMetadata2 mPlaylistMetadata;

        public PlaylistParamsImpl(Context context, PlaylistParams instance,
                @RepeatMode int repeatMode, @ShuffleMode int shuffleMode,
                MediaMetadata2 playlistMetadata) {
            // TODO(jaewan): Sanity check
            mContext = context;
            mInstance = instance;
            mRepeatMode = repeatMode;
            mShuffleMode = shuffleMode;
            mPlaylistMetadata = playlistMetadata;
        }

        public @RepeatMode int getRepeatMode_impl() {
            return mRepeatMode;
        }

        public @ShuffleMode int getShuffleMode_impl() {
            return mShuffleMode;
        }

        public MediaMetadata2 getPlaylistMetadata_impl() {
            return mPlaylistMetadata;
        }

        @Override
        public Bundle toBundle_impl() {
            Bundle bundle = new Bundle();
            bundle.putInt(KEY_REPEAT_MODE, mRepeatMode);
            bundle.putInt(KEY_SHUFFLE_MODE, mShuffleMode);
            if (mPlaylistMetadata != null) {
                bundle.putBundle(KEY_MEDIA_METADATA2_BUNDLE, mPlaylistMetadata.toBundle());
            }
            return bundle;
        }

        public static PlaylistParams fromBundle(Context context, Bundle bundle) {
            if (bundle == null) {
                return null;
            }
            if (!bundle.containsKey(KEY_REPEAT_MODE) || !bundle.containsKey(KEY_SHUFFLE_MODE)) {
                return null;
            }

            Bundle metadataBundle = bundle.getBundle(KEY_MEDIA_METADATA2_BUNDLE);
            MediaMetadata2 metadata = metadataBundle == null
                    ? null : MediaMetadata2.fromBundle(context, metadataBundle);

            return new PlaylistParams(context,
                    bundle.getInt(KEY_REPEAT_MODE),
                    bundle.getInt(KEY_SHUFFLE_MODE),
                    metadata);
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -225,7 +225,7 @@ public class MediaSession2Stub extends IMediaSession2.Stub {
                    break;
                case MediaSession2.COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS:
                    session.getInstance().setPlaylistParams(
                            PlaylistParams.fromBundle(
                            PlaylistParams.fromBundle(session.getContext(),
                                    args.getBundle(ARGUMENT_KEY_PLAYLIST_PARAMS)));
                    break;
                default:
Loading