• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static org.robolectric.util.reflector.Reflector.reflector;
4 
5 import android.app.PendingIntent;
6 import android.media.MediaMetadata;
7 import android.media.Rating;
8 import android.media.session.MediaController;
9 import android.media.session.MediaController.Callback;
10 import android.media.session.MediaController.PlaybackInfo;
11 import android.media.session.PlaybackState;
12 import android.os.Bundle;
13 import android.os.Handler;
14 import java.util.ArrayList;
15 import java.util.List;
16 import javax.annotation.Nonnull;
17 import javax.annotation.Nullable;
18 import org.robolectric.annotation.Implementation;
19 import org.robolectric.annotation.Implements;
20 import org.robolectric.annotation.RealObject;
21 import org.robolectric.util.ReflectionHelpers;
22 import org.robolectric.util.ReflectionHelpers.ClassParameter;
23 import org.robolectric.util.reflector.Direct;
24 import org.robolectric.util.reflector.ForType;
25 
26 /** Implementation of {@link android.media.session.MediaController}. */
27 @Implements(value = MediaController.class)
28 public class ShadowMediaController {
29   @RealObject private MediaController realMediaController;
30   private PlaybackState playbackState;
31   private PlaybackInfo playbackInfo;
32   private MediaMetadata mediaMetadata;
33   private PendingIntent sessionActivity;
34   private Bundle extras;
35 
36   /**
37    * A value of RATING_NONE for ratingType indicates that rating media is not supported by the media
38    * session associated with the media controller
39    */
40   private int ratingType = Rating.RATING_NONE;
41 
42   private final List<Callback> callbacks = new ArrayList<>();
43 
44   /** Saves the package name for use inside the shadow. */
setPackageName(String packageName)45   public void setPackageName(String packageName) {
46     ReflectionHelpers.setField(realMediaController, "mPackageName", packageName);
47   }
48 
49   /**
50    * Saves the playbackState to control the return value of {@link
51    * MediaController#getPlaybackState()}.
52    */
setPlaybackState(PlaybackState playbackState)53   public void setPlaybackState(PlaybackState playbackState) {
54     this.playbackState = playbackState;
55   }
56 
57   /** Gets the playbackState set via {@link #setPlaybackState}. */
58   @Implementation
getPlaybackState()59   protected PlaybackState getPlaybackState() {
60     return playbackState;
61   }
62 
63   /**
64    * Saves the playbackInfo to control the return value of {@link
65    * MediaController#getPlaybackInfo()}.
66    *
67    * <p>{@link PlaybackInfoBuilder} can be used to create PlaybackInfo instances.
68    */
setPlaybackInfo(PlaybackInfo playbackInfo)69   public void setPlaybackInfo(PlaybackInfo playbackInfo) {
70     this.playbackInfo = playbackInfo;
71   }
72 
73   /** Gets the playbackInfo set via {@link #setPlaybackInfo}. */
74   @Implementation
getPlaybackInfo()75   protected PlaybackInfo getPlaybackInfo() {
76     return playbackInfo;
77   }
78 
79   /**
80    * Saves the mediaMetadata to control the return value of {@link MediaController#getMetadata()}.
81    */
setMetadata(MediaMetadata mediaMetadata)82   public void setMetadata(MediaMetadata mediaMetadata) {
83     this.mediaMetadata = mediaMetadata;
84   }
85 
86   /** Gets the mediaMetadata set via {@link #setMetadata}. */
87   @Implementation
getMetadata()88   protected MediaMetadata getMetadata() {
89     return mediaMetadata;
90   }
91 
92   /**
93    * Saves the rating type to control the return value of {@link MediaController#getRatingType()}.
94    */
setRatingType(int ratingType)95   public void setRatingType(int ratingType) {
96     if (ratingType >= 0 && ratingType <= Rating.RATING_PERCENTAGE) {
97       this.ratingType = ratingType;
98     } else {
99       throw new IllegalArgumentException(
100           "Invalid RatingType value "
101               + ratingType
102               + ". The valid range is from 0 to "
103               + Rating.RATING_PERCENTAGE);
104     }
105   }
106 
107   /** Gets the rating type set via {@link #setRatingType}. */
108   @Implementation
getRatingType()109   protected int getRatingType() {
110     return ratingType;
111   }
112 
113   /**
114    * Saves the sessionActivity to control the return value of {@link
115    * MediaController#getSessionActivity()}.
116    */
setSessionActivity(PendingIntent sessionActivity)117   public void setSessionActivity(PendingIntent sessionActivity) {
118     this.sessionActivity = sessionActivity;
119   }
120 
121   /** Gets the playbackState set via {@link #setSessionActivity}. */
122   @Implementation
getSessionActivity()123   protected PendingIntent getSessionActivity() {
124     return sessionActivity;
125   }
126 
127   /** Saves the extras to control the return value of {@link MediaController#getExtras()}. */
setExtras(Bundle extras)128   public void setExtras(Bundle extras) {
129     this.extras = extras;
130   }
131 
132   /** Gets the extras set via {@link #extras}. */
133   @Implementation
getExtras()134   protected Bundle getExtras() {
135     return extras;
136   }
137 
138   /**
139    * Register callback and store it in the shadow to make it easier to check the state of the
140    * registered callbacks. Handler is just passed on to the real class.
141    */
142   @Implementation
registerCallback(@onnull Callback callback, @Nullable Handler handler)143   protected void registerCallback(@Nonnull Callback callback, @Nullable Handler handler) {
144     callbacks.add(callback);
145     reflector(MediaControllerReflector.class, realMediaController)
146         .registerCallback(callback, handler);
147   }
148 
149   /**
150    * Unregister callback and remove it from the shadow to make it easier to check the state of the
151    * registered callbacks.
152    */
153   @Implementation
unregisterCallback(@onnull Callback callback)154   protected void unregisterCallback(@Nonnull Callback callback) {
155     callbacks.remove(callback);
156     reflector(MediaControllerReflector.class, realMediaController).unregisterCallback(callback);
157   }
158 
159   /** Gets the callbacks registered to MediaController. */
getCallbacks()160   public List<Callback> getCallbacks() {
161     return callbacks;
162   }
163 
164   /** Executes all registered onPlaybackStateChanged callbacks. */
executeOnPlaybackStateChanged(PlaybackState playbackState)165   public void executeOnPlaybackStateChanged(PlaybackState playbackState) {
166     setPlaybackState(playbackState);
167 
168     int messageId =
169         ReflectionHelpers.getStaticField(MediaController.class, "MSG_UPDATE_PLAYBACK_STATE");
170     ReflectionHelpers.callInstanceMethod(
171         MediaController.class,
172         realMediaController,
173         "postMessage",
174         ClassParameter.from(int.class, messageId),
175         ClassParameter.from(Object.class, playbackState),
176         ClassParameter.from(Bundle.class, new Bundle()));
177   }
178 
179   /** Executes all registered onSessionDestroyed callbacks. */
executeOnSessionDestroyed()180   public void executeOnSessionDestroyed() {
181     int messageId = ReflectionHelpers.getStaticField(MediaController.class, "MSG_DESTROYED");
182     ReflectionHelpers.callInstanceMethod(
183         MediaController.class,
184         realMediaController,
185         "postMessage",
186         ClassParameter.from(int.class, messageId),
187         ClassParameter.from(Object.class, null),
188         ClassParameter.from(Bundle.class, null));
189   }
190 
191   /** Executes all registered onMetadataChanged callbacks. */
executeOnMetadataChanged(MediaMetadata metadata)192   public void executeOnMetadataChanged(MediaMetadata metadata) {
193     setMetadata(metadata);
194 
195     int messageId = ReflectionHelpers.getStaticField(MediaController.class, "MSG_UPDATE_METADATA");
196     ReflectionHelpers.callInstanceMethod(
197         MediaController.class,
198         realMediaController,
199         "postMessage",
200         ClassParameter.from(int.class, messageId),
201         ClassParameter.from(Object.class, metadata),
202         ClassParameter.from(Bundle.class, new Bundle()));
203   }
204 
205   @ForType(MediaController.class)
206   interface MediaControllerReflector {
207 
208     @Direct
registerCallback(@onnull Callback callback, @Nullable Handler handler)209     void registerCallback(@Nonnull Callback callback, @Nullable Handler handler);
210 
211     @Direct
unregisterCallback(@onnull Callback callback)212     void unregisterCallback(@Nonnull Callback callback);
213   }
214 }
215