Home | History | Annotate | Download | only in shadows
      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
     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    */
     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    */
     76   public void callAttach(Context context) {
     77     ReflectionHelpers.callInstanceMethod(Application.class, realApplication, "attach",
     78         ReflectionHelpers.ClassParameter.from(Context.class, context));
     79   }
     80 
     81   public List<Toast> getShownToasts() {
     82     return shownToasts;
     83   }
     84 
     85   /**
     86    * Return the foreground scheduler.
     87    *
     88    * @return  Foreground scheduler.
     89    */
     90   public Scheduler getForegroundThreadScheduler() {
     91     return RuntimeEnvironment.getMasterScheduler();
     92   }
     93 
     94   /**
     95    * Return the background scheduler.
     96    *
     97    * @return  Background scheduler.
     98    */
     99   public Scheduler getBackgroundThreadScheduler() {
    100     return backgroundScheduler;
    101   }
    102 
    103   public void setComponentNameAndServiceForBindService(ComponentName name, IBinder service) {
    104     getShadowInstrumentation().setComponentNameAndServiceForBindService(name, service);
    105   }
    106 
    107   public void setComponentNameAndServiceForBindServiceForIntent(
    108       Intent intent, ComponentName name, IBinder service) {
    109     getShadowInstrumentation()
    110         .setComponentNameAndServiceForBindServiceForIntent(intent, name, service);
    111   }
    112 
    113   public void assertNoBroadcastListenersOfActionRegistered(ContextWrapper context, String action) {
    114     getShadowInstrumentation().assertNoBroadcastListenersOfActionRegistered(context, action);
    115   }
    116 
    117   public List<ServiceConnection> getBoundServiceConnections() {
    118     return getShadowInstrumentation().getBoundServiceConnections();
    119   }
    120 
    121   public void setUnbindServiceShouldThrowIllegalArgument(boolean flag) {
    122     getShadowInstrumentation().setUnbindServiceShouldThrowIllegalArgument(flag);
    123   }
    124 
    125   public List<ServiceConnection> getUnboundServiceConnections() {
    126     return getShadowInstrumentation().getUnboundServiceConnections();
    127   }
    128 
    129   /** @deprecated use PackageManager.queryBroadcastReceivers instead */
    130   @Deprecated
    131   public boolean hasReceiverForIntent(Intent intent) {
    132     return getShadowInstrumentation().hasReceiverForIntent(intent);
    133   }
    134 
    135   /** @deprecated use PackageManager.queryBroadcastReceivers instead */
    136   @Deprecated
    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    */
    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
    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
    160   public ShadowAlertDialog getLatestAlertDialog() {
    161     return latestAlertDialog;
    162   }
    163 
    164   protected void setLatestAlertDialog(ShadowAlertDialog latestAlertDialog) {
    165     this.latestAlertDialog = latestAlertDialog;
    166   }
    167 
    168   /**
    169    * @deprecated Use {@link ShadowDialog#getLatestDialog()} instead.
    170    */
    171   @Deprecated
    172   public ShadowDialog getLatestDialog() {
    173     return latestDialog;
    174   }
    175 
    176   protected void setLatestDialog(ShadowDialog latestDialog) {
    177     this.latestDialog = latestDialog;
    178   }
    179 
    180   public Object getBluetoothAdapter() {
    181     return bluetoothAdapter;
    182   }
    183 
    184   public void declareActionUnbindable(String action) {
    185     getShadowInstrumentation().declareActionUnbindable(action);
    186   }
    187 
    188   public PowerManager.WakeLock getLatestWakeLock() {
    189     return latestWakeLock;
    190   }
    191 
    192   public void addWakeLock( PowerManager.WakeLock wl ) {
    193     latestWakeLock = wl;
    194   }
    195 
    196   public void clearWakeLocks() {
    197     latestWakeLock = null;
    198   }
    199 
    200   private final Map<String, Object> singletons = new HashMap<>();
    201 
    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    */
    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
    234   public ShadowPopupMenu getLatestPopupMenu() {
    235     return latestPopupMenu;
    236   }
    237 
    238   protected void setLatestPopupMenu(ShadowPopupMenu latestPopupMenu) {
    239     this.latestPopupMenu = latestPopupMenu;
    240   }
    241 
    242   public PopupWindow getLatestPopupWindow() {
    243     return latestPopupWindow;
    244   }
    245 
    246   protected void setLatestPopupWindow(PopupWindow latestPopupWindow) {
    247     this.latestPopupWindow = latestPopupWindow;
    248   }
    249 
    250   public ListPopupWindow getLatestListPopupWindow() {
    251     return latestListPopupWindow;
    252   }
    253 
    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 
    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 
    280     public BroadcastReceiver getBroadcastReceiver() {
    281       return broadcastReceiver;
    282     }
    283 
    284     public IntentFilter getIntentFilter() {
    285       return intentFilter;
    286     }
    287 
    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
    298   public void setSystemService(String key, Object service) {
    299     ShadowContextImpl shadowContext = Shadow.extract(realApplication.getBaseContext());
    300     shadowContext.setSystemService(key, service);
    301   }
    302 
    303 }
    304