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