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