1package org.robolectric.shadows; 2 3import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; 4import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; 5import static android.os.Build.VERSION_CODES.KITKAT; 6import static android.os.Build.VERSION_CODES.LOLLIPOP; 7import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 8import static android.os.Build.VERSION_CODES.M; 9import static android.os.Build.VERSION_CODES.N; 10import static android.os.Build.VERSION_CODES.N_MR1; 11import static android.os.Build.VERSION_CODES.O; 12import static android.os.Build.VERSION_CODES.O_MR1; 13import static org.robolectric.RuntimeEnvironment.getApiLevel; 14import static org.robolectric.shadow.api.Shadow.newInstanceOf; 15 16import android.accounts.IAccountManager; 17import android.app.IWallpaperManager; 18import android.app.admin.IDevicePolicyManager; 19import android.content.BroadcastReceiver; 20import android.content.ComponentName; 21import android.content.ContentResolver; 22import android.content.Context; 23import android.content.IContentProvider; 24import android.content.IRestrictionsManager; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.content.IntentSender; 28import android.content.ServiceConnection; 29import android.hardware.SystemSensorManager; 30import android.hardware.fingerprint.IFingerprintService; 31import android.net.wifi.p2p.IWifiP2pManager; 32import android.net.wifi.p2p.WifiP2pManager; 33import android.os.Bundle; 34import android.os.Environment; 35import android.os.Handler; 36import android.os.IUserManager; 37import android.os.Looper; 38import android.os.UserHandle; 39import android.view.Display; 40import android.view.accessibility.AccessibilityManager; 41import android.view.autofill.IAutoFillManager; 42import java.io.File; 43import java.util.HashMap; 44import java.util.Map; 45import org.robolectric.RuntimeEnvironment; 46import org.robolectric.annotation.Implementation; 47import org.robolectric.annotation.Implements; 48import org.robolectric.annotation.RealObject; 49import org.robolectric.annotation.Resetter; 50import org.robolectric.util.ReflectionHelpers; 51import org.robolectric.util.ReflectionHelpers.ClassParameter; 52 53@Implements(className = ShadowContextImpl.CLASS_NAME) 54public class ShadowContextImpl { 55 56 public static final String CLASS_NAME = "android.app.ContextImpl"; 57 private static final Map<String, String> SYSTEM_SERVICE_MAP = new HashMap<>(); 58 private ContentResolver contentResolver; 59 60 @RealObject 61 private Context realObject; 62 63 static { 64 // note that these are different! 65 // They specify concrete classes within Robolectric for interfaces or abstract classes defined by Android 66 SYSTEM_SERVICE_MAP.put(Context.WINDOW_SERVICE, "android.view.WindowManagerImpl"); 67 SYSTEM_SERVICE_MAP.put(Context.CLIPBOARD_SERVICE, "android.content.ClipboardManager"); 68 SYSTEM_SERVICE_MAP.put(Context.SENSOR_SERVICE, "android.hardware.SystemSensorManager"); 69 SYSTEM_SERVICE_MAP.put(Context.VIBRATOR_SERVICE, "org.robolectric.fakes.RoboVibrator"); 70 71 // the rest are as mapped in docs... 72 SYSTEM_SERVICE_MAP.put(Context.LAYOUT_INFLATER_SERVICE, "android.view.LayoutInflater"); 73 SYSTEM_SERVICE_MAP.put(Context.ACTIVITY_SERVICE, "android.app.ActivityManager"); 74 SYSTEM_SERVICE_MAP.put(Context.POWER_SERVICE, "android.os.PowerManager"); 75 SYSTEM_SERVICE_MAP.put(Context.ALARM_SERVICE, "android.app.AlarmManager"); 76 SYSTEM_SERVICE_MAP.put(Context.NOTIFICATION_SERVICE, "android.app.NotificationManager"); 77 SYSTEM_SERVICE_MAP.put(Context.KEYGUARD_SERVICE, "android.app.KeyguardManager"); 78 SYSTEM_SERVICE_MAP.put(Context.LOCATION_SERVICE, "android.location.LocationManager"); 79 SYSTEM_SERVICE_MAP.put(Context.SEARCH_SERVICE, "android.app.SearchManager"); 80 SYSTEM_SERVICE_MAP.put(Context.STORAGE_SERVICE, "android.os.storage.StorageManager"); 81 SYSTEM_SERVICE_MAP.put(Context.CONNECTIVITY_SERVICE, "android.net.ConnectivityManager"); 82 SYSTEM_SERVICE_MAP.put(Context.WIFI_SERVICE, "android.net.wifi.WifiManager"); 83 SYSTEM_SERVICE_MAP.put(Context.AUDIO_SERVICE, "android.media.AudioManager"); 84 SYSTEM_SERVICE_MAP.put(Context.TELEPHONY_SERVICE, "android.telephony.TelephonyManager"); 85 SYSTEM_SERVICE_MAP.put(Context.INPUT_METHOD_SERVICE, "android.view.inputmethod.InputMethodManager"); 86 SYSTEM_SERVICE_MAP.put(Context.UI_MODE_SERVICE, "android.app.UiModeManager"); 87 SYSTEM_SERVICE_MAP.put(Context.DOWNLOAD_SERVICE, "android.app.DownloadManager"); 88 SYSTEM_SERVICE_MAP.put(Context.TEXT_SERVICES_MANAGER_SERVICE, "android.view.textservice.TextServicesManager"); 89 SYSTEM_SERVICE_MAP.put(Context.DEVICE_POLICY_SERVICE, "android.app.admin.DevicePolicyManager"); 90 SYSTEM_SERVICE_MAP.put(Context.DROPBOX_SERVICE, "android.os.DropBoxManager"); 91 SYSTEM_SERVICE_MAP.put(Context.MEDIA_ROUTER_SERVICE, "android.media.MediaRouter"); 92 SYSTEM_SERVICE_MAP.put(Context.ACCESSIBILITY_SERVICE, "android.view.accessibility.AccessibilityManager"); 93 SYSTEM_SERVICE_MAP.put(Context.ACCOUNT_SERVICE, "android.accounts.AccountManager"); 94 SYSTEM_SERVICE_MAP.put(Context.NFC_SERVICE, "android.nfc.NfcManager"); 95 SYSTEM_SERVICE_MAP.put(Context.WALLPAPER_SERVICE, "android.app.WallpaperManager"); 96 SYSTEM_SERVICE_MAP.put(Context.WIFI_P2P_SERVICE, "android.net.wifi.p2p.WifiP2pManager"); 97 SYSTEM_SERVICE_MAP.put(Context.USB_SERVICE, "android.hardware.usb.UsbManager"); 98 SYSTEM_SERVICE_MAP.put(Context.AUTOFILL_MANAGER_SERVICE, "android.view.autofill.AutofillManager"); 99 SYSTEM_SERVICE_MAP.put(Context.TEXT_CLASSIFICATION_SERVICE, "android.view.textclassifier.TextClassificationManager"); 100 101 if (getApiLevel() >= JELLY_BEAN_MR1) { 102 SYSTEM_SERVICE_MAP.put(Context.DISPLAY_SERVICE, "android.hardware.display.DisplayManager"); 103 SYSTEM_SERVICE_MAP.put(Context.USER_SERVICE, "android.os.UserManager"); 104 } 105 if (getApiLevel() >= JELLY_BEAN_MR2) { 106 SYSTEM_SERVICE_MAP.put(Context.BLUETOOTH_SERVICE, "android.bluetooth.BluetoothManager"); 107 } 108 if (getApiLevel() >= KITKAT) { 109 SYSTEM_SERVICE_MAP.put(Context.PRINT_SERVICE, "android.print.PrintManager"); 110 SYSTEM_SERVICE_MAP.put(Context.APP_OPS_SERVICE, "android.app.AppOpsManager"); 111 SYSTEM_SERVICE_MAP.put(Context.CAPTIONING_SERVICE, "android.view.accessibility.CaptioningManager"); 112 } 113 if (getApiLevel() >= LOLLIPOP) { 114 SYSTEM_SERVICE_MAP.put(Context.JOB_SCHEDULER_SERVICE, "android.app.JobSchedulerImpl"); 115 SYSTEM_SERVICE_MAP.put(Context.NETWORK_SCORE_SERVICE, "android.net.NetworkScoreManager"); 116 SYSTEM_SERVICE_MAP.put(Context.TELECOM_SERVICE, "android.telecom.TelecomManager"); 117 SYSTEM_SERVICE_MAP.put(Context.MEDIA_SESSION_SERVICE, "android.media.session.MediaSessionManager"); 118 SYSTEM_SERVICE_MAP.put(Context.BATTERY_SERVICE, "android.os.BatteryManager"); 119 SYSTEM_SERVICE_MAP.put(Context.RESTRICTIONS_SERVICE, "android.content.RestrictionsManager"); 120 } 121 if (getApiLevel() >= LOLLIPOP_MR1) { 122 SYSTEM_SERVICE_MAP.put(Context.TELEPHONY_SUBSCRIPTION_SERVICE, "android.telephony.SubscriptionManager"); 123 } 124 if (getApiLevel() >= M) { 125 SYSTEM_SERVICE_MAP.put(Context.FINGERPRINT_SERVICE, "android.hardware.fingerprint.FingerprintManager"); 126 } 127 if (getApiLevel() >= N_MR1) { 128 SYSTEM_SERVICE_MAP.put(Context.SHORTCUT_SERVICE, "android.content.pm.ShortcutManager"); 129 } 130 131 if (getApiLevel() >= M) { 132 SYSTEM_SERVICE_MAP.put(Context.LAYOUT_INFLATER_SERVICE, "com.android.internal.policy.PhoneLayoutInflater"); 133 } else { 134 SYSTEM_SERVICE_MAP.put(Context.LAYOUT_INFLATER_SERVICE, "com.android.internal.policy.impl.PhoneLayoutInflater"); 135 } 136 } 137 138 private Map<String, Object> systemServices = new HashMap<String, Object>(); 139 140 @Implementation 141 public Object getSystemService(String name) { 142 if (name.equals(Context.LAYOUT_INFLATER_SERVICE)) { 143 return new RoboLayoutInflater(RuntimeEnvironment.application); 144 } 145 146 Object service = systemServices.get(name); 147 if (service == null) { 148 String serviceClassName = SYSTEM_SERVICE_MAP.get(name); 149 if (serviceClassName == null) { 150 System.err.println("WARNING: unknown service " + name); 151 return null; 152 } 153 154 try { 155 Class<?> clazz = Class.forName(serviceClassName); 156 157 if (serviceClassName.equals("android.content.RestrictionsManager")) { 158 service = ReflectionHelpers.callConstructor(clazz, 159 ClassParameter.from(Context.class, RuntimeEnvironment.application), 160 ClassParameter.from(IRestrictionsManager.class, null)); 161 } else if (serviceClassName.equals("android.app.admin.DevicePolicyManager")) { 162 if (getApiLevel() >= N) { 163 service = ReflectionHelpers.callConstructor(clazz, 164 ClassParameter.from(Context.class, RuntimeEnvironment.application), 165 ClassParameter.from(IDevicePolicyManager.class, null), 166 ClassParameter.from(boolean.class, false)); 167 } else { 168 service = ReflectionHelpers.callConstructor(clazz, 169 ClassParameter.from(Context.class, RuntimeEnvironment.application), 170 ClassParameter.from(Handler.class, null)); 171 } 172 } else if (serviceClassName.equals("android.app.SearchManager") 173 || serviceClassName.equals("android.app.ActivityManager")) { 174 175 service = ReflectionHelpers.callConstructor(clazz, 176 ClassParameter.from(Context.class, RuntimeEnvironment.application), 177 ClassParameter.from(Handler.class, null)); 178 } else if (serviceClassName.equals("android.app.WallpaperManager")) { 179 if (getApiLevel() <= O_MR1) { 180 service = ReflectionHelpers.callConstructor(clazz, 181 ClassParameter.from(Context.class, RuntimeEnvironment.application), 182 ClassParameter.from(Handler.class, null)); 183 } 184 // BEGIN-INTERNAL 185 else { 186 service = ReflectionHelpers.callConstructor(clazz, 187 ClassParameter.from(IWallpaperManager.class, null), 188 ClassParameter.from(Context.class, RuntimeEnvironment.application), 189 ClassParameter.from(Handler.class, null)); 190 } 191 // END-INTERNAL 192 } else if (serviceClassName.equals("android.os.storage.StorageManager")) { 193 service = ReflectionHelpers.callConstructor(clazz); 194 } else if (serviceClassName.equals("android.nfc.NfcManager") || serviceClassName.equals("android.telecom.TelecomManager")) { 195 service = ReflectionHelpers.callConstructor(clazz, 196 ClassParameter.from(Context.class, RuntimeEnvironment.application)); 197 } else if (serviceClassName.equals("android.hardware.display.DisplayManager") || serviceClassName.equals("android.telephony.SubscriptionManager")) { 198 service = ReflectionHelpers.callConstructor(clazz, ClassParameter.from(Context.class, RuntimeEnvironment.application)); 199 } else if (serviceClassName.equals("android.view.accessibility.AccessibilityManager")) { 200 service = AccessibilityManager.getInstance(realObject); 201 } else if (getApiLevel() >= JELLY_BEAN_MR1 && serviceClassName.equals("android.view.WindowManagerImpl")) { 202 Class<?> windowMgrImplClass = Class.forName("android.view.WindowManagerImpl"); 203 if (getApiLevel() >= N) { 204 service = ReflectionHelpers.callConstructor(windowMgrImplClass, 205 ClassParameter.from(Context.class, realObject)); 206 } else { 207 Display display = ShadowDisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 208 service = ReflectionHelpers.callConstructor(windowMgrImplClass, 209 ClassParameter.from(Display.class, display)); 210 } 211 } else if (serviceClassName.equals("android.accounts.AccountManager")) { 212 service = ReflectionHelpers.callConstructor(Class.forName("android.accounts.AccountManager"), 213 ClassParameter.from(Context.class, RuntimeEnvironment.application), 214 ClassParameter.from(IAccountManager.class , null)); 215 } else if (serviceClassName.equals("android.net.wifi.p2p.WifiP2pManager")) { 216 service = new WifiP2pManager(ReflectionHelpers.createNullProxy(IWifiP2pManager.class)); 217 } else if (getApiLevel() >= KITKAT && serviceClassName.equals("android.print.PrintManager")) { 218 service = ReflectionHelpers.callConstructor(Class.forName("android.print.PrintManager"), 219 ClassParameter.from(Context.class, RuntimeEnvironment.application), 220 ClassParameter.from(android.print.IPrintManager.class, null), 221 ClassParameter.from(int.class, -1), 222 ClassParameter.from(int.class, -1)); 223 } else if (serviceClassName.equals("android.hardware.SystemSensorManager")) { 224 if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR2) { 225 service = new SystemSensorManager(RuntimeEnvironment.application, Looper.getMainLooper()); 226 } else { 227 service = ReflectionHelpers.callConstructor( 228 Class.forName(serviceClassName), 229 ClassParameter.from(Looper.class, Looper.getMainLooper())); 230 } 231 } else if (getApiLevel() >= O && serviceClassName.equals("android.app.KeyguardManager")) { 232 service = 233 ReflectionHelpers.callConstructor( 234 clazz, ClassParameter.from(Context.class, RuntimeEnvironment.application)); 235 } else if (getApiLevel() >= KITKAT && serviceClassName.equals("android.view.accessibility.CaptioningManager")) { 236 service = ReflectionHelpers.callConstructor(clazz, 237 ClassParameter.from(Context.class, RuntimeEnvironment.application)); 238 } else if (serviceClassName.equals("android.os.UserManager")) { 239 service = ReflectionHelpers.callConstructor(clazz, 240 ClassParameter.from(Context.class, RuntimeEnvironment.application), 241 ClassParameter.from(IUserManager.class, null)); 242 } else if (getApiLevel() >= M && serviceClassName.equals("android.hardware.fingerprint.FingerprintManager")) { 243 service = ReflectionHelpers.callConstructor(clazz, 244 ClassParameter.from(Context.class, RuntimeEnvironment.application), 245 ClassParameter.from(IFingerprintService.class, null)); 246 } else if (getApiLevel() >= O && serviceClassName.equals("android.view.autofill.AutofillManager")) { 247 service = ReflectionHelpers.callConstructor(clazz, 248 ClassParameter.from(Context.class, RuntimeEnvironment.application), 249 ClassParameter.from(IAutoFillManager.class, null)); 250 } else if (getApiLevel() >= O && serviceClassName.equals("android.view.textclassifier.TextClassificationManager")) { 251 service = ReflectionHelpers.callConstructor(clazz, 252 ClassParameter.from(Context.class, RuntimeEnvironment.application)); 253 } else if (serviceClassName.equals("com.android.internal.policy.impl.PhoneLayoutInflater") || serviceClassName.equals("com.android.internal.policy.PhoneLayoutInflater")) { 254 service = ReflectionHelpers.callConstructor(clazz, 255 ClassParameter.from(Context.class, RuntimeEnvironment.application)); 256 } else { 257 service = newInstanceOf(clazz); 258 } 259 } catch (ClassNotFoundException e) { 260 throw new RuntimeException(e); 261 } 262 263 systemServices.put(name, service); 264 } 265 return service; 266 } 267 268 public void setSystemService(String key, Object service) { 269 systemServices.put(key, service); 270 } 271 272 @Implementation 273 public void startIntentSender(IntentSender intent, Intent fillInIntent, 274 int flagsMask, int flagsValues, int extraFlags, Bundle options) throws IntentSender.SendIntentException { 275 intent.sendIntent(realObject, 0, fillInIntent, null, null, null); 276 } 277 278 @Implementation 279 public ComponentName startService(Intent service) { 280 return ShadowApplication.getInstance().startService(service); 281 } 282 283 @Implementation(minSdk = O) 284 public ComponentName startForegroundService(Intent service) { 285 return ShadowApplication.getInstance().startService(service); 286 } 287 288 @Implementation 289 public void startActivity(Intent intent) { 290 ShadowApplication.getInstance().startActivity(intent); 291 } 292 293 @Implementation 294 public void sendBroadcast(Intent intent) { 295 ShadowApplication.getInstance().sendBroadcast(intent); 296 } 297 298 @Implementation 299 public ClassLoader getClassLoader() { 300 return this.getClass().getClassLoader(); 301 } 302 303 @Implementation 304 public boolean bindService(Intent intent, final ServiceConnection serviceConnection, int i) { 305 return ShadowApplication.getInstance().bindService(intent, serviceConnection, i); 306 } 307 308 @Implementation 309 public void unbindService(final ServiceConnection serviceConnection) { 310 ShadowApplication.getInstance().unbindService(serviceConnection); 311 } 312 313 @Implementation 314 public int checkCallingPermission(String permission) { 315 return checkPermission(permission, -1, -1); 316 } 317 318 @Implementation 319 public int checkCallingOrSelfPermission(String permission) { 320 return checkPermission(permission, -1, -1); 321 } 322 323 @Implementation 324 public ContentResolver getContentResolver() { 325 if (contentResolver == null) { 326 contentResolver = new ContentResolver(realObject) { 327 @Override 328 protected IContentProvider acquireProvider(Context c, String name) { 329 return null; 330 } 331 332 @Override 333 public boolean releaseProvider(IContentProvider icp) { 334 return false; 335 } 336 337 @Override 338 protected IContentProvider acquireUnstableProvider(Context c, String name) { 339 return null; 340 } 341 342 @Override 343 public boolean releaseUnstableProvider(IContentProvider icp) { 344 return false; 345 } 346 347 @Override 348 public void unstableProviderDied(IContentProvider icp) { 349 350 } 351 }; 352 } 353 return contentResolver; 354 } 355 356 @Implementation 357 public void sendBroadcast(Intent intent, String receiverPermission) { 358 ShadowApplication.getInstance().sendBroadcast(intent, receiverPermission); 359 } 360 361 @Implementation 362 public void sendOrderedBroadcast(Intent intent, String receiverPermission) { 363 ShadowApplication.getInstance().sendOrderedBroadcast(intent, receiverPermission); 364 } 365 366 @Implementation 367 public void sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, 368 Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { 369 ShadowApplication.getInstance().sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, 370 initialData, initialExtras); 371 } 372 373 @Implementation 374 public void sendStickyBroadcast(Intent intent) { 375 ShadowApplication.getInstance().sendStickyBroadcast(intent); 376 } 377 378 @Implementation 379 public int checkPermission(String permission, int pid, int uid) { 380 return ShadowApplication.getInstance().checkPermission(permission, pid, uid); 381 } 382 383 @Implementation 384 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 385 return ShadowApplication.getInstance().registerReceiverWithContext(receiver, filter, null, null, realObject); 386 } 387 388 @Implementation 389 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { 390 return ShadowApplication.getInstance().registerReceiverWithContext(receiver, filter, broadcastPermission, scheduler, realObject); 391 } 392 393 @Implementation 394 public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, 395 IntentFilter filter, String broadcastPermission, Handler scheduler) { 396 return ShadowApplication.getInstance().registerReceiverWithContext(receiver, filter, broadcastPermission, scheduler, realObject); 397 } 398 399 @Implementation 400 public void unregisterReceiver(BroadcastReceiver broadcastReceiver) { 401 ShadowApplication.getInstance().unregisterReceiver(broadcastReceiver); 402 } 403 404 @Implementation 405 public boolean stopService(Intent name) { 406 return ShadowApplication.getInstance().stopService(name); 407 } 408 409 @Implementation 410 public void startActivity(Intent intent, Bundle options) { 411 ShadowApplication.getInstance().startActivity(intent, options); 412 } 413 414 @Implementation 415 public void startActivities(Intent[] intents) { 416 for (int i = intents.length - 1; i >= 0; i--) { 417 startActivity(intents[i]); 418 } 419 } 420 421 @Implementation 422 public void startActivities(Intent[] intents, Bundle options) { 423 for (int i = intents.length - 1; i >= 0; i--) { 424 startActivity(intents[i], options); 425 } 426 } 427 428 @Implementation 429 public int getUserId() { 430 return 0; 431 } 432 433 @Implementation 434 public File getExternalCacheDir() { 435 return Environment.getExternalStorageDirectory(); 436 } 437 438 @Implementation(maxSdk = JELLY_BEAN_MR2) 439 public File getExternalFilesDir(String type) { 440 return Environment.getExternalStoragePublicDirectory(type); 441 } 442 443 @Implementation(minSdk = KITKAT) 444 public File[] getExternalFilesDirs(String type) { 445 return new File[] { Environment.getExternalStoragePublicDirectory(type) }; 446 } 447 448 @Resetter 449 public static void reset() { 450 String prefsCacheFieldName = RuntimeEnvironment.getApiLevel() >= N ? "sSharedPrefsCache" : "sSharedPrefs"; 451 Object prefsDefaultValue = RuntimeEnvironment.getApiLevel() >= KITKAT ? null : new HashMap<>(); 452 Class<?> contextImplClass = ReflectionHelpers.loadClass(ShadowContextImpl.class.getClassLoader(), "android.app.ContextImpl"); 453 ReflectionHelpers.setStaticField(contextImplClass, prefsCacheFieldName, prefsDefaultValue); 454 } 455} 456