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<>(); 77 map.put( 78 Context.CLIPBOARD_SERVICE, createBinder(IClipboard.class, "android.content.IClipboard")); 79 map.put( 80 Context.WIFI_P2P_SERVICE, 81 createBinder(IWifiP2pManager.class, "android.net.wifi.p2p.IWifiP2pManager")); 82 map.put( 83 Context.ACCOUNT_SERVICE, 84 createBinder(IAccountManager.class, "android.accounts.IAccountManager")); 85 map.put( 86 Context.USB_SERVICE, createBinder(IUsbManager.class, "android.hardware.usb.IUsbManager")); 87 map.put( 88 Context.LOCATION_SERVICE, 89 createBinder(ILocationManager.class, "android.location.ILocationManager")); 90 map.put( 91 Context.INPUT_METHOD_SERVICE, 92 createBinder(IInputMethodManager.class, "com.android.internal.view.IInputMethodManager")); 93 map.put(Context.ALARM_SERVICE, createBinder(IAlarmManager.class, "android.app.IAlarmManager")); 94 map.put(Context.POWER_SERVICE, createBinder(IPowerManager.class, "android.os.IPowerManager")); 95 map.put( 96 BatteryStats.SERVICE_NAME, 97 createBinder(IBatteryStats.class, "com.android.internal.app.IBatteryStats")); 98 map.put( 99 Context.DROPBOX_SERVICE, 100 createBinder( 101 IDropBoxManagerService.class, "com.android.internal.os.IDropBoxManagerService")); 102 map.put( 103 Context.DEVICE_POLICY_SERVICE, 104 createBinder(IDevicePolicyManager.class, "android.app.admin.IDevicePolicyManager")); 105 map.put( 106 Context.CONNECTIVITY_SERVICE, 107 createBinder(IConnectivityManager.class, "android.net.IConnectivityManager")); 108 map.put( 109 Context.WIFI_SERVICE, createBinder(IWifiManager.class, "android.net.wifi.IWifiManager")); 110 map.put( 111 Context.SEARCH_SERVICE, createBinder(ISearchManager.class, "android.app.ISearchManager")); 112 map.put( 113 Context.UI_MODE_SERVICE, createBinder(ISearchManager.class, "android.app.IUiModeManager")); 114 map.put( 115 Context.NETWORK_POLICY_SERVICE, 116 createBinder(ISearchManager.class, "android.net.INetworkPolicyManager")); 117 map.put(Context.INPUT_SERVICE, createBinder(IInputManager.class, "android.net.IInputManager")); 118 map.put( 119 Context.COUNTRY_DETECTOR, 120 createBinder(ICountryDetector.class, "android.location.ICountryDetector")); 121 map.put( 122 Context.NSD_SERVICE, createBinder(INsdManager.class, "android.net.nsd.INsdManagerandroi")); 123 map.put( 124 Context.AUDIO_SERVICE, createBinder(IAudioService.class, "android.media.IAudioService")); 125 map.put( 126 Context.APPWIDGET_SERVICE, 127 createBinder(IAppWidgetService.class, "com.android.internal.appwidget.IAppWidgetService")); 128 129 if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR1) { 130 map.put(Context.USER_SERVICE, createBinder(IUserManager.class, "android.os.IUserManager")); 131 } 132 if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR2) { 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) { 144 map.put( 145 Context.RESTRICTIONS_SERVICE, 146 createBinder(IRestrictionsManager.class, "android.content.IRestrictionsManager")); 147 map.put( 148 Context.TRUST_SERVICE, 149 createBinder(ITrustManager.class, "android.app.trust.ITrustManager")); 150 map.put( 151 Context.JOB_SCHEDULER_SERVICE, 152 createBinder(IJobScheduler.class, "android.app.job.IJobScheduler")); 153 map.put( 154 Context.NETWORK_SCORE_SERVICE, 155 createBinder(INetworkScoreService.class, "android.net.INetworkScoreService")); 156 map.put( 157 Context.USAGE_STATS_SERVICE, 158 createBinder(IUsageStatsManager.class, "android.app.usage.IUsageStatsManager")); 159 map.put( 160 Context.MEDIA_ROUTER_SERVICE, 161 createBinder(IMediaRouterService.class, "android.media.IMediaRouterService")); 162 map.put( 163 Context.MEDIA_SESSION_SERVICE, 164 createDeepBinder(ISessionManager.class, "android.media.session.ISessionManager")); 165 } 166 if (RuntimeEnvironment.getApiLevel() >= M) { 167 map.put( 168 Context.FINGERPRINT_SERVICE, 169 createBinder( 170 IFingerprintService.class, "android.hardware.fingerprint.IFingerprintService")); 171 } 172 if (RuntimeEnvironment.getApiLevel() >= N_MR1) { 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) { 185 map.put( 186 Context.SLICE_SERVICE, 187 createBinder(ISliceManager.class, "android.app.slice.SliceManager")); 188 } 189 // BEGIN-INTERNAL 190 if (RuntimeEnvironment.getApiLevel() >= Q) { 191 map.put(Context.NOTIFICATION_SERVICE, 192 createBinder(INotificationManager.class, "android.app.INotificationManager")); 193 map.put(Context.COLOR_DISPLAY_SERVICE, createBinder(IColorDisplayManager.class, 194 "android.hardware.display.ColorDisplayManager")); 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 207 protected static IBinder getService(String name) { 208 if (unavailableServices.contains(name)) { 209 return null; 210 } 211 return SERVICES.get(name); 212 } 213 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 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 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 239 protected static void addService(String name, IBinder service) {} 240 241 @Implementation 242 protected static IBinder checkService(String name) { 243 return null; 244 } 245 246 @Implementation 247 protected static String[] listServices() throws RemoteException { 248 return null; 249 } 250 251 @Implementation 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 */ 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 267 public static void reset() { 268 unavailableServices.clear(); 269 } 270 } 271