Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import static android.os.Build.VERSION_CODES.KITKAT;
      4 import static org.robolectric.RuntimeEnvironment.getApiLevel;
      5 
      6 import android.accessibilityservice.AccessibilityServiceInfo;
      7 import android.content.Context;
      8 import android.content.pm.ServiceInfo;
      9 import android.os.Handler;
     10 import android.os.Looper;
     11 import android.os.Message;
     12 import android.util.Log;
     13 import android.view.accessibility.AccessibilityManager;
     14 import android.view.accessibility.IAccessibilityManager;
     15 import java.util.List;
     16 import org.robolectric.annotation.HiddenApi;
     17 import org.robolectric.annotation.Implementation;
     18 import org.robolectric.annotation.Implements;
     19 import org.robolectric.annotation.RealObject;
     20 import org.robolectric.annotation.Resetter;
     21 import org.robolectric.shadow.api.Shadow;
     22 import org.robolectric.util.ReflectionHelpers;
     23 import org.robolectric.util.ReflectionHelpers.ClassParameter;
     24 
     25 @Implements(AccessibilityManager.class)
     26 public class ShadowAccessibilityManager {
     27   private static AccessibilityManager sInstance;
     28   private static final Object sInstanceSync = new Object();
     29 
     30   @RealObject AccessibilityManager realAccessibilityManager;
     31   private boolean enabled;
     32   private List<AccessibilityServiceInfo> installedAccessibilityServiceList;
     33   private List<AccessibilityServiceInfo> enabledAccessibilityServiceList;
     34   private List<ServiceInfo> accessibilityServiceList;
     35   private boolean touchExplorationEnabled;
     36 
     37   @Resetter
     38   public static void reset() {
     39     synchronized (sInstanceSync) {
     40       sInstance = null;
     41     }
     42   }
     43 
     44   @HiddenApi
     45   @Implementation
     46   public static AccessibilityManager getInstance(Context context) throws Exception {
     47     synchronized (sInstanceSync) {
     48       if (sInstance == null) {
     49           sInstance = createInstance(context);
     50       }
     51     }
     52     return sInstance;
     53   }
     54 
     55   private static AccessibilityManager createInstance(Context context) throws Exception {
     56     if (getApiLevel() >= KITKAT) {
     57       AccessibilityManager accessibilityManager = Shadow.newInstance(AccessibilityManager.class,
     58           new Class[]{Context.class, IAccessibilityManager.class, int.class},
     59           new Object[]{context, ReflectionHelpers.createNullProxy(IAccessibilityManager.class), 0});
     60       ReflectionHelpers.setField(accessibilityManager, "mHandler", new MyHandler(context.getMainLooper(), accessibilityManager));
     61       return accessibilityManager;
     62     } else {
     63       AccessibilityManager accessibilityManager = Shadow.newInstance(AccessibilityManager.class, new Class[0], new Object[0]);
     64       ReflectionHelpers.setField(accessibilityManager, "mHandler", new MyHandler(context.getMainLooper(), accessibilityManager));
     65       return accessibilityManager;
     66     }
     67   }
     68 
     69   @Implementation
     70   public boolean addAccessibilityStateChangeListener(AccessibilityManager.AccessibilityStateChangeListener listener) {
     71     return true;
     72   }
     73 
     74   @Implementation
     75   public boolean removeAccessibilityStateChangeListener(AccessibilityManager.AccessibilityStateChangeListener listener) {
     76     return true;
     77   }
     78 
     79   @Implementation
     80   public List<ServiceInfo> getAccessibilityServiceList () {
     81     return accessibilityServiceList;
     82   }
     83 
     84   public void setAccessibilityServiceList(List<ServiceInfo> accessibilityServiceList) {
     85     this.accessibilityServiceList = accessibilityServiceList;
     86   }
     87 
     88   @Implementation
     89   public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList (int feedbackTypeFlags) {
     90     return enabledAccessibilityServiceList;
     91   }
     92 
     93   public void setEnabledAccessibilityServiceList(List<AccessibilityServiceInfo> enabledAccessibilityServiceList) {
     94     this.enabledAccessibilityServiceList = enabledAccessibilityServiceList;
     95   }
     96 
     97   @Implementation
     98   public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList () {
     99     return installedAccessibilityServiceList;
    100   }
    101 
    102   public void setInstalledAccessibilityServiceList(List<AccessibilityServiceInfo> installedAccessibilityServiceList) {
    103     this.installedAccessibilityServiceList = installedAccessibilityServiceList;
    104   }
    105 
    106   @Implementation
    107   public boolean isEnabled () {
    108     return enabled;
    109   }
    110 
    111   public void setEnabled(boolean enabled) {
    112     this.enabled = enabled;
    113     ReflectionHelpers.setField(realAccessibilityManager, "mIsEnabled", enabled);
    114   }
    115 
    116   @Implementation
    117   public boolean isTouchExplorationEnabled () {
    118     return touchExplorationEnabled;
    119   }
    120 
    121   public void setTouchExplorationEnabled(boolean touchExplorationEnabled) {
    122     this.touchExplorationEnabled = touchExplorationEnabled;
    123   }
    124 
    125   static class MyHandler extends Handler {
    126     private static final int DO_SET_STATE = 10;
    127     private final AccessibilityManager accessibilityManager;
    128 
    129     MyHandler(Looper mainLooper, AccessibilityManager accessibilityManager) {
    130       super(mainLooper);
    131       this.accessibilityManager = accessibilityManager;
    132     }
    133 
    134     @Override
    135     public void handleMessage(Message message) {
    136       switch (message.what) {
    137         case DO_SET_STATE:
    138           ReflectionHelpers.callInstanceMethod(accessibilityManager, "setState", ClassParameter.from(int.class, message.arg1));
    139           return;
    140         default:
    141           Log.w("AccessibilityManager", "Unknown message type: " + message.what);
    142       }
    143     }
    144   }
    145 }
    146