Home | History | Annotate | Download | only in shadows
      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