• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
4 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
5 import static android.os.Build.VERSION_CODES.KITKAT;
6 import static android.os.Build.VERSION_CODES.LOLLIPOP;
7 import static android.os.Build.VERSION_CODES.M;
8 import static android.os.Build.VERSION_CODES.N_MR1;
9 import static android.os.Build.VERSION_CODES.O;
10 import static android.os.Build.VERSION_CODES.P;
11 import static android.os.Build.VERSION_CODES.Q;
12 import static android.os.Build.VERSION_CODES.R;
13 import static android.os.Build.VERSION_CODES.S;
14 
15 import android.accounts.IAccountManager;
16 import android.app.IAlarmManager;
17 import android.app.INotificationManager;
18 import android.app.ISearchManager;
19 import android.app.admin.IDevicePolicyManager;
20 import android.app.job.IJobScheduler;
21 import android.app.slice.ISliceManager;
22 import android.app.trust.ITrustManager;
23 import android.app.usage.IUsageStatsManager;
24 import android.content.Context;
25 import android.content.IClipboard;
26 import android.content.IRestrictionsManager;
27 import android.content.pm.ICrossProfileApps;
28 import android.content.pm.IShortcutService;
29 import android.hardware.display.IColorDisplayManager;
30 import android.hardware.fingerprint.IFingerprintService;
31 import android.hardware.input.IInputManager;
32 import android.hardware.usb.IUsbManager;
33 import android.location.ICountryDetector;
34 import android.location.ILocationManager;
35 import android.media.IAudioService;
36 import android.media.IMediaRouterService;
37 import android.media.session.ISessionManager;
38 import android.net.IConnectivityManager;
39 import android.net.INetworkScoreService;
40 import android.net.ITetheringConnector;
41 import android.net.IVpnManager;
42 import android.net.nsd.INsdManager;
43 import android.net.wifi.IWifiManager;
44 import android.net.wifi.p2p.IWifiP2pManager;
45 import android.os.BatteryStats;
46 import android.os.Binder;
47 import android.os.IBatteryPropertiesRegistrar;
48 import android.os.IBinder;
49 import android.os.IInterface;
50 import android.os.IPowerManager;
51 import android.os.IThermalService;
52 import android.os.IUserManager;
53 import android.os.RemoteException;
54 import android.os.ServiceManager;
55 import android.os.storage.IStorageManager;
56 import android.permission.IPermissionManager;
57 import android.service.persistentdata.IPersistentDataBlockService;
58 import android.view.IWindowManager;
59 
60 import com.android.internal.app.IAppOpsService;
61 import com.android.internal.app.IBatteryStats;
62 import com.android.internal.appwidget.IAppWidgetService;
63 import com.android.internal.os.IDropBoxManagerService;
64 import com.android.internal.view.IInputMethodManager;
65 import java.util.Collections;
66 import java.util.HashMap;
67 import java.util.HashSet;
68 import java.util.Map;
69 import java.util.Set;
70 import org.robolectric.RuntimeEnvironment;
71 import org.robolectric.annotation.Implementation;
72 import org.robolectric.annotation.Implements;
73 import org.robolectric.annotation.Resetter;
74 import org.robolectric.util.ReflectionHelpers;
75 
76 @SuppressWarnings("NewApi")
77 @Implements(value = ServiceManager.class, isInAndroidSdk = false)
78 public class ShadowServiceManager {
79 
80   private static final Map<String, IBinder> SERVICES;
81 
82   private static final Set<String> unavailableServices = new HashSet<>();
83 
84   static {
85     Map<String, IBinder> map = new HashMap<>();
map.put( Context.CLIPBOARD_SERVICE, createBinder(IClipboard.class, "android.content.IClipboard"))86     map.put(
87         Context.CLIPBOARD_SERVICE, createBinder(IClipboard.class, "android.content.IClipboard"));
map.put( Context.WIFI_P2P_SERVICE, createBinder(IWifiP2pManager.class, "android.net.wifi.p2p.IWifiP2pManager"))88     map.put(
89         Context.WIFI_P2P_SERVICE,
90         createBinder(IWifiP2pManager.class, "android.net.wifi.p2p.IWifiP2pManager"));
map.put( Context.ACCOUNT_SERVICE, createBinder(IAccountManager.class, "android.accounts.IAccountManager"))91     map.put(
92         Context.ACCOUNT_SERVICE,
93         createBinder(IAccountManager.class, "android.accounts.IAccountManager"));
map.put( Context.USB_SERVICE, createBinder(IUsbManager.class, "android.hardware.usb.IUsbManager"))94     map.put(
95         Context.USB_SERVICE, createBinder(IUsbManager.class, "android.hardware.usb.IUsbManager"));
map.put( Context.LOCATION_SERVICE, createBinder(ILocationManager.class, "android.location.ILocationManager"))96     map.put(
97         Context.LOCATION_SERVICE,
98         createBinder(ILocationManager.class, "android.location.ILocationManager"));
map.put( Context.INPUT_METHOD_SERVICE, createBinder(IInputMethodManager.class, "com.android.internal.view.IInputMethodManager"))99     map.put(
100         Context.INPUT_METHOD_SERVICE,
101         createBinder(IInputMethodManager.class, "com.android.internal.view.IInputMethodManager"));
map.put(Context.ALARM_SERVICE, createBinder(IAlarmManager.class, "android.app.IAlarmManager"))102     map.put(Context.ALARM_SERVICE, createBinder(IAlarmManager.class, "android.app.IAlarmManager"));
map.put(Context.POWER_SERVICE, createBinder(IPowerManager.class, "android.os.IPowerManager"))103     map.put(Context.POWER_SERVICE, createBinder(IPowerManager.class, "android.os.IPowerManager"));
map.put( BatteryStats.SERVICE_NAME, createBinder(IBatteryStats.class, "com.android.internal.app.IBatteryStats"))104     map.put(
105         BatteryStats.SERVICE_NAME,
106         createBinder(IBatteryStats.class, "com.android.internal.app.IBatteryStats"));
map.put( Context.DROPBOX_SERVICE, createBinder( IDropBoxManagerService.class, "com.android.internal.os.IDropBoxManagerService"))107     map.put(
108         Context.DROPBOX_SERVICE,
109         createBinder(
110             IDropBoxManagerService.class, "com.android.internal.os.IDropBoxManagerService"));
map.put( Context.DEVICE_POLICY_SERVICE, createBinder(IDevicePolicyManager.class, "android.app.admin.IDevicePolicyManager"))111     map.put(
112         Context.DEVICE_POLICY_SERVICE,
113         createBinder(IDevicePolicyManager.class, "android.app.admin.IDevicePolicyManager"));
map.put( Context.CONNECTIVITY_SERVICE, createBinder(IConnectivityManager.class, "android.net.IConnectivityManager"))114     map.put(
115         Context.CONNECTIVITY_SERVICE,
116         createBinder(IConnectivityManager.class, "android.net.IConnectivityManager"));
map.put( Context.WIFI_SERVICE, createBinder(IWifiManager.class, "android.net.wifi.IWifiManager"))117     map.put(
118         Context.WIFI_SERVICE, createBinder(IWifiManager.class, "android.net.wifi.IWifiManager"));
map.put( Context.SEARCH_SERVICE, createBinder(ISearchManager.class, "android.app.ISearchManager"))119     map.put(
120         Context.SEARCH_SERVICE, createBinder(ISearchManager.class, "android.app.ISearchManager"));
map.put( Context.UI_MODE_SERVICE, createBinder(ISearchManager.class, "android.app.IUiModeManager"))121     map.put(
122         Context.UI_MODE_SERVICE, createBinder(ISearchManager.class, "android.app.IUiModeManager"));
map.put( Context.NETWORK_POLICY_SERVICE, createBinder(ISearchManager.class, "android.net.INetworkPolicyManager"))123     map.put(
124         Context.NETWORK_POLICY_SERVICE,
125         createBinder(ISearchManager.class, "android.net.INetworkPolicyManager"));
map.put(Context.INPUT_SERVICE, createBinder(IInputManager.class, "android.net.IInputManager"))126     map.put(Context.INPUT_SERVICE, createBinder(IInputManager.class, "android.net.IInputManager"));
map.put( Context.COUNTRY_DETECTOR, createBinder(ICountryDetector.class, "android.location.ICountryDetector"))127     map.put(
128         Context.COUNTRY_DETECTOR,
129         createBinder(ICountryDetector.class, "android.location.ICountryDetector"));
map.put( Context.NSD_SERVICE, createBinder(INsdManager.class, "android.net.nsd.INsdManagerandroi"))130     map.put(
131         Context.NSD_SERVICE, createBinder(INsdManager.class, "android.net.nsd.INsdManagerandroi"));
map.put( Context.AUDIO_SERVICE, createBinder(IAudioService.class, "android.media.IAudioService"))132     map.put(
133         Context.AUDIO_SERVICE, createBinder(IAudioService.class, "android.media.IAudioService"));
map.put( Context.APPWIDGET_SERVICE, createBinder(IAppWidgetService.class, "com.android.internal.appwidget.IAppWidgetService"))134     map.put(
135         Context.APPWIDGET_SERVICE,
136         createBinder(IAppWidgetService.class, "com.android.internal.appwidget.IAppWidgetService"));
map.put( Context.WINDOW_SERVICE, createBinder(IWindowManager.class, "android.view.IWindowManager"))137     map.put(
138             Context.WINDOW_SERVICE,
139             createBinder(IWindowManager.class, "android.view.IWindowManager"));
140 
141     if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR1) {
map.put(Context.USER_SERVICE, createBinder(IUserManager.class, "android.os.IUserManager"))142       map.put(Context.USER_SERVICE, createBinder(IUserManager.class, "android.os.IUserManager"));
143     }
144     if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR2) {
map.put( Context.APP_OPS_SERVICE, createBinder(IAppOpsService.class, "com.android.internal.app.IAppOpsService"))145       map.put(
146           Context.APP_OPS_SERVICE,
147           createBinder(IAppOpsService.class, "com.android.internal.app.IAppOpsService"));
148     }
149     if (RuntimeEnvironment.getApiLevel() >= KITKAT) {
150       map.put(
151           "batteryproperties",
152           createBinder(
153               IBatteryPropertiesRegistrar.class, "android.os.IBatteryPropertiesRegistrar"));
154     }
155     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) {
map.put( Context.RESTRICTIONS_SERVICE, createBinder(IRestrictionsManager.class, "android.content.IRestrictionsManager"))156       map.put(
157           Context.RESTRICTIONS_SERVICE,
158           createBinder(IRestrictionsManager.class, "android.content.IRestrictionsManager"));
map.put( Context.TRUST_SERVICE, createBinder(ITrustManager.class, "android.app.trust.ITrustManager"))159       map.put(
160           Context.TRUST_SERVICE,
161           createBinder(ITrustManager.class, "android.app.trust.ITrustManager"));
map.put( Context.JOB_SCHEDULER_SERVICE, createBinder(IJobScheduler.class, "android.app.job.IJobScheduler"))162       map.put(
163           Context.JOB_SCHEDULER_SERVICE,
164           createBinder(IJobScheduler.class, "android.app.job.IJobScheduler"));
map.put( Context.NETWORK_SCORE_SERVICE, createBinder(INetworkScoreService.class, "android.net.INetworkScoreService"))165       map.put(
166           Context.NETWORK_SCORE_SERVICE,
167           createBinder(INetworkScoreService.class, "android.net.INetworkScoreService"));
map.put( Context.USAGE_STATS_SERVICE, createBinder(IUsageStatsManager.class, "android.app.usage.IUsageStatsManager"))168       map.put(
169           Context.USAGE_STATS_SERVICE,
170           createBinder(IUsageStatsManager.class, "android.app.usage.IUsageStatsManager"));
map.put( Context.MEDIA_ROUTER_SERVICE, createBinder(IMediaRouterService.class, "android.media.IMediaRouterService"))171       map.put(
172           Context.MEDIA_ROUTER_SERVICE,
173           createBinder(IMediaRouterService.class, "android.media.IMediaRouterService"));
map.put( Context.MEDIA_SESSION_SERVICE, createDeepBinder(ISessionManager.class, "android.media.session.ISessionManager"))174       map.put(
175           Context.MEDIA_SESSION_SERVICE,
176           createDeepBinder(ISessionManager.class, "android.media.session.ISessionManager"));
map.put( Context.PERSISTENT_DATA_BLOCK_SERVICE, createBinder(IPersistentDataBlockService.class, "android.service.persistentdata.IPersistentDataBlockService"))177       map.put(
178           Context.PERSISTENT_DATA_BLOCK_SERVICE,
179           createBinder(IPersistentDataBlockService.class,
180                   "android.service.persistentdata.IPersistentDataBlockService"));
181     }
182     if (RuntimeEnvironment.getApiLevel() >= M) {
map.put( Context.FINGERPRINT_SERVICE, createBinder( IFingerprintService.class, "android.hardware.fingerprint.IFingerprintService"))183       map.put(
184           Context.FINGERPRINT_SERVICE,
185           createBinder(
186               IFingerprintService.class, "android.hardware.fingerprint.IFingerprintService"));
187     }
188     if (RuntimeEnvironment.getApiLevel() >= N_MR1) {
map.put( Context.SHORTCUT_SERVICE, createBinder(IShortcutService.class, "android.content.pm.IShortcutService"))189       map.put(
190           Context.SHORTCUT_SERVICE,
191           createBinder(IShortcutService.class, "android.content.pm.IShortcutService"));
192     }
193     if (RuntimeEnvironment.getApiLevel() >= O) {
194       map.put("mount", createBinder(IStorageManager.class, "android.os.storage.IStorageManager"));
195     } else {
196       map.put(
197           "mount",
198           createBinder("android.os.storage.IMountService", "android.os.storage.IMountService"));
199     }
200     if (RuntimeEnvironment.getApiLevel() >= P) {
map.put( Context.SLICE_SERVICE, createBinder(ISliceManager.class, "android.app.slice.SliceManager"))201       map.put(
202           Context.SLICE_SERVICE,
203           createBinder(ISliceManager.class, "android.app.slice.SliceManager"));
map.put( Context.CROSS_PROFILE_APPS_SERVICE, createBinder(ICrossProfileApps.class, "android.content.pm.ICrossProfileApps"))204       map.put(
205           Context.CROSS_PROFILE_APPS_SERVICE,
206           createBinder(ICrossProfileApps.class, "android.content.pm.ICrossProfileApps"));
207     }
208     // BEGIN-INTERNAL
209     if (RuntimeEnvironment.getApiLevel() >= Q) {
map.put(Context.NOTIFICATION_SERVICE, createBinder(INotificationManager.class, "android.app.INotificationManager"))210       map.put(Context.NOTIFICATION_SERVICE,
211           createBinder(INotificationManager.class, "android.app.INotificationManager"));
map.put(Context.COLOR_DISPLAY_SERVICE, createBinder(IColorDisplayManager.class, "android.hardware.display.ColorDisplayManager"))212       map.put(Context.COLOR_DISPLAY_SERVICE, createBinder(IColorDisplayManager.class,
213           "android.hardware.display.ColorDisplayManager"));
214     }
215     if (RuntimeEnvironment.getApiLevel() >= R) {
map.put(Context.TETHERING_SERVICE, createBinder(ITetheringConnector.class, "android.net.ITetheringConnector"))216       map.put(Context.TETHERING_SERVICE,
217               createBinder(ITetheringConnector.class, "android.net.ITetheringConnector"));
map.put(Context.THERMAL_SERVICE, createBinder(IThermalService.class, "android.os.IThermalService"))218       map.put(Context.THERMAL_SERVICE,
219               createBinder(IThermalService.class, "android.os.IThermalService"));
220     }
221     if (RuntimeEnvironment.getApiLevel() >= S) {
222       map.put("permissionmgr",
223               createBinder(IPermissionManager.class, "android.permission.IPermissionManager"));
map.put(Context.VPN_MANAGEMENT_SERVICE, createBinder(IVpnManager.class, "android.net.IVpnManager"))224       map.put(Context.VPN_MANAGEMENT_SERVICE,
225               createBinder(IVpnManager.class, "android.net.IVpnManager"));
226     }
227     // END-INTERNAL
228     SERVICES = Collections.unmodifiableMap(map);
229   }
230 
231   /**
232    * Returns the binder associated with the given system service. If the given service is set to
233    * unavailable in {@link #setServiceAvailability}, {@code null} will be returned.
234    */
235   @Implementation
getService(String name)236   protected static IBinder getService(String name) {
237     if (unavailableServices.contains(name)) {
238       return null;
239     }
240     return SERVICES.get(name);
241   }
242 
createBinder(String className, String descriptor)243   private static Binder createBinder(String className, String descriptor) {
244     Class<IInterface> clazz;
245     try {
246       clazz = (Class<IInterface>) Class.forName(className);
247     } catch (ClassNotFoundException e) {
248       throw new RuntimeException(e);
249     }
250     Binder binder = new Binder();
251     binder.attachInterface(ReflectionHelpers.createNullProxy(clazz), descriptor);
252     return binder;
253   }
254 
createBinder(Class<? extends IInterface> clazz, String descriptor)255   private static Binder createBinder(Class<? extends IInterface> clazz, String descriptor) {
256     Binder binder = new Binder();
257     binder.attachInterface(ReflectionHelpers.createNullProxy(clazz), descriptor);
258     return binder;
259   }
260 
createDeepBinder(Class<? extends IInterface> clazz, String descriptor)261   private static Binder createDeepBinder(Class<? extends IInterface> clazz, String descriptor) {
262     Binder binder = new Binder();
263     binder.attachInterface(ReflectionHelpers.createDeepProxy(clazz), descriptor);
264     return binder;
265   }
266 
267   @Implementation
addService(String name, IBinder service)268   protected static void addService(String name, IBinder service) {}
269 
270   @Implementation
checkService(String name)271   protected static IBinder checkService(String name) {
272     return null;
273   }
274 
275   @Implementation
listServices()276   protected static String[] listServices() throws RemoteException {
277     return null;
278   }
279 
280   @Implementation
initServiceCache(Map<String, IBinder> cache)281   protected static void initServiceCache(Map<String, IBinder> cache) {}
282 
283   /**
284    * Sets the availability of the given system service. If the service is set as unavailable,
285    * subsequent calls to {@link Context#getSystemService} for that service will return {@code null}.
286    */
setServiceAvailability(String service, boolean available)287   public static void setServiceAvailability(String service, boolean available) {
288     if (available) {
289       unavailableServices.remove(service);
290     } else {
291       unavailableServices.add(service);
292     }
293   }
294 
295   @Resetter
reset()296   public static void reset() {
297     unavailableServices.clear();
298   }
299 }
300