PlaybackStateCompat.java revision d2eec9eeb9bacd4b62d4fc1c66760ec1f7f8a73b
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.Parcel; 20import android.os.Parcelable; 21import android.os.SystemClock; 22import android.text.TextUtils; 23 24/** 25 * Playback state for a {@link MediaSessionCompat}. This includes a state like 26 * {@link PlaybackStateCompat#STATE_PLAYING}, the current playback position, 27 * and the current control capabilities. 28 */ 29public final class PlaybackStateCompat implements Parcelable { 30 /** 31 * Indicates this performer supports the stop command. 32 * 33 * @see Builder#setActions 34 */ 35 public static final long ACTION_STOP = 1 << 0; 36 37 /** 38 * Indicates this performer supports the pause command. 39 * 40 * @see Builder#setActions 41 */ 42 public static final long ACTION_PAUSE = 1 << 1; 43 44 /** 45 * Indicates this performer supports the play command. 46 * 47 * @see Builder#setActions 48 */ 49 public static final long ACTION_PLAY = 1 << 2; 50 51 /** 52 * Indicates this performer supports the rewind command. 53 * 54 * @see Builder#setActions 55 */ 56 public static final long ACTION_REWIND = 1 << 3; 57 58 /** 59 * Indicates this performer supports the previous command. 60 * 61 * @see Builder#setActions 62 */ 63 public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4; 64 65 /** 66 * Indicates this performer supports the next command. 67 * 68 * @see Builder#setActions 69 */ 70 public static final long ACTION_SKIP_TO_NEXT = 1 << 5; 71 72 /** 73 * Indicates this performer supports the fast forward command. 74 * 75 * @see Builder#setActions 76 */ 77 public static final long ACTION_FAST_FORWARD = 1 << 6; 78 79 /** 80 * Indicates this performer supports the set rating command. 81 * 82 * @see Builder#setActions 83 */ 84 public static final long ACTION_SET_RATING = 1 << 7; 85 86 /** 87 * Indicates this performer supports the seek to command. 88 * 89 * @see Builder#setActions 90 */ 91 public static final long ACTION_SEEK_TO = 1 << 8; 92 93 /** 94 * Indicates this performer supports the play/pause toggle command. 95 * 96 * @see Builder#setActions 97 */ 98 public static final long ACTION_PLAY_PAUSE = 1 << 9; 99 100 /** 101 * This is the default playback state and indicates that no media has been 102 * added yet, or the performer has been reset and has no content to play. 103 * 104 * @see Builder#setState 105 */ 106 public final static int STATE_NONE = 0; 107 108 /** 109 * State indicating this item is currently stopped. 110 * 111 * @see Builder#setState 112 */ 113 public final static int STATE_STOPPED = 1; 114 115 /** 116 * State indicating this item is currently paused. 117 * 118 * @see Builder#setState 119 */ 120 public final static int STATE_PAUSED = 2; 121 122 /** 123 * State indicating this item is currently playing. 124 * 125 * @see Builder#setState 126 */ 127 public final static int STATE_PLAYING = 3; 128 129 /** 130 * State indicating this item is currently fast forwarding. 131 * 132 * @see Builder#setState 133 */ 134 public final static int STATE_FAST_FORWARDING = 4; 135 136 /** 137 * State indicating this item is currently rewinding. 138 * 139 * @see Builder#setState 140 */ 141 public final static int STATE_REWINDING = 5; 142 143 /** 144 * State indicating this item is currently buffering and will begin playing 145 * when enough data has buffered. 146 * 147 * @see Builder#setState 148 */ 149 public final static int STATE_BUFFERING = 6; 150 151 /** 152 * State indicating this item is currently in an error state. The error 153 * message should also be set when entering this state. 154 * 155 * @see Builder#setState 156 */ 157 public final static int STATE_ERROR = 7; 158 159 /** 160 * State indicating the class doing playback is currently connecting to a 161 * route. Depending on the implementation you may return to the previous 162 * state when the connection finishes or enter {@link #STATE_NONE}. If 163 * the connection failed {@link #STATE_ERROR} should be used. 164 * @hide 165 */ 166 public final static int STATE_CONNECTING = 8; 167 168 /** 169 * State indicating the player is currently skipping to the previous item. 170 * 171 * @see Builder#setState 172 */ 173 public final static int STATE_SKIPPING_TO_PREVIOUS = 9; 174 175 /** 176 * State indicating the player is currently skipping to the next item. 177 * 178 * @see Builder#setState 179 */ 180 public final static int STATE_SKIPPING_TO_NEXT = 10; 181 182 /** 183 * Use this value for the position to indicate the position is not known. 184 */ 185 public final static long PLAYBACK_POSITION_UNKNOWN = -1; 186 187 private final int mState; 188 private final long mPosition; 189 private final long mBufferPosition; 190 private final float mRate; 191 private final long mActions; 192 private final CharSequence mErrorMessage; 193 private final long mUpdateTime; 194 195 private Object mStateObj; 196 197 private PlaybackStateCompat(int state, long position, long bufferPosition, 198 float rate, long actions, CharSequence errorMessage, long updateTime) { 199 mState = state; 200 mPosition = position; 201 mBufferPosition = bufferPosition; 202 mRate = rate; 203 mActions = actions; 204 mErrorMessage = errorMessage; 205 mUpdateTime = updateTime; 206 } 207 208 private PlaybackStateCompat(Parcel in) { 209 mState = in.readInt(); 210 mPosition = in.readLong(); 211 mRate = in.readFloat(); 212 mUpdateTime = in.readLong(); 213 mBufferPosition = in.readLong(); 214 mActions = in.readLong(); 215 mErrorMessage = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 216 } 217 218 @Override 219 public String toString() { 220 StringBuilder bob = new StringBuilder("PlaybackState {"); 221 bob.append("state=").append(mState); 222 bob.append(", position=").append(mPosition); 223 bob.append(", buffered position=").append(mBufferPosition); 224 bob.append(", rate=").append(mRate); 225 bob.append(", updated=").append(mUpdateTime); 226 bob.append(", actions=").append(mActions); 227 bob.append(", error=").append(mErrorMessage); 228 bob.append("}"); 229 return bob.toString(); 230 } 231 232 @Override 233 public int describeContents() { 234 return 0; 235 } 236 237 @Override 238 public void writeToParcel(Parcel dest, int flags) { 239 dest.writeInt(mState); 240 dest.writeLong(mPosition); 241 dest.writeFloat(mRate); 242 dest.writeLong(mUpdateTime); 243 dest.writeLong(mBufferPosition); 244 dest.writeLong(mActions); 245 TextUtils.writeToParcel(mErrorMessage, dest, flags); 246 } 247 248 /** 249 * Get the current state of playback. One of the following: 250 * <ul> 251 * <li> {@link PlaybackStateCompat#STATE_NONE}</li> 252 * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li> 253 * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li> 254 * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li> 255 * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li> 256 * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li> 257 * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li> 258 * <li> {@link PlaybackStateCompat#STATE_ERROR}</li> 259 */ 260 public int getState() { 261 return mState; 262 } 263 264 /** 265 * Get the current playback position in ms. 266 */ 267 public long getPosition() { 268 return mPosition; 269 } 270 271 /** 272 * Get the current buffer position in ms. This is the farthest playback 273 * point that can be reached from the current position using only buffered 274 * content. 275 */ 276 public long getBufferPosition() { 277 return mBufferPosition; 278 } 279 280 /** 281 * Get the current playback rate as a multiple of normal playback. This 282 * should be negative when rewinding. A value of 1 means normal playback and 283 * 0 means paused. 284 * 285 * @return The current rate of playback. 286 */ 287 public float getPlaybackRate() { 288 return mRate; 289 } 290 291 /** 292 * Get the current actions available on this session. This should use a 293 * bitmask of the available actions. 294 * <ul> 295 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li> 296 * <li> {@link PlaybackStateCompat#ACTION_REWIND}</li> 297 * <li> {@link PlaybackStateCompat#ACTION_PLAY}</li> 298 * <li> {@link PlaybackStateCompat#ACTION_PAUSE}</li> 299 * <li> {@link PlaybackStateCompat#ACTION_STOP}</li> 300 * <li> {@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li> 301 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li> 302 * <li> {@link PlaybackStateCompat#ACTION_SEEK_TO}</li> 303 * <li> {@link PlaybackStateCompat#ACTION_SET_RATING}</li> 304 * </ul> 305 */ 306 public long getActions() { 307 return mActions; 308 } 309 310 /** 311 * Get a user readable error message. This should be set when the state is 312 * {@link PlaybackStateCompat#STATE_ERROR}. 313 */ 314 public CharSequence getErrorMessage() { 315 return mErrorMessage; 316 } 317 318 /** 319 * Get the elapsed real time at which position was last updated. If the 320 * position has never been set this will return 0; 321 * 322 * @return The last time the position was updated. 323 */ 324 public long getLastPositionUpdateTime() { 325 return mUpdateTime; 326 } 327 328 /** 329 * Creates an instance from a framework {@link android.media.session.PlaybackState} object. 330 * <p> 331 * This method is only supported on API 21+. 332 * </p> 333 * 334 * @param stateObj A {@link android.media.session.PlaybackState} object, or null if none. 335 * @return An equivalent {@link PlaybackStateCompat} object, or null if none. 336 */ 337 public static PlaybackStateCompat fromPlaybackState(Object stateObj) { 338 if (stateObj == null || Build.VERSION.SDK_INT < 21) { 339 return null; 340 } 341 342 PlaybackStateCompat state = new PlaybackStateCompat( 343 PlaybackStateCompatApi21.getState(stateObj), 344 PlaybackStateCompatApi21.getPosition(stateObj), 345 PlaybackStateCompatApi21.getBufferPosition(stateObj), 346 PlaybackStateCompatApi21.getPlaybackRate(stateObj), 347 PlaybackStateCompatApi21.getActions(stateObj), 348 PlaybackStateCompatApi21.getErrorMessage(stateObj), 349 PlaybackStateCompatApi21.getLastPositionUpdateTime(stateObj)); 350 state.mStateObj = stateObj; 351 return state; 352 } 353 354 /** 355 * Gets the underlying framework {@link android.media.session.PlaybackState} object. 356 * <p> 357 * This method is only supported on API 21+. 358 * </p> 359 * 360 * @return An equivalent {@link android.media.session.PlaybackState} object, or null if none. 361 */ 362 public Object getPlaybackState() { 363 if (mStateObj != null || Build.VERSION.SDK_INT < 21) { 364 return mStateObj; 365 } 366 367 mStateObj = PlaybackStateCompatApi21.newInstance(mState, mPosition, mBufferPosition, 368 mRate, mActions, mErrorMessage, mUpdateTime); 369 return mStateObj; 370 } 371 372 public static final Parcelable.Creator<PlaybackStateCompat> CREATOR = 373 new Parcelable.Creator<PlaybackStateCompat>() { 374 @Override 375 public PlaybackStateCompat createFromParcel(Parcel in) { 376 return new PlaybackStateCompat(in); 377 } 378 379 @Override 380 public PlaybackStateCompat[] newArray(int size) { 381 return new PlaybackStateCompat[size]; 382 } 383 }; 384 385 /** 386 * Builder for {@link PlaybackStateCompat} objects. 387 */ 388 public static final class Builder { 389 private int mState; 390 private long mPosition; 391 private long mBufferPosition; 392 private float mRate; 393 private long mActions; 394 private CharSequence mErrorMessage; 395 private long mUpdateTime; 396 397 /** 398 * Create an empty Builder. 399 */ 400 public Builder() { 401 } 402 403 /** 404 * Create a Builder using a {@link PlaybackStateCompat} instance to set the 405 * initial values. 406 * 407 * @param source The playback state to copy. 408 */ 409 public Builder(PlaybackStateCompat source) { 410 mState = source.mState; 411 mPosition = source.mPosition; 412 mRate = source.mRate; 413 mUpdateTime = source.mUpdateTime; 414 mBufferPosition = source.mBufferPosition; 415 mActions = source.mActions; 416 mErrorMessage = source.mErrorMessage; 417 } 418 419 /** 420 * Set the current state of playback. 421 * <p> 422 * The position must be in ms and indicates the current playback position 423 * within the track. If the position is unknown use 424 * {@link #PLAYBACK_POSITION_UNKNOWN}. 425 * <p> 426 * The rate is a multiple of normal playback and should be 0 when paused and 427 * negative when rewinding. Normal playback rate is 1.0. 428 * <p> 429 * The state must be one of the following: 430 * <ul> 431 * <li> {@link PlaybackStateCompat#STATE_NONE}</li> 432 * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li> 433 * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li> 434 * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li> 435 * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li> 436 * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li> 437 * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li> 438 * <li> {@link PlaybackStateCompat#STATE_ERROR}</li> 439 * </ul> 440 * 441 * @param state The current state of playback. 442 * @param position The position in the current track in ms. 443 * @param playbackRate The current rate of playback as a multiple of normal 444 * playback. 445 */ 446 public void setState(int state, long position, float playbackRate) { 447 this.mState = state; 448 this.mPosition = position; 449 this.mRate = playbackRate; 450 mUpdateTime = SystemClock.elapsedRealtime(); 451 } 452 453 /** 454 * Set the current buffer position in ms. This is the farthest playback 455 * point that can be reached from the current position using only buffered 456 * content. 457 */ 458 public void setBufferPosition(long bufferPosition) { 459 mBufferPosition = bufferPosition; 460 } 461 462 /** 463 * Set the current capabilities available on this session. This should use a 464 * bitmask of the available capabilities. 465 * <ul> 466 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li> 467 * <li> {@link PlaybackStateCompat#ACTION_REWIND}</li> 468 * <li> {@link PlaybackStateCompat#ACTION_PLAY}</li> 469 * <li> {@link PlaybackStateCompat#ACTION_PAUSE}</li> 470 * <li> {@link PlaybackStateCompat#ACTION_STOP}</li> 471 * <li> {@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li> 472 * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li> 473 * <li> {@link PlaybackStateCompat#ACTION_SEEK_TO}</li> 474 * <li> {@link PlaybackStateCompat#ACTION_SET_RATING}</li> 475 * </ul> 476 */ 477 public void setActions(long capabilities) { 478 mActions = capabilities; 479 } 480 481 /** 482 * Set a user readable error message. This should be set when the state is 483 * {@link PlaybackStateCompat#STATE_ERROR}. 484 */ 485 public void setErrorMessage(CharSequence errorMessage) { 486 mErrorMessage = errorMessage; 487 } 488 489 /** 490 * Creates the playback state object. 491 */ 492 public PlaybackStateCompat build() { 493 return new PlaybackStateCompat(mState, mPosition, mBufferPosition, 494 mRate, mActions, mErrorMessage, mUpdateTime); 495 } 496 } 497} 498