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