AccessibilityManager.java revision 3fb3d7c4e756bd32d5abde0abca9ab52d559bc84
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.view.accessibility; 18 19import android.content.Context; 20import android.content.pm.ServiceInfo; 21import android.os.Binder; 22import android.os.Handler; 23import android.os.IBinder; 24import android.os.Looper; 25import android.os.Message; 26import android.os.RemoteException; 27import android.os.ServiceManager; 28import android.os.SystemClock; 29import android.util.Log; 30 31import java.util.Collections; 32import java.util.List; 33 34/** 35 * System level service that serves as an event dispatch for {@link AccessibilityEvent}s. 36 * Such events are generated when something notable happens in the user interface, 37 * for example an {@link android.app.Activity} starts, the focus or selection of a 38 * {@link android.view.View} changes etc. Parties interested in handling accessibility 39 * events implement and register an accessibility service which extends 40 * {@link android.accessibilityservice.AccessibilityService}. 41 * 42 * @see AccessibilityEvent 43 * @see android.accessibilityservice.AccessibilityService 44 * @see android.content.Context#getSystemService 45 */ 46public final class AccessibilityManager { 47 private static final String LOG_TAG = "AccessibilityManager"; 48 49 static final Object sInstanceSync = new Object(); 50 51 private static AccessibilityManager sInstance; 52 53 private static final int DO_SET_ENABLED = 10; 54 55 final IAccessibilityManager mService; 56 57 final Handler mHandler; 58 59 boolean mIsEnabled; 60 61 final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() { 62 public void setEnabled(boolean enabled) { 63 mHandler.obtainMessage(DO_SET_ENABLED, enabled ? 1 : 0, 0).sendToTarget(); 64 } 65 }; 66 67 class MyHandler extends Handler { 68 69 MyHandler(Looper mainLooper) { 70 super(mainLooper); 71 } 72 73 @Override 74 public void handleMessage(Message message) { 75 switch (message.what) { 76 case DO_SET_ENABLED : 77 synchronized (mHandler) { 78 mIsEnabled = (message.arg1 == 1); 79 } 80 return; 81 default : 82 Log.w(LOG_TAG, "Unknown message type: " + message.what); 83 } 84 } 85 } 86 87 /** 88 * Get an AccessibilityManager instance (create one if necessary). 89 * 90 * @hide 91 */ 92 public static AccessibilityManager getInstance(Context context) { 93 synchronized (sInstanceSync) { 94 if (sInstance == null) { 95 IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE); 96 IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder); 97 sInstance = new AccessibilityManager(context, service); 98 } 99 } 100 return sInstance; 101 } 102 103 /** 104 * Create an instance. 105 * 106 * @param context A {@link Context}. 107 * @param service An interface to the backing service. 108 * 109 * @hide 110 */ 111 public AccessibilityManager(Context context, IAccessibilityManager service) { 112 mHandler = new MyHandler(context.getMainLooper()); 113 mService = service; 114 115 try { 116 mIsEnabled = mService.addClient(mClient); 117 } catch (RemoteException re) { 118 Log.e(LOG_TAG, "AccessibilityManagerService is dead", re); 119 } 120 } 121 122 /** 123 * Returns if the {@link AccessibilityManager} is enabled. 124 * 125 * @return True if this {@link AccessibilityManager} is enabled, false otherwise. 126 */ 127 public boolean isEnabled() { 128 synchronized (mHandler) { 129 return mIsEnabled; 130 } 131 } 132 133 /** 134 * Returns the client interface this instance registers in 135 * the centralized accessibility manager service. 136 * 137 * @return The client. 138 * 139 * @hide 140 */ 141 public IAccessibilityManagerClient getClient() { 142 return (IAccessibilityManagerClient) mClient.asBinder(); 143 } 144 145 /** 146 * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not 147 * enabled the call is a NOOP. 148 * 149 * @param event The {@link AccessibilityEvent}. 150 * 151 * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent} 152 * while accessibility is not enabled. 153 */ 154 public void sendAccessibilityEvent(AccessibilityEvent event) { 155 if (!mIsEnabled) { 156 throw new IllegalStateException("Accessibility off. Did you forget to check that?"); 157 } 158 boolean doRecycle = false; 159 try { 160 event.setEventTime(SystemClock.uptimeMillis()); 161 // it is possible that this manager is in the same process as the service but 162 // client using it is called through Binder from another process. Example: MMS 163 // app adds a SMS notification and the NotificationManagerService calls this method 164 long identityToken = Binder.clearCallingIdentity(); 165 doRecycle = mService.sendAccessibilityEvent(event); 166 Binder.restoreCallingIdentity(identityToken); 167 if (false) { 168 Log.i(LOG_TAG, event + " sent"); 169 } 170 } catch (RemoteException re) { 171 Log.e(LOG_TAG, "Error during sending " + event + " ", re); 172 } finally { 173 if (doRecycle) { 174 event.recycle(); 175 } 176 } 177 } 178 179 /** 180 * Requests interruption of the accessibility feedback from all accessibility services. 181 */ 182 public void interrupt() { 183 if (!mIsEnabled) { 184 throw new IllegalStateException("Accessibility off. Did you forget to check that?"); 185 } 186 try { 187 mService.interrupt(); 188 if (false) { 189 Log.i(LOG_TAG, "Requested interrupt from all services"); 190 } 191 } catch (RemoteException re) { 192 Log.e(LOG_TAG, "Error while requesting interrupt from all services. ", re); 193 } 194 } 195 196 /** 197 * Returns the {@link ServiceInfo}s of the installed accessibility services. 198 * 199 * @return An unmodifiable list with {@link ServiceInfo}s. 200 */ 201 public List<ServiceInfo> getAccessibilityServiceList() { 202 List<ServiceInfo> services = null; 203 try { 204 services = mService.getAccessibilityServiceList(); 205 if (false) { 206 Log.i(LOG_TAG, "Installed AccessibilityServices " + services); 207 } 208 } catch (RemoteException re) { 209 Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re); 210 } 211 return Collections.unmodifiableList(services); 212 } 213} 214