• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static org.robolectric.annotation.LooperMode.Mode.LEGACY;
4 import static org.robolectric.shadows.ShadowLooper.assertLooperMode;
5 
6 import android.app.ActivityThread;
7 import android.app.AlertDialog;
8 import android.app.Application;
9 import android.app.Dialog;
10 import android.appwidget.AppWidgetManager;
11 import android.bluetooth.BluetoothAdapter;
12 import android.content.BroadcastReceiver;
13 import android.content.ComponentName;
14 import android.content.Context;
15 import android.content.ContextWrapper;
16 import android.content.Intent;
17 import android.content.IntentFilter;
18 import android.content.ServiceConnection;
19 import android.os.Build;
20 import android.os.Handler;
21 import android.os.IBinder;
22 import android.os.PowerManager;
23 import android.widget.ListPopupWindow;
24 import android.widget.PopupWindow;
25 import android.widget.Toast;
26 import com.google.common.collect.ImmutableList;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import org.robolectric.RuntimeEnvironment;
32 import org.robolectric.annotation.Implements;
33 import org.robolectric.annotation.RealObject;
34 import org.robolectric.shadow.api.Shadow;
35 import org.robolectric.shadows.ShadowActivityThread._ActivityThread_;
36 import org.robolectric.shadows.ShadowActivityThread._AppBindData_;
37 import org.robolectric.shadows.ShadowUserManager.UserManagerState;
38 import org.robolectric.util.ReflectionHelpers;
39 import org.robolectric.util.Scheduler;
40 import org.robolectric.util.reflector.Reflector;
41 
42 @Implements(Application.class)
43 public class ShadowApplication extends ShadowContextWrapper {
44   @RealObject private Application realApplication;
45 
46   private List<android.widget.Toast> shownToasts = new ArrayList<>();
47   private ShadowPopupMenu latestPopupMenu;
48   private PopupWindow latestPopupWindow;
49   private ListPopupWindow latestListPopupWindow;
50   private UserManagerState userManagerState;
51 
52   /**
53    * @deprecated Use {@code shadowOf({@link ApplicationProvider#getApplicationContext()})} instead.
54    */
55   @Deprecated
getInstance()56   public static ShadowApplication getInstance() {
57     return Shadow.extract(RuntimeEnvironment.getApplication());
58   }
59 
60   /**
61    * Runs any background tasks previously queued by {@link android.os.AsyncTask#execute(Object[])}.
62    *
63    * <p>Note: calling this method does not pause or un-pause the scheduler.
64    */
runBackgroundTasks()65   public static void runBackgroundTasks() {
66     getInstance().getBackgroundThreadScheduler().advanceBy(0);
67   }
68 
69   /** Configures the value to be returned by {@link Application#getProcessName()}. */
setProcessName(String processName)70   public static void setProcessName(String processName) {
71     // No need for a @Resetter because the whole ActivityThread is reset before each test.
72     _ActivityThread_ activityThread =
73         Reflector.reflector(_ActivityThread_.class, ShadowActivityThread.currentActivityThread());
74     Reflector.reflector(_AppBindData_.class, activityThread.getBoundApplication())
75         .setProcessName(processName);
76   }
77 
78   /**
79    * Attaches an application to a base context.
80    *
81    * @param context The context with which to initialize the application, whose base context will be
82    *     attached to the application
83    */
callAttach(Context context)84   public void callAttach(Context context) {
85     ReflectionHelpers.callInstanceMethod(
86         Application.class,
87         realApplication,
88         "attach",
89         ReflectionHelpers.ClassParameter.from(Context.class, context));
90   }
91 
getShownToasts()92   public List<Toast> getShownToasts() {
93     return shownToasts;
94   }
95 
96   /**
97    * Return the foreground scheduler.
98    *
99    * @return Foreground scheduler.
100    * @deprecated use {@link org.robolectric.Robolectric#getForegroundThreadScheduler()}
101    */
102   @Deprecated
getForegroundThreadScheduler()103   public Scheduler getForegroundThreadScheduler() {
104     return RuntimeEnvironment.getMasterScheduler();
105   }
106 
107   /**
108    * Return the background scheduler.
109    *
110    * @return Background scheduler.
111    * @deprecated use {@link org.robolectric.Robolectric#getBackgroundThreadScheduler()}
112    */
113   @Deprecated
getBackgroundThreadScheduler()114   public Scheduler getBackgroundThreadScheduler() {
115     assertLooperMode(LEGACY);
116     return ShadowLegacyLooper.getBackgroundThreadScheduler();
117   }
118 
119   /**
120    * Sets whether or not calls to unbindService should call onServiceDisconnected().
121    *
122    * <p>The default for this is currently {@code true} because that is the historical behavior.
123    * However, this does not correctly mirror Android's actual behavior. This value will eventually
124    * default to {@code false} once users have had a chance to migrate, and eventually the option
125    * will be removed altogether.
126    */
setUnbindServiceCallsOnServiceDisconnected(boolean flag)127   public void setUnbindServiceCallsOnServiceDisconnected(boolean flag) {
128     getShadowInstrumentation().setUnbindServiceCallsOnServiceDisconnected(flag);
129   }
130 
setComponentNameAndServiceForBindService(ComponentName name, IBinder service)131   public void setComponentNameAndServiceForBindService(ComponentName name, IBinder service) {
132     getShadowInstrumentation().setComponentNameAndServiceForBindService(name, service);
133   }
134 
setComponentNameAndServiceForBindServiceForIntent( Intent intent, ComponentName name, IBinder service)135   public void setComponentNameAndServiceForBindServiceForIntent(
136       Intent intent, ComponentName name, IBinder service) {
137     getShadowInstrumentation()
138         .setComponentNameAndServiceForBindServiceForIntent(intent, name, service);
139   }
140 
assertNoBroadcastListenersOfActionRegistered(ContextWrapper context, String action)141   public void assertNoBroadcastListenersOfActionRegistered(ContextWrapper context, String action) {
142     getShadowInstrumentation().assertNoBroadcastListenersOfActionRegistered(context, action);
143   }
144 
getBoundServiceConnections()145   public List<ServiceConnection> getBoundServiceConnections() {
146     return getShadowInstrumentation().getBoundServiceConnections();
147   }
148 
setUnbindServiceShouldThrowIllegalArgument(boolean flag)149   public void setUnbindServiceShouldThrowIllegalArgument(boolean flag) {
150     getShadowInstrumentation().setUnbindServiceShouldThrowIllegalArgument(flag);
151   }
152 
153   /**
154    * Configures the ShadowApplication so that calls to bindService will throw the given
155    * SecurityException.
156    */
setThrowInBindService(SecurityException e)157   public void setThrowInBindService(SecurityException e) {
158     getShadowInstrumentation().setThrowInBindService(e);
159   }
160 
161   /**
162    * Configures the ShadowApplication so that calls to bindService will call
163    * ServiceConnection#onServiceConnected before returning.
164    */
setBindServiceCallsOnServiceConnectedDirectly(boolean callDirectly)165   public void setBindServiceCallsOnServiceConnectedDirectly(boolean callDirectly) {
166     getShadowInstrumentation().setBindServiceCallsOnServiceConnectedDirectly(callDirectly);
167   }
168 
getUnboundServiceConnections()169   public List<ServiceConnection> getUnboundServiceConnections() {
170     return getShadowInstrumentation().getUnboundServiceConnections();
171   }
172 
173   /**
174    * @deprecated use PackageManager.queryBroadcastReceivers instead
175    */
176   @Deprecated
hasReceiverForIntent(Intent intent)177   public boolean hasReceiverForIntent(Intent intent) {
178     return getShadowInstrumentation().hasReceiverForIntent(intent);
179   }
180 
181   /**
182    * @deprecated use PackageManager.queryBroadcastReceivers instead
183    */
184   @Deprecated
getReceiversForIntent(Intent intent)185   public List<BroadcastReceiver> getReceiversForIntent(Intent intent) {
186     return getShadowInstrumentation().getReceiversForIntent(intent);
187   }
188 
189   /**
190    * @return list of {@link Wrapper}s for registered receivers
191    */
getRegisteredReceivers()192   public ImmutableList<Wrapper> getRegisteredReceivers() {
193     return getShadowInstrumentation().getRegisteredReceivers();
194   }
195 
196   /** Clears the list of {@link Wrapper}s for registered receivers */
clearRegisteredReceivers()197   public void clearRegisteredReceivers() {
198     getShadowInstrumentation().clearRegisteredReceivers();
199   }
200 
201   /**
202    * @deprecated Please use {@link Context#getSystemService(Context.APPWIDGET_SERVICE)} intstead.
203    */
204   @Deprecated
getAppWidgetManager()205   public AppWidgetManager getAppWidgetManager() {
206     return (AppWidgetManager) realApplication.getSystemService(Context.APPWIDGET_SERVICE);
207   }
208 
209   /**
210    * @deprecated Use {@link ShadowAlertDialog#getLatestAlertDialog()} instead.
211    */
212   @Deprecated
getLatestAlertDialog()213   public ShadowAlertDialog getLatestAlertDialog() {
214     AlertDialog dialog = ShadowAlertDialog.getLatestAlertDialog();
215     return dialog == null ? null : Shadow.extract(dialog);
216   }
217 
218   /**
219    * @deprecated Use {@link ShadowDialog#getLatestDialog()} instead.
220    */
221   @Deprecated
getLatestDialog()222   public ShadowDialog getLatestDialog() {
223     Dialog dialog = ShadowDialog.getLatestDialog();
224     return dialog == null ? null : Shadow.extract(dialog);
225   }
226 
227   /**
228    * @deprecated Use {@link BluetoothAdapter#getDefaultAdapter()} ()} instead.
229    */
230   @Deprecated
getBluetoothAdapter()231   public BluetoothAdapter getBluetoothAdapter() {
232     return BluetoothAdapter.getDefaultAdapter();
233   }
234 
declareActionUnbindable(String action)235   public void declareActionUnbindable(String action) {
236     getShadowInstrumentation().declareActionUnbindable(action);
237   }
238 
239   /**
240    * Configures the ShadowApplication so that bindService calls for the given ComponentName return
241    * false and do not call onServiceConnected.
242    */
declareComponentUnbindable(ComponentName component)243   public void declareComponentUnbindable(ComponentName component) {
244     getShadowInstrumentation().declareComponentUnbindable(component);
245   }
246 
247   /**
248    * @deprecated use ShadowPowerManager.getLatestWakeLock
249    */
250   @Deprecated
getLatestWakeLock()251   public PowerManager.WakeLock getLatestWakeLock() {
252     return ShadowPowerManager.getLatestWakeLock();
253   }
254 
255   /**
256    * @deprecated use PowerManager APIs instead
257    */
258   @Deprecated
addWakeLock(PowerManager.WakeLock wl)259   public void addWakeLock(PowerManager.WakeLock wl) {
260     ShadowPowerManager.addWakeLock(wl);
261   }
262 
263   /**
264    * @deprecated use ShadowPowerManager.clearWakeLocks
265    */
266   @Deprecated
clearWakeLocks()267   public void clearWakeLocks() {
268     ShadowPowerManager.clearWakeLocks();
269   }
270 
271   private final Map<String, Object> singletons = new HashMap<>();
272 
getSingleton(Class<T> clazz, Provider<T> provider)273   public <T> T getSingleton(Class<T> clazz, Provider<T> provider) {
274     synchronized (singletons) {
275       //noinspection unchecked
276       T item = (T) singletons.get(clazz.getName());
277       if (item == null) {
278         singletons.put(clazz.getName(), item = provider.get());
279       }
280       return item;
281     }
282   }
283 
284   /**
285    * Set to true if you'd like Robolectric to strictly simulate the real Android behavior when
286    * calling {@link Context#startActivity(android.content.Intent)}. Real Android throws a {@link
287    * android.content.ActivityNotFoundException} if given an {@link Intent} that is not known to the
288    * {@link android.content.pm.PackageManager}
289    *
290    * <p>By default, this behavior is off (false).
291    *
292    * @param checkActivities True to validate activities.
293    */
checkActivities(boolean checkActivities)294   public void checkActivities(boolean checkActivities) {
295     ActivityThread activityThread = (ActivityThread) RuntimeEnvironment.getActivityThread();
296     ShadowInstrumentation shadowInstrumentation =
297         Shadow.extract(activityThread.getInstrumentation());
298     shadowInstrumentation.checkActivities(checkActivities);
299   }
300 
301   /**
302    * @deprecated Use {@link ShadowPopupMenu#getLatestPopupMenu()} instead.
303    */
304   @Deprecated
getLatestPopupMenu()305   public ShadowPopupMenu getLatestPopupMenu() {
306     return latestPopupMenu;
307   }
308 
setLatestPopupMenu(ShadowPopupMenu latestPopupMenu)309   protected void setLatestPopupMenu(ShadowPopupMenu latestPopupMenu) {
310     this.latestPopupMenu = latestPopupMenu;
311   }
312 
getLatestPopupWindow()313   public PopupWindow getLatestPopupWindow() {
314     return latestPopupWindow;
315   }
316 
setLatestPopupWindow(PopupWindow latestPopupWindow)317   protected void setLatestPopupWindow(PopupWindow latestPopupWindow) {
318     this.latestPopupWindow = latestPopupWindow;
319   }
320 
getLatestListPopupWindow()321   public ListPopupWindow getLatestListPopupWindow() {
322     return latestListPopupWindow;
323   }
324 
setLatestListPopupWindow(ListPopupWindow latestListPopupWindow)325   protected void setLatestListPopupWindow(ListPopupWindow latestListPopupWindow) {
326     this.latestListPopupWindow = latestListPopupWindow;
327   }
328 
getUserManagerState()329   UserManagerState getUserManagerState() {
330     if (userManagerState == null) {
331       userManagerState = new UserManagerState();
332     }
333 
334     return userManagerState;
335   }
336 
337   public static final class Wrapper {
338     public BroadcastReceiver broadcastReceiver;
339     public IntentFilter intentFilter;
340     public Context context;
341     public Throwable exception;
342     public String broadcastPermission;
343     public Handler scheduler;
344     public int flags;
345 
Wrapper( BroadcastReceiver broadcastReceiver, IntentFilter intentFilter, Context context, String broadcastPermission, Handler scheduler, int flags)346     public Wrapper(
347         BroadcastReceiver broadcastReceiver,
348         IntentFilter intentFilter,
349         Context context,
350         String broadcastPermission,
351         Handler scheduler,
352         int flags) {
353       this.broadcastReceiver = broadcastReceiver;
354       this.intentFilter = intentFilter;
355       this.context = context;
356       this.broadcastPermission = broadcastPermission;
357       this.scheduler = scheduler;
358       this.flags = flags;
359       exception = new Throwable();
360     }
361 
getBroadcastReceiver()362     public BroadcastReceiver getBroadcastReceiver() {
363       return broadcastReceiver;
364     }
365 
getIntentFilter()366     public IntentFilter getIntentFilter() {
367       return intentFilter;
368     }
369 
getContext()370     public Context getContext() {
371       return context;
372     }
373 
374     @Override
toString()375     public String toString() {
376       return "Wrapper[receiver=["
377           + broadcastReceiver
378           + "], context=["
379           + context
380           + "], intentFilter=["
381           + intentFilter
382           + "]]";
383     }
384   }
385 
386   /**
387    * @deprecated Do not depend on this method to override services as it will be removed in a future
388    *     update. The preferered method is use the shadow of the corresponding service.
389    */
390   @Deprecated
setSystemService(String key, Object service)391   public void setSystemService(String key, Object service) {
392     ShadowContextImpl shadowContext = Shadow.extract(realApplication.getBaseContext());
393     shadowContext.setSystemService(key, service);
394   }
395 
396   /**
397    * Enables or disables predictive back for the current application.
398    *
399    * <p>This is the equivalent of specifying {code android:enableOnBackInvokedCallback} on the
400    * {@code <application>} tag in the Android manifest.
401    */
setEnableOnBackInvokedCallback(boolean isEnabled)402   public static void setEnableOnBackInvokedCallback(boolean isEnabled) {
403     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
404       ShadowWindowOnBackInvokedDispatcher.setEnablePredictiveBack(isEnabled);
405       RuntimeEnvironment.getApplication()
406           .getApplicationInfo()
407           .setEnableOnBackInvokedCallback(isEnabled);
408     }
409   }
410 }
411