1 package org.robolectric.shadows;
2 
3 import static org.robolectric.shadow.api.Shadow.newInstanceOf;
4 
5 import android.app.ActivityThread;
6 import android.app.Application;
7 import android.appwidget.AppWidgetManager;
8 import android.content.BroadcastReceiver;
9 import android.content.ComponentName;
10 import android.content.Context;
11 import android.content.ContextWrapper;
12 import android.content.Intent;
13 import android.content.IntentFilter;
14 import android.content.ServiceConnection;
15 import android.os.Handler;
16 import android.os.IBinder;
17 import android.os.PowerManager;
18 import android.widget.ListPopupWindow;
19 import android.widget.PopupWindow;
20 import android.widget.Toast;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import org.robolectric.RoboSettings;
26 import org.robolectric.RuntimeEnvironment;
27 import org.robolectric.annotation.Implements;
28 import org.robolectric.annotation.RealObject;
29 import org.robolectric.shadow.api.Shadow;
30 import org.robolectric.util.ReflectionHelpers;
31 import org.robolectric.util.Scheduler;
32 
33 @Implements(Application.class)
34 public class ShadowApplication extends ShadowContextWrapper {
35   @RealObject private Application realApplication;
36 
37   private Scheduler backgroundScheduler = RoboSettings.isUseGlobalScheduler()
38       ? getForegroundThreadScheduler()
39       : new Scheduler();
40   private List<android.widget.Toast> shownToasts = new ArrayList<>();
41   private PowerManager.WakeLock latestWakeLock;
42   private ShadowAlertDialog latestAlertDialog;
43   private ShadowDialog latestDialog;
44   private ShadowPopupMenu latestPopupMenu;
45   private Object bluetoothAdapter = newInstanceOf("android.bluetooth.BluetoothAdapter");
46   private PopupWindow latestPopupWindow;
47   private ListPopupWindow latestListPopupWindow;
48 
49   /**
50    * @deprecated Use
51    *     `shadowOf({@link androidx.test.core.app.ApplicationProvider#getApplicationContext})`
52    *     instead.
53    */
54   @Deprecated
getInstance()55   public static ShadowApplication getInstance() {
56     return RuntimeEnvironment.application == null
57         ? null
58         : Shadow.extract(RuntimeEnvironment.application);
59   }
60 
61   /**
62    * Runs any background tasks previously queued by {@link android.os.AsyncTask#execute(Object[])}.
63    *
64    * Note: calling this method does not pause or un-pause the scheduler.
65    */
runBackgroundTasks()66   public static void runBackgroundTasks() {
67     getInstance().getBackgroundThreadScheduler().advanceBy(0);
68   }
69 
70   /**
71    * Attaches an application to a base context.
72    *
73    * @param context The context with which to initialize the application, whose base context will
74    *                be attached to the application
75    */
callAttach(Context context)76   public void callAttach(Context context) {
77     ReflectionHelpers.callInstanceMethod(Application.class, realApplication, "attach",
78         ReflectionHelpers.ClassParameter.from(Context.class, context));
79   }
80 
getShownToasts()81   public List<Toast> getShownToasts() {
82     return shownToasts;
83   }
84 
85   /**
86    * Return the foreground scheduler.
87    *
88    * @return  Foreground scheduler.
89    */
getForegroundThreadScheduler()90   public Scheduler getForegroundThreadScheduler() {
91     return RuntimeEnvironment.getMasterScheduler();
92   }
93 
94   /**
95    * Return the background scheduler.
96    *
97    * @return  Background scheduler.
98    */
getBackgroundThreadScheduler()99   public Scheduler getBackgroundThreadScheduler() {
100     return backgroundScheduler;
101   }
102 
setComponentNameAndServiceForBindService(ComponentName name, IBinder service)103   public void setComponentNameAndServiceForBindService(ComponentName name, IBinder service) {
104     getShadowInstrumentation().setComponentNameAndServiceForBindService(name, service);
105   }
106 
setComponentNameAndServiceForBindServiceForIntent( Intent intent, ComponentName name, IBinder service)107   public void setComponentNameAndServiceForBindServiceForIntent(
108       Intent intent, ComponentName name, IBinder service) {
109     getShadowInstrumentation()
110         .setComponentNameAndServiceForBindServiceForIntent(intent, name, service);
111   }
112 
assertNoBroadcastListenersOfActionRegistered(ContextWrapper context, String action)113   public void assertNoBroadcastListenersOfActionRegistered(ContextWrapper context, String action) {
114     getShadowInstrumentation().assertNoBroadcastListenersOfActionRegistered(context, action);
115   }
116 
getBoundServiceConnections()117   public List<ServiceConnection> getBoundServiceConnections() {
118     return getShadowInstrumentation().getBoundServiceConnections();
119   }
120 
setUnbindServiceShouldThrowIllegalArgument(boolean flag)121   public void setUnbindServiceShouldThrowIllegalArgument(boolean flag) {
122     getShadowInstrumentation().setUnbindServiceShouldThrowIllegalArgument(flag);
123   }
124 
getUnboundServiceConnections()125   public List<ServiceConnection> getUnboundServiceConnections() {
126     return getShadowInstrumentation().getUnboundServiceConnections();
127   }
128 
129   /** @deprecated use PackageManager.queryBroadcastReceivers instead */
130   @Deprecated
hasReceiverForIntent(Intent intent)131   public boolean hasReceiverForIntent(Intent intent) {
132     return getShadowInstrumentation().hasReceiverForIntent(intent);
133   }
134 
135   /** @deprecated use PackageManager.queryBroadcastReceivers instead */
136   @Deprecated
getReceiversForIntent(Intent intent)137   public List<BroadcastReceiver> getReceiversForIntent(Intent intent) {
138     return getShadowInstrumentation().getReceiversForIntent(intent);
139   }
140 
141   /**
142    * @return list of {@link Wrapper}s for registered receivers
143    */
getRegisteredReceivers()144   public List<Wrapper> getRegisteredReceivers() {
145     return getShadowInstrumentation().getRegisteredReceivers();
146   }
147 
148   /**
149    * @deprecated Please use {@link Context#getSystemService(Context.APPWIDGET_SERVICE)} intstead.
150    */
151   @Deprecated
getAppWidgetManager()152   public AppWidgetManager getAppWidgetManager() {
153     return (AppWidgetManager) realApplication.getSystemService(Context.APPWIDGET_SERVICE);
154   }
155 
156   /**
157    * @deprecated Use {@link ShadowAlertDialog#getLatestAlertDialog()} instead.
158    */
159   @Deprecated
getLatestAlertDialog()160   public ShadowAlertDialog getLatestAlertDialog() {
161     return latestAlertDialog;
162   }
163 
setLatestAlertDialog(ShadowAlertDialog latestAlertDialog)164   protected void setLatestAlertDialog(ShadowAlertDialog latestAlertDialog) {
165     this.latestAlertDialog = latestAlertDialog;
166   }
167 
168   /**
169    * @deprecated Use {@link ShadowDialog#getLatestDialog()} instead.
170    */
171   @Deprecated
getLatestDialog()172   public ShadowDialog getLatestDialog() {
173     return latestDialog;
174   }
175 
setLatestDialog(ShadowDialog latestDialog)176   protected void setLatestDialog(ShadowDialog latestDialog) {
177     this.latestDialog = latestDialog;
178   }
179 
getBluetoothAdapter()180   public Object getBluetoothAdapter() {
181     return bluetoothAdapter;
182   }
183 
declareActionUnbindable(String action)184   public void declareActionUnbindable(String action) {
185     getShadowInstrumentation().declareActionUnbindable(action);
186   }
187 
getLatestWakeLock()188   public PowerManager.WakeLock getLatestWakeLock() {
189     return latestWakeLock;
190   }
191 
addWakeLock( PowerManager.WakeLock wl )192   public void addWakeLock( PowerManager.WakeLock wl ) {
193     latestWakeLock = wl;
194   }
195 
clearWakeLocks()196   public void clearWakeLocks() {
197     latestWakeLock = null;
198   }
199 
200   private final Map<String, Object> singletons = new HashMap<>();
201 
getSingleton(Class<T> clazz, Provider<T> provider)202   public <T> T getSingleton(Class<T> clazz, Provider<T> provider) {
203     synchronized (singletons) {
204       //noinspection unchecked
205       T item = (T) singletons.get(clazz.getName());
206       if (item == null) {
207         singletons.put(clazz.getName(), item = provider.get());
208       }
209       return item;
210     }
211   }
212 
213   /**
214    * Set to true if you'd like Robolectric to strictly simulate the real Android behavior when
215    * calling {@link Context#startActivity(android.content.Intent)}. Real Android throws a
216    * {@link android.content.ActivityNotFoundException} if given
217    * an {@link Intent} that is not known to the {@link android.content.pm.PackageManager}
218    *
219    * By default, this behavior is off (false).
220    *
221    * @param checkActivities True to validate activities.
222    */
checkActivities(boolean checkActivities)223   public void checkActivities(boolean checkActivities) {
224     ActivityThread activityThread = (ActivityThread) RuntimeEnvironment.getActivityThread();
225     ShadowInstrumentation shadowInstrumentation =
226         Shadow.extract(activityThread.getInstrumentation());
227     shadowInstrumentation.checkActivities(checkActivities);
228   }
229 
230   /**
231    * @deprecated Use {@link ShadowPopupMenu#getLatestPopupMenu()} instead.
232    */
233   @Deprecated
getLatestPopupMenu()234   public ShadowPopupMenu getLatestPopupMenu() {
235     return latestPopupMenu;
236   }
237 
setLatestPopupMenu(ShadowPopupMenu latestPopupMenu)238   protected void setLatestPopupMenu(ShadowPopupMenu latestPopupMenu) {
239     this.latestPopupMenu = latestPopupMenu;
240   }
241 
getLatestPopupWindow()242   public PopupWindow getLatestPopupWindow() {
243     return latestPopupWindow;
244   }
245 
setLatestPopupWindow(PopupWindow latestPopupWindow)246   protected void setLatestPopupWindow(PopupWindow latestPopupWindow) {
247     this.latestPopupWindow = latestPopupWindow;
248   }
249 
getLatestListPopupWindow()250   public ListPopupWindow getLatestListPopupWindow() {
251     return latestListPopupWindow;
252   }
253 
setLatestListPopupWindow(ListPopupWindow latestListPopupWindow)254   protected void setLatestListPopupWindow(ListPopupWindow latestListPopupWindow) {
255     this.latestListPopupWindow = latestListPopupWindow;
256   }
257 
258   public static class Wrapper {
259     public BroadcastReceiver broadcastReceiver;
260     public IntentFilter intentFilter;
261     public Context context;
262     public Throwable exception;
263     public String broadcastPermission;
264     public Handler scheduler;
265 
Wrapper( BroadcastReceiver broadcastReceiver, IntentFilter intentFilter, Context context, String broadcastPermission, Handler scheduler)266     public Wrapper(
267         BroadcastReceiver broadcastReceiver,
268         IntentFilter intentFilter,
269         Context context,
270         String broadcastPermission,
271         Handler scheduler) {
272       this.broadcastReceiver = broadcastReceiver;
273       this.intentFilter = intentFilter;
274       this.context = context;
275       this.broadcastPermission = broadcastPermission;
276       this.scheduler = scheduler;
277       exception = new Throwable();
278     }
279 
getBroadcastReceiver()280     public BroadcastReceiver getBroadcastReceiver() {
281       return broadcastReceiver;
282     }
283 
getIntentFilter()284     public IntentFilter getIntentFilter() {
285       return intentFilter;
286     }
287 
getContext()288     public Context getContext() {
289       return context;
290     }
291   }
292 
293   /**
294    * @deprecated Do not depend on this method to override services as it will be removed in a future
295    * update. The preferered method is use the shadow of the corresponding service.
296    */
297   @Deprecated
setSystemService(String key, Object service)298   public void setSystemService(String key, Object service) {
299     ShadowContextImpl shadowContext = Shadow.extract(realApplication.getBaseContext());
300     shadowContext.setSystemService(key, service);
301   }
302 
303 }
304