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 17 package com.android.server.accessibility; 18 19 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; 20 21 import android.Manifest; 22 import android.accessibilityservice.AccessibilityService; 23 import android.accessibilityservice.AccessibilityServiceInfo; 24 import android.accessibilityservice.IAccessibilityServiceClient; 25 import android.accessibilityservice.IAccessibilityServiceConnection; 26 import android.app.AlertDialog; 27 import android.app.PendingIntent; 28 import android.app.StatusBarManager; 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentName; 31 import android.content.ContentResolver; 32 import android.content.Context; 33 import android.content.DialogInterface; 34 import android.content.DialogInterface.OnClickListener; 35 import android.content.Intent; 36 import android.content.IntentFilter; 37 import android.content.ServiceConnection; 38 import android.content.pm.PackageManager; 39 import android.content.pm.ResolveInfo; 40 import android.content.pm.ServiceInfo; 41 import android.content.pm.UserInfo; 42 import android.database.ContentObserver; 43 import android.graphics.Point; 44 import android.graphics.Rect; 45 import android.graphics.Region; 46 import android.hardware.display.DisplayManager; 47 import android.hardware.input.InputManager; 48 import android.net.Uri; 49 import android.os.Binder; 50 import android.os.Build; 51 import android.os.Bundle; 52 import android.os.Handler; 53 import android.os.IBinder; 54 import android.os.Looper; 55 import android.os.Message; 56 import android.os.Process; 57 import android.os.RemoteCallbackList; 58 import android.os.RemoteException; 59 import android.os.ServiceManager; 60 import android.os.SystemClock; 61 import android.os.UserHandle; 62 import android.os.UserManager; 63 import android.provider.Settings; 64 import android.text.TextUtils; 65 import android.text.TextUtils.SimpleStringSplitter; 66 import android.util.Pools.Pool; 67 import android.util.Pools.SimplePool; 68 import android.util.Slog; 69 import android.util.SparseArray; 70 import android.view.Display; 71 import android.view.IWindow; 72 import android.view.InputDevice; 73 import android.view.InputEventConsistencyVerifier; 74 import android.view.KeyCharacterMap; 75 import android.view.KeyEvent; 76 import android.view.MagnificationSpec; 77 import android.view.WindowInfo; 78 import android.view.WindowManager; 79 import android.view.WindowManagerInternal; 80 import android.view.WindowManagerPolicy; 81 import android.view.accessibility.AccessibilityEvent; 82 import android.view.accessibility.AccessibilityInteractionClient; 83 import android.view.accessibility.AccessibilityManager; 84 import android.view.accessibility.AccessibilityNodeInfo; 85 import android.view.accessibility.AccessibilityWindowInfo; 86 import android.view.accessibility.IAccessibilityInteractionConnection; 87 import android.view.accessibility.IAccessibilityInteractionConnectionCallback; 88 import android.view.accessibility.IAccessibilityManager; 89 import android.view.accessibility.IAccessibilityManagerClient; 90 91 import com.android.internal.R; 92 import com.android.internal.content.PackageMonitor; 93 import com.android.internal.statusbar.IStatusBarService; 94 import com.android.internal.widget.LockPatternUtils; 95 import com.android.server.LocalServices; 96 97 import org.xmlpull.v1.XmlPullParserException; 98 99 import java.io.FileDescriptor; 100 import java.io.IOException; 101 import java.io.PrintWriter; 102 import java.util.ArrayList; 103 import java.util.Arrays; 104 import java.util.Collections; 105 import java.util.HashMap; 106 import java.util.HashSet; 107 import java.util.Iterator; 108 import java.util.List; 109 import java.util.Map; 110 import java.util.Set; 111 import java.util.concurrent.CopyOnWriteArrayList; 112 113 /** 114 * This class is instantiated by the system as a system level service and can be 115 * accessed only by the system. The task of this service is to be a centralized 116 * event dispatch for {@link AccessibilityEvent}s generated across all processes 117 * on the device. Events are dispatched to {@link AccessibilityService}s. 118 */ 119 public class AccessibilityManagerService extends IAccessibilityManager.Stub { 120 121 private static final boolean DEBUG = false; 122 123 private static final String LOG_TAG = "AccessibilityManagerService"; 124 125 // TODO: This is arbitrary. When there is time implement this by watching 126 // when that accessibility services are bound. 127 private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000; 128 129 private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000; 130 131 private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE = 132 "registerUiTestAutomationService"; 133 134 private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED = 135 "temporaryEnableAccessibilityStateUntilKeyguardRemoved"; 136 137 private static final String GET_WINDOW_TOKEN = "getWindowToken"; 138 139 private static final ComponentName sFakeAccessibilityServiceComponentName = 140 new ComponentName("foo.bar", "FakeService"); 141 142 private static final String FUNCTION_DUMP = "dump"; 143 144 private static final char COMPONENT_NAME_SEPARATOR = ':'; 145 146 private static final int OWN_PROCESS_ID = android.os.Process.myPid(); 147 148 private static final int MAX_POOL_SIZE = 10; 149 150 private static final int WINDOW_ID_UNKNOWN = -1; 151 152 private static int sIdCounter = 0; 153 154 private static int sNextWindowId; 155 156 private final Context mContext; 157 158 private final Object mLock = new Object(); 159 160 private final Pool<PendingEvent> mPendingEventPool = 161 new SimplePool<>(MAX_POOL_SIZE); 162 163 private final SimpleStringSplitter mStringColonSplitter = 164 new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); 165 166 private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = 167 new ArrayList<>(); 168 169 private final Region mTempRegion = new Region(); 170 171 private final Rect mTempRect = new Rect(); 172 173 private final Rect mTempRect1 = new Rect(); 174 175 private final Point mTempPoint = new Point(); 176 177 private final PackageManager mPackageManager; 178 179 private final WindowManagerInternal mWindowManagerService; 180 181 private final SecurityPolicy mSecurityPolicy; 182 183 private final MainHandler mMainHandler; 184 185 private InteractionBridge mInteractionBridge; 186 187 private AlertDialog mEnableTouchExplorationDialog; 188 189 private AccessibilityInputFilter mInputFilter; 190 191 private boolean mHasInputFilter; 192 193 private final Set<ComponentName> mTempComponentNameSet = new HashSet<>(); 194 195 private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList = 196 new ArrayList<>(); 197 198 private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients = 199 new RemoteCallbackList<>(); 200 201 private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections = 202 new SparseArray<>(); 203 204 private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>(); 205 206 private final SparseArray<UserState> mUserStates = new SparseArray<>(); 207 208 private final UserManager mUserManager; 209 210 private final LockPatternUtils mLockPatternUtils; 211 212 private int mCurrentUserId = UserHandle.USER_OWNER; 213 214 //TODO: Remove this hack 215 private boolean mInitialized; 216 217 private WindowsForAccessibilityCallback mWindowsForAccessibilityCallback; 218 219 private UserState getCurrentUserStateLocked() { 220 return getUserStateLocked(mCurrentUserId); 221 } 222 223 /** 224 * Creates a new instance. 225 * 226 * @param context A {@link Context} instance. 227 */ 228 public AccessibilityManagerService(Context context) { 229 mContext = context; 230 mPackageManager = mContext.getPackageManager(); 231 mWindowManagerService = LocalServices.getService(WindowManagerInternal.class); 232 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 233 mSecurityPolicy = new SecurityPolicy(); 234 mMainHandler = new MainHandler(mContext.getMainLooper()); 235 mLockPatternUtils = new LockPatternUtils(context); 236 registerBroadcastReceivers(); 237 new AccessibilityContentObserver(mMainHandler).register( 238 context.getContentResolver()); 239 } 240 241 private UserState getUserStateLocked(int userId) { 242 UserState state = mUserStates.get(userId); 243 if (state == null) { 244 state = new UserState(userId); 245 mUserStates.put(userId, state); 246 } 247 return state; 248 } 249 250 private void registerBroadcastReceivers() { 251 PackageMonitor monitor = new PackageMonitor() { 252 @Override 253 public void onSomePackagesChanged() { 254 synchronized (mLock) { 255 // Only the profile parent can install accessibility services. 256 // Therefore we ignore packages from linked profiles. 257 if (getChangingUserId() != mCurrentUserId) { 258 return; 259 } 260 // We will update when the automation service dies. 261 UserState userState = getCurrentUserStateLocked(); 262 // We have to reload the installed services since some services may 263 // have different attributes, resolve info (does not support equals), 264 // etc. Remove them then to force reload. Do it even if automation is 265 // running since when it goes away, we will have to reload as well. 266 userState.mInstalledServices.clear(); 267 if (userState.mUiAutomationService == null) { 268 if (readConfigurationForUserStateLocked(userState)) { 269 onUserStateChangedLocked(userState); 270 } 271 } 272 } 273 } 274 275 @Override 276 public void onPackageRemoved(String packageName, int uid) { 277 synchronized (mLock) { 278 final int userId = getChangingUserId(); 279 // Only the profile parent can install accessibility services. 280 // Therefore we ignore packages from linked profiles. 281 if (userId != mCurrentUserId) { 282 return; 283 } 284 UserState userState = getUserStateLocked(userId); 285 Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 286 while (it.hasNext()) { 287 ComponentName comp = it.next(); 288 String compPkg = comp.getPackageName(); 289 if (compPkg.equals(packageName)) { 290 it.remove(); 291 // Update the enabled services setting. 292 persistComponentNamesToSettingLocked( 293 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 294 userState.mEnabledServices, userId); 295 // Update the touch exploration granted services setting. 296 userState.mTouchExplorationGrantedServices.remove(comp); 297 persistComponentNamesToSettingLocked( 298 Settings.Secure. 299 TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 300 userState.mTouchExplorationGrantedServices, userId); 301 // We will update when the automation service dies. 302 if (userState.mUiAutomationService == null) { 303 onUserStateChangedLocked(userState); 304 } 305 return; 306 } 307 } 308 } 309 } 310 311 @Override 312 public boolean onHandleForceStop(Intent intent, String[] packages, 313 int uid, boolean doit) { 314 synchronized (mLock) { 315 final int userId = getChangingUserId(); 316 // Only the profile parent can install accessibility services. 317 // Therefore we ignore packages from linked profiles. 318 if (userId != mCurrentUserId) { 319 return false; 320 } 321 UserState userState = getUserStateLocked(userId); 322 Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 323 while (it.hasNext()) { 324 ComponentName comp = it.next(); 325 String compPkg = comp.getPackageName(); 326 for (String pkg : packages) { 327 if (compPkg.equals(pkg)) { 328 if (!doit) { 329 return true; 330 } 331 it.remove(); 332 persistComponentNamesToSettingLocked( 333 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 334 userState.mEnabledServices, userId); 335 // We will update when the automation service dies. 336 if (userState.mUiAutomationService == null) { 337 onUserStateChangedLocked(userState); 338 } 339 } 340 } 341 } 342 return false; 343 } 344 } 345 }; 346 347 // package changes 348 monitor.register(mContext, null, UserHandle.ALL, true); 349 350 // user change and unlock 351 IntentFilter intentFilter = new IntentFilter(); 352 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 353 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 354 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 355 356 mContext.registerReceiverAsUser(new BroadcastReceiver() { 357 @Override 358 public void onReceive(Context context, Intent intent) { 359 String action = intent.getAction(); 360 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 361 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 362 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 363 removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 364 } else if (Intent.ACTION_USER_PRESENT.equals(action)) { 365 // We will update when the automation service dies. 366 UserState userState = getCurrentUserStateLocked(); 367 if (userState.mUiAutomationService == null) { 368 if (readConfigurationForUserStateLocked(userState)) { 369 onUserStateChangedLocked(userState); 370 } 371 } 372 } 373 } 374 }, UserHandle.ALL, intentFilter, null, null); 375 } 376 377 @Override 378 public int addClient(IAccessibilityManagerClient client, int userId) { 379 synchronized (mLock) { 380 // We treat calls from a profile as if made by its parent as profiles 381 // share the accessibility state of the parent. The call below 382 // performs the current profile parent resolution. 383 final int resolvedUserId = mSecurityPolicy 384 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 385 // If the client is from a process that runs across users such as 386 // the system UI or the system we add it to the global state that 387 // is shared across users. 388 UserState userState = getUserStateLocked(resolvedUserId); 389 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 390 mGlobalClients.register(client); 391 if (DEBUG) { 392 Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid()); 393 } 394 return userState.getClientState(); 395 } else { 396 userState.mClients.register(client); 397 // If this client is not for the current user we do not 398 // return a state since it is not for the foreground user. 399 // We will send the state to the client on a user switch. 400 if (DEBUG) { 401 Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid() 402 + " and userId:" + mCurrentUserId); 403 } 404 return (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0; 405 } 406 } 407 } 408 409 @Override 410 public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) { 411 synchronized (mLock) { 412 // We treat calls from a profile as if made by its parent as profiles 413 // share the accessibility state of the parent. The call below 414 // performs the current profile parent resolution.. 415 final int resolvedUserId = mSecurityPolicy 416 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 417 // This method does nothing for a background user. 418 if (resolvedUserId != mCurrentUserId) { 419 return true; // yes, recycle the event 420 } 421 if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) { 422 mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(event.getWindowId(), 423 event.getSourceNodeId(), event.getEventType()); 424 mSecurityPolicy.updateEventSourceLocked(event); 425 notifyAccessibilityServicesDelayedLocked(event, false); 426 notifyAccessibilityServicesDelayedLocked(event, true); 427 } 428 if (mHasInputFilter && mInputFilter != null) { 429 mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER, 430 AccessibilityEvent.obtain(event)).sendToTarget(); 431 } 432 event.recycle(); 433 getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0; 434 } 435 return (OWN_PROCESS_ID != Binder.getCallingPid()); 436 } 437 438 @Override 439 public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) { 440 synchronized (mLock) { 441 // We treat calls from a profile as if made by its parent as profiles 442 // share the accessibility state of the parent. The call below 443 // performs the current profile parent resolution. 444 final int resolvedUserId = mSecurityPolicy 445 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 446 // The automation service is a fake one and should not be reported 447 // to clients as being installed - it really is not. 448 UserState userState = getUserStateLocked(resolvedUserId); 449 if (userState.mUiAutomationService != null) { 450 List<AccessibilityServiceInfo> installedServices = new ArrayList<>(); 451 installedServices.addAll(userState.mInstalledServices); 452 installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo); 453 return installedServices; 454 } 455 return userState.mInstalledServices; 456 } 457 } 458 459 @Override 460 public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, 461 int userId) { 462 List<AccessibilityServiceInfo> result = null; 463 synchronized (mLock) { 464 // We treat calls from a profile as if made by its parent as profiles 465 // share the accessibility state of the parent. The call below 466 // performs the current profile parent resolution. 467 final int resolvedUserId = mSecurityPolicy 468 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 469 470 // The automation service is a fake one and should not be reported 471 // to clients as being enabled. The automation service is always the 472 // only active one, if it exists. 473 UserState userState = getUserStateLocked(resolvedUserId); 474 if (userState.mUiAutomationService != null) { 475 return Collections.emptyList(); 476 } 477 478 result = mEnabledServicesForFeedbackTempList; 479 result.clear(); 480 List<Service> services = userState.mBoundServices; 481 while (feedbackType != 0) { 482 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType)); 483 feedbackType &= ~feedbackTypeBit; 484 final int serviceCount = services.size(); 485 for (int i = 0; i < serviceCount; i++) { 486 Service service = services.get(i); 487 if ((service.mFeedbackType & feedbackTypeBit) != 0) { 488 result.add(service.mAccessibilityServiceInfo); 489 } 490 } 491 } 492 } 493 return result; 494 } 495 496 @Override 497 public void interrupt(int userId) { 498 CopyOnWriteArrayList<Service> services; 499 synchronized (mLock) { 500 // We treat calls from a profile as if made by its parent as profiles 501 // share the accessibility state of the parent. The call below 502 // performs the current profile parent resolution. 503 final int resolvedUserId = mSecurityPolicy 504 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 505 // This method does nothing for a background user. 506 if (resolvedUserId != mCurrentUserId) { 507 return; 508 } 509 services = getUserStateLocked(resolvedUserId).mBoundServices; 510 } 511 for (int i = 0, count = services.size(); i < count; i++) { 512 Service service = services.get(i); 513 try { 514 service.mServiceInterface.onInterrupt(); 515 } catch (RemoteException re) { 516 Slog.e(LOG_TAG, "Error during sending interrupt request to " 517 + service.mService, re); 518 } 519 } 520 } 521 522 @Override 523 public int addAccessibilityInteractionConnection(IWindow windowToken, 524 IAccessibilityInteractionConnection connection, int userId) throws RemoteException { 525 synchronized (mLock) { 526 // We treat calls from a profile as if made by its parent as profiles 527 // share the accessibility state of the parent. The call below 528 // performs the current profile parent resolution. 529 final int resolvedUserId = mSecurityPolicy 530 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 531 final int windowId = sNextWindowId++; 532 // If the window is from a process that runs across users such as 533 // the system UI or the system we add it to the global state that 534 // is shared across users. 535 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 536 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 537 windowId, connection, UserHandle.USER_ALL); 538 wrapper.linkToDeath(); 539 mGlobalInteractionConnections.put(windowId, wrapper); 540 mGlobalWindowTokens.put(windowId, windowToken.asBinder()); 541 if (DEBUG) { 542 Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid() 543 + " with windowId: " + windowId + " and token: " + windowToken.asBinder()); 544 } 545 } else { 546 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 547 windowId, connection, resolvedUserId); 548 wrapper.linkToDeath(); 549 UserState userState = getUserStateLocked(resolvedUserId); 550 userState.mInteractionConnections.put(windowId, wrapper); 551 userState.mWindowTokens.put(windowId, windowToken.asBinder()); 552 if (DEBUG) { 553 Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid() 554 + " with windowId: " + windowId + " and userId:" + mCurrentUserId 555 + " and token: " + windowToken.asBinder()); 556 } 557 } 558 return windowId; 559 } 560 } 561 562 @Override 563 public void removeAccessibilityInteractionConnection(IWindow window) { 564 synchronized (mLock) { 565 // We treat calls from a profile as if made by its parent as profiles 566 // share the accessibility state of the parent. The call below 567 // performs the current profile parent resolution. 568 mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( 569 UserHandle.getCallingUserId()); 570 IBinder token = window.asBinder(); 571 final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked( 572 token, mGlobalWindowTokens, mGlobalInteractionConnections); 573 if (removedWindowId >= 0) { 574 if (DEBUG) { 575 Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid() 576 + " with windowId: " + removedWindowId + " and token: " + window.asBinder()); 577 } 578 return; 579 } 580 final int userCount = mUserStates.size(); 581 for (int i = 0; i < userCount; i++) { 582 UserState userState = mUserStates.valueAt(i); 583 final int removedWindowIdForUser = 584 removeAccessibilityInteractionConnectionInternalLocked( 585 token, userState.mWindowTokens, userState.mInteractionConnections); 586 if (removedWindowIdForUser >= 0) { 587 if (DEBUG) { 588 Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid() 589 + " with windowId: " + removedWindowIdForUser + " and userId:" 590 + mUserStates.keyAt(i) + " and token: " + window.asBinder()); 591 } 592 return; 593 } 594 } 595 } 596 } 597 598 private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, 599 SparseArray<IBinder> windowTokens, 600 SparseArray<AccessibilityConnectionWrapper> interactionConnections) { 601 final int count = windowTokens.size(); 602 for (int i = 0; i < count; i++) { 603 if (windowTokens.valueAt(i) == windowToken) { 604 final int windowId = windowTokens.keyAt(i); 605 windowTokens.removeAt(i); 606 AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId); 607 wrapper.unlinkToDeath(); 608 interactionConnections.remove(windowId); 609 return windowId; 610 } 611 } 612 return -1; 613 } 614 615 @Override 616 public void registerUiTestAutomationService(IBinder owner, 617 IAccessibilityServiceClient serviceClient, 618 AccessibilityServiceInfo accessibilityServiceInfo) { 619 mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT, 620 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE); 621 622 accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName); 623 624 synchronized (mLock) { 625 UserState userState = getCurrentUserStateLocked(); 626 627 if (userState.mUiAutomationService != null) { 628 throw new IllegalStateException("UiAutomationService " + serviceClient 629 + "already registered!"); 630 } 631 632 try { 633 owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0); 634 } catch (RemoteException re) { 635 Slog.e(LOG_TAG, "Couldn't register for the death of a" 636 + " UiTestAutomationService!", re); 637 return; 638 } 639 640 userState.mUiAutomationServiceOwner = owner; 641 userState.mUiAutomationServiceClient = serviceClient; 642 643 // Set the temporary state. 644 userState.mIsAccessibilityEnabled = true; 645 userState.mIsTouchExplorationEnabled = false; 646 userState.mIsEnhancedWebAccessibilityEnabled = false; 647 userState.mIsDisplayMagnificationEnabled = false; 648 userState.mInstalledServices.add(accessibilityServiceInfo); 649 userState.mEnabledServices.clear(); 650 userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName); 651 userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName); 652 653 // Use the new state instead of settings. 654 onUserStateChangedLocked(userState); 655 } 656 } 657 658 @Override 659 public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) { 660 synchronized (mLock) { 661 UserState userState = getCurrentUserStateLocked(); 662 // Automation service is not bound, so pretend it died to perform clean up. 663 if (userState.mUiAutomationService != null 664 && serviceClient != null 665 && userState.mUiAutomationService.mServiceInterface != null 666 && userState.mUiAutomationService.mServiceInterface.asBinder() 667 == serviceClient.asBinder()) { 668 userState.mUiAutomationService.binderDied(); 669 } else { 670 throw new IllegalStateException("UiAutomationService " + serviceClient 671 + " not registered!"); 672 } 673 } 674 } 675 676 @Override 677 public void temporaryEnableAccessibilityStateUntilKeyguardRemoved( 678 ComponentName service, boolean touchExplorationEnabled) { 679 mSecurityPolicy.enforceCallingPermission( 680 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY, 681 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED); 682 if (!mWindowManagerService.isKeyguardLocked()) { 683 return; 684 } 685 synchronized (mLock) { 686 // Set the temporary state. 687 UserState userState = getCurrentUserStateLocked(); 688 689 // This is a nop if UI automation is enabled. 690 if (userState.mUiAutomationService != null) { 691 return; 692 } 693 694 userState.mIsAccessibilityEnabled = true; 695 userState.mIsTouchExplorationEnabled = touchExplorationEnabled; 696 userState.mIsEnhancedWebAccessibilityEnabled = false; 697 userState.mIsDisplayMagnificationEnabled = false; 698 userState.mEnabledServices.clear(); 699 userState.mEnabledServices.add(service); 700 userState.mBindingServices.clear(); 701 userState.mTouchExplorationGrantedServices.clear(); 702 userState.mTouchExplorationGrantedServices.add(service); 703 704 // User the current state instead settings. 705 onUserStateChangedLocked(userState); 706 } 707 } 708 709 @Override 710 public IBinder getWindowToken(int windowId) { 711 mSecurityPolicy.enforceCallingPermission( 712 Manifest.permission.RETRIEVE_WINDOW_TOKEN, 713 GET_WINDOW_TOKEN); 714 synchronized (mLock) { 715 // We treat calls from a profile as if made by its parent as profiles 716 // share the accessibility state of the parent. The call below 717 // performs the current profile parent resolution. 718 final int resolvedUserId = mSecurityPolicy 719 .resolveCallingUserIdEnforcingPermissionsLocked( 720 UserHandle.getCallingUserId()); 721 if (resolvedUserId != mCurrentUserId) { 722 return null; 723 } 724 if (mSecurityPolicy.findWindowById(windowId) == null) { 725 return null; 726 } 727 IBinder token = mGlobalWindowTokens.get(windowId); 728 if (token != null) { 729 return token; 730 } 731 return getCurrentUserStateLocked().mWindowTokens.get(windowId); 732 } 733 } 734 735 boolean onGesture(int gestureId) { 736 synchronized (mLock) { 737 boolean handled = notifyGestureLocked(gestureId, false); 738 if (!handled) { 739 handled = notifyGestureLocked(gestureId, true); 740 } 741 return handled; 742 } 743 } 744 745 boolean notifyKeyEvent(KeyEvent event, int policyFlags) { 746 synchronized (mLock) { 747 KeyEvent localClone = KeyEvent.obtain(event); 748 boolean handled = notifyKeyEventLocked(localClone, policyFlags, false); 749 if (!handled) { 750 handled = notifyKeyEventLocked(localClone, policyFlags, true); 751 } 752 return handled; 753 } 754 } 755 756 /** 757 * Gets a point within the accessibility focused node where we can send down 758 * and up events to perform a click. 759 * 760 * @param outPoint The click point to populate. 761 * @return Whether accessibility a click point was found and set. 762 */ 763 // TODO: (multi-display) Make sure this works for multiple displays. 764 boolean getAccessibilityFocusClickPointInScreen(Point outPoint) { 765 return getInteractionBridgeLocked() 766 .getAccessibilityFocusClickPointInScreenNotLocked(outPoint); 767 } 768 769 /** 770 * Gets the bounds of a window. 771 * 772 * @param outBounds The output to which to write the bounds. 773 */ 774 boolean getWindowBounds(int windowId, Rect outBounds) { 775 IBinder token; 776 synchronized (mLock) { 777 token = mGlobalWindowTokens.get(windowId); 778 if (token == null) { 779 token = getCurrentUserStateLocked().mWindowTokens.get(windowId); 780 } 781 } 782 mWindowManagerService.getWindowFrame(token, outBounds); 783 if (!outBounds.isEmpty()) { 784 return true; 785 } 786 return false; 787 } 788 789 boolean accessibilityFocusOnlyInActiveWindow() { 790 synchronized (mLock) { 791 return mWindowsForAccessibilityCallback == null; 792 } 793 } 794 795 int getActiveWindowId() { 796 return mSecurityPolicy.getActiveWindowId(); 797 } 798 799 void onTouchInteractionStart() { 800 mSecurityPolicy.onTouchInteractionStart(); 801 } 802 803 void onTouchInteractionEnd() { 804 mSecurityPolicy.onTouchInteractionEnd(); 805 } 806 807 void onMagnificationStateChanged() { 808 notifyClearAccessibilityCacheLocked(); 809 } 810 811 private void switchUser(int userId) { 812 synchronized (mLock) { 813 if (mCurrentUserId == userId && mInitialized) { 814 return; 815 } 816 817 // Disconnect from services for the old user. 818 UserState oldUserState = getCurrentUserStateLocked(); 819 oldUserState.onSwitchToAnotherUser(); 820 821 // Disable the local managers for the old user. 822 if (oldUserState.mClients.getRegisteredCallbackCount() > 0) { 823 mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER, 824 oldUserState.mUserId, 0).sendToTarget(); 825 } 826 827 // Announce user changes only if more that one exist. 828 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 829 final boolean announceNewUser = userManager.getUsers().size() > 1; 830 831 // The user changed. 832 mCurrentUserId = userId; 833 834 UserState userState = getCurrentUserStateLocked(); 835 if (userState.mUiAutomationService != null) { 836 // Switching users disables the UI automation service. 837 userState.mUiAutomationService.binderDied(); 838 } 839 840 readConfigurationForUserStateLocked(userState); 841 // Even if reading did not yield change, we have to update 842 // the state since the context in which the current user 843 // state was used has changed since it was inactive. 844 onUserStateChangedLocked(userState); 845 846 if (announceNewUser) { 847 // Schedule announcement of the current user if needed. 848 mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED, 849 WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS); 850 } 851 } 852 } 853 854 private void removeUser(int userId) { 855 synchronized (mLock) { 856 mUserStates.remove(userId); 857 } 858 } 859 860 private InteractionBridge getInteractionBridgeLocked() { 861 if (mInteractionBridge == null) { 862 mInteractionBridge = new InteractionBridge(); 863 } 864 return mInteractionBridge; 865 } 866 867 private boolean notifyGestureLocked(int gestureId, boolean isDefault) { 868 // TODO: Now we are giving the gestures to the last enabled 869 // service that can handle them which is the last one 870 // in our list since we write the last enabled as the 871 // last record in the enabled services setting. Ideally, 872 // the user should make the call which service handles 873 // gestures. However, only one service should handle 874 // gestures to avoid user frustration when different 875 // behavior is observed from different combinations of 876 // enabled accessibility services. 877 UserState state = getCurrentUserStateLocked(); 878 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 879 Service service = state.mBoundServices.get(i); 880 if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) { 881 service.notifyGesture(gestureId); 882 return true; 883 } 884 } 885 return false; 886 } 887 888 private boolean notifyKeyEventLocked(KeyEvent event, int policyFlags, boolean isDefault) { 889 // TODO: Now we are giving the key events to the last enabled 890 // service that can handle them Ideally, the user should 891 // make the call which service handles key events. However, 892 // only one service should handle key events to avoid user 893 // frustration when different behavior is observed from 894 // different combinations of enabled accessibility services. 895 UserState state = getCurrentUserStateLocked(); 896 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 897 Service service = state.mBoundServices.get(i); 898 // Key events are handled only by services that declared 899 // this capability and requested to filter key events. 900 if (!service.mRequestFilterKeyEvents || 901 (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo 902 .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { 903 continue; 904 } 905 if (service.mIsDefault == isDefault) { 906 service.notifyKeyEvent(event, policyFlags); 907 return true; 908 } 909 } 910 return false; 911 } 912 913 private void notifyClearAccessibilityCacheLocked() { 914 UserState state = getCurrentUserStateLocked(); 915 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 916 Service service = state.mBoundServices.get(i); 917 service.notifyClearAccessibilityNodeInfoCache(); 918 } 919 } 920 921 /** 922 * Removes an AccessibilityInteractionConnection. 923 * 924 * @param windowId The id of the window to which the connection is targeted. 925 * @param userId The id of the user owning the connection. UserHandle.USER_ALL 926 * if global. 927 */ 928 private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) { 929 if (userId == UserHandle.USER_ALL) { 930 mGlobalWindowTokens.remove(windowId); 931 mGlobalInteractionConnections.remove(windowId); 932 } else { 933 UserState userState = getCurrentUserStateLocked(); 934 userState.mWindowTokens.remove(windowId); 935 userState.mInteractionConnections.remove(windowId); 936 } 937 if (DEBUG) { 938 Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId); 939 } 940 } 941 942 private boolean readInstalledAccessibilityServiceLocked(UserState userState) { 943 mTempAccessibilityServiceInfoList.clear(); 944 945 List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser( 946 new Intent(AccessibilityService.SERVICE_INTERFACE), 947 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, 948 mCurrentUserId); 949 950 for (int i = 0, count = installedServices.size(); i < count; i++) { 951 ResolveInfo resolveInfo = installedServices.get(i); 952 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 953 if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals( 954 serviceInfo.permission)) { 955 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName( 956 serviceInfo.packageName, serviceInfo.name).flattenToShortString() 957 + ": it does not require the permission " 958 + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE); 959 continue; 960 } 961 AccessibilityServiceInfo accessibilityServiceInfo; 962 try { 963 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext); 964 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo); 965 } catch (XmlPullParserException | IOException xppe) { 966 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe); 967 } 968 } 969 970 if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) { 971 userState.mInstalledServices.clear(); 972 userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList); 973 mTempAccessibilityServiceInfoList.clear(); 974 return true; 975 } 976 977 mTempAccessibilityServiceInfoList.clear(); 978 return false; 979 } 980 981 private boolean readEnabledAccessibilityServicesLocked(UserState userState) { 982 mTempComponentNameSet.clear(); 983 readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 984 userState.mUserId, mTempComponentNameSet); 985 if (!mTempComponentNameSet.equals(userState.mEnabledServices)) { 986 userState.mEnabledServices.clear(); 987 userState.mEnabledServices.addAll(mTempComponentNameSet); 988 mTempComponentNameSet.clear(); 989 return true; 990 } 991 mTempComponentNameSet.clear(); 992 return false; 993 } 994 995 private boolean readTouchExplorationGrantedAccessibilityServicesLocked( 996 UserState userState) { 997 mTempComponentNameSet.clear(); 998 readComponentNamesFromSettingLocked( 999 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 1000 userState.mUserId, mTempComponentNameSet); 1001 if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) { 1002 userState.mTouchExplorationGrantedServices.clear(); 1003 userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet); 1004 mTempComponentNameSet.clear(); 1005 return true; 1006 } 1007 mTempComponentNameSet.clear(); 1008 return false; 1009 } 1010 1011 /** 1012 * Performs {@link AccessibilityService}s delayed notification. The delay is configurable 1013 * and denotes the period after the last event before notifying the service. 1014 * 1015 * @param event The event. 1016 * @param isDefault True to notify default listeners, not default services. 1017 */ 1018 private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, 1019 boolean isDefault) { 1020 try { 1021 UserState state = getCurrentUserStateLocked(); 1022 for (int i = 0, count = state.mBoundServices.size(); i < count; i++) { 1023 Service service = state.mBoundServices.get(i); 1024 1025 if (service.mIsDefault == isDefault) { 1026 if (canDispatchEventToServiceLocked(service, event, 1027 state.mHandledFeedbackTypes)) { 1028 state.mHandledFeedbackTypes |= service.mFeedbackType; 1029 service.notifyAccessibilityEvent(event); 1030 } 1031 } 1032 } 1033 } catch (IndexOutOfBoundsException oobe) { 1034 // An out of bounds exception can happen if services are going away 1035 // as the for loop is running. If that happens, just bail because 1036 // there are no more services to notify. 1037 } 1038 } 1039 1040 private void addServiceLocked(Service service, UserState userState) { 1041 try { 1042 service.onAdded(); 1043 userState.mBoundServices.add(service); 1044 userState.mComponentNameToServiceMap.put(service.mComponentName, service); 1045 } catch (RemoteException re) { 1046 /* do nothing */ 1047 } 1048 } 1049 1050 /** 1051 * Removes a service. 1052 * 1053 * @param service The service. 1054 */ 1055 private void removeServiceLocked(Service service, UserState userState) { 1056 userState.mBoundServices.remove(service); 1057 userState.mComponentNameToServiceMap.remove(service.mComponentName); 1058 service.onRemoved(); 1059 } 1060 1061 /** 1062 * Determines if given event can be dispatched to a service based on the package of the 1063 * event source and already notified services for that event type. Specifically, a 1064 * service is notified if it is interested in events from the package and no other service 1065 * providing the same feedback type has been notified. Exception are services the 1066 * provide generic feedback (feedback type left as a safety net for unforeseen feedback 1067 * types) which are always notified. 1068 * 1069 * @param service The potential receiver. 1070 * @param event The event. 1071 * @param handledFeedbackTypes The feedback types for which services have been notified. 1072 * @return True if the listener should be notified, false otherwise. 1073 */ 1074 private boolean canDispatchEventToServiceLocked(Service service, AccessibilityEvent event, 1075 int handledFeedbackTypes) { 1076 1077 if (!service.canReceiveEventsLocked()) { 1078 return false; 1079 } 1080 1081 if (event.getWindowId() != WINDOW_ID_UNKNOWN && !event.isImportantForAccessibility() 1082 && (service.mFetchFlags 1083 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) { 1084 return false; 1085 } 1086 1087 int eventType = event.getEventType(); 1088 if ((service.mEventTypes & eventType) != eventType) { 1089 return false; 1090 } 1091 1092 Set<String> packageNames = service.mPackageNames; 1093 String packageName = (event.getPackageName() != null) 1094 ? event.getPackageName().toString() : null; 1095 1096 if (packageNames.isEmpty() || packageNames.contains(packageName)) { 1097 int feedbackType = service.mFeedbackType; 1098 if ((handledFeedbackTypes & feedbackType) != feedbackType 1099 || feedbackType == AccessibilityServiceInfo.FEEDBACK_GENERIC) { 1100 return true; 1101 } 1102 } 1103 1104 return false; 1105 } 1106 1107 private void unbindAllServicesLocked(UserState userState) { 1108 List<Service> services = userState.mBoundServices; 1109 for (int i = 0, count = services.size(); i < count; i++) { 1110 Service service = services.get(i); 1111 if (service.unbindLocked()) { 1112 i--; 1113 count--; 1114 } 1115 } 1116 } 1117 1118 /** 1119 * Populates a set with the {@link ComponentName}s stored in a colon 1120 * separated value setting for a given user. 1121 * 1122 * @param settingName The setting to parse. 1123 * @param userId The user id. 1124 * @param outComponentNames The output component names. 1125 */ 1126 private void readComponentNamesFromSettingLocked(String settingName, int userId, 1127 Set<ComponentName> outComponentNames) { 1128 String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(), 1129 settingName, userId); 1130 outComponentNames.clear(); 1131 if (settingValue != null) { 1132 TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; 1133 splitter.setString(settingValue); 1134 while (splitter.hasNext()) { 1135 String str = splitter.next(); 1136 if (str == null || str.length() <= 0) { 1137 continue; 1138 } 1139 ComponentName enabledService = ComponentName.unflattenFromString(str); 1140 if (enabledService != null) { 1141 outComponentNames.add(enabledService); 1142 } 1143 } 1144 } 1145 } 1146 1147 /** 1148 * Persists the component names in the specified setting in a 1149 * colon separated fashion. 1150 * 1151 * @param settingName The setting name. 1152 * @param componentNames The component names. 1153 */ 1154 private void persistComponentNamesToSettingLocked(String settingName, 1155 Set<ComponentName> componentNames, int userId) { 1156 StringBuilder builder = new StringBuilder(); 1157 for (ComponentName componentName : componentNames) { 1158 if (builder.length() > 0) { 1159 builder.append(COMPONENT_NAME_SEPARATOR); 1160 } 1161 builder.append(componentName.flattenToShortString()); 1162 } 1163 Settings.Secure.putStringForUser(mContext.getContentResolver(), 1164 settingName, builder.toString(), userId); 1165 } 1166 1167 private void manageServicesLocked(UserState userState) { 1168 Map<ComponentName, Service> componentNameToServiceMap = 1169 userState.mComponentNameToServiceMap; 1170 boolean isEnabled = userState.mIsAccessibilityEnabled; 1171 1172 for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) { 1173 AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i); 1174 ComponentName componentName = ComponentName.unflattenFromString( 1175 installedService.getId()); 1176 Service service = componentNameToServiceMap.get(componentName); 1177 1178 if (isEnabled) { 1179 // Wait for the binding if it is in process. 1180 if (userState.mBindingServices.contains(componentName)) { 1181 continue; 1182 } 1183 if (userState.mEnabledServices.contains(componentName)) { 1184 if (service == null) { 1185 service = new Service(userState.mUserId, componentName, installedService); 1186 } else if (userState.mBoundServices.contains(service)) { 1187 continue; 1188 } 1189 service.bindLocked(); 1190 } else { 1191 if (service != null) { 1192 service.unbindLocked(); 1193 } 1194 } 1195 } else { 1196 if (service != null) { 1197 service.unbindLocked(); 1198 } else { 1199 userState.mBindingServices.remove(componentName); 1200 } 1201 } 1202 } 1203 1204 // No enabled installed services => disable accessibility to avoid 1205 // sending accessibility events with no recipient across processes. 1206 if (isEnabled && userState.mBoundServices.isEmpty() 1207 && userState.mBindingServices.isEmpty()) { 1208 userState.mIsAccessibilityEnabled = false; 1209 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1210 Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId); 1211 } 1212 } 1213 1214 private void scheduleUpdateClientsIfNeededLocked(UserState userState) { 1215 final int clientState = userState.getClientState(); 1216 if (userState.mLastSentClientState != clientState 1217 && (mGlobalClients.getRegisteredCallbackCount() > 0 1218 || userState.mClients.getRegisteredCallbackCount() > 0)) { 1219 userState.mLastSentClientState = clientState; 1220 mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS, 1221 clientState, userState.mUserId) .sendToTarget(); 1222 } 1223 } 1224 1225 private void scheduleUpdateInputFilter(UserState userState) { 1226 mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget(); 1227 } 1228 1229 private void updateInputFilter(UserState userState) { 1230 boolean setInputFilter = false; 1231 AccessibilityInputFilter inputFilter = null; 1232 synchronized (mLock) { 1233 int flags = 0; 1234 if (userState.mIsDisplayMagnificationEnabled) { 1235 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER; 1236 } 1237 // Touch exploration without accessibility makes no sense. 1238 if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) { 1239 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION; 1240 } 1241 if (userState.mIsFilterKeyEventsEnabled) { 1242 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS; 1243 } 1244 if (flags != 0) { 1245 if (!mHasInputFilter) { 1246 mHasInputFilter = true; 1247 if (mInputFilter == null) { 1248 mInputFilter = new AccessibilityInputFilter(mContext, 1249 AccessibilityManagerService.this); 1250 } 1251 inputFilter = mInputFilter; 1252 setInputFilter = true; 1253 } 1254 mInputFilter.setEnabledFeatures(flags); 1255 } else { 1256 if (mHasInputFilter) { 1257 mHasInputFilter = false; 1258 mInputFilter.disableFeatures(); 1259 inputFilter = null; 1260 setInputFilter = true; 1261 } 1262 } 1263 } 1264 if (setInputFilter) { 1265 mWindowManagerService.setInputFilter(inputFilter); 1266 } 1267 } 1268 1269 private void showEnableTouchExplorationDialog(final Service service) { 1270 synchronized (mLock) { 1271 String label = service.mResolveInfo.loadLabel( 1272 mContext.getPackageManager()).toString(); 1273 1274 final UserState state = getCurrentUserStateLocked(); 1275 if (state.mIsTouchExplorationEnabled) { 1276 return; 1277 } 1278 if (mEnableTouchExplorationDialog != null 1279 && mEnableTouchExplorationDialog.isShowing()) { 1280 return; 1281 } 1282 mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext) 1283 .setIconAttribute(android.R.attr.alertDialogIcon) 1284 .setPositiveButton(android.R.string.ok, new OnClickListener() { 1285 @Override 1286 public void onClick(DialogInterface dialog, int which) { 1287 // The user allowed the service to toggle touch exploration. 1288 state.mTouchExplorationGrantedServices.add(service.mComponentName); 1289 persistComponentNamesToSettingLocked( 1290 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 1291 state.mTouchExplorationGrantedServices, state.mUserId); 1292 // Enable touch exploration. 1293 UserState userState = getUserStateLocked(service.mUserId); 1294 userState.mIsTouchExplorationEnabled = true; 1295 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1296 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, 1297 service.mUserId); 1298 onUserStateChangedLocked(userState); 1299 } 1300 }) 1301 .setNegativeButton(android.R.string.cancel, new OnClickListener() { 1302 @Override 1303 public void onClick(DialogInterface dialog, int which) { 1304 dialog.dismiss(); 1305 } 1306 }) 1307 .setTitle(R.string.enable_explore_by_touch_warning_title) 1308 .setMessage(mContext.getString( 1309 R.string.enable_explore_by_touch_warning_message, label)) 1310 .create(); 1311 mEnableTouchExplorationDialog.getWindow().setType( 1312 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 1313 mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags 1314 |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 1315 mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true); 1316 mEnableTouchExplorationDialog.show(); 1317 } 1318 } 1319 1320 private void onUserStateChangedLocked(UserState userState) { 1321 // TODO: Remove this hack 1322 mInitialized = true; 1323 updateLegacyCapabilitiesLocked(userState); 1324 updateServicesLocked(userState); 1325 updateWindowsForAccessibilityCallbackLocked(userState); 1326 updateAccessibilityFocusBehaviorLocked(userState); 1327 updateFilterKeyEventsLocked(userState); 1328 updateTouchExplorationLocked(userState); 1329 updateEnhancedWebAccessibilityLocked(userState); 1330 updateDisplayColorAdjustmentSettingsLocked(userState); 1331 scheduleUpdateInputFilter(userState); 1332 scheduleUpdateClientsIfNeededLocked(userState); 1333 } 1334 1335 private void updateAccessibilityFocusBehaviorLocked(UserState userState) { 1336 // If there is no service that can operate with interactive windows 1337 // then we keep the old behavior where a window loses accessibility 1338 // focus if it is no longer active. This still changes the behavior 1339 // for services that do not operate with interactive windows and run 1340 // at the same time as the one(s) which does. In practice however, 1341 // there is only one service that uses accessibility focus and it 1342 // is typically the one that operates with interactive windows, So, 1343 // this is fine. Note that to allow a service to work across windows 1344 // we have to allow accessibility focus stay in any of them. Sigh... 1345 List<Service> boundServices = userState.mBoundServices; 1346 final int boundServiceCount = boundServices.size(); 1347 for (int i = 0; i < boundServiceCount; i++) { 1348 Service boundService = boundServices.get(i); 1349 if (boundService.canRetrieveInteractiveWindowsLocked()) { 1350 userState.mAccessibilityFocusOnlyInActiveWindow = false; 1351 return; 1352 } 1353 } 1354 userState.mAccessibilityFocusOnlyInActiveWindow = true; 1355 } 1356 1357 private void updateWindowsForAccessibilityCallbackLocked(UserState userState) { 1358 if (userState.mIsAccessibilityEnabled) { 1359 // We observe windows for accessibility only if there is at least 1360 // one bound service that can retrieve window content that specified 1361 // it is interested in accessing such windows. For services that are 1362 // binding we do an update pass after each bind event, so we run this 1363 // code and register the callback if needed. 1364 boolean boundServiceCanRetrieveInteractiveWindows = false; 1365 1366 List<Service> boundServices = userState.mBoundServices; 1367 final int boundServiceCount = boundServices.size(); 1368 for (int i = 0; i < boundServiceCount; i++) { 1369 Service boundService = boundServices.get(i); 1370 if (boundService.canRetrieveInteractiveWindowsLocked()) { 1371 boundServiceCanRetrieveInteractiveWindows = true; 1372 break; 1373 } 1374 } 1375 1376 if (boundServiceCanRetrieveInteractiveWindows) { 1377 if (mWindowsForAccessibilityCallback == null) { 1378 mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback(); 1379 mWindowManagerService.setWindowsForAccessibilityCallback( 1380 mWindowsForAccessibilityCallback); 1381 } 1382 return; 1383 } 1384 } 1385 1386 if (mWindowsForAccessibilityCallback != null) { 1387 mWindowsForAccessibilityCallback = null; 1388 mWindowManagerService.setWindowsForAccessibilityCallback(null); 1389 // Drop all windows we know about. 1390 mSecurityPolicy.clearWindowsLocked(); 1391 } 1392 } 1393 1394 private void updateLegacyCapabilitiesLocked(UserState userState) { 1395 // Up to JB-MR1 we had a white list with services that can enable touch 1396 // exploration. When a service is first started we show a dialog to the 1397 // use to get a permission to white list the service. 1398 final int installedServiceCount = userState.mInstalledServices.size(); 1399 for (int i = 0; i < installedServiceCount; i++) { 1400 AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i); 1401 ResolveInfo resolveInfo = serviceInfo.getResolveInfo(); 1402 if ((serviceInfo.getCapabilities() 1403 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0 1404 && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion 1405 <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 1406 ComponentName componentName = new ComponentName( 1407 resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); 1408 if (userState.mTouchExplorationGrantedServices.contains(componentName)) { 1409 serviceInfo.setCapabilities(serviceInfo.getCapabilities() 1410 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION); 1411 } 1412 } 1413 } 1414 } 1415 1416 private void updateFilterKeyEventsLocked(UserState userState) { 1417 final int serviceCount = userState.mBoundServices.size(); 1418 for (int i = 0; i < serviceCount; i++) { 1419 Service service = userState.mBoundServices.get(i); 1420 if (service.mRequestFilterKeyEvents 1421 && (service.mAccessibilityServiceInfo.getCapabilities() 1422 & AccessibilityServiceInfo 1423 .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) { 1424 userState.mIsFilterKeyEventsEnabled = true; 1425 return; 1426 } 1427 } 1428 userState.mIsFilterKeyEventsEnabled = false; 1429 } 1430 1431 private void updateServicesLocked(UserState userState) { 1432 if (userState.mIsAccessibilityEnabled) { 1433 manageServicesLocked(userState); 1434 } else { 1435 unbindAllServicesLocked(userState); 1436 } 1437 } 1438 1439 private boolean readConfigurationForUserStateLocked(UserState userState) { 1440 boolean somthingChanged = readAccessibilityEnabledSettingLocked(userState); 1441 somthingChanged |= readInstalledAccessibilityServiceLocked(userState); 1442 somthingChanged |= readEnabledAccessibilityServicesLocked(userState); 1443 somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState); 1444 somthingChanged |= readTouchExplorationEnabledSettingLocked(userState); 1445 somthingChanged |= readHighTextContrastEnabledSettingLocked(userState); 1446 somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState); 1447 somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState); 1448 somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState); 1449 return somthingChanged; 1450 } 1451 1452 private boolean readAccessibilityEnabledSettingLocked(UserState userState) { 1453 final boolean accessibilityEnabled = Settings.Secure.getIntForUser( 1454 mContext.getContentResolver(), 1455 Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1; 1456 if (accessibilityEnabled != userState.mIsAccessibilityEnabled) { 1457 userState.mIsAccessibilityEnabled = accessibilityEnabled; 1458 return true; 1459 } 1460 return false; 1461 } 1462 1463 private boolean readTouchExplorationEnabledSettingLocked(UserState userState) { 1464 final boolean touchExplorationEnabled = Settings.Secure.getIntForUser( 1465 mContext.getContentResolver(), 1466 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1; 1467 if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) { 1468 userState.mIsTouchExplorationEnabled = touchExplorationEnabled; 1469 return true; 1470 } 1471 return false; 1472 } 1473 1474 private boolean readDisplayMagnificationEnabledSettingLocked(UserState userState) { 1475 final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser( 1476 mContext.getContentResolver(), 1477 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 1478 0, userState.mUserId) == 1; 1479 if (displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled) { 1480 userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled; 1481 return true; 1482 } 1483 return false; 1484 } 1485 1486 private boolean readEnhancedWebAccessibilityEnabledChangedLocked(UserState userState) { 1487 final boolean enhancedWeAccessibilityEnabled = Settings.Secure.getIntForUser( 1488 mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 1489 0, userState.mUserId) == 1; 1490 if (enhancedWeAccessibilityEnabled != userState.mIsEnhancedWebAccessibilityEnabled) { 1491 userState.mIsEnhancedWebAccessibilityEnabled = enhancedWeAccessibilityEnabled; 1492 return true; 1493 } 1494 return false; 1495 } 1496 1497 private boolean readDisplayColorAdjustmentSettingsLocked(UserState userState) { 1498 final boolean displayAdjustmentsEnabled = DisplayAdjustmentUtils.hasAdjustments(mContext, 1499 userState.mUserId); 1500 if (displayAdjustmentsEnabled != userState.mHasDisplayColorAdjustment) { 1501 userState.mHasDisplayColorAdjustment = displayAdjustmentsEnabled; 1502 return true; 1503 } 1504 // If display adjustment is enabled, always assume there was a change in 1505 // the adjustment settings. 1506 return displayAdjustmentsEnabled; 1507 } 1508 1509 private boolean readHighTextContrastEnabledSettingLocked(UserState userState) { 1510 final boolean highTextContrastEnabled = Settings.Secure.getIntForUser( 1511 mContext.getContentResolver(), 1512 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0, 1513 userState.mUserId) == 1; 1514 if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) { 1515 userState.mIsTextHighContrastEnabled = highTextContrastEnabled; 1516 return true; 1517 } 1518 return false; 1519 } 1520 1521 private void updateTouchExplorationLocked(UserState userState) { 1522 boolean enabled = false; 1523 final int serviceCount = userState.mBoundServices.size(); 1524 for (int i = 0; i < serviceCount; i++) { 1525 Service service = userState.mBoundServices.get(i); 1526 if (canRequestAndRequestsTouchExplorationLocked(service)) { 1527 enabled = true; 1528 break; 1529 } 1530 } 1531 if (enabled != userState.mIsTouchExplorationEnabled) { 1532 userState.mIsTouchExplorationEnabled = enabled; 1533 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1534 Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0, 1535 userState.mUserId); 1536 } 1537 } 1538 1539 private boolean canRequestAndRequestsTouchExplorationLocked(Service service) { 1540 // Service not ready or cannot request the feature - well nothing to do. 1541 if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) { 1542 return false; 1543 } 1544 // UI test automation service can always enable it. 1545 if (service.mIsAutomation) { 1546 return true; 1547 } 1548 if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion 1549 <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 1550 // Up to JB-MR1 we had a white list with services that can enable touch 1551 // exploration. When a service is first started we show a dialog to the 1552 // use to get a permission to white list the service. 1553 UserState userState = getUserStateLocked(service.mUserId); 1554 if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) { 1555 return true; 1556 } else if (mEnableTouchExplorationDialog == null 1557 || !mEnableTouchExplorationDialog.isShowing()) { 1558 mMainHandler.obtainMessage( 1559 MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG, 1560 service).sendToTarget(); 1561 } 1562 } else { 1563 // Starting in JB-MR2 we request an accessibility service to declare 1564 // certain capabilities in its meta-data to allow it to enable the 1565 // corresponding features. 1566 if ((service.mAccessibilityServiceInfo.getCapabilities() 1567 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) { 1568 return true; 1569 } 1570 } 1571 return false; 1572 } 1573 1574 private void updateEnhancedWebAccessibilityLocked(UserState userState) { 1575 boolean enabled = false; 1576 final int serviceCount = userState.mBoundServices.size(); 1577 for (int i = 0; i < serviceCount; i++) { 1578 Service service = userState.mBoundServices.get(i); 1579 if (canRequestAndRequestsEnhancedWebAccessibilityLocked(service)) { 1580 enabled = true; 1581 break; 1582 } 1583 } 1584 if (enabled != userState.mIsEnhancedWebAccessibilityEnabled) { 1585 userState.mIsEnhancedWebAccessibilityEnabled = enabled; 1586 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1587 Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, enabled ? 1 : 0, 1588 userState.mUserId); 1589 } 1590 } 1591 1592 private boolean canRequestAndRequestsEnhancedWebAccessibilityLocked(Service service) { 1593 if (!service.canReceiveEventsLocked() || !service.mRequestEnhancedWebAccessibility ) { 1594 return false; 1595 } 1596 if (service.mIsAutomation || (service.mAccessibilityServiceInfo.getCapabilities() 1597 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0) { 1598 return true; 1599 } 1600 return false; 1601 } 1602 1603 private void updateDisplayColorAdjustmentSettingsLocked(UserState userState) { 1604 DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId); 1605 } 1606 1607 private boolean hasRunningServicesLocked(UserState userState) { 1608 return !userState.mBoundServices.isEmpty() || !userState.mBindingServices.isEmpty(); 1609 } 1610 1611 private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) { 1612 IBinder windowToken = mGlobalWindowTokens.get(windowId); 1613 if (windowToken == null) { 1614 windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId); 1615 } 1616 if (windowToken != null) { 1617 return mWindowManagerService.getCompatibleMagnificationSpecForWindow( 1618 windowToken); 1619 } 1620 return null; 1621 } 1622 1623 @Override 1624 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1625 mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP); 1626 synchronized (mLock) { 1627 pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)"); 1628 pw.println(); 1629 final int userCount = mUserStates.size(); 1630 for (int i = 0; i < userCount; i++) { 1631 UserState userState = mUserStates.valueAt(i); 1632 pw.append("User state[attributes:{id=" + userState.mUserId); 1633 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId)); 1634 pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled); 1635 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled); 1636 pw.append(", displayMagnificationEnabled=" 1637 + userState.mIsDisplayMagnificationEnabled); 1638 if (userState.mUiAutomationService != null) { 1639 pw.append(", "); 1640 userState.mUiAutomationService.dump(fd, pw, args); 1641 pw.println(); 1642 } 1643 pw.append("}"); 1644 pw.println(); 1645 pw.append(" services:{"); 1646 final int serviceCount = userState.mBoundServices.size(); 1647 for (int j = 0; j < serviceCount; j++) { 1648 if (j > 0) { 1649 pw.append(", "); 1650 pw.println(); 1651 pw.append(" "); 1652 } 1653 Service service = userState.mBoundServices.get(j); 1654 service.dump(fd, pw, args); 1655 } 1656 pw.println("}]"); 1657 pw.println(); 1658 } 1659 if (mSecurityPolicy.mWindows != null) { 1660 final int windowCount = mSecurityPolicy.mWindows.size(); 1661 for (int j = 0; j < windowCount; j++) { 1662 if (j > 0) { 1663 pw.append(','); 1664 pw.println(); 1665 } 1666 pw.append("Window["); 1667 AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j); 1668 pw.append(window.toString()); 1669 pw.append(']'); 1670 } 1671 } 1672 } 1673 } 1674 1675 private class AccessibilityConnectionWrapper implements DeathRecipient { 1676 private final int mWindowId; 1677 private final int mUserId; 1678 private final IAccessibilityInteractionConnection mConnection; 1679 1680 public AccessibilityConnectionWrapper(int windowId, 1681 IAccessibilityInteractionConnection connection, int userId) { 1682 mWindowId = windowId; 1683 mUserId = userId; 1684 mConnection = connection; 1685 } 1686 1687 public void linkToDeath() throws RemoteException { 1688 mConnection.asBinder().linkToDeath(this, 0); 1689 } 1690 1691 public void unlinkToDeath() { 1692 mConnection.asBinder().unlinkToDeath(this, 0); 1693 } 1694 1695 @Override 1696 public void binderDied() { 1697 unlinkToDeath(); 1698 synchronized (mLock) { 1699 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId); 1700 } 1701 } 1702 } 1703 1704 private final class MainHandler extends Handler { 1705 public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1; 1706 public static final int MSG_SEND_STATE_TO_CLIENTS = 2; 1707 public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3; 1708 public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5; 1709 public static final int MSG_UPDATE_INPUT_FILTER = 6; 1710 public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7; 1711 public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8; 1712 public static final int MSG_CLEAR_ACCESSIBILITY_FOCUS = 9; 1713 1714 public MainHandler(Looper looper) { 1715 super(looper); 1716 } 1717 1718 @Override 1719 public void handleMessage(Message msg) { 1720 final int type = msg.what; 1721 switch (type) { 1722 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: { 1723 AccessibilityEvent event = (AccessibilityEvent) msg.obj; 1724 synchronized (mLock) { 1725 if (mHasInputFilter && mInputFilter != null) { 1726 mInputFilter.notifyAccessibilityEvent(event); 1727 } 1728 } 1729 event.recycle(); 1730 } break; 1731 1732 case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: { 1733 KeyEvent event = (KeyEvent) msg.obj; 1734 final int policyFlags = msg.arg1; 1735 synchronized (mLock) { 1736 if (mHasInputFilter && mInputFilter != null) { 1737 mInputFilter.sendInputEvent(event, policyFlags); 1738 } 1739 } 1740 event.recycle(); 1741 } break; 1742 1743 case MSG_SEND_STATE_TO_CLIENTS: { 1744 final int clientState = msg.arg1; 1745 final int userId = msg.arg2; 1746 sendStateToClients(clientState, mGlobalClients); 1747 sendStateToClientsForUser(clientState, userId); 1748 } break; 1749 1750 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: { 1751 final int userId = msg.arg1; 1752 sendStateToClientsForUser(0, userId); 1753 } break; 1754 1755 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: { 1756 announceNewUserIfNeeded(); 1757 } break; 1758 1759 case MSG_UPDATE_INPUT_FILTER: { 1760 UserState userState = (UserState) msg.obj; 1761 updateInputFilter(userState); 1762 } break; 1763 1764 case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: { 1765 Service service = (Service) msg.obj; 1766 showEnableTouchExplorationDialog(service); 1767 } break; 1768 1769 case MSG_CLEAR_ACCESSIBILITY_FOCUS: { 1770 final int windowId = msg.arg1; 1771 InteractionBridge bridge; 1772 synchronized (mLock) { 1773 bridge = getInteractionBridgeLocked(); 1774 } 1775 bridge.clearAccessibilityFocusNotLocked(windowId); 1776 } break; 1777 } 1778 } 1779 1780 private void announceNewUserIfNeeded() { 1781 synchronized (mLock) { 1782 UserState userState = getCurrentUserStateLocked(); 1783 if (userState.mIsAccessibilityEnabled) { 1784 UserManager userManager = (UserManager) mContext.getSystemService( 1785 Context.USER_SERVICE); 1786 String message = mContext.getString(R.string.user_switched, 1787 userManager.getUserInfo(mCurrentUserId).name); 1788 AccessibilityEvent event = AccessibilityEvent.obtain( 1789 AccessibilityEvent.TYPE_ANNOUNCEMENT); 1790 event.getText().add(message); 1791 sendAccessibilityEvent(event, mCurrentUserId); 1792 } 1793 } 1794 } 1795 1796 private void sendStateToClientsForUser(int clientState, int userId) { 1797 final UserState userState; 1798 synchronized (mLock) { 1799 userState = getUserStateLocked(userId); 1800 } 1801 sendStateToClients(clientState, userState.mClients); 1802 } 1803 1804 private void sendStateToClients(int clientState, 1805 RemoteCallbackList<IAccessibilityManagerClient> clients) { 1806 try { 1807 final int userClientCount = clients.beginBroadcast(); 1808 for (int i = 0; i < userClientCount; i++) { 1809 IAccessibilityManagerClient client = clients.getBroadcastItem(i); 1810 try { 1811 client.setState(clientState); 1812 } catch (RemoteException re) { 1813 /* ignore */ 1814 } 1815 } 1816 } finally { 1817 clients.finishBroadcast(); 1818 } 1819 } 1820 } 1821 1822 private PendingEvent obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence) { 1823 PendingEvent pendingEvent = mPendingEventPool.acquire(); 1824 if (pendingEvent == null) { 1825 pendingEvent = new PendingEvent(); 1826 } 1827 pendingEvent.event = event; 1828 pendingEvent.policyFlags = policyFlags; 1829 pendingEvent.sequence = sequence; 1830 return pendingEvent; 1831 } 1832 1833 private void recyclePendingEventLocked(PendingEvent pendingEvent) { 1834 pendingEvent.clear(); 1835 mPendingEventPool.release(pendingEvent); 1836 } 1837 1838 private int findWindowIdLocked(IBinder token) { 1839 final int globalIndex = mGlobalWindowTokens.indexOfValue(token); 1840 if (globalIndex >= 0) { 1841 return mGlobalWindowTokens.keyAt(globalIndex); 1842 } 1843 UserState userState = getCurrentUserStateLocked(); 1844 final int userIndex = userState.mWindowTokens.indexOfValue(token); 1845 if (userIndex >= 0) { 1846 return userState.mWindowTokens.keyAt(userIndex); 1847 } 1848 return -1; 1849 } 1850 1851 private void ensureWindowsAvailableTimed() { 1852 synchronized (mLock) { 1853 if (mSecurityPolicy.mWindows != null) { 1854 return; 1855 } 1856 // If we have no registered callback, update the state we 1857 // we may have to register one but it didn't happen yet. 1858 if (mWindowsForAccessibilityCallback == null) { 1859 UserState userState = getCurrentUserStateLocked(); 1860 onUserStateChangedLocked(userState); 1861 } 1862 // We have no windows but do not care about them, done. 1863 if (mWindowsForAccessibilityCallback == null) { 1864 return; 1865 } 1866 1867 // Wait for the windows with a timeout. 1868 final long startMillis = SystemClock.uptimeMillis(); 1869 while (mSecurityPolicy.mWindows == null) { 1870 final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 1871 final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis; 1872 if (remainMillis <= 0) { 1873 return; 1874 } 1875 try { 1876 mLock.wait(remainMillis); 1877 } catch (InterruptedException ie) { 1878 /* ignore */ 1879 } 1880 } 1881 } 1882 } 1883 1884 /** 1885 * This class represents an accessibility service. It stores all per service 1886 * data required for the service management, provides API for starting/stopping the 1887 * service and is responsible for adding/removing the service in the data structures 1888 * for service management. The class also exposes configuration interface that is 1889 * passed to the service it represents as soon it is bound. It also serves as the 1890 * connection for the service. 1891 */ 1892 class Service extends IAccessibilityServiceConnection.Stub 1893 implements ServiceConnection, DeathRecipient {; 1894 1895 final int mUserId; 1896 1897 int mId = 0; 1898 1899 AccessibilityServiceInfo mAccessibilityServiceInfo; 1900 1901 IBinder mService; 1902 1903 IAccessibilityServiceClient mServiceInterface; 1904 1905 int mEventTypes; 1906 1907 int mFeedbackType; 1908 1909 Set<String> mPackageNames = new HashSet<>(); 1910 1911 boolean mIsDefault; 1912 1913 boolean mRequestTouchExplorationMode; 1914 1915 boolean mRequestEnhancedWebAccessibility; 1916 1917 boolean mRequestFilterKeyEvents; 1918 1919 boolean mRetrieveInteractiveWindows; 1920 1921 int mFetchFlags; 1922 1923 long mNotificationTimeout; 1924 1925 ComponentName mComponentName; 1926 1927 Intent mIntent; 1928 1929 boolean mIsAutomation; 1930 1931 final ResolveInfo mResolveInfo; 1932 1933 final IBinder mOverlayWindowToken = new Binder(); 1934 1935 // the events pending events to be dispatched to this service 1936 final SparseArray<AccessibilityEvent> mPendingEvents = 1937 new SparseArray<>(); 1938 1939 final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher(); 1940 1941 boolean mWasConnectedAndDied; 1942 1943 // Handler only for dispatching accessibility events since we use event 1944 // types as message types allowing us to remove messages per event type. 1945 public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) { 1946 @Override 1947 public void handleMessage(Message message) { 1948 final int eventType = message.what; 1949 notifyAccessibilityEventInternal(eventType); 1950 } 1951 }; 1952 1953 // Handler for scheduling method invocations on the main thread. 1954 public InvocationHandler mInvocationHandler = new InvocationHandler( 1955 mMainHandler.getLooper()); 1956 1957 public Service(int userId, ComponentName componentName, 1958 AccessibilityServiceInfo accessibilityServiceInfo) { 1959 mUserId = userId; 1960 mResolveInfo = accessibilityServiceInfo.getResolveInfo(); 1961 mId = sIdCounter++; 1962 mComponentName = componentName; 1963 mAccessibilityServiceInfo = accessibilityServiceInfo; 1964 mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName)); 1965 if (!mIsAutomation) { 1966 mIntent = new Intent().setComponent(mComponentName); 1967 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, 1968 com.android.internal.R.string.accessibility_binding_label); 1969 mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( 1970 mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); 1971 } 1972 setDynamicallyConfigurableProperties(accessibilityServiceInfo); 1973 } 1974 1975 public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { 1976 mEventTypes = info.eventTypes; 1977 mFeedbackType = info.feedbackType; 1978 String[] packageNames = info.packageNames; 1979 if (packageNames != null) { 1980 mPackageNames.addAll(Arrays.asList(packageNames)); 1981 } 1982 mNotificationTimeout = info.notificationTimeout; 1983 mIsDefault = (info.flags & DEFAULT) != 0; 1984 1985 if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion 1986 >= Build.VERSION_CODES.JELLY_BEAN) { 1987 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { 1988 mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 1989 } else { 1990 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 1991 } 1992 } 1993 1994 if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { 1995 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 1996 } else { 1997 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 1998 } 1999 2000 mRequestTouchExplorationMode = (info.flags 2001 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; 2002 mRequestEnhancedWebAccessibility = (info.flags 2003 & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0; 2004 mRequestFilterKeyEvents = (info.flags 2005 & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; 2006 mRetrieveInteractiveWindows = (info.flags 2007 & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; 2008 } 2009 2010 /** 2011 * Binds to the accessibility service. 2012 * 2013 * @return True if binding is successful. 2014 */ 2015 public boolean bindLocked() { 2016 UserState userState = getUserStateLocked(mUserId); 2017 if (!mIsAutomation) { 2018 if (mService == null && mContext.bindServiceAsUser( 2019 mIntent, this, Context.BIND_AUTO_CREATE, new UserHandle(mUserId))) { 2020 userState.mBindingServices.add(mComponentName); 2021 } 2022 } else { 2023 userState.mBindingServices.add(mComponentName); 2024 mService = userState.mUiAutomationServiceClient.asBinder(); 2025 mMainHandler.post(new Runnable() { 2026 @Override 2027 public void run() { 2028 // Simulate asynchronous connection since in onServiceConnected 2029 // we may modify the state data in case of an error but bind is 2030 // called while iterating over the data and bad things can happen. 2031 onServiceConnected(mComponentName, mService); 2032 } 2033 }); 2034 userState.mUiAutomationService = this; 2035 } 2036 return false; 2037 } 2038 2039 /** 2040 * Unbinds form the accessibility service and removes it from the data 2041 * structures for service management. 2042 * 2043 * @return True if unbinding is successful. 2044 */ 2045 public boolean unbindLocked() { 2046 if (mService == null) { 2047 return false; 2048 } 2049 UserState userState = getUserStateLocked(mUserId); 2050 mKeyEventDispatcher.flush(); 2051 if (!mIsAutomation) { 2052 mContext.unbindService(this); 2053 } else { 2054 userState.destroyUiAutomationService(); 2055 } 2056 removeServiceLocked(this, userState); 2057 resetLocked(); 2058 return true; 2059 } 2060 2061 public boolean canReceiveEventsLocked() { 2062 return (mEventTypes != 0 && mFeedbackType != 0 && mService != null); 2063 } 2064 2065 @Override 2066 public void setOnKeyEventResult(boolean handled, int sequence) { 2067 mKeyEventDispatcher.setOnKeyEventResult(handled, sequence); 2068 } 2069 2070 @Override 2071 public AccessibilityServiceInfo getServiceInfo() { 2072 synchronized (mLock) { 2073 return mAccessibilityServiceInfo; 2074 } 2075 } 2076 2077 public boolean canRetrieveInteractiveWindowsLocked() { 2078 return mSecurityPolicy.canRetrieveWindowContentLocked(this) 2079 && mRetrieveInteractiveWindows; 2080 } 2081 2082 @Override 2083 public void setServiceInfo(AccessibilityServiceInfo info) { 2084 final long identity = Binder.clearCallingIdentity(); 2085 try { 2086 synchronized (mLock) { 2087 // If the XML manifest had data to configure the service its info 2088 // should be already set. In such a case update only the dynamically 2089 // configurable properties. 2090 AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; 2091 if (oldInfo != null) { 2092 oldInfo.updateDynamicallyConfigurableProperties(info); 2093 setDynamicallyConfigurableProperties(oldInfo); 2094 } else { 2095 setDynamicallyConfigurableProperties(info); 2096 } 2097 UserState userState = getUserStateLocked(mUserId); 2098 onUserStateChangedLocked(userState); 2099 } 2100 } finally { 2101 Binder.restoreCallingIdentity(identity); 2102 } 2103 } 2104 2105 @Override 2106 public void onServiceConnected(ComponentName componentName, IBinder service) { 2107 synchronized (mLock) { 2108 mService = service; 2109 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service); 2110 UserState userState = getUserStateLocked(mUserId); 2111 addServiceLocked(this, userState); 2112 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) { 2113 userState.mBindingServices.remove(mComponentName); 2114 mWasConnectedAndDied = false; 2115 try { 2116 mServiceInterface.init(this, mId, mOverlayWindowToken); 2117 onUserStateChangedLocked(userState); 2118 } catch (RemoteException re) { 2119 Slog.w(LOG_TAG, "Error while setting connection for service: " 2120 + service, re); 2121 binderDied(); 2122 } 2123 } else { 2124 binderDied(); 2125 } 2126 } 2127 } 2128 2129 @Override 2130 public List<AccessibilityWindowInfo> getWindows() { 2131 ensureWindowsAvailableTimed(); 2132 synchronized (mLock) { 2133 // We treat calls from a profile as if made by its perent as profiles 2134 // share the accessibility state of the parent. The call below 2135 // performs the current profile parent resolution. 2136 final int resolvedUserId = mSecurityPolicy 2137 .resolveCallingUserIdEnforcingPermissionsLocked( 2138 UserHandle.USER_CURRENT); 2139 if (resolvedUserId != mCurrentUserId) { 2140 return null; 2141 } 2142 final boolean permissionGranted = 2143 mSecurityPolicy.canRetrieveWindowsLocked(this); 2144 if (!permissionGranted) { 2145 return null; 2146 } 2147 if (mSecurityPolicy.mWindows == null) { 2148 return null; 2149 } 2150 List<AccessibilityWindowInfo> windows = new ArrayList<>(); 2151 final int windowCount = mSecurityPolicy.mWindows.size(); 2152 for (int i = 0; i < windowCount; i++) { 2153 AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i); 2154 AccessibilityWindowInfo windowClone = 2155 AccessibilityWindowInfo.obtain(window); 2156 windowClone.setConnectionId(mId); 2157 windows.add(windowClone); 2158 } 2159 return windows; 2160 } 2161 } 2162 2163 @Override 2164 public AccessibilityWindowInfo getWindow(int windowId) { 2165 ensureWindowsAvailableTimed(); 2166 synchronized (mLock) { 2167 // We treat calls from a profile as if made by its parent as profiles 2168 // share the accessibility state of the parent. The call below 2169 // performs the current profile parent resolution. 2170 final int resolvedUserId = mSecurityPolicy 2171 .resolveCallingUserIdEnforcingPermissionsLocked( 2172 UserHandle.USER_CURRENT); 2173 if (resolvedUserId != mCurrentUserId) { 2174 return null; 2175 } 2176 final boolean permissionGranted = 2177 mSecurityPolicy.canRetrieveWindowsLocked(this); 2178 if (!permissionGranted) { 2179 return null; 2180 } 2181 AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId); 2182 if (window != null) { 2183 AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); 2184 windowClone.setConnectionId(mId); 2185 return windowClone; 2186 } 2187 return null; 2188 } 2189 } 2190 2191 @Override 2192 public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId, 2193 long accessibilityNodeId, String viewIdResName, int interactionId, 2194 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 2195 throws RemoteException { 2196 final int resolvedWindowId; 2197 IAccessibilityInteractionConnection connection = null; 2198 Region partialInteractiveRegion = mTempRegion; 2199 synchronized (mLock) { 2200 // We treat calls from a profile as if made by its parent as profiles 2201 // share the accessibility state of the parent. The call below 2202 // performs the current profile parent resolution. 2203 final int resolvedUserId = mSecurityPolicy 2204 .resolveCallingUserIdEnforcingPermissionsLocked( 2205 UserHandle.USER_CURRENT); 2206 if (resolvedUserId != mCurrentUserId) { 2207 return false; 2208 } 2209 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 2210 final boolean permissionGranted = 2211 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 2212 if (!permissionGranted) { 2213 return false; 2214 } else { 2215 connection = getConnectionLocked(resolvedWindowId); 2216 if (connection == null) { 2217 return false; 2218 } 2219 } 2220 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 2221 resolvedWindowId, partialInteractiveRegion)) { 2222 partialInteractiveRegion = null; 2223 } 2224 } 2225 final int interrogatingPid = Binder.getCallingPid(); 2226 final long identityToken = Binder.clearCallingIdentity(); 2227 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 2228 try { 2229 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName, 2230 partialInteractiveRegion, interactionId, callback, mFetchFlags, 2231 interrogatingPid, interrogatingTid, spec); 2232 return true; 2233 } catch (RemoteException re) { 2234 if (DEBUG) { 2235 Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); 2236 } 2237 } finally { 2238 Binder.restoreCallingIdentity(identityToken); 2239 } 2240 return false; 2241 } 2242 2243 @Override 2244 public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, 2245 long accessibilityNodeId, String text, int interactionId, 2246 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 2247 throws RemoteException { 2248 final int resolvedWindowId; 2249 IAccessibilityInteractionConnection connection = null; 2250 Region partialInteractiveRegion = mTempRegion; 2251 synchronized (mLock) { 2252 // We treat calls from a profile as if made by its parent as profiles 2253 // share the accessibility state of the parent. The call below 2254 // performs the current profile parent resolution. 2255 final int resolvedUserId = mSecurityPolicy 2256 .resolveCallingUserIdEnforcingPermissionsLocked( 2257 UserHandle.USER_CURRENT); 2258 if (resolvedUserId != mCurrentUserId) { 2259 return false; 2260 } 2261 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 2262 final boolean permissionGranted = 2263 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 2264 if (!permissionGranted) { 2265 return false; 2266 } else { 2267 connection = getConnectionLocked(resolvedWindowId); 2268 if (connection == null) { 2269 return false; 2270 } 2271 } 2272 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 2273 resolvedWindowId, partialInteractiveRegion)) { 2274 partialInteractiveRegion = null; 2275 } 2276 } 2277 final int interrogatingPid = Binder.getCallingPid(); 2278 final long identityToken = Binder.clearCallingIdentity(); 2279 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 2280 try { 2281 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, 2282 partialInteractiveRegion, interactionId, callback, mFetchFlags, 2283 interrogatingPid, interrogatingTid, spec); 2284 return true; 2285 } catch (RemoteException re) { 2286 if (DEBUG) { 2287 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); 2288 } 2289 } finally { 2290 Binder.restoreCallingIdentity(identityToken); 2291 } 2292 return false; 2293 } 2294 2295 @Override 2296 public boolean findAccessibilityNodeInfoByAccessibilityId( 2297 int accessibilityWindowId, long accessibilityNodeId, int interactionId, 2298 IAccessibilityInteractionConnectionCallback callback, int flags, 2299 long interrogatingTid) throws RemoteException { 2300 final int resolvedWindowId; 2301 IAccessibilityInteractionConnection connection = null; 2302 Region partialInteractiveRegion = mTempRegion; 2303 synchronized (mLock) { 2304 // We treat calls from a profile as if made by its parent as profiles 2305 // share the accessibility state of the parent. The call below 2306 // performs the current profile parent resolution. 2307 final int resolvedUserId = mSecurityPolicy 2308 .resolveCallingUserIdEnforcingPermissionsLocked( 2309 UserHandle.USER_CURRENT); 2310 if (resolvedUserId != mCurrentUserId) { 2311 return false; 2312 } 2313 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 2314 final boolean permissionGranted = 2315 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 2316 if (!permissionGranted) { 2317 return false; 2318 } else { 2319 connection = getConnectionLocked(resolvedWindowId); 2320 if (connection == null) { 2321 return false; 2322 } 2323 } 2324 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 2325 resolvedWindowId, partialInteractiveRegion)) { 2326 partialInteractiveRegion = null; 2327 } 2328 } 2329 final int interrogatingPid = Binder.getCallingPid(); 2330 final long identityToken = Binder.clearCallingIdentity(); 2331 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 2332 try { 2333 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, 2334 partialInteractiveRegion, interactionId, callback, mFetchFlags | flags, 2335 interrogatingPid, interrogatingTid, spec); 2336 return true; 2337 } catch (RemoteException re) { 2338 if (DEBUG) { 2339 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); 2340 } 2341 } finally { 2342 Binder.restoreCallingIdentity(identityToken); 2343 } 2344 return false; 2345 } 2346 2347 @Override 2348 public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, 2349 int focusType, int interactionId, 2350 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 2351 throws RemoteException { 2352 final int resolvedWindowId; 2353 IAccessibilityInteractionConnection connection = null; 2354 Region partialInteractiveRegion = mTempRegion; 2355 synchronized (mLock) { 2356 // We treat calls from a profile as if made by its parent as profiles 2357 // share the accessibility state of the parent. The call below 2358 // performs the current profile parent resolution. 2359 final int resolvedUserId = mSecurityPolicy 2360 .resolveCallingUserIdEnforcingPermissionsLocked( 2361 UserHandle.USER_CURRENT); 2362 if (resolvedUserId != mCurrentUserId) { 2363 return false; 2364 } 2365 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( 2366 accessibilityWindowId, focusType); 2367 final boolean permissionGranted = 2368 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 2369 if (!permissionGranted) { 2370 return false; 2371 } else { 2372 connection = getConnectionLocked(resolvedWindowId); 2373 if (connection == null) { 2374 return false; 2375 } 2376 } 2377 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 2378 resolvedWindowId, partialInteractiveRegion)) { 2379 partialInteractiveRegion = null; 2380 } 2381 } 2382 final int interrogatingPid = Binder.getCallingPid(); 2383 final long identityToken = Binder.clearCallingIdentity(); 2384 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 2385 try { 2386 connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, 2387 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, 2388 spec); 2389 return true; 2390 } catch (RemoteException re) { 2391 if (DEBUG) { 2392 Slog.e(LOG_TAG, "Error calling findFocus()"); 2393 } 2394 } finally { 2395 Binder.restoreCallingIdentity(identityToken); 2396 } 2397 return false; 2398 } 2399 2400 @Override 2401 public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, 2402 int direction, int interactionId, 2403 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 2404 throws RemoteException { 2405 final int resolvedWindowId; 2406 IAccessibilityInteractionConnection connection = null; 2407 Region partialInteractiveRegion = mTempRegion; 2408 synchronized (mLock) { 2409 // We treat calls from a profile as if made by its parent as profiles 2410 // share the accessibility state of the parent. The call below 2411 // performs the current profile parent resolution. 2412 final int resolvedUserId = mSecurityPolicy 2413 .resolveCallingUserIdEnforcingPermissionsLocked( 2414 UserHandle.USER_CURRENT); 2415 if (resolvedUserId != mCurrentUserId) { 2416 return false; 2417 } 2418 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 2419 final boolean permissionGranted = 2420 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 2421 if (!permissionGranted) { 2422 return false; 2423 } else { 2424 connection = getConnectionLocked(resolvedWindowId); 2425 if (connection == null) { 2426 return false; 2427 } 2428 } 2429 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 2430 resolvedWindowId, partialInteractiveRegion)) { 2431 partialInteractiveRegion = null; 2432 } 2433 } 2434 final int interrogatingPid = Binder.getCallingPid(); 2435 final long identityToken = Binder.clearCallingIdentity(); 2436 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 2437 try { 2438 connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, 2439 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, 2440 spec); 2441 return true; 2442 } catch (RemoteException re) { 2443 if (DEBUG) { 2444 Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); 2445 } 2446 } finally { 2447 Binder.restoreCallingIdentity(identityToken); 2448 } 2449 return false; 2450 } 2451 2452 @Override 2453 public boolean performAccessibilityAction(int accessibilityWindowId, 2454 long accessibilityNodeId, int action, Bundle arguments, int interactionId, 2455 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 2456 throws RemoteException { 2457 final int resolvedWindowId; 2458 IAccessibilityInteractionConnection connection = null; 2459 synchronized (mLock) { 2460 // We treat calls from a profile as if made by its parent as profiles 2461 // share the accessibility state of the parent. The call below 2462 // performs the current profile parent resolution. 2463 final int resolvedUserId = mSecurityPolicy 2464 .resolveCallingUserIdEnforcingPermissionsLocked( 2465 UserHandle.USER_CURRENT); 2466 if (resolvedUserId != mCurrentUserId) { 2467 return false; 2468 } 2469 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 2470 final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 2471 this, resolvedWindowId); 2472 if (!permissionGranted) { 2473 return false; 2474 } else { 2475 connection = getConnectionLocked(resolvedWindowId); 2476 if (connection == null) { 2477 return false; 2478 } 2479 } 2480 } 2481 final int interrogatingPid = Binder.getCallingPid(); 2482 final long identityToken = Binder.clearCallingIdentity(); 2483 try { 2484 connection.performAccessibilityAction(accessibilityNodeId, action, arguments, 2485 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid); 2486 } catch (RemoteException re) { 2487 if (DEBUG) { 2488 Slog.e(LOG_TAG, "Error calling performAccessibilityAction()"); 2489 } 2490 } finally { 2491 Binder.restoreCallingIdentity(identityToken); 2492 } 2493 return true; 2494 } 2495 2496 @Override 2497 public boolean performGlobalAction(int action) { 2498 synchronized (mLock) { 2499 // We treat calls from a profile as if made by its parent as profiles 2500 // share the accessibility state of the parent. The call below 2501 // performs the current profile parent resolution. 2502 final int resolvedUserId = mSecurityPolicy 2503 .resolveCallingUserIdEnforcingPermissionsLocked( 2504 UserHandle.USER_CURRENT); 2505 if (resolvedUserId != mCurrentUserId) { 2506 return false; 2507 } 2508 } 2509 final long identity = Binder.clearCallingIdentity(); 2510 try { 2511 switch (action) { 2512 case AccessibilityService.GLOBAL_ACTION_BACK: { 2513 sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK); 2514 } return true; 2515 case AccessibilityService.GLOBAL_ACTION_HOME: { 2516 sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME); 2517 } return true; 2518 case AccessibilityService.GLOBAL_ACTION_RECENTS: { 2519 openRecents(); 2520 } return true; 2521 case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: { 2522 expandNotifications(); 2523 } return true; 2524 case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: { 2525 expandQuickSettings(); 2526 } return true; 2527 case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: { 2528 showGlobalActions(); 2529 } return true; 2530 } 2531 return false; 2532 } finally { 2533 Binder.restoreCallingIdentity(identity); 2534 } 2535 } 2536 2537 @Override 2538 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 2539 mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP); 2540 synchronized (mLock) { 2541 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo() 2542 .loadLabel(mContext.getPackageManager())); 2543 pw.append(", feedbackType" 2544 + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); 2545 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); 2546 pw.append(", eventTypes=" 2547 + AccessibilityEvent.eventTypeToString(mEventTypes)); 2548 pw.append(", notificationTimeout=" + mNotificationTimeout); 2549 pw.append("]"); 2550 } 2551 } 2552 2553 @Override 2554 public void onServiceDisconnected(ComponentName componentName) { 2555 /* do nothing - #binderDied takes care */ 2556 } 2557 2558 public void onAdded() throws RemoteException { 2559 linkToOwnDeathLocked(); 2560 final long identity = Binder.clearCallingIdentity(); 2561 try { 2562 mWindowManagerService.addWindowToken(mOverlayWindowToken, 2563 WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY); 2564 } finally { 2565 Binder.restoreCallingIdentity(identity); 2566 } 2567 } 2568 2569 public void onRemoved() { 2570 final long identity = Binder.clearCallingIdentity(); 2571 try { 2572 mWindowManagerService.removeWindowToken(mOverlayWindowToken, true); 2573 } finally { 2574 Binder.restoreCallingIdentity(identity); 2575 } 2576 unlinkToOwnDeathLocked(); 2577 } 2578 2579 public void linkToOwnDeathLocked() throws RemoteException { 2580 mService.linkToDeath(this, 0); 2581 } 2582 2583 public void unlinkToOwnDeathLocked() { 2584 mService.unlinkToDeath(this, 0); 2585 } 2586 2587 public void resetLocked() { 2588 try { 2589 // Clear the proxy in the other process so this 2590 // IAccessibilityServiceConnection can be garbage collected. 2591 mServiceInterface.init(null, mId, null); 2592 } catch (RemoteException re) { 2593 /* ignore */ 2594 } 2595 mService = null; 2596 mServiceInterface = null; 2597 } 2598 2599 public boolean isConnectedLocked() { 2600 return (mService != null); 2601 } 2602 2603 public void binderDied() { 2604 synchronized (mLock) { 2605 // It is possible that this service's package was force stopped during 2606 // whose handling the death recipient is unlinked and still get a call 2607 // on binderDied since the call was made before we unlink but was 2608 // waiting on the lock we held during the force stop handling. 2609 if (!isConnectedLocked()) { 2610 return; 2611 } 2612 mWasConnectedAndDied = true; 2613 mKeyEventDispatcher.flush(); 2614 UserState userState = getUserStateLocked(mUserId); 2615 // The death recipient is unregistered in removeServiceLocked 2616 removeServiceLocked(this, userState); 2617 resetLocked(); 2618 if (mIsAutomation) { 2619 // We no longer have an automation service, so restore 2620 // the state based on values in the settings database. 2621 userState.mInstalledServices.remove(mAccessibilityServiceInfo); 2622 userState.mEnabledServices.remove(mComponentName); 2623 userState.destroyUiAutomationService(); 2624 if (readConfigurationForUserStateLocked(userState)) { 2625 onUserStateChangedLocked(userState); 2626 } 2627 } 2628 } 2629 } 2630 2631 /** 2632 * Performs a notification for an {@link AccessibilityEvent}. 2633 * 2634 * @param event The event. 2635 */ 2636 public void notifyAccessibilityEvent(AccessibilityEvent event) { 2637 synchronized (mLock) { 2638 final int eventType = event.getEventType(); 2639 // Make a copy since during dispatch it is possible the event to 2640 // be modified to remove its source if the receiving service does 2641 // not have permission to access the window content. 2642 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); 2643 AccessibilityEvent oldEvent = mPendingEvents.get(eventType); 2644 mPendingEvents.put(eventType, newEvent); 2645 2646 final int what = eventType; 2647 if (oldEvent != null) { 2648 mEventDispatchHandler.removeMessages(what); 2649 oldEvent.recycle(); 2650 } 2651 2652 Message message = mEventDispatchHandler.obtainMessage(what); 2653 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout); 2654 } 2655 } 2656 2657 /** 2658 * Notifies an accessibility service client for a scheduled event given the event type. 2659 * 2660 * @param eventType The type of the event to dispatch. 2661 */ 2662 private void notifyAccessibilityEventInternal(int eventType) { 2663 IAccessibilityServiceClient listener; 2664 AccessibilityEvent event; 2665 2666 synchronized (mLock) { 2667 listener = mServiceInterface; 2668 2669 // If the service died/was disabled while the message for dispatching 2670 // the accessibility event was propagating the listener may be null. 2671 if (listener == null) { 2672 return; 2673 } 2674 2675 event = mPendingEvents.get(eventType); 2676 2677 // Check for null here because there is a concurrent scenario in which this 2678 // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked 2679 // which posts a message for dispatching an event. 2) The message is pulled 2680 // from the queue by the handler on the service thread and the latter is 2681 // just about to acquire the lock and call this method. 3) Now another binder 2682 // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked 2683 // so the service thread waits for the lock; 4) The binder thread replaces 2684 // the event with a more recent one (assume the same event type) and posts a 2685 // dispatch request releasing the lock. 5) Now the main thread is unblocked and 2686 // dispatches the event which is removed from the pending ones. 6) And ... now 2687 // the service thread handles the last message posted by the last binder call 2688 // but the event is already dispatched and hence looking it up in the pending 2689 // ones yields null. This check is much simpler that keeping count for each 2690 // event type of each service to catch such a scenario since only one message 2691 // is processed at a time. 2692 if (event == null) { 2693 return; 2694 } 2695 2696 mPendingEvents.remove(eventType); 2697 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) { 2698 event.setConnectionId(mId); 2699 } else { 2700 event.setSource(null); 2701 } 2702 event.setSealed(true); 2703 } 2704 2705 try { 2706 listener.onAccessibilityEvent(event); 2707 if (DEBUG) { 2708 Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); 2709 } 2710 } catch (RemoteException re) { 2711 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); 2712 } finally { 2713 event.recycle(); 2714 } 2715 } 2716 2717 public void notifyGesture(int gestureId) { 2718 mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, 2719 gestureId, 0).sendToTarget(); 2720 } 2721 2722 public void notifyKeyEvent(KeyEvent event, int policyFlags) { 2723 mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_KEY_EVENT, 2724 policyFlags, 0, event).sendToTarget(); 2725 } 2726 2727 public void notifyClearAccessibilityNodeInfoCache() { 2728 mInvocationHandler.sendEmptyMessage( 2729 InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); 2730 } 2731 2732 private void notifyGestureInternal(int gestureId) { 2733 final IAccessibilityServiceClient listener; 2734 synchronized (mLock) { 2735 listener = mServiceInterface; 2736 } 2737 if (listener != null) { 2738 try { 2739 listener.onGesture(gestureId); 2740 } catch (RemoteException re) { 2741 Slog.e(LOG_TAG, "Error during sending gesture " + gestureId 2742 + " to " + mService, re); 2743 } 2744 } 2745 } 2746 2747 private void notifyKeyEventInternal(KeyEvent event, int policyFlags) { 2748 mKeyEventDispatcher.notifyKeyEvent(event, policyFlags); 2749 } 2750 2751 private void notifyClearAccessibilityCacheInternal() { 2752 final IAccessibilityServiceClient listener; 2753 synchronized (mLock) { 2754 listener = mServiceInterface; 2755 } 2756 if (listener != null) { 2757 try { 2758 listener.clearAccessibilityCache(); 2759 } catch (RemoteException re) { 2760 Slog.e(LOG_TAG, "Error during requesting accessibility info cache" 2761 + " to be cleared.", re); 2762 } 2763 } 2764 } 2765 2766 private void sendDownAndUpKeyEvents(int keyCode) { 2767 final long token = Binder.clearCallingIdentity(); 2768 2769 // Inject down. 2770 final long downTime = SystemClock.uptimeMillis(); 2771 KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, 2772 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 2773 InputDevice.SOURCE_KEYBOARD, null); 2774 InputManager.getInstance().injectInputEvent(down, 2775 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 2776 down.recycle(); 2777 2778 // Inject up. 2779 final long upTime = SystemClock.uptimeMillis(); 2780 KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0, 2781 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 2782 InputDevice.SOURCE_KEYBOARD, null); 2783 InputManager.getInstance().injectInputEvent(up, 2784 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 2785 up.recycle(); 2786 2787 Binder.restoreCallingIdentity(token); 2788 } 2789 2790 private void expandNotifications() { 2791 final long token = Binder.clearCallingIdentity(); 2792 2793 StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 2794 android.app.Service.STATUS_BAR_SERVICE); 2795 statusBarManager.expandNotificationsPanel(); 2796 2797 Binder.restoreCallingIdentity(token); 2798 } 2799 2800 private void expandQuickSettings() { 2801 final long token = Binder.clearCallingIdentity(); 2802 2803 StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 2804 android.app.Service.STATUS_BAR_SERVICE); 2805 statusBarManager.expandSettingsPanel(); 2806 2807 Binder.restoreCallingIdentity(token); 2808 } 2809 2810 private void openRecents() { 2811 final long token = Binder.clearCallingIdentity(); 2812 2813 IStatusBarService statusBarService = IStatusBarService.Stub.asInterface( 2814 ServiceManager.getService("statusbar")); 2815 try { 2816 statusBarService.toggleRecentApps(); 2817 } catch (RemoteException e) { 2818 Slog.e(LOG_TAG, "Error toggling recent apps."); 2819 } 2820 2821 Binder.restoreCallingIdentity(token); 2822 } 2823 2824 private void showGlobalActions() { 2825 mWindowManagerService.showGlobalActions(); 2826 } 2827 2828 private IAccessibilityInteractionConnection getConnectionLocked(int windowId) { 2829 if (DEBUG) { 2830 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId); 2831 } 2832 AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId); 2833 if (wrapper == null) { 2834 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId); 2835 } 2836 if (wrapper != null && wrapper.mConnection != null) { 2837 return wrapper.mConnection; 2838 } 2839 if (DEBUG) { 2840 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId); 2841 } 2842 return null; 2843 } 2844 2845 private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { 2846 if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) { 2847 return mSecurityPolicy.getActiveWindowId(); 2848 } 2849 return accessibilityWindowId; 2850 } 2851 2852 private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { 2853 if (windowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) { 2854 return mSecurityPolicy.mActiveWindowId; 2855 } 2856 if (windowId == AccessibilityNodeInfo.ANY_WINDOW_ID) { 2857 if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) { 2858 return mSecurityPolicy.mFocusedWindowId; 2859 } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) { 2860 return mSecurityPolicy.mAccessibilityFocusedWindowId; 2861 } 2862 } 2863 return windowId; 2864 } 2865 2866 private final class InvocationHandler extends Handler { 2867 public static final int MSG_ON_GESTURE = 1; 2868 public static final int MSG_ON_KEY_EVENT = 2; 2869 public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 3; 2870 public static final int MSG_ON_KEY_EVENT_TIMEOUT = 4; 2871 2872 public InvocationHandler(Looper looper) { 2873 super(looper, null, true); 2874 } 2875 2876 @Override 2877 public void handleMessage(Message message) { 2878 final int type = message.what; 2879 switch (type) { 2880 case MSG_ON_GESTURE: { 2881 final int gestureId = message.arg1; 2882 notifyGestureInternal(gestureId); 2883 } break; 2884 2885 case MSG_ON_KEY_EVENT: { 2886 KeyEvent event = (KeyEvent) message.obj; 2887 final int policyFlags = message.arg1; 2888 notifyKeyEventInternal(event, policyFlags); 2889 } break; 2890 2891 case MSG_CLEAR_ACCESSIBILITY_CACHE: { 2892 notifyClearAccessibilityCacheInternal(); 2893 } break; 2894 2895 case MSG_ON_KEY_EVENT_TIMEOUT: { 2896 PendingEvent eventState = (PendingEvent) message.obj; 2897 setOnKeyEventResult(false, eventState.sequence); 2898 } break; 2899 2900 default: { 2901 throw new IllegalArgumentException("Unknown message: " + type); 2902 } 2903 } 2904 } 2905 } 2906 2907 private final class KeyEventDispatcher { 2908 2909 private static final long ON_KEY_EVENT_TIMEOUT_MILLIS = 500; 2910 2911 private PendingEvent mPendingEvents; 2912 2913 private final InputEventConsistencyVerifier mSentEventsVerifier = 2914 InputEventConsistencyVerifier.isInstrumentationEnabled() 2915 ? new InputEventConsistencyVerifier( 2916 this, 0, KeyEventDispatcher.class.getSimpleName()) : null; 2917 2918 public void notifyKeyEvent(KeyEvent event, int policyFlags) { 2919 final PendingEvent pendingEvent; 2920 2921 synchronized (mLock) { 2922 pendingEvent = addPendingEventLocked(event, policyFlags); 2923 } 2924 2925 Message message = mInvocationHandler.obtainMessage( 2926 InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent); 2927 mInvocationHandler.sendMessageDelayed(message, ON_KEY_EVENT_TIMEOUT_MILLIS); 2928 2929 try { 2930 // Accessibility services are exclusively not in the system 2931 // process, therefore no need to clone the motion event to 2932 // prevent tampering. It will be cloned in the IPC call. 2933 mServiceInterface.onKeyEvent(pendingEvent.event, pendingEvent.sequence); 2934 } catch (RemoteException re) { 2935 setOnKeyEventResult(false, pendingEvent.sequence); 2936 } 2937 } 2938 2939 public void setOnKeyEventResult(boolean handled, int sequence) { 2940 synchronized (mLock) { 2941 PendingEvent pendingEvent = removePendingEventLocked(sequence); 2942 if (pendingEvent != null) { 2943 mInvocationHandler.removeMessages( 2944 InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, 2945 pendingEvent); 2946 pendingEvent.handled = handled; 2947 finishPendingEventLocked(pendingEvent); 2948 } 2949 } 2950 } 2951 2952 public void flush() { 2953 synchronized (mLock) { 2954 cancelAllPendingEventsLocked(); 2955 if (mSentEventsVerifier != null) { 2956 mSentEventsVerifier.reset(); 2957 } 2958 } 2959 } 2960 2961 private PendingEvent addPendingEventLocked(KeyEvent event, int policyFlags) { 2962 final int sequence = event.getSequenceNumber(); 2963 PendingEvent pendingEvent = obtainPendingEventLocked(event, policyFlags, sequence); 2964 pendingEvent.next = mPendingEvents; 2965 mPendingEvents = pendingEvent; 2966 return pendingEvent; 2967 } 2968 2969 private PendingEvent removePendingEventLocked(int sequence) { 2970 PendingEvent previous = null; 2971 PendingEvent current = mPendingEvents; 2972 2973 while (current != null) { 2974 if (current.sequence == sequence) { 2975 if (previous != null) { 2976 previous.next = current.next; 2977 } else { 2978 mPendingEvents = current.next; 2979 } 2980 current.next = null; 2981 return current; 2982 } 2983 previous = current; 2984 current = current.next; 2985 } 2986 return null; 2987 } 2988 2989 private void finishPendingEventLocked(PendingEvent pendingEvent) { 2990 if (!pendingEvent.handled) { 2991 sendKeyEventToInputFilter(pendingEvent.event, pendingEvent.policyFlags); 2992 } 2993 // Nullify the event since we do not want it to be 2994 // recycled yet. It will be sent to the input filter. 2995 pendingEvent.event = null; 2996 recyclePendingEventLocked(pendingEvent); 2997 } 2998 2999 private void sendKeyEventToInputFilter(KeyEvent event, int policyFlags) { 3000 if (DEBUG) { 3001 Slog.i(LOG_TAG, "Injecting event: " + event); 3002 } 3003 if (mSentEventsVerifier != null) { 3004 mSentEventsVerifier.onKeyEvent(event, 0); 3005 } 3006 policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER; 3007 mMainHandler.obtainMessage(MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, 3008 policyFlags, 0, event).sendToTarget(); 3009 } 3010 3011 private void cancelAllPendingEventsLocked() { 3012 while (mPendingEvents != null) { 3013 PendingEvent pendingEvent = removePendingEventLocked(mPendingEvents.sequence); 3014 pendingEvent.handled = false; 3015 mInvocationHandler.removeMessages(InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, 3016 pendingEvent); 3017 finishPendingEventLocked(pendingEvent); 3018 } 3019 } 3020 } 3021 } 3022 3023 private static final class PendingEvent { 3024 PendingEvent next; 3025 3026 KeyEvent event; 3027 int policyFlags; 3028 int sequence; 3029 boolean handled; 3030 3031 public void clear() { 3032 if (event != null) { 3033 event.recycle(); 3034 event = null; 3035 } 3036 next = null; 3037 policyFlags = 0; 3038 sequence = 0; 3039 handled = false; 3040 } 3041 } 3042 3043 final class WindowsForAccessibilityCallback implements 3044 WindowManagerInternal.WindowsForAccessibilityCallback { 3045 3046 @Override 3047 public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) { 3048 synchronized (mLock) { 3049 // Populate the windows to report. 3050 List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>(); 3051 final int receivedWindowCount = windows.size(); 3052 for (int i = 0; i < receivedWindowCount; i++) { 3053 WindowInfo receivedWindow = windows.get(i); 3054 AccessibilityWindowInfo reportedWindow = populateReportedWindow( 3055 receivedWindow); 3056 if (reportedWindow != null) { 3057 reportedWindows.add(reportedWindow); 3058 } 3059 } 3060 3061 if (DEBUG) { 3062 Slog.i(LOG_TAG, "Windows changed: " + reportedWindows); 3063 } 3064 3065 // Let the policy update the focused and active windows. 3066 mSecurityPolicy.updateWindowsLocked(reportedWindows); 3067 3068 // Someone may be waiting for the windows - advertise it. 3069 mLock.notifyAll(); 3070 } 3071 } 3072 3073 private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) { 3074 final int windowId = findWindowIdLocked(window.token); 3075 if (windowId < 0) { 3076 return null; 3077 } 3078 3079 AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain(); 3080 3081 reportedWindow.setId(windowId); 3082 reportedWindow.setType(getTypeForWindowManagerWindowType(window.type)); 3083 reportedWindow.setLayer(window.layer); 3084 reportedWindow.setFocused(window.focused); 3085 reportedWindow.setBoundsInScreen(window.boundsInScreen); 3086 3087 final int parentId = findWindowIdLocked(window.parentToken); 3088 if (parentId >= 0) { 3089 reportedWindow.setParentId(parentId); 3090 } 3091 3092 if (window.childTokens != null) { 3093 final int childCount = window.childTokens.size(); 3094 for (int i = 0; i < childCount; i++) { 3095 IBinder childToken = window.childTokens.get(i); 3096 final int childId = findWindowIdLocked(childToken); 3097 if (childId >= 0) { 3098 reportedWindow.addChild(childId); 3099 } 3100 } 3101 } 3102 3103 return reportedWindow; 3104 } 3105 3106 private int getTypeForWindowManagerWindowType(int windowType) { 3107 switch (windowType) { 3108 case WindowManager.LayoutParams.TYPE_APPLICATION: 3109 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA: 3110 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL: 3111 case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING: 3112 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL: 3113 case WindowManager.LayoutParams.TYPE_BASE_APPLICATION: 3114 case WindowManager.LayoutParams.TYPE_PHONE: 3115 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE: 3116 case WindowManager.LayoutParams.TYPE_TOAST: 3117 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: { 3118 return AccessibilityWindowInfo.TYPE_APPLICATION; 3119 } 3120 3121 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 3122 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: { 3123 return AccessibilityWindowInfo.TYPE_INPUT_METHOD; 3124 } 3125 3126 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG: 3127 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 3128 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: 3129 case WindowManager.LayoutParams.TYPE_SEARCH_BAR: 3130 case WindowManager.LayoutParams.TYPE_STATUS_BAR: 3131 case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL: 3132 case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL: 3133 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY: 3134 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT: 3135 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG: 3136 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR: 3137 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: { 3138 return AccessibilityWindowInfo.TYPE_SYSTEM; 3139 } 3140 3141 case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: { 3142 return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY; 3143 } 3144 3145 default: { 3146 return -1; 3147 } 3148 } 3149 } 3150 } 3151 3152 private final class InteractionBridge { 3153 private final Display mDefaultDisplay; 3154 private final int mConnectionId; 3155 private final AccessibilityInteractionClient mClient; 3156 3157 public InteractionBridge() { 3158 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 3159 info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 3160 info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; 3161 info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 3162 Service service = new Service(UserHandle.USER_NULL, 3163 sFakeAccessibilityServiceComponentName, info); 3164 3165 mConnectionId = service.mId; 3166 3167 mClient = AccessibilityInteractionClient.getInstance(); 3168 mClient.addConnection(mConnectionId, service); 3169 3170 //TODO: (multi-display) We need to support multiple displays. 3171 DisplayManager displayManager = (DisplayManager) 3172 mContext.getSystemService(Context.DISPLAY_SERVICE); 3173 mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); 3174 } 3175 3176 public void clearAccessibilityFocusNotLocked(int windowId) { 3177 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId); 3178 if (focus != null) { 3179 focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 3180 } 3181 } 3182 3183 public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) { 3184 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(); 3185 if (focus == null) { 3186 return false; 3187 } 3188 3189 synchronized (mLock) { 3190 Rect boundsInScreen = mTempRect; 3191 focus.getBoundsInScreen(boundsInScreen); 3192 3193 // Clip to the window bounds. 3194 Rect windowBounds = mTempRect1; 3195 getWindowBounds(focus.getWindowId(), windowBounds); 3196 boundsInScreen.intersect(windowBounds); 3197 if (boundsInScreen.isEmpty()) { 3198 return false; 3199 } 3200 3201 // Apply magnification if needed. 3202 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId()); 3203 if (spec != null && !spec.isNop()) { 3204 boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY); 3205 boundsInScreen.scale(1 / spec.scale); 3206 } 3207 3208 // Clip to the screen bounds. 3209 Point screenSize = mTempPoint; 3210 mDefaultDisplay.getRealSize(screenSize); 3211 boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y); 3212 if (boundsInScreen.isEmpty()) { 3213 return false; 3214 } 3215 3216 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY()); 3217 } 3218 3219 return true; 3220 } 3221 3222 private AccessibilityNodeInfo getAccessibilityFocusNotLocked() { 3223 final int focusedWindowId; 3224 synchronized (mLock) { 3225 focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId; 3226 if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) { 3227 return null; 3228 } 3229 } 3230 return getAccessibilityFocusNotLocked(focusedWindowId); 3231 } 3232 3233 private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) { 3234 return mClient.findFocus(mConnectionId, 3235 windowId, AccessibilityNodeInfo.ROOT_NODE_ID, 3236 AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); 3237 } 3238 } 3239 3240 final class SecurityPolicy { 3241 public static final int INVALID_WINDOW_ID = -1; 3242 3243 private static final int RETRIEVAL_ALLOWING_EVENT_TYPES = 3244 AccessibilityEvent.TYPE_VIEW_CLICKED 3245 | AccessibilityEvent.TYPE_VIEW_FOCUSED 3246 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 3247 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 3248 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 3249 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 3250 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 3251 | AccessibilityEvent.TYPE_VIEW_SELECTED 3252 | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED 3253 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 3254 | AccessibilityEvent.TYPE_VIEW_SCROLLED 3255 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 3256 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED 3257 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 3258 3259 public List<AccessibilityWindowInfo> mWindows; 3260 3261 public int mActiveWindowId = INVALID_WINDOW_ID; 3262 public int mFocusedWindowId = INVALID_WINDOW_ID; 3263 public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; 3264 public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 3265 3266 private boolean mTouchInteractionInProgress; 3267 3268 private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) { 3269 final int eventType = event.getEventType(); 3270 switch (eventType) { 3271 // All events that are for changes in a global window 3272 // state should *always* be dispatched. 3273 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: 3274 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: 3275 case AccessibilityEvent.TYPE_ANNOUNCEMENT: 3276 // All events generated by the user touching the 3277 // screen should *always* be dispatched. 3278 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: 3279 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: 3280 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START: 3281 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END: 3282 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START: 3283 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END: 3284 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: 3285 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: 3286 // Also windows changing should always be anounced. 3287 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: { 3288 return true; 3289 } 3290 // All events for changes in window content should be 3291 // dispatched *only* if this window is one of the windows 3292 // the accessibility layer reports which are windows 3293 // that a sighted user can touch. 3294 default: { 3295 return isRetrievalAllowingWindow(event.getWindowId()); 3296 } 3297 } 3298 } 3299 3300 public void clearWindowsLocked() { 3301 List<AccessibilityWindowInfo> windows = Collections.emptyList(); 3302 final int activeWindowId = mActiveWindowId; 3303 updateWindowsLocked(windows); 3304 mActiveWindowId = activeWindowId; 3305 mWindows = null; 3306 } 3307 3308 public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) { 3309 if (mWindows == null) { 3310 mWindows = new ArrayList<>(); 3311 } 3312 3313 final int oldWindowCount = mWindows.size(); 3314 for (int i = oldWindowCount - 1; i >= 0; i--) { 3315 mWindows.remove(i).recycle(); 3316 } 3317 3318 mFocusedWindowId = INVALID_WINDOW_ID; 3319 if (!mTouchInteractionInProgress) { 3320 mActiveWindowId = INVALID_WINDOW_ID; 3321 } 3322 3323 // If the active window goes away while the user is touch exploring we 3324 // reset the active window id and wait for the next hover event from 3325 // under the user's finger to determine which one is the new one. It 3326 // is possible that the finger is not moving and the input system 3327 // filters out such events. 3328 boolean activeWindowGone = true; 3329 3330 final int windowCount = windows.size(); 3331 if (windowCount > 0) { 3332 for (int i = 0; i < windowCount; i++) { 3333 AccessibilityWindowInfo window = windows.get(i); 3334 final int windowId = window.getId(); 3335 if (window.isFocused()) { 3336 mFocusedWindowId = windowId; 3337 if (!mTouchInteractionInProgress) { 3338 mActiveWindowId = windowId; 3339 window.setActive(true); 3340 } else if (windowId == mActiveWindowId) { 3341 activeWindowGone = false; 3342 } 3343 } 3344 mWindows.add(window); 3345 } 3346 3347 if (mTouchInteractionInProgress && activeWindowGone) { 3348 mActiveWindowId = mFocusedWindowId; 3349 } 3350 3351 // Focused window may change the active one, so set the 3352 // active window once we decided which it is. 3353 for (int i = 0; i < windowCount; i++) { 3354 AccessibilityWindowInfo window = mWindows.get(i); 3355 if (window.getId() == mActiveWindowId) { 3356 window.setActive(true); 3357 } 3358 if (window.getId() == mAccessibilityFocusedWindowId) { 3359 window.setAccessibilityFocused(true); 3360 } 3361 } 3362 } 3363 3364 notifyWindowsChanged(); 3365 } 3366 3367 public boolean computePartialInteractiveRegionForWindowLocked(int windowId, 3368 Region outRegion) { 3369 if (mWindows == null) { 3370 return false; 3371 } 3372 3373 // Windows are ordered in z order so start from the bottom and find 3374 // the window of interest. After that all windows that cover it should 3375 // be subtracted from the resulting region. Note that for accessibility 3376 // we are returning only interactive windows. 3377 Region windowInteractiveRegion = null; 3378 boolean windowInteractiveRegionChanged = false; 3379 3380 final int windowCount = mWindows.size(); 3381 for (int i = windowCount - 1; i >= 0; i--) { 3382 AccessibilityWindowInfo currentWindow = mWindows.get(i); 3383 if (windowInteractiveRegion == null) { 3384 if (currentWindow.getId() == windowId) { 3385 Rect currentWindowBounds = mTempRect; 3386 currentWindow.getBoundsInScreen(currentWindowBounds); 3387 outRegion.set(currentWindowBounds); 3388 windowInteractiveRegion = outRegion; 3389 continue; 3390 } 3391 } else if (currentWindow.getType() 3392 != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) { 3393 Rect currentWindowBounds = mTempRect; 3394 currentWindow.getBoundsInScreen(currentWindowBounds); 3395 if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) { 3396 windowInteractiveRegionChanged = true; 3397 } 3398 } 3399 } 3400 3401 return windowInteractiveRegionChanged; 3402 } 3403 3404 public void updateEventSourceLocked(AccessibilityEvent event) { 3405 if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) { 3406 event.setSource(null); 3407 } 3408 } 3409 3410 public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, 3411 int eventType) { 3412 // The active window is either the window that has input focus or 3413 // the window that the user is currently touching. If the user is 3414 // touching a window that does not have input focus as soon as the 3415 // the user stops touching that window the focused window becomes 3416 // the active one. Here we detect the touched window and make it 3417 // active. In updateWindowsLocked() we update the focused window 3418 // and if the user is not touching the screen, we make the focused 3419 // window the active one. 3420 switch (eventType) { 3421 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: { 3422 // If no service has the capability to introspect screen, 3423 // we do not register callback in the window manager for 3424 // window changes, so we have to ask the window manager 3425 // what the focused window is to update the active one. 3426 // The active window also determined events from which 3427 // windows are delivered. 3428 synchronized (mLock) { 3429 if (mWindowsForAccessibilityCallback == null) { 3430 mFocusedWindowId = getFocusedWindowId(); 3431 if (windowId == mFocusedWindowId) { 3432 mActiveWindowId = windowId; 3433 } 3434 } 3435 } 3436 } break; 3437 3438 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: { 3439 // Do not allow delayed hover events to confuse us 3440 // which the active window is. 3441 synchronized (mLock) { 3442 if (mTouchInteractionInProgress && mActiveWindowId != windowId) { 3443 setActiveWindowLocked(windowId); 3444 } 3445 } 3446 } break; 3447 3448 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: { 3449 synchronized (mLock) { 3450 if (mAccessibilityFocusedWindowId != windowId) { 3451 mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, 3452 mAccessibilityFocusedWindowId, 0).sendToTarget(); 3453 mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId); 3454 mAccessibilityFocusNodeId = nodeId; 3455 } 3456 } 3457 } break; 3458 3459 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: { 3460 synchronized (mLock) { 3461 if (mAccessibilityFocusNodeId == nodeId) { 3462 mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 3463 } 3464 if (mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID 3465 && mAccessibilityFocusedWindowId == windowId) { 3466 mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; 3467 } 3468 } 3469 } break; 3470 } 3471 } 3472 3473 public void onTouchInteractionStart() { 3474 synchronized (mLock) { 3475 mTouchInteractionInProgress = true; 3476 } 3477 } 3478 3479 public void onTouchInteractionEnd() { 3480 synchronized (mLock) { 3481 mTouchInteractionInProgress = false; 3482 // We want to set the active window to be current immediately 3483 // after the user has stopped touching the screen since if the 3484 // user types with the IME he should get a feedback for the 3485 // letter typed in the text view which is in the input focused 3486 // window. Note that we always deliver hover accessibility events 3487 // (they are a result of user touching the screen) so change of 3488 // the active window before all hover accessibility events from 3489 // the touched window are delivered is fine. 3490 final int oldActiveWindow = mSecurityPolicy.mActiveWindowId; 3491 setActiveWindowLocked(mFocusedWindowId); 3492 3493 // If there is no service that can operate with active windows 3494 // we keep accessibility focus behavior to constrain it only in 3495 // the active window. Look at updateAccessibilityFocusBehaviorLocked 3496 // for details. 3497 if (oldActiveWindow != mSecurityPolicy.mActiveWindowId 3498 && mAccessibilityFocusedWindowId == oldActiveWindow 3499 && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) { 3500 mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, 3501 oldActiveWindow, 0).sendToTarget(); 3502 } 3503 } 3504 } 3505 3506 public int getActiveWindowId() { 3507 if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) { 3508 mActiveWindowId = getFocusedWindowId(); 3509 } 3510 return mActiveWindowId; 3511 } 3512 3513 private void setActiveWindowLocked(int windowId) { 3514 if (mActiveWindowId != windowId) { 3515 mActiveWindowId = windowId; 3516 if (mWindows != null) { 3517 final int windowCount = mWindows.size(); 3518 for (int i = 0; i < windowCount; i++) { 3519 AccessibilityWindowInfo window = mWindows.get(i); 3520 window.setActive(window.getId() == windowId); 3521 } 3522 } 3523 notifyWindowsChanged(); 3524 } 3525 } 3526 3527 private void setAccessibilityFocusedWindowLocked(int windowId) { 3528 if (mAccessibilityFocusedWindowId != windowId) { 3529 mAccessibilityFocusedWindowId = windowId; 3530 if (mWindows != null) { 3531 final int windowCount = mWindows.size(); 3532 for (int i = 0; i < windowCount; i++) { 3533 AccessibilityWindowInfo window = mWindows.get(i); 3534 window.setAccessibilityFocused(window.getId() == windowId); 3535 } 3536 } 3537 3538 notifyWindowsChanged(); 3539 } 3540 } 3541 3542 private void notifyWindowsChanged() { 3543 if (mWindowsForAccessibilityCallback == null) { 3544 return; 3545 } 3546 final long identity = Binder.clearCallingIdentity(); 3547 try { 3548 // Let the client know the windows changed. 3549 AccessibilityEvent event = AccessibilityEvent.obtain( 3550 AccessibilityEvent.TYPE_WINDOWS_CHANGED); 3551 event.setEventTime(SystemClock.uptimeMillis()); 3552 sendAccessibilityEvent(event, mCurrentUserId); 3553 } finally { 3554 Binder.restoreCallingIdentity(identity); 3555 } 3556 } 3557 3558 public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) { 3559 return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId); 3560 } 3561 3562 public boolean canRetrieveWindowsLocked(Service service) { 3563 return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows; 3564 } 3565 3566 public boolean canRetrieveWindowContentLocked(Service service) { 3567 return (service.mAccessibilityServiceInfo.getCapabilities() 3568 & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; 3569 } 3570 3571 private int resolveProfileParentLocked(int userId) { 3572 if (userId != mCurrentUserId) { 3573 final long identity = Binder.clearCallingIdentity(); 3574 try { 3575 UserInfo parent = mUserManager.getProfileParent(userId); 3576 if (parent != null) { 3577 return parent.getUserHandle().getIdentifier(); 3578 } 3579 } finally { 3580 Binder.restoreCallingIdentity(identity); 3581 } 3582 } 3583 return userId; 3584 } 3585 3586 public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) { 3587 final int callingUid = Binder.getCallingUid(); 3588 if (callingUid == 0 3589 || callingUid == Process.SYSTEM_UID 3590 || callingUid == Process.SHELL_UID) { 3591 if (userId == UserHandle.USER_CURRENT 3592 || userId == UserHandle.USER_CURRENT_OR_SELF) { 3593 return mCurrentUserId; 3594 } 3595 return resolveProfileParentLocked(userId); 3596 } 3597 final int callingUserId = UserHandle.getUserId(callingUid); 3598 if (callingUserId == userId) { 3599 return resolveProfileParentLocked(userId); 3600 } 3601 final int callingUserParentId = resolveProfileParentLocked(callingUserId); 3602 if (callingUserParentId == mCurrentUserId && 3603 (userId == UserHandle.USER_CURRENT 3604 || userId == UserHandle.USER_CURRENT_OR_SELF)) { 3605 return mCurrentUserId; 3606 } 3607 if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS) 3608 && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) { 3609 throw new SecurityException("Call from user " + callingUserId + " as user " 3610 + userId + " without permission INTERACT_ACROSS_USERS or " 3611 + "INTERACT_ACROSS_USERS_FULL not allowed."); 3612 } 3613 if (userId == UserHandle.USER_CURRENT 3614 || userId == UserHandle.USER_CURRENT_OR_SELF) { 3615 return mCurrentUserId; 3616 } 3617 throw new IllegalArgumentException("Calling user can be changed to only " 3618 + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF."); 3619 } 3620 3621 public boolean isCallerInteractingAcrossUsers(int userId) { 3622 final int callingUid = Binder.getCallingUid(); 3623 return (Binder.getCallingPid() == android.os.Process.myPid() 3624 || callingUid == Process.SHELL_UID 3625 || userId == UserHandle.USER_CURRENT 3626 || userId == UserHandle.USER_CURRENT_OR_SELF); 3627 } 3628 3629 private boolean isRetrievalAllowingWindow(int windowId) { 3630 // The system gets to interact with any window it wants. 3631 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 3632 return true; 3633 } 3634 if (windowId == mActiveWindowId) { 3635 return true; 3636 } 3637 return findWindowById(windowId) != null; 3638 } 3639 3640 private AccessibilityWindowInfo findWindowById(int windowId) { 3641 if (mWindows != null) { 3642 final int windowCount = mWindows.size(); 3643 for (int i = 0; i < windowCount; i++) { 3644 AccessibilityWindowInfo window = mWindows.get(i); 3645 if (window.getId() == windowId) { 3646 return window; 3647 } 3648 } 3649 } 3650 return null; 3651 } 3652 3653 private void enforceCallingPermission(String permission, String function) { 3654 if (OWN_PROCESS_ID == Binder.getCallingPid()) { 3655 return; 3656 } 3657 if (!hasPermission(permission)) { 3658 throw new SecurityException("You do not have " + permission 3659 + " required to call " + function + " from pid=" 3660 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 3661 } 3662 } 3663 3664 private boolean hasPermission(String permission) { 3665 return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED; 3666 } 3667 3668 private int getFocusedWindowId() { 3669 IBinder token = mWindowManagerService.getFocusedWindowToken(); 3670 synchronized (mLock) { 3671 return findWindowIdLocked(token); 3672 } 3673 } 3674 } 3675 3676 private class UserState { 3677 public final int mUserId; 3678 3679 // Non-transient state. 3680 3681 public final RemoteCallbackList<IAccessibilityManagerClient> mClients = 3682 new RemoteCallbackList<>(); 3683 3684 public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections = 3685 new SparseArray<>(); 3686 3687 public final SparseArray<IBinder> mWindowTokens = new SparseArray<>(); 3688 3689 // Transient state. 3690 3691 public final CopyOnWriteArrayList<Service> mBoundServices = 3692 new CopyOnWriteArrayList<>(); 3693 3694 public final Map<ComponentName, Service> mComponentNameToServiceMap = 3695 new HashMap<>(); 3696 3697 public final List<AccessibilityServiceInfo> mInstalledServices = 3698 new ArrayList<>(); 3699 3700 public final Set<ComponentName> mBindingServices = new HashSet<>(); 3701 3702 public final Set<ComponentName> mEnabledServices = new HashSet<>(); 3703 3704 public final Set<ComponentName> mTouchExplorationGrantedServices = 3705 new HashSet<>(); 3706 3707 public int mHandledFeedbackTypes = 0; 3708 3709 public int mLastSentClientState = -1; 3710 3711 public boolean mIsAccessibilityEnabled; 3712 public boolean mIsTouchExplorationEnabled; 3713 public boolean mIsTextHighContrastEnabled; 3714 public boolean mIsEnhancedWebAccessibilityEnabled; 3715 public boolean mIsDisplayMagnificationEnabled; 3716 public boolean mIsFilterKeyEventsEnabled; 3717 public boolean mHasDisplayColorAdjustment; 3718 public boolean mAccessibilityFocusOnlyInActiveWindow; 3719 3720 private Service mUiAutomationService; 3721 private IAccessibilityServiceClient mUiAutomationServiceClient; 3722 3723 private IBinder mUiAutomationServiceOwner; 3724 private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient = 3725 new DeathRecipient() { 3726 @Override 3727 public void binderDied() { 3728 mUiAutomationServiceOwner.unlinkToDeath( 3729 mUiAutomationSerivceOnwerDeathRecipient, 0); 3730 mUiAutomationServiceOwner = null; 3731 if (mUiAutomationService != null) { 3732 mUiAutomationService.binderDied(); 3733 } 3734 } 3735 }; 3736 3737 public UserState(int userId) { 3738 mUserId = userId; 3739 } 3740 3741 public int getClientState() { 3742 int clientState = 0; 3743 if (mIsAccessibilityEnabled) { 3744 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED; 3745 } 3746 // Touch exploration relies on enabled accessibility. 3747 if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) { 3748 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; 3749 } 3750 if (mIsTextHighContrastEnabled) { 3751 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; 3752 } 3753 return clientState; 3754 } 3755 3756 public void onSwitchToAnotherUser() { 3757 // Clear UI test automation state. 3758 if (mUiAutomationService != null) { 3759 mUiAutomationService.binderDied(); 3760 } 3761 3762 // Unbind all services. 3763 unbindAllServicesLocked(this); 3764 3765 // Clear service management state. 3766 mBoundServices.clear(); 3767 mBindingServices.clear(); 3768 3769 // Clear event management state. 3770 mHandledFeedbackTypes = 0; 3771 mLastSentClientState = -1; 3772 3773 // Clear state persisted in settings. 3774 mEnabledServices.clear(); 3775 mTouchExplorationGrantedServices.clear(); 3776 mIsAccessibilityEnabled = false; 3777 mIsTouchExplorationEnabled = false; 3778 mIsEnhancedWebAccessibilityEnabled = false; 3779 mIsDisplayMagnificationEnabled = false; 3780 } 3781 3782 public void destroyUiAutomationService() { 3783 mUiAutomationService = null; 3784 mUiAutomationServiceClient = null; 3785 if (mUiAutomationServiceOwner != null) { 3786 mUiAutomationServiceOwner.unlinkToDeath( 3787 mUiAutomationSerivceOnwerDeathRecipient, 0); 3788 mUiAutomationServiceOwner = null; 3789 } 3790 } 3791 } 3792 3793 private final class AccessibilityContentObserver extends ContentObserver { 3794 3795 private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor( 3796 Settings.Secure.ACCESSIBILITY_ENABLED); 3797 3798 private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor( 3799 Settings.Secure.TOUCH_EXPLORATION_ENABLED); 3800 3801 private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor( 3802 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); 3803 3804 private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor( 3805 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 3806 3807 private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure 3808 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); 3809 3810 private final Uri mEnhancedWebAccessibilityUri = Settings.Secure 3811 .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION); 3812 3813 private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor( 3814 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 3815 3816 private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor( 3817 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED); 3818 3819 private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor( 3820 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER); 3821 3822 private final Uri mHighTextContrastUri = Settings.Secure.getUriFor( 3823 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED); 3824 3825 public AccessibilityContentObserver(Handler handler) { 3826 super(handler); 3827 } 3828 3829 public void register(ContentResolver contentResolver) { 3830 contentResolver.registerContentObserver(mAccessibilityEnabledUri, 3831 false, this, UserHandle.USER_ALL); 3832 contentResolver.registerContentObserver(mTouchExplorationEnabledUri, 3833 false, this, UserHandle.USER_ALL); 3834 contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri, 3835 false, this, UserHandle.USER_ALL); 3836 contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri, 3837 false, this, UserHandle.USER_ALL); 3838 contentResolver.registerContentObserver( 3839 mTouchExplorationGrantedAccessibilityServicesUri, 3840 false, this, UserHandle.USER_ALL); 3841 contentResolver.registerContentObserver(mEnhancedWebAccessibilityUri, 3842 false, this, UserHandle.USER_ALL); 3843 contentResolver.registerContentObserver( 3844 mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL); 3845 contentResolver.registerContentObserver( 3846 mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL); 3847 contentResolver.registerContentObserver( 3848 mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL); 3849 contentResolver.registerContentObserver( 3850 mHighTextContrastUri, false, this, UserHandle.USER_ALL); 3851 } 3852 3853 @Override 3854 public void onChange(boolean selfChange, Uri uri) { 3855 synchronized (mLock) { 3856 // Profiles share the accessibility state of the parent. Therefore, 3857 // we are checking for changes only the parent settings. 3858 UserState userState = getCurrentUserStateLocked(); 3859 3860 // We will update when the automation service dies. 3861 if (userState.mUiAutomationService != null) { 3862 return; 3863 } 3864 3865 if (mAccessibilityEnabledUri.equals(uri)) { 3866 if (readAccessibilityEnabledSettingLocked(userState)) { 3867 onUserStateChangedLocked(userState); 3868 } 3869 } else if (mTouchExplorationEnabledUri.equals(uri)) { 3870 if (readTouchExplorationEnabledSettingLocked(userState)) { 3871 onUserStateChangedLocked(userState); 3872 } 3873 } else if (mDisplayMagnificationEnabledUri.equals(uri)) { 3874 if (readDisplayMagnificationEnabledSettingLocked(userState)) { 3875 onUserStateChangedLocked(userState); 3876 } 3877 } else if (mEnabledAccessibilityServicesUri.equals(uri)) { 3878 if (readEnabledAccessibilityServicesLocked(userState)) { 3879 onUserStateChangedLocked(userState); 3880 } 3881 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) { 3882 if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) { 3883 onUserStateChangedLocked(userState); 3884 } 3885 } else if (mEnhancedWebAccessibilityUri.equals(uri)) { 3886 if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) { 3887 onUserStateChangedLocked(userState); 3888 } 3889 } else if (mDisplayInversionEnabledUri.equals(uri) 3890 || mDisplayDaltonizerEnabledUri.equals(uri) 3891 || mDisplayDaltonizerUri.equals(uri)) { 3892 if (readDisplayColorAdjustmentSettingsLocked(userState)) { 3893 updateDisplayColorAdjustmentSettingsLocked(userState); 3894 } 3895 } else if (mHighTextContrastUri.equals(uri)) { 3896 if (readHighTextContrastEnabledSettingLocked(userState)) { 3897 onUserStateChangedLocked(userState); 3898 } 3899 } 3900 } 3901 } 3902 } 3903 } 3904