/* * Copyright (C) 2014 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.session; import static com.android.media.flags.Flags.FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE; import android.annotation.DrawableRes; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.LongDef; import android.annotation.Nullable; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.text.TextUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; /** * Playback state for a {@link MediaSession}. This includes a state like * {@link PlaybackState#STATE_PLAYING}, the current playback position, * and the current control capabilities. */ public final class PlaybackState implements Parcelable { private static final String TAG = "PlaybackState"; /** * @hide */ @LongDef(flag = true, value = {ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND, ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING, ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH, ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE, ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI, ACTION_SET_PLAYBACK_SPEED}) @Retention(RetentionPolicy.SOURCE) public @interface Actions {} /** * Indicates this session supports the stop command. * * @see Builder#setActions(long) */ public static final long ACTION_STOP = 1 << 0; /** * Indicates this session supports the pause command. * * @see Builder#setActions(long) */ public static final long ACTION_PAUSE = 1 << 1; /** * Indicates this session supports the play command. * * @see Builder#setActions(long) */ public static final long ACTION_PLAY = 1 << 2; /** * Indicates this session supports the rewind command. * * @see Builder#setActions(long) */ public static final long ACTION_REWIND = 1 << 3; /** * Indicates this session supports the previous command. * * @see Builder#setActions(long) */ public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4; /** * Indicates this session supports the next command. * * @see Builder#setActions(long) */ public static final long ACTION_SKIP_TO_NEXT = 1 << 5; /** * Indicates this session supports the fast forward command. * * @see Builder#setActions(long) */ public static final long ACTION_FAST_FORWARD = 1 << 6; /** * Indicates this session supports the set rating command. * * @see Builder#setActions(long) */ public static final long ACTION_SET_RATING = 1 << 7; /** * Indicates this session supports the seek to command. * * @see Builder#setActions(long) */ public static final long ACTION_SEEK_TO = 1 << 8; /** * Indicates this session supports the play/pause toggle command. * * @see Builder#setActions(long) */ public static final long ACTION_PLAY_PAUSE = 1 << 9; /** * Indicates this session supports the play from media id command. * * @see Builder#setActions(long) */ public static final long ACTION_PLAY_FROM_MEDIA_ID = 1 << 10; /** * Indicates this session supports the play from search command. * * @see Builder#setActions(long) */ public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11; /** * Indicates this session supports the skip to queue item command. * * @see Builder#setActions(long) */ public static final long ACTION_SKIP_TO_QUEUE_ITEM = 1 << 12; /** * Indicates this session supports the play from URI command. * * @see Builder#setActions(long) */ public static final long ACTION_PLAY_FROM_URI = 1 << 13; /** * Indicates this session supports the prepare command. * * @see Builder#setActions(long) */ public static final long ACTION_PREPARE = 1 << 14; /** * Indicates this session supports the prepare from media id command. * * @see Builder#setActions(long) */ public static final long ACTION_PREPARE_FROM_MEDIA_ID = 1 << 15; /** * Indicates this session supports the prepare from search command. * * @see Builder#setActions(long) */ public static final long ACTION_PREPARE_FROM_SEARCH = 1 << 16; /** * Indicates this session supports the prepare from URI command. * * @see Builder#setActions(long) */ public static final long ACTION_PREPARE_FROM_URI = 1 << 17; // Note: The value jumps from 1 << 17 to 1 << 22 for matching same value with AndroidX. /** * Indicates this session supports the set playback speed command. * * @see Builder#setActions(long) */ public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22; /** * @hide */ @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING, STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING, STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM, STATE_PLAYBACK_SUPPRESSED}) @Retention(RetentionPolicy.SOURCE) public @interface State {} /** * This is the default playback state and indicates that no media has been * added yet, or the performer has been reset and has no content to play. * * @see Builder#setState(int, long, float) * @see Builder#setState(int, long, float, long) */ public static final int STATE_NONE = 0; /** * State indicating this item is currently stopped. * * @see Builder#setState */ public static final int STATE_STOPPED = 1; /** * State indicating this item is currently paused. * * @see Builder#setState */ public static final int STATE_PAUSED = 2; /** * State indicating this item is currently playing. * * @see Builder#setState */ public static final int STATE_PLAYING = 3; /** * State indicating this item is currently fast forwarding. * * @see Builder#setState */ public static final int STATE_FAST_FORWARDING = 4; /** * State indicating this item is currently rewinding. * * @see Builder#setState */ public static final int STATE_REWINDING = 5; /** * State indicating this item is currently buffering and will begin playing * when enough data has buffered. * * @see Builder#setState */ public static final int STATE_BUFFERING = 6; /** * State indicating this item is currently in an error state. The error * message should also be set when entering this state. * * @see Builder#setState */ public static final int STATE_ERROR = 7; /** * State indicating the class doing playback is currently connecting to a * new destination. Depending on the implementation you may return to the previous * state when the connection finishes or enter {@link #STATE_NONE}. * If the connection failed {@link #STATE_ERROR} should be used. * * @see Builder#setState */ public static final int STATE_CONNECTING = 8; /** * State indicating the player is currently skipping to the previous item. * * @see Builder#setState */ public static final int STATE_SKIPPING_TO_PREVIOUS = 9; /** * State indicating the player is currently skipping to the next item. * * @see Builder#setState */ public static final int STATE_SKIPPING_TO_NEXT = 10; /** * State indicating the player is currently skipping to a specific item in * the queue. * * @see Builder#setState */ public static final int STATE_SKIPPING_TO_QUEUE_ITEM = 11; /** * State indicating that playback is paused due to an external transient interruption, like a * phone call. * *
This state is different from {@link #STATE_PAUSED} in that it is deemed transitory,
* possibly allowing the service associated to the session in this state to run in the
* foreground.
*
* @see Builder#setState
*/
@FlaggedApi(FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE)
public static final int STATE_PLAYBACK_SUPPRESSED = 12;
/**
* Use this value for the position to indicate the position is not known.
*/
public static final long PLAYBACK_POSITION_UNKNOWN = -1;
private final int mState;
private final long mPosition;
private final long mBufferedPosition;
private final float mSpeed;
private final long mActions;
private List
* The playback state is considered as an active if the state is one of the following:
*
* The position must be in ms and indicates the current playback
* position within the item. If the position is unknown use
* {@link #PLAYBACK_POSITION_UNKNOWN}. When not using an unknown
* position the time at which the position was updated must be provided.
* It is okay to use {@link SystemClock#elapsedRealtime()} if the
* current position was just retrieved.
*
* The speed is a multiple of normal playback and should be 0 when
* paused and negative when rewinding. Normal playback speed is 1.0.
*
* The state must be one of the following:
*
* The position must be in ms and indicates the current playback
* position within the item. If the position is unknown use
* {@link #PLAYBACK_POSITION_UNKNOWN}. The update time will be set to
* the current {@link SystemClock#elapsedRealtime()}.
*
* The speed is a multiple of normal playback and should be 0 when
* paused and negative when rewinding. Normal playback speed is 1.0.
*
* The state must be one of the following:
*
* e.g. start a radio station based on the current item or skip ahead by
* 30 seconds.
*
* @param action An identifier for this action. It can be sent back to
* the {@link MediaSession} through
* {@link MediaController.TransportControls#sendCustomAction(String, Bundle)}.
* @param name The display name for the action. If text is shown with
* the action or used for accessibility, this is what should
* be used.
* @param icon The resource action of the icon that should be displayed
* for the action. The resource should be in the package of
* the {@link MediaSession}.
* @return this
*/
public Builder addCustomAction(String action, String name, int icon) {
return addCustomAction(new PlaybackState.CustomAction(action, name, icon, null));
}
/**
* Add a custom action to the playback state. Actions can be used to expose additional
* functionality to {@link MediaController MediaControllers} beyond what is offered by the
* standard transport controls.
*
* An example of an action would be to start a radio station based on the current item
* or to skip ahead by 30 seconds.
*
* @param customAction The custom action to add to the {@link PlaybackState}.
* @return this
*/
public Builder addCustomAction(PlaybackState.CustomAction customAction) {
if (customAction == null) {
throw new IllegalArgumentException(
"You may not add a null CustomAction to PlaybackState.");
}
mCustomActions.add(customAction);
return this;
}
/**
* Set the current buffered position in ms. This is the farthest
* playback point that can be reached from the current position using
* only buffered content.
*
* @param bufferedPosition The position in ms that playback is buffered
* to.
* @return this
*/
public Builder setBufferedPosition(long bufferedPosition) {
mBufferedPosition = bufferedPosition;
return this;
}
/**
* Set the active item in the play queue by specifying its id. The
* default value is {@link MediaSession.QueueItem#UNKNOWN_ID}
*
* @param id The id of the active item.
* @return this
*/
public Builder setActiveQueueItemId(long id) {
mActiveItemId = id;
return this;
}
/**
* Set a user readable error message. This should be set when the state
* is {@link PlaybackState#STATE_ERROR}.
*
* @param error The error message for display to the user.
* @return this
*/
public Builder setErrorMessage(CharSequence error) {
mErrorMessage = error;
return this;
}
/**
* Set any custom extras to be included with the playback state.
*
* @param extras The extras to include.
* @return this
*/
public Builder setExtras(Bundle extras) {
mExtras = extras;
return this;
}
/**
* Build and return the {@link PlaybackState} instance with these
* values.
*
* @return A new state instance.
*/
public PlaybackState build() {
return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferedPosition,
mActions, mCustomActions, mActiveItemId, mErrorMessage, mExtras);
}
}
}
*
*/
@State
public int getState() {
return mState;
}
/**
* Get the current playback position in ms.
*/
public long getPosition() {
return mPosition;
}
/**
* Get the current buffered position in ms. This is the farthest playback
* point that can be reached from the current position using only buffered
* content.
*/
public long getBufferedPosition() {
return mBufferedPosition;
}
/**
* Get the current playback speed as a multiple of normal playback. This
* should be negative when rewinding. A value of 1 means normal playback and
* 0 means paused.
*
* @return The current speed of playback.
*/
public float getPlaybackSpeed() {
return mSpeed;
}
/**
* Get the current actions available on this session. This should use a
* bitmask of the available actions.
*
*
*/
@Actions
public long getActions() {
return mActions;
}
/**
* Get the list of custom actions.
*/
public List
*
*/
public boolean isActive() {
switch (mState) {
case PlaybackState.STATE_FAST_FORWARDING:
case PlaybackState.STATE_REWINDING:
case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
case PlaybackState.STATE_SKIPPING_TO_NEXT:
case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM:
case PlaybackState.STATE_BUFFERING:
case PlaybackState.STATE_CONNECTING:
case PlaybackState.STATE_PLAYING:
case PlaybackState.STATE_PLAYBACK_SUPPRESSED:
return true;
}
return false;
}
public static final @android.annotation.NonNull Parcelable.Creator
*
*
* @param state The current state of playback.
* @param position The position in the current item in ms.
* @param playbackSpeed The current speed of playback as a multiple of
* normal playback.
* @param updateTime The time in the {@link SystemClock#elapsedRealtime}
* timebase that the position was updated at.
* @return this
*/
public Builder setState(@State int state, long position, float playbackSpeed,
long updateTime) {
mState = state;
mPosition = position;
mUpdateTime = updateTime;
mSpeed = playbackSpeed;
return this;
}
/**
* Set the current state of playback.
*
*
*
* @param state The current state of playback.
* @param position The position in the current item in ms.
* @param playbackSpeed The current speed of playback as a multiple of
* normal playback.
* @return this
*/
public Builder setState(@State int state, long position, float playbackSpeed) {
return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime());
}
/**
* Set the current actions available on this session. This should use a
* bitmask of possible actions.
*
*
*
* @param actions The set of actions allowed.
* @return this
*/
public Builder setActions(@Actions long actions) {
mActions = actions;
return this;
}
/**
* Add a custom action to the playback state. Actions can be used to
* expose additional functionality to {@link MediaController
* MediaControllers} beyond what is offered by the standard transport
* controls.
*