1 /* 2 * Copyright (C) 2017 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 com.android.car.media.drawer; 17 18 import android.graphics.PorterDuff; 19 import android.graphics.drawable.Drawable; 20 import android.media.session.MediaController; 21 import android.media.session.MediaSession; 22 import android.media.session.PlaybackState; 23 import android.os.Handler; 24 import android.support.annotation.Nullable; 25 26 import com.android.car.app.CarDrawerActivity; 27 import com.android.car.app.DrawerItemViewHolder; 28 import com.android.car.media.MediaPlaybackModel; 29 import com.android.car.media.R; 30 31 import java.util.ArrayList; 32 import java.util.Collections; 33 import java.util.List; 34 35 /** 36 * {@link MediaItemsFetcher} implementation that fetches items from the {@link MediaController}'s 37 * currently playing queue. 38 */ 39 class MediaQueueItemsFetcher implements MediaItemsFetcher { 40 private static final String TAG = "MediaQueueItemsFetcher"; 41 42 private final Handler mHandler = new Handler(); 43 private final CarDrawerActivity mActivity; 44 private MediaPlaybackModel mMediaPlaybackModel; 45 private ItemsUpdatedCallback mCallback; 46 private List<MediaSession.QueueItem> mItems = new ArrayList<>(); 47 MediaQueueItemsFetcher(CarDrawerActivity activity, MediaPlaybackModel model)48 MediaQueueItemsFetcher(CarDrawerActivity activity, MediaPlaybackModel model) { 49 mActivity = activity; 50 mMediaPlaybackModel = model; 51 } 52 53 @Override start(ItemsUpdatedCallback callback)54 public void start(ItemsUpdatedCallback callback) { 55 mCallback = callback; 56 if (mMediaPlaybackModel != null) { 57 mMediaPlaybackModel.addListener(listener); 58 updateItemsFrom(mMediaPlaybackModel.getQueue()); 59 } 60 // Inform client of current items. Invoke async to avoid re-entrancy issues. 61 mHandler.post(mCallback::onItemsUpdated); 62 } 63 64 @Override getItemCount()65 public int getItemCount() { 66 return mItems.size(); 67 } 68 69 @Override populateViewHolder(DrawerItemViewHolder holder, int position)70 public void populateViewHolder(DrawerItemViewHolder holder, int position) { 71 MediaSession.QueueItem item = mItems.get(position); 72 MediaItemsFetcher.populateViewHolderFrom(holder, item.getDescription()); 73 74 if (item.getQueueId() == getActiveQueueItemId()) { 75 int primaryColor = mMediaPlaybackModel.getPrimaryColor(); 76 Drawable drawable = 77 mActivity.getResources().getDrawable(R.drawable.ic_music_active); 78 drawable.setColorFilter(primaryColor, PorterDuff.Mode.SRC_IN); 79 holder.getRightIcon().setImageDrawable(drawable); 80 } else { 81 holder.getRightIcon().setImageBitmap(null); 82 } 83 } 84 85 @Override onItemClick(int position)86 public void onItemClick(int position) { 87 MediaController.TransportControls controls = mMediaPlaybackModel.getTransportControls(); 88 if (controls != null) { 89 controls.skipToQueueItem(mItems.get(position).getQueueId()); 90 } 91 mActivity.closeDrawer(); 92 } 93 94 @Override cleanup()95 public void cleanup() { 96 mMediaPlaybackModel.removeListener(listener); 97 } 98 updateItemsFrom(List<MediaSession.QueueItem> queue)99 private void updateItemsFrom(List<MediaSession.QueueItem> queue) { 100 mItems.clear(); 101 // We only show items starting from active-item in the queue. 102 final long activeItemId = getActiveQueueItemId(); 103 boolean activeItemFound = false; 104 for (MediaSession.QueueItem item : queue) { 105 if (activeItemId == item.getQueueId()) { 106 activeItemFound = true; 107 } 108 if (activeItemFound) { 109 mItems.add(item); 110 } 111 } 112 } 113 getActiveQueueItemId()114 private long getActiveQueueItemId() { 115 if (mMediaPlaybackModel != null) { 116 PlaybackState playbackState = mMediaPlaybackModel.getPlaybackState(); 117 if (playbackState != null) { 118 return playbackState.getActiveQueueItemId(); 119 } 120 } 121 return MediaSession.QueueItem.UNKNOWN_ID; 122 } 123 124 private final MediaPlaybackModel.Listener listener = new MediaPlaybackModel.AbstractListener() { 125 @Override 126 public void onQueueChanged(List<MediaSession.QueueItem> queue) { 127 updateItemsFrom(queue); 128 mCallback.onItemsUpdated(); 129 } 130 131 @Override 132 public void onPlaybackStateChanged(@Nullable PlaybackState state) { 133 // Since active playing item may have changed, force re-draw of queue items. 134 mCallback.onItemsUpdated(); 135 } 136 137 @Override 138 public void onSessionDestroyed(CharSequence destroyedMediaClientName) { 139 onQueueChanged(Collections.emptyList()); 140 } 141 }; 142 } 143