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