1/* 2 * Copyright 2018 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 17package android.media; 18 19import static android.media.MediaPlayerBase.BUFFERING_STATE_UNKNOWN; 20 21import android.annotation.CallbackExecutor; 22import android.annotation.NonNull; 23import android.annotation.Nullable; 24import android.app.PendingIntent; 25import android.content.Context; 26import android.media.MediaPlaylistAgent.RepeatMode; 27import android.media.MediaPlaylistAgent.ShuffleMode; 28import android.media.MediaSession2.CommandButton; 29import android.media.MediaSession2.ControllerInfo; 30import android.media.MediaSession2.ErrorCode; 31import android.media.session.MediaSessionManager; 32import android.media.update.ApiLoader; 33import android.media.update.MediaController2Provider; 34import android.media.update.MediaController2Provider.PlaybackInfoProvider; 35import android.net.Uri; 36import android.os.Bundle; 37import android.os.ResultReceiver; 38 39import java.util.List; 40import java.util.concurrent.Executor; 41 42/** 43 * @hide 44 * Allows an app to interact with an active {@link MediaSession2} or a 45 * {@link MediaSessionService2} in any status. Media buttons and other commands can be sent to 46 * the session. 47 * <p> 48 * When you're done, use {@link #close()} to clean up resources. This also helps session service 49 * to be destroyed when there's no controller associated with it. 50 * <p> 51 * When controlling {@link MediaSession2}, the controller will be available immediately after 52 * the creation. 53 * <p> 54 * When controlling {@link MediaSessionService2}, the {@link MediaController2} would be 55 * available only if the session service allows this controller by 56 * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)} for the service. 57 * Wait {@link ControllerCallback#onConnected(MediaController2, SessionCommandGroup2)} or 58 * {@link ControllerCallback#onDisconnected(MediaController2)} for the result. 59 * <p> 60 * A controller can be created through token from {@link MediaSessionManager} if you hold the 61 * signature|privileged permission "android.permission.MEDIA_CONTENT_CONTROL" permission or are 62 * an enabled notification listener or by getting a {@link SessionToken2} directly the 63 * the session owner. 64 * <p> 65 * MediaController2 objects are thread-safe. 66 * <p> 67 * @see MediaSession2 68 * @see MediaSessionService2 69 */ 70public class MediaController2 implements AutoCloseable { 71 /** 72 * Interface for listening to change in activeness of the {@link MediaSession2}. It's 73 * active if and only if it has set a player. 74 */ 75 public abstract static class ControllerCallback { 76 /** 77 * Called when the controller is successfully connected to the session. The controller 78 * becomes available afterwards. 79 * 80 * @param controller the controller for this event 81 * @param allowedCommands commands that's allowed by the session. 82 */ 83 public void onConnected(@NonNull MediaController2 controller, 84 @NonNull SessionCommandGroup2 allowedCommands) { } 85 86 /** 87 * Called when the session refuses the controller or the controller is disconnected from 88 * the session. The controller becomes unavailable afterwards and the callback wouldn't 89 * be called. 90 * <p> 91 * It will be also called after the {@link #close()}, so you can put clean up code here. 92 * You don't need to call {@link #close()} after this. 93 * 94 * @param controller the controller for this event 95 * @param controller controller for this event 96 */ 97 public void onDisconnected(@NonNull MediaController2 controller) { } 98 99 /** 100 * Called when the session set the custom layout through the 101 * {@link MediaSession2#setCustomLayout(ControllerInfo, List)}. 102 * <p> 103 * Can be called before {@link #onConnected(MediaController2, SessionCommandGroup2)} is 104 * called. 105 * 106 * @param controller the controller for this event 107 * @param layout 108 */ 109 public void onCustomLayoutChanged(@NonNull MediaController2 controller, 110 @NonNull List<CommandButton> layout) { } 111 112 /** 113 * Called when the session has changed anything related with the {@link PlaybackInfo}. 114 * 115 * @param controller the controller for this event 116 * @param info new playback info 117 */ 118 public void onPlaybackInfoChanged(@NonNull MediaController2 controller, 119 @NonNull PlaybackInfo info) { } 120 121 /** 122 * Called when the allowed commands are changed by session. 123 * 124 * @param controller the controller for this event 125 * @param commands newly allowed commands 126 */ 127 public void onAllowedCommandsChanged(@NonNull MediaController2 controller, 128 @NonNull SessionCommandGroup2 commands) { } 129 130 /** 131 * Called when the session sent a custom command. 132 * 133 * @param controller the controller for this event 134 * @param command 135 * @param args 136 * @param receiver 137 */ 138 public void onCustomCommand(@NonNull MediaController2 controller, 139 @NonNull SessionCommand2 command, @Nullable Bundle args, 140 @Nullable ResultReceiver receiver) { } 141 142 /** 143 * Called when the player state is changed. 144 * 145 * @param controller the controller for this event 146 * @param state 147 */ 148 public void onPlayerStateChanged(@NonNull MediaController2 controller, int state) { } 149 150 /** 151 * Called when playback speed is changed. 152 * 153 * @param controller the controller for this event 154 * @param speed speed 155 */ 156 public void onPlaybackSpeedChanged(@NonNull MediaController2 controller, 157 float speed) { } 158 159 /** 160 * Called to report buffering events for a data source. 161 * <p> 162 * Use {@link #getBufferedPosition()} for current buffering position. 163 * 164 * @param controller the controller for this event 165 * @param item the media item for which buffering is happening. 166 * @param state the new buffering state. 167 */ 168 public void onBufferingStateChanged(@NonNull MediaController2 controller, 169 @NonNull MediaItem2 item, @MediaPlayerBase.BuffState int state) { } 170 171 /** 172 * Called to indicate that seeking is completed. 173 * 174 * @param controller the controller for this event. 175 * @param position the previous seeking request. 176 */ 177 public void onSeekCompleted(@NonNull MediaController2 controller, long position) { } 178 179 /** 180 * Called when a error from 181 * 182 * @param controller the controller for this event 183 * @param errorCode error code 184 * @param extras extra information 185 */ 186 public void onError(@NonNull MediaController2 controller, @ErrorCode int errorCode, 187 @Nullable Bundle extras) { } 188 189 /** 190 * Called when the player's currently playing item is changed 191 * <p> 192 * When it's called, you should invalidate previous playback information and wait for later 193 * callbacks. 194 * 195 * @param controller the controller for this event 196 * @param item new item 197 * @see #onBufferingStateChanged(MediaController2, MediaItem2, int) 198 */ 199 // TODO(jaewan): Use this (b/74316764) 200 public void onCurrentMediaItemChanged(@NonNull MediaController2 controller, 201 @NonNull MediaItem2 item) { } 202 203 /** 204 * Called when a playlist is changed. 205 * 206 * @param controller the controller for this event 207 * @param list new playlist 208 * @param metadata new metadata 209 */ 210 public void onPlaylistChanged(@NonNull MediaController2 controller, 211 @NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) { } 212 213 /** 214 * Called when a playlist metadata is changed. 215 * 216 * @param controller the controller for this event 217 * @param metadata new metadata 218 */ 219 public void onPlaylistMetadataChanged(@NonNull MediaController2 controller, 220 @Nullable MediaMetadata2 metadata) { } 221 222 /** 223 * Called when the shuffle mode is changed. 224 * 225 * @param controller the controller for this event 226 * @param shuffleMode repeat mode 227 * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE 228 * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL 229 * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP 230 */ 231 public void onShuffleModeChanged(@NonNull MediaController2 controller, 232 @MediaPlaylistAgent.ShuffleMode int shuffleMode) { } 233 234 /** 235 * Called when the repeat mode is changed. 236 * 237 * @param controller the controller for this event 238 * @param repeatMode repeat mode 239 * @see MediaPlaylistAgent#REPEAT_MODE_NONE 240 * @see MediaPlaylistAgent#REPEAT_MODE_ONE 241 * @see MediaPlaylistAgent#REPEAT_MODE_ALL 242 * @see MediaPlaylistAgent#REPEAT_MODE_GROUP 243 */ 244 public void onRepeatModeChanged(@NonNull MediaController2 controller, 245 @MediaPlaylistAgent.RepeatMode int repeatMode) { } 246 } 247 248 /** 249 * Holds information about the current playback and how audio is handled for 250 * this session. 251 */ 252 // The same as MediaController.PlaybackInfo 253 public static final class PlaybackInfo { 254 /** 255 * The session uses remote playback. 256 */ 257 public static final int PLAYBACK_TYPE_REMOTE = 2; 258 /** 259 * The session uses local playback. 260 */ 261 public static final int PLAYBACK_TYPE_LOCAL = 1; 262 263 private final PlaybackInfoProvider mProvider; 264 265 /** 266 * @hide 267 */ 268 public PlaybackInfo(PlaybackInfoProvider provider) { 269 mProvider = provider; 270 } 271 272 /** 273 * @hide 274 */ 275 public PlaybackInfoProvider getProvider() { 276 return mProvider; 277 } 278 279 /** 280 * Get the type of playback which affects volume handling. One of: 281 * <ul> 282 * <li>{@link #PLAYBACK_TYPE_LOCAL}</li> 283 * <li>{@link #PLAYBACK_TYPE_REMOTE}</li> 284 * </ul> 285 * 286 * @return The type of playback this session is using. 287 */ 288 public int getPlaybackType() { 289 return mProvider.getPlaybackType_impl(); 290 } 291 292 /** 293 * Get the audio attributes for this session. The attributes will affect 294 * volume handling for the session. When the volume type is 295 * {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE} these may be ignored by the 296 * remote volume handler. 297 * 298 * @return The attributes for this session. 299 */ 300 public AudioAttributes getAudioAttributes() { 301 return mProvider.getAudioAttributes_impl(); 302 } 303 304 /** 305 * Get the type of volume control that can be used. One of: 306 * <ul> 307 * <li>{@link VolumeProvider2#VOLUME_CONTROL_ABSOLUTE}</li> 308 * <li>{@link VolumeProvider2#VOLUME_CONTROL_RELATIVE}</li> 309 * <li>{@link VolumeProvider2#VOLUME_CONTROL_FIXED}</li> 310 * </ul> 311 * 312 * @return The type of volume control that may be used with this session. 313 */ 314 public int getControlType() { 315 return mProvider.getControlType_impl(); 316 } 317 318 /** 319 * Get the maximum volume that may be set for this session. 320 * 321 * @return The maximum allowed volume where this session is playing. 322 */ 323 public int getMaxVolume() { 324 return mProvider.getMaxVolume_impl(); 325 } 326 327 /** 328 * Get the current volume for this session. 329 * 330 * @return The current volume where this session is playing. 331 */ 332 public int getCurrentVolume() { 333 return mProvider.getCurrentVolume_impl(); 334 } 335 } 336 337 private final MediaController2Provider mProvider; 338 339 /** 340 * Create a {@link MediaController2} from the {@link SessionToken2}. 341 * This connects to the session and may wake up the service if it's not available. 342 * 343 * @param context Context 344 * @param token token to connect to 345 * @param executor executor to run callbacks on. 346 * @param callback controller callback to receive changes in 347 */ 348 public MediaController2(@NonNull Context context, @NonNull SessionToken2 token, 349 @NonNull @CallbackExecutor Executor executor, @NonNull ControllerCallback callback) { 350 super(); 351 352 mProvider = createProvider(context, token, executor, callback); 353 // This also connects to the token. 354 // Explicit connect() isn't added on purpose because retrying connect() is impossible with 355 // session whose session binder is only valid while it's active. 356 // prevent a controller from reusable after the 357 // session is released and recreated. 358 mProvider.initialize(); 359 } 360 361 MediaController2Provider createProvider(@NonNull Context context, 362 @NonNull SessionToken2 token, @NonNull Executor executor, 363 @NonNull ControllerCallback callback) { 364 return ApiLoader.getProvider().createMediaController2( 365 context, this, token, executor, callback); 366 } 367 368 /** 369 * Release this object, and disconnect from the session. After this, callbacks wouldn't be 370 * received. 371 */ 372 @Override 373 public void close() { 374 mProvider.close_impl(); 375 } 376 377 /** 378 * @hide 379 */ 380 public MediaController2Provider getProvider() { 381 return mProvider; 382 } 383 384 /** 385 * @return token 386 */ 387 public @NonNull SessionToken2 getSessionToken() { 388 return mProvider.getSessionToken_impl(); 389 } 390 391 /** 392 * Returns whether this class is connected to active {@link MediaSession2} or not. 393 */ 394 public boolean isConnected() { 395 return mProvider.isConnected_impl(); 396 } 397 398 public void play() { 399 mProvider.play_impl(); 400 } 401 402 public void pause() { 403 mProvider.pause_impl(); 404 } 405 406 public void stop() { 407 mProvider.stop_impl(); 408 } 409 410 /** 411 * Request that the player prepare its playback. In other words, other sessions can continue 412 * to play during the preparation of this session. This method can be used to speed up the 413 * start of the playback. Once the preparation is done, the session will change its playback 414 * state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards, {@link #play} can be called 415 * to start playback. 416 */ 417 public void prepare() { 418 mProvider.prepare_impl(); 419 } 420 421 /** 422 * Fast forwards playback. If playback is already fast forwarding this may increase the rate. 423 */ 424 public void fastForward() { 425 mProvider.fastForward_impl(); 426 } 427 428 /** 429 * Rewinds playback. If playback is already rewinding this may increase the rate. 430 */ 431 public void rewind() { 432 mProvider.rewind_impl(); 433 } 434 435 /** 436 * Move to a new location in the media stream. 437 * 438 * @param pos Position to move to, in milliseconds. 439 */ 440 public void seekTo(long pos) { 441 mProvider.seekTo_impl(pos); 442 } 443 444 /** 445 * Revisit this API later. 446 * @hide 447 */ 448 public void skipForward() { 449 // TODO(jaewan): (Post-P) Discuss this API later. 450 // To match with KEYCODE_MEDIA_SKIP_FORWARD 451 } 452 453 /** 454 * @hide 455 */ 456 public void skipBackward() { 457 // TODO(jaewan): (Post-P) Discuss this API later. 458 // To match with KEYCODE_MEDIA_SKIP_BACKWARD 459 } 460 461 /** 462 * Request that the player start playback for a specific media id. 463 * 464 * @param mediaId The id of the requested media. 465 * @param extras Optional extras that can include extra information about the media item 466 * to be played. 467 */ 468 public void playFromMediaId(@NonNull String mediaId, @Nullable Bundle extras) { 469 mProvider.playFromMediaId_impl(mediaId, extras); 470 } 471 472 /** 473 * Request that the player start playback for a specific search query. 474 * 475 * @param query The search query. Should not be an empty string. 476 * @param extras Optional extras that can include extra information about the query. 477 */ 478 public void playFromSearch(@NonNull String query, @Nullable Bundle extras) { 479 mProvider.playFromSearch_impl(query, extras); 480 } 481 482 /** 483 * Request that the player start playback for a specific {@link Uri}. 484 * 485 * @param uri The URI of the requested media. 486 * @param extras Optional extras that can include extra information about the media item 487 * to be played. 488 */ 489 public void playFromUri(@NonNull Uri uri, @Nullable Bundle extras) { 490 mProvider.playFromUri_impl(uri, extras); 491 } 492 493 /** 494 * Request that the player prepare playback for a specific media id. In other words, other 495 * sessions can continue to play during the preparation of this session. This method can be 496 * used to speed up the start of the playback. Once the preparation is done, the session 497 * will change its playback state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards, 498 * {@link #play} can be called to start playback. If the preparation is not needed, 499 * {@link #playFromMediaId} can be directly called without this method. 500 * 501 * @param mediaId The id of the requested media. 502 * @param extras Optional extras that can include extra information about the media item 503 * to be prepared. 504 */ 505 public void prepareFromMediaId(@NonNull String mediaId, @Nullable Bundle extras) { 506 mProvider.prepareFromMediaId_impl(mediaId, extras); 507 } 508 509 /** 510 * Request that the player prepare playback for a specific search query. 511 * In other words, other sessions can continue to play during the preparation of this session. 512 * This method can be used to speed up the start of the playback. 513 * Once the preparation is done, the session will change its playback state to 514 * {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards, 515 * {@link #play} can be called to start playback. If the preparation is not needed, 516 * {@link #playFromSearch} can be directly called without this method. 517 * 518 * @param query The search query. Should not be an empty string. 519 * @param extras Optional extras that can include extra information about the query. 520 */ 521 public void prepareFromSearch(@NonNull String query, @Nullable Bundle extras) { 522 mProvider.prepareFromSearch_impl(query, extras); 523 } 524 525 /** 526 * Request that the player prepare playback for a specific {@link Uri}. In other words, 527 * other sessions can continue to play during the preparation of this session. This method 528 * can be used to speed up the start of the playback. Once the preparation is done, the 529 * session will change its playback state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. 530 * Afterwards, {@link #play} can be called to start playback. If the preparation is not needed, 531 * {@link #playFromUri} can be directly called without this method. 532 * 533 * @param uri The URI of the requested media. 534 * @param extras Optional extras that can include extra information about the media item 535 * to be prepared. 536 */ 537 public void prepareFromUri(@NonNull Uri uri, @Nullable Bundle extras) { 538 mProvider.prepareFromUri_impl(uri, extras); 539 } 540 541 /** 542 * Set the volume of the output this session is playing on. The command will be ignored if it 543 * does not support {@link VolumeProvider2#VOLUME_CONTROL_ABSOLUTE}. 544 * <p> 545 * If the session is local playback, this changes the device's volume with the stream that 546 * session's player is using. Flags will be specified for the {@link AudioManager}. 547 * <p> 548 * If the session is remote player (i.e. session has set volume provider), its volume provider 549 * will receive this request instead. 550 * 551 * @see #getPlaybackInfo() 552 * @param value The value to set it to, between 0 and the reported max. 553 * @param flags flags from {@link AudioManager} to include with the volume request for local 554 * playback 555 */ 556 public void setVolumeTo(int value, int flags) { 557 mProvider.setVolumeTo_impl(value, flags); 558 } 559 560 /** 561 * Adjust the volume of the output this session is playing on. The direction 562 * must be one of {@link AudioManager#ADJUST_LOWER}, 563 * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}. 564 * The command will be ignored if the session does not support 565 * {@link VolumeProvider2#VOLUME_CONTROL_RELATIVE} or 566 * {@link VolumeProvider2#VOLUME_CONTROL_ABSOLUTE}. 567 * <p> 568 * If the session is local playback, this changes the device's volume with the stream that 569 * session's player is using. Flags will be specified for the {@link AudioManager}. 570 * <p> 571 * If the session is remote player (i.e. session has set volume provider), its volume provider 572 * will receive this request instead. 573 * 574 * @see #getPlaybackInfo() 575 * @param direction The direction to adjust the volume in. 576 * @param flags flags from {@link AudioManager} to include with the volume request for local 577 * playback 578 */ 579 public void adjustVolume(int direction, int flags) { 580 mProvider.adjustVolume_impl(direction, flags); 581 } 582 583 /** 584 * Get an intent for launching UI associated with this session if one exists. 585 * 586 * @return A {@link PendingIntent} to launch UI or null. 587 */ 588 public @Nullable PendingIntent getSessionActivity() { 589 return mProvider.getSessionActivity_impl(); 590 } 591 592 /** 593 * Get the lastly cached player state from 594 * {@link ControllerCallback#onPlayerStateChanged(MediaController2, int)}. 595 * 596 * @return player state 597 */ 598 public int getPlayerState() { 599 return mProvider.getPlayerState_impl(); 600 } 601 602 /** 603 * Gets the current playback position. 604 * <p> 605 * This returns the calculated value of the position, based on the difference between the 606 * update time and current time. 607 * 608 * @return position 609 */ 610 public long getCurrentPosition() { 611 return mProvider.getCurrentPosition_impl(); 612 } 613 614 /** 615 * Get the lastly cached playback speed from 616 * {@link ControllerCallback#onPlaybackSpeedChanged(MediaController2, float)}. 617 * 618 * @return speed 619 */ 620 public float getPlaybackSpeed() { 621 return mProvider.getPlaybackSpeed_impl(); 622 } 623 624 /** 625 * Set the playback speed. 626 */ 627 public void setPlaybackSpeed(float speed) { 628 // TODO(jaewan): implement this (b/74093080) 629 } 630 631 632 /** 633 * Gets the current buffering state of the player. 634 * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already 635 * buffered. 636 * @return the buffering state. 637 */ 638 public @MediaPlayerBase.BuffState int getBufferingState() { 639 // TODO(jaewan): Implement. 640 return BUFFERING_STATE_UNKNOWN; 641 } 642 643 /** 644 * Gets the lastly cached buffered position from the session when 645 * {@link ControllerCallback#onBufferingStateChanged(MediaController2, MediaItem2, int)} is 646 * called. 647 * 648 * @return buffering position in millis 649 */ 650 public long getBufferedPosition() { 651 return mProvider.getBufferedPosition_impl(); 652 } 653 654 /** 655 * Get the current playback info for this session. 656 * 657 * @return The current playback info or null. 658 */ 659 public @Nullable PlaybackInfo getPlaybackInfo() { 660 return mProvider.getPlaybackInfo_impl(); 661 } 662 663 /** 664 * Rate the media. This will cause the rating to be set for the current user. 665 * The rating style must follow the user rating style from the session. 666 * You can get the rating style from the session through the 667 * {@link MediaMetadata#getRating(String)} with the key 668 * {@link MediaMetadata#METADATA_KEY_USER_RATING}. 669 * <p> 670 * If the user rating was {@code null}, the media item does not accept setting user rating. 671 * 672 * @param mediaId The id of the media 673 * @param rating The rating to set 674 */ 675 public void setRating(@NonNull String mediaId, @NonNull Rating2 rating) { 676 mProvider.setRating_impl(mediaId, rating); 677 } 678 679 /** 680 * Send custom command to the session 681 * 682 * @param command custom command 683 * @param args optional argument 684 * @param cb optional result receiver 685 */ 686 public void sendCustomCommand(@NonNull SessionCommand2 command, @Nullable Bundle args, 687 @Nullable ResultReceiver cb) { 688 mProvider.sendCustomCommand_impl(command, args, cb); 689 } 690 691 /** 692 * Returns the cached playlist from 693 * {@link ControllerCallback#onPlaylistChanged(MediaController2, List, MediaMetadata2)}. 694 * <p> 695 * This list may differ with the list that was specified with 696 * {@link #setPlaylist(List, MediaMetadata2)} depending on the session implementation. Use media 697 * items returned here for other playlist APIs such as {@link #skipToPlaylistItem(MediaItem2)}. 698 * 699 * @return The playlist. Can be {@code null} if the controller doesn't have enough permission or 700 * the session hasn't set any playlist. 701 */ 702 public @Nullable List<MediaItem2> getPlaylist() { 703 return mProvider.getPlaylist_impl(); 704 } 705 706 /** 707 * Sets the playlist. 708 * <p> 709 * Even when the playlist is successfully set, use the playlist returned from 710 * {@link #getPlaylist()} for playlist APIs such as {@link #skipToPlaylistItem(MediaItem2)}. 711 * Otherwise the session in the remote process can't distinguish between media items. 712 * 713 * @param list playlist 714 * @param metadata metadata of the playlist 715 * @see #getPlaylist() 716 * @see ControllerCallback#onPlaylistChanged(MediaController2, List, MediaMetadata2) 717 */ 718 public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) { 719 mProvider.setPlaylist_impl(list, metadata); 720 } 721 722 /** 723 * Updates the playlist metadata 724 * 725 * @param metadata metadata of the playlist 726 */ 727 public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) { 728 mProvider.updatePlaylistMetadata_impl(metadata); 729 } 730 731 /** 732 * Gets the lastly cached playlist playlist metadata either from 733 * {@link ControllerCallback#onPlaylistMetadataChanged(MediaController2, MediaMetadata2)} or 734 * {@link ControllerCallback#onPlaylistChanged(MediaController2, List, MediaMetadata2)}. 735 * 736 * @return metadata metadata of the playlist, or null if none is set 737 */ 738 public @Nullable MediaMetadata2 getPlaylistMetadata() { 739 return mProvider.getPlaylistMetadata_impl(); 740 } 741 742 743 /** 744 * Adds the media item to the playlist at position index. Index equals or greater than 745 * the current playlist size will add the item at the end of the playlist. 746 * <p> 747 * This will not change the currently playing media item. 748 * If index is less than or equal to the current index of the playlist, 749 * the current index of the playlist will be incremented correspondingly. 750 * 751 * @param index the index you want to add 752 * @param item the media item you want to add 753 */ 754 public void addPlaylistItem(int index, @NonNull MediaItem2 item) { 755 mProvider.addPlaylistItem_impl(index, item); 756 } 757 758 /** 759 * Removes the media item at index in the playlist. 760 *<p> 761 * If the item is the currently playing item of the playlist, current playback 762 * will be stopped and playback moves to next source in the list. 763 * 764 * @param item the media item you want to add 765 */ 766 public void removePlaylistItem(@NonNull MediaItem2 item) { 767 mProvider.removePlaylistItem_impl(item); 768 } 769 770 /** 771 * Replace the media item at index in the playlist. This can be also used to update metadata of 772 * an item. 773 * 774 * @param index the index of the item to replace 775 * @param item the new item 776 */ 777 public void replacePlaylistItem(int index, @NonNull MediaItem2 item) { 778 mProvider.replacePlaylistItem_impl(index, item); 779 } 780 781 /** 782 * Get the lastly cached current item from 783 * {@link ControllerCallback#onCurrentMediaItemChanged(MediaController2, MediaItem2)}. 784 * 785 * @return index of the current item 786 */ 787 public MediaItem2 getCurrentMediaItem() { 788 return mProvider.getCurrentMediaItem_impl(); 789 } 790 791 /** 792 * Skips to the previous item in the playlist. 793 * <p> 794 * This calls {@link MediaSession2#skipToPreviousItem()} if the session allows. 795 */ 796 public void skipToPreviousItem() { 797 mProvider.skipToPreviousItem_impl(); 798 } 799 800 /** 801 * Skips to the next item in the playlist. 802 * <p> 803 * This calls {@link MediaSession2#skipToNextItem()} if the session allows. 804 */ 805 public void skipToNextItem() { 806 mProvider.skipToNextItem_impl(); 807 } 808 809 /** 810 * Skips to the item in the playlist. 811 * <p> 812 * This calls {@link MediaSession2#skipToPlaylistItem(MediaItem2)} if the session allows. 813 * 814 * @param item The item in the playlist you want to play 815 */ 816 public void skipToPlaylistItem(@NonNull MediaItem2 item) { 817 mProvider.skipToPlaylistItem_impl(item); 818 } 819 820 /** 821 * Gets the cached repeat mode from the {@link ControllerCallback#onRepeatModeChanged( 822 * MediaController2, int)}. 823 * 824 * @return repeat mode 825 * @see MediaPlaylistAgent#REPEAT_MODE_NONE 826 * @see MediaPlaylistAgent#REPEAT_MODE_ONE 827 * @see MediaPlaylistAgent#REPEAT_MODE_ALL 828 * @see MediaPlaylistAgent#REPEAT_MODE_GROUP 829 */ 830 public @RepeatMode int getRepeatMode() { 831 return mProvider.getRepeatMode_impl(); 832 } 833 834 /** 835 * Sets the repeat mode. 836 * 837 * @param repeatMode repeat mode 838 * @see MediaPlaylistAgent#REPEAT_MODE_NONE 839 * @see MediaPlaylistAgent#REPEAT_MODE_ONE 840 * @see MediaPlaylistAgent#REPEAT_MODE_ALL 841 * @see MediaPlaylistAgent#REPEAT_MODE_GROUP 842 */ 843 public void setRepeatMode(@RepeatMode int repeatMode) { 844 mProvider.setRepeatMode_impl(repeatMode); 845 } 846 847 /** 848 * Gets the cached shuffle mode from the {@link ControllerCallback#onShuffleModeChanged( 849 * MediaController2, int)}. 850 * 851 * @return The shuffle mode 852 * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE 853 * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL 854 * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP 855 */ 856 public @ShuffleMode int getShuffleMode() { 857 return mProvider.getShuffleMode_impl(); 858 } 859 860 /** 861 * Sets the shuffle mode. 862 * 863 * @param shuffleMode The shuffle mode 864 * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE 865 * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL 866 * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP 867 */ 868 public void setShuffleMode(@ShuffleMode int shuffleMode) { 869 mProvider.setShuffleMode_impl(shuffleMode); 870 } 871} 872