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