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

Commit 51e33d19 authored by Jaewan Kim's avatar Jaewan Kim Committed by Android (Google) Code Review
Browse files

Merge changes from topics "session2_seekcompleted", "session2_pullout",...

Merge changes from topics "session2_seekcompleted", "session2_pullout", "session2_fastforward" into pi-dev

* changes:
  MediaPlayerBase: Add PlayerEventCallback#onSeekCompleted()
  MediaSession2: Pull out Command/CommandGroup from the MediaSession2
  MediaController2: Add fastForward() / rewind()
parents 4f3d29de 598265bd
Loading
Loading
Loading
Loading
+17 −23
Original line number Diff line number Diff line
@@ -25,9 +25,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.media.MediaPlaylistAgent.RepeatMode;
import android.media.MediaPlaylistAgent.ShuffleMode;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandButton;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.ErrorCode;
import android.media.session.MediaSessionManager;
@@ -56,7 +54,7 @@ import java.util.concurrent.Executor;
 * When controlling {@link MediaSessionService2}, the {@link MediaController2} would be
 * available only if the session service allows this controller by
 * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)} for the service.
 * Wait {@link ControllerCallback#onConnected(MediaController2, CommandGroup)} or
 * Wait {@link ControllerCallback#onConnected(MediaController2, SessionCommandGroup2)} or
 * {@link ControllerCallback#onDisconnected(MediaController2)} for the result.
 * <p>
 * A controller can be created through token from {@link MediaSessionManager} if you hold the
@@ -83,7 +81,7 @@ public class MediaController2 implements AutoCloseable {
         * @param allowedCommands commands that's allowed by the session.
         */
        public void onConnected(@NonNull MediaController2 controller,
                @NonNull CommandGroup allowedCommands) { }
                @NonNull SessionCommandGroup2 allowedCommands) { }

        /**
         * Called when the session refuses the controller or the controller is disconnected from
@@ -102,7 +100,8 @@ public class MediaController2 implements AutoCloseable {
         * Called when the session set the custom layout through the
         * {@link MediaSession2#setCustomLayout(ControllerInfo, List)}.
         * <p>
         * Can be called before {@link #onConnected(MediaController2, CommandGroup)} is called.
         * Can be called before {@link #onConnected(MediaController2, SessionCommandGroup2)} is
         * called.
         *
         * @param controller the controller for this event
         * @param layout
@@ -126,7 +125,7 @@ public class MediaController2 implements AutoCloseable {
         * @param commands newly allowed commands
         */
        public void onAllowedCommandsChanged(@NonNull MediaController2 controller,
                @NonNull CommandGroup commands) { }
                @NonNull SessionCommandGroup2 commands) { }

        /**
         * Called when the session sent a custom command.
@@ -137,7 +136,7 @@ public class MediaController2 implements AutoCloseable {
         * @param receiver
         */
        public void onCustomCommand(@NonNull MediaController2 controller,
                @NonNull Command command, @Nullable Bundle args,
                @NonNull SessionCommand2 command, @Nullable Bundle args,
                @Nullable ResultReceiver receiver) { }

        /**
@@ -148,16 +147,6 @@ public class MediaController2 implements AutoCloseable {
         */
        public void onPlayerStateChanged(@NonNull MediaController2 controller, int state) { }

        /**
         * Called when the player's position is changed
         *
         * @param controller the controller for this event
         * @param eventTimeMs timestamp when the position information is sent from the session
         * @param positionMs position in millis
         */
        public void onPositionChanged(@NonNull MediaController2 controller,
                long eventTimeMs, long positionMs) { }

        /**
         * Called when playback speed is changed.
         *
@@ -179,6 +168,14 @@ public class MediaController2 implements AutoCloseable {
        public void onBufferingStateChanged(@NonNull MediaController2 controller,
                @NonNull MediaItem2 item, @MediaPlayerBase.BuffState int state) { }

        /**
         * Called to indicate that seeking is completed.
         *
         * @param controller the controller for this event.
         * @param position the previous seeking request.
         */
        public void onSeekCompleted(@NonNull MediaController2 controller, long position) { }

        /**
         * Called when a error from
         *
@@ -197,7 +194,6 @@ public class MediaController2 implements AutoCloseable {
         *
         * @param controller the controller for this event
         * @param item new item
         * @see #onPositionChanged(MediaController2, long, long)
         * @see #onBufferingStateChanged(MediaController2, MediaItem2, int)
         */
        // TODO(jaewan): Use this (b/74316764)
@@ -423,16 +419,14 @@ public class MediaController2 implements AutoCloseable {
    }

    /**
     * Start fast forwarding. If playback is already fast forwarding this
     * may increase the rate.
     * Fast forwards playback. If playback is already fast forwarding this may increase the rate.
     */
    public void fastForward() {
        mProvider.fastForward_impl();
    }

    /**
     * Start rewinding. If playback is already rewinding this may increase
     * the rate.
     * Rewinds playback. If playback is already rewinding this may increase the rate.
     */
    public void rewind() {
        mProvider.rewind_impl();
@@ -689,7 +683,7 @@ public class MediaController2 implements AutoCloseable {
     * @param args optional argument
     * @param cb optional result receiver
     */
    public void sendCustomCommand(@NonNull Command command, @Nullable Bundle args,
    public void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args,
            @Nullable ResultReceiver cb) {
        mProvider.sendCustomCommand_impl(command, args, cb);
    }
+10 −28
Original line number Diff line number Diff line
@@ -130,33 +130,6 @@ public abstract class MediaPlayerBase implements AutoCloseable {
     */
    public abstract void seekTo(long pos);

    /**
     * Fast forwards playback. If playback is already fast forwarding this may increase the rate.
     * <p>
     * Default implementation sets the playback speed to the 2.0f
     * @see #setPlaybackSpeed(float)
     * @hide
     */
    // TODO(jaewan): Unhide (b/74724709)
    public void fastForward() {
        setPlaybackSpeed(2.0f);
    }

    /**
     * Rewinds playback. If playback is already rewinding this may increase the rate.
     * <p>
     * Default implementation sets the playback speed to the -1.0f if
     * {@link #isReversePlaybackSupported()} returns {@code true}.
     * @see #setPlaybackSpeed(float)
     * @hide
     */
    // TODO(jaewan): Unhide (b/74724709)
    public void rewind() {
        if (isReversePlaybackSupported()) {
            setPlaybackSpeed(-1.0f);
        }
    }

    public static final long UNKNOWN_TIME = -1;

    /**
@@ -340,10 +313,19 @@ public abstract class MediaPlayerBase implements AutoCloseable {

        /**
         * Called to indicate that the playback speed has changed.
         * @param mpb the player that is buffering
         * @param mpb the player that has changed the playback speed.
         * @param speed the new playback speed.
         */
        public void onPlaybackSpeedChanged(@NonNull MediaPlayerBase mpb, float speed) { }

        /**
         * Called to indicate that {@link #seekTo(long)} is completed.
         *
         * @param mpb the player that has completed seeking.
         * @param position the previous seeking request.
         * @see #seekTo(long)
         */
        public void onSeekCompleted(@NonNull MediaPlayerBase mpb, long position) { }
    }

}
+66 −452

File changed.

Preview size limit exceeded, changes collapsed.

+336 −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 android.media;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.MediaSession2Provider;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.SessionCallback;
import android.net.Uri;
import android.os.Bundle;

import java.util.List;

/**
 * @hide
 * Define a command that a {@link MediaController2} can send to a {@link MediaSession2}.
 * <p>
 * If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
 * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
 * {@link #getCustomCommand()} shouldn't be {@code null}.
 */
public final class SessionCommand2 {
    /**
     * Command code for the custom command which can be defined by string action in the
     * {@link SessionCommand2}.
     */
    public static final int COMMAND_CODE_CUSTOM = 0;

    /**
     * Command code for {@link MediaController2#play()}.
     * <p>
     * Command would be sent directly to the player if the session doesn't reject the request
     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo,
     * SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYBACK_PLAY = 1;

    /**
     * Command code for {@link MediaController2#pause()}.
     * <p>
     * Command would be sent directly to the player if the session doesn't reject the request
     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo,
     * SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2;

    /**
     * Command code for {@link MediaController2#stop()}.
     * <p>
     * Command would be sent directly to the player if the session doesn't reject the request
     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo,
     * SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYBACK_STOP = 3;

    /**
     * Command code for {@link MediaController2#skipToNextItem()}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the {@link SessionCallback#onCommandRequest(
     * MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_SKIP_NEXT_ITEM = 4;

    /**
     * Command code for {@link MediaController2#skipToPreviousItem()}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the {@link SessionCallback#onCommandRequest(
     * MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_SKIP_PREV_ITEM = 5;

    /**
     * Command code for {@link MediaController2#prepare()}.
     * <p>
     * Command would be sent directly to the player if the session doesn't reject the request
     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo,
     * SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYBACK_PREPARE = 6;

    /**
     * Command code for {@link MediaController2#fastForward()}.
     */
    public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 7;

    /**
     * Command code for {@link MediaController2#rewind()}.
     */
    public static final int COMMAND_CODE_SESSION_REWIND = 8;

    /**
     * Command code for {@link MediaController2#seekTo(long)}.
     * <p>
     * Command would be sent directly to the player if the session doesn't reject the request
     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo,
     * SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYBACK_SEEK_TO = 9;

    /**
     * Command code for both {@link MediaController2#setVolumeTo(int, int)}.
     * <p>
     * Command would set the device volume or send to the volume provider directly if the session
     * doesn't reject the request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_SET_VOLUME = 10;

    /**
     * Command code for both {@link MediaController2#adjustVolume(int, int)}.
     * <p>
     * Command would adjust the device volume or send to the volume provider directly if the session
     * doesn't reject the request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_ADJUST_VOLUME = 11;

    /**
     * Command code for {@link MediaController2#skipToPlaylistItem(MediaItem2)}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM = 12;

    /**
     * Command code for {@link MediaController2#setShuffleMode(int)}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_SET_SHUFFLE_MODE = 13;

    /**
     * Command code for {@link MediaController2#setRepeatMode(int)}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_SET_REPEAT_MODE = 14;

    /**
     * Command code for {@link MediaController2#addPlaylistItem(int, MediaItem2)}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_ADD_ITEM = 15;

    /**
     * Command code for {@link MediaController2#addPlaylistItem(int, MediaItem2)}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_REMOVE_ITEM = 16;

    /**
     * Command code for {@link MediaController2#replacePlaylistItem(int, MediaItem2)}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_REPLACE_ITEM = 17;

    /**
     * Command code for {@link MediaController2#getPlaylist()}. This will expose metadata
     * information to the controller.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_GET_LIST = 18;

    /**
     * Command code for {@link MediaController2#setPlaylist(List, MediaMetadata2)}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_SET_LIST = 19;

    /**
     * Command code for {@link MediaController2#getPlaylistMetadata()}. This will expose
     * metadata information to the controller.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_GET_LIST_METADATA = 20;

    /**
     * Command code for {@link MediaController2#updatePlaylistMetadata(MediaMetadata2)}.
     * <p>
     * Command would be sent directly to the playlist agent if the session doesn't reject the
     * request through the
     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, SessionCommand2)}.
     */
    public static final int COMMAND_CODE_PLAYLIST_SET_LIST_METADATA = 21;

    /**
     * Command code for {@link MediaController2#playFromMediaId(String, Bundle)}.
     */
    public static final int COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID = 22;

    /**
     * Command code for {@link MediaController2#playFromUri(Uri, Bundle)}.
     */
    public static final int COMMAND_CODE_SESSION_PLAY_FROM_URI = 23;

    /**
     * Command code for {@link MediaController2#playFromSearch(String, Bundle)}.
     */
    public static final int COMMAND_CODE_SESSION_PLAY_FROM_SEARCH = 24;

    /**
     * Command code for {@link MediaController2#prepareFromMediaId(String, Bundle)}.
     */
    public static final int COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID = 25;

    /**
     * Command code for {@link MediaController2#prepareFromUri(Uri, Bundle)}.
     */
    public static final int COMMAND_CODE_SESSION_PREPARE_FROM_URI = 26;

    /**
     * Command code for {@link MediaController2#prepareFromSearch(String, Bundle)}.
     */
    public static final int COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH = 27;

    /**
     * Command code for {@link MediaController2#setRating(String, Rating2)}.
     */
    public static final int COMMAND_CODE_SESSION_SET_RATING = 28;

    // TODO(jaewan): Add javadoc
    public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 29;
    public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 30;
    public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 31;
    public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 32;
    public static final int COMMAND_CODE_LIBRARY_SEARCH = 33;
    public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 34;
    public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 35;

    // TODO(jaewan): Rename and move provider
    private final MediaSession2Provider.CommandProvider mProvider;

    public SessionCommand2(int commandCode) {
        mProvider = ApiLoader.getProvider().createMediaSession2Command(
                this, commandCode, null, null);
    }

    public SessionCommand2(@NonNull String action, @Nullable Bundle extras) {
        if (action == null) {
            throw new IllegalArgumentException("action shouldn't be null");
        }
        mProvider = ApiLoader.getProvider().createMediaSession2Command(
                this, COMMAND_CODE_CUSTOM, action, extras);
    }

    /**
     * @hide
     */
    public MediaSession2Provider.CommandProvider getProvider() {
        return mProvider;
    }

    public int getCommandCode() {
        return mProvider.getCommandCode_impl();
    }

    public @Nullable String getCustomCommand() {
        return mProvider.getCustomCommand_impl();
    }

    public @Nullable Bundle getExtras() {
        return mProvider.getExtras_impl();
    }

    /**
     * @return a new Bundle instance from the Command
     * @hide
     */
    public Bundle toBundle() {
        return mProvider.toBundle_impl();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof SessionCommand2)) {
            return false;
        }
        return mProvider.equals_impl(((SessionCommand2) obj).mProvider);
    }

    @Override
    public int hashCode() {
        return mProvider.hashCode_impl();
    }

    /**
     * @return a new Command instance from the Bundle
     * @hide
     */
    public static SessionCommand2 fromBundle(@NonNull Bundle command) {
        return ApiLoader.getProvider().fromBundle_MediaSession2Command(command);
    }
}
+106 −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 android.media;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.MediaSession2Provider;
import android.os.Bundle;

import java.util.Set;

/**
 * @hide
 * Represent set of {@link SessionCommand2}.
 */
public final class SessionCommandGroup2 {
    // TODO(jaewan): Rename and move provider
    private final MediaSession2Provider.CommandGroupProvider mProvider;

    public SessionCommandGroup2() {
        mProvider = ApiLoader.getProvider().createMediaSession2CommandGroup(this, null);
    }

    public SessionCommandGroup2(@Nullable SessionCommandGroup2 others) {
        mProvider = ApiLoader.getProvider().createMediaSession2CommandGroup(this, others);
    }

    /**
     * @hide
     */
    public SessionCommandGroup2(@NonNull MediaSession2Provider.CommandGroupProvider provider) {
        mProvider = provider;
    }

    public void addCommand(@NonNull SessionCommand2 command) {
        mProvider.addCommand_impl(command);
    }

    public void addCommand(int commandCode) {
        // TODO(jaewna): Implement
    }

    public void addAllPredefinedCommands() {
        mProvider.addAllPredefinedCommands_impl();
    }

    public void removeCommand(@NonNull SessionCommand2 command) {
        mProvider.removeCommand_impl(command);
    }

    public void removeCommand(int commandCode) {
        // TODO(jaewan): Implement.
    }

    public boolean hasCommand(@NonNull SessionCommand2 command) {
        return mProvider.hasCommand_impl(command);
    }

    public boolean hasCommand(int code) {
        return mProvider.hasCommand_impl(code);
    }

    public @NonNull
    Set<SessionCommand2> getCommands() {
        return mProvider.getCommands_impl();
    }

    /**
     * @hide
     */
    public @NonNull MediaSession2Provider.CommandGroupProvider getProvider() {
        return mProvider;
    }

    /**
     * @return new bundle from the CommandGroup
     * @hide
     */
    public @NonNull Bundle toBundle() {
        return mProvider.toBundle_impl();
    }

    /**
     * @return new instance of CommandGroup from the bundle
     * @hide
     */
    public static @Nullable SessionCommandGroup2 fromBundle(Bundle commands) {
        return ApiLoader.getProvider().fromBundle_MediaSession2CommandGroup(commands);
    }
}
Loading