AccessibilityManagerService.java revision 1f22b6a25d7df6c5488d9bd01793e7a20d921349
1/* 2 ** Copyright 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 com.android.server.accessibility; 18 19import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; 20import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 21 22import android.Manifest; 23import android.accessibilityservice.AccessibilityService; 24import android.accessibilityservice.AccessibilityServiceInfo; 25import android.accessibilityservice.IAccessibilityServiceClient; 26import android.accessibilityservice.IAccessibilityServiceConnection; 27import android.app.AlertDialog; 28import android.app.PendingIntent; 29import android.app.StatusBarManager; 30import android.content.BroadcastReceiver; 31import android.content.ComponentName; 32import android.content.ContentResolver; 33import android.content.Context; 34import android.content.DialogInterface; 35import android.content.DialogInterface.OnClickListener; 36import android.content.Intent; 37import android.content.IntentFilter; 38import android.content.ServiceConnection; 39import android.content.pm.PackageManager; 40import android.content.pm.ResolveInfo; 41import android.content.pm.ServiceInfo; 42import android.database.ContentObserver; 43import android.graphics.Rect; 44import android.hardware.input.InputManager; 45import android.net.Uri; 46import android.os.Binder; 47import android.os.Build; 48import android.os.Bundle; 49import android.os.Handler; 50import android.os.IBinder; 51import android.os.Looper; 52import android.os.Message; 53import android.os.Process; 54import android.os.RemoteCallbackList; 55import android.os.RemoteException; 56import android.os.ServiceManager; 57import android.os.SystemClock; 58import android.os.UserHandle; 59import android.os.UserManager; 60import android.provider.Settings; 61import android.text.TextUtils; 62import android.text.TextUtils.SimpleStringSplitter; 63import android.util.Slog; 64import android.util.SparseArray; 65import android.view.IWindow; 66import android.view.IWindowManager; 67import android.view.InputDevice; 68import android.view.KeyCharacterMap; 69import android.view.KeyEvent; 70import android.view.WindowInfo; 71import android.view.WindowManager; 72import android.view.accessibility.AccessibilityEvent; 73import android.view.accessibility.AccessibilityInteractionClient; 74import android.view.accessibility.AccessibilityManager; 75import android.view.accessibility.AccessibilityNodeInfo; 76import android.view.accessibility.IAccessibilityInteractionConnection; 77import android.view.accessibility.IAccessibilityInteractionConnectionCallback; 78import android.view.accessibility.IAccessibilityManager; 79import android.view.accessibility.IAccessibilityManagerClient; 80 81import com.android.internal.R; 82import com.android.internal.content.PackageMonitor; 83import com.android.internal.statusbar.IStatusBarService; 84 85import org.xmlpull.v1.XmlPullParserException; 86 87import java.io.IOException; 88import java.util.ArrayList; 89import java.util.Arrays; 90import java.util.HashMap; 91import java.util.HashSet; 92import java.util.Iterator; 93import java.util.List; 94import java.util.Map; 95import java.util.Set; 96import java.util.concurrent.CopyOnWriteArrayList; 97 98/** 99 * This class is instantiated by the system as a system level service and can be 100 * accessed only by the system. The task of this service is to be a centralized 101 * event dispatch for {@link AccessibilityEvent}s generated across all processes 102 * on the device. Events are dispatched to {@link AccessibilityService}s. 103 * 104 * @hide 105 */ 106public class AccessibilityManagerService extends IAccessibilityManager.Stub { 107 108 private static final boolean DEBUG = false; 109 110 private static final String LOG_TAG = "AccessibilityManagerService"; 111 112 // TODO: This is arbitrary. When there is time implement this by watching 113 // when that accessibility services are bound. 114 private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 5000; 115 116 private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE = 117 "registerUiTestAutomationService"; 118 119 private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED = 120 "temporaryEnableAccessibilityStateUntilKeyguardRemoved"; 121 122 private static final char COMPONENT_NAME_SEPARATOR = ':'; 123 124 private static final int OWN_PROCESS_ID = android.os.Process.myPid(); 125 126 private static int sIdCounter = 0; 127 128 private static int sNextWindowId; 129 130 private final Context mContext; 131 132 private final Object mLock = new Object(); 133 134 private final SimpleStringSplitter mStringColonSplitter = 135 new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); 136 137 private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = 138 new ArrayList<AccessibilityServiceInfo>(); 139 140 private final PackageManager mPackageManager; 141 142 private final IWindowManager mWindowManagerService; 143 144 private final SecurityPolicy mSecurityPolicy; 145 146 private final MainHandler mMainHandler; 147 148 private Service mUiAutomationService; 149 150 private Service mQueryBridge; 151 152 private AlertDialog mEnableTouchExplorationDialog; 153 154 private AccessibilityInputFilter mInputFilter; 155 156 private boolean mHasInputFilter; 157 158 private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients = 159 new RemoteCallbackList<IAccessibilityManagerClient>(); 160 161 private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections = 162 new SparseArray<AccessibilityConnectionWrapper>(); 163 164 private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<IBinder>(); 165 166 private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 167 168 private final TempUserStateChangeMemento mTempStateChangeForCurrentUserMemento = 169 new TempUserStateChangeMemento(); 170 171 private int mCurrentUserId = UserHandle.USER_OWNER; 172 173 private UserState getCurrentUserStateLocked() { 174 return getUserStateLocked(mCurrentUserId); 175 } 176 177 private UserState getUserStateLocked(int userId) { 178 UserState state = mUserStates.get(userId); 179 if (state == null) { 180 state = new UserState(userId); 181 mUserStates.put(userId, state); 182 } 183 return state; 184 } 185 186 /** 187 * Creates a new instance. 188 * 189 * @param context A {@link Context} instance. 190 */ 191 public AccessibilityManagerService(Context context) { 192 mContext = context; 193 mPackageManager = mContext.getPackageManager(); 194 mWindowManagerService = (IWindowManager) ServiceManager.getService(Context.WINDOW_SERVICE); 195 mSecurityPolicy = new SecurityPolicy(); 196 mMainHandler = new MainHandler(mContext.getMainLooper()); 197 registerBroadcastReceivers(); 198 new AccessibilityContentObserver(mMainHandler).register( 199 context.getContentResolver()); 200 } 201 202 private void registerBroadcastReceivers() { 203 PackageMonitor monitor = new PackageMonitor() { 204 @Override 205 public void onSomePackagesChanged() { 206 synchronized (mLock) { 207 if (getChangingUserId() != mCurrentUserId) { 208 return; 209 } 210 // We will update when the automation service dies. 211 if (mUiAutomationService == null) { 212 UserState userState = getCurrentUserStateLocked(); 213 populateInstalledAccessibilityServiceLocked(userState); 214 manageServicesLocked(userState); 215 } 216 } 217 } 218 219 @Override 220 public void onPackageRemoved(String packageName, int uid) { 221 synchronized (mLock) { 222 final int userId = getChangingUserId(); 223 if (userId != mCurrentUserId) { 224 return; 225 } 226 UserState state = getUserStateLocked(userId); 227 Iterator<ComponentName> it = state.mEnabledServices.iterator(); 228 while (it.hasNext()) { 229 ComponentName comp = it.next(); 230 String compPkg = comp.getPackageName(); 231 if (compPkg.equals(packageName)) { 232 it.remove(); 233 // Update the enabled services setting. 234 persistComponentNamesToSettingLocked( 235 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 236 state.mEnabledServices, userId); 237 // Update the touch exploration granted services setting. 238 state.mTouchExplorationGrantedServices.remove(comp); 239 persistComponentNamesToSettingLocked( 240 Settings.Secure. 241 TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 242 state.mEnabledServices, userId); 243 return; 244 } 245 } 246 } 247 } 248 249 @Override 250 public boolean onHandleForceStop(Intent intent, String[] packages, 251 int uid, boolean doit) { 252 synchronized (mLock) { 253 final int userId = getChangingUserId(); 254 if (userId != mCurrentUserId) { 255 return false; 256 } 257 UserState state = getUserStateLocked(userId); 258 Iterator<ComponentName> it = state.mEnabledServices.iterator(); 259 while (it.hasNext()) { 260 ComponentName comp = it.next(); 261 String compPkg = comp.getPackageName(); 262 for (String pkg : packages) { 263 if (compPkg.equals(pkg)) { 264 if (!doit) { 265 return true; 266 } 267 it.remove(); 268 persistComponentNamesToSettingLocked( 269 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 270 state.mEnabledServices, userId); 271 } 272 } 273 } 274 return false; 275 } 276 } 277 }; 278 279 // package changes 280 monitor.register(mContext, null, UserHandle.ALL, true); 281 282 // user change and unlock 283 IntentFilter intentFilter = new IntentFilter(); 284 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 285 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 286 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 287 288 mContext.registerReceiverAsUser(new BroadcastReceiver() { 289 @Override 290 public void onReceive(Context context, Intent intent) { 291 String action = intent.getAction(); 292 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 293 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 294 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 295 removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 296 } else if (Intent.ACTION_USER_PRESENT.equals(action)) { 297 restoreStateFromMementoIfNeeded(); 298 } 299 } 300 }, UserHandle.ALL, intentFilter, null, null); 301 } 302 303 public int addClient(IAccessibilityManagerClient client, int userId) { 304 synchronized (mLock) { 305 final int resolvedUserId = mSecurityPolicy 306 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 307 // If the client is from a process that runs across users such as 308 // the system UI or the system we add it to the global state that 309 // is shared across users. 310 UserState userState = getUserStateLocked(resolvedUserId); 311 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 312 mGlobalClients.register(client); 313 if (DEBUG) { 314 Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid()); 315 } 316 return getClientState(userState); 317 } else { 318 userState.mClients.register(client); 319 // If this client is not for the current user we do not 320 // return a state since it is not for the foreground user. 321 // We will send the state to the client on a user switch. 322 if (DEBUG) { 323 Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid() 324 + " and userId:" + mCurrentUserId); 325 } 326 return (resolvedUserId == mCurrentUserId) ? getClientState(userState) : 0; 327 } 328 } 329 } 330 331 public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) { 332 synchronized (mLock) { 333 final int resolvedUserId = mSecurityPolicy 334 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 335 // This method does nothing for a background user. 336 if (resolvedUserId != mCurrentUserId) { 337 return true; // yes, recycle the event 338 } 339 if (mSecurityPolicy.canDispatchAccessibilityEvent(event)) { 340 mSecurityPolicy.updateEventSourceLocked(event); 341 mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_ACTIVE_WINDOW, 342 event.getWindowId(), event.getEventType()).sendToTarget(); 343 notifyAccessibilityServicesDelayedLocked(event, false); 344 notifyAccessibilityServicesDelayedLocked(event, true); 345 } 346 if (mHasInputFilter && mInputFilter != null) { 347 mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER, 348 AccessibilityEvent.obtain(event)).sendToTarget(); 349 } 350 event.recycle(); 351 getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0; 352 } 353 return (OWN_PROCESS_ID != Binder.getCallingPid()); 354 } 355 356 public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) { 357 synchronized (mLock) { 358 final int resolvedUserId = mSecurityPolicy 359 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 360 return getUserStateLocked(resolvedUserId).mInstalledServices; 361 } 362 } 363 364 public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, 365 int userId) { 366 List<AccessibilityServiceInfo> result = null; 367 synchronized (mLock) { 368 final int resolvedUserId = mSecurityPolicy 369 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 370 result = mEnabledServicesForFeedbackTempList; 371 result.clear(); 372 List<Service> services = getUserStateLocked(resolvedUserId).mServices; 373 while (feedbackType != 0) { 374 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType)); 375 feedbackType &= ~feedbackTypeBit; 376 final int serviceCount = services.size(); 377 for (int i = 0; i < serviceCount; i++) { 378 Service service = services.get(i); 379 if ((service.mFeedbackType & feedbackTypeBit) != 0) { 380 result.add(service.mAccessibilityServiceInfo); 381 } 382 } 383 } 384 } 385 return result; 386 } 387 388 public void interrupt(int userId) { 389 CopyOnWriteArrayList<Service> services; 390 synchronized (mLock) { 391 final int resolvedUserId = mSecurityPolicy 392 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 393 // This method does nothing for a background user. 394 if (resolvedUserId != mCurrentUserId) { 395 return; 396 } 397 services = getUserStateLocked(resolvedUserId).mServices; 398 } 399 for (int i = 0, count = services.size(); i < count; i++) { 400 Service service = services.get(i); 401 try { 402 service.mServiceInterface.onInterrupt(); 403 } catch (RemoteException re) { 404 Slog.e(LOG_TAG, "Error during sending interrupt request to " 405 + service.mService, re); 406 } 407 } 408 } 409 410 public int addAccessibilityInteractionConnection(IWindow windowToken, 411 IAccessibilityInteractionConnection connection, int userId) throws RemoteException { 412 synchronized (mLock) { 413 final int resolvedUserId = mSecurityPolicy 414 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 415 final int windowId = sNextWindowId++; 416 // If the window is from a process that runs across users such as 417 // the system UI or the system we add it to the global state that 418 // is shared across users. 419 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 420 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 421 windowId, connection, UserHandle.USER_ALL); 422 wrapper.linkToDeath(); 423 mGlobalInteractionConnections.put(windowId, wrapper); 424 mGlobalWindowTokens.put(windowId, windowToken.asBinder()); 425 if (DEBUG) { 426 Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid() 427 + " with windowId: " + windowId); 428 } 429 } else { 430 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 431 windowId, connection, resolvedUserId); 432 wrapper.linkToDeath(); 433 UserState userState = getUserStateLocked(resolvedUserId); 434 userState.mInteractionConnections.put(windowId, wrapper); 435 userState.mWindowTokens.put(windowId, windowToken.asBinder()); 436 if (DEBUG) { 437 Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid() 438 + " with windowId: " + windowId + " and userId:" + mCurrentUserId); 439 } 440 } 441 if (DEBUG) { 442 Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId); 443 } 444 return windowId; 445 } 446 } 447 448 public void removeAccessibilityInteractionConnection(IWindow window) { 449 synchronized (mLock) { 450 mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( 451 UserHandle.getCallingUserId()); 452 IBinder token = window.asBinder(); 453 final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked( 454 token, mGlobalWindowTokens, mGlobalInteractionConnections); 455 if (removedWindowId >= 0) { 456 if (DEBUG) { 457 Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid() 458 + " with windowId: " + removedWindowId); 459 } 460 return; 461 } 462 final int userCount = mUserStates.size(); 463 for (int i = 0; i < userCount; i++) { 464 UserState userState = mUserStates.valueAt(i); 465 final int removedWindowIdForUser = 466 removeAccessibilityInteractionConnectionInternalLocked( 467 token, userState.mWindowTokens, userState.mInteractionConnections); 468 if (removedWindowIdForUser >= 0) { 469 if (DEBUG) { 470 Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid() 471 + " with windowId: " + removedWindowIdForUser + " and userId:" 472 + mUserStates.keyAt(i)); 473 } 474 return; 475 } 476 } 477 } 478 } 479 480 private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, 481 SparseArray<IBinder> windowTokens, 482 SparseArray<AccessibilityConnectionWrapper> interactionConnections) { 483 final int count = windowTokens.size(); 484 for (int i = 0; i < count; i++) { 485 if (windowTokens.valueAt(i) == windowToken) { 486 final int windowId = windowTokens.keyAt(i); 487 windowTokens.removeAt(i); 488 AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId); 489 wrapper.unlinkToDeath(); 490 interactionConnections.remove(windowId); 491 return windowId; 492 } 493 } 494 return -1; 495 } 496 497 public void registerUiTestAutomationService(IAccessibilityServiceClient serviceClient, 498 AccessibilityServiceInfo accessibilityServiceInfo) { 499 mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT, 500 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE); 501 ComponentName componentName = new ComponentName("foo.bar", 502 "AutomationAccessibilityService"); 503 synchronized (mLock) { 504 // If an automation services is connected to the system all services are stopped 505 // so the automation one is the only one running. Settings are not changed so when 506 // the automation service goes away the state is restored from the settings. 507 UserState userState = getCurrentUserStateLocked(); 508 unbindAllServicesLocked(userState); 509 510 // If necessary enable accessibility and announce that. 511 if (!userState.mIsAccessibilityEnabled) { 512 userState.mIsAccessibilityEnabled = true; 513 } 514 // No touch exploration. 515 userState.mIsTouchExplorationEnabled = false; 516 517 // Hook the automation service up. 518 mUiAutomationService = new Service(mCurrentUserId, componentName, 519 accessibilityServiceInfo, true); 520 mUiAutomationService.onServiceConnected(componentName, serviceClient.asBinder()); 521 522 updateInputFilterLocked(userState); 523 scheduleSendStateToClientsLocked(userState); 524 } 525 } 526 527 public void temporaryEnableAccessibilityStateUntilKeyguardRemoved( 528 ComponentName service, boolean touchExplorationEnabled) { 529 mSecurityPolicy.enforceCallingPermission( 530 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY, 531 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED); 532 try { 533 if (!mWindowManagerService.isKeyguardLocked()) { 534 return; 535 } 536 } catch (RemoteException re) { 537 return; 538 } 539 synchronized (mLock) { 540 UserState userState = getCurrentUserStateLocked(); 541 // Stash the old state so we can restore it when the keyguard is gone. 542 mTempStateChangeForCurrentUserMemento.initialize(mCurrentUserId, getCurrentUserStateLocked()); 543 // Set the temporary state. 544 userState.mIsAccessibilityEnabled = true; 545 userState.mIsTouchExplorationEnabled= touchExplorationEnabled; 546 userState.mIsDisplayMagnificationEnabled = false; 547 userState.mEnabledServices.clear(); 548 userState.mEnabledServices.add(service); 549 userState.mTouchExplorationGrantedServices.clear(); 550 userState.mTouchExplorationGrantedServices.add(service); 551 // Update the internal state. 552 performServiceManagementLocked(userState); 553 updateInputFilterLocked(userState); 554 scheduleSendStateToClientsLocked(userState); 555 } 556 } 557 558 public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) { 559 synchronized (mLock) { 560 // Automation service is not bound, so pretend it died to perform clean up. 561 if (mUiAutomationService != null 562 && mUiAutomationService.mServiceInterface == serviceClient) { 563 mUiAutomationService.binderDied(); 564 } 565 } 566 } 567 568 boolean onGesture(int gestureId) { 569 synchronized (mLock) { 570 boolean handled = notifyGestureLocked(gestureId, false); 571 if (!handled) { 572 handled = notifyGestureLocked(gestureId, true); 573 } 574 return handled; 575 } 576 } 577 578 /** 579 * Gets the bounds of the accessibility focus in the active window. 580 * 581 * @param outBounds The output to which to write the focus bounds. 582 * @return Whether accessibility focus was found and the bounds are populated. 583 */ 584 boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) { 585 // Instead of keeping track of accessibility focus events per 586 // window to be able to find the focus in the active window, 587 // we take a stateless approach and look it up. This is fine 588 // since we do this only when the user clicks/long presses. 589 Service service = getQueryBridge(); 590 final int connectionId = service.mId; 591 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); 592 client.addConnection(connectionId, service); 593 try { 594 AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance() 595 .getRootInActiveWindow(connectionId); 596 if (root == null) { 597 return false; 598 } 599 AccessibilityNodeInfo focus = root.findFocus( 600 AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); 601 if (focus == null) { 602 return false; 603 } 604 focus.getBoundsInScreen(outBounds); 605 return true; 606 } finally { 607 client.removeConnection(connectionId); 608 } 609 } 610 611 /** 612 * Gets the bounds of the active window. 613 * 614 * @param outBounds The output to which to write the bounds. 615 */ 616 boolean getActiveWindowBounds(Rect outBounds) { 617 IBinder token; 618 synchronized (mLock) { 619 final int windowId = mSecurityPolicy.mActiveWindowId; 620 token = mGlobalWindowTokens.get(windowId); 621 if (token == null) { 622 token = getCurrentUserStateLocked().mWindowTokens.get(windowId); 623 } 624 } 625 WindowInfo info = null; 626 try { 627 info = mWindowManagerService.getWindowInfo(token); 628 if (info != null) { 629 outBounds.set(info.frame); 630 return true; 631 } 632 } catch (RemoteException re) { 633 /* ignore */ 634 } finally { 635 if (info != null) { 636 info.recycle(); 637 } 638 } 639 return false; 640 } 641 642 int getActiveWindowId() { 643 return mSecurityPolicy.mActiveWindowId; 644 } 645 646 private void switchUser(int userId) { 647 synchronized (mLock) { 648 // The user switched so we do not need to restore the current user 649 // state since we will fully rebuild it when he becomes current again. 650 mTempStateChangeForCurrentUserMemento.clear(); 651 652 // Disconnect from services for the old user. 653 UserState oldUserState = getUserStateLocked(mCurrentUserId); 654 unbindAllServicesLocked(oldUserState); 655 656 // Disable the local managers for the old user. 657 if (oldUserState.mClients.getRegisteredCallbackCount() > 0) { 658 mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER, 659 oldUserState.mUserId, 0).sendToTarget(); 660 } 661 662 // The user changed. 663 mCurrentUserId = userId; 664 665 // Recreate the internal state for the new user. 666 mMainHandler.obtainMessage(MainHandler.MSG_SEND_RECREATE_INTERNAL_STATE, 667 mCurrentUserId, 0).sendToTarget(); 668 669 // Schedule announcement of the current user if needed. 670 mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED, 671 WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS); 672 } 673 } 674 675 private void removeUser(int userId) { 676 synchronized (mLock) { 677 mUserStates.remove(userId); 678 } 679 } 680 681 private void restoreStateFromMementoIfNeeded() { 682 synchronized (mLock) { 683 if (mTempStateChangeForCurrentUserMemento.mUserId != UserHandle.USER_NULL) { 684 UserState userState = getCurrentUserStateLocked(); 685 // Restore the state from the memento. 686 mTempStateChangeForCurrentUserMemento.applyTo(userState); 687 mTempStateChangeForCurrentUserMemento.clear(); 688 // Update the internal state. 689 performServiceManagementLocked(userState); 690 updateInputFilterLocked(userState); 691 scheduleSendStateToClientsLocked(userState); 692 } 693 } 694 } 695 696 private Service getQueryBridge() { 697 if (mQueryBridge == null) { 698 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 699 mQueryBridge = new Service(UserHandle.USER_NULL, null, info, true); 700 } 701 return mQueryBridge; 702 } 703 704 private boolean notifyGestureLocked(int gestureId, boolean isDefault) { 705 // TODO: Now we are giving the gestures to the last enabled 706 // service that can handle them which is the last one 707 // in our list since we write the last enabled as the 708 // last record in the enabled services setting. Ideally, 709 // the user should make the call which service handles 710 // gestures. However, only one service should handle 711 // gestures to avoid user frustration when different 712 // behavior is observed from different combinations of 713 // enabled accessibility services. 714 UserState state = getCurrentUserStateLocked(); 715 for (int i = state.mServices.size() - 1; i >= 0; i--) { 716 Service service = state.mServices.get(i); 717 if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) { 718 service.notifyGesture(gestureId); 719 return true; 720 } 721 } 722 return false; 723 } 724 725 /** 726 * Removes an AccessibilityInteractionConnection. 727 * 728 * @param windowId The id of the window to which the connection is targeted. 729 * @param userId The id of the user owning the connection. UserHandle.USER_ALL 730 * if global. 731 */ 732 private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) { 733 if (userId == UserHandle.USER_ALL) { 734 mGlobalWindowTokens.remove(windowId); 735 mGlobalInteractionConnections.remove(windowId); 736 } else { 737 UserState userState = getCurrentUserStateLocked(); 738 userState.mWindowTokens.remove(windowId); 739 userState.mInteractionConnections.remove(windowId); 740 } 741 if (DEBUG) { 742 Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId); 743 } 744 } 745 746 private void populateInstalledAccessibilityServiceLocked(UserState userState) { 747 userState.mInstalledServices.clear(); 748 749 List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser( 750 new Intent(AccessibilityService.SERVICE_INTERFACE), 751 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, 752 mCurrentUserId); 753 754 for (int i = 0, count = installedServices.size(); i < count; i++) { 755 ResolveInfo resolveInfo = installedServices.get(i); 756 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 757 if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals( 758 serviceInfo.permission)) { 759 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName( 760 serviceInfo.packageName, serviceInfo.name).flattenToShortString() 761 + ": it does not require the permission " 762 + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE); 763 continue; 764 } 765 AccessibilityServiceInfo accessibilityServiceInfo; 766 try { 767 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext); 768 userState.mInstalledServices.add(accessibilityServiceInfo); 769 } catch (XmlPullParserException xppe) { 770 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe); 771 } catch (IOException ioe) { 772 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", ioe); 773 } 774 } 775 } 776 777 private void populateEnabledAccessibilityServicesLocked(UserState userState) { 778 populateComponentNamesFromSettingLocked( 779 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 780 userState.mUserId, 781 userState.mEnabledServices); 782 } 783 784 private void populateTouchExplorationGrantedAccessibilityServicesLocked( 785 UserState userState) { 786 populateComponentNamesFromSettingLocked( 787 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 788 userState.mUserId, 789 userState.mTouchExplorationGrantedServices); 790 } 791 792 /** 793 * Performs {@link AccessibilityService}s delayed notification. The delay is configurable 794 * and denotes the period after the last event before notifying the service. 795 * 796 * @param event The event. 797 * @param isDefault True to notify default listeners, not default services. 798 */ 799 private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, 800 boolean isDefault) { 801 try { 802 UserState state = getCurrentUserStateLocked(); 803 for (int i = 0, count = state.mServices.size(); i < count; i++) { 804 Service service = state.mServices.get(i); 805 806 if (service.mIsDefault == isDefault) { 807 if (canDispathEventLocked(service, event, state.mHandledFeedbackTypes)) { 808 state.mHandledFeedbackTypes |= service.mFeedbackType; 809 service.notifyAccessibilityEvent(event); 810 } 811 } 812 } 813 } catch (IndexOutOfBoundsException oobe) { 814 // An out of bounds exception can happen if services are going away 815 // as the for loop is running. If that happens, just bail because 816 // there are no more services to notify. 817 return; 818 } 819 } 820 821 /** 822 * Adds a service for a user. 823 * 824 * @param service The service to add. 825 * @param userId The user id. 826 */ 827 private void tryAddServiceLocked(Service service, int userId) { 828 try { 829 UserState userState = getUserStateLocked(userId); 830 if (userState.mServices.contains(service)) { 831 return; 832 } 833 service.linkToOwnDeath(); 834 userState.mServices.add(service); 835 userState.mComponentNameToServiceMap.put(service.mComponentName, service); 836 updateInputFilterLocked(userState); 837 tryEnableTouchExplorationLocked(service); 838 } catch (RemoteException e) { 839 /* do nothing */ 840 } 841 } 842 843 /** 844 * Removes a service. 845 * 846 * @param service The service. 847 * @return True if the service was removed, false otherwise. 848 */ 849 private boolean tryRemoveServiceLocked(Service service) { 850 UserState userState = getUserStateLocked(service.mUserId); 851 final boolean removed = userState.mServices.remove(service); 852 if (!removed) { 853 return false; 854 } 855 userState.mComponentNameToServiceMap.remove(service.mComponentName); 856 service.unlinkToOwnDeath(); 857 service.dispose(); 858 updateInputFilterLocked(userState); 859 tryDisableTouchExplorationLocked(service); 860 return removed; 861 } 862 863 /** 864 * Determines if given event can be dispatched to a service based on the package of the 865 * event source and already notified services for that event type. Specifically, a 866 * service is notified if it is interested in events from the package and no other service 867 * providing the same feedback type has been notified. Exception are services the 868 * provide generic feedback (feedback type left as a safety net for unforeseen feedback 869 * types) which are always notified. 870 * 871 * @param service The potential receiver. 872 * @param event The event. 873 * @param handledFeedbackTypes The feedback types for which services have been notified. 874 * @return True if the listener should be notified, false otherwise. 875 */ 876 private boolean canDispathEventLocked(Service service, AccessibilityEvent event, 877 int handledFeedbackTypes) { 878 879 if (!service.canReceiveEvents()) { 880 return false; 881 } 882 883 if (!event.isImportantForAccessibility() 884 && !service.mIncludeNotImportantViews) { 885 return false; 886 } 887 888 int eventType = event.getEventType(); 889 if ((service.mEventTypes & eventType) != eventType) { 890 return false; 891 } 892 893 Set<String> packageNames = service.mPackageNames; 894 CharSequence packageName = event.getPackageName(); 895 896 if (packageNames.isEmpty() || packageNames.contains(packageName)) { 897 int feedbackType = service.mFeedbackType; 898 if ((handledFeedbackTypes & feedbackType) != feedbackType 899 || feedbackType == AccessibilityServiceInfo.FEEDBACK_GENERIC) { 900 return true; 901 } 902 } 903 904 return false; 905 } 906 907 /** 908 * Manages services by starting enabled ones and stopping disabled ones. 909 */ 910 private void manageServicesLocked(UserState userState) { 911 final int enabledInstalledServicesCount = updateServicesStateLocked(userState); 912 // No enabled installed services => disable accessibility to avoid 913 // sending accessibility events with no recipient across processes. 914 if (userState.mIsAccessibilityEnabled && enabledInstalledServicesCount == 0) { 915 Settings.Secure.putIntForUser(mContext.getContentResolver(), 916 Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId); 917 } 918 } 919 920 /** 921 * Unbinds all bound services for a user. 922 * 923 * @param userState The user state. 924 */ 925 private void unbindAllServicesLocked(UserState userState) { 926 List<Service> services = userState.mServices; 927 for (int i = 0, count = services.size(); i < count; i++) { 928 Service service = services.get(i); 929 if (service.unbind()) { 930 i--; 931 count--; 932 } 933 } 934 } 935 936 /** 937 * Populates a set with the {@link ComponentName}s stored in a colon 938 * separated value setting for a given user. 939 * 940 * @param settingName The setting to parse. 941 * @param userId The user id. 942 * @param outComponentNames The output component names. 943 */ 944 private void populateComponentNamesFromSettingLocked(String settingName, int userId, 945 Set<ComponentName> outComponentNames) { 946 String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(), 947 settingName, userId); 948 outComponentNames.clear(); 949 if (settingValue != null) { 950 TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; 951 splitter.setString(settingValue); 952 while (splitter.hasNext()) { 953 String str = splitter.next(); 954 if (str == null || str.length() <= 0) { 955 continue; 956 } 957 ComponentName enabledService = ComponentName.unflattenFromString(str); 958 if (enabledService != null) { 959 outComponentNames.add(enabledService); 960 } 961 } 962 } 963 } 964 965 /** 966 * Persists the component names in the specified setting in a 967 * colon separated fashion. 968 * 969 * @param settingName The setting name. 970 * @param componentNames The component names. 971 */ 972 private void persistComponentNamesToSettingLocked(String settingName, 973 Set<ComponentName> componentNames, int userId) { 974 StringBuilder builder = new StringBuilder(); 975 for (ComponentName componentName : componentNames) { 976 if (builder.length() > 0) { 977 builder.append(COMPONENT_NAME_SEPARATOR); 978 } 979 builder.append(componentName.flattenToShortString()); 980 } 981 Settings.Secure.putStringForUser(mContext.getContentResolver(), 982 settingName, builder.toString(), userId); 983 } 984 985 /** 986 * Updates the state of each service by starting (or keeping running) enabled ones and 987 * stopping the rest. 988 * 989 * @param userState The user state for which to do that. 990 * @return The number of enabled installed services. 991 */ 992 private int updateServicesStateLocked(UserState userState) { 993 Map<ComponentName, Service> componentNameToServiceMap = 994 userState.mComponentNameToServiceMap; 995 boolean isEnabled = userState.mIsAccessibilityEnabled; 996 997 int enabledInstalledServices = 0; 998 for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) { 999 AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i); 1000 ComponentName componentName = ComponentName.unflattenFromString( 1001 installedService.getId()); 1002 Service service = componentNameToServiceMap.get(componentName); 1003 1004 if (isEnabled) { 1005 if (userState.mEnabledServices.contains(componentName)) { 1006 if (service == null) { 1007 service = new Service(userState.mUserId, componentName, 1008 installedService, false); 1009 } 1010 service.bind(); 1011 enabledInstalledServices++; 1012 } else { 1013 if (service != null) { 1014 service.unbind(); 1015 } 1016 } 1017 } else { 1018 if (service != null) { 1019 service.unbind(); 1020 } 1021 } 1022 } 1023 1024 return enabledInstalledServices; 1025 } 1026 1027 private void scheduleSendStateToClientsLocked(UserState userState) { 1028 if (mGlobalClients.getRegisteredCallbackCount() > 0 1029 || userState.mClients.getRegisteredCallbackCount() > 0) { 1030 final int clientState = getClientState(userState); 1031 mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS, 1032 clientState, userState.mUserId) .sendToTarget(); 1033 } 1034 } 1035 1036 private void updateInputFilterLocked(UserState userState) { 1037 boolean setInputFilter = false; 1038 AccessibilityInputFilter inputFilter = null; 1039 synchronized (mLock) { 1040 if ((userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) 1041 || userState.mIsDisplayMagnificationEnabled) { 1042 if (!mHasInputFilter) { 1043 mHasInputFilter = true; 1044 if (mInputFilter == null) { 1045 mInputFilter = new AccessibilityInputFilter(mContext, 1046 AccessibilityManagerService.this); 1047 } 1048 inputFilter = mInputFilter; 1049 setInputFilter = true; 1050 } 1051 int flags = 0; 1052 if (userState.mIsDisplayMagnificationEnabled) { 1053 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER; 1054 } 1055 if (userState.mIsTouchExplorationEnabled) { 1056 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION; 1057 } 1058 mInputFilter.setEnabledFeatures(flags); 1059 } else { 1060 if (mHasInputFilter) { 1061 mHasInputFilter = false; 1062 mInputFilter.setEnabledFeatures(0); 1063 inputFilter = null; 1064 setInputFilter = true; 1065 } 1066 } 1067 } 1068 if (setInputFilter) { 1069 try { 1070 mWindowManagerService.setInputFilter(inputFilter); 1071 } catch (RemoteException re) { 1072 /* ignore */ 1073 } 1074 } 1075 } 1076 1077 private void showEnableTouchExplorationDialog(final Service service) { 1078 String label = service.mResolveInfo.loadLabel( 1079 mContext.getPackageManager()).toString(); 1080 synchronized (mLock) { 1081 final UserState state = getCurrentUserStateLocked(); 1082 if (state.mIsTouchExplorationEnabled) { 1083 return; 1084 } 1085 if (mEnableTouchExplorationDialog != null 1086 && mEnableTouchExplorationDialog.isShowing()) { 1087 return; 1088 } 1089 mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext) 1090 .setIcon(android.R.drawable.ic_dialog_alert) 1091 .setPositiveButton(android.R.string.ok, new OnClickListener() { 1092 @Override 1093 public void onClick(DialogInterface dialog, int which) { 1094 // The user allowed the service to toggle touch exploration. 1095 state.mTouchExplorationGrantedServices.add(service.mComponentName); 1096 persistComponentNamesToSettingLocked( 1097 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 1098 state.mTouchExplorationGrantedServices, state.mUserId); 1099 // Enable touch exploration. 1100 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1101 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, 1102 service.mUserId); 1103 } 1104 }) 1105 .setNegativeButton(android.R.string.cancel, new OnClickListener() { 1106 @Override 1107 public void onClick(DialogInterface dialog, int which) { 1108 dialog.dismiss(); 1109 } 1110 }) 1111 .setTitle(R.string.enable_explore_by_touch_warning_title) 1112 .setMessage(mContext.getString( 1113 R.string.enable_explore_by_touch_warning_message, label)) 1114 .create(); 1115 mEnableTouchExplorationDialog.getWindow().setType( 1116 WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG); 1117 mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true); 1118 mEnableTouchExplorationDialog.show(); 1119 } 1120 } 1121 1122 private int getClientState(UserState userState) { 1123 int clientState = 0; 1124 if (userState.mIsAccessibilityEnabled) { 1125 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED; 1126 } 1127 // Touch exploration relies on enabled accessibility. 1128 if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) { 1129 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; 1130 } 1131 return clientState; 1132 } 1133 1134 private void recreateInternalStateLocked(UserState userState) { 1135 populateInstalledAccessibilityServiceLocked(userState); 1136 populateEnabledAccessibilityServicesLocked(userState); 1137 populateTouchExplorationGrantedAccessibilityServicesLocked(userState); 1138 1139 handleTouchExplorationEnabledSettingChangedLocked(userState); 1140 handleDisplayMagnificationEnabledSettingChangedLocked(userState); 1141 handleAccessibilityEnabledSettingChangedLocked(userState); 1142 1143 performServiceManagementLocked(userState); 1144 updateInputFilterLocked(userState); 1145 scheduleSendStateToClientsLocked(userState); 1146 } 1147 1148 private void handleAccessibilityEnabledSettingChangedLocked(UserState userState) { 1149 userState.mIsAccessibilityEnabled = Settings.Secure.getIntForUser( 1150 mContext.getContentResolver(), 1151 Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1; 1152 } 1153 1154 private void performServiceManagementLocked(UserState userState) { 1155 if (userState.mIsAccessibilityEnabled ) { 1156 manageServicesLocked(userState); 1157 } else { 1158 unbindAllServicesLocked(userState); 1159 } 1160 } 1161 1162 private void handleTouchExplorationEnabledSettingChangedLocked(UserState userState) { 1163 userState.mIsTouchExplorationEnabled = Settings.Secure.getIntForUser( 1164 mContext.getContentResolver(), 1165 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1; 1166 } 1167 1168 private void handleDisplayMagnificationEnabledSettingChangedLocked(UserState userState) { 1169 userState.mIsDisplayMagnificationEnabled = Settings.Secure.getIntForUser( 1170 mContext.getContentResolver(), 1171 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 1172 0, userState.mUserId) == 1; 1173 } 1174 1175 private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked( 1176 UserState userState) { 1177 final int serviceCount = userState.mServices.size(); 1178 for (int i = 0; i < serviceCount; i++) { 1179 Service service = userState.mServices.get(i); 1180 if (service.mRequestTouchExplorationMode 1181 && userState.mTouchExplorationGrantedServices.contains( 1182 service.mComponentName)) { 1183 tryEnableTouchExplorationLocked(service); 1184 return; 1185 } 1186 } 1187 if (userState.mIsTouchExplorationEnabled) { 1188 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1189 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId); 1190 } 1191 } 1192 1193 private void tryEnableTouchExplorationLocked(final Service service) { 1194 UserState userState = getUserStateLocked(service.mUserId); 1195 if (!userState.mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode 1196 && service.canReceiveEvents()) { 1197 final boolean canToggleTouchExploration = 1198 userState.mTouchExplorationGrantedServices.contains(service.mComponentName); 1199 if (!service.mIsAutomation && !canToggleTouchExploration) { 1200 showEnableTouchExplorationDialog(service); 1201 } else { 1202 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1203 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, userState.mUserId); 1204 } 1205 } 1206 } 1207 1208 private void tryDisableTouchExplorationLocked(Service service) { 1209 if (!service.canReceiveEvents()) { 1210 return; 1211 } 1212 UserState userState = getUserStateLocked(service.mUserId); 1213 if (userState.mIsTouchExplorationEnabled) { 1214 final int serviceCount = userState.mServices.size(); 1215 for (int i = 0; i < serviceCount; i++) { 1216 Service other = userState.mServices.get(i); 1217 if (other != service && other.mRequestTouchExplorationMode) { 1218 return; 1219 } 1220 } 1221 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1222 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId); 1223 } 1224 } 1225 1226 private class AccessibilityConnectionWrapper implements DeathRecipient { 1227 private final int mWindowId; 1228 private final int mUserId; 1229 private final IAccessibilityInteractionConnection mConnection; 1230 1231 public AccessibilityConnectionWrapper(int windowId, 1232 IAccessibilityInteractionConnection connection, int userId) { 1233 mWindowId = windowId; 1234 mUserId = userId; 1235 mConnection = connection; 1236 } 1237 1238 public void linkToDeath() throws RemoteException { 1239 mConnection.asBinder().linkToDeath(this, 0); 1240 } 1241 1242 public void unlinkToDeath() { 1243 mConnection.asBinder().unlinkToDeath(this, 0); 1244 } 1245 1246 @Override 1247 public void binderDied() { 1248 unlinkToDeath(); 1249 synchronized (mLock) { 1250 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId); 1251 } 1252 } 1253 } 1254 1255 private final class MainHandler extends Handler { 1256 public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1; 1257 public static final int MSG_SEND_STATE_TO_CLIENTS = 2; 1258 public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3; 1259 public static final int MSG_SEND_RECREATE_INTERNAL_STATE = 4; 1260 public static final int MSG_UPDATE_ACTIVE_WINDOW = 5; 1261 public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 6; 1262 1263 public MainHandler(Looper looper) { 1264 super(looper); 1265 } 1266 1267 @Override 1268 public void handleMessage(Message msg) { 1269 final int type = msg.what; 1270 switch (type) { 1271 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: { 1272 AccessibilityEvent event = (AccessibilityEvent) msg.obj; 1273 synchronized (mLock) { 1274 if (mHasInputFilter && mInputFilter != null) { 1275 mInputFilter.notifyAccessibilityEvent(event); 1276 } 1277 } 1278 event.recycle(); 1279 } break; 1280 case MSG_SEND_STATE_TO_CLIENTS: { 1281 final int clientState = msg.arg1; 1282 final int userId = msg.arg2; 1283 sendStateToClients(clientState, mGlobalClients); 1284 sendStateToClientsForUser(clientState, userId); 1285 } break; 1286 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: { 1287 final int userId = msg.arg1; 1288 sendStateToClientsForUser(0, userId); 1289 } break; 1290 case MSG_SEND_RECREATE_INTERNAL_STATE: { 1291 final int userId = msg.arg1; 1292 synchronized (mLock) { 1293 UserState userState = getUserStateLocked(userId); 1294 recreateInternalStateLocked(userState); 1295 } 1296 } break; 1297 case MSG_UPDATE_ACTIVE_WINDOW: { 1298 final int windowId = msg.arg1; 1299 final int eventType = msg.arg2; 1300 mSecurityPolicy.updateActiveWindow(windowId, eventType); 1301 } break; 1302 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: { 1303 announceNewUserIfNeeded(); 1304 } break; 1305 } 1306 } 1307 1308 private void announceNewUserIfNeeded() { 1309 synchronized (mLock) { 1310 UserState userState = getCurrentUserStateLocked(); 1311 if (userState.mIsAccessibilityEnabled) { 1312 UserManager userManager = (UserManager) mContext.getSystemService( 1313 Context.USER_SERVICE); 1314 String message = mContext.getString(R.string.user_switched, 1315 userManager.getUserInfo(mCurrentUserId).name); 1316 AccessibilityEvent event = AccessibilityEvent.obtain( 1317 AccessibilityEvent.TYPE_ANNOUNCEMENT); 1318 event.getText().add(message); 1319 sendAccessibilityEvent(event, mCurrentUserId); 1320 } 1321 } 1322 } 1323 1324 private void sendStateToClientsForUser(int clientState, int userId) { 1325 final UserState userState; 1326 synchronized (mLock) { 1327 userState = getUserStateLocked(userId); 1328 } 1329 sendStateToClients(clientState, userState.mClients); 1330 } 1331 1332 private void sendStateToClients(int clientState, 1333 RemoteCallbackList<IAccessibilityManagerClient> clients) { 1334 try { 1335 final int userClientCount = clients.beginBroadcast(); 1336 for (int i = 0; i < userClientCount; i++) { 1337 IAccessibilityManagerClient client = clients.getBroadcastItem(i); 1338 try { 1339 client.setState(clientState); 1340 } catch (RemoteException re) { 1341 /* ignore */ 1342 } 1343 } 1344 } finally { 1345 clients.finishBroadcast(); 1346 } 1347 } 1348 } 1349 1350 /** 1351 * This class represents an accessibility service. It stores all per service 1352 * data required for the service management, provides API for starting/stopping the 1353 * service and is responsible for adding/removing the service in the data structures 1354 * for service management. The class also exposes configuration interface that is 1355 * passed to the service it represents as soon it is bound. It also serves as the 1356 * connection for the service. 1357 */ 1358 class Service extends IAccessibilityServiceConnection.Stub 1359 implements ServiceConnection, DeathRecipient { 1360 1361 // We pick the MSB to avoid collision since accessibility event types are 1362 // used as message types allowing us to remove messages per event type. 1363 private static final int MSG_ON_GESTURE = 0x80000000; 1364 1365 final int mUserId; 1366 1367 int mId = 0; 1368 1369 AccessibilityServiceInfo mAccessibilityServiceInfo; 1370 1371 IBinder mService; 1372 1373 IAccessibilityServiceClient mServiceInterface; 1374 1375 int mEventTypes; 1376 1377 int mFeedbackType; 1378 1379 Set<String> mPackageNames = new HashSet<String>(); 1380 1381 boolean mIsDefault; 1382 1383 boolean mRequestTouchExplorationMode; 1384 1385 boolean mIncludeNotImportantViews; 1386 1387 long mNotificationTimeout; 1388 1389 ComponentName mComponentName; 1390 1391 Intent mIntent; 1392 1393 boolean mCanRetrieveScreenContent; 1394 1395 boolean mIsAutomation; 1396 1397 final Rect mTempBounds = new Rect(); 1398 1399 final ResolveInfo mResolveInfo; 1400 1401 // the events pending events to be dispatched to this service 1402 final SparseArray<AccessibilityEvent> mPendingEvents = 1403 new SparseArray<AccessibilityEvent>(); 1404 1405 /** 1406 * Handler for delayed event dispatch. 1407 */ 1408 public Handler mHandler = new Handler(mMainHandler.getLooper()) { 1409 @Override 1410 public void handleMessage(Message message) { 1411 final int type = message.what; 1412 switch (type) { 1413 case MSG_ON_GESTURE: { 1414 final int gestureId = message.arg1; 1415 notifyGestureInternal(gestureId); 1416 } break; 1417 default: { 1418 final int eventType = type; 1419 notifyAccessibilityEventInternal(eventType); 1420 } break; 1421 } 1422 } 1423 }; 1424 1425 public Service(int userId, ComponentName componentName, 1426 AccessibilityServiceInfo accessibilityServiceInfo, boolean isAutomation) { 1427 mUserId = userId; 1428 mResolveInfo = accessibilityServiceInfo.getResolveInfo(); 1429 mId = sIdCounter++; 1430 mComponentName = componentName; 1431 mAccessibilityServiceInfo = accessibilityServiceInfo; 1432 mIsAutomation = isAutomation; 1433 if (!isAutomation) { 1434 mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent(); 1435 mRequestTouchExplorationMode = 1436 (accessibilityServiceInfo.flags 1437 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; 1438 mIntent = new Intent().setComponent(mComponentName); 1439 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, 1440 com.android.internal.R.string.accessibility_binding_label); 1441 mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( 1442 mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); 1443 } else { 1444 mCanRetrieveScreenContent = true; 1445 } 1446 setDynamicallyConfigurableProperties(accessibilityServiceInfo); 1447 } 1448 1449 public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { 1450 mEventTypes = info.eventTypes; 1451 mFeedbackType = info.feedbackType; 1452 String[] packageNames = info.packageNames; 1453 if (packageNames != null) { 1454 mPackageNames.addAll(Arrays.asList(packageNames)); 1455 } 1456 mNotificationTimeout = info.notificationTimeout; 1457 mIsDefault = (info.flags & DEFAULT) != 0; 1458 1459 if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion 1460 >= Build.VERSION_CODES.JELLY_BEAN) { 1461 mIncludeNotImportantViews = 1462 (info.flags & FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0; 1463 } 1464 1465 mRequestTouchExplorationMode = (info.flags 1466 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; 1467 1468 // If this service is up and running we may have to enable touch 1469 // exploration, otherwise this will happen when the service connects. 1470 synchronized (mLock) { 1471 if (canReceiveEvents()) { 1472 if (mRequestTouchExplorationMode) { 1473 tryEnableTouchExplorationLocked(this); 1474 } else { 1475 tryDisableTouchExplorationLocked(this); 1476 } 1477 } 1478 } 1479 } 1480 1481 /** 1482 * Binds to the accessibility service. 1483 * 1484 * @return True if binding is successful. 1485 */ 1486 public boolean bind() { 1487 if (!mIsAutomation && mService == null) { 1488 return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE, mUserId); 1489 } 1490 return false; 1491 } 1492 1493 /** 1494 * Unbinds form the accessibility service and removes it from the data 1495 * structures for service management. 1496 * 1497 * @return True if unbinding is successful. 1498 */ 1499 public boolean unbind() { 1500 if (mService != null) { 1501 synchronized (mLock) { 1502 tryRemoveServiceLocked(this); 1503 } 1504 if (!mIsAutomation) { 1505 mContext.unbindService(this); 1506 } 1507 return true; 1508 } 1509 return false; 1510 } 1511 1512 public boolean canReceiveEvents() { 1513 return (mEventTypes != 0 && mFeedbackType != 0 && mService != null); 1514 } 1515 1516 @Override 1517 public AccessibilityServiceInfo getServiceInfo() { 1518 synchronized (mLock) { 1519 return mAccessibilityServiceInfo; 1520 } 1521 } 1522 1523 @Override 1524 public void setServiceInfo(AccessibilityServiceInfo info) { 1525 final long identity = Binder.clearCallingIdentity(); 1526 try { 1527 synchronized (mLock) { 1528 // If the XML manifest had data to configure the service its info 1529 // should be already set. In such a case update only the dynamically 1530 // configurable properties. 1531 AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; 1532 if (oldInfo != null) { 1533 oldInfo.updateDynamicallyConfigurableProperties(info); 1534 setDynamicallyConfigurableProperties(oldInfo); 1535 } else { 1536 setDynamicallyConfigurableProperties(info); 1537 } 1538 } 1539 } finally { 1540 Binder.restoreCallingIdentity(identity); 1541 } 1542 } 1543 1544 @Override 1545 public void onServiceConnected(ComponentName componentName, IBinder service) { 1546 mService = service; 1547 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service); 1548 try { 1549 mServiceInterface.setConnection(this, mId); 1550 synchronized (mLock) { 1551 tryAddServiceLocked(this, mUserId); 1552 } 1553 } catch (RemoteException re) { 1554 Slog.w(LOG_TAG, "Error while setting Controller for service: " + service, re); 1555 } 1556 } 1557 1558 @Override 1559 public float findAccessibilityNodeInfoByViewId(int accessibilityWindowId, 1560 long accessibilityNodeId, int viewId, int interactionId, 1561 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 1562 throws RemoteException { 1563 final int resolvedWindowId; 1564 IAccessibilityInteractionConnection connection = null; 1565 synchronized (mLock) { 1566 final int resolvedUserId = mSecurityPolicy 1567 .resolveCallingUserIdEnforcingPermissionsLocked( 1568 UserHandle.getCallingUserId()); 1569 if (resolvedUserId != mCurrentUserId) { 1570 return -1; 1571 } 1572 mSecurityPolicy.enforceCanRetrieveWindowContent(this); 1573 final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this); 1574 if (!permissionGranted) { 1575 return 0; 1576 } else { 1577 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 1578 connection = getConnectionLocked(resolvedWindowId); 1579 if (connection == null) { 1580 return 0; 1581 } 1582 } 1583 } 1584 final int flags = (mIncludeNotImportantViews) ? 1585 AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; 1586 final int interrogatingPid = Binder.getCallingPid(); 1587 final long identityToken = Binder.clearCallingIdentity(); 1588 try { 1589 connection.findAccessibilityNodeInfoByViewId(accessibilityNodeId, viewId, 1590 interactionId, callback, flags, interrogatingPid, interrogatingTid); 1591 return getCompatibilityScale(resolvedWindowId); 1592 } catch (RemoteException re) { 1593 if (DEBUG) { 1594 Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); 1595 } 1596 } finally { 1597 Binder.restoreCallingIdentity(identityToken); 1598 } 1599 return 0; 1600 } 1601 1602 @Override 1603 public float findAccessibilityNodeInfosByText(int accessibilityWindowId, 1604 long accessibilityNodeId, String text, int interactionId, 1605 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 1606 throws RemoteException { 1607 final int resolvedWindowId; 1608 IAccessibilityInteractionConnection connection = null; 1609 synchronized (mLock) { 1610 final int resolvedUserId = mSecurityPolicy 1611 .resolveCallingUserIdEnforcingPermissionsLocked( 1612 UserHandle.getCallingUserId()); 1613 if (resolvedUserId != mCurrentUserId) { 1614 return -1; 1615 } 1616 mSecurityPolicy.enforceCanRetrieveWindowContent(this); 1617 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 1618 final boolean permissionGranted = 1619 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 1620 if (!permissionGranted) { 1621 return 0; 1622 } else { 1623 connection = getConnectionLocked(resolvedWindowId); 1624 if (connection == null) { 1625 return 0; 1626 } 1627 } 1628 } 1629 final int flags = (mIncludeNotImportantViews) ? 1630 AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; 1631 final int interrogatingPid = Binder.getCallingPid(); 1632 final long identityToken = Binder.clearCallingIdentity(); 1633 try { 1634 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, 1635 interactionId, callback, flags, interrogatingPid, 1636 interrogatingTid); 1637 return getCompatibilityScale(resolvedWindowId); 1638 } catch (RemoteException re) { 1639 if (DEBUG) { 1640 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); 1641 } 1642 } finally { 1643 Binder.restoreCallingIdentity(identityToken); 1644 } 1645 return 0; 1646 } 1647 1648 @Override 1649 public float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, 1650 long accessibilityNodeId, int interactionId, 1651 IAccessibilityInteractionConnectionCallback callback, int flags, 1652 long interrogatingTid) throws RemoteException { 1653 final int resolvedWindowId; 1654 IAccessibilityInteractionConnection connection = null; 1655 synchronized (mLock) { 1656 final int resolvedUserId = mSecurityPolicy 1657 .resolveCallingUserIdEnforcingPermissionsLocked( 1658 UserHandle.getCallingUserId()); 1659 if (resolvedUserId != mCurrentUserId) { 1660 return -1; 1661 } 1662 mSecurityPolicy.enforceCanRetrieveWindowContent(this); 1663 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 1664 final boolean permissionGranted = 1665 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 1666 if (!permissionGranted) { 1667 return 0; 1668 } else { 1669 connection = getConnectionLocked(resolvedWindowId); 1670 if (connection == null) { 1671 return 0; 1672 } 1673 } 1674 } 1675 final int allFlags = flags | ((mIncludeNotImportantViews) ? 1676 AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0); 1677 final int interrogatingPid = Binder.getCallingPid(); 1678 final long identityToken = Binder.clearCallingIdentity(); 1679 try { 1680 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, 1681 interactionId, callback, allFlags, interrogatingPid, interrogatingTid); 1682 return getCompatibilityScale(resolvedWindowId); 1683 } catch (RemoteException re) { 1684 if (DEBUG) { 1685 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); 1686 } 1687 } finally { 1688 Binder.restoreCallingIdentity(identityToken); 1689 } 1690 return 0; 1691 } 1692 1693 @Override 1694 public float findFocus(int accessibilityWindowId, long accessibilityNodeId, 1695 int focusType, int interactionId, 1696 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 1697 throws RemoteException { 1698 final int resolvedWindowId; 1699 IAccessibilityInteractionConnection connection = null; 1700 synchronized (mLock) { 1701 final int resolvedUserId = mSecurityPolicy 1702 .resolveCallingUserIdEnforcingPermissionsLocked( 1703 UserHandle.getCallingUserId()); 1704 if (resolvedUserId != mCurrentUserId) { 1705 return -1; 1706 } 1707 mSecurityPolicy.enforceCanRetrieveWindowContent(this); 1708 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 1709 final boolean permissionGranted = 1710 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 1711 if (!permissionGranted) { 1712 return 0; 1713 } else { 1714 connection = getConnectionLocked(resolvedWindowId); 1715 if (connection == null) { 1716 return 0; 1717 } 1718 } 1719 } 1720 final int flags = (mIncludeNotImportantViews) ? 1721 AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; 1722 final int interrogatingPid = Binder.getCallingPid(); 1723 final long identityToken = Binder.clearCallingIdentity(); 1724 try { 1725 connection.findFocus(accessibilityNodeId, focusType, interactionId, callback, 1726 flags, interrogatingPid, interrogatingTid); 1727 return getCompatibilityScale(resolvedWindowId); 1728 } catch (RemoteException re) { 1729 if (DEBUG) { 1730 Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()"); 1731 } 1732 } finally { 1733 Binder.restoreCallingIdentity(identityToken); 1734 } 1735 return 0; 1736 } 1737 1738 @Override 1739 public float focusSearch(int accessibilityWindowId, long accessibilityNodeId, 1740 int direction, int interactionId, 1741 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 1742 throws RemoteException { 1743 final int resolvedWindowId; 1744 IAccessibilityInteractionConnection connection = null; 1745 synchronized (mLock) { 1746 final int resolvedUserId = mSecurityPolicy 1747 .resolveCallingUserIdEnforcingPermissionsLocked( 1748 UserHandle.getCallingUserId()); 1749 if (resolvedUserId != mCurrentUserId) { 1750 return -1; 1751 } 1752 mSecurityPolicy.enforceCanRetrieveWindowContent(this); 1753 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 1754 final boolean permissionGranted = 1755 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 1756 if (!permissionGranted) { 1757 return 0; 1758 } else { 1759 connection = getConnectionLocked(resolvedWindowId); 1760 if (connection == null) { 1761 return 0; 1762 } 1763 } 1764 } 1765 final int flags = (mIncludeNotImportantViews) ? 1766 AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; 1767 final int interrogatingPid = Binder.getCallingPid(); 1768 final long identityToken = Binder.clearCallingIdentity(); 1769 try { 1770 connection.focusSearch(accessibilityNodeId, direction, interactionId, callback, 1771 flags, interrogatingPid, interrogatingTid); 1772 return getCompatibilityScale(resolvedWindowId); 1773 } catch (RemoteException re) { 1774 if (DEBUG) { 1775 Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); 1776 } 1777 } finally { 1778 Binder.restoreCallingIdentity(identityToken); 1779 } 1780 return 0; 1781 } 1782 1783 @Override 1784 public boolean performAccessibilityAction(int accessibilityWindowId, 1785 long accessibilityNodeId, int action, Bundle arguments, int interactionId, 1786 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 1787 throws RemoteException { 1788 final int resolvedWindowId; 1789 IAccessibilityInteractionConnection connection = null; 1790 synchronized (mLock) { 1791 final int resolvedUserId = mSecurityPolicy 1792 .resolveCallingUserIdEnforcingPermissionsLocked( 1793 UserHandle.getCallingUserId()); 1794 if (resolvedUserId != mCurrentUserId) { 1795 return false; 1796 } 1797 mSecurityPolicy.enforceCanRetrieveWindowContent(this); 1798 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 1799 final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this, 1800 resolvedWindowId, action, arguments); 1801 if (!permissionGranted) { 1802 return false; 1803 } else { 1804 connection = getConnectionLocked(resolvedWindowId); 1805 if (connection == null) { 1806 return false; 1807 } 1808 } 1809 } 1810 final int flags = (mIncludeNotImportantViews) ? 1811 AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; 1812 final int interrogatingPid = Binder.getCallingPid(); 1813 final long identityToken = Binder.clearCallingIdentity(); 1814 try { 1815 connection.performAccessibilityAction(accessibilityNodeId, action, arguments, 1816 interactionId, callback, flags, interrogatingPid, interrogatingTid); 1817 } catch (RemoteException re) { 1818 if (DEBUG) { 1819 Slog.e(LOG_TAG, "Error calling performAccessibilityAction()"); 1820 } 1821 } finally { 1822 Binder.restoreCallingIdentity(identityToken); 1823 } 1824 return true; 1825 } 1826 1827 public boolean performGlobalAction(int action) { 1828 synchronized (mLock) { 1829 final int resolvedUserId = mSecurityPolicy 1830 .resolveCallingUserIdEnforcingPermissionsLocked( 1831 UserHandle.getCallingUserId()); 1832 if (resolvedUserId != mCurrentUserId) { 1833 return false; 1834 } 1835 } 1836 final long identity = Binder.clearCallingIdentity(); 1837 try { 1838 switch (action) { 1839 case AccessibilityService.GLOBAL_ACTION_BACK: { 1840 sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK); 1841 } return true; 1842 case AccessibilityService.GLOBAL_ACTION_HOME: { 1843 sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME); 1844 } return true; 1845 case AccessibilityService.GLOBAL_ACTION_RECENTS: { 1846 openRecents(); 1847 } return true; 1848 case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: { 1849 expandNotifications(); 1850 } return true; 1851 case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: { 1852 expandQuickSettings(); 1853 } return true; 1854 } 1855 return false; 1856 } finally { 1857 Binder.restoreCallingIdentity(identity); 1858 } 1859 } 1860 1861 public void onServiceDisconnected(ComponentName componentName) { 1862 /* do nothing - #binderDied takes care */ 1863 } 1864 1865 public void linkToOwnDeath() throws RemoteException { 1866 mService.linkToDeath(this, 0); 1867 } 1868 1869 public void unlinkToOwnDeath() { 1870 mService.unlinkToDeath(this, 0); 1871 } 1872 1873 public void dispose() { 1874 try { 1875 // Clear the proxy in the other process so this 1876 // IAccessibilityServiceConnection can be garbage collected. 1877 mServiceInterface.setConnection(null, mId); 1878 } catch (RemoteException re) { 1879 /* ignore */ 1880 } 1881 mService = null; 1882 mServiceInterface = null; 1883 } 1884 1885 public void binderDied() { 1886 synchronized (mLock) { 1887 // The death recipient is unregistered in tryRemoveServiceLocked 1888 tryRemoveServiceLocked(this); 1889 // We no longer have an automation service, so restore 1890 // the state based on values in the settings database. 1891 if (mIsAutomation) { 1892 mUiAutomationService = null; 1893 recreateInternalStateLocked(getUserStateLocked(mUserId)); 1894 } 1895 } 1896 } 1897 1898 /** 1899 * Performs a notification for an {@link AccessibilityEvent}. 1900 * 1901 * @param event The event. 1902 */ 1903 public void notifyAccessibilityEvent(AccessibilityEvent event) { 1904 synchronized (mLock) { 1905 final int eventType = event.getEventType(); 1906 // Make a copy since during dispatch it is possible the event to 1907 // be modified to remove its source if the receiving service does 1908 // not have permission to access the window content. 1909 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); 1910 AccessibilityEvent oldEvent = mPendingEvents.get(eventType); 1911 mPendingEvents.put(eventType, newEvent); 1912 1913 final int what = eventType; 1914 if (oldEvent != null) { 1915 mHandler.removeMessages(what); 1916 oldEvent.recycle(); 1917 } 1918 1919 Message message = mHandler.obtainMessage(what); 1920 mHandler.sendMessageDelayed(message, mNotificationTimeout); 1921 } 1922 } 1923 1924 /** 1925 * Notifies an accessibility service client for a scheduled event given the event type. 1926 * 1927 * @param eventType The type of the event to dispatch. 1928 */ 1929 private void notifyAccessibilityEventInternal(int eventType) { 1930 IAccessibilityServiceClient listener; 1931 AccessibilityEvent event; 1932 1933 synchronized (mLock) { 1934 listener = mServiceInterface; 1935 1936 // If the service died/was disabled while the message for dispatching 1937 // the accessibility event was propagating the listener may be null. 1938 if (listener == null) { 1939 return; 1940 } 1941 1942 event = mPendingEvents.get(eventType); 1943 1944 // Check for null here because there is a concurrent scenario in which this 1945 // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked 1946 // which posts a message for dispatching an event. 2) The message is pulled 1947 // from the queue by the handler on the service thread and the latter is 1948 // just about to acquire the lock and call this method. 3) Now another binder 1949 // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked 1950 // so the service thread waits for the lock; 4) The binder thread replaces 1951 // the event with a more recent one (assume the same event type) and posts a 1952 // dispatch request releasing the lock. 5) Now the main thread is unblocked and 1953 // dispatches the event which is removed from the pending ones. 6) And ... now 1954 // the service thread handles the last message posted by the last binder call 1955 // but the event is already dispatched and hence looking it up in the pending 1956 // ones yields null. This check is much simpler that keeping count for each 1957 // event type of each service to catch such a scenario since only one message 1958 // is processed at a time. 1959 if (event == null) { 1960 return; 1961 } 1962 1963 mPendingEvents.remove(eventType); 1964 if (mSecurityPolicy.canRetrieveWindowContent(this)) { 1965 event.setConnectionId(mId); 1966 } else { 1967 event.setSource(null); 1968 } 1969 event.setSealed(true); 1970 } 1971 1972 try { 1973 listener.onAccessibilityEvent(event); 1974 if (DEBUG) { 1975 Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); 1976 } 1977 } catch (RemoteException re) { 1978 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); 1979 } finally { 1980 event.recycle(); 1981 } 1982 } 1983 1984 public void notifyGesture(int gestureId) { 1985 mHandler.obtainMessage(MSG_ON_GESTURE, gestureId, 0).sendToTarget(); 1986 } 1987 1988 private void notifyGestureInternal(int gestureId) { 1989 IAccessibilityServiceClient listener = mServiceInterface; 1990 if (listener != null) { 1991 try { 1992 listener.onGesture(gestureId); 1993 } catch (RemoteException re) { 1994 Slog.e(LOG_TAG, "Error during sending gesture " + gestureId 1995 + " to " + mService, re); 1996 } 1997 } 1998 } 1999 2000 private void sendDownAndUpKeyEvents(int keyCode) { 2001 final long token = Binder.clearCallingIdentity(); 2002 2003 // Inject down. 2004 final long downTime = SystemClock.uptimeMillis(); 2005 KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, 2006 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 2007 InputDevice.SOURCE_KEYBOARD, null); 2008 InputManager.getInstance().injectInputEvent(down, 2009 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 2010 down.recycle(); 2011 2012 // Inject up. 2013 final long upTime = SystemClock.uptimeMillis(); 2014 KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0, 2015 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 2016 InputDevice.SOURCE_KEYBOARD, null); 2017 InputManager.getInstance().injectInputEvent(up, 2018 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 2019 up.recycle(); 2020 2021 Binder.restoreCallingIdentity(token); 2022 } 2023 2024 private void expandNotifications() { 2025 final long token = Binder.clearCallingIdentity(); 2026 2027 StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 2028 android.app.Service.STATUS_BAR_SERVICE); 2029 statusBarManager.expandNotifications(); 2030 2031 Binder.restoreCallingIdentity(token); 2032 } 2033 2034 private void expandQuickSettings() { 2035 final long token = Binder.clearCallingIdentity(); 2036 2037 StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 2038 android.app.Service.STATUS_BAR_SERVICE); 2039 statusBarManager.expandQuickSettings(); 2040 2041 Binder.restoreCallingIdentity(token); 2042 } 2043 2044 private void openRecents() { 2045 final long token = Binder.clearCallingIdentity(); 2046 2047 IStatusBarService statusBarService = IStatusBarService.Stub.asInterface( 2048 ServiceManager.getService("statusbar")); 2049 try { 2050 statusBarService.toggleRecentApps(); 2051 } catch (RemoteException e) { 2052 Slog.e(LOG_TAG, "Error toggling recent apps."); 2053 } 2054 2055 Binder.restoreCallingIdentity(token); 2056 } 2057 2058 private IAccessibilityInteractionConnection getConnectionLocked(int windowId) { 2059 if (DEBUG) { 2060 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId); 2061 } 2062 AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId); 2063 if (wrapper == null) { 2064 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId); 2065 } 2066 if (wrapper != null && wrapper.mConnection != null) { 2067 return wrapper.mConnection; 2068 } 2069 if (DEBUG) { 2070 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId); 2071 } 2072 return null; 2073 } 2074 2075 private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { 2076 if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) { 2077 return mSecurityPolicy.mActiveWindowId; 2078 } 2079 return accessibilityWindowId; 2080 } 2081 2082 private float getCompatibilityScale(int windowId) { 2083 try { 2084 IBinder windowToken = mGlobalWindowTokens.get(windowId); 2085 if (windowToken != null) { 2086 return mWindowManagerService.getWindowCompatibilityScale(windowToken); 2087 } 2088 windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId); 2089 if (windowToken != null) { 2090 return mWindowManagerService.getWindowCompatibilityScale(windowToken); 2091 } 2092 } catch (RemoteException re) { 2093 /* ignore */ 2094 } 2095 return 1.0f; 2096 } 2097 } 2098 2099 final class SecurityPolicy { 2100 private static final int VALID_ACTIONS = 2101 AccessibilityNodeInfo.ACTION_CLICK 2102 | AccessibilityNodeInfo.ACTION_LONG_CLICK 2103 | AccessibilityNodeInfo.ACTION_FOCUS 2104 | AccessibilityNodeInfo.ACTION_CLEAR_FOCUS 2105 | AccessibilityNodeInfo.ACTION_SELECT 2106 | AccessibilityNodeInfo.ACTION_CLEAR_SELECTION 2107 | AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS 2108 | AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS 2109 | AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY 2110 | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY 2111 | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT 2112 | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT 2113 | AccessibilityNodeInfo.ACTION_SCROLL_FORWARD 2114 | AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD; 2115 2116 private static final int RETRIEVAL_ALLOWING_EVENT_TYPES = 2117 AccessibilityEvent.TYPE_VIEW_CLICKED 2118 | AccessibilityEvent.TYPE_VIEW_FOCUSED 2119 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 2120 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 2121 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 2122 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 2123 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 2124 | AccessibilityEvent.TYPE_VIEW_SELECTED 2125 | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED 2126 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 2127 | AccessibilityEvent.TYPE_VIEW_SCROLLED 2128 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 2129 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED; 2130 2131 private int mActiveWindowId; 2132 2133 private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) { 2134 // Send window changed event only for the retrieval allowing window. 2135 return (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED 2136 || event.getWindowId() == mActiveWindowId); 2137 } 2138 2139 public void updateEventSourceLocked(AccessibilityEvent event) { 2140 if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) { 2141 event.setSource(null); 2142 } 2143 } 2144 2145 public void updateActiveWindow(int windowId, int eventType) { 2146 // The active window is either the window that has input focus or 2147 // the window that the user is currently touching. If the user is 2148 // touching a window that does not have input focus as soon as the 2149 // the user stops touching that window the focused window becomes 2150 // the active one. 2151 switch (eventType) { 2152 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: { 2153 if (getFocusedWindowId() == windowId) { 2154 mActiveWindowId = windowId; 2155 } 2156 } break; 2157 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: 2158 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: { 2159 mActiveWindowId = windowId; 2160 } break; 2161 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END: { 2162 mActiveWindowId = getFocusedWindowId(); 2163 } break; 2164 } 2165 } 2166 2167 public int getRetrievalAllowingWindowLocked() { 2168 return mActiveWindowId; 2169 } 2170 2171 public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) { 2172 return canRetrieveWindowContent(service) && isRetrievalAllowingWindow(windowId); 2173 } 2174 2175 public boolean canPerformActionLocked(Service service, int windowId, int action, 2176 Bundle arguments) { 2177 return canRetrieveWindowContent(service) 2178 && isRetrievalAllowingWindow(windowId) 2179 && isActionPermitted(action); 2180 } 2181 2182 public boolean canRetrieveWindowContent(Service service) { 2183 return service.mCanRetrieveScreenContent; 2184 } 2185 2186 public void enforceCanRetrieveWindowContent(Service service) throws RemoteException { 2187 // This happens due to incorrect registration so make it apparent. 2188 if (!canRetrieveWindowContent(service)) { 2189 Slog.e(LOG_TAG, "Accessibility serivce " + service.mComponentName + " does not " + 2190 "declare android:canRetrieveWindowContent."); 2191 throw new RemoteException(); 2192 } 2193 } 2194 2195 public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) { 2196 final int callingUid = Binder.getCallingUid(); 2197 if (callingUid == Process.SYSTEM_UID 2198 || callingUid == Process.SHELL_UID) { 2199 return mCurrentUserId; 2200 } 2201 final int callingUserId = UserHandle.getUserId(callingUid); 2202 if (callingUserId == userId) { 2203 return userId; 2204 } 2205 if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS) 2206 && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) { 2207 throw new SecurityException("Call from user " + callingUserId + " as user " 2208 + userId + " without permission INTERACT_ACROSS_USERS or " 2209 + "INTERACT_ACROSS_USERS_FULL not allowed."); 2210 } 2211 if (userId == UserHandle.USER_CURRENT 2212 || userId == UserHandle.USER_CURRENT_OR_SELF) { 2213 return mCurrentUserId; 2214 } 2215 throw new IllegalArgumentException("Calling user can be changed to only " 2216 + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF."); 2217 } 2218 2219 public boolean isCallerInteractingAcrossUsers(int userId) { 2220 final int callingUid = Binder.getCallingUid(); 2221 return (Binder.getCallingPid() == android.os.Process.myPid() 2222 || callingUid == Process.SHELL_UID 2223 || userId == UserHandle.USER_CURRENT 2224 || userId == UserHandle.USER_CURRENT_OR_SELF); 2225 } 2226 2227 private boolean isRetrievalAllowingWindow(int windowId) { 2228 return (mActiveWindowId == windowId); 2229 } 2230 2231 private boolean isActionPermitted(int action) { 2232 return (VALID_ACTIONS & action) != 0; 2233 } 2234 2235 private void enforceCallingPermission(String permission, String function) { 2236 if (OWN_PROCESS_ID == Binder.getCallingPid()) { 2237 return; 2238 } 2239 if (!hasPermission(permission)) { 2240 throw new SecurityException("You do not have " + permission 2241 + " required to call " + function); 2242 } 2243 } 2244 2245 private boolean hasPermission(String permission) { 2246 return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED; 2247 } 2248 2249 private int getFocusedWindowId() { 2250 try { 2251 // We call this only on window focus change or after touch 2252 // exploration gesture end and the shown windows are not that 2253 // many, so the linear look up is just fine. 2254 IBinder token = mWindowManagerService.getFocusedWindowToken(); 2255 if (token != null) { 2256 synchronized (mLock) { 2257 int windowId = getFocusedWindowIdLocked(token, mGlobalWindowTokens); 2258 if (windowId < 0) { 2259 windowId = getFocusedWindowIdLocked(token, 2260 getCurrentUserStateLocked().mWindowTokens); 2261 } 2262 return windowId; 2263 } 2264 } 2265 } catch (RemoteException re) { 2266 /* ignore */ 2267 } 2268 return -1; 2269 } 2270 2271 private int getFocusedWindowIdLocked(IBinder token, SparseArray<IBinder> windows) { 2272 final int windowCount = windows.size(); 2273 for (int i = 0; i < windowCount; i++) { 2274 if (windows.valueAt(i) == token) { 2275 return windows.keyAt(i); 2276 } 2277 } 2278 return -1; 2279 } 2280 } 2281 2282 private class UserState { 2283 public final int mUserId; 2284 2285 public final CopyOnWriteArrayList<Service> mServices = new CopyOnWriteArrayList<Service>(); 2286 2287 public final RemoteCallbackList<IAccessibilityManagerClient> mClients = 2288 new RemoteCallbackList<IAccessibilityManagerClient>(); 2289 2290 public final Map<ComponentName, Service> mComponentNameToServiceMap = 2291 new HashMap<ComponentName, Service>(); 2292 2293 public final List<AccessibilityServiceInfo> mInstalledServices = 2294 new ArrayList<AccessibilityServiceInfo>(); 2295 2296 public final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>(); 2297 2298 public final Set<ComponentName> mTouchExplorationGrantedServices = 2299 new HashSet<ComponentName>(); 2300 2301 public final SparseArray<AccessibilityConnectionWrapper> 2302 mInteractionConnections = 2303 new SparseArray<AccessibilityConnectionWrapper>(); 2304 2305 public final SparseArray<IBinder> mWindowTokens = new SparseArray<IBinder>(); 2306 2307 public int mHandledFeedbackTypes = 0; 2308 2309 public boolean mIsAccessibilityEnabled; 2310 public boolean mIsTouchExplorationEnabled; 2311 public boolean mIsDisplayMagnificationEnabled; 2312 2313 public UserState(int userId) { 2314 mUserId = userId; 2315 } 2316 } 2317 2318 private class TempUserStateChangeMemento { 2319 public int mUserId = UserHandle.USER_NULL; 2320 public boolean mIsAccessibilityEnabled; 2321 public boolean mIsTouchExplorationEnabled; 2322 public boolean mIsDisplayMagnificationEnabled; 2323 public final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>(); 2324 public final Set<ComponentName> mTouchExplorationGrantedServices = 2325 new HashSet<ComponentName>(); 2326 2327 public void initialize(int userId, UserState userState) { 2328 mUserId = userId; 2329 mIsAccessibilityEnabled = userState.mIsAccessibilityEnabled; 2330 mIsTouchExplorationEnabled = userState.mIsTouchExplorationEnabled; 2331 mIsDisplayMagnificationEnabled = userState.mIsDisplayMagnificationEnabled; 2332 mEnabledServices.clear(); 2333 mEnabledServices.addAll(userState.mEnabledServices); 2334 mTouchExplorationGrantedServices.clear(); 2335 mTouchExplorationGrantedServices.addAll(userState.mTouchExplorationGrantedServices); 2336 } 2337 2338 public void applyTo(UserState userState) { 2339 userState.mIsAccessibilityEnabled = mIsAccessibilityEnabled; 2340 userState.mIsTouchExplorationEnabled = mIsTouchExplorationEnabled; 2341 userState.mIsDisplayMagnificationEnabled = mIsDisplayMagnificationEnabled; 2342 userState.mEnabledServices.clear(); 2343 userState.mEnabledServices.addAll(mEnabledServices); 2344 userState.mTouchExplorationGrantedServices.clear(); 2345 userState.mTouchExplorationGrantedServices.addAll(mTouchExplorationGrantedServices); 2346 } 2347 2348 public void clear() { 2349 mUserId = UserHandle.USER_NULL; 2350 mIsAccessibilityEnabled = false; 2351 mIsTouchExplorationEnabled = false; 2352 mIsDisplayMagnificationEnabled = false; 2353 mEnabledServices.clear(); 2354 mTouchExplorationGrantedServices.clear(); 2355 } 2356 } 2357 2358 private final class AccessibilityContentObserver extends ContentObserver { 2359 2360 private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor( 2361 Settings.Secure.ACCESSIBILITY_ENABLED); 2362 2363 private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor( 2364 Settings.Secure.TOUCH_EXPLORATION_ENABLED); 2365 2366 private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor( 2367 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); 2368 2369 private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor( 2370 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 2371 2372 private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure 2373 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); 2374 2375 public AccessibilityContentObserver(Handler handler) { 2376 super(handler); 2377 } 2378 2379 public void register(ContentResolver contentResolver) { 2380 contentResolver.registerContentObserver(mAccessibilityEnabledUri, 2381 false, this, UserHandle.USER_ALL); 2382 contentResolver.registerContentObserver(mTouchExplorationEnabledUri, 2383 false, this, UserHandle.USER_ALL); 2384 contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri, 2385 false, this, UserHandle.USER_ALL); 2386 contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri, 2387 false, this, UserHandle.USER_ALL); 2388 contentResolver.registerContentObserver( 2389 mTouchExplorationGrantedAccessibilityServicesUri, 2390 false, this, UserHandle.USER_ALL); 2391 } 2392 2393 @Override 2394 public void onChange(boolean selfChange, Uri uri) { 2395 if (mAccessibilityEnabledUri.equals(uri)) { 2396 synchronized (mLock) { 2397 // We will update when the automation service dies. 2398 if (mUiAutomationService == null) { 2399 UserState userState = getCurrentUserStateLocked(); 2400 handleAccessibilityEnabledSettingChangedLocked(userState); 2401 performServiceManagementLocked(userState); 2402 updateInputFilterLocked(userState); 2403 scheduleSendStateToClientsLocked(userState); 2404 } 2405 } 2406 } else if (mTouchExplorationEnabledUri.equals(uri)) { 2407 synchronized (mLock) { 2408 // We will update when the automation service dies. 2409 if (mUiAutomationService == null) { 2410 UserState userState = getCurrentUserStateLocked(); 2411 handleTouchExplorationEnabledSettingChangedLocked(userState); 2412 updateInputFilterLocked(userState); 2413 scheduleSendStateToClientsLocked(userState); 2414 } 2415 } 2416 } else if (mDisplayMagnificationEnabledUri.equals(uri)) { 2417 synchronized (mLock) { 2418 // We will update when the automation service dies. 2419 if (mUiAutomationService == null) { 2420 UserState userState = getCurrentUserStateLocked(); 2421 handleDisplayMagnificationEnabledSettingChangedLocked(userState); 2422 updateInputFilterLocked(userState); 2423 scheduleSendStateToClientsLocked(userState); 2424 } 2425 } 2426 } else if (mEnabledAccessibilityServicesUri.equals(uri)) { 2427 synchronized (mLock) { 2428 // We will update when the automation service dies. 2429 if (mUiAutomationService == null) { 2430 UserState userState = getCurrentUserStateLocked(); 2431 populateEnabledAccessibilityServicesLocked(userState); 2432 manageServicesLocked(userState); 2433 } 2434 } 2435 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) { 2436 synchronized (mLock) { 2437 // We will update when the automation service dies. 2438 if (mUiAutomationService == null) { 2439 UserState userState = getCurrentUserStateLocked(); 2440 populateTouchExplorationGrantedAccessibilityServicesLocked(userState); 2441 handleTouchExplorationGrantedAccessibilityServicesChangedLocked(userState); 2442 } 2443 } 2444 } 2445 } 2446 } 2447} 2448