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 */ 16 17 package android.support.v4.media.session; 18 19 import android.app.PendingIntent; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.media.AudioAttributes; 23 import android.media.MediaDescription; 24 import android.media.MediaMetadata; 25 import android.media.Rating; 26 import android.media.VolumeProvider; 27 import android.media.session.MediaSession; 28 import android.media.session.PlaybackState; 29 import android.os.Bundle; 30 import android.os.Handler; 31 import android.os.Parcelable; 32 import android.os.ResultReceiver; 33 import android.support.annotation.RequiresApi; 34 import android.util.Log; 35 36 import java.lang.reflect.Field; 37 import java.util.ArrayList; 38 import java.util.List; 39 40 @RequiresApi(21) 41 class MediaSessionCompatApi21 { 42 static final String TAG = "MediaSessionCompatApi21"; 43 createSession(Context context, String tag)44 public static Object createSession(Context context, String tag) { 45 return new MediaSession(context, tag); 46 } 47 verifySession(Object mediaSession)48 public static Object verifySession(Object mediaSession) { 49 if (mediaSession instanceof MediaSession) { 50 return mediaSession; 51 } 52 throw new IllegalArgumentException("mediaSession is not a valid MediaSession object"); 53 } 54 verifyToken(Object token)55 public static Object verifyToken(Object token) { 56 if (token instanceof MediaSession.Token) { 57 return token; 58 } 59 throw new IllegalArgumentException("token is not a valid MediaSession.Token object"); 60 } 61 createCallback(Callback callback)62 public static Object createCallback(Callback callback) { 63 return new CallbackProxy<Callback>(callback); 64 } 65 setCallback(Object sessionObj, Object callbackObj, Handler handler)66 public static void setCallback(Object sessionObj, Object callbackObj, Handler handler) { 67 ((MediaSession) sessionObj).setCallback((MediaSession.Callback) callbackObj, handler); 68 } 69 setFlags(Object sessionObj, int flags)70 public static void setFlags(Object sessionObj, int flags) { 71 ((MediaSession)sessionObj).setFlags(flags); 72 } 73 setPlaybackToLocal(Object sessionObj, int stream)74 public static void setPlaybackToLocal(Object sessionObj, int stream) { 75 // TODO update APIs to use support version of AudioAttributes 76 AudioAttributes.Builder bob = new AudioAttributes.Builder(); 77 bob.setLegacyStreamType(stream); 78 ((MediaSession) sessionObj).setPlaybackToLocal(bob.build()); 79 } 80 setPlaybackToRemote(Object sessionObj, Object volumeProviderObj)81 public static void setPlaybackToRemote(Object sessionObj, Object volumeProviderObj) { 82 ((MediaSession)sessionObj).setPlaybackToRemote((VolumeProvider)volumeProviderObj); 83 } 84 setActive(Object sessionObj, boolean active)85 public static void setActive(Object sessionObj, boolean active) { 86 ((MediaSession)sessionObj).setActive(active); 87 } 88 isActive(Object sessionObj)89 public static boolean isActive(Object sessionObj) { 90 return ((MediaSession)sessionObj).isActive(); 91 } 92 sendSessionEvent(Object sessionObj, String event, Bundle extras)93 public static void sendSessionEvent(Object sessionObj, String event, Bundle extras) { 94 ((MediaSession)sessionObj).sendSessionEvent(event, extras); 95 } 96 release(Object sessionObj)97 public static void release(Object sessionObj) { 98 ((MediaSession)sessionObj).release(); 99 } 100 getSessionToken(Object sessionObj)101 public static Parcelable getSessionToken(Object sessionObj) { 102 return ((MediaSession)sessionObj).getSessionToken(); 103 } 104 setPlaybackState(Object sessionObj, Object stateObj)105 public static void setPlaybackState(Object sessionObj, Object stateObj) { 106 ((MediaSession)sessionObj).setPlaybackState((PlaybackState)stateObj); 107 } 108 setMetadata(Object sessionObj, Object metadataObj)109 public static void setMetadata(Object sessionObj, Object metadataObj) { 110 ((MediaSession)sessionObj).setMetadata((MediaMetadata)metadataObj); 111 } 112 setSessionActivity(Object sessionObj, PendingIntent pi)113 public static void setSessionActivity(Object sessionObj, PendingIntent pi) { 114 ((MediaSession) sessionObj).setSessionActivity(pi); 115 } 116 setMediaButtonReceiver(Object sessionObj, PendingIntent pi)117 public static void setMediaButtonReceiver(Object sessionObj, PendingIntent pi) { 118 ((MediaSession) sessionObj).setMediaButtonReceiver(pi); 119 } 120 setQueue(Object sessionObj, List<Object> queueObjs)121 public static void setQueue(Object sessionObj, List<Object> queueObjs) { 122 if (queueObjs == null) { 123 ((MediaSession) sessionObj).setQueue(null); 124 return; 125 } 126 ArrayList<MediaSession.QueueItem> queue = new ArrayList<MediaSession.QueueItem>(); 127 for (Object itemObj : queueObjs) { 128 queue.add((MediaSession.QueueItem) itemObj); 129 } 130 ((MediaSession) sessionObj).setQueue(queue); 131 } 132 setQueueTitle(Object sessionObj, CharSequence title)133 public static void setQueueTitle(Object sessionObj, CharSequence title) { 134 ((MediaSession) sessionObj).setQueueTitle(title); 135 } 136 setExtras(Object sessionObj, Bundle extras)137 public static void setExtras(Object sessionObj, Bundle extras) { 138 ((MediaSession) sessionObj).setExtras(extras); 139 } 140 hasCallback(Object sessionObj)141 public static boolean hasCallback(Object sessionObj) { 142 Field callbackField = null; 143 try { 144 callbackField = sessionObj.getClass().getDeclaredField("mCallback"); 145 if (callbackField != null) { 146 callbackField.setAccessible(true); 147 return callbackField.get(sessionObj) != null; 148 } 149 } catch (NoSuchFieldException | IllegalAccessException e) { 150 Log.w(TAG, "Failed to get mCallback object."); 151 } 152 return false; 153 } 154 155 interface Callback { onCommand(String command, Bundle extras, ResultReceiver cb)156 void onCommand(String command, Bundle extras, ResultReceiver cb); onMediaButtonEvent(Intent mediaButtonIntent)157 boolean onMediaButtonEvent(Intent mediaButtonIntent); onPlay()158 void onPlay(); onPlayFromMediaId(String mediaId, Bundle extras)159 void onPlayFromMediaId(String mediaId, Bundle extras); onPlayFromSearch(String search, Bundle extras)160 void onPlayFromSearch(String search, Bundle extras); onSkipToQueueItem(long id)161 void onSkipToQueueItem(long id); onPause()162 void onPause(); onSkipToNext()163 void onSkipToNext(); onSkipToPrevious()164 void onSkipToPrevious(); onFastForward()165 void onFastForward(); onRewind()166 void onRewind(); onStop()167 void onStop(); onSeekTo(long position)168 void onSeekTo(long position); onSetRating(Object ratingObject)169 void onSetRating(Object ratingObject); onCustomAction(String action, Bundle extras)170 void onCustomAction(String action, Bundle extras); 171 } 172 173 static class CallbackProxy<T extends Callback> extends MediaSession.Callback { 174 protected final T mCallback; 175 CallbackProxy(T callback)176 public CallbackProxy(T callback) { 177 mCallback = callback; 178 } 179 180 @Override onCommand(String command, Bundle args, ResultReceiver cb)181 public void onCommand(String command, Bundle args, ResultReceiver cb) { 182 mCallback.onCommand(command, args, cb); 183 } 184 185 @Override onMediaButtonEvent(Intent mediaButtonIntent)186 public boolean onMediaButtonEvent(Intent mediaButtonIntent) { 187 return mCallback.onMediaButtonEvent(mediaButtonIntent) 188 || super.onMediaButtonEvent(mediaButtonIntent); 189 } 190 191 @Override onPlay()192 public void onPlay() { 193 mCallback.onPlay(); 194 } 195 196 @Override onPlayFromMediaId(String mediaId, Bundle extras)197 public void onPlayFromMediaId(String mediaId, Bundle extras) { 198 mCallback.onPlayFromMediaId(mediaId, extras); 199 } 200 201 @Override onPlayFromSearch(String search, Bundle extras)202 public void onPlayFromSearch(String search, Bundle extras) { 203 mCallback.onPlayFromSearch(search, extras); 204 } 205 206 @Override onSkipToQueueItem(long id)207 public void onSkipToQueueItem(long id) { 208 mCallback.onSkipToQueueItem(id); 209 } 210 211 @Override onPause()212 public void onPause() { 213 mCallback.onPause(); 214 } 215 216 @Override onSkipToNext()217 public void onSkipToNext() { 218 mCallback.onSkipToNext(); 219 } 220 221 @Override onSkipToPrevious()222 public void onSkipToPrevious() { 223 mCallback.onSkipToPrevious(); 224 } 225 226 @Override onFastForward()227 public void onFastForward() { 228 mCallback.onFastForward(); 229 } 230 231 @Override onRewind()232 public void onRewind() { 233 mCallback.onRewind(); 234 } 235 236 @Override onStop()237 public void onStop() { 238 mCallback.onStop(); 239 } 240 241 @Override onSeekTo(long pos)242 public void onSeekTo(long pos) { 243 mCallback.onSeekTo(pos); 244 } 245 246 @Override onSetRating(Rating rating)247 public void onSetRating(Rating rating) { 248 mCallback.onSetRating(rating); 249 } 250 251 @Override onCustomAction(String action, Bundle extras)252 public void onCustomAction(String action, Bundle extras) { 253 mCallback.onCustomAction(action, extras); 254 } 255 } 256 257 static class QueueItem { 258 createItem(Object mediaDescription, long id)259 public static Object createItem(Object mediaDescription, long id) { 260 return new MediaSession.QueueItem((MediaDescription) mediaDescription, id); 261 } 262 getDescription(Object queueItem)263 public static Object getDescription(Object queueItem) { 264 return ((MediaSession.QueueItem) queueItem).getDescription(); 265 } 266 getQueueId(Object queueItem)267 public static long getQueueId(Object queueItem) { 268 return ((MediaSession.QueueItem) queueItem).getQueueId(); 269 } 270 } 271 } 272