/**
   * Update the current media player state, optionally showing an error message.
   *
   * @param error if not null, error message to present to the user.
   */
  private void updatePlaybackState(String error) {
    LogHelper.d(TAG, "updatePlaybackState, playback state=" + mPlayback.getState());
    long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
    if (mPlayback != null && mPlayback.isConnected()) {
      position = mPlayback.getCurrentStreamPosition();
    }

    PlaybackState.Builder stateBuilder =
        new PlaybackState.Builder().setActions(getAvailableActions());

    setCustomAction(stateBuilder);
    int state = mPlayback.getState();

    // If there is an error message, send it to the playback state:
    if (error != null) {
      // Error states are really only supposed to be used for errors that cause playback to
      // stop unexpectedly and persist until the user takes action to fix it.
      stateBuilder.setErrorMessage(error);
      state = PlaybackState.STATE_ERROR;
    }
    stateBuilder.setState(state, position, 1.0f, SystemClock.elapsedRealtime());

    // Set the activeQueueItemId if the current index is valid.
    if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
      MediaSession.QueueItem item = mPlayingQueue.get(mCurrentIndexOnQueue);
      stateBuilder.setActiveQueueItemId(item.getQueueId());
    }

    mSession.setPlaybackState(stateBuilder.build());

    if (state == PlaybackState.STATE_PLAYING || state == PlaybackState.STATE_PAUSED) {
      mMediaNotificationManager.startNotification();
    }
  }
 public static int getMusicIndexOnQueue(Iterable<MediaSession.QueueItem> queue, long queueId) {
   int index = 0;
   for (MediaSession.QueueItem item : queue) {
     if (queueId == item.getQueueId()) {
       return index;
     }
     index++;
   }
   return -1;
 }
 public static int getMusicIndexOnQueue(Iterable<MediaSession.QueueItem> queue, String mediaId) {
   int index = 0;
   for (MediaSession.QueueItem item : queue) {
     if (mediaId.equals(item.getDescription().getMediaId())) {
       return index;
     }
     index++;
   }
   return -1;
 }
 private MediaMetadata getCurrentPlayingMusic() {
   if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
     MediaSession.QueueItem item = mPlayingQueue.get(mCurrentIndexOnQueue);
     if (item != null) {
       LogHelper.d(TAG, "getCurrentPlayingMusic for musicId=", item.getDescription().getMediaId());
       return mMusicProvider.getMusic(
           MediaIDHelper.extractMusicIDFromMediaID(item.getDescription().getMediaId()));
     }
   }
   return null;
 }
  private void updateMetadata() {
    if (!QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
      LogHelper.e(TAG, "Can't retrieve current metadata.");
      updatePlaybackState(getResources().getString(R.string.error_no_metadata));
      return;
    }
    MediaSession.QueueItem queueItem = mPlayingQueue.get(mCurrentIndexOnQueue);
    String musicId =
        MediaIDHelper.extractMusicIDFromMediaID(queueItem.getDescription().getMediaId());
    MediaMetadata track = mMusicProvider.getMusic(musicId);
    final String trackId = track.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
    if (!musicId.equals(trackId)) {
      IllegalStateException e = new IllegalStateException("track ID should match musicId.");
      LogHelper.e(
          TAG,
          "track ID should match musicId.",
          " musicId=",
          musicId,
          " trackId=",
          trackId,
          " mediaId from queueItem=",
          queueItem.getDescription().getMediaId(),
          " title from queueItem=",
          queueItem.getDescription().getTitle(),
          " mediaId from track=",
          track.getDescription().getMediaId(),
          " title from track=",
          track.getDescription().getTitle(),
          " source.hashcode from track=",
          track.getString(MusicProvider.CUSTOM_METADATA_TRACK_SOURCE).hashCode(),
          e);
      throw e;
    }
    LogHelper.d(TAG, "Updating metadata for MusicID= " + musicId);
    mSession.setMetadata(track);

    // Set the proper album artwork on the media session, so it can be shown in the
    // locked screen and in other places.
    if (track.getDescription().getIconBitmap() == null
        && track.getDescription().getIconUri() != null) {
      String albumUri = track.getDescription().getIconUri().toString();
      AlbumArtCache.getInstance()
          .fetch(
              albumUri,
              new AlbumArtCache.FetchListener() {
                @Override
                public void onFetched(String artUrl, Bitmap bitmap, Bitmap icon) {
                  MediaSession.QueueItem queueItem = mPlayingQueue.get(mCurrentIndexOnQueue);
                  MediaMetadata track = mMusicProvider.getMusic(trackId);
                  track =
                      new MediaMetadata.Builder(track)

                          // set high resolution bitmap in METADATA_KEY_ALBUM_ART. This is used, for
                          // example, on the lockscreen background when the media session is active.
                          .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)

                          // set small version of the album art in the DISPLAY_ICON. This is used on
                          // the MediaDescription and thus it should be small to be serialized if
                          // necessary..
                          .putBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON, icon)
                          .build();

                  MediaDescription md;
                  mMusicProvider.updateMusic(trackId, track);

                  // If we are still playing the same music
                  String currentPlayingId =
                      MediaIDHelper.extractMusicIDFromMediaID(
                          queueItem.getDescription().getMediaId());
                  if (trackId.equals(currentPlayingId)) {
                    mSession.setMetadata(track);
                  }
                }
              });
    }
  }