• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 package android.media.session;
17 
18 import android.annotation.DrawableRes;
19 import android.annotation.IntDef;
20 import android.annotation.LongDef;
21 import android.annotation.Nullable;
22 import android.os.Bundle;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.os.SystemClock;
26 import android.text.TextUtils;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.util.ArrayList;
31 import java.util.List;
32 
33 /**
34  * Playback state for a {@link MediaSession}. This includes a state like
35  * {@link PlaybackState#STATE_PLAYING}, the current playback position,
36  * and the current control capabilities.
37  */
38 public final class PlaybackState implements Parcelable {
39     private static final String TAG = "PlaybackState";
40 
41     /**
42      * @hide
43      */
44     @LongDef(flag = true, value = {ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
45             ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
46             ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
47             ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
48             ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI,
49             ACTION_SET_PLAYBACK_SPEED})
50     @Retention(RetentionPolicy.SOURCE)
51     public @interface Actions {}
52 
53     /**
54      * Indicates this session supports the stop command.
55      *
56      * @see Builder#setActions(long)
57      */
58     public static final long ACTION_STOP = 1 << 0;
59 
60     /**
61      * Indicates this session supports the pause command.
62      *
63      * @see Builder#setActions(long)
64      */
65     public static final long ACTION_PAUSE = 1 << 1;
66 
67     /**
68      * Indicates this session supports the play command.
69      *
70      * @see Builder#setActions(long)
71      */
72     public static final long ACTION_PLAY = 1 << 2;
73 
74     /**
75      * Indicates this session supports the rewind command.
76      *
77      * @see Builder#setActions(long)
78      */
79     public static final long ACTION_REWIND = 1 << 3;
80 
81     /**
82      * Indicates this session supports the previous command.
83      *
84      * @see Builder#setActions(long)
85      */
86     public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4;
87 
88     /**
89      * Indicates this session supports the next command.
90      *
91      * @see Builder#setActions(long)
92      */
93     public static final long ACTION_SKIP_TO_NEXT = 1 << 5;
94 
95     /**
96      * Indicates this session supports the fast forward command.
97      *
98      * @see Builder#setActions(long)
99      */
100     public static final long ACTION_FAST_FORWARD = 1 << 6;
101 
102     /**
103      * Indicates this session supports the set rating command.
104      *
105      * @see Builder#setActions(long)
106      */
107     public static final long ACTION_SET_RATING = 1 << 7;
108 
109     /**
110      * Indicates this session supports the seek to command.
111      *
112      * @see Builder#setActions(long)
113      */
114     public static final long ACTION_SEEK_TO = 1 << 8;
115 
116     /**
117      * Indicates this session supports the play/pause toggle command.
118      *
119      * @see Builder#setActions(long)
120      */
121     public static final long ACTION_PLAY_PAUSE = 1 << 9;
122 
123     /**
124      * Indicates this session supports the play from media id command.
125      *
126      * @see Builder#setActions(long)
127      */
128     public static final long ACTION_PLAY_FROM_MEDIA_ID = 1 << 10;
129 
130     /**
131      * Indicates this session supports the play from search command.
132      *
133      * @see Builder#setActions(long)
134      */
135     public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11;
136 
137     /**
138      * Indicates this session supports the skip to queue item command.
139      *
140      * @see Builder#setActions(long)
141      */
142     public static final long ACTION_SKIP_TO_QUEUE_ITEM = 1 << 12;
143 
144     /**
145      * Indicates this session supports the play from URI command.
146      *
147      * @see Builder#setActions(long)
148      */
149     public static final long ACTION_PLAY_FROM_URI = 1 << 13;
150 
151     /**
152      * Indicates this session supports the prepare command.
153      *
154      * @see Builder#setActions(long)
155      */
156     public static final long ACTION_PREPARE = 1 << 14;
157 
158     /**
159      * Indicates this session supports the prepare from media id command.
160      *
161      * @see Builder#setActions(long)
162      */
163     public static final long ACTION_PREPARE_FROM_MEDIA_ID = 1 << 15;
164 
165     /**
166      * Indicates this session supports the prepare from search command.
167      *
168      * @see Builder#setActions(long)
169      */
170     public static final long ACTION_PREPARE_FROM_SEARCH = 1 << 16;
171 
172     /**
173      * Indicates this session supports the prepare from URI command.
174      *
175      * @see Builder#setActions(long)
176      */
177     public static final long ACTION_PREPARE_FROM_URI = 1 << 17;
178 
179     // Note: The value jumps from 1 << 17 to 1 << 22 for matching same value with AndroidX.
180     /**
181      * Indicates this session supports the set playback speed command.
182      *
183      * @see Builder#setActions(long)
184      */
185     public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22;
186 
187     /**
188      * @hide
189      */
190     @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING,
191             STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING,
192             STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM})
193     @Retention(RetentionPolicy.SOURCE)
194     public @interface State {}
195 
196     /**
197      * This is the default playback state and indicates that no media has been
198      * added yet, or the performer has been reset and has no content to play.
199      *
200      * @see Builder#setState(int, long, float)
201      * @see Builder#setState(int, long, float, long)
202      */
203     public static final int STATE_NONE = 0;
204 
205     /**
206      * State indicating this item is currently stopped.
207      *
208      * @see Builder#setState
209      */
210     public static final int STATE_STOPPED = 1;
211 
212     /**
213      * State indicating this item is currently paused.
214      *
215      * @see Builder#setState
216      */
217     public static final int STATE_PAUSED = 2;
218 
219     /**
220      * State indicating this item is currently playing.
221      *
222      * @see Builder#setState
223      */
224     public static final int STATE_PLAYING = 3;
225 
226     /**
227      * State indicating this item is currently fast forwarding.
228      *
229      * @see Builder#setState
230      */
231     public static final int STATE_FAST_FORWARDING = 4;
232 
233     /**
234      * State indicating this item is currently rewinding.
235      *
236      * @see Builder#setState
237      */
238     public static final int STATE_REWINDING = 5;
239 
240     /**
241      * State indicating this item is currently buffering and will begin playing
242      * when enough data has buffered.
243      *
244      * @see Builder#setState
245      */
246     public static final int STATE_BUFFERING = 6;
247 
248     /**
249      * State indicating this item is currently in an error state. The error
250      * message should also be set when entering this state.
251      *
252      * @see Builder#setState
253      */
254     public static final int STATE_ERROR = 7;
255 
256     /**
257      * State indicating the class doing playback is currently connecting to a
258      * new destination.  Depending on the implementation you may return to the previous
259      * state when the connection finishes or enter {@link #STATE_NONE}.
260      * If the connection failed {@link #STATE_ERROR} should be used.
261      *
262      * @see Builder#setState
263      */
264     public static final int STATE_CONNECTING = 8;
265 
266     /**
267      * State indicating the player is currently skipping to the previous item.
268      *
269      * @see Builder#setState
270      */
271     public static final int STATE_SKIPPING_TO_PREVIOUS = 9;
272 
273     /**
274      * State indicating the player is currently skipping to the next item.
275      *
276      * @see Builder#setState
277      */
278     public static final int STATE_SKIPPING_TO_NEXT = 10;
279 
280     /**
281      * State indicating the player is currently skipping to a specific item in
282      * the queue.
283      *
284      * @see Builder#setState
285      */
286     public static final int STATE_SKIPPING_TO_QUEUE_ITEM = 11;
287 
288     /**
289      * Use this value for the position to indicate the position is not known.
290      */
291     public static final long PLAYBACK_POSITION_UNKNOWN = -1;
292 
293     private final int mState;
294     private final long mPosition;
295     private final long mBufferedPosition;
296     private final float mSpeed;
297     private final long mActions;
298     private List<PlaybackState.CustomAction> mCustomActions;
299     private final CharSequence mErrorMessage;
300     private final long mUpdateTime;
301     private final long mActiveItemId;
302     private final Bundle mExtras;
303 
PlaybackState(int state, long position, long updateTime, float speed, long bufferedPosition, long transportControls, List<PlaybackState.CustomAction> customActions, long activeItemId, CharSequence error, Bundle extras)304     private PlaybackState(int state, long position, long updateTime, float speed,
305             long bufferedPosition, long transportControls,
306             List<PlaybackState.CustomAction> customActions, long activeItemId,
307             CharSequence error, Bundle extras) {
308         mState = state;
309         mPosition = position;
310         mSpeed = speed;
311         mUpdateTime = updateTime;
312         mBufferedPosition = bufferedPosition;
313         mActions = transportControls;
314         mCustomActions = new ArrayList<>(customActions);
315         mActiveItemId = activeItemId;
316         mErrorMessage = error;
317         mExtras = extras;
318     }
319 
PlaybackState(Parcel in)320     private PlaybackState(Parcel in) {
321         mState = in.readInt();
322         mPosition = in.readLong();
323         mSpeed = in.readFloat();
324         mUpdateTime = in.readLong();
325         mBufferedPosition = in.readLong();
326         mActions = in.readLong();
327         mCustomActions = in.createTypedArrayList(CustomAction.CREATOR);
328         mActiveItemId = in.readLong();
329         mErrorMessage = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
330         mExtras = in.readBundle();
331     }
332 
333     @Override
toString()334     public String toString() {
335         StringBuilder bob = new StringBuilder("PlaybackState {");
336         bob.append("state=").append(mState);
337         bob.append(", position=").append(mPosition);
338         bob.append(", buffered position=").append(mBufferedPosition);
339         bob.append(", speed=").append(mSpeed);
340         bob.append(", updated=").append(mUpdateTime);
341         bob.append(", actions=").append(mActions);
342         bob.append(", custom actions=").append(mCustomActions);
343         bob.append(", active item id=").append(mActiveItemId);
344         bob.append(", error=").append(mErrorMessage);
345         bob.append("}");
346         return bob.toString();
347     }
348 
349     @Override
describeContents()350     public int describeContents() {
351         return 0;
352     }
353 
354     @Override
writeToParcel(Parcel dest, int flags)355     public void writeToParcel(Parcel dest, int flags) {
356         dest.writeInt(mState);
357         dest.writeLong(mPosition);
358         dest.writeFloat(mSpeed);
359         dest.writeLong(mUpdateTime);
360         dest.writeLong(mBufferedPosition);
361         dest.writeLong(mActions);
362         dest.writeTypedList(mCustomActions);
363         dest.writeLong(mActiveItemId);
364         TextUtils.writeToParcel(mErrorMessage, dest, 0);
365         dest.writeBundle(mExtras);
366     }
367 
368     /**
369      * Get the current state of playback. One of the following:
370      * <ul>
371      * <li> {@link PlaybackState#STATE_NONE}</li>
372      * <li> {@link PlaybackState#STATE_STOPPED}</li>
373      * <li> {@link PlaybackState#STATE_PLAYING}</li>
374      * <li> {@link PlaybackState#STATE_PAUSED}</li>
375      * <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
376      * <li> {@link PlaybackState#STATE_REWINDING}</li>
377      * <li> {@link PlaybackState#STATE_BUFFERING}</li>
378      * <li> {@link PlaybackState#STATE_ERROR}</li>
379      * <li> {@link PlaybackState#STATE_CONNECTING}</li>
380      * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
381      * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
382      * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
383      * </ul>
384      */
385     @State
getState()386     public int getState() {
387         return mState;
388     }
389 
390     /**
391      * Get the current playback position in ms.
392      */
getPosition()393     public long getPosition() {
394         return mPosition;
395     }
396 
397     /**
398      * Get the current buffered position in ms. This is the farthest playback
399      * point that can be reached from the current position using only buffered
400      * content.
401      */
getBufferedPosition()402     public long getBufferedPosition() {
403         return mBufferedPosition;
404     }
405 
406     /**
407      * Get the current playback speed as a multiple of normal playback. This
408      * should be negative when rewinding. A value of 1 means normal playback and
409      * 0 means paused.
410      *
411      * @return The current speed of playback.
412      */
getPlaybackSpeed()413     public float getPlaybackSpeed() {
414         return mSpeed;
415     }
416 
417     /**
418      * Get the current actions available on this session. This should use a
419      * bitmask of the available actions.
420      * <ul>
421      * <li> {@link PlaybackState#ACTION_SKIP_TO_PREVIOUS}</li>
422      * <li> {@link PlaybackState#ACTION_REWIND}</li>
423      * <li> {@link PlaybackState#ACTION_PLAY}</li>
424      * <li> {@link PlaybackState#ACTION_PAUSE}</li>
425      * <li> {@link PlaybackState#ACTION_STOP}</li>
426      * <li> {@link PlaybackState#ACTION_FAST_FORWARD}</li>
427      * <li> {@link PlaybackState#ACTION_SKIP_TO_NEXT}</li>
428      * <li> {@link PlaybackState#ACTION_SEEK_TO}</li>
429      * <li> {@link PlaybackState#ACTION_SET_RATING}</li>
430      * <li> {@link PlaybackState#ACTION_PLAY_PAUSE}</li>
431      * <li> {@link PlaybackState#ACTION_PLAY_FROM_MEDIA_ID}</li>
432      * <li> {@link PlaybackState#ACTION_PLAY_FROM_SEARCH}</li>
433      * <li> {@link PlaybackState#ACTION_SKIP_TO_QUEUE_ITEM}</li>
434      * <li> {@link PlaybackState#ACTION_PLAY_FROM_URI}</li>
435      * <li> {@link PlaybackState#ACTION_PREPARE}</li>
436      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li>
437      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li>
438      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
439      * <li> {@link PlaybackState#ACTION_SET_PLAYBACK_SPEED}</li>
440      * </ul>
441      */
442     @Actions
getActions()443     public long getActions() {
444         return mActions;
445     }
446 
447     /**
448      * Get the list of custom actions.
449      */
getCustomActions()450     public List<PlaybackState.CustomAction> getCustomActions() {
451         return mCustomActions;
452     }
453 
454     /**
455      * Get a user readable error message. This should be set when the state is
456      * {@link PlaybackState#STATE_ERROR}.
457      */
getErrorMessage()458     public CharSequence getErrorMessage() {
459         return mErrorMessage;
460     }
461 
462     /**
463      * Get the elapsed real time at which position was last updated. If the
464      * position has never been set this will return 0;
465      *
466      * @return The last time the position was updated.
467      */
getLastPositionUpdateTime()468     public long getLastPositionUpdateTime() {
469         return mUpdateTime;
470     }
471 
472     /**
473      * Get the id of the currently active item in the queue. If there is no
474      * queue or a queue is not supported by the session this will be
475      * {@link MediaSession.QueueItem#UNKNOWN_ID}.
476      *
477      * @return The id of the currently active item in the queue or
478      *         {@link MediaSession.QueueItem#UNKNOWN_ID}.
479      */
getActiveQueueItemId()480     public long getActiveQueueItemId() {
481         return mActiveItemId;
482     }
483 
484     /**
485      * Get any custom extras that were set on this playback state.
486      *
487      * @return The extras for this state or null.
488      */
getExtras()489     public @Nullable Bundle getExtras() {
490         return mExtras;
491     }
492 
493     /**
494      * Returns whether this is considered as an active playback state.
495      * <p>
496      * The playback state is considered as an active if the state is one of the following:
497      * <ul>
498      * <li>{@link #STATE_BUFFERING}</li>
499      * <li>{@link #STATE_CONNECTING}</li>
500      * <li>{@link #STATE_FAST_FORWARDING}</li>
501      * <li>{@link #STATE_PLAYING}</li>
502      * <li>{@link #STATE_REWINDING}</li>
503      * <li>{@link #STATE_SKIPPING_TO_NEXT}</li>
504      * <li>{@link #STATE_SKIPPING_TO_PREVIOUS}</li>
505      * <li>{@link #STATE_SKIPPING_TO_QUEUE_ITEM}</li>
506      * </ul>
507      */
isActive()508     public boolean isActive() {
509         switch (mState) {
510             case PlaybackState.STATE_FAST_FORWARDING:
511             case PlaybackState.STATE_REWINDING:
512             case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
513             case PlaybackState.STATE_SKIPPING_TO_NEXT:
514             case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM:
515             case PlaybackState.STATE_BUFFERING:
516             case PlaybackState.STATE_CONNECTING:
517             case PlaybackState.STATE_PLAYING:
518                 return true;
519         }
520         return false;
521     }
522 
523     public static final @android.annotation.NonNull Parcelable.Creator<PlaybackState> CREATOR =
524             new Parcelable.Creator<PlaybackState>() {
525         @Override
526         public PlaybackState createFromParcel(Parcel in) {
527             return new PlaybackState(in);
528         }
529 
530         @Override
531         public PlaybackState[] newArray(int size) {
532             return new PlaybackState[size];
533         }
534     };
535 
536     /**
537      * {@link PlaybackState.CustomAction CustomActions} can be used to extend the capabilities of
538      * the standard transport controls by exposing app specific actions to
539      * {@link MediaController MediaControllers}.
540      */
541     public static final class CustomAction implements Parcelable {
542         private final String mAction;
543         private final CharSequence mName;
544         private final int mIcon;
545         private final Bundle mExtras;
546 
547         /**
548          * Use {@link PlaybackState.CustomAction.Builder#build()}.
549          */
CustomAction(String action, CharSequence name, int icon, Bundle extras)550         private CustomAction(String action, CharSequence name, int icon, Bundle extras) {
551             mAction = action;
552             mName = name;
553             mIcon = icon;
554             mExtras = extras;
555         }
556 
CustomAction(Parcel in)557         private CustomAction(Parcel in) {
558             mAction = in.readString();
559             mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
560             mIcon = in.readInt();
561             mExtras = in.readBundle();
562         }
563 
564         @Override
writeToParcel(Parcel dest, int flags)565         public void writeToParcel(Parcel dest, int flags) {
566             dest.writeString(mAction);
567             TextUtils.writeToParcel(mName, dest, flags);
568             dest.writeInt(mIcon);
569             dest.writeBundle(mExtras);
570         }
571 
572         @Override
describeContents()573         public int describeContents() {
574             return 0;
575         }
576 
577         public static final @android.annotation.NonNull Parcelable.Creator<PlaybackState.CustomAction> CREATOR =
578                 new Parcelable.Creator<PlaybackState.CustomAction>() {
579 
580                     @Override
581                     public PlaybackState.CustomAction createFromParcel(Parcel p) {
582                         return new PlaybackState.CustomAction(p);
583                     }
584 
585                     @Override
586                     public PlaybackState.CustomAction[] newArray(int size) {
587                         return new PlaybackState.CustomAction[size];
588                     }
589                 };
590 
591         /**
592          * Returns the action of the {@link CustomAction}.
593          *
594          * @return The action of the {@link CustomAction}.
595          */
getAction()596         public String getAction() {
597             return mAction;
598         }
599 
600         /**
601          * Returns the display name of this action. e.g. "Favorite"
602          *
603          * @return The display name of this {@link CustomAction}.
604          */
getName()605         public CharSequence getName() {
606             return mName;
607         }
608 
609         /**
610          * Returns the resource id of the icon in the {@link MediaSession MediaSession's} package.
611          *
612          * @return The resource id of the icon in the {@link MediaSession MediaSession's} package.
613          */
getIcon()614         public int getIcon() {
615             return mIcon;
616         }
617 
618         /**
619          * Returns extras which provide additional application-specific information about the
620          * action, or null if none. These arguments are meant to be consumed by a
621          * {@link MediaController} if it knows how to handle them.
622          *
623          * @return Optional arguments for the {@link CustomAction}.
624          */
getExtras()625         public Bundle getExtras() {
626             return mExtras;
627         }
628 
629         @Override
toString()630         public String toString() {
631             return "Action:" + "mName='" + mName + ", mIcon=" + mIcon + ", mExtras=" + mExtras;
632         }
633 
634         /**
635          * Builder for {@link CustomAction} objects.
636          */
637         public static final class Builder {
638             private final String mAction;
639             private final CharSequence mName;
640             private final int mIcon;
641             private Bundle mExtras;
642 
643             /**
644              * Creates a {@link CustomAction} builder with the id, name, and icon set.
645              *
646              * @param action The action of the {@link CustomAction}.
647              * @param name The display name of the {@link CustomAction}. This name will be displayed
648              *             along side the action if the UI supports it.
649              * @param icon The icon resource id of the {@link CustomAction}. This resource id
650              *             must be in the same package as the {@link MediaSession}. It will be
651              *             displayed with the custom action if the UI supports it.
652              */
Builder(String action, CharSequence name, @DrawableRes int icon)653             public Builder(String action, CharSequence name, @DrawableRes int icon) {
654                 if (TextUtils.isEmpty(action)) {
655                     throw new IllegalArgumentException(
656                             "You must specify an action to build a CustomAction.");
657                 }
658                 if (TextUtils.isEmpty(name)) {
659                     throw new IllegalArgumentException(
660                             "You must specify a name to build a CustomAction.");
661                 }
662                 if (icon == 0) {
663                     throw new IllegalArgumentException(
664                             "You must specify an icon resource id to build a CustomAction.");
665                 }
666                 mAction = action;
667                 mName = name;
668                 mIcon = icon;
669             }
670 
671             /**
672              * Set optional extras for the {@link CustomAction}. These extras are meant to be
673              * consumed by a {@link MediaController} if it knows how to handle them.
674              * Keys should be fully qualified (e.g. "com.example.MY_ARG") to avoid collisions.
675              *
676              * @param extras Optional extras for the {@link CustomAction}.
677              * @return this.
678              */
setExtras(Bundle extras)679             public Builder setExtras(Bundle extras) {
680                 mExtras = extras;
681                 return this;
682             }
683 
684             /**
685              * Build and return the {@link CustomAction} instance with the specified values.
686              *
687              * @return A new {@link CustomAction} instance.
688              */
build()689             public CustomAction build() {
690                 return new CustomAction(mAction, mName, mIcon, mExtras);
691             }
692         }
693     }
694 
695     /**
696      * Builder for {@link PlaybackState} objects.
697      */
698     public static final class Builder {
699         private final List<PlaybackState.CustomAction> mCustomActions = new ArrayList<>();
700 
701         private int mState;
702         private long mPosition;
703         private long mBufferedPosition;
704         private float mSpeed;
705         private long mActions;
706         private CharSequence mErrorMessage;
707         private long mUpdateTime;
708         private long mActiveItemId = MediaSession.QueueItem.UNKNOWN_ID;
709         private Bundle mExtras;
710 
711         /**
712          * Creates an initially empty state builder.
713          */
Builder()714         public Builder() {
715         }
716 
717         /**
718          * Creates a builder with the same initial values as those in the from
719          * state.
720          *
721          * @param from The state to use for initializing the builder.
722          */
Builder(PlaybackState from)723         public Builder(PlaybackState from) {
724             if (from == null) {
725                 return;
726             }
727             mState = from.mState;
728             mPosition = from.mPosition;
729             mBufferedPosition = from.mBufferedPosition;
730             mSpeed = from.mSpeed;
731             mActions = from.mActions;
732             if (from.mCustomActions != null) {
733                 mCustomActions.addAll(from.mCustomActions);
734             }
735             mErrorMessage = from.mErrorMessage;
736             mUpdateTime = from.mUpdateTime;
737             mActiveItemId = from.mActiveItemId;
738             mExtras = from.mExtras;
739         }
740 
741         /**
742          * Set the current state of playback.
743          * <p>
744          * The position must be in ms and indicates the current playback
745          * position within the item. If the position is unknown use
746          * {@link #PLAYBACK_POSITION_UNKNOWN}. When not using an unknown
747          * position the time at which the position was updated must be provided.
748          * It is okay to use {@link SystemClock#elapsedRealtime()} if the
749          * current position was just retrieved.
750          * <p>
751          * The speed is a multiple of normal playback and should be 0 when
752          * paused and negative when rewinding. Normal playback speed is 1.0.
753          * <p>
754          * The state must be one of the following:
755          * <ul>
756          * <li> {@link PlaybackState#STATE_NONE}</li>
757          * <li> {@link PlaybackState#STATE_STOPPED}</li>
758          * <li> {@link PlaybackState#STATE_PLAYING}</li>
759          * <li> {@link PlaybackState#STATE_PAUSED}</li>
760          * <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
761          * <li> {@link PlaybackState#STATE_REWINDING}</li>
762          * <li> {@link PlaybackState#STATE_BUFFERING}</li>
763          * <li> {@link PlaybackState#STATE_ERROR}</li>
764          * <li> {@link PlaybackState#STATE_CONNECTING}</li>
765          * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
766          * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
767          * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
768          * </ul>
769          *
770          * @param state The current state of playback.
771          * @param position The position in the current item in ms.
772          * @param playbackSpeed The current speed of playback as a multiple of
773          *            normal playback.
774          * @param updateTime The time in the {@link SystemClock#elapsedRealtime}
775          *            timebase that the position was updated at.
776          * @return this
777          */
setState(@tate int state, long position, float playbackSpeed, long updateTime)778         public Builder setState(@State int state, long position, float playbackSpeed,
779                 long updateTime) {
780             mState = state;
781             mPosition = position;
782             mUpdateTime = updateTime;
783             mSpeed = playbackSpeed;
784             return this;
785         }
786 
787         /**
788          * Set the current state of playback.
789          * <p>
790          * The position must be in ms and indicates the current playback
791          * position within the item. If the position is unknown use
792          * {@link #PLAYBACK_POSITION_UNKNOWN}. The update time will be set to
793          * the current {@link SystemClock#elapsedRealtime()}.
794          * <p>
795          * The speed is a multiple of normal playback and should be 0 when
796          * paused and negative when rewinding. Normal playback speed is 1.0.
797          * <p>
798          * The state must be one of the following:
799          * <ul>
800          * <li> {@link PlaybackState#STATE_NONE}</li>
801          * <li> {@link PlaybackState#STATE_STOPPED}</li>
802          * <li> {@link PlaybackState#STATE_PLAYING}</li>
803          * <li> {@link PlaybackState#STATE_PAUSED}</li>
804          * <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
805          * <li> {@link PlaybackState#STATE_REWINDING}</li>
806          * <li> {@link PlaybackState#STATE_BUFFERING}</li>
807          * <li> {@link PlaybackState#STATE_ERROR}</li>
808          * <li> {@link PlaybackState#STATE_CONNECTING}</li>
809          * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
810          * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
811          * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
812          * </ul>
813          *
814          * @param state The current state of playback.
815          * @param position The position in the current item in ms.
816          * @param playbackSpeed The current speed of playback as a multiple of
817          *            normal playback.
818          * @return this
819          */
setState(@tate int state, long position, float playbackSpeed)820         public Builder setState(@State int state, long position, float playbackSpeed) {
821             return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime());
822         }
823 
824         /**
825          * Set the current actions available on this session. This should use a
826          * bitmask of possible actions.
827          * <ul>
828          * <li> {@link PlaybackState#ACTION_SKIP_TO_PREVIOUS}</li>
829          * <li> {@link PlaybackState#ACTION_REWIND}</li>
830          * <li> {@link PlaybackState#ACTION_PLAY}</li>
831          * <li> {@link PlaybackState#ACTION_PAUSE}</li>
832          * <li> {@link PlaybackState#ACTION_STOP}</li>
833          * <li> {@link PlaybackState#ACTION_FAST_FORWARD}</li>
834          * <li> {@link PlaybackState#ACTION_SKIP_TO_NEXT}</li>
835          * <li> {@link PlaybackState#ACTION_SEEK_TO}</li>
836          * <li> {@link PlaybackState#ACTION_SET_RATING}</li>
837          * <li> {@link PlaybackState#ACTION_PLAY_PAUSE}</li>
838          * <li> {@link PlaybackState#ACTION_PLAY_FROM_MEDIA_ID}</li>
839          * <li> {@link PlaybackState#ACTION_PLAY_FROM_SEARCH}</li>
840          * <li> {@link PlaybackState#ACTION_SKIP_TO_QUEUE_ITEM}</li>
841          * <li> {@link PlaybackState#ACTION_PLAY_FROM_URI}</li>
842          * <li> {@link PlaybackState#ACTION_PREPARE}</li>
843          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li>
844          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li>
845          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
846          * <li> {@link PlaybackState#ACTION_SET_PLAYBACK_SPEED}</li>
847          * </ul>
848          *
849          * @param actions The set of actions allowed.
850          * @return this
851          */
setActions(@ctions long actions)852         public Builder setActions(@Actions long actions) {
853             mActions = actions;
854             return this;
855         }
856 
857         /**
858          * Add a custom action to the playback state. Actions can be used to
859          * expose additional functionality to {@link MediaController
860          * MediaControllers} beyond what is offered by the standard transport
861          * controls.
862          * <p>
863          * e.g. start a radio station based on the current item or skip ahead by
864          * 30 seconds.
865          *
866          * @param action An identifier for this action. It can be sent back to
867          *            the {@link MediaSession} through
868          *            {@link MediaController.TransportControls#sendCustomAction(String, Bundle)}.
869          * @param name The display name for the action. If text is shown with
870          *            the action or used for accessibility, this is what should
871          *            be used.
872          * @param icon The resource action of the icon that should be displayed
873          *            for the action. The resource should be in the package of
874          *            the {@link MediaSession}.
875          * @return this
876          */
addCustomAction(String action, String name, int icon)877         public Builder addCustomAction(String action, String name, int icon) {
878             return addCustomAction(new PlaybackState.CustomAction(action, name, icon, null));
879         }
880 
881         /**
882          * Add a custom action to the playback state. Actions can be used to expose additional
883          * functionality to {@link MediaController MediaControllers} beyond what is offered by the
884          * standard transport controls.
885          * <p>
886          * An example of an action would be to start a radio station based on the current item
887          * or to skip ahead by 30 seconds.
888          *
889          * @param customAction The custom action to add to the {@link PlaybackState}.
890          * @return this
891          */
addCustomAction(PlaybackState.CustomAction customAction)892         public Builder addCustomAction(PlaybackState.CustomAction customAction) {
893             if (customAction == null) {
894                 throw new IllegalArgumentException(
895                         "You may not add a null CustomAction to PlaybackState.");
896             }
897             mCustomActions.add(customAction);
898             return this;
899         }
900 
901         /**
902          * Set the current buffered position in ms. This is the farthest
903          * playback point that can be reached from the current position using
904          * only buffered content.
905          *
906          * @param bufferedPosition The position in ms that playback is buffered
907          *            to.
908          * @return this
909          */
setBufferedPosition(long bufferedPosition)910         public Builder setBufferedPosition(long bufferedPosition) {
911             mBufferedPosition = bufferedPosition;
912             return this;
913         }
914 
915         /**
916          * Set the active item in the play queue by specifying its id. The
917          * default value is {@link MediaSession.QueueItem#UNKNOWN_ID}
918          *
919          * @param id The id of the active item.
920          * @return this
921          */
setActiveQueueItemId(long id)922         public Builder setActiveQueueItemId(long id) {
923             mActiveItemId = id;
924             return this;
925         }
926 
927         /**
928          * Set a user readable error message. This should be set when the state
929          * is {@link PlaybackState#STATE_ERROR}.
930          *
931          * @param error The error message for display to the user.
932          * @return this
933          */
setErrorMessage(CharSequence error)934         public Builder setErrorMessage(CharSequence error) {
935             mErrorMessage = error;
936             return this;
937         }
938 
939         /**
940          * Set any custom extras to be included with the playback state.
941          *
942          * @param extras The extras to include.
943          * @return this
944          */
setExtras(Bundle extras)945         public Builder setExtras(Bundle extras) {
946             mExtras = extras;
947             return this;
948         }
949 
950         /**
951          * Build and return the {@link PlaybackState} instance with these
952          * values.
953          *
954          * @return A new state instance.
955          */
build()956         public PlaybackState build() {
957             return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferedPosition,
958                     mActions, mCustomActions, mActiveItemId, mErrorMessage, mExtras);
959         }
960     }
961 }
962