133873d2b41a5cd2597b20a4e88eb8942944c0f23Tyler Schultzpackage com.xtremelabs.robolectric.shadows;
28baea4cbf332f0e0acf559dfab4aa59dd7c71003Christian Williams & Ryan Richard
38baea4cbf332f0e0acf559dfab4aa59dd7c71003Christian Williams & Ryan Richardimport android.app.Application;
486335af816f048e32aad504aed0af63a73097a5fChristian Williams & Ryan Richardimport android.appwidget.AppWidgetManager;
5d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport android.content.BroadcastReceiver;
6d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport android.content.ComponentName;
7d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport android.content.ContentResolver;
8d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport android.content.Context;
9d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport android.content.Intent;
10d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport android.content.IntentFilter;
11d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport android.content.ServiceConnection;
12a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williamsimport android.content.res.Resources;
1360716685debb5811792ecd99e71b20bfa4ff6a7bPhil Goodwin & Rick Kawalaimport android.os.IBinder;
147d446513cda09628ec24023cfdebeca847700b52Christian Williams & Phil Goodwinimport android.os.Looper;
1586335af816f048e32aad504aed0af63a73097a5fChristian Williams & Ryan Richardimport android.view.LayoutInflater;
16854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwinimport android.widget.Toast;
17b01474a3329222965d31068f5c33e59c6e6aa6a4Josh Lauer & Christian Williamsimport com.xtremelabs.robolectric.Robolectric;
1822c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.Implementation;
1922c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.Implements;
2022c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.RealObject;
21eb645dd6f075c4c7d6d61193fde416739adb7fc1Gregg Van Hove & Phil Goodwinimport com.xtremelabs.robolectric.res.ResourceLoader;
222cdde11355e7c249e83a8b7aaabae5977bbc3e49Phil Goodwinimport com.xtremelabs.robolectric.tester.org.apache.http.FakeHttpLayer;
230fe1965a36c508fb5b9fa4c8d0caa2d30540f2ccChristian Williams & Phil Goodwinimport com.xtremelabs.robolectric.util.Scheduler;
24eb645dd6f075c4c7d6d61193fde416739adb7fc1Gregg Van Hove & Phil Goodwin
25d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport java.util.ArrayList;
26d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport java.util.HashMap;
27d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport java.util.Iterator;
28d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport java.util.List;
29d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawalaimport java.util.Map;
30eb645dd6f075c4c7d6d61193fde416739adb7fc1Gregg Van Hove & Phil Goodwin
31eb645dd6f075c4c7d6d61193fde416739adb7fc1Gregg Van Hove & Phil Goodwinimport static com.xtremelabs.robolectric.Robolectric.newInstanceOf;
32eb645dd6f075c4c7d6d61193fde416739adb7fc1Gregg Van Hove & Phil Goodwinimport static com.xtremelabs.robolectric.Robolectric.shadowOf;
3383628c488feafc9655efb44de601004cf52ed0c7Christian Williams & Phil Goodwin
346a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin/**
3533040bdd7715a46bfcfe3cc5f894972ef65d31beChristian Williams * Shadows the {@code android.app.Application} class.
366a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin */
378baea4cbf332f0e0acf559dfab4aa59dd7c71003Christian Williams & Ryan Richard@SuppressWarnings({"UnusedDeclaration"})
388baea4cbf332f0e0acf559dfab4aa59dd7c71003Christian Williams & Ryan Richard@Implements(Application.class)
39afe0a89d904a7fe2f5980b9deb26cc3240192459Christian Williamspublic class ShadowApplication extends ShadowContextWrapper {
4037cf065cb637e23534051f51791b8ef69828374bChristian Williams    private static final Map<String, String> SYSTEM_SERVICE_MAP = new HashMap<String, String>();
4137cf065cb637e23534051f51791b8ef69828374bChristian Williams
4237cf065cb637e23534051f51791b8ef69828374bChristian Williams    static {
43e057483dbccea1e7373aed776bb14ef85aaa93c7Michael Portuesi        // note that these are different!
44f99fa781cfd614512c48db52387c825d4f167f31Michael Portuesi    	// They specify concrete classes within Robolectric for interfaces or abstract classes defined by Android
452cdde11355e7c249e83a8b7aaabae5977bbc3e49Phil Goodwin        SYSTEM_SERVICE_MAP.put(Context.WINDOW_SERVICE, "com.xtremelabs.robolectric.tester.android.view.TestWindowManager");
46e057483dbccea1e7373aed776bb14ef85aaa93c7Michael Portuesi        SYSTEM_SERVICE_MAP.put(Context.CLIPBOARD_SERVICE, "com.xtremelabs.robolectric.tester.android.text.TestClipboardManager");
47f99fa781cfd614512c48db52387c825d4f167f31Michael Portuesi        SYSTEM_SERVICE_MAP.put(Context.SENSOR_SERVICE, "android.hardware.TestSensorManager");
48f99fa781cfd614512c48db52387c825d4f167f31Michael Portuesi        SYSTEM_SERVICE_MAP.put(Context.VIBRATOR_SERVICE, "android.os.TestVibrator");
49f99fa781cfd614512c48db52387c825d4f167f31Michael Portuesi
5037cf065cb637e23534051f51791b8ef69828374bChristian Williams        // the rest are as mapped in docs...
5137cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.LAYOUT_INFLATER_SERVICE, "android.view.LayoutInflater");
5237cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.ACTIVITY_SERVICE, "android.app.ActivityManager");
5337cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.POWER_SERVICE, "android.os.PowerManager");
5437cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.ALARM_SERVICE, "android.app.AlarmManager");
5537cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.NOTIFICATION_SERVICE, "android.app.NotificationManager");
5637cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.KEYGUARD_SERVICE, "android.app.KeyguardManager");
5737cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.LOCATION_SERVICE, "android.location.LocationManager");
5837cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.SEARCH_SERVICE, "android.app.SearchManager");
5937cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.STORAGE_SERVICE, "android.os.storage.StorageManager");
6037cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.CONNECTIVITY_SERVICE, "android.net.ConnectivityManager");
6137cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.WIFI_SERVICE, "android.net.wifi.WifiManager");
6237cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.AUDIO_SERVICE, "android.media.AudioManager");
6337cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.TELEPHONY_SERVICE, "android.telephony.TelephonyManager");
6437cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.INPUT_METHOD_SERVICE, "android.view.inputmethod.InputMethodManager");
6537cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.UI_MODE_SERVICE, "android.app.UiModeManager");
6637cf065cb637e23534051f51791b8ef69828374bChristian Williams        SYSTEM_SERVICE_MAP.put(Context.DOWNLOAD_SERVICE, "android.app.DownloadManager");
6737cf065cb637e23534051f51791b8ef69828374bChristian Williams    }
6837cf065cb637e23534051f51791b8ef69828374bChristian Williams
694a7b7902404d0c3743f96c043e3cc6b9069cf438Christian Williams    @RealObject private Application realApplication;
704a7b7902404d0c3743f96c043e3cc6b9069cf438Christian Williams
71a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams    private ResourceLoader resourceLoader;
7220b94927aff24d7bd975d6ee717f1b65da9ee7c1Josh Lauer & Christian Williams    private ContentResolver contentResolver;
7337cf065cb637e23534051f51791b8ef69828374bChristian Williams    private Map<String, Object> systemServices = new HashMap<String, Object>();
746fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard    private List<Intent> startedActivities = new ArrayList<Intent>();
756fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard    private List<Intent> startedServices = new ArrayList<Intent>();
7679d9aa26ae9e43f95f71c0e8c5506a2294eea2a0Dave    private List<Intent> stoppedServies = new ArrayList<Intent>();
77b3e9fb748b89249eb03508a317664880abb552ffMatthias Kiefer    private List<Intent> broadcastIntents = new ArrayList<Intent>();
78609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala    private List<ServiceConnection> unboundServiceConnections = new ArrayList<ServiceConnection>();
79cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    private List<Wrapper> registeredReceivers = new ArrayList<Wrapper>();
80f34421dbee452431bce72fb485211739606e8962Stefano Dacchille    private Map<String, Intent> stickyIntents = new HashMap<String, Intent>();
81f91a118112ae13d39251dd3c09f1d85d33283ba1Christian Williams & Phil Goodwin    private FakeHttpLayer fakeHttpLayer = new FakeHttpLayer();
82570d4f805f8fdbd8c786330989b40706129f5b1ePhil Goodwin & Ryan Richard    private Looper mainLooper = ShadowLooper.myLooper();
830fe1965a36c508fb5b9fa4c8d0caa2d30540f2ccChristian Williams & Phil Goodwin    private Scheduler backgroundScheduler = new Scheduler();
849ae1d769a5136e8382d7712bb9afc4fedb6d0060David Farber & Lowell Kirsh    private Map<String, Map<String, Object>> sharedPreferenceMap = new HashMap<String, Map<String, Object>>();
85854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    private ArrayList<Toast> shownToasts = new ArrayList<Toast>();
86854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    private ShadowAlertDialog latestAlertDialog;
87854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    private ShadowDialog latestDialog;
881741463ed4618ec2b72cbd7764649fd0cca10a40Phil Goodwin    private Object bluetoothAdapter = Robolectric.newInstanceOf("android.bluetooth.BluetoothAdapter");
89e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard    private Resources resources;
908baea4cbf332f0e0acf559dfab4aa59dd7c71003Christian Williams & Ryan Richard
9186335af816f048e32aad504aed0af63a73097a5fChristian Williams & Ryan Richard    // these are managed by the AppSingletonizier... kinda gross, sorry [xw]
92cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    LayoutInflater layoutInflater;
93cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    AppWidgetManager appWidgetManager;
940871c2e966da6a78491c2c58f5ff526d1ab17004Phil Goodwin & Rick Kawala    private ServiceConnection serviceConnection;
9560716685debb5811792ecd99e71b20bfa4ff6a7bPhil Goodwin & Rick Kawala    private ComponentName componentNameForBindService;
9660716685debb5811792ecd99e71b20bfa4ff6a7bPhil Goodwin & Rick Kawala    private IBinder serviceForBindService;
97058c2967a3a025d998be7f3c283677c88de4c504Pivotal Shiny Android    private List<String> unbindableActions = new ArrayList<String>();
9886335af816f048e32aad504aed0af63a73097a5fChristian Williams & Ryan Richard
996a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
1006a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Associates a {@code ResourceLoader} with an {@code Application} instance
10140c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams     *
10240c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams     * @param application    application
103fffbcf54817243f6192cf2443257d57198f1ea78Phil Goodwin     * @param resourceLoader resource loader
1046a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @return the application
10540c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams     *         todo: make this non-static?
1066a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
1076a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    public static Application bind(Application application, ResourceLoader resourceLoader) {
1080fe1965a36c508fb5b9fa4c8d0caa2d30540f2ccChristian Williams & Phil Goodwin        ShadowApplication shadowApplication = shadowOf(application);
1096a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin        if (shadowApplication.resourceLoader != null) throw new RuntimeException("ResourceLoader already set!");
1106a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin        shadowApplication.resourceLoader = resourceLoader;
111409f98dea7d03643e910843eb87ac898126c973fadriancowham        shadowApplication.resources = ShadowResources.bind(new Resources(null, null, null), resourceLoader);
1126a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin        return application;
1136a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    }
1146a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin
115854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    public List<Toast> getShownToasts() {
116854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin        return shownToasts;
117854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    }
118854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin
1190fe1965a36c508fb5b9fa4c8d0caa2d30540f2ccChristian Williams & Phil Goodwin    public Scheduler getBackgroundScheduler() {
1200fe1965a36c508fb5b9fa4c8d0caa2d30540f2ccChristian Williams & Phil Goodwin        return backgroundScheduler;
1210fe1965a36c508fb5b9fa4c8d0caa2d30540f2ccChristian Williams & Phil Goodwin    }
1220fe1965a36c508fb5b9fa4c8d0caa2d30540f2ccChristian Williams & Phil Goodwin
1231c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
1241c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Implementation
125a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams    public Context getApplicationContext() {
126a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams        return realApplication;
127a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams    }
128a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams
1291c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
1301c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Implementation
131a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams    public Resources getResources() {
132409f98dea7d03643e910843eb87ac898126c973fadriancowham        if (resources == null ) {
133409f98dea7d03643e910843eb87ac898126c973fadriancowham        	resources = ShadowResources.bind(new Resources(null, null, null), resourceLoader);
134e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard        }
135e02d2608f3fa739dd328c6b44a2122b9dfb73bedLowell Kirsh & Ryan Richard        return resources;
136a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams    }
137a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams
138a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams    @Implementation
1391c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
1401c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public ContentResolver getContentResolver() {
14120b94927aff24d7bd975d6ee717f1b65da9ee7c1Josh Lauer & Christian Williams        if (contentResolver == null) {
14220b94927aff24d7bd975d6ee717f1b65da9ee7c1Josh Lauer & Christian Williams            contentResolver = new ContentResolver(realApplication) {
14320b94927aff24d7bd975d6ee717f1b65da9ee7c1Josh Lauer & Christian Williams            };
14420b94927aff24d7bd975d6ee717f1b65da9ee7c1Josh Lauer & Christian Williams        }
1458baea4cbf332f0e0acf559dfab4aa59dd7c71003Christian Williams & Ryan Richard        return contentResolver;
1468baea4cbf332f0e0acf559dfab4aa59dd7c71003Christian Williams & Ryan Richard    }
14783628c488feafc9655efb44de601004cf52ed0c7Christian Williams & Phil Goodwin
148de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
1491c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
1501c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public Object getSystemService(String name) {
15183628c488feafc9655efb44de601004cf52ed0c7Christian Williams & Phil Goodwin        if (name.equals(Context.LAYOUT_INFLATER_SERVICE)) {
15286335af816f048e32aad504aed0af63a73097a5fChristian Williams & Ryan Richard            return LayoutInflater.from(realApplication);
15337cf065cb637e23534051f51791b8ef69828374bChristian Williams        } else {
15437cf065cb637e23534051f51791b8ef69828374bChristian Williams            Object service = systemServices.get(name);
15537cf065cb637e23534051f51791b8ef69828374bChristian Williams            if (service == null) {
15637cf065cb637e23534051f51791b8ef69828374bChristian Williams                String serviceClassName = SYSTEM_SERVICE_MAP.get(name);
15737cf065cb637e23534051f51791b8ef69828374bChristian Williams                if (serviceClassName != null) {
15837cf065cb637e23534051f51791b8ef69828374bChristian Williams                    try {
15937cf065cb637e23534051f51791b8ef69828374bChristian Williams                        service = newInstanceOf(Class.forName(serviceClassName));
16037cf065cb637e23534051f51791b8ef69828374bChristian Williams                    } catch (ClassNotFoundException e) {
16137cf065cb637e23534051f51791b8ef69828374bChristian Williams                        throw new RuntimeException(e);
16237cf065cb637e23534051f51791b8ef69828374bChristian Williams                    }
16337cf065cb637e23534051f51791b8ef69828374bChristian Williams                    systemServices.put(name, service);
16437cf065cb637e23534051f51791b8ef69828374bChristian Williams                }
16537cf065cb637e23534051f51791b8ef69828374bChristian Williams            }
16637cf065cb637e23534051f51791b8ef69828374bChristian Williams            return service;
16783628c488feafc9655efb44de601004cf52ed0c7Christian Williams & Phil Goodwin        }
16883628c488feafc9655efb44de601004cf52ed0c7Christian Williams & Phil Goodwin    }
16983628c488feafc9655efb44de601004cf52ed0c7Christian Williams & Phil Goodwin
170de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
1711c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
1721c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public void startActivity(Intent intent) {
1736fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard        startedActivities.add(intent);
1746c88b7681232641b1b96d533fd6ce5cd9d9a9867Christian Williams    }
1756c88b7681232641b1b96d533fd6ce5cd9d9a9867Christian Williams
1766fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard    @Implementation
1771c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
1781c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public ComponentName startService(Intent intent) {
1796fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard        startedServices.add(intent);
1806fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard        return new ComponentName("some.service.package", "SomeServiceName-FIXME");
1816fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard    }
1821c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz
18379d9aa26ae9e43f95f71c0e8c5506a2294eea2a0Dave    @Implementation
1841c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
1851c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public boolean stopService(Intent name) {
1861c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        stoppedServies.add(name);
1871c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz
1881c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        return startedServices.contains(name);
18979d9aa26ae9e43f95f71c0e8c5506a2294eea2a0Dave    }
1906fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard
19160716685debb5811792ecd99e71b20bfa4ff6a7bPhil Goodwin & Rick Kawala    public void setComponentNameAndServiceForBindService(ComponentName name, IBinder service) {
19260716685debb5811792ecd99e71b20bfa4ff6a7bPhil Goodwin & Rick Kawala        this.componentNameForBindService = name;
19360716685debb5811792ecd99e71b20bfa4ff6a7bPhil Goodwin & Rick Kawala        this.serviceForBindService = service;
19460716685debb5811792ecd99e71b20bfa4ff6a7bPhil Goodwin & Rick Kawala    }
19560716685debb5811792ecd99e71b20bfa4ff6a7bPhil Goodwin & Rick Kawala
1960871c2e966da6a78491c2c58f5ff526d1ab17004Phil Goodwin & Rick Kawala    @Implementation
1972992159379913de26c8bab3d9d88978ea3084c28pivotal    public boolean bindService(Intent intent, final ServiceConnection serviceConnection, int i) {
198058c2967a3a025d998be7f3c283677c88de4c504Pivotal Shiny Android        if (unbindableActions.contains(intent.getAction())) {
199058c2967a3a025d998be7f3c283677c88de4c504Pivotal Shiny Android            return false;
200058c2967a3a025d998be7f3c283677c88de4c504Pivotal Shiny Android        }
2010871c2e966da6a78491c2c58f5ff526d1ab17004Phil Goodwin & Rick Kawala        startedServices.add(intent);
2022992159379913de26c8bab3d9d88978ea3084c28pivotal        shadowOf(Looper.getMainLooper()).post(new Runnable() {
2032992159379913de26c8bab3d9d88978ea3084c28pivotal            @Override
2042992159379913de26c8bab3d9d88978ea3084c28pivotal            public void run() {
2052992159379913de26c8bab3d9d88978ea3084c28pivotal                serviceConnection.onServiceConnected(componentNameForBindService, serviceForBindService);
2062992159379913de26c8bab3d9d88978ea3084c28pivotal            }
2072992159379913de26c8bab3d9d88978ea3084c28pivotal        }, 0);
2080871c2e966da6a78491c2c58f5ff526d1ab17004Phil Goodwin & Rick Kawala        return true;
2090871c2e966da6a78491c2c58f5ff526d1ab17004Phil Goodwin & Rick Kawala    }
2100871c2e966da6a78491c2c58f5ff526d1ab17004Phil Goodwin & Rick Kawala
211609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala    @Implementation
212609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala    public void unbindService(final ServiceConnection serviceConnection) {
213609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala        unboundServiceConnections.add(serviceConnection);
214609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala        shadowOf(Looper.getMainLooper()).post(new Runnable() {
215609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala            @Override
216609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala            public void run() {
217609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala                serviceConnection.onServiceDisconnected(componentNameForBindService);
218609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala            }
219609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala        }, 0);
220609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala    }
221609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala
222609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala    public List<ServiceConnection> getUnboundServiceConnections() {
223609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala        return unboundServiceConnections;
224609d051ccbc948a9077d0d7d226826c8e3cf2fccJesse Toth & Rick Kawala    }
2256a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
2266a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Consumes the most recent {@code Intent} started by {@link #startActivity(android.content.Intent)} and returns it.
227adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *
2286a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @return the most recently started {@code Intent}
2296a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
2301c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
2311c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public Intent getNextStartedActivity() {
2326fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard        if (startedActivities.isEmpty()) {
2336fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard            return null;
2346fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard        } else {
2356fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard            return startedActivities.remove(0);
2366fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard        }
2376fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard    }
2386fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard
2396a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
2406a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Returns the most recent {@code Intent} started by {@link #startActivity(android.content.Intent)} without
2416a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * consuming it.
242adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *
2436a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @return the most recently started {@code Intent}
2446a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
2451c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
2461c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public Intent peekNextStartedActivity() {
247153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin        if (startedActivities.isEmpty()) {
248153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin            return null;
249153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin        } else {
250153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin            return startedActivities.get(0);
251153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin        }
252153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin    }
253153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin
2546a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
2556a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Consumes the most recent {@code Intent} started by {@link #startService(android.content.Intent)} and returns it.
256adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *
2576a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @return the most recently started {@code Intent}
2586a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
2591c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
2601c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public Intent getNextStartedService() {
2616fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard        if (startedServices.isEmpty()) {
2626c88b7681232641b1b96d533fd6ce5cd9d9a9867Christian Williams            return null;
2636c88b7681232641b1b96d533fd6ce5cd9d9a9867Christian Williams        } else {
2646fb1776c3dd0820074e31a750d991ce69a0597d2Christian Williams & Ryan Richard            return startedServices.remove(0);
2656c88b7681232641b1b96d533fd6ce5cd9d9a9867Christian Williams        }
2666c88b7681232641b1b96d533fd6ce5cd9d9a9867Christian Williams    }
267153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin
2686a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
2696a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Returns the most recent {@code Intent} started by {@link #startService(android.content.Intent)} without
2706a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * consuming it.
271adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *
2726a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @return the most recently started {@code Intent}
2736a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
2741c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
2751c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public Intent peekNextStartedService() {
276153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin        if (startedServices.isEmpty()) {
277153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin            return null;
278153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin        } else {
279153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin            return startedServices.get(0);
280153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin        }
281153375bef736c346ba375c53fdef2c626a0a1457Chee Wong & Phil Goodwin    }
2821c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz
28379d9aa26ae9e43f95f71c0e8c5506a2294eea2a0Dave    /**
284ce10dc20fc2b03d028292d7e9d65af2ed1fba2c8Dave     * Clears all {@code Intent} started by {@link #startService(android.content.Intent)}
285ce10dc20fc2b03d028292d7e9d65af2ed1fba2c8Dave     */
2861c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
2871c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public void clearStartedServices() {
2881c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        startedServices.clear();
2891c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    }
2901c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz
291ce10dc20fc2b03d028292d7e9d65af2ed1fba2c8Dave    /**
2921c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz     * Consumes the {@code Intent} requested to stop a service by {@link #stopService(android.content.Intent)}
29379d9aa26ae9e43f95f71c0e8c5506a2294eea2a0Dave     * from the bottom of the stack of stop requests.
29479d9aa26ae9e43f95f71c0e8c5506a2294eea2a0Dave     */
2951c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
2961c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public Intent getNextStoppedService() {
2971c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        if (stoppedServies.isEmpty()) {
2981c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz            return null;
2991c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        } else {
3001c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz            return stoppedServies.remove(0);
3011c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        }
30279d9aa26ae9e43f95f71c0e8c5506a2294eea2a0Dave    }
303a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams
3046a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
3056a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Non-Android accessor (and a handy way to get a working {@code ResourceLoader}
306adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *
3076a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @return the {@code ResourceLoader} associated with this Application
3086a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
30970650f03fb9161ce77255654517d34b67232588eChristian Williams & Phil Goodwin    public ResourceLoader getResourceLoader() {
310a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams        return resourceLoader;
311a7e263ae4add03982ef3fe294d72ae43102ce52eChristian Williams    }
312e5b3697e977e4be17b802f889643c48226125d56Christian Williams
3136a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
3146a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Broadcasts the {@code Intent} by iterating through the registered receivers, invoking their filters, and calling
3156a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * {@code onRecieve(Application, Intent)} as appropriate. Does not enqueue the {@code Intent} for later inspection.
316adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *
3176a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @param intent the {@code Intent} to broadcast
318adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *               todo: enqueue the Intent for later inspection
3196a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
3201c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
3211c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Implementation
322e5b3697e977e4be17b802f889643c48226125d56Christian Williams    public void sendBroadcast(Intent intent) {
323b3e9fb748b89249eb03508a317664880abb552ffMatthias Kiefer        broadcastIntents.add(intent);
324b3e9fb748b89249eb03508a317664880abb552ffMatthias Kiefer
3251c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        List<Wrapper> copy = new ArrayList<Wrapper>();
3261c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        copy.addAll(registeredReceivers);
3271c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        for (Wrapper wrapper : copy) {
328e5b3697e977e4be17b802f889643c48226125d56Christian Williams            if (wrapper.intentFilter.matchAction(intent.getAction())) {
329e5b3697e977e4be17b802f889643c48226125d56Christian Williams                wrapper.broadcastReceiver.onReceive(realApplication, intent);
330e5b3697e977e4be17b802f889643c48226125d56Christian Williams            }
331e5b3697e977e4be17b802f889643c48226125d56Christian Williams        }
332e5b3697e977e4be17b802f889643c48226125d56Christian Williams    }
333b3e9fb748b89249eb03508a317664880abb552ffMatthias Kiefer
334b3e9fb748b89249eb03508a317664880abb552ffMatthias Kiefer    public List<Intent> getBroadcastIntents() {
335b3e9fb748b89249eb03508a317664880abb552ffMatthias Kiefer        return broadcastIntents;
336b3e9fb748b89249eb03508a317664880abb552ffMatthias Kiefer    }
337e5b3697e977e4be17b802f889643c48226125d56Christian Williams
33888f8f90ced92ded73f5639948d9a5649c3d56baeStefano Dacchille    @Implementation
33988f8f90ced92ded73f5639948d9a5649c3d56baeStefano Dacchille    public void sendStickyBroadcast(Intent intent) {
340f34421dbee452431bce72fb485211739606e8962Stefano Dacchille        stickyIntents.put(intent.getAction(), intent);
34188f8f90ced92ded73f5639948d9a5649c3d56baeStefano Dacchille        sendBroadcast(intent);
34288f8f90ced92ded73f5639948d9a5649c3d56baeStefano Dacchille    }
34388f8f90ced92ded73f5639948d9a5649c3d56baeStefano Dacchille
3446a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
3456a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Always returns {@code null}
346adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *
3476a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @return {@code null}
3486a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
3491c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
3501c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Implementation
351e5b3697e977e4be17b802f889643c48226125d56Christian Williams    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
3520add4ea006647573fc11fac463c87842f2dcc403Christian Williams        return registerReceiverWithContext(receiver, filter, realApplication);
3530add4ea006647573fc11fac463c87842f2dcc403Christian Williams    }
3540add4ea006647573fc11fac463c87842f2dcc403Christian Williams
3550add4ea006647573fc11fac463c87842f2dcc403Christian Williams    Intent registerReceiverWithContext(BroadcastReceiver receiver, IntentFilter filter, Context context) {
35633cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille        if (receiver != null) {
35733cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille            registeredReceivers.add(new Wrapper(receiver, filter, context));
35833cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille        }
35933cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille        return getStickyIntent(filter);
36033cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille    }
36133cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille
36233cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille    private Intent getStickyIntent(IntentFilter filter) {
363f34421dbee452431bce72fb485211739606e8962Stefano Dacchille        for (Intent stickyIntent : stickyIntents.values()) {
36433cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille            String action = null;
36533cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille            for (int i = 0; i < filter.countActions(); i++) {
36633cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille                action = filter.getAction(i);
36733cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille                if (stickyIntent.getAction().equals(action)) {
36833cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille                    return stickyIntent;
36933cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille                }
37033cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille            }
37133cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille        }
37233cb58b49af57097ec8450f1e2e8daed530fa823Stefano Dacchille
373e5b3697e977e4be17b802f889643c48226125d56Christian Williams        return null;
374e5b3697e977e4be17b802f889643c48226125d56Christian Williams    }
375e5b3697e977e4be17b802f889643c48226125d56Christian Williams
3761c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
3771c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Implementation
378e5b3697e977e4be17b802f889643c48226125d56Christian Williams    public void unregisterReceiver(BroadcastReceiver broadcastReceiver) {
379e5b3697e977e4be17b802f889643c48226125d56Christian Williams        boolean found = false;
380e5b3697e977e4be17b802f889643c48226125d56Christian Williams        Iterator<Wrapper> iterator = registeredReceivers.iterator();
381e5b3697e977e4be17b802f889643c48226125d56Christian Williams        while (iterator.hasNext()) {
382e5b3697e977e4be17b802f889643c48226125d56Christian Williams            Wrapper wrapper = iterator.next();
383e5b3697e977e4be17b802f889643c48226125d56Christian Williams            if (wrapper.broadcastReceiver == broadcastReceiver) {
384e5b3697e977e4be17b802f889643c48226125d56Christian Williams                iterator.remove();
385e5b3697e977e4be17b802f889643c48226125d56Christian Williams                found = true;
386e5b3697e977e4be17b802f889643c48226125d56Christian Williams            }
387e5b3697e977e4be17b802f889643c48226125d56Christian Williams        }
388e5b3697e977e4be17b802f889643c48226125d56Christian Williams        if (!found) {
389e5b3697e977e4be17b802f889643c48226125d56Christian Williams            throw new IllegalArgumentException("Receiver not registered: " + broadcastReceiver);
390e5b3697e977e4be17b802f889643c48226125d56Christian Williams        }
391e5b3697e977e4be17b802f889643c48226125d56Christian Williams    }
392e5b3697e977e4be17b802f889643c48226125d56Christian Williams
3936a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
3946a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * Iterates through all of the registered receivers on this {@code Application} and if any of them match the given
3956a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * {@code Context} object throws a {@code RuntimeException}
396adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     *
3976a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @param context the {@code Context} to check for on each of the remaining registered receivers
398adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     * @param type    the type to report for the context if an exception is thrown
3996a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     * @throws RuntimeException if there are any recievers registered with the given {@code Context}
4006a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
401cfbfc594c509dd0b8b70d5dfad9692947f3ef506Christian Williams    public void assertNoBroadcastListenersRegistered(Context context, String type) {
4020add4ea006647573fc11fac463c87842f2dcc403Christian Williams        for (Wrapper registeredReceiver : registeredReceivers) {
4030add4ea006647573fc11fac463c87842f2dcc403Christian Williams            if (registeredReceiver.context == context) {
404cfbfc594c509dd0b8b70d5dfad9692947f3ef506Christian Williams                RuntimeException e = new IllegalStateException(type + " " + context + " leaked has leaked IntentReceiver "
4050add4ea006647573fc11fac463c87842f2dcc403Christian Williams                        + registeredReceiver.broadcastReceiver + " that was originally registered here. " +
4060add4ea006647573fc11fac463c87842f2dcc403Christian Williams                        "Are you missing a call to unregisterReceiver()?");
4070add4ea006647573fc11fac463c87842f2dcc403Christian Williams                e.setStackTrace(registeredReceiver.exception.getStackTrace());
4080add4ea006647573fc11fac463c87842f2dcc403Christian Williams                throw e;
4090add4ea006647573fc11fac463c87842f2dcc403Christian Williams            }
4100add4ea006647573fc11fac463c87842f2dcc403Christian Williams        }
4110add4ea006647573fc11fac463c87842f2dcc403Christian Williams    }
4120add4ea006647573fc11fac463c87842f2dcc403Christian Williams
4131c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    public void assertNoBroadcastListenersOfActionRegistered(Context context, String action) {
4141c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        for (Wrapper registeredReceiver : registeredReceivers) {
4151c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz            if (registeredReceiver.context == context) {
4161c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                Iterator<String> actions = registeredReceiver.intentFilter.actionsIterator();
4171c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                while (actions.hasNext()) {
4181c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                    if (actions.next().equals(action)) {
4191c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                        RuntimeException e = new IllegalStateException("Unexpected BroadcastReceiver on " + context +
4201c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                                " with action " + action + " "
4211c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                                + registeredReceiver.broadcastReceiver + " that was originally registered here:");
4221c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                        e.setStackTrace(registeredReceiver.exception.getStackTrace());
4231c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                        throw e;
4241c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                    }
4251c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz                }
4261c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz            }
4271c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz        }
4281c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    }
4291c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz
43019b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala    public boolean hasReceiverForIntent(Intent intent) {
43119b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala        for (Wrapper wrapper : registeredReceivers) {
43219b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala            if (wrapper.intentFilter.matchAction(intent.getAction())) {
43319b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala                return true;
43419b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala            }
43519b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala        }
43619b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala        return false;
43719b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala    }
43819b2ad34fedcb153f5faed627e9197e9f723a4c2Phil Goodwin & Rick Kawala
439d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala    public List<BroadcastReceiver> getReceiversForIntent(Intent intent) {
440d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala        ArrayList<BroadcastReceiver> broadcastReceivers = new ArrayList<BroadcastReceiver>();
441d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala        for (Wrapper wrapper : registeredReceivers) {
442d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala            if (wrapper.intentFilter.matchAction(intent.getAction())) {
443d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala                broadcastReceivers.add(wrapper.getBroadcastReceiver());
444d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala            }
445d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala        }
446d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala        return broadcastReceivers;
447d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala    }
448d1187f6f20be286bcb860840352bdb70d0cdc6c8Phil Goodwin & Rick Kawala
4496a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
450adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     * Non-Android accessor.
45140c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams     *
452fffbcf54817243f6192cf2443257d57198f1ea78Phil Goodwin     * @return list of {@link Wrapper}s for registered receivers
4536a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
454cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    public List<Wrapper> getRegisteredReceivers() {
455cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin        return registeredReceivers;
456cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    }
457cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin
4586a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
459adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     * Non-Android accessor.
46040c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams     *
461fffbcf54817243f6192cf2443257d57198f1ea78Phil Goodwin     * @return the layout inflater used by this {@code Application}
4626a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
463cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    public LayoutInflater getLayoutInflater() {
464cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin        return layoutInflater;
465cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    }
466cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin
4676a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin    /**
468adfaceabbda4c8c51f24a0def8926075bd7306adChristian Williams     * Non-Android accessor.
46940c6251719cccc0a84ae99c976d2836b14374ce6Christian Williams     *
470fffbcf54817243f6192cf2443257d57198f1ea78Phil Goodwin     * @return the app widget manager used by this {@code Application}
4716a3415646e4410abf4766e5e7fad273a2bd042acPhil Goodwin     */
472cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    public AppWidgetManager getAppWidgetManager() {
473cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin        return appWidgetManager;
474cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    }
475cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin
476f91a118112ae13d39251dd3c09f1d85d33283ba1Christian Williams & Phil Goodwin    public FakeHttpLayer getFakeHttpLayer() {
477f91a118112ae13d39251dd3c09f1d85d33283ba1Christian Williams & Phil Goodwin        return fakeHttpLayer;
478f91a118112ae13d39251dd3c09f1d85d33283ba1Christian Williams & Phil Goodwin    }
479f91a118112ae13d39251dd3c09f1d85d33283ba1Christian Williams & Phil Goodwin
4801c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Override
4811c5a1843c60477a9a49148c46cb1b98d5ee5b26bTim Labeeuw & Tyler Schultz    @Implementation
4827d446513cda09628ec24023cfdebeca847700b52Christian Williams & Phil Goodwin    public Looper getMainLooper() {
4837d446513cda09628ec24023cfdebeca847700b52Christian Williams & Phil Goodwin        return mainLooper;
4847d446513cda09628ec24023cfdebeca847700b52Christian Williams & Phil Goodwin    }
4857d446513cda09628ec24023cfdebeca847700b52Christian Williams & Phil Goodwin
4869ae1d769a5136e8382d7712bb9afc4fedb6d0060David Farber & Lowell Kirsh    public Map<String, Map<String, Object>> getSharedPreferenceMap() {
4875ae1c7fd48d3a37bab8af74fec0f70f0a0935f49Christian Williams & Phil Goodwin        return sharedPreferenceMap;
4885ae1c7fd48d3a37bab8af74fec0f70f0a0935f49Christian Williams & Phil Goodwin    }
4895ae1c7fd48d3a37bab8af74fec0f70f0a0935f49Christian Williams & Phil Goodwin
490854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    public ShadowAlertDialog getLatestAlertDialog() {
491854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin        return latestAlertDialog;
492854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    }
493854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin
494854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    public void setLatestAlertDialog(ShadowAlertDialog latestAlertDialog) {
495854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin        this.latestAlertDialog = latestAlertDialog;
496854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    }
497854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin
498854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    public ShadowDialog getLatestDialog() {
499854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin        return latestDialog;
500854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    }
501854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin
502854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    public void setLatestDialog(ShadowDialog latestDialog) {
503854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin        this.latestDialog = latestDialog;
504854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin    }
505854ca0a46da43847ab5b2ed9ce4ad8f580ae5a17Christian Williams & Phil Goodwin
5061741463ed4618ec2b72cbd7764649fd0cca10a40Phil Goodwin    public Object getBluetoothAdapter() {
507b01474a3329222965d31068f5c33e59c6e6aa6a4Josh Lauer & Christian Williams        return bluetoothAdapter;
508b01474a3329222965d31068f5c33e59c6e6aa6a4Josh Lauer & Christian Williams    }
509b01474a3329222965d31068f5c33e59c6e6aa6a4Josh Lauer & Christian Williams
510058c2967a3a025d998be7f3c283677c88de4c504Pivotal Shiny Android    public void declareActionUnbindable(String action) {
511058c2967a3a025d998be7f3c283677c88de4c504Pivotal Shiny Android        unbindableActions.add(action);
512058c2967a3a025d998be7f3c283677c88de4c504Pivotal Shiny Android    }
513058c2967a3a025d998be7f3c283677c88de4c504Pivotal Shiny Android
51463b3a0ea111f7f644dd5611412c9052914138605Stefano Dacchille    public void setSystemService(String key, Object service) {
51563b3a0ea111f7f644dd5611412c9052914138605Stefano Dacchille        systemServices.put(key, service);
51663b3a0ea111f7f644dd5611412c9052914138605Stefano Dacchille    }
51763b3a0ea111f7f644dd5611412c9052914138605Stefano Dacchille
518fffbcf54817243f6192cf2443257d57198f1ea78Phil Goodwin    public class Wrapper {
51972ca49dced475c55926dbad730c306184bb6a68eDavid Farber & Ryan Richard        public BroadcastReceiver broadcastReceiver;
52072ca49dced475c55926dbad730c306184bb6a68eDavid Farber & Ryan Richard        public IntentFilter intentFilter;
52172ca49dced475c55926dbad730c306184bb6a68eDavid Farber & Ryan Richard        public Context context;
5220add4ea006647573fc11fac463c87842f2dcc403Christian Williams        public Throwable exception;
523e5b3697e977e4be17b802f889643c48226125d56Christian Williams
5240add4ea006647573fc11fac463c87842f2dcc403Christian Williams        public Wrapper(BroadcastReceiver broadcastReceiver, IntentFilter intentFilter, Context context) {
525e5b3697e977e4be17b802f889643c48226125d56Christian Williams            this.broadcastReceiver = broadcastReceiver;
526e5b3697e977e4be17b802f889643c48226125d56Christian Williams            this.intentFilter = intentFilter;
5270add4ea006647573fc11fac463c87842f2dcc403Christian Williams            this.context = context;
5280add4ea006647573fc11fac463c87842f2dcc403Christian Williams            exception = new Throwable();
529e5b3697e977e4be17b802f889643c48226125d56Christian Williams        }
530845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala
531845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala        public BroadcastReceiver getBroadcastReceiver() {
532845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala            return broadcastReceiver;
533845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala        }
534845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala
535845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala        public IntentFilter getIntentFilter() {
536845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala            return intentFilter;
537845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala        }
538845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala
539845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala        public Context getContext() {
540845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala            return context;
541845165f98ff048e8074e94fbc860b566cbae9d11Glenn Jahnke & Rick Kawala        }
542e5b3697e977e4be17b802f889643c48226125d56Christian Williams    }
5438baea4cbf332f0e0acf559dfab4aa59dd7c71003Christian Williams & Ryan Richard}
544