PlaybackStateCompat.java revision 024c5c4a5f04a2201a92cb3538648396da3f8c9d
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 */
16package android.support.v4.media.session;
17
18import android.os.Build;
19import android.os.Bundle;
20import android.os.Parcel;
21import android.os.Parcelable;
22import android.os.SystemClock;
23import android.text.TextUtils;
24
25/**
26 * Playback state for a {@link MediaSessionCompat}. This includes a state like
27 * {@link PlaybackStateCompat#STATE_PLAYING}, the current playback position,
28 * and the current control capabilities.
29 */
30public final class PlaybackStateCompat implements Parcelable {
31
32    /**
33     * Indicates this session supports the stop command.
34     *
35     * @see Builder#setActions(long)
36     */
37    public static final long ACTION_STOP = 1 << 0;
38
39    /**
40     * Indicates this session supports the pause command.
41     *
42     * @see Builder#setActions(long)
43     */
44    public static final long ACTION_PAUSE = 1 << 1;
45
46    /**
47     * Indicates this session supports the play command.
48     *
49     * @see Builder#setActions(long)
50     */
51    public static final long ACTION_PLAY = 1 << 2;
52
53    /**
54     * Indicates this session supports the rewind command.
55     *
56     * @see Builder#setActions(long)
57     */
58    public static final long ACTION_REWIND = 1 << 3;
59
60    /**
61     * Indicates this session supports the previous command.
62     *
63     * @see Builder#setActions(long)
64     */
65    public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4;
66
67    /**
68     * Indicates this session supports the next command.
69     *
70     * @see Builder#setActions(long)
71     */
72    public static final long ACTION_SKIP_TO_NEXT = 1 << 5;
73
74    /**
75     * Indicates this session supports the fast forward command.
76     *
77     * @see Builder#setActions(long)
78     */
79    public static final long ACTION_FAST_FORWARD = 1 << 6;
80
81    /**
82     * Indicates this session supports the set rating command.
83     *
84     * @see Builder#setActions(long)
85     */
86    public static final long ACTION_SET_RATING = 1 << 7;
87
88    /**
89     * Indicates this session supports the seek to command.
90     *
91     * @see Builder#setActions(long)
92     */
93    public static final long ACTION_SEEK_TO = 1 << 8;
94
95    /**
96     * Indicates this session supports the play/pause toggle command.
97     *
98     * @see Builder#setActions(long)
99     */
100    public static final long ACTION_PLAY_PAUSE = 1 << 9;
101
102    /**
103     * Indicates this session supports the play from media id command.
104     *
105     * @see Builder#setActions(long)
106     */
107    public static final long ACTION_PLAY_FROM_MEDIA_ID = 1 << 10;
108
109    /**
110     * Indicates this session supports the play from search command.
111     *
112     * @see Builder#setActions(long)
113     */
114    public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11;
115
116    /**
117     * Indicates this session supports the skip to queue item command.
118     *
119     * @see Builder#setActions(long)
120     */
121    public static final long ACTION_SKIP_TO_QUEUE_ITEM = 1 << 12;
122
123    /**
124     * This is the default playback state and indicates that no media has been
125     * added yet, or the performer has been reset and has no content to play.
126     *
127     * @see Builder#setState
128     */
129    public final static int STATE_NONE = 0;
130
131    /**
132     * State indicating this item is currently stopped.
133     *
134     * @see Builder#setState
135     */
136    public final static int STATE_STOPPED = 1;
137
138    /**
139     * State indicating this item is currently paused.
140     *
141     * @see Builder#setState
142     */
143    public final static int STATE_PAUSED = 2;
144
145    /**
146     * State indicating this item is currently playing.
147     *
148     * @see Builder#setState
149     */
150    public final static int STATE_PLAYING = 3;
151
152    /**
153     * State indicating this item is currently fast forwarding.
154     *
155     * @see Builder#setState
156     */
157    public final static int STATE_FAST_FORWARDING = 4;
158
159    /**
160     * State indicating this item is currently rewinding.
161     *
162     * @see Builder#setState
163     */
164    public final static int STATE_REWINDING = 5;
165
166    /**
167     * State indicating this item is currently buffering and will begin playing
168     * when enough data has buffered.
169     *
170     * @see Builder#setState
171     */
172    public final static int STATE_BUFFERING = 6;
173
174    /**
175     * State indicating this item is currently in an error state. The error
176     * message should also be set when entering this state.
177     *
178     * @see Builder#setState
179     */
180    public final static int STATE_ERROR = 7;
181
182    /**
183     * State indicating the class doing playback is currently connecting to a
184     * route. Depending on the implementation you may return to the previous
185     * state when the connection finishes or enter {@link #STATE_NONE}. If
186     * the connection failed {@link #STATE_ERROR} should be used.
187     * @hide
188     */
189    public final static int STATE_CONNECTING = 8;
190
191    /**
192     * State indicating the player is currently skipping to the previous item.
193     *
194     * @see Builder#setState
195     */
196    public final static int STATE_SKIPPING_TO_PREVIOUS = 9;
197
198    /**
199     * State indicating the player is currently skipping to the next item.
200     *
201     * @see Builder#setState
202     */
203    public final static int STATE_SKIPPING_TO_NEXT = 10;
204
205    /**
206     * Use this value for the position to indicate the position is not known.
207     */
208    public final static long PLAYBACK_POSITION_UNKNOWN = -1;
209
210    private final int mState;
211    private final long mPosition;
212    private final long mBufferedPosition;
213    private final float mSpeed;
214    private final long mActions;
215    private final CharSequence mErrorMessage;
216    private final long mUpdateTime;
217
218    private Object mStateObj;
219
220    private PlaybackStateCompat(int state, long position, long bufferedPosition,
221            float rate, long actions, CharSequence errorMessage, long updateTime) {
222        mState = state;
223        mPosition = position;
224        mBufferedPosition = bufferedPosition;
225        mSpeed = rate;
226        mActions = actions;
227        mErrorMessage = errorMessage;
228        mUpdateTime = updateTime;
229    }
230
231    private PlaybackStateCompat(Parcel in) {
232        mState = in.readInt();
233        mPosition = in.readLong();
234        mSpeed = in.readFloat();
235        mUpdateTime = in.readLong();
236        mBufferedPosition = in.readLong();
237        mActions = in.readLong();
238        mErrorMessage = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
239    }
240
241    @Override
242    public String toString() {
243        StringBuilder bob = new StringBuilder("PlaybackState {");
244        bob.append("state=").append(mState);
245        bob.append(", position=").append(mPosition);
246        bob.append(", buffered position=").append(mBufferedPosition);
247        bob.append(", speed=").append(mSpeed);
248        bob.append(", updated=").append(mUpdateTime);
249        bob.append(", actions=").append(mActions);
250        bob.append(", error=").append(mErrorMessage);
251        bob.append("}");
252        return bob.toString();
253    }
254
255    @Override
256    public int describeContents() {
257        return 0;
258    }
259
260    @Override
261    public void writeToParcel(Parcel dest, int flags) {
262        dest.writeInt(mState);
263        dest.writeLong(mPosition);
264        dest.writeFloat(mSpeed);
265        dest.writeLong(mUpdateTime);
266        dest.writeLong(mBufferedPosition);
267        dest.writeLong(mActions);
268        TextUtils.writeToParcel(mErrorMessage, dest, flags);
269    }
270
271    /**
272     * Get the current state of playback. One of the following:
273     * <ul>
274     * <li> {@link PlaybackStateCompat#STATE_NONE}</li>
275     * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li>
276     * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li>
277     * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li>
278     * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li>
279     * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li>
280     * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li>
281     * <li> {@link PlaybackStateCompat#STATE_ERROR}</li>
282     */
283    public int getState() {
284        return mState;
285    }
286
287    /**
288     * Get the current playback position in ms.
289     */
290    public long getPosition() {
291        return mPosition;
292    }
293
294    /**
295     * Get the current buffered position in ms. This is the farthest playback
296     * point that can be reached from the current position using only buffered
297     * content.
298     */
299    public long getBufferedPosition() {
300        return mBufferedPosition;
301    }
302
303    /**
304     * Get the current playback speed as a multiple of normal playback. This
305     * should be negative when rewinding. A value of 1 means normal playback and
306     * 0 means paused.
307     *
308     * @return The current speed of playback.
309     */
310    public float getPlaybackSpeed() {
311        return mSpeed;
312    }
313
314    /**
315     * Get the current actions available on this session. This should use a
316     * bitmask of the available actions.
317     * <ul>
318     * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li>
319     * <li> {@link PlaybackStateCompat#ACTION_REWIND}</li>
320     * <li> {@link PlaybackStateCompat#ACTION_PLAY}</li>
321     * <li> {@link PlaybackStateCompat#ACTION_PLAY_PAUSE}</li>
322     * <li> {@link PlaybackStateCompat#ACTION_PAUSE}</li>
323     * <li> {@link PlaybackStateCompat#ACTION_STOP}</li>
324     * <li> {@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li>
325     * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li>
326     * <li> {@link PlaybackStateCompat#ACTION_SEEK_TO}</li>
327     * <li> {@link PlaybackStateCompat#ACTION_SET_RATING}</li>
328     * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_MEDIA_ID}</li>
329     * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_SEARCH}</li>
330     * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_QUEUE_ITEM}</li>
331     * </ul>
332     */
333    public long getActions() {
334        return mActions;
335    }
336
337    /**
338     * Get a user readable error message. This should be set when the state is
339     * {@link PlaybackStateCompat#STATE_ERROR}.
340     */
341    public CharSequence getErrorMessage() {
342        return mErrorMessage;
343    }
344
345    /**
346     * Get the elapsed real time at which position was last updated. If the
347     * position has never been set this will return 0;
348     *
349     * @return The last time the position was updated.
350     */
351    public long getLastPositionUpdateTime() {
352        return mUpdateTime;
353    }
354
355    /**
356     * Creates an instance from a framework {@link android.media.session.PlaybackState} object.
357     * <p>
358     * This method is only supported on API 21+.
359     * </p>
360     *
361     * @param stateObj A {@link android.media.session.PlaybackState} object, or null if none.
362     * @return An equivalent {@link PlaybackStateCompat} object, or null if none.
363     */
364    public static PlaybackStateCompat fromPlaybackState(Object stateObj) {
365        if (stateObj == null || Build.VERSION.SDK_INT < 21) {
366            return null;
367        }
368
369        PlaybackStateCompat state = new PlaybackStateCompat(
370                PlaybackStateCompatApi21.getState(stateObj),
371                PlaybackStateCompatApi21.getPosition(stateObj),
372                PlaybackStateCompatApi21.getBufferedPosition(stateObj),
373                PlaybackStateCompatApi21.getPlaybackSpeed(stateObj),
374                PlaybackStateCompatApi21.getActions(stateObj),
375                PlaybackStateCompatApi21.getErrorMessage(stateObj),
376                PlaybackStateCompatApi21.getLastPositionUpdateTime(stateObj));
377        state.mStateObj = stateObj;
378        return state;
379    }
380
381    /**
382     * Gets the underlying framework {@link android.media.session.PlaybackState} object.
383     * <p>
384     * This method is only supported on API 21+.
385     * </p>
386     *
387     * @return An equivalent {@link android.media.session.PlaybackState} object, or null if none.
388     */
389    public Object getPlaybackState() {
390        if (mStateObj != null || Build.VERSION.SDK_INT < 21) {
391            return mStateObj;
392        }
393
394        mStateObj = PlaybackStateCompatApi21.newInstance(mState, mPosition, mBufferedPosition,
395                mSpeed, mActions, mErrorMessage, mUpdateTime);
396        return mStateObj;
397    }
398
399    public static final Parcelable.Creator<PlaybackStateCompat> CREATOR =
400            new Parcelable.Creator<PlaybackStateCompat>() {
401        @Override
402        public PlaybackStateCompat createFromParcel(Parcel in) {
403            return new PlaybackStateCompat(in);
404        }
405
406        @Override
407        public PlaybackStateCompat[] newArray(int size) {
408            return new PlaybackStateCompat[size];
409        }
410    };
411
412    /**
413     * {@link PlaybackStateCompat.CustomAction CustomActions} can be used to
414     * extend the capabilities of the standard transport controls by exposing
415     * app specific actions to {@link MediaControllerCompat Controllers}.
416     */
417    public static final class CustomAction implements Parcelable {
418        private final String mAction;
419        private final CharSequence mName;
420        private final int mIcon;
421        private final Bundle mExtras;
422
423        /**
424         * Use {@link PlaybackStateCompat.CustomAction.Builder#build()}.
425         */
426        private CustomAction(String action, CharSequence name, int icon, Bundle extras) {
427            mAction = action;
428            mName = name;
429            mIcon = icon;
430            mExtras = extras;
431        }
432
433        private CustomAction(Parcel in) {
434            mAction = in.readString();
435            mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
436            mIcon = in.readInt();
437            mExtras = in.readBundle();
438        }
439
440        @Override
441        public void writeToParcel(Parcel dest, int flags) {
442            dest.writeString(mAction);
443            TextUtils.writeToParcel(mName, dest, flags);
444            dest.writeInt(mIcon);
445            dest.writeBundle(mExtras);
446        }
447
448        @Override
449        public int describeContents() {
450            return 0;
451        }
452
453        public static final Parcelable.Creator<PlaybackStateCompat.CustomAction> CREATOR
454                = new Parcelable.Creator<PlaybackStateCompat.CustomAction>() {
455
456                    @Override
457                    public PlaybackStateCompat.CustomAction createFromParcel(Parcel p) {
458                        return new PlaybackStateCompat.CustomAction(p);
459                    }
460
461                    @Override
462                    public PlaybackStateCompat.CustomAction[] newArray(int size) {
463                        return new PlaybackStateCompat.CustomAction[size];
464                    }
465                };
466
467        /**
468         * Returns the action of the {@link CustomAction}.
469         *
470         * @return The action of the {@link CustomAction}.
471         */
472        public String getAction() {
473            return mAction;
474        }
475
476        /**
477         * Returns the display name of this action. e.g. "Favorite"
478         *
479         * @return The display name of this {@link CustomAction}.
480         */
481        public CharSequence getName() {
482            return mName;
483        }
484
485        /**
486         * Returns the resource id of the icon in the {@link MediaSessionCompat
487         * Session's} package.
488         *
489         * @return The resource id of the icon in the {@link MediaSessionCompat
490         *         Session's} package.
491         */
492        public int getIcon() {
493            return mIcon;
494        }
495
496        /**
497         * Returns extras which provide additional application-specific
498         * information about the action, or null if none. These arguments are
499         * meant to be consumed by a {@link MediaControllerCompat} if it knows
500         * how to handle them.
501         *
502         * @return Optional arguments for the {@link CustomAction}.
503         */
504        public Bundle getExtras() {
505            return mExtras;
506        }
507
508        @Override
509        public String toString() {
510            return "Action:" +
511                    "mName='" + mName +
512                    ", mIcon=" + mIcon +
513                    ", mExtras=" + mExtras;
514        }
515
516        /**
517         * Builder for {@link CustomAction} objects.
518         */
519        public static final class Builder {
520            private final String mAction;
521            private final CharSequence mName;
522            private final int mIcon;
523            private Bundle mExtras;
524
525            /**
526             * Creates a {@link CustomAction} builder with the id, name, and
527             * icon set.
528             *
529             * @param action The action of the {@link CustomAction}.
530             * @param name The display name of the {@link CustomAction}. This
531             *            name will be displayed along side the action if the UI
532             *            supports it.
533             * @param icon The icon resource id of the {@link CustomAction}.
534             *            This resource id must be in the same package as the
535             *            {@link MediaSessionCompat}. It will be displayed with
536             *            the custom action if the UI supports it.
537             */
538            public Builder(String action, CharSequence name, int icon) {
539                if (TextUtils.isEmpty(action)) {
540                    throw new IllegalArgumentException(
541                            "You must specify an action to build a CustomAction.");
542                }
543                if (TextUtils.isEmpty(name)) {
544                    throw new IllegalArgumentException(
545                            "You must specify a name to build a CustomAction.");
546                }
547                if (icon == 0) {
548                    throw new IllegalArgumentException(
549                            "You must specify an icon resource id to build a CustomAction.");
550                }
551                mAction = action;
552                mName = name;
553                mIcon = icon;
554            }
555
556            /**
557             * Set optional extras for the {@link CustomAction}. These extras
558             * are meant to be consumed by a {@link MediaControllerCompat} if it
559             * knows how to handle them. Keys should be fully qualified (e.g.
560             * "com.example.MY_ARG") to avoid collisions.
561             *
562             * @param extras Optional extras for the {@link CustomAction}.
563             * @return this.
564             */
565            public Builder setExtras(Bundle extras) {
566                mExtras = extras;
567                return this;
568            }
569
570            /**
571             * Build and return the {@link CustomAction} instance with the
572             * specified values.
573             *
574             * @return A new {@link CustomAction} instance.
575             */
576            public CustomAction build() {
577                return new CustomAction(mAction, mName, mIcon, mExtras);
578            }
579        }
580    }
581
582    /**
583     * Builder for {@link PlaybackStateCompat} objects.
584     */
585    public static final class Builder {
586        private int mState;
587        private long mPosition;
588        private long mBufferedPosition;
589        private float mRate;
590        private long mActions;
591        private CharSequence mErrorMessage;
592        private long mUpdateTime;
593
594        /**
595         * Create an empty Builder.
596         */
597        public Builder() {
598        }
599
600        /**
601         * Create a Builder using a {@link PlaybackStateCompat} instance to set the
602         * initial values.
603         *
604         * @param source The playback state to copy.
605         */
606        public Builder(PlaybackStateCompat source) {
607            mState = source.mState;
608            mPosition = source.mPosition;
609            mRate = source.mSpeed;
610            mUpdateTime = source.mUpdateTime;
611            mBufferedPosition = source.mBufferedPosition;
612            mActions = source.mActions;
613            mErrorMessage = source.mErrorMessage;
614        }
615
616        /**
617         * Set the current state of playback.
618         * <p>
619         * The position must be in ms and indicates the current playback
620         * position within the track. If the position is unknown use
621         * {@link #PLAYBACK_POSITION_UNKNOWN}.
622         * <p>
623         * The rate is a multiple of normal playback and should be 0 when paused
624         * and negative when rewinding. Normal playback rate is 1.0.
625         * <p>
626         * The state must be one of the following:
627         * <ul>
628         * <li> {@link PlaybackStateCompat#STATE_NONE}</li>
629         * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li>
630         * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li>
631         * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li>
632         * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li>
633         * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li>
634         * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li>
635         * <li> {@link PlaybackStateCompat#STATE_ERROR}</li>
636         * </ul>
637         *
638         * @param state The current state of playback.
639         * @param position The position in the current track in ms.
640         * @param playbackSpeed The current rate of playback as a multiple of
641         *            normal playback.
642         */
643        public Builder setState(int state, long position, float playbackSpeed) {
644            return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime());
645        }
646
647        /**
648         * Set the current state of playback.
649         * <p>
650         * The position must be in ms and indicates the current playback
651         * position within the track. If the position is unknown use
652         * {@link #PLAYBACK_POSITION_UNKNOWN}.
653         * <p>
654         * The rate is a multiple of normal playback and should be 0 when paused
655         * and negative when rewinding. Normal playback rate is 1.0.
656         * <p>
657         * The state must be one of the following:
658         * <ul>
659         * <li> {@link PlaybackStateCompat#STATE_NONE}</li>
660         * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li>
661         * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li>
662         * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li>
663         * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li>
664         * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li>
665         * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li>
666         * <li> {@link PlaybackStateCompat#STATE_ERROR}</li>
667         * </ul>
668         *
669         * @param state The current state of playback.
670         * @param position The position in the current item in ms.
671         * @param playbackSpeed The current speed of playback as a multiple of
672         *            normal playback.
673         * @param updateTime The time in the {@link SystemClock#elapsedRealtime}
674         *            timebase that the position was updated at.
675         * @return this
676         */
677        public Builder setState(int state, long position, float playbackSpeed, long updateTime) {
678            mState = state;
679            mPosition = position;
680            mUpdateTime = updateTime;
681            mRate = playbackSpeed;
682            return this;
683        }
684
685        /**
686         * Set the current buffered position in ms. This is the farthest
687         * playback point that can be reached from the current position using
688         * only buffered content.
689         *
690         * @return this
691         */
692        public Builder setBufferedPosition(long bufferPosition) {
693            mBufferedPosition = bufferPosition;
694            return this;
695        }
696
697        /**
698         * Set the current capabilities available on this session. This should
699         * use a bitmask of the available capabilities.
700         * <ul>
701         * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li>
702         * <li> {@link PlaybackStateCompat#ACTION_REWIND}</li>
703         * <li> {@link PlaybackStateCompat#ACTION_PLAY}</li>
704         * <li> {@link PlaybackStateCompat#ACTION_PLAY_PAUSE}</li>
705         * <li> {@link PlaybackStateCompat#ACTION_PAUSE}</li>
706         * <li> {@link PlaybackStateCompat#ACTION_STOP}</li>
707         * <li> {@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li>
708         * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li>
709         * <li> {@link PlaybackStateCompat#ACTION_SEEK_TO}</li>
710         * <li> {@link PlaybackStateCompat#ACTION_SET_RATING}</li>
711         * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_MEDIA_ID}</li>
712         * <li> {@link PlaybackStateCompat#ACTION_PLAY_FROM_SEARCH}</li>
713         * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_QUEUE_ITEM}</li>
714         * </ul>
715         *
716         * @return this
717         */
718        public Builder setActions(long capabilities) {
719            mActions = capabilities;
720            return this;
721        }
722
723        /**
724         * Set a user readable error message. This should be set when the state
725         * is {@link PlaybackStateCompat#STATE_ERROR}.
726         *
727         * @return this
728         */
729        public Builder setErrorMessage(CharSequence errorMessage) {
730            mErrorMessage = errorMessage;
731            return this;
732        }
733
734        /**
735         * Creates the playback state object.
736         */
737        public PlaybackStateCompat build() {
738            return new PlaybackStateCompat(mState, mPosition, mBufferedPosition,
739                    mRate, mActions, mErrorMessage, mUpdateTime);
740        }
741    }
742}
743