import android.media.AudioManager;
import android.media.MediaDescription;
import android.media.MediaMetadata;
-import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSession.QueueItem;
import android.media.session.MediaSessionManager;
new MediaSessionManager.OnActiveSessionsChangedListener() {
@Override
- public void onActiveSessionsChanged(List<MediaController> mediaControllerList) {
+ public void onActiveSessionsChanged(List<android.media.session.MediaController> mediaControllerList) {
if (DEBUG) Log.v(TAG, "received onActiveSessionsChanged");
- if (isAvailablePlayersChanged(mediaControllerList)) {
+ List<MediaController> mediaControllerListTemp = new ArrayList<MediaController>();
+ for (android.media.session.MediaController temp : mediaControllerList) {
+ mediaControllerListTemp.add(MediaController.wrap(temp));
+ }
+
+ if (isAvailablePlayersChanged(mediaControllerListTemp)) {
// rebuild the list cached locally in this file
buildMediaPlayersList();
// inform the remote device that the player list has changed
sendAvailablePlayersChanged();
- } else if (isAddressedPlayerChanged(mediaControllerList)) {
- int newAddrPlayerID = getNewAddrPlayerID(mediaControllerList.get(0)
+ } else if (isAddressedPlayerChanged(mediaControllerListTemp)) {
+ int newAddrPlayerID = getNewAddrPlayerID(mediaControllerListTemp.get(0)
.getPackageName());
// inform the remote device that the addressed player has changed
sendAddressedPlayerChanged(newAddrPlayerID);
mMediaPlayerInfoList.clear();
/* Initializing all media players */
- for (MediaController mediaController : getActiveControllersList()) {
- initMediaPlayer(mediaController);
+ for (android.media.session.MediaController mediaController : getActiveControllersList()) {
+ initMediaPlayer(MediaController.wrap(mediaController));
}
}
/* Using session manager apis, getting the list of active media controllers */
- private List<MediaController> getActiveControllersList() {
- List<MediaController> controllersList = new ArrayList<MediaController>();
+ private List<android.media.session.MediaController> getActiveControllersList() {
+ List<android.media.session.MediaController> controllersList =
+ new ArrayList<android.media.session.MediaController>();
controllersList = mMediaSessionManager.getActiveSessions(null);
Log.i(TAG, "getActiveControllersList: " + controllersList.size() + " controllers");
return controllersList;
--- /dev/null
+package com.android.bluetooth.avrcp;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.pm.ParceledListSlice;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.MediaMetadata;
+import android.media.Rating;
+import android.media.VolumeProvider;
+import android.media.session.PlaybackState;
+import android.media.session.MediaSession;
+import android.media.session.MediaSession.QueueItem;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MediaController {
+ public android.media.session.MediaController mDelegate;
+ public android.media.session.MediaController.TransportControls mTransportDelegate;
+ public TransportControls mTransportControls;
+
+ @Nullable
+ public static MediaController wrap(@Nullable android.media.session.MediaController delegate) {
+ return (delegate != null) ? new MediaController(delegate) : null;
+ }
+
+ public MediaController(@NonNull android.media.session.MediaController delegate) {
+ mDelegate = delegate;
+ mTransportDelegate = delegate.getTransportControls();
+ mTransportControls = new TransportControls();
+ }
+
+ public android.media.session.MediaController getWrappedInstance() {
+ return mDelegate;
+ }
+
+ public @NonNull TransportControls getTransportControls() {
+ return mTransportControls;
+ }
+
+ public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) {
+ return mDelegate.dispatchMediaButtonEvent(keyEvent);
+ }
+
+ public @Nullable PlaybackState getPlaybackState() {
+ return mDelegate.getPlaybackState();
+ }
+
+ public @Nullable MediaMetadata getMetadata() {
+ return mDelegate.getMetadata();
+ }
+
+ public @Nullable List<MediaSession.QueueItem> getQueue() {
+ return mDelegate.getQueue();
+ }
+
+ public @Nullable CharSequence getQueueTitle() {
+ return mDelegate.getQueueTitle();
+ }
+
+ public @Nullable Bundle getExtras() {
+ return mDelegate.getExtras();
+ }
+
+ public int getRatingType() {
+ return mDelegate.getRatingType();
+ }
+
+ public long getFlags() {
+ return mDelegate.getFlags();
+ }
+
+ public @Nullable android.media.session.MediaController.PlaybackInfo getPlaybackInfo() {
+ return mDelegate.getPlaybackInfo();
+ }
+
+ public @Nullable PendingIntent getSessionActivity() {
+ return mDelegate.getSessionActivity();
+ }
+
+ public @NonNull MediaSession.Token getSessionToken() {
+ return mDelegate.getSessionToken();
+ }
+
+ public void setVolumeTo(int value, int flags) {
+ mDelegate.setVolumeTo(value, flags);
+ }
+
+ public void adjustVolume(int direction, int flags) {
+ mDelegate.adjustVolume(direction, flags);
+ }
+
+ public void registerCallback(@NonNull Callback callback) {
+ //TODO(apanicke): Add custom callback struct to be able to analyze and
+ // delegate callbacks
+ mDelegate.registerCallback(callback);
+ }
+
+ public void registerCallback(@NonNull Callback callback, @Nullable Handler handler) {
+ mDelegate.registerCallback(callback, handler);
+ }
+
+ public void unregisterCallback(@NonNull Callback callback) {
+ mDelegate.unregisterCallback(callback);
+ }
+
+ public void sendCommand(@NonNull String command, @Nullable Bundle args,
+ @Nullable ResultReceiver cb) {
+ mDelegate.sendCommand(command, args, cb);
+ }
+
+ public String getPackageName() {
+ return mDelegate.getPackageName();
+ }
+
+ public String getTag() {
+ return mDelegate.getTag();
+ }
+
+ public boolean controlsSameSession(MediaController other) {
+ return mDelegate.controlsSameSession(other.getWrappedInstance());
+ }
+
+ public boolean controlsSameSession(android.media.session.MediaController other) {
+ return mDelegate.controlsSameSession(other);
+ }
+
+ public static abstract class Callback extends android.media.session.MediaController.Callback { }
+
+ public class TransportControls {
+
+ public void prepare() {
+ mTransportDelegate.prepare();
+ }
+
+ public void prepareFromMediaId(String mediaId, Bundle extras) {
+ mTransportDelegate.prepareFromMediaId(mediaId, extras);
+ }
+
+ public void prepareFromSearch(String query, Bundle extras) {
+ mTransportDelegate.prepareFromSearch(query, extras);
+ }
+
+ public void prepareFromUri(Uri uri, Bundle extras) {
+ mTransportDelegate.prepareFromUri(uri, extras);
+ }
+
+ public void play() {
+ mTransportDelegate.play();
+ }
+
+ public void playFromMediaId(String mediaId, Bundle extras) {
+ mTransportDelegate.playFromMediaId(mediaId, extras);
+ }
+
+ public void playFromSearch(String query, Bundle extras) {
+ mTransportDelegate.playFromSearch(query, extras);
+ }
+
+ public void playFromUri(Uri uri, Bundle extras) {
+ mTransportDelegate.playFromUri(uri, extras);
+ }
+
+ public void skipToQueueItem(long id) {
+ mTransportDelegate.skipToQueueItem(id);
+ }
+
+ public void pause() {
+ mTransportDelegate.pause();
+ }
+
+ public void stop() {
+ mTransportDelegate.stop();
+ }
+
+ public void seekTo(long pos) {
+ mTransportDelegate.seekTo(pos);
+ }
+
+ public void fastForward() {
+ mTransportDelegate.fastForward();
+ }
+
+ public void skipToNext() {
+ mTransportDelegate.skipToNext();
+ }
+
+ public void rewind() {
+ mTransportDelegate.rewind();
+ }
+
+ public void skipToPrevious() {
+ mTransportDelegate.skipToPrevious();
+ }
+
+ public void setRating(Rating rating) {
+ mTransportDelegate.setRating(rating);
+ }
+
+ public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction,
+ @Nullable Bundle args) {
+ mTransportDelegate.sendCustomAction(customAction, args);
+ }
+
+ public void sendCustomAction(@NonNull String action, @Nullable Bundle args) {
+ mTransportDelegate.sendCustomAction(action, args);
+ }
+ }
+}
+
--- /dev/null
+package com.android.bluetooth.avrcp;
+
+import android.bluetooth.BluetoothAvrcp;
+import android.media.session.MediaSession;
+import android.media.session.MediaSession.QueueItem;
+import android.media.MediaDescription;
+import android.media.MediaMetadata;
+import android.os.Bundle;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+import static org.mockito.Mockito.*;
+
+public class AddressedMediaPlayerTest extends AndroidTestCase {
+
+ public void testHandlePassthroughCmd() {
+ MediaController mockController = mock(com.android.bluetooth.avrcp.MediaController.class);
+ MediaController.TransportControls mockTransport = mock(MediaController.TransportControls.class);
+ AvrcpMediaRspInterface mockRspInterface = mock(AvrcpMediaRspInterface.class);
+
+ when(mockController.getTransportControls()).thenReturn(mockTransport);
+ AddressedMediaPlayer myMediaPlayer = new AddressedMediaPlayer(mockRspInterface);
+
+
+ // Test rewind
+ myMediaPlayer.handlePassthroughCmd(BluetoothAvrcp.PASSTHROUGH_ID_REWIND,
+ AvrcpConstants.KEY_STATE_PRESS,
+ null,
+ mockController);
+ verify(mockTransport).rewind();
+
+ // Test fast forward
+ myMediaPlayer.handlePassthroughCmd(BluetoothAvrcp.PASSTHROUGH_ID_FAST_FOR,
+ AvrcpConstants.KEY_STATE_PRESS,
+ null,
+ mockController);
+ verify(mockTransport).fastForward();
+
+ // Test play
+ myMediaPlayer.handlePassthroughCmd(BluetoothAvrcp.PASSTHROUGH_ID_PLAY,
+ AvrcpConstants.KEY_STATE_PRESS,
+ null,
+ mockController);
+ verify(mockTransport).play();
+
+ // Test pause
+ myMediaPlayer.handlePassthroughCmd(BluetoothAvrcp.PASSTHROUGH_ID_PAUSE,
+ AvrcpConstants.KEY_STATE_PRESS,
+ null,
+ mockController);
+ verify(mockTransport).pause();
+
+ // Test stop
+ myMediaPlayer.handlePassthroughCmd(BluetoothAvrcp.PASSTHROUGH_ID_STOP,
+ AvrcpConstants.KEY_STATE_PRESS,
+ null,
+ mockController);
+ verify(mockTransport).stop();
+
+ // Test skip to next
+ myMediaPlayer.handlePassthroughCmd(BluetoothAvrcp.PASSTHROUGH_ID_FORWARD,
+ AvrcpConstants.KEY_STATE_PRESS,
+ null,
+ mockController);
+ verify(mockTransport).skipToNext();
+
+ // Test skip backwards
+ myMediaPlayer.handlePassthroughCmd(BluetoothAvrcp.PASSTHROUGH_ID_BACKWARD,
+ AvrcpConstants.KEY_STATE_PRESS,
+ null,
+ mockController);
+ verify(mockTransport).skipToPrevious();
+
+ // Test invalid key
+ myMediaPlayer.handlePassthroughCmd(0xFF,
+ AvrcpConstants.KEY_STATE_PRESS,
+ null,
+ mockController);
+ verifyNoMoreInteractions(mockTransport);
+
+ // Test key release
+ myMediaPlayer.handlePassthroughCmd(BluetoothAvrcp.PASSTHROUGH_ID_PLAY,
+ AvrcpConstants.KEY_STATE_RELEASE,
+ null,
+ mockController);
+ verifyNoMoreInteractions(mockTransport);
+ }
+}