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