1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.S; 4 import static org.robolectric.util.ReflectionHelpers.createDeepProxy; 5 import static org.robolectric.util.reflector.Reflector.reflector; 6 7 import android.content.ComponentName; 8 import android.content.Context; 9 import android.media.session.ISessionManager; 10 import android.media.session.MediaController; 11 import android.media.session.MediaSessionManager; 12 import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener; 13 import android.os.Handler; 14 import com.google.common.collect.ImmutableList; 15 import java.util.List; 16 import java.util.Set; 17 import java.util.concurrent.CopyOnWriteArrayList; 18 import java.util.concurrent.CopyOnWriteArraySet; 19 import org.robolectric.annotation.Implementation; 20 import org.robolectric.annotation.Implements; 21 import org.robolectric.annotation.RealObject; 22 import org.robolectric.annotation.Resetter; 23 import org.robolectric.util.reflector.Accessor; 24 import org.robolectric.util.reflector.ForType; 25 26 /** Shadow for {@link MediaSessionManager}. */ 27 @Implements(value = MediaSessionManager.class) 28 public class ShadowMediaSessionManager { 29 private static final List<MediaController> controllers = new CopyOnWriteArrayList<>(); 30 private static final Set<OnActiveSessionsChangedListener> listeners = new CopyOnWriteArraySet<>(); 31 @RealObject MediaSessionManager realMediaSessionManager; 32 33 @Implementation(minSdk = S) __constructor__(Context context)34 protected void __constructor__(Context context) { 35 // the real constructor throws NPE when trying to load the service 36 reflector(MediaSessionManagerReflector.class, realMediaSessionManager).setContext(context); 37 reflector(MediaSessionManagerReflector.class, realMediaSessionManager) 38 .setService(createDeepProxy(ISessionManager.class)); 39 } 40 41 @Implementation getActiveSessions(ComponentName ignoredNotificationListener)42 protected List<MediaController> getActiveSessions(ComponentName ignoredNotificationListener) { 43 return ImmutableList.copyOf(controllers); 44 } 45 46 @Implementation addOnActiveSessionsChangedListener( OnActiveSessionsChangedListener listener, ComponentName ignoredNotificationListener)47 protected void addOnActiveSessionsChangedListener( 48 OnActiveSessionsChangedListener listener, ComponentName ignoredNotificationListener) { 49 listeners.add(listener); 50 } 51 52 @Implementation addOnActiveSessionsChangedListener( OnActiveSessionsChangedListener listener, ComponentName ignoredNotificationListener, Handler ignoreHandler)53 protected void addOnActiveSessionsChangedListener( 54 OnActiveSessionsChangedListener listener, 55 ComponentName ignoredNotificationListener, 56 Handler ignoreHandler) { 57 listeners.add(listener); 58 } 59 60 @Implementation removeOnActiveSessionsChangedListener(OnActiveSessionsChangedListener listener)61 protected void removeOnActiveSessionsChangedListener(OnActiveSessionsChangedListener listener) { 62 listeners.remove(listener); 63 } 64 65 /** 66 * Adds a {@link MediaController} that will be returned when calling {@link 67 * #getActiveSessions(ComponentName)}. This will trigger a callback on each {@link 68 * OnActiveSessionsChangedListener} callback registered with this class. 69 * 70 * @param controller The controller to add. 71 */ addController(MediaController controller)72 public void addController(MediaController controller) { 73 controllers.add(controller); 74 for (OnActiveSessionsChangedListener listener : listeners) { 75 listener.onActiveSessionsChanged(controllers); 76 } 77 } 78 79 /** 80 * Clears all controllers such that {@link #getActiveSessions(ComponentName)} will return the 81 * empty list. This will trigger a callback on each {@link OnActiveSessionsChangedListener} 82 * callback registered with this class. 83 */ clearControllers()84 public void clearControllers() { 85 controllers.clear(); 86 for (OnActiveSessionsChangedListener listener : listeners) { 87 listener.onActiveSessionsChanged(controllers); 88 } 89 } 90 91 @Resetter reset()92 public static void reset() { 93 controllers.clear(); 94 listeners.clear(); 95 } 96 97 @ForType(MediaSessionManager.class) 98 interface MediaSessionManagerReflector { 99 100 @Accessor("mContext") setContext(Context context)101 void setContext(Context context); 102 103 @Accessor("mService") setService(ISessionManager service)104 void setService(ISessionManager service); 105 } 106 } 107