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 import static android.view.Display.DEFAULT_DISPLAY; 21 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 22 23 import android.Manifest; 24 import android.accessibilityservice.AccessibilityService; 25 import android.accessibilityservice.AccessibilityServiceInfo; 26 import android.accessibilityservice.GestureDescription; 27 import android.accessibilityservice.IAccessibilityServiceClient; 28 import android.accessibilityservice.IAccessibilityServiceConnection; 29 import android.annotation.NonNull; 30 import android.app.AlertDialog; 31 import android.app.PendingIntent; 32 import android.app.StatusBarManager; 33 import android.app.UiAutomation; 34 import android.content.BroadcastReceiver; 35 import android.content.ComponentName; 36 import android.content.ContentResolver; 37 import android.content.Context; 38 import android.content.DialogInterface; 39 import android.content.DialogInterface.OnClickListener; 40 import android.content.Intent; 41 import android.content.IntentFilter; 42 import android.content.ServiceConnection; 43 import android.content.pm.PackageManager; 44 import android.content.pm.ParceledListSlice; 45 import android.content.pm.ResolveInfo; 46 import android.content.pm.ServiceInfo; 47 import android.content.pm.UserInfo; 48 import android.database.ContentObserver; 49 import android.graphics.Point; 50 import android.graphics.Rect; 51 import android.graphics.Region; 52 import android.hardware.display.DisplayManager; 53 import android.hardware.fingerprint.IFingerprintService; 54 import android.hardware.input.InputManager; 55 import android.media.AudioManagerInternal; 56 import android.net.Uri; 57 import android.os.Binder; 58 import android.os.Build; 59 import android.os.Bundle; 60 import android.os.Handler; 61 import android.os.IBinder; 62 import android.os.Looper; 63 import android.os.Message; 64 import android.os.PowerManager; 65 import android.os.Process; 66 import android.os.RemoteCallbackList; 67 import android.os.RemoteException; 68 import android.os.ServiceManager; 69 import android.os.SystemClock; 70 import android.os.UserHandle; 71 import android.os.UserManager; 72 import android.os.UserManagerInternal; 73 import android.provider.Settings; 74 import android.provider.SettingsStringUtil; 75 import android.provider.SettingsStringUtil.ComponentNameSet; 76 import android.provider.SettingsStringUtil.SettingStringHelper; 77 import android.text.TextUtils; 78 import android.text.TextUtils.SimpleStringSplitter; 79 import android.util.IntArray; 80 import android.util.Slog; 81 import android.util.SparseArray; 82 import android.view.Display; 83 import android.view.IWindow; 84 import android.view.InputDevice; 85 import android.view.KeyCharacterMap; 86 import android.view.KeyEvent; 87 import android.view.MagnificationSpec; 88 import android.view.View; 89 import android.view.WindowInfo; 90 import android.view.WindowManager; 91 import android.view.WindowManagerInternal; 92 import android.view.accessibility.AccessibilityCache; 93 import android.view.accessibility.AccessibilityEvent; 94 import android.view.accessibility.AccessibilityInteractionClient; 95 import android.view.accessibility.AccessibilityManager; 96 import android.view.accessibility.AccessibilityNodeInfo; 97 import android.view.accessibility.AccessibilityWindowInfo; 98 import android.view.accessibility.IAccessibilityInteractionConnection; 99 import android.view.accessibility.IAccessibilityInteractionConnectionCallback; 100 import android.view.accessibility.IAccessibilityManager; 101 import android.view.accessibility.IAccessibilityManagerClient; 102 103 import com.android.internal.R; 104 import com.android.internal.annotations.GuardedBy; 105 import com.android.internal.content.PackageMonitor; 106 import com.android.internal.os.SomeArgs; 107 import com.android.internal.util.DumpUtils; 108 import com.android.internal.util.IntPair; 109 import com.android.server.LocalServices; 110 import com.android.server.policy.AccessibilityShortcutController; 111 import com.android.server.statusbar.StatusBarManagerInternal; 112 113 import org.xmlpull.v1.XmlPullParserException; 114 115 import java.io.FileDescriptor; 116 import java.io.IOException; 117 import java.io.PrintWriter; 118 import java.util.ArrayList; 119 import java.util.Arrays; 120 import java.util.Collections; 121 import java.util.HashMap; 122 import java.util.HashSet; 123 import java.util.Iterator; 124 import java.util.List; 125 import java.util.Map; 126 import java.util.Set; 127 import java.util.concurrent.CopyOnWriteArrayList; 128 import java.util.function.Consumer; 129 130 /** 131 * This class is instantiated by the system as a system level service and can be 132 * accessed only by the system. The task of this service is to be a centralized 133 * event dispatch for {@link AccessibilityEvent}s generated across all processes 134 * on the device. Events are dispatched to {@link AccessibilityService}s. 135 */ 136 public class AccessibilityManagerService extends IAccessibilityManager.Stub { 137 138 private static final boolean DEBUG = false; 139 140 private static final String LOG_TAG = "AccessibilityManagerService"; 141 142 // TODO: This is arbitrary. When there is time implement this by watching 143 // when that accessibility services are bound. 144 private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000; 145 146 private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000; 147 148 // TODO: Restructure service initialization so services aren't connected before all of 149 // their capabilities are ready. 150 private static final int WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS = 1000; 151 152 private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE = 153 "registerUiTestAutomationService"; 154 155 private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED = 156 "temporaryEnableAccessibilityStateUntilKeyguardRemoved"; 157 158 private static final String GET_WINDOW_TOKEN = "getWindowToken"; 159 160 private static final String SET_PIP_ACTION_REPLACEMENT = 161 "setPictureInPictureActionReplacingConnection"; 162 163 private static final ComponentName sFakeAccessibilityServiceComponentName = 164 new ComponentName("foo.bar", "FakeService"); 165 166 private static final String FUNCTION_DUMP = "dump"; 167 168 private static final char COMPONENT_NAME_SEPARATOR = ':'; 169 170 private static final int OWN_PROCESS_ID = android.os.Process.myPid(); 171 172 // Each service has an ID. Also provide one for magnification gesture handling 173 public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0; 174 175 private static int sIdCounter = MAGNIFICATION_GESTURE_HANDLER_ID + 1; 176 177 private static int sNextWindowId; 178 179 private final Context mContext; 180 181 private final Object mLock = new Object(); 182 183 private final SimpleStringSplitter mStringColonSplitter = 184 new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); 185 186 private final Rect mTempRect = new Rect(); 187 188 private final Rect mTempRect1 = new Rect(); 189 190 private final Point mTempPoint = new Point(); 191 192 private final PackageManager mPackageManager; 193 194 private final PowerManager mPowerManager; 195 196 private final WindowManagerInternal mWindowManagerService; 197 198 private final SecurityPolicy mSecurityPolicy; 199 200 private final MainHandler mMainHandler; 201 202 private MagnificationController mMagnificationController; 203 204 private InteractionBridge mInteractionBridge; 205 206 private AlertDialog mEnableTouchExplorationDialog; 207 208 private AccessibilityInputFilter mInputFilter; 209 210 private boolean mHasInputFilter; 211 212 private KeyEventDispatcher mKeyEventDispatcher; 213 214 private MotionEventInjector mMotionEventInjector; 215 216 private FingerprintGestureDispatcher mFingerprintGestureDispatcher; 217 218 private final Set<ComponentName> mTempComponentNameSet = new HashSet<>(); 219 220 private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList = 221 new ArrayList<>(); 222 223 private final IntArray mTempIntArray = new IntArray(0); 224 225 private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients = 226 new RemoteCallbackList<>(); 227 228 private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections = 229 new SparseArray<>(); 230 231 private AccessibilityConnectionWrapper mPictureInPictureActionReplacingConnection; 232 233 private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>(); 234 235 private final SparseArray<UserState> mUserStates = new SparseArray<>(); 236 237 private final UserManager mUserManager; 238 239 private int mCurrentUserId = UserHandle.USER_SYSTEM; 240 241 //TODO: Remove this hack 242 private boolean mInitialized; 243 244 private WindowsForAccessibilityCallback mWindowsForAccessibilityCallback; 245 246 private boolean mIsAccessibilityButtonShown; 247 248 private UserState getCurrentUserStateLocked() { 249 return getUserStateLocked(mCurrentUserId); 250 } 251 252 /** 253 * Creates a new instance. 254 * 255 * @param context A {@link Context} instance. 256 */ 257 public AccessibilityManagerService(Context context) { 258 mContext = context; 259 mPackageManager = mContext.getPackageManager(); 260 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 261 mWindowManagerService = LocalServices.getService(WindowManagerInternal.class); 262 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 263 mSecurityPolicy = new SecurityPolicy(); 264 mMainHandler = new MainHandler(mContext.getMainLooper()); 265 registerBroadcastReceivers(); 266 new AccessibilityContentObserver(mMainHandler).register( 267 context.getContentResolver()); 268 } 269 270 private UserState getUserStateLocked(int userId) { 271 UserState state = mUserStates.get(userId); 272 if (state == null) { 273 state = new UserState(userId); 274 mUserStates.put(userId, state); 275 } 276 return state; 277 } 278 279 private void registerBroadcastReceivers() { 280 PackageMonitor monitor = new PackageMonitor() { 281 @Override 282 public void onSomePackagesChanged() { 283 synchronized (mLock) { 284 // Only the profile parent can install accessibility services. 285 // Therefore we ignore packages from linked profiles. 286 if (getChangingUserId() != mCurrentUserId) { 287 return; 288 } 289 // We will update when the automation service dies. 290 UserState userState = getCurrentUserStateLocked(); 291 // We have to reload the installed services since some services may 292 // have different attributes, resolve info (does not support equals), 293 // etc. Remove them then to force reload. 294 userState.mInstalledServices.clear(); 295 if (!userState.isUiAutomationSuppressingOtherServices()) { 296 if (readConfigurationForUserStateLocked(userState)) { 297 onUserStateChangedLocked(userState); 298 } 299 } 300 } 301 } 302 303 @Override 304 public void onPackageUpdateFinished(String packageName, int uid) { 305 // Unbind all services from this package, and then update the user state to 306 // re-bind new versions of them. 307 synchronized (mLock) { 308 final int userId = getChangingUserId(); 309 if (userId != mCurrentUserId) { 310 return; 311 } 312 UserState userState = getUserStateLocked(userId); 313 boolean unboundAService = false; 314 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 315 Service boundService = userState.mBoundServices.get(i); 316 String servicePkg = boundService.mComponentName.getPackageName(); 317 if (servicePkg.equals(packageName)) { 318 boundService.unbindLocked(); 319 unboundAService = true; 320 } 321 } 322 if (unboundAService) { 323 onUserStateChangedLocked(userState); 324 } 325 } 326 } 327 328 @Override 329 public void onPackageRemoved(String packageName, int uid) { 330 synchronized (mLock) { 331 final int userId = getChangingUserId(); 332 // Only the profile parent can install accessibility services. 333 // Therefore we ignore packages from linked profiles. 334 if (userId != mCurrentUserId) { 335 return; 336 } 337 UserState userState = getUserStateLocked(userId); 338 Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 339 while (it.hasNext()) { 340 ComponentName comp = it.next(); 341 String compPkg = comp.getPackageName(); 342 if (compPkg.equals(packageName)) { 343 it.remove(); 344 // Update the enabled services setting. 345 persistComponentNamesToSettingLocked( 346 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 347 userState.mEnabledServices, userId); 348 // Update the touch exploration granted services setting. 349 userState.mTouchExplorationGrantedServices.remove(comp); 350 persistComponentNamesToSettingLocked( 351 Settings.Secure. 352 TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 353 userState.mTouchExplorationGrantedServices, userId); 354 // We will update when the automation service dies. 355 if (!userState.isUiAutomationSuppressingOtherServices()) { 356 onUserStateChangedLocked(userState); 357 } 358 return; 359 } 360 } 361 } 362 } 363 364 @Override 365 public boolean onHandleForceStop(Intent intent, String[] packages, 366 int uid, boolean doit) { 367 synchronized (mLock) { 368 final int userId = getChangingUserId(); 369 // Only the profile parent can install accessibility services. 370 // Therefore we ignore packages from linked profiles. 371 if (userId != mCurrentUserId) { 372 return false; 373 } 374 UserState userState = getUserStateLocked(userId); 375 Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 376 while (it.hasNext()) { 377 ComponentName comp = it.next(); 378 String compPkg = comp.getPackageName(); 379 for (String pkg : packages) { 380 if (compPkg.equals(pkg)) { 381 if (!doit) { 382 return true; 383 } 384 it.remove(); 385 persistComponentNamesToSettingLocked( 386 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 387 userState.mEnabledServices, userId); 388 // We will update when the automation service dies. 389 if (!userState.isUiAutomationSuppressingOtherServices()) { 390 onUserStateChangedLocked(userState); 391 } 392 } 393 } 394 } 395 return false; 396 } 397 } 398 }; 399 400 // package changes 401 monitor.register(mContext, null, UserHandle.ALL, true); 402 403 // user change and unlock 404 IntentFilter intentFilter = new IntentFilter(); 405 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 406 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); 407 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 408 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 409 intentFilter.addAction(Intent.ACTION_SETTING_RESTORED); 410 411 mContext.registerReceiverAsUser(new BroadcastReceiver() { 412 @Override 413 public void onReceive(Context context, Intent intent) { 414 String action = intent.getAction(); 415 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 416 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 417 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { 418 unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 419 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 420 removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 421 } else if (Intent.ACTION_USER_PRESENT.equals(action)) { 422 // We will update when the automation service dies. 423 synchronized (mLock) { 424 UserState userState = getCurrentUserStateLocked(); 425 if (!userState.isUiAutomationSuppressingOtherServices()) { 426 if (readConfigurationForUserStateLocked(userState)) { 427 onUserStateChangedLocked(userState); 428 } 429 } 430 } 431 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { 432 final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); 433 if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) { 434 synchronized (mLock) { 435 restoreEnabledAccessibilityServicesLocked( 436 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE), 437 intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)); 438 } 439 } 440 } 441 } 442 }, UserHandle.ALL, intentFilter, null, null); 443 } 444 445 @Override 446 public long addClient(IAccessibilityManagerClient client, int userId) { 447 synchronized (mLock) { 448 // We treat calls from a profile as if made by its parent as profiles 449 // share the accessibility state of the parent. The call below 450 // performs the current profile parent resolution. 451 final int resolvedUserId = mSecurityPolicy 452 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 453 // If the client is from a process that runs across users such as 454 // the system UI or the system we add it to the global state that 455 // is shared across users. 456 UserState userState = getUserStateLocked(resolvedUserId); 457 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 458 mGlobalClients.register(client); 459 if (DEBUG) { 460 Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid()); 461 } 462 return IntPair.of( 463 userState.getClientState(), userState.mLastSentRelevantEventTypes); 464 } else { 465 userState.mUserClients.register(client); 466 // If this client is not for the current user we do not 467 // return a state since it is not for the foreground user. 468 // We will send the state to the client on a user switch. 469 if (DEBUG) { 470 Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid() 471 + " and userId:" + mCurrentUserId); 472 } 473 return IntPair.of( 474 (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0, 475 userState.mLastSentRelevantEventTypes); 476 } 477 } 478 } 479 480 @Override 481 public void sendAccessibilityEvent(AccessibilityEvent event, int userId) { 482 boolean dispatchEvent = false; 483 484 synchronized (mLock) { 485 if (event.getWindowId() == 486 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) { 487 // The replacer window isn't shown to services. Move its events into the pip. 488 AccessibilityWindowInfo pip = mSecurityPolicy.getPictureInPictureWindow(); 489 if (pip != null) { 490 int pipId = pip.getId(); 491 event.setWindowId(pipId); 492 event.setSealed(true); 493 AccessibilityNodeInfo info = event.getSource(); 494 info.setSealed(false); 495 event.setSealed(false); 496 if (info != null) { 497 info.setSourceNodeId(info.getSourceNodeId(), pipId); 498 event.setSource(info); 499 info.recycle(); 500 } 501 } 502 } 503 504 // We treat calls from a profile as if made by its parent as profiles 505 // share the accessibility state of the parent. The call below 506 // performs the current profile parent resolution.. 507 final int resolvedUserId = mSecurityPolicy 508 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 509 // This method does nothing for a background user. 510 if (resolvedUserId == mCurrentUserId) { 511 if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) { 512 mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked( 513 event.getWindowId(), event.getSourceNodeId(), 514 event.getEventType(), event.getAction()); 515 mSecurityPolicy.updateEventSourceLocked(event); 516 dispatchEvent = true; 517 } 518 if (mHasInputFilter && mInputFilter != null) { 519 mMainHandler.obtainMessage( 520 MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER, 521 AccessibilityEvent.obtain(event)).sendToTarget(); 522 } 523 } 524 } 525 526 if (dispatchEvent) { 527 // Make sure clients receiving this event will be able to get the 528 // current state of the windows as the window manager may be delaying 529 // the computation for performance reasons. 530 if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 531 && mWindowsForAccessibilityCallback != null) { 532 WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class); 533 wm.computeWindowsForAccessibility(); 534 } 535 synchronized (mLock) { 536 notifyAccessibilityServicesDelayedLocked(event, false); 537 notifyAccessibilityServicesDelayedLocked(event, true); 538 } 539 } 540 541 if (OWN_PROCESS_ID != Binder.getCallingPid()) { 542 event.recycle(); 543 } 544 } 545 546 @Override 547 public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) { 548 synchronized (mLock) { 549 // We treat calls from a profile as if made by its parent as profiles 550 // share the accessibility state of the parent. The call below 551 // performs the current profile parent resolution. 552 final int resolvedUserId = mSecurityPolicy 553 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 554 // The automation service is a fake one and should not be reported 555 // to clients as being installed - it really is not. 556 UserState userState = getUserStateLocked(resolvedUserId); 557 if (userState.mUiAutomationService != null) { 558 List<AccessibilityServiceInfo> installedServices = new ArrayList<>(); 559 installedServices.addAll(userState.mInstalledServices); 560 installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo); 561 return installedServices; 562 } 563 return userState.mInstalledServices; 564 } 565 } 566 567 @Override 568 public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, 569 int userId) { 570 synchronized (mLock) { 571 // We treat calls from a profile as if made by its parent as profiles 572 // share the accessibility state of the parent. The call below 573 // performs the current profile parent resolution. 574 final int resolvedUserId = mSecurityPolicy 575 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 576 577 // The automation service can suppress other services. 578 final UserState userState = getUserStateLocked(resolvedUserId); 579 if (userState.isUiAutomationSuppressingOtherServices()) { 580 return Collections.emptyList(); 581 } 582 583 final List<Service> services = userState.mBoundServices; 584 final int serviceCount = services.size(); 585 final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount); 586 for (int i = 0; i < serviceCount; ++i) { 587 final Service service = services.get(i); 588 // Don't report the UIAutomation (fake service) 589 if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName) 590 && (service.mFeedbackType & feedbackType) != 0) { 591 result.add(service.mAccessibilityServiceInfo); 592 } 593 } 594 return result; 595 } 596 } 597 598 @Override 599 public void interrupt(int userId) { 600 List<IAccessibilityServiceClient> interfacesToInterrupt; 601 synchronized (mLock) { 602 // We treat calls from a profile as if made by its parent as profiles 603 // share the accessibility state of the parent. The call below 604 // performs the current profile parent resolution. 605 final int resolvedUserId = mSecurityPolicy 606 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 607 // This method does nothing for a background user. 608 if (resolvedUserId != mCurrentUserId) { 609 return; 610 } 611 List<Service> services = getUserStateLocked(resolvedUserId).mBoundServices; 612 int numServices = services.size(); 613 interfacesToInterrupt = new ArrayList<>(numServices); 614 for (int i = 0; i < numServices; i++) { 615 Service service = services.get(i); 616 IBinder a11yServiceBinder = service.mService; 617 IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface; 618 if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) { 619 interfacesToInterrupt.add(a11yServiceInterface); 620 } 621 } 622 } 623 for (int i = 0, count = interfacesToInterrupt.size(); i < count; i++) { 624 try { 625 interfacesToInterrupt.get(i).onInterrupt(); 626 } catch (RemoteException re) { 627 Slog.e(LOG_TAG, "Error sending interrupt request to " 628 + interfacesToInterrupt.get(i), re); 629 } 630 } 631 } 632 633 @Override 634 public int addAccessibilityInteractionConnection(IWindow windowToken, 635 IAccessibilityInteractionConnection connection, int userId) throws RemoteException { 636 synchronized (mLock) { 637 // We treat calls from a profile as if made by its parent as profiles 638 // share the accessibility state of the parent. The call below 639 // performs the current profile parent resolution. 640 final int resolvedUserId = mSecurityPolicy 641 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 642 final int windowId = sNextWindowId++; 643 // If the window is from a process that runs across users such as 644 // the system UI or the system we add it to the global state that 645 // is shared across users. 646 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 647 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 648 windowId, connection, UserHandle.USER_ALL); 649 wrapper.linkToDeath(); 650 mGlobalInteractionConnections.put(windowId, wrapper); 651 mGlobalWindowTokens.put(windowId, windowToken.asBinder()); 652 if (DEBUG) { 653 Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid() 654 + " with windowId: " + windowId + " and token: " + windowToken.asBinder()); 655 } 656 } else { 657 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 658 windowId, connection, resolvedUserId); 659 wrapper.linkToDeath(); 660 UserState userState = getUserStateLocked(resolvedUserId); 661 userState.mInteractionConnections.put(windowId, wrapper); 662 userState.mWindowTokens.put(windowId, windowToken.asBinder()); 663 if (DEBUG) { 664 Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid() 665 + " with windowId: " + windowId + " and userId:" + mCurrentUserId 666 + " and token: " + windowToken.asBinder()); 667 } 668 } 669 return windowId; 670 } 671 } 672 673 @Override 674 public void removeAccessibilityInteractionConnection(IWindow window) { 675 synchronized (mLock) { 676 // We treat calls from a profile as if made by its parent as profiles 677 // share the accessibility state of the parent. The call below 678 // performs the current profile parent resolution. 679 mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( 680 UserHandle.getCallingUserId()); 681 IBinder token = window.asBinder(); 682 final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked( 683 token, mGlobalWindowTokens, mGlobalInteractionConnections); 684 if (removedWindowId >= 0) { 685 if (DEBUG) { 686 Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid() 687 + " with windowId: " + removedWindowId + " and token: " + window.asBinder()); 688 } 689 return; 690 } 691 final int userCount = mUserStates.size(); 692 for (int i = 0; i < userCount; i++) { 693 UserState userState = mUserStates.valueAt(i); 694 final int removedWindowIdForUser = 695 removeAccessibilityInteractionConnectionInternalLocked( 696 token, userState.mWindowTokens, userState.mInteractionConnections); 697 if (removedWindowIdForUser >= 0) { 698 if (DEBUG) { 699 Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid() 700 + " with windowId: " + removedWindowIdForUser + " and userId:" 701 + mUserStates.keyAt(i) + " and token: " + window.asBinder()); 702 } 703 return; 704 } 705 } 706 } 707 } 708 709 private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, 710 SparseArray<IBinder> windowTokens, 711 SparseArray<AccessibilityConnectionWrapper> interactionConnections) { 712 final int count = windowTokens.size(); 713 for (int i = 0; i < count; i++) { 714 if (windowTokens.valueAt(i) == windowToken) { 715 final int windowId = windowTokens.keyAt(i); 716 windowTokens.removeAt(i); 717 AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId); 718 wrapper.unlinkToDeath(); 719 interactionConnections.remove(windowId); 720 return windowId; 721 } 722 } 723 return -1; 724 } 725 726 @Override 727 public void setPictureInPictureActionReplacingConnection( 728 IAccessibilityInteractionConnection connection) throws RemoteException { 729 mSecurityPolicy.enforceCallingPermission(Manifest.permission.MODIFY_ACCESSIBILITY_DATA, 730 SET_PIP_ACTION_REPLACEMENT); 731 synchronized (mLock) { 732 if (mPictureInPictureActionReplacingConnection != null) { 733 mPictureInPictureActionReplacingConnection.unlinkToDeath(); 734 mPictureInPictureActionReplacingConnection = null; 735 } 736 if (connection != null) { 737 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 738 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID, 739 connection, UserHandle.USER_ALL); 740 mPictureInPictureActionReplacingConnection = wrapper; 741 wrapper.linkToDeath(); 742 } 743 mSecurityPolicy.notifyWindowsChanged(); 744 } 745 } 746 747 @Override 748 public void registerUiTestAutomationService(IBinder owner, 749 IAccessibilityServiceClient serviceClient, 750 AccessibilityServiceInfo accessibilityServiceInfo, 751 int flags) { 752 mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT, 753 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE); 754 755 accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName); 756 757 synchronized (mLock) { 758 UserState userState = getCurrentUserStateLocked(); 759 760 if (userState.mUiAutomationService != null) { 761 throw new IllegalStateException("UiAutomationService " + serviceClient 762 + "already registered!"); 763 } 764 765 try { 766 owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0); 767 } catch (RemoteException re) { 768 Slog.e(LOG_TAG, "Couldn't register for the death of a" 769 + " UiTestAutomationService!", re); 770 return; 771 } 772 773 userState.mUiAutomationServiceOwner = owner; 774 userState.mUiAutomationServiceClient = serviceClient; 775 userState.mUiAutomationFlags = flags; 776 userState.mInstalledServices.add(accessibilityServiceInfo); 777 if ((flags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0) { 778 // Set the temporary state, and use it instead of settings 779 userState.mIsTouchExplorationEnabled = false; 780 userState.mIsDisplayMagnificationEnabled = false; 781 userState.mIsNavBarMagnificationEnabled = false; 782 userState.mIsAutoclickEnabled = false; 783 userState.mEnabledServices.clear(); 784 } 785 userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName); 786 userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName); 787 788 // Use the new state instead of settings. 789 onUserStateChangedLocked(userState); 790 } 791 } 792 793 @Override 794 public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) { 795 synchronized (mLock) { 796 UserState userState = getCurrentUserStateLocked(); 797 // Automation service is not bound, so pretend it died to perform clean up. 798 if (userState.mUiAutomationService != null 799 && serviceClient != null 800 && userState.mUiAutomationService.mServiceInterface != null 801 && userState.mUiAutomationService.mServiceInterface.asBinder() 802 == serviceClient.asBinder()) { 803 userState.mUiAutomationService.binderDied(); 804 } else { 805 throw new IllegalStateException("UiAutomationService " + serviceClient 806 + " not registered!"); 807 } 808 } 809 } 810 811 @Override 812 public void temporaryEnableAccessibilityStateUntilKeyguardRemoved( 813 ComponentName service, boolean touchExplorationEnabled) { 814 mSecurityPolicy.enforceCallingPermission( 815 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY, 816 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED); 817 if (!mWindowManagerService.isKeyguardLocked()) { 818 return; 819 } 820 synchronized (mLock) { 821 // Set the temporary state. 822 UserState userState = getCurrentUserStateLocked(); 823 824 // This is a nop if UI automation is enabled. 825 if (userState.isUiAutomationSuppressingOtherServices()) { 826 return; 827 } 828 829 userState.mIsTouchExplorationEnabled = touchExplorationEnabled; 830 userState.mIsDisplayMagnificationEnabled = false; 831 userState.mIsNavBarMagnificationEnabled = false; 832 userState.mIsAutoclickEnabled = false; 833 userState.mEnabledServices.clear(); 834 userState.mEnabledServices.add(service); 835 userState.mBindingServices.clear(); 836 userState.mTouchExplorationGrantedServices.clear(); 837 userState.mTouchExplorationGrantedServices.add(service); 838 839 // User the current state instead settings. 840 onUserStateChangedLocked(userState); 841 } 842 } 843 844 @Override 845 public IBinder getWindowToken(int windowId, int userId) { 846 mSecurityPolicy.enforceCallingPermission( 847 Manifest.permission.RETRIEVE_WINDOW_TOKEN, 848 GET_WINDOW_TOKEN); 849 synchronized (mLock) { 850 // We treat calls from a profile as if made by its parent as profiles 851 // share the accessibility state of the parent. The call below 852 // performs the current profile parent resolution. 853 final int resolvedUserId = mSecurityPolicy 854 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 855 if (resolvedUserId != mCurrentUserId) { 856 return null; 857 } 858 if (mSecurityPolicy.findWindowById(windowId) == null) { 859 return null; 860 } 861 IBinder token = mGlobalWindowTokens.get(windowId); 862 if (token != null) { 863 return token; 864 } 865 return getCurrentUserStateLocked().mWindowTokens.get(windowId); 866 } 867 } 868 869 /** 870 * Invoked remotely over AIDL by SysUi when the accessibility button within the system's 871 * navigation area has been clicked. 872 */ 873 @Override 874 public void notifyAccessibilityButtonClicked() { 875 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE) 876 != PackageManager.PERMISSION_GRANTED) { 877 throw new SecurityException("Caller does not hold permission " 878 + android.Manifest.permission.STATUS_BAR_SERVICE); 879 } 880 synchronized (mLock) { 881 notifyAccessibilityButtonClickedLocked(); 882 } 883 } 884 885 /** 886 * Invoked remotely over AIDL by SysUi when the visibility of the accessibility 887 * button within the system's navigation area has changed. 888 * 889 * @param shown {@code true} if the accessibility button is shown to the 890 * user, {@code false} otherwise 891 */ 892 @Override 893 public void notifyAccessibilityButtonVisibilityChanged(boolean shown) { 894 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE) 895 != PackageManager.PERMISSION_GRANTED) { 896 throw new SecurityException("Caller does not hold permission " 897 + android.Manifest.permission.STATUS_BAR_SERVICE); 898 } 899 synchronized (mLock) { 900 notifyAccessibilityButtonVisibilityChangedLocked(shown); 901 } 902 } 903 904 905 boolean onGesture(int gestureId) { 906 synchronized (mLock) { 907 boolean handled = notifyGestureLocked(gestureId, false); 908 if (!handled) { 909 handled = notifyGestureLocked(gestureId, true); 910 } 911 return handled; 912 } 913 } 914 915 boolean notifyKeyEvent(KeyEvent event, int policyFlags) { 916 synchronized (mLock) { 917 List<Service> boundServices = getCurrentUserStateLocked().mBoundServices; 918 if (boundServices.isEmpty()) { 919 return false; 920 } 921 return getKeyEventDispatcher().notifyKeyEventLocked(event, policyFlags, boundServices); 922 } 923 } 924 925 /** 926 * Called by the MagnificationController when the state of display 927 * magnification changes. 928 * 929 * @param region the new magnified region, may be empty if 930 * magnification is not enabled (e.g. scale is 1) 931 * @param scale the new scale 932 * @param centerX the new screen-relative center X coordinate 933 * @param centerY the new screen-relative center Y coordinate 934 */ 935 public void notifyMagnificationChanged(@NonNull Region region, 936 float scale, float centerX, float centerY) { 937 synchronized (mLock) { 938 notifyClearAccessibilityCacheLocked(); 939 notifyMagnificationChangedLocked(region, scale, centerX, centerY); 940 } 941 } 942 943 /** 944 * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector. 945 * Not using a getter because the AccessibilityInputFilter isn't thread-safe 946 * 947 * @param motionEventInjector The new value of the motionEventInjector. May be null. 948 */ 949 void setMotionEventInjector(MotionEventInjector motionEventInjector) { 950 synchronized (mLock) { 951 mMotionEventInjector = motionEventInjector; 952 // We may be waiting on this object being set 953 mLock.notifyAll(); 954 } 955 } 956 957 /** 958 * Gets a point within the accessibility focused node where we can send down 959 * and up events to perform a click. 960 * 961 * @param outPoint The click point to populate. 962 * @return Whether accessibility a click point was found and set. 963 */ 964 // TODO: (multi-display) Make sure this works for multiple displays. 965 boolean getAccessibilityFocusClickPointInScreen(Point outPoint) { 966 return getInteractionBridge().getAccessibilityFocusClickPointInScreenNotLocked(outPoint); 967 } 968 969 /** 970 * Perform an accessibility action on the view that currently has accessibility focus. 971 * Has no effect if no item has accessibility focus, if the item with accessibility 972 * focus does not expose the specified action, or if the action fails. 973 * 974 * @param actionId The id of the action to perform. 975 * 976 * @return {@code true} if the action was performed. {@code false} if it was not. 977 */ 978 public boolean performActionOnAccessibilityFocusedItem( 979 AccessibilityNodeInfo.AccessibilityAction action) { 980 return getInteractionBridge().performActionOnAccessibilityFocusedItemNotLocked(action); 981 } 982 983 /** 984 * Gets the bounds of a window. 985 * 986 * @param outBounds The output to which to write the bounds. 987 */ 988 boolean getWindowBounds(int windowId, Rect outBounds) { 989 IBinder token; 990 synchronized (mLock) { 991 token = mGlobalWindowTokens.get(windowId); 992 if (token == null) { 993 token = getCurrentUserStateLocked().mWindowTokens.get(windowId); 994 } 995 } 996 mWindowManagerService.getWindowFrame(token, outBounds); 997 if (!outBounds.isEmpty()) { 998 return true; 999 } 1000 return false; 1001 } 1002 1003 boolean accessibilityFocusOnlyInActiveWindow() { 1004 synchronized (mLock) { 1005 return mWindowsForAccessibilityCallback == null; 1006 } 1007 } 1008 1009 int getActiveWindowId() { 1010 return mSecurityPolicy.getActiveWindowId(); 1011 } 1012 1013 void onTouchInteractionStart() { 1014 mSecurityPolicy.onTouchInteractionStart(); 1015 } 1016 1017 void onTouchInteractionEnd() { 1018 mSecurityPolicy.onTouchInteractionEnd(); 1019 } 1020 1021 private void switchUser(int userId) { 1022 synchronized (mLock) { 1023 if (mCurrentUserId == userId && mInitialized) { 1024 return; 1025 } 1026 1027 // Disconnect from services for the old user. 1028 UserState oldUserState = getCurrentUserStateLocked(); 1029 oldUserState.onSwitchToAnotherUser(); 1030 1031 // Disable the local managers for the old user. 1032 if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) { 1033 mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER, 1034 oldUserState.mUserId, 0).sendToTarget(); 1035 } 1036 1037 // Announce user changes only if more that one exist. 1038 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1039 final boolean announceNewUser = userManager.getUsers().size() > 1; 1040 1041 // The user changed. 1042 mCurrentUserId = userId; 1043 1044 UserState userState = getCurrentUserStateLocked(); 1045 if (userState.mUiAutomationService != null) { 1046 // Switching users disables the UI automation service. 1047 userState.mUiAutomationService.binderDied(); 1048 } 1049 1050 readConfigurationForUserStateLocked(userState); 1051 // Even if reading did not yield change, we have to update 1052 // the state since the context in which the current user 1053 // state was used has changed since it was inactive. 1054 onUserStateChangedLocked(userState); 1055 1056 if (announceNewUser) { 1057 // Schedule announcement of the current user if needed. 1058 mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED, 1059 WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS); 1060 } 1061 } 1062 } 1063 1064 private void unlockUser(int userId) { 1065 synchronized (mLock) { 1066 int parentUserId = mSecurityPolicy.resolveProfileParentLocked(userId); 1067 if (parentUserId == mCurrentUserId) { 1068 UserState userState = getUserStateLocked(mCurrentUserId); 1069 onUserStateChangedLocked(userState); 1070 } 1071 } 1072 } 1073 1074 private void removeUser(int userId) { 1075 synchronized (mLock) { 1076 mUserStates.remove(userId); 1077 } 1078 } 1079 1080 // Called only during settings restore; currently supports only the owner user 1081 // TODO: http://b/22388012 1082 void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting) { 1083 readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false); 1084 readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true); 1085 1086 UserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); 1087 userState.mEnabledServices.clear(); 1088 userState.mEnabledServices.addAll(mTempComponentNameSet); 1089 persistComponentNamesToSettingLocked( 1090 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 1091 userState.mEnabledServices, 1092 UserHandle.USER_SYSTEM); 1093 onUserStateChangedLocked(userState); 1094 } 1095 1096 private InteractionBridge getInteractionBridge() { 1097 synchronized (mLock) { 1098 if (mInteractionBridge == null) { 1099 mInteractionBridge = new InteractionBridge(); 1100 } 1101 return mInteractionBridge; 1102 } 1103 } 1104 1105 private boolean notifyGestureLocked(int gestureId, boolean isDefault) { 1106 // TODO: Now we are giving the gestures to the last enabled 1107 // service that can handle them which is the last one 1108 // in our list since we write the last enabled as the 1109 // last record in the enabled services setting. Ideally, 1110 // the user should make the call which service handles 1111 // gestures. However, only one service should handle 1112 // gestures to avoid user frustration when different 1113 // behavior is observed from different combinations of 1114 // enabled accessibility services. 1115 UserState state = getCurrentUserStateLocked(); 1116 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1117 Service service = state.mBoundServices.get(i); 1118 if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) { 1119 service.notifyGesture(gestureId); 1120 return true; 1121 } 1122 } 1123 return false; 1124 } 1125 1126 private void notifyClearAccessibilityCacheLocked() { 1127 UserState state = getCurrentUserStateLocked(); 1128 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1129 Service service = state.mBoundServices.get(i); 1130 service.notifyClearAccessibilityNodeInfoCache(); 1131 } 1132 } 1133 1134 private void notifyMagnificationChangedLocked(@NonNull Region region, 1135 float scale, float centerX, float centerY) { 1136 final UserState state = getCurrentUserStateLocked(); 1137 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1138 final Service service = state.mBoundServices.get(i); 1139 service.notifyMagnificationChangedLocked(region, scale, centerX, centerY); 1140 } 1141 } 1142 1143 private void notifySoftKeyboardShowModeChangedLocked(int showMode) { 1144 final UserState state = getCurrentUserStateLocked(); 1145 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1146 final Service service = state.mBoundServices.get(i); 1147 service.notifySoftKeyboardShowModeChangedLocked(showMode); 1148 } 1149 } 1150 1151 private void notifyAccessibilityButtonClickedLocked() { 1152 final UserState state = getCurrentUserStateLocked(); 1153 1154 int potentialTargets = state.mIsNavBarMagnificationEnabled ? 1 : 0; 1155 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1156 final Service service = state.mBoundServices.get(i); 1157 if (service.mRequestAccessibilityButton) { 1158 potentialTargets++; 1159 } 1160 } 1161 1162 if (potentialTargets == 0) { 1163 return; 1164 } 1165 if (potentialTargets == 1) { 1166 if (state.mIsNavBarMagnificationEnabled) { 1167 mMainHandler.obtainMessage( 1168 MainHandler.MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER).sendToTarget(); 1169 return; 1170 } else { 1171 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1172 final Service service = state.mBoundServices.get(i); 1173 if (service.mRequestAccessibilityButton) { 1174 service.notifyAccessibilityButtonClickedLocked(); 1175 return; 1176 } 1177 } 1178 } 1179 } else { 1180 if (state.mServiceAssignedToAccessibilityButton == null 1181 && !state.mIsNavBarMagnificationAssignedToAccessibilityButton) { 1182 mMainHandler.obtainMessage( 1183 MainHandler.MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER).sendToTarget(); 1184 } else if (state.mIsNavBarMagnificationEnabled 1185 && state.mIsNavBarMagnificationAssignedToAccessibilityButton) { 1186 mMainHandler.obtainMessage( 1187 MainHandler.MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER).sendToTarget(); 1188 return; 1189 } else { 1190 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1191 final Service service = state.mBoundServices.get(i); 1192 if (service.mRequestAccessibilityButton && (service.mComponentName.equals( 1193 state.mServiceAssignedToAccessibilityButton))) { 1194 service.notifyAccessibilityButtonClickedLocked(); 1195 return; 1196 } 1197 } 1198 } 1199 // The user may have turned off the assigned service or feature 1200 mMainHandler.obtainMessage( 1201 MainHandler.MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER).sendToTarget(); 1202 } 1203 } 1204 1205 private void notifyAccessibilityButtonVisibilityChangedLocked(boolean available) { 1206 final UserState state = getCurrentUserStateLocked(); 1207 mIsAccessibilityButtonShown = available; 1208 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1209 final Service service = state.mBoundServices.get(i); 1210 if (service.mRequestAccessibilityButton) { 1211 service.notifyAccessibilityButtonAvailabilityChangedLocked( 1212 service.isAccessibilityButtonAvailableLocked(state)); 1213 } 1214 } 1215 } 1216 1217 /** 1218 * Removes an AccessibilityInteractionConnection. 1219 * 1220 * @param windowId The id of the window to which the connection is targeted. 1221 * @param userId The id of the user owning the connection. UserHandle.USER_ALL 1222 * if global. 1223 */ 1224 private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) { 1225 if (userId == UserHandle.USER_ALL) { 1226 mGlobalWindowTokens.remove(windowId); 1227 mGlobalInteractionConnections.remove(windowId); 1228 } else { 1229 UserState userState = getCurrentUserStateLocked(); 1230 userState.mWindowTokens.remove(windowId); 1231 userState.mInteractionConnections.remove(windowId); 1232 } 1233 if (DEBUG) { 1234 Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId); 1235 } 1236 } 1237 1238 private boolean readInstalledAccessibilityServiceLocked(UserState userState) { 1239 mTempAccessibilityServiceInfoList.clear(); 1240 1241 List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser( 1242 new Intent(AccessibilityService.SERVICE_INTERFACE), 1243 PackageManager.GET_SERVICES 1244 | PackageManager.GET_META_DATA 1245 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 1246 | PackageManager.MATCH_DIRECT_BOOT_AWARE 1247 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 1248 mCurrentUserId); 1249 1250 for (int i = 0, count = installedServices.size(); i < count; i++) { 1251 ResolveInfo resolveInfo = installedServices.get(i); 1252 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 1253 if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals( 1254 serviceInfo.permission)) { 1255 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName( 1256 serviceInfo.packageName, serviceInfo.name).flattenToShortString() 1257 + ": it does not require the permission " 1258 + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE); 1259 continue; 1260 } 1261 AccessibilityServiceInfo accessibilityServiceInfo; 1262 try { 1263 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext); 1264 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo); 1265 } catch (XmlPullParserException | IOException xppe) { 1266 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe); 1267 } 1268 } 1269 1270 if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) { 1271 userState.mInstalledServices.clear(); 1272 userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList); 1273 mTempAccessibilityServiceInfoList.clear(); 1274 return true; 1275 } 1276 1277 mTempAccessibilityServiceInfoList.clear(); 1278 return false; 1279 } 1280 1281 private boolean readEnabledAccessibilityServicesLocked(UserState userState) { 1282 mTempComponentNameSet.clear(); 1283 readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 1284 userState.mUserId, mTempComponentNameSet); 1285 if (!mTempComponentNameSet.equals(userState.mEnabledServices)) { 1286 userState.mEnabledServices.clear(); 1287 userState.mEnabledServices.addAll(mTempComponentNameSet); 1288 if (userState.mUiAutomationService != null) { 1289 userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName); 1290 } 1291 mTempComponentNameSet.clear(); 1292 return true; 1293 } 1294 mTempComponentNameSet.clear(); 1295 return false; 1296 } 1297 1298 private boolean readTouchExplorationGrantedAccessibilityServicesLocked( 1299 UserState userState) { 1300 mTempComponentNameSet.clear(); 1301 readComponentNamesFromSettingLocked( 1302 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 1303 userState.mUserId, mTempComponentNameSet); 1304 if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) { 1305 userState.mTouchExplorationGrantedServices.clear(); 1306 userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet); 1307 mTempComponentNameSet.clear(); 1308 return true; 1309 } 1310 mTempComponentNameSet.clear(); 1311 return false; 1312 } 1313 1314 /** 1315 * Performs {@link AccessibilityService}s delayed notification. The delay is configurable 1316 * and denotes the period after the last event before notifying the service. 1317 * 1318 * @param event The event. 1319 * @param isDefault True to notify default listeners, not default services. 1320 */ 1321 private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, 1322 boolean isDefault) { 1323 try { 1324 UserState state = getCurrentUserStateLocked(); 1325 for (int i = 0, count = state.mBoundServices.size(); i < count; i++) { 1326 Service service = state.mBoundServices.get(i); 1327 1328 if (service.mIsDefault == isDefault) { 1329 if (doesServiceWantEventLocked(service, event)) { 1330 service.notifyAccessibilityEvent(event, true); 1331 } else if (service.mUsesAccessibilityCache 1332 && (AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK 1333 & event.getEventType()) != 0) { 1334 service.notifyAccessibilityEvent(event, false); 1335 } 1336 } 1337 } 1338 } catch (IndexOutOfBoundsException oobe) { 1339 // An out of bounds exception can happen if services are going away 1340 // as the for loop is running. If that happens, just bail because 1341 // there are no more services to notify. 1342 } 1343 } 1344 1345 private void addServiceLocked(Service service, UserState userState) { 1346 try { 1347 if (!userState.mBoundServices.contains(service)) { 1348 service.onAdded(); 1349 userState.mBoundServices.add(service); 1350 userState.mComponentNameToServiceMap.put(service.mComponentName, service); 1351 scheduleNotifyClientsOfServicesStateChange(userState); 1352 } 1353 } catch (RemoteException re) { 1354 /* do nothing */ 1355 } 1356 } 1357 1358 /** 1359 * Removes a service. 1360 * 1361 * @param service The service. 1362 */ 1363 private void removeServiceLocked(Service service, UserState userState) { 1364 userState.mBoundServices.remove(service); 1365 service.onRemoved(); 1366 // It may be possible to bind a service twice, which confuses the map. Rebuild the map 1367 // to make sure we can still reach a service 1368 userState.mComponentNameToServiceMap.clear(); 1369 for (int i = 0; i < userState.mBoundServices.size(); i++) { 1370 Service boundService = userState.mBoundServices.get(i); 1371 userState.mComponentNameToServiceMap.put(boundService.mComponentName, boundService); 1372 } 1373 scheduleNotifyClientsOfServicesStateChange(userState); 1374 } 1375 1376 private void updateRelevantEventsLocked(UserState userState) { 1377 int relevantEventTypes = AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK; 1378 for (Service service : userState.mBoundServices) { 1379 relevantEventTypes |= service.mEventTypes; 1380 } 1381 int finalRelevantEventTypes = relevantEventTypes; 1382 1383 if (userState.mLastSentRelevantEventTypes != finalRelevantEventTypes) { 1384 userState.mLastSentRelevantEventTypes = finalRelevantEventTypes; 1385 mMainHandler.obtainMessage(MainHandler.MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS, 1386 userState.mUserId, finalRelevantEventTypes); 1387 mMainHandler.post(() -> { 1388 broadcastToClients(userState, (client) -> { 1389 try { 1390 client.setRelevantEventTypes(finalRelevantEventTypes); 1391 } catch (RemoteException re) { 1392 /* ignore */ 1393 } 1394 }); 1395 }); 1396 } 1397 } 1398 1399 private void broadcastToClients( 1400 UserState userState, Consumer<IAccessibilityManagerClient> clientAction) { 1401 mGlobalClients.broadcast(clientAction); 1402 userState.mUserClients.broadcast(clientAction); 1403 } 1404 1405 /** 1406 * Determines if given event can be dispatched to a service based on the package of the 1407 * event source. Specifically, a service is notified if it is interested in events from the 1408 * package. 1409 * 1410 * @param service The potential receiver. 1411 * @param event The event. 1412 * @return True if the listener should be notified, false otherwise. 1413 */ 1414 private boolean doesServiceWantEventLocked(Service service, AccessibilityEvent event) { 1415 1416 if (!service.canReceiveEventsLocked()) { 1417 return false; 1418 } 1419 1420 if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) 1421 && !event.isImportantForAccessibility() 1422 && (service.mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) 1423 == 0) { 1424 return false; 1425 } 1426 1427 int eventType = event.getEventType(); 1428 if ((service.mEventTypes & eventType) != eventType) { 1429 return false; 1430 } 1431 1432 Set<String> packageNames = service.mPackageNames; 1433 String packageName = (event.getPackageName() != null) 1434 ? event.getPackageName().toString() : null; 1435 1436 return (packageNames.isEmpty() || packageNames.contains(packageName)); 1437 } 1438 1439 private void unbindAllServicesLocked(UserState userState) { 1440 List<Service> services = userState.mBoundServices; 1441 for (int i = 0, count = services.size(); i < count; i++) { 1442 Service service = services.get(i); 1443 if (service.unbindLocked()) { 1444 i--; 1445 count--; 1446 } 1447 } 1448 } 1449 1450 /** 1451 * Populates a set with the {@link ComponentName}s stored in a colon 1452 * separated value setting for a given user. 1453 * 1454 * @param settingName The setting to parse. 1455 * @param userId The user id. 1456 * @param outComponentNames The output component names. 1457 */ 1458 private void readComponentNamesFromSettingLocked(String settingName, int userId, 1459 Set<ComponentName> outComponentNames) { 1460 String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(), 1461 settingName, userId); 1462 readComponentNamesFromStringLocked(settingValue, outComponentNames, false); 1463 } 1464 1465 /** 1466 * Populates a set with the {@link ComponentName}s contained in a colon-delimited string. 1467 * 1468 * @param names The colon-delimited string to parse. 1469 * @param outComponentNames The set of component names to be populated based on 1470 * the contents of the <code>names</code> string. 1471 * @param doMerge If true, the parsed component names will be merged into the output 1472 * set, rather than replacing the set's existing contents entirely. 1473 */ 1474 private void readComponentNamesFromStringLocked(String names, 1475 Set<ComponentName> outComponentNames, 1476 boolean doMerge) { 1477 if (!doMerge) { 1478 outComponentNames.clear(); 1479 } 1480 if (names != null) { 1481 TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; 1482 splitter.setString(names); 1483 while (splitter.hasNext()) { 1484 String str = splitter.next(); 1485 if (str == null || str.length() <= 0) { 1486 continue; 1487 } 1488 ComponentName enabledService = ComponentName.unflattenFromString(str); 1489 if (enabledService != null) { 1490 outComponentNames.add(enabledService); 1491 } 1492 } 1493 } 1494 } 1495 1496 /** 1497 * Persists the component names in the specified setting in a 1498 * colon separated fashion. 1499 * 1500 * @param settingName The setting name. 1501 * @param componentNames The component names. 1502 */ 1503 private void persistComponentNamesToSettingLocked(String settingName, 1504 Set<ComponentName> componentNames, int userId) { 1505 StringBuilder builder = new StringBuilder(); 1506 for (ComponentName componentName : componentNames) { 1507 if (builder.length() > 0) { 1508 builder.append(COMPONENT_NAME_SEPARATOR); 1509 } 1510 builder.append(componentName.flattenToShortString()); 1511 } 1512 final long identity = Binder.clearCallingIdentity(); 1513 try { 1514 Settings.Secure.putStringForUser(mContext.getContentResolver(), 1515 settingName, builder.toString(), userId); 1516 } finally { 1517 Binder.restoreCallingIdentity(identity); 1518 } 1519 } 1520 1521 private void updateServicesLocked(UserState userState) { 1522 Map<ComponentName, Service> componentNameToServiceMap = 1523 userState.mComponentNameToServiceMap; 1524 boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class) 1525 .isUserUnlockingOrUnlocked(userState.mUserId); 1526 1527 for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) { 1528 AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i); 1529 ComponentName componentName = ComponentName.unflattenFromString( 1530 installedService.getId()); 1531 1532 Service service = componentNameToServiceMap.get(componentName); 1533 1534 // Ignore non-encryption-aware services until user is unlocked 1535 if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) { 1536 Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName); 1537 continue; 1538 } 1539 1540 // Wait for the binding if it is in process. 1541 if (userState.mBindingServices.contains(componentName)) { 1542 continue; 1543 } 1544 if (userState.mEnabledServices.contains(componentName)) { 1545 if (service == null) { 1546 service = new Service(userState.mUserId, componentName, installedService); 1547 } else if (userState.mBoundServices.contains(service)) { 1548 continue; 1549 } 1550 service.bindLocked(); 1551 } else { 1552 if (service != null) { 1553 service.unbindLocked(); 1554 } 1555 } 1556 } 1557 1558 final int count = userState.mBoundServices.size(); 1559 mTempIntArray.clear(); 1560 for (int i = 0; i < count; i++) { 1561 final ResolveInfo resolveInfo = 1562 userState.mBoundServices.get(i).mAccessibilityServiceInfo.getResolveInfo(); 1563 if (resolveInfo != null) { 1564 mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid); 1565 } 1566 } 1567 // Calling out with lock held, but to a lower-level service 1568 final AudioManagerInternal audioManager = 1569 LocalServices.getService(AudioManagerInternal.class); 1570 if (audioManager != null) { 1571 audioManager.setAccessibilityServiceUids(mTempIntArray); 1572 } 1573 updateAccessibilityEnabledSetting(userState); 1574 } 1575 1576 private void scheduleUpdateClientsIfNeededLocked(UserState userState) { 1577 final int clientState = userState.getClientState(); 1578 if (userState.mLastSentClientState != clientState 1579 && (mGlobalClients.getRegisteredCallbackCount() > 0 1580 || userState.mUserClients.getRegisteredCallbackCount() > 0)) { 1581 userState.mLastSentClientState = clientState; 1582 mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS, 1583 clientState, userState.mUserId).sendToTarget(); 1584 } 1585 } 1586 1587 private void showAccessibilityButtonTargetSelection() { 1588 Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON); 1589 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1590 mContext.startActivityAsUser(intent, UserHandle.of(mCurrentUserId)); 1591 } 1592 1593 private void scheduleNotifyClientsOfServicesStateChange(UserState userState) { 1594 mMainHandler.obtainMessage(MainHandler.MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS, 1595 userState.mUserId).sendToTarget(); 1596 } 1597 1598 private void scheduleUpdateInputFilter(UserState userState) { 1599 mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget(); 1600 } 1601 1602 private void scheduleUpdateFingerprintGestureHandling(UserState userState) { 1603 mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_FINGERPRINT, userState).sendToTarget(); 1604 } 1605 1606 private void updateInputFilter(UserState userState) { 1607 boolean setInputFilter = false; 1608 AccessibilityInputFilter inputFilter = null; 1609 synchronized (mLock) { 1610 int flags = 0; 1611 if (userState.mIsDisplayMagnificationEnabled) { 1612 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER; 1613 } 1614 if (userState.mIsNavBarMagnificationEnabled) { 1615 flags |= AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER; 1616 } 1617 if (userHasMagnificationServicesLocked(userState)) { 1618 flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER; 1619 } 1620 // Touch exploration without accessibility makes no sense. 1621 if (userState.isHandlingAccessibilityEvents() 1622 && userState.mIsTouchExplorationEnabled) { 1623 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION; 1624 } 1625 if (userState.mIsFilterKeyEventsEnabled) { 1626 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS; 1627 } 1628 if (userState.mIsAutoclickEnabled) { 1629 flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK; 1630 } 1631 if (userState.mIsPerformGesturesEnabled) { 1632 flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS; 1633 } 1634 if (flags != 0) { 1635 if (!mHasInputFilter) { 1636 mHasInputFilter = true; 1637 if (mInputFilter == null) { 1638 mInputFilter = new AccessibilityInputFilter(mContext, 1639 AccessibilityManagerService.this); 1640 } 1641 inputFilter = mInputFilter; 1642 setInputFilter = true; 1643 } 1644 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags); 1645 } else { 1646 if (mHasInputFilter) { 1647 mHasInputFilter = false; 1648 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, 0); 1649 inputFilter = null; 1650 setInputFilter = true; 1651 } 1652 } 1653 } 1654 if (setInputFilter) { 1655 mWindowManagerService.setInputFilter(inputFilter); 1656 } 1657 } 1658 1659 private void showEnableTouchExplorationDialog(final Service service) { 1660 synchronized (mLock) { 1661 String label = service.mResolveInfo.loadLabel( 1662 mContext.getPackageManager()).toString(); 1663 1664 final UserState state = getCurrentUserStateLocked(); 1665 if (state.mIsTouchExplorationEnabled) { 1666 return; 1667 } 1668 if (mEnableTouchExplorationDialog != null 1669 && mEnableTouchExplorationDialog.isShowing()) { 1670 return; 1671 } 1672 mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext) 1673 .setIconAttribute(android.R.attr.alertDialogIcon) 1674 .setPositiveButton(android.R.string.ok, new OnClickListener() { 1675 @Override 1676 public void onClick(DialogInterface dialog, int which) { 1677 // The user allowed the service to toggle touch exploration. 1678 state.mTouchExplorationGrantedServices.add(service.mComponentName); 1679 persistComponentNamesToSettingLocked( 1680 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 1681 state.mTouchExplorationGrantedServices, state.mUserId); 1682 // Enable touch exploration. 1683 UserState userState = getUserStateLocked(service.mUserId); 1684 userState.mIsTouchExplorationEnabled = true; 1685 final long identity = Binder.clearCallingIdentity(); 1686 try { 1687 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1688 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, 1689 service.mUserId); 1690 } finally { 1691 Binder.restoreCallingIdentity(identity); 1692 } 1693 onUserStateChangedLocked(userState); 1694 } 1695 }) 1696 .setNegativeButton(android.R.string.cancel, new OnClickListener() { 1697 @Override 1698 public void onClick(DialogInterface dialog, int which) { 1699 dialog.dismiss(); 1700 } 1701 }) 1702 .setTitle(R.string.enable_explore_by_touch_warning_title) 1703 .setMessage(mContext.getString( 1704 R.string.enable_explore_by_touch_warning_message, label)) 1705 .create(); 1706 mEnableTouchExplorationDialog.getWindow().setType( 1707 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 1708 mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags 1709 |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 1710 mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true); 1711 mEnableTouchExplorationDialog.show(); 1712 } 1713 } 1714 1715 /** 1716 * Called when any property of the user state has changed. 1717 * 1718 * @param userState the new user state 1719 */ 1720 private void onUserStateChangedLocked(UserState userState) { 1721 // TODO: Remove this hack 1722 mInitialized = true; 1723 updateLegacyCapabilitiesLocked(userState); 1724 updateServicesLocked(userState); 1725 updateAccessibilityShortcutLocked(userState); 1726 updateWindowsForAccessibilityCallbackLocked(userState); 1727 updateAccessibilityFocusBehaviorLocked(userState); 1728 updateFilterKeyEventsLocked(userState); 1729 updateTouchExplorationLocked(userState); 1730 updatePerformGesturesLocked(userState); 1731 updateDisplayDaltonizerLocked(userState); 1732 updateDisplayInversionLocked(userState); 1733 updateMagnificationLocked(userState); 1734 updateSoftKeyboardShowModeLocked(userState); 1735 scheduleUpdateFingerprintGestureHandling(userState); 1736 scheduleUpdateInputFilter(userState); 1737 scheduleUpdateClientsIfNeededLocked(userState); 1738 updateRelevantEventsLocked(userState); 1739 updateAccessibilityButtonTargetsLocked(userState); 1740 } 1741 1742 private void updateAccessibilityFocusBehaviorLocked(UserState userState) { 1743 // If there is no service that can operate with interactive windows 1744 // then we keep the old behavior where a window loses accessibility 1745 // focus if it is no longer active. This still changes the behavior 1746 // for services that do not operate with interactive windows and run 1747 // at the same time as the one(s) which does. In practice however, 1748 // there is only one service that uses accessibility focus and it 1749 // is typically the one that operates with interactive windows, So, 1750 // this is fine. Note that to allow a service to work across windows 1751 // we have to allow accessibility focus stay in any of them. Sigh... 1752 List<Service> boundServices = userState.mBoundServices; 1753 final int boundServiceCount = boundServices.size(); 1754 for (int i = 0; i < boundServiceCount; i++) { 1755 Service boundService = boundServices.get(i); 1756 if (boundService.canRetrieveInteractiveWindowsLocked()) { 1757 userState.mAccessibilityFocusOnlyInActiveWindow = false; 1758 return; 1759 } 1760 } 1761 userState.mAccessibilityFocusOnlyInActiveWindow = true; 1762 } 1763 1764 private void updateWindowsForAccessibilityCallbackLocked(UserState userState) { 1765 // We observe windows for accessibility only if there is at least 1766 // one bound service that can retrieve window content that specified 1767 // it is interested in accessing such windows. For services that are 1768 // binding we do an update pass after each bind event, so we run this 1769 // code and register the callback if needed. 1770 1771 List<Service> boundServices = userState.mBoundServices; 1772 final int boundServiceCount = boundServices.size(); 1773 for (int i = 0; i < boundServiceCount; i++) { 1774 Service boundService = boundServices.get(i); 1775 if (boundService.canRetrieveInteractiveWindowsLocked()) { 1776 if (mWindowsForAccessibilityCallback == null) { 1777 mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback(); 1778 mWindowManagerService.setWindowsForAccessibilityCallback( 1779 mWindowsForAccessibilityCallback); 1780 } 1781 return; 1782 } 1783 } 1784 1785 if (mWindowsForAccessibilityCallback != null) { 1786 mWindowsForAccessibilityCallback = null; 1787 mWindowManagerService.setWindowsForAccessibilityCallback(null); 1788 // Drop all windows we know about. 1789 mSecurityPolicy.clearWindowsLocked(); 1790 } 1791 } 1792 1793 private void updateLegacyCapabilitiesLocked(UserState userState) { 1794 // Up to JB-MR1 we had a white list with services that can enable touch 1795 // exploration. When a service is first started we show a dialog to the 1796 // use to get a permission to white list the service. 1797 final int installedServiceCount = userState.mInstalledServices.size(); 1798 for (int i = 0; i < installedServiceCount; i++) { 1799 AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i); 1800 ResolveInfo resolveInfo = serviceInfo.getResolveInfo(); 1801 if ((serviceInfo.getCapabilities() 1802 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0 1803 && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion 1804 <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 1805 ComponentName componentName = new ComponentName( 1806 resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); 1807 if (userState.mTouchExplorationGrantedServices.contains(componentName)) { 1808 serviceInfo.setCapabilities(serviceInfo.getCapabilities() 1809 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION); 1810 } 1811 } 1812 } 1813 } 1814 1815 private void updatePerformGesturesLocked(UserState userState) { 1816 final int serviceCount = userState.mBoundServices.size(); 1817 for (int i = 0; i < serviceCount; i++) { 1818 Service service = userState.mBoundServices.get(i); 1819 if ((service.mAccessibilityServiceInfo.getCapabilities() 1820 & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) { 1821 userState.mIsPerformGesturesEnabled = true; 1822 return; 1823 } 1824 } 1825 userState.mIsPerformGesturesEnabled = false; 1826 } 1827 1828 private void updateFilterKeyEventsLocked(UserState userState) { 1829 final int serviceCount = userState.mBoundServices.size(); 1830 for (int i = 0; i < serviceCount; i++) { 1831 Service service = userState.mBoundServices.get(i); 1832 if (service.mRequestFilterKeyEvents 1833 && (service.mAccessibilityServiceInfo.getCapabilities() 1834 & AccessibilityServiceInfo 1835 .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) { 1836 userState.mIsFilterKeyEventsEnabled = true; 1837 return; 1838 } 1839 } 1840 userState.mIsFilterKeyEventsEnabled = false; 1841 } 1842 1843 private boolean readConfigurationForUserStateLocked(UserState userState) { 1844 boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState); 1845 somethingChanged |= readEnabledAccessibilityServicesLocked(userState); 1846 somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState); 1847 somethingChanged |= readTouchExplorationEnabledSettingLocked(userState); 1848 somethingChanged |= readHighTextContrastEnabledSettingLocked(userState); 1849 somethingChanged |= readMagnificationEnabledSettingsLocked(userState); 1850 somethingChanged |= readAutoclickEnabledSettingLocked(userState); 1851 somethingChanged |= readAccessibilityShortcutSettingLocked(userState); 1852 somethingChanged |= readAccessibilityButtonSettingsLocked(userState); 1853 return somethingChanged; 1854 } 1855 1856 private void updateAccessibilityEnabledSetting(UserState userState) { 1857 final long identity = Binder.clearCallingIdentity(); 1858 try { 1859 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1860 Settings.Secure.ACCESSIBILITY_ENABLED, 1861 userState.isHandlingAccessibilityEvents() ? 1 : 0, 1862 userState.mUserId); 1863 } finally { 1864 Binder.restoreCallingIdentity(identity); 1865 } 1866 } 1867 1868 private boolean readTouchExplorationEnabledSettingLocked(UserState userState) { 1869 final boolean touchExplorationEnabled = Settings.Secure.getIntForUser( 1870 mContext.getContentResolver(), 1871 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1; 1872 if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) { 1873 userState.mIsTouchExplorationEnabled = touchExplorationEnabled; 1874 return true; 1875 } 1876 return false; 1877 } 1878 1879 private boolean readMagnificationEnabledSettingsLocked(UserState userState) { 1880 final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser( 1881 mContext.getContentResolver(), 1882 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 1883 0, userState.mUserId) == 1; 1884 final boolean navBarMagnificationEnabled = Settings.Secure.getIntForUser( 1885 mContext.getContentResolver(), 1886 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 1887 0, userState.mUserId) == 1; 1888 if ((displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled) 1889 || (navBarMagnificationEnabled != userState.mIsNavBarMagnificationEnabled)) { 1890 userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled; 1891 userState.mIsNavBarMagnificationEnabled = navBarMagnificationEnabled; 1892 return true; 1893 } 1894 return false; 1895 } 1896 1897 private boolean readAutoclickEnabledSettingLocked(UserState userState) { 1898 final boolean autoclickEnabled = Settings.Secure.getIntForUser( 1899 mContext.getContentResolver(), 1900 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 1901 0, userState.mUserId) == 1; 1902 if (autoclickEnabled != userState.mIsAutoclickEnabled) { 1903 userState.mIsAutoclickEnabled = autoclickEnabled; 1904 return true; 1905 } 1906 return false; 1907 } 1908 1909 private boolean readHighTextContrastEnabledSettingLocked(UserState userState) { 1910 final boolean highTextContrastEnabled = Settings.Secure.getIntForUser( 1911 mContext.getContentResolver(), 1912 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0, 1913 userState.mUserId) == 1; 1914 if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) { 1915 userState.mIsTextHighContrastEnabled = highTextContrastEnabled; 1916 return true; 1917 } 1918 return false; 1919 } 1920 1921 private boolean readSoftKeyboardShowModeChangedLocked(UserState userState) { 1922 final int softKeyboardShowMode = Settings.Secure.getIntForUser( 1923 mContext.getContentResolver(), 1924 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0, 1925 userState.mUserId); 1926 if (softKeyboardShowMode != userState.mSoftKeyboardShowMode) { 1927 userState.mSoftKeyboardShowMode = softKeyboardShowMode; 1928 return true; 1929 } 1930 return false; 1931 } 1932 1933 private void updateTouchExplorationLocked(UserState userState) { 1934 boolean enabled = false; 1935 final int serviceCount = userState.mBoundServices.size(); 1936 for (int i = 0; i < serviceCount; i++) { 1937 Service service = userState.mBoundServices.get(i); 1938 if (canRequestAndRequestsTouchExplorationLocked(service)) { 1939 enabled = true; 1940 break; 1941 } 1942 } 1943 if (enabled != userState.mIsTouchExplorationEnabled) { 1944 userState.mIsTouchExplorationEnabled = enabled; 1945 final long identity = Binder.clearCallingIdentity(); 1946 try { 1947 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1948 Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0, 1949 userState.mUserId); 1950 } finally { 1951 Binder.restoreCallingIdentity(identity); 1952 } 1953 } 1954 } 1955 1956 private boolean readAccessibilityShortcutSettingLocked(UserState userState) { 1957 String componentNameToEnableString = AccessibilityShortcutController 1958 .getTargetServiceComponentNameString(mContext, userState.mUserId); 1959 if ((componentNameToEnableString == null) || componentNameToEnableString.isEmpty()) { 1960 if (userState.mServiceToEnableWithShortcut == null) { 1961 return false; 1962 } 1963 userState.mServiceToEnableWithShortcut = null; 1964 return true; 1965 } 1966 ComponentName componentNameToEnable = 1967 ComponentName.unflattenFromString(componentNameToEnableString); 1968 if ((componentNameToEnable != null) 1969 && componentNameToEnable.equals(userState.mServiceToEnableWithShortcut)) { 1970 return false; 1971 } 1972 userState.mServiceToEnableWithShortcut = componentNameToEnable; 1973 return true; 1974 } 1975 1976 private boolean readAccessibilityButtonSettingsLocked(UserState userState) { 1977 String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(), 1978 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId); 1979 if (TextUtils.isEmpty(componentId)) { 1980 if ((userState.mServiceAssignedToAccessibilityButton == null) 1981 && !userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { 1982 return false; 1983 } 1984 userState.mServiceAssignedToAccessibilityButton = null; 1985 userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false; 1986 return true; 1987 } 1988 1989 if (componentId.equals(MagnificationController.class.getName())) { 1990 if (userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { 1991 return false; 1992 } 1993 userState.mServiceAssignedToAccessibilityButton = null; 1994 userState.mIsNavBarMagnificationAssignedToAccessibilityButton = true; 1995 return true; 1996 } 1997 1998 ComponentName componentName = ComponentName.unflattenFromString(componentId); 1999 if (componentName.equals(userState.mServiceAssignedToAccessibilityButton)) { 2000 return false; 2001 } 2002 userState.mServiceAssignedToAccessibilityButton = componentName; 2003 userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false; 2004 return true; 2005 } 2006 2007 /** 2008 * Check if the service that will be enabled by the shortcut is installed. If it isn't, 2009 * clear the value and the associated setting so a sideloaded service can't spoof the 2010 * package name of the default service. 2011 * 2012 * @param userState 2013 */ 2014 private void updateAccessibilityShortcutLocked(UserState userState) { 2015 if (userState.mServiceToEnableWithShortcut == null) { 2016 return; 2017 } 2018 boolean shortcutServiceIsInstalled = false; 2019 for (int i = 0; i < userState.mInstalledServices.size(); i++) { 2020 if (userState.mInstalledServices.get(i).getComponentName() 2021 .equals(userState.mServiceToEnableWithShortcut)) { 2022 shortcutServiceIsInstalled = true; 2023 } 2024 } 2025 if (!shortcutServiceIsInstalled) { 2026 userState.mServiceToEnableWithShortcut = null; 2027 final long identity = Binder.clearCallingIdentity(); 2028 try { 2029 Settings.Secure.putStringForUser(mContext.getContentResolver(), 2030 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null, userState.mUserId); 2031 2032 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2033 Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0, userState.mUserId); 2034 } finally { 2035 Binder.restoreCallingIdentity(identity); 2036 } 2037 } 2038 } 2039 2040 private boolean canRequestAndRequestsTouchExplorationLocked(Service service) { 2041 // Service not ready or cannot request the feature - well nothing to do. 2042 if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) { 2043 return false; 2044 } 2045 // UI test automation service can always enable it. 2046 if (service.mIsAutomation) { 2047 return true; 2048 } 2049 if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion 2050 <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 2051 // Up to JB-MR1 we had a white list with services that can enable touch 2052 // exploration. When a service is first started we show a dialog to the 2053 // use to get a permission to white list the service. 2054 UserState userState = getUserStateLocked(service.mUserId); 2055 if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) { 2056 return true; 2057 } else if (mEnableTouchExplorationDialog == null 2058 || !mEnableTouchExplorationDialog.isShowing()) { 2059 mMainHandler.obtainMessage( 2060 MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG, 2061 service).sendToTarget(); 2062 } 2063 } else { 2064 // Starting in JB-MR2 we request an accessibility service to declare 2065 // certain capabilities in its meta-data to allow it to enable the 2066 // corresponding features. 2067 if ((service.mAccessibilityServiceInfo.getCapabilities() 2068 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) { 2069 return true; 2070 } 2071 } 2072 return false; 2073 } 2074 2075 private void updateDisplayDaltonizerLocked(UserState userState) { 2076 DisplayAdjustmentUtils.applyDaltonizerSetting(mContext, userState.mUserId); 2077 } 2078 2079 private void updateDisplayInversionLocked(UserState userState) { 2080 DisplayAdjustmentUtils.applyInversionSetting(mContext, userState.mUserId); 2081 } 2082 2083 private void updateMagnificationLocked(UserState userState) { 2084 if (userState.mUserId != mCurrentUserId) { 2085 return; 2086 } 2087 2088 if (userState.mIsDisplayMagnificationEnabled || userState.mIsNavBarMagnificationEnabled 2089 || userHasListeningMagnificationServicesLocked(userState)) { 2090 // Initialize the magnification controller if necessary 2091 getMagnificationController(); 2092 mMagnificationController.register(); 2093 } else if (mMagnificationController != null) { 2094 mMagnificationController.unregister(); 2095 } 2096 } 2097 2098 /** 2099 * Returns whether the specified user has any services that are capable of 2100 * controlling magnification. 2101 */ 2102 private boolean userHasMagnificationServicesLocked(UserState userState) { 2103 final List<Service> services = userState.mBoundServices; 2104 for (int i = 0, count = services.size(); i < count; i++) { 2105 final Service service = services.get(i); 2106 if (mSecurityPolicy.canControlMagnification(service)) { 2107 return true; 2108 } 2109 } 2110 return false; 2111 } 2112 2113 /** 2114 * Returns whether the specified user has any services that are capable of 2115 * controlling magnification and are actively listening for magnification updates. 2116 */ 2117 private boolean userHasListeningMagnificationServicesLocked(UserState userState) { 2118 final List<Service> services = userState.mBoundServices; 2119 for (int i = 0, count = services.size(); i < count; i++) { 2120 final Service service = services.get(i); 2121 if (mSecurityPolicy.canControlMagnification(service) 2122 && service.mInvocationHandler.mIsMagnificationCallbackEnabled) { 2123 return true; 2124 } 2125 } 2126 return false; 2127 } 2128 2129 private void updateSoftKeyboardShowModeLocked(UserState userState) { 2130 final int userId = userState.mUserId; 2131 // Only check whether we need to reset the soft keyboard mode if it is not set to the 2132 // default. 2133 if ((userId == mCurrentUserId) && (userState.mSoftKeyboardShowMode != 0)) { 2134 // Check whether the last Accessibility Service that changed the soft keyboard mode to 2135 // something other than the default is still enabled and, if not, remove flag and 2136 // reset to the default soft keyboard behavior. 2137 boolean serviceChangingSoftKeyboardModeIsEnabled = 2138 userState.mEnabledServices.contains(userState.mServiceChangingSoftKeyboardMode); 2139 2140 if (!serviceChangingSoftKeyboardModeIsEnabled) { 2141 final long identity = Binder.clearCallingIdentity(); 2142 try { 2143 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2144 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 2145 0, 2146 userState.mUserId); 2147 } finally { 2148 Binder.restoreCallingIdentity(identity); 2149 } 2150 userState.mSoftKeyboardShowMode = 0; 2151 userState.mServiceChangingSoftKeyboardMode = null; 2152 notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode); 2153 } 2154 } 2155 } 2156 2157 private void updateFingerprintGestureHandling(UserState userState) { 2158 final List<Service> services; 2159 synchronized (mLock) { 2160 services = userState.mBoundServices; 2161 if ((mFingerprintGestureDispatcher == null) 2162 && mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 2163 // Only create the controller when a service wants to use the feature 2164 int numServices = services.size(); 2165 for (int i = 0; i < numServices; i++) { 2166 if (services.get(i).isCapturingFingerprintGestures()) { 2167 final long identity = Binder.clearCallingIdentity(); 2168 IFingerprintService service = null; 2169 try { 2170 service = IFingerprintService.Stub.asInterface( 2171 ServiceManager.getService(Context.FINGERPRINT_SERVICE)); 2172 } finally { 2173 Binder.restoreCallingIdentity(identity); 2174 } 2175 if (service != null) { 2176 mFingerprintGestureDispatcher = new FingerprintGestureDispatcher( 2177 service, mLock); 2178 break; 2179 } 2180 } 2181 } 2182 } 2183 } 2184 if (mFingerprintGestureDispatcher != null) { 2185 mFingerprintGestureDispatcher.updateClientList(services); 2186 } 2187 } 2188 2189 private void updateAccessibilityButtonTargetsLocked(UserState userState) { 2190 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 2191 final Service service = userState.mBoundServices.get(i); 2192 if (service.mRequestAccessibilityButton) { 2193 service.notifyAccessibilityButtonAvailabilityChangedLocked( 2194 service.isAccessibilityButtonAvailableLocked(userState)); 2195 } 2196 } 2197 } 2198 2199 @GuardedBy("mLock") 2200 private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) { 2201 IBinder windowToken = mGlobalWindowTokens.get(windowId); 2202 if (windowToken == null) { 2203 windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId); 2204 } 2205 if (windowToken != null) { 2206 return mWindowManagerService.getCompatibleMagnificationSpecForWindow( 2207 windowToken); 2208 } 2209 return null; 2210 } 2211 2212 private KeyEventDispatcher getKeyEventDispatcher() { 2213 if (mKeyEventDispatcher == null) { 2214 mKeyEventDispatcher = new KeyEventDispatcher( 2215 mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock, 2216 mPowerManager); 2217 } 2218 return mKeyEventDispatcher; 2219 } 2220 2221 /** 2222 * AIDL-exposed method to be called when the accessibility shortcut is enabled. Requires 2223 * permission to write secure settings, since someone with that permission can enable 2224 * accessibility services themselves. 2225 */ 2226 public void performAccessibilityShortcut() { 2227 if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) 2228 && (mContext.checkCallingPermission(Manifest.permission.WRITE_SECURE_SETTINGS) 2229 != PackageManager.PERMISSION_GRANTED)) { 2230 throw new SecurityException( 2231 "performAccessibilityShortcut requires the WRITE_SECURE_SETTINGS permission"); 2232 } 2233 synchronized(mLock) { 2234 UserState userState = getUserStateLocked(mCurrentUserId); 2235 ComponentName serviceName = userState.mServiceToEnableWithShortcut; 2236 if (serviceName == null) { 2237 return; 2238 } 2239 final long identity = Binder.clearCallingIdentity(); 2240 try { 2241 if (userState.mComponentNameToServiceMap.get(serviceName) == null) { 2242 enableAccessibilityServiceLocked(serviceName, mCurrentUserId); 2243 } else { 2244 disableAccessibilityServiceLocked(serviceName, mCurrentUserId); 2245 } 2246 } finally { 2247 Binder.restoreCallingIdentity(identity); 2248 } 2249 } 2250 }; 2251 2252 /** 2253 * Enables accessibility service specified by {@param componentName} for the {@param userId}. 2254 */ 2255 private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) { 2256 final SettingStringHelper setting = 2257 new SettingStringHelper( 2258 mContext.getContentResolver(), 2259 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 2260 userId); 2261 setting.write(ComponentNameSet.add(setting.read(), componentName)); 2262 2263 UserState userState = getUserStateLocked(userId); 2264 if (userState.mEnabledServices.add(componentName)) { 2265 onUserStateChangedLocked(userState); 2266 } 2267 } 2268 2269 /** 2270 * Disables accessibility service specified by {@param componentName} for the {@param userId}. 2271 */ 2272 private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) { 2273 final SettingsStringUtil.SettingStringHelper setting = 2274 new SettingStringHelper( 2275 mContext.getContentResolver(), 2276 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 2277 userId); 2278 setting.write(ComponentNameSet.remove(setting.read(), componentName)); 2279 2280 UserState userState = getUserStateLocked(userId); 2281 if (userState.mEnabledServices.remove(componentName)) { 2282 onUserStateChangedLocked(userState); 2283 } 2284 } 2285 2286 /** 2287 * AIDL-exposed method. System only. 2288 * Inform accessibility that a fingerprint gesture was performed 2289 * 2290 * @param gestureKeyCode The key code corresponding to the fingerprint gesture. 2291 * @return {@code true} if accessibility consumes the fingerprint gesture, {@code false} if it 2292 * doesn't. 2293 */ 2294 @Override 2295 public boolean sendFingerprintGesture(int gestureKeyCode) { 2296 synchronized(mLock) { 2297 if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) { 2298 throw new SecurityException("Only SYSTEM can call sendFingerprintGesture"); 2299 } 2300 } 2301 if (mFingerprintGestureDispatcher == null) { 2302 return false; 2303 } 2304 return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode); 2305 } 2306 2307 @Override 2308 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 2309 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 2310 synchronized (mLock) { 2311 pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)"); 2312 pw.println(); 2313 final int userCount = mUserStates.size(); 2314 for (int i = 0; i < userCount; i++) { 2315 UserState userState = mUserStates.valueAt(i); 2316 pw.append("User state[attributes:{id=" + userState.mUserId); 2317 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId)); 2318 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled); 2319 pw.append(", displayMagnificationEnabled=" 2320 + userState.mIsDisplayMagnificationEnabled); 2321 pw.append(", navBarMagnificationEnabled=" 2322 + userState.mIsNavBarMagnificationEnabled); 2323 pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled); 2324 if (userState.mUiAutomationService != null) { 2325 pw.append(", "); 2326 userState.mUiAutomationService.dump(fd, pw, args); 2327 pw.println(); 2328 } 2329 pw.append("}"); 2330 pw.println(); 2331 pw.append(" services:{"); 2332 final int serviceCount = userState.mBoundServices.size(); 2333 for (int j = 0; j < serviceCount; j++) { 2334 if (j > 0) { 2335 pw.append(", "); 2336 pw.println(); 2337 pw.append(" "); 2338 } 2339 Service service = userState.mBoundServices.get(j); 2340 service.dump(fd, pw, args); 2341 } 2342 pw.println("}]"); 2343 pw.println(); 2344 } 2345 if (mSecurityPolicy.mWindows != null) { 2346 final int windowCount = mSecurityPolicy.mWindows.size(); 2347 for (int j = 0; j < windowCount; j++) { 2348 if (j > 0) { 2349 pw.append(','); 2350 pw.println(); 2351 } 2352 pw.append("Window["); 2353 AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j); 2354 pw.append(window.toString()); 2355 pw.append(']'); 2356 } 2357 } 2358 } 2359 } 2360 2361 private class AccessibilityConnectionWrapper implements DeathRecipient { 2362 private final int mWindowId; 2363 private final int mUserId; 2364 private final IAccessibilityInteractionConnection mConnection; 2365 2366 public AccessibilityConnectionWrapper(int windowId, 2367 IAccessibilityInteractionConnection connection, int userId) { 2368 mWindowId = windowId; 2369 mUserId = userId; 2370 mConnection = connection; 2371 } 2372 2373 public void linkToDeath() throws RemoteException { 2374 mConnection.asBinder().linkToDeath(this, 0); 2375 } 2376 2377 public void unlinkToDeath() { 2378 mConnection.asBinder().unlinkToDeath(this, 0); 2379 } 2380 2381 @Override 2382 public void binderDied() { 2383 unlinkToDeath(); 2384 synchronized (mLock) { 2385 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId); 2386 } 2387 } 2388 } 2389 2390 private final class MainHandler extends Handler { 2391 public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1; 2392 public static final int MSG_SEND_STATE_TO_CLIENTS = 2; 2393 public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3; 2394 public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5; 2395 public static final int MSG_UPDATE_INPUT_FILTER = 6; 2396 public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7; 2397 public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8; 2398 public static final int MSG_CLEAR_ACCESSIBILITY_FOCUS = 9; 2399 public static final int MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS = 10; 2400 public static final int MSG_UPDATE_FINGERPRINT = 11; 2401 public static final int MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS = 12; 2402 public static final int MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER = 13; 2403 public static final int MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER = 14; 2404 2405 public MainHandler(Looper looper) { 2406 super(looper); 2407 } 2408 2409 @Override 2410 public void handleMessage(Message msg) { 2411 final int type = msg.what; 2412 switch (type) { 2413 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: { 2414 AccessibilityEvent event = (AccessibilityEvent) msg.obj; 2415 synchronized (mLock) { 2416 if (mHasInputFilter && mInputFilter != null) { 2417 mInputFilter.notifyAccessibilityEvent(event); 2418 } 2419 } 2420 event.recycle(); 2421 } break; 2422 2423 case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: { 2424 KeyEvent event = (KeyEvent) msg.obj; 2425 final int policyFlags = msg.arg1; 2426 synchronized (mLock) { 2427 if (mHasInputFilter && mInputFilter != null) { 2428 mInputFilter.sendInputEvent(event, policyFlags); 2429 } 2430 } 2431 event.recycle(); 2432 } break; 2433 2434 case MSG_SEND_STATE_TO_CLIENTS: { 2435 final int clientState = msg.arg1; 2436 final int userId = msg.arg2; 2437 sendStateToClients(clientState, mGlobalClients); 2438 sendStateToClients(clientState, getUserClientsForId(userId)); 2439 } break; 2440 2441 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: { 2442 final int userId = msg.arg1; 2443 sendStateToClients(0, getUserClientsForId(userId)); 2444 } break; 2445 2446 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: { 2447 announceNewUserIfNeeded(); 2448 } break; 2449 2450 case MSG_UPDATE_INPUT_FILTER: { 2451 UserState userState = (UserState) msg.obj; 2452 updateInputFilter(userState); 2453 } break; 2454 2455 case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: { 2456 Service service = (Service) msg.obj; 2457 showEnableTouchExplorationDialog(service); 2458 } break; 2459 2460 case MSG_CLEAR_ACCESSIBILITY_FOCUS: { 2461 final int windowId = msg.arg1; 2462 getInteractionBridge().clearAccessibilityFocusNotLocked(windowId); 2463 } break; 2464 2465 case MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS: { 2466 final int userId = msg.arg1; 2467 notifyClientsOfServicesStateChange(mGlobalClients); 2468 notifyClientsOfServicesStateChange(getUserClientsForId(userId)); 2469 } break; 2470 2471 case MSG_UPDATE_FINGERPRINT: { 2472 updateFingerprintGestureHandling((UserState) msg.obj); 2473 } break; 2474 2475 case MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS: { 2476 final int userId = msg.arg1; 2477 final int relevantEventTypes = msg.arg2; 2478 final UserState userState; 2479 synchronized (mLock) { 2480 userState = getUserStateLocked(userId); 2481 } 2482 broadcastToClients(userState, (client) -> { 2483 try { 2484 client.setRelevantEventTypes(relevantEventTypes); 2485 } catch (RemoteException re) { 2486 /* ignore */ 2487 } 2488 }); 2489 } break; 2490 2491 case MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER: { 2492 synchronized (mLock) { 2493 if (mHasInputFilter && mInputFilter != null) { 2494 mInputFilter.notifyAccessibilityButtonClicked(); 2495 } 2496 } 2497 } break; 2498 2499 case MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER: { 2500 showAccessibilityButtonTargetSelection(); 2501 } break; 2502 } 2503 } 2504 2505 private void announceNewUserIfNeeded() { 2506 synchronized (mLock) { 2507 UserState userState = getCurrentUserStateLocked(); 2508 if (userState.isHandlingAccessibilityEvents()) { 2509 UserManager userManager = (UserManager) mContext.getSystemService( 2510 Context.USER_SERVICE); 2511 String message = mContext.getString(R.string.user_switched, 2512 userManager.getUserInfo(mCurrentUserId).name); 2513 AccessibilityEvent event = AccessibilityEvent.obtain( 2514 AccessibilityEvent.TYPE_ANNOUNCEMENT); 2515 event.getText().add(message); 2516 sendAccessibilityEvent(event, mCurrentUserId); 2517 } 2518 } 2519 } 2520 2521 private RemoteCallbackList<IAccessibilityManagerClient> getUserClientsForId(int userId) { 2522 final UserState userState; 2523 synchronized (mLock) { 2524 userState = getUserStateLocked(userId); 2525 } 2526 return userState.mUserClients; 2527 } 2528 2529 private void sendStateToClients(int clientState, 2530 RemoteCallbackList<IAccessibilityManagerClient> clients) { 2531 clients.broadcast((client) -> { 2532 try { 2533 client.setState(clientState); 2534 } catch (RemoteException re) { 2535 /* ignore */ 2536 } 2537 }); 2538 } 2539 2540 private void notifyClientsOfServicesStateChange( 2541 RemoteCallbackList<IAccessibilityManagerClient> clients) { 2542 try { 2543 final int userClientCount = clients.beginBroadcast(); 2544 for (int i = 0; i < userClientCount; i++) { 2545 IAccessibilityManagerClient client = clients.getBroadcastItem(i); 2546 try { 2547 client.notifyServicesStateChanged(); 2548 } catch (RemoteException re) { 2549 /* ignore */ 2550 } 2551 } 2552 } finally { 2553 clients.finishBroadcast(); 2554 } 2555 } 2556 } 2557 2558 private int findWindowIdLocked(IBinder token) { 2559 final int globalIndex = mGlobalWindowTokens.indexOfValue(token); 2560 if (globalIndex >= 0) { 2561 return mGlobalWindowTokens.keyAt(globalIndex); 2562 } 2563 UserState userState = getCurrentUserStateLocked(); 2564 final int userIndex = userState.mWindowTokens.indexOfValue(token); 2565 if (userIndex >= 0) { 2566 return userState.mWindowTokens.keyAt(userIndex); 2567 } 2568 return -1; 2569 } 2570 2571 private void ensureWindowsAvailableTimed() { 2572 synchronized (mLock) { 2573 if (mSecurityPolicy.mWindows != null) { 2574 return; 2575 } 2576 // If we have no registered callback, update the state we 2577 // we may have to register one but it didn't happen yet. 2578 if (mWindowsForAccessibilityCallback == null) { 2579 UserState userState = getCurrentUserStateLocked(); 2580 onUserStateChangedLocked(userState); 2581 } 2582 // We have no windows but do not care about them, done. 2583 if (mWindowsForAccessibilityCallback == null) { 2584 return; 2585 } 2586 2587 // Wait for the windows with a timeout. 2588 final long startMillis = SystemClock.uptimeMillis(); 2589 while (mSecurityPolicy.mWindows == null) { 2590 final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 2591 final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis; 2592 if (remainMillis <= 0) { 2593 return; 2594 } 2595 try { 2596 mLock.wait(remainMillis); 2597 } catch (InterruptedException ie) { 2598 /* ignore */ 2599 } 2600 } 2601 } 2602 } 2603 2604 MagnificationController getMagnificationController() { 2605 synchronized (mLock) { 2606 if (mMagnificationController == null) { 2607 mMagnificationController = new MagnificationController(mContext, this, mLock); 2608 mMagnificationController.setUserId(mCurrentUserId); 2609 } 2610 return mMagnificationController; 2611 } 2612 } 2613 2614 /** 2615 * This class represents an accessibility service. It stores all per service 2616 * data required for the service management, provides API for starting/stopping the 2617 * service and is responsible for adding/removing the service in the data structures 2618 * for service management. The class also exposes configuration interface that is 2619 * passed to the service it represents as soon it is bound. It also serves as the 2620 * connection for the service. 2621 */ 2622 class Service extends IAccessibilityServiceConnection.Stub 2623 implements ServiceConnection, DeathRecipient, KeyEventDispatcher.KeyEventFilter, 2624 FingerprintGestureDispatcher.FingerprintGestureClient { 2625 2626 final int mUserId; 2627 2628 int mId = 0; 2629 2630 AccessibilityServiceInfo mAccessibilityServiceInfo; 2631 2632 // The service that's bound to this instance. Whenever this value is non-null, this 2633 // object is registered as a death recipient 2634 IBinder mService; 2635 2636 IAccessibilityServiceClient mServiceInterface; 2637 2638 int mEventTypes; 2639 2640 int mFeedbackType; 2641 2642 Set<String> mPackageNames = new HashSet<>(); 2643 2644 boolean mIsDefault; 2645 2646 boolean mRequestTouchExplorationMode; 2647 2648 boolean mRequestFilterKeyEvents; 2649 2650 boolean mRetrieveInteractiveWindows; 2651 2652 boolean mCaptureFingerprintGestures; 2653 2654 boolean mRequestAccessibilityButton; 2655 2656 boolean mReceivedAccessibilityButtonCallbackSinceBind; 2657 2658 boolean mLastAccessibilityButtonCallbackState; 2659 2660 int mFetchFlags; 2661 2662 long mNotificationTimeout; 2663 2664 ComponentName mComponentName; 2665 2666 Intent mIntent; 2667 2668 boolean mIsAutomation; 2669 2670 final ResolveInfo mResolveInfo; 2671 2672 final IBinder mOverlayWindowToken = new Binder(); 2673 2674 // the events pending events to be dispatched to this service 2675 final SparseArray<AccessibilityEvent> mPendingEvents = 2676 new SparseArray<>(); 2677 2678 boolean mWasConnectedAndDied; 2679 2680 /** Whether this service relies on its {@link AccessibilityCache} being up to date */ 2681 boolean mUsesAccessibilityCache = false; 2682 2683 // Handler only for dispatching accessibility events since we use event 2684 // types as message types allowing us to remove messages per event type. 2685 public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) { 2686 @Override 2687 public void handleMessage(Message message) { 2688 final int eventType = message.what; 2689 AccessibilityEvent event = (AccessibilityEvent) message.obj; 2690 boolean serviceWantsEvent = message.arg1 != 0; 2691 notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent); 2692 } 2693 }; 2694 2695 // Handler for scheduling method invocations on the main thread. 2696 public final InvocationHandler mInvocationHandler = new InvocationHandler( 2697 mMainHandler.getLooper()); 2698 2699 public Service(int userId, ComponentName componentName, 2700 AccessibilityServiceInfo accessibilityServiceInfo) { 2701 mUserId = userId; 2702 mResolveInfo = accessibilityServiceInfo.getResolveInfo(); 2703 mId = sIdCounter++; 2704 mComponentName = componentName; 2705 mAccessibilityServiceInfo = accessibilityServiceInfo; 2706 mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName)); 2707 if (!mIsAutomation) { 2708 mIntent = new Intent().setComponent(mComponentName); 2709 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, 2710 com.android.internal.R.string.accessibility_binding_label); 2711 final long idendtity = Binder.clearCallingIdentity(); 2712 try { 2713 mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( 2714 mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); 2715 } finally { 2716 Binder.restoreCallingIdentity(idendtity); 2717 } 2718 } 2719 setDynamicallyConfigurableProperties(accessibilityServiceInfo); 2720 } 2721 2722 @Override 2723 public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) { 2724 if (!mRequestFilterKeyEvents || (mServiceInterface == null)) { 2725 return false; 2726 } 2727 if((mAccessibilityServiceInfo.getCapabilities() 2728 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { 2729 return false; 2730 } 2731 try { 2732 mServiceInterface.onKeyEvent(keyEvent, sequenceNumber); 2733 } catch (RemoteException e) { 2734 return false; 2735 } 2736 return true; 2737 } 2738 2739 @Override 2740 public boolean isCapturingFingerprintGestures() { 2741 return (mServiceInterface != null) 2742 && mSecurityPolicy.canCaptureFingerprintGestures(this) 2743 && mCaptureFingerprintGestures; 2744 } 2745 2746 @Override 2747 public void onFingerprintGestureDetectionActiveChanged(boolean active) { 2748 if (!isCapturingFingerprintGestures()) { 2749 return; 2750 } 2751 IAccessibilityServiceClient serviceInterface; 2752 synchronized (mLock) { 2753 serviceInterface = mServiceInterface; 2754 } 2755 if (serviceInterface != null) { 2756 try { 2757 mServiceInterface.onFingerprintCapturingGesturesChanged(active); 2758 } catch (RemoteException e) { 2759 } 2760 } 2761 } 2762 2763 @Override 2764 public void onFingerprintGesture(int gesture) { 2765 if (!isCapturingFingerprintGestures()) { 2766 return; 2767 } 2768 IAccessibilityServiceClient serviceInterface; 2769 synchronized (mLock) { 2770 serviceInterface = mServiceInterface; 2771 } 2772 if (serviceInterface != null) { 2773 try { 2774 mServiceInterface.onFingerprintGesture(gesture); 2775 } catch (RemoteException e) { 2776 } 2777 } 2778 } 2779 2780 public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { 2781 mEventTypes = info.eventTypes; 2782 mFeedbackType = info.feedbackType; 2783 String[] packageNames = info.packageNames; 2784 if (packageNames != null) { 2785 mPackageNames.addAll(Arrays.asList(packageNames)); 2786 } 2787 mNotificationTimeout = info.notificationTimeout; 2788 mIsDefault = (info.flags & DEFAULT) != 0; 2789 2790 if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion 2791 >= Build.VERSION_CODES.JELLY_BEAN) { 2792 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { 2793 mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 2794 } else { 2795 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 2796 } 2797 } 2798 2799 if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { 2800 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 2801 } else { 2802 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 2803 } 2804 2805 mRequestTouchExplorationMode = (info.flags 2806 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; 2807 mRequestFilterKeyEvents = (info.flags 2808 & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; 2809 mRetrieveInteractiveWindows = (info.flags 2810 & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; 2811 mCaptureFingerprintGestures = (info.flags 2812 & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0; 2813 mRequestAccessibilityButton = (info.flags 2814 & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; 2815 } 2816 2817 /** 2818 * Binds to the accessibility service. 2819 * 2820 * @return True if binding is successful. 2821 */ 2822 public boolean bindLocked() { 2823 UserState userState = getUserStateLocked(mUserId); 2824 if (!mIsAutomation) { 2825 final long identity = Binder.clearCallingIdentity(); 2826 try { 2827 if (mService == null && mContext.bindServiceAsUser( 2828 mIntent, this, 2829 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 2830 new UserHandle(mUserId))) { 2831 userState.mBindingServices.add(mComponentName); 2832 } 2833 } finally { 2834 Binder.restoreCallingIdentity(identity); 2835 } 2836 } else { 2837 userState.mBindingServices.add(mComponentName); 2838 mMainHandler.post(new Runnable() { 2839 @Override 2840 public void run() { 2841 // Simulate asynchronous connection since in onServiceConnected 2842 // we may modify the state data in case of an error but bind is 2843 // called while iterating over the data and bad things can happen. 2844 onServiceConnected(mComponentName, 2845 userState.mUiAutomationServiceClient.asBinder()); 2846 } 2847 }); 2848 userState.mUiAutomationService = this; 2849 } 2850 return false; 2851 } 2852 2853 /** 2854 * Unbinds from the accessibility service and removes it from the data 2855 * structures for service management. 2856 * 2857 * @return True if unbinding is successful. 2858 */ 2859 public boolean unbindLocked() { 2860 UserState userState = getUserStateLocked(mUserId); 2861 getKeyEventDispatcher().flush(this); 2862 if (!mIsAutomation) { 2863 mContext.unbindService(this); 2864 } else { 2865 userState.destroyUiAutomationService(); 2866 } 2867 removeServiceLocked(this, userState); 2868 resetLocked(); 2869 return true; 2870 } 2871 2872 @Override 2873 public void disableSelf() { 2874 synchronized(mLock) { 2875 UserState userState = getUserStateLocked(mUserId); 2876 if (userState.mEnabledServices.remove(mComponentName)) { 2877 final long identity = Binder.clearCallingIdentity(); 2878 try { 2879 persistComponentNamesToSettingLocked( 2880 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 2881 userState.mEnabledServices, mUserId); 2882 } finally { 2883 Binder.restoreCallingIdentity(identity); 2884 } 2885 onUserStateChangedLocked(userState); 2886 } 2887 } 2888 } 2889 2890 public boolean canReceiveEventsLocked() { 2891 return (mEventTypes != 0 && mFeedbackType != 0 && mService != null); 2892 } 2893 2894 @Override 2895 public void setOnKeyEventResult(boolean handled, int sequence) { 2896 getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence); 2897 } 2898 2899 @Override 2900 public AccessibilityServiceInfo getServiceInfo() { 2901 synchronized (mLock) { 2902 return mAccessibilityServiceInfo; 2903 } 2904 } 2905 2906 public boolean canRetrieveInteractiveWindowsLocked() { 2907 return mSecurityPolicy.canRetrieveWindowContentLocked(this) 2908 && mRetrieveInteractiveWindows; 2909 } 2910 2911 @Override 2912 public void setServiceInfo(AccessibilityServiceInfo info) { 2913 final long identity = Binder.clearCallingIdentity(); 2914 try { 2915 synchronized (mLock) { 2916 // If the XML manifest had data to configure the service its info 2917 // should be already set. In such a case update only the dynamically 2918 // configurable properties. 2919 AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; 2920 if (oldInfo != null) { 2921 oldInfo.updateDynamicallyConfigurableProperties(info); 2922 setDynamicallyConfigurableProperties(oldInfo); 2923 } else { 2924 setDynamicallyConfigurableProperties(info); 2925 } 2926 UserState userState = getUserStateLocked(mUserId); 2927 onUserStateChangedLocked(userState); 2928 scheduleNotifyClientsOfServicesStateChange(userState); 2929 } 2930 } finally { 2931 Binder.restoreCallingIdentity(identity); 2932 } 2933 } 2934 2935 @Override 2936 public void onServiceConnected(ComponentName componentName, IBinder service) { 2937 synchronized (mLock) { 2938 if (mService != service) { 2939 if (mService != null) { 2940 mService.unlinkToDeath(this, 0); 2941 } 2942 mService = service; 2943 try { 2944 mService.linkToDeath(this, 0); 2945 } catch (RemoteException re) { 2946 Slog.e(LOG_TAG, "Failed registering death link"); 2947 binderDied(); 2948 return; 2949 } 2950 } 2951 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service); 2952 UserState userState = getUserStateLocked(mUserId); 2953 addServiceLocked(this, userState); 2954 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) { 2955 userState.mBindingServices.remove(mComponentName); 2956 mWasConnectedAndDied = false; 2957 try { 2958 mServiceInterface.init(this, mId, mOverlayWindowToken); 2959 onUserStateChangedLocked(userState); 2960 } catch (RemoteException re) { 2961 Slog.w(LOG_TAG, "Error while setting connection for service: " 2962 + service, re); 2963 binderDied(); 2964 } 2965 } else { 2966 binderDied(); 2967 } 2968 } 2969 } 2970 2971 private boolean isCalledForCurrentUserLocked() { 2972 // We treat calls from a profile as if made by its parent as profiles 2973 // share the accessibility state of the parent. The call below 2974 // performs the current profile parent resolution. 2975 final int resolvedUserId = mSecurityPolicy 2976 .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT); 2977 return resolvedUserId == mCurrentUserId; 2978 } 2979 2980 @Override 2981 public List<AccessibilityWindowInfo> getWindows() { 2982 ensureWindowsAvailableTimed(); 2983 synchronized (mLock) { 2984 if (!isCalledForCurrentUserLocked()) { 2985 return null; 2986 } 2987 final boolean permissionGranted = 2988 mSecurityPolicy.canRetrieveWindowsLocked(this); 2989 if (!permissionGranted) { 2990 return null; 2991 } 2992 if (mSecurityPolicy.mWindows == null) { 2993 return null; 2994 } 2995 List<AccessibilityWindowInfo> windows = new ArrayList<>(); 2996 final int windowCount = mSecurityPolicy.mWindows.size(); 2997 for (int i = 0; i < windowCount; i++) { 2998 AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i); 2999 AccessibilityWindowInfo windowClone = 3000 AccessibilityWindowInfo.obtain(window); 3001 windowClone.setConnectionId(mId); 3002 windows.add(windowClone); 3003 } 3004 return windows; 3005 } 3006 } 3007 3008 @Override 3009 public AccessibilityWindowInfo getWindow(int windowId) { 3010 ensureWindowsAvailableTimed(); 3011 synchronized (mLock) { 3012 if (!isCalledForCurrentUserLocked()) { 3013 return null; 3014 } 3015 final boolean permissionGranted = 3016 mSecurityPolicy.canRetrieveWindowsLocked(this); 3017 if (!permissionGranted) { 3018 return null; 3019 } 3020 AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId); 3021 if (window != null) { 3022 AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); 3023 windowClone.setConnectionId(mId); 3024 return windowClone; 3025 } 3026 return null; 3027 } 3028 } 3029 3030 @Override 3031 public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId, 3032 long accessibilityNodeId, String viewIdResName, int interactionId, 3033 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3034 throws RemoteException { 3035 final int resolvedWindowId; 3036 IAccessibilityInteractionConnection connection = null; 3037 Region partialInteractiveRegion = Region.obtain(); 3038 MagnificationSpec spec; 3039 synchronized (mLock) { 3040 mUsesAccessibilityCache = true; 3041 if (!isCalledForCurrentUserLocked()) { 3042 return false; 3043 } 3044 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3045 final boolean permissionGranted = 3046 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3047 if (!permissionGranted) { 3048 return false; 3049 } else { 3050 connection = getConnectionLocked(resolvedWindowId); 3051 if (connection == null) { 3052 return false; 3053 } 3054 } 3055 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3056 resolvedWindowId, partialInteractiveRegion)) { 3057 partialInteractiveRegion.recycle(); 3058 partialInteractiveRegion = null; 3059 } 3060 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3061 } 3062 final int interrogatingPid = Binder.getCallingPid(); 3063 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3064 interrogatingPid, interrogatingTid); 3065 final long identityToken = Binder.clearCallingIdentity(); 3066 try { 3067 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName, 3068 partialInteractiveRegion, interactionId, callback, mFetchFlags, 3069 interrogatingPid, interrogatingTid, spec); 3070 return true; 3071 } catch (RemoteException re) { 3072 if (DEBUG) { 3073 Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); 3074 } 3075 } finally { 3076 Binder.restoreCallingIdentity(identityToken); 3077 // Recycle if passed to another process. 3078 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3079 partialInteractiveRegion.recycle(); 3080 } 3081 } 3082 return false; 3083 } 3084 3085 @Override 3086 public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, 3087 long accessibilityNodeId, String text, int interactionId, 3088 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3089 throws RemoteException { 3090 final int resolvedWindowId; 3091 IAccessibilityInteractionConnection connection = null; 3092 Region partialInteractiveRegion = Region.obtain(); 3093 MagnificationSpec spec; 3094 synchronized (mLock) { 3095 mUsesAccessibilityCache = true; 3096 if (!isCalledForCurrentUserLocked()) { 3097 return false; 3098 } 3099 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3100 final boolean permissionGranted = 3101 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3102 if (!permissionGranted) { 3103 return false; 3104 } else { 3105 connection = getConnectionLocked(resolvedWindowId); 3106 if (connection == null) { 3107 return false; 3108 } 3109 } 3110 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3111 resolvedWindowId, partialInteractiveRegion)) { 3112 partialInteractiveRegion.recycle(); 3113 partialInteractiveRegion = null; 3114 } 3115 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3116 } 3117 final int interrogatingPid = Binder.getCallingPid(); 3118 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3119 interrogatingPid, interrogatingTid); 3120 final long identityToken = Binder.clearCallingIdentity(); 3121 try { 3122 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, 3123 partialInteractiveRegion, interactionId, callback, mFetchFlags, 3124 interrogatingPid, interrogatingTid, spec); 3125 return true; 3126 } catch (RemoteException re) { 3127 if (DEBUG) { 3128 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); 3129 } 3130 } finally { 3131 Binder.restoreCallingIdentity(identityToken); 3132 // Recycle if passed to another process. 3133 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3134 partialInteractiveRegion.recycle(); 3135 } 3136 } 3137 return false; 3138 } 3139 3140 @Override 3141 public boolean findAccessibilityNodeInfoByAccessibilityId( 3142 int accessibilityWindowId, long accessibilityNodeId, int interactionId, 3143 IAccessibilityInteractionConnectionCallback callback, int flags, 3144 long interrogatingTid, Bundle arguments) throws RemoteException { 3145 final int resolvedWindowId; 3146 IAccessibilityInteractionConnection connection = null; 3147 Region partialInteractiveRegion = Region.obtain(); 3148 MagnificationSpec spec; 3149 synchronized (mLock) { 3150 mUsesAccessibilityCache = true; 3151 if (!isCalledForCurrentUserLocked()) { 3152 return false; 3153 } 3154 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3155 final boolean permissionGranted = 3156 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3157 if (!permissionGranted) { 3158 return false; 3159 } else { 3160 connection = getConnectionLocked(resolvedWindowId); 3161 if (connection == null) { 3162 return false; 3163 } 3164 } 3165 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3166 resolvedWindowId, partialInteractiveRegion)) { 3167 partialInteractiveRegion.recycle(); 3168 partialInteractiveRegion = null; 3169 } 3170 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3171 } 3172 final int interrogatingPid = Binder.getCallingPid(); 3173 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3174 interrogatingPid, interrogatingTid); 3175 final long identityToken = Binder.clearCallingIdentity(); 3176 try { 3177 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, 3178 partialInteractiveRegion, interactionId, callback, mFetchFlags | flags, 3179 interrogatingPid, interrogatingTid, spec, arguments); 3180 return true; 3181 } catch (RemoteException re) { 3182 if (DEBUG) { 3183 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); 3184 } 3185 } finally { 3186 Binder.restoreCallingIdentity(identityToken); 3187 // Recycle if passed to another process. 3188 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3189 partialInteractiveRegion.recycle(); 3190 } 3191 } 3192 return false; 3193 } 3194 3195 @Override 3196 public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, 3197 int focusType, int interactionId, 3198 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3199 throws RemoteException { 3200 final int resolvedWindowId; 3201 IAccessibilityInteractionConnection connection = null; 3202 Region partialInteractiveRegion = Region.obtain(); 3203 MagnificationSpec spec; 3204 synchronized (mLock) { 3205 if (!isCalledForCurrentUserLocked()) { 3206 return false; 3207 } 3208 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( 3209 accessibilityWindowId, focusType); 3210 final boolean permissionGranted = 3211 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3212 if (!permissionGranted) { 3213 return false; 3214 } else { 3215 connection = getConnectionLocked(resolvedWindowId); 3216 if (connection == null) { 3217 return false; 3218 } 3219 } 3220 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3221 resolvedWindowId, partialInteractiveRegion)) { 3222 partialInteractiveRegion.recycle(); 3223 partialInteractiveRegion = null; 3224 } 3225 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3226 } 3227 final int interrogatingPid = Binder.getCallingPid(); 3228 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3229 interrogatingPid, interrogatingTid); 3230 final long identityToken = Binder.clearCallingIdentity(); 3231 try { 3232 connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, 3233 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, 3234 spec); 3235 return true; 3236 } catch (RemoteException re) { 3237 if (DEBUG) { 3238 Slog.e(LOG_TAG, "Error calling findFocus()"); 3239 } 3240 } finally { 3241 Binder.restoreCallingIdentity(identityToken); 3242 // Recycle if passed to another process. 3243 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3244 partialInteractiveRegion.recycle(); 3245 } 3246 } 3247 return false; 3248 } 3249 3250 @Override 3251 public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, 3252 int direction, int interactionId, 3253 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3254 throws RemoteException { 3255 final int resolvedWindowId; 3256 IAccessibilityInteractionConnection connection = null; 3257 Region partialInteractiveRegion = Region.obtain(); 3258 MagnificationSpec spec; 3259 synchronized (mLock) { 3260 if (!isCalledForCurrentUserLocked()) { 3261 return false; 3262 } 3263 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3264 final boolean permissionGranted = 3265 mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 3266 if (!permissionGranted) { 3267 return false; 3268 } else { 3269 connection = getConnectionLocked(resolvedWindowId); 3270 if (connection == null) { 3271 return false; 3272 } 3273 } 3274 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 3275 resolvedWindowId, partialInteractiveRegion)) { 3276 partialInteractiveRegion.recycle(); 3277 partialInteractiveRegion = null; 3278 } 3279 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 3280 } 3281 final int interrogatingPid = Binder.getCallingPid(); 3282 callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, 3283 interrogatingPid, interrogatingTid); 3284 final long identityToken = Binder.clearCallingIdentity(); 3285 try { 3286 connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, 3287 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, 3288 spec); 3289 return true; 3290 } catch (RemoteException re) { 3291 if (DEBUG) { 3292 Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); 3293 } 3294 } finally { 3295 Binder.restoreCallingIdentity(identityToken); 3296 // Recycle if passed to another process. 3297 if (partialInteractiveRegion != null && Binder.isProxy(connection)) { 3298 partialInteractiveRegion.recycle(); 3299 } 3300 } 3301 return false; 3302 } 3303 3304 @Override 3305 public void sendGesture(int sequence, ParceledListSlice gestureSteps) { 3306 synchronized (mLock) { 3307 if (mSecurityPolicy.canPerformGestures(this)) { 3308 final long endMillis = 3309 SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS; 3310 while ((mMotionEventInjector == null) 3311 && (SystemClock.uptimeMillis() < endMillis)) { 3312 try { 3313 mLock.wait(endMillis - SystemClock.uptimeMillis()); 3314 } catch (InterruptedException ie) { 3315 /* ignore */ 3316 } 3317 } 3318 if (mMotionEventInjector != null) { 3319 List<GestureDescription.GestureStep> steps = gestureSteps.getList(); 3320 mMotionEventInjector.injectEvents(steps, mServiceInterface, sequence); 3321 return; 3322 } else { 3323 Slog.e(LOG_TAG, "MotionEventInjector installation timed out"); 3324 } 3325 } 3326 } 3327 try { 3328 mServiceInterface.onPerformGestureResult(sequence, false); 3329 } catch (RemoteException re) { 3330 Slog.e(LOG_TAG, "Error sending motion event injection failure to " 3331 + mServiceInterface, re); 3332 } 3333 } 3334 3335 @Override 3336 public boolean performAccessibilityAction(int accessibilityWindowId, 3337 long accessibilityNodeId, int action, Bundle arguments, int interactionId, 3338 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 3339 throws RemoteException { 3340 final int resolvedWindowId; 3341 IAccessibilityInteractionConnection connection = null; 3342 synchronized (mLock) { 3343 if (!isCalledForCurrentUserLocked()) { 3344 return false; 3345 } 3346 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 3347 final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 3348 this, resolvedWindowId); 3349 if (!permissionGranted) { 3350 return false; 3351 } else { 3352 connection = getConnectionLocked(resolvedWindowId); 3353 if (connection == null) { 3354 return false; 3355 } 3356 AccessibilityWindowInfo windowInfo = 3357 mSecurityPolicy.findWindowById(resolvedWindowId); 3358 if ((windowInfo != null) && windowInfo.inPictureInPicture()) { 3359 boolean isA11yFocusAction = 3360 (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) 3361 || (action == 3362 AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 3363 if ((mPictureInPictureActionReplacingConnection != null) 3364 && !isA11yFocusAction) { 3365 connection = mPictureInPictureActionReplacingConnection.mConnection; 3366 } 3367 } 3368 } 3369 } 3370 final int interrogatingPid = Binder.getCallingPid(); 3371 final long identityToken = Binder.clearCallingIdentity(); 3372 try { 3373 // Regardless of whether or not the action succeeds, it was generated by an 3374 // accessibility service that is driven by user actions, so note user activity. 3375 mPowerManager.userActivity(SystemClock.uptimeMillis(), 3376 PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); 3377 3378 connection.performAccessibilityAction(accessibilityNodeId, action, arguments, 3379 interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid); 3380 } catch (RemoteException re) { 3381 if (DEBUG) { 3382 Slog.e(LOG_TAG, "Error calling performAccessibilityAction()"); 3383 } 3384 } finally { 3385 Binder.restoreCallingIdentity(identityToken); 3386 } 3387 return true; 3388 } 3389 3390 @Override 3391 public boolean performGlobalAction(int action) { 3392 synchronized (mLock) { 3393 if (!isCalledForCurrentUserLocked()) { 3394 return false; 3395 } 3396 } 3397 final long identity = Binder.clearCallingIdentity(); 3398 try { 3399 mPowerManager.userActivity(SystemClock.uptimeMillis(), 3400 PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); 3401 switch (action) { 3402 case AccessibilityService.GLOBAL_ACTION_BACK: { 3403 sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK); 3404 } return true; 3405 case AccessibilityService.GLOBAL_ACTION_HOME: { 3406 sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME); 3407 } return true; 3408 case AccessibilityService.GLOBAL_ACTION_RECENTS: { 3409 return openRecents(); 3410 } 3411 case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: { 3412 expandNotifications(); 3413 } return true; 3414 case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: { 3415 expandQuickSettings(); 3416 } return true; 3417 case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: { 3418 showGlobalActions(); 3419 } return true; 3420 case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: { 3421 toggleSplitScreen(); 3422 } return true; 3423 } 3424 return false; 3425 } finally { 3426 Binder.restoreCallingIdentity(identity); 3427 } 3428 } 3429 3430 @Override 3431 public boolean isFingerprintGestureDetectionAvailable() { 3432 return isCapturingFingerprintGestures() 3433 && (mFingerprintGestureDispatcher != null) 3434 && mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable(); 3435 } 3436 3437 @Override 3438 public float getMagnificationScale() { 3439 synchronized (mLock) { 3440 if (!isCalledForCurrentUserLocked()) { 3441 return 1.0f; 3442 } 3443 } 3444 final long identity = Binder.clearCallingIdentity(); 3445 try { 3446 return getMagnificationController().getScale(); 3447 } finally { 3448 Binder.restoreCallingIdentity(identity); 3449 } 3450 } 3451 3452 @Override 3453 public Region getMagnificationRegion() { 3454 synchronized (mLock) { 3455 final Region region = Region.obtain(); 3456 if (!isCalledForCurrentUserLocked()) { 3457 return region; 3458 } 3459 MagnificationController magnificationController = getMagnificationController(); 3460 boolean forceRegistration = mSecurityPolicy.canControlMagnification(this); 3461 boolean initiallyRegistered = magnificationController.isRegisteredLocked(); 3462 if (!initiallyRegistered && forceRegistration) { 3463 magnificationController.register(); 3464 } 3465 final long identity = Binder.clearCallingIdentity(); 3466 try { 3467 magnificationController.getMagnificationRegion(region); 3468 return region; 3469 } finally { 3470 Binder.restoreCallingIdentity(identity); 3471 if (!initiallyRegistered && forceRegistration) { 3472 magnificationController.unregister(); 3473 } 3474 } 3475 } 3476 } 3477 3478 @Override 3479 public float getMagnificationCenterX() { 3480 synchronized (mLock) { 3481 if (!isCalledForCurrentUserLocked()) { 3482 return 0.0f; 3483 } 3484 } 3485 final long identity = Binder.clearCallingIdentity(); 3486 try { 3487 return getMagnificationController().getCenterX(); 3488 } finally { 3489 Binder.restoreCallingIdentity(identity); 3490 } 3491 } 3492 3493 @Override 3494 public float getMagnificationCenterY() { 3495 synchronized (mLock) { 3496 if (!isCalledForCurrentUserLocked()) { 3497 return 0.0f; 3498 } 3499 } 3500 final long identity = Binder.clearCallingIdentity(); 3501 try { 3502 return getMagnificationController().getCenterY(); 3503 } finally { 3504 Binder.restoreCallingIdentity(identity); 3505 } 3506 } 3507 3508 @Override 3509 public boolean resetMagnification(boolean animate) { 3510 synchronized (mLock) { 3511 if (!isCalledForCurrentUserLocked()) { 3512 return false; 3513 } 3514 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this); 3515 if (!permissionGranted) { 3516 return false; 3517 } 3518 } 3519 final long identity = Binder.clearCallingIdentity(); 3520 try { 3521 return getMagnificationController().reset(animate); 3522 } finally { 3523 Binder.restoreCallingIdentity(identity); 3524 } 3525 } 3526 3527 @Override 3528 public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY, 3529 boolean animate) { 3530 synchronized (mLock) { 3531 if (!isCalledForCurrentUserLocked()) { 3532 return false; 3533 } 3534 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this); 3535 if (!permissionGranted) { 3536 return false; 3537 } 3538 final long identity = Binder.clearCallingIdentity(); 3539 try { 3540 MagnificationController magnificationController = getMagnificationController(); 3541 if (!magnificationController.isRegisteredLocked()) { 3542 magnificationController.register(); 3543 } 3544 return magnificationController 3545 .setScaleAndCenter(scale, centerX, centerY, animate, mId); 3546 } finally { 3547 Binder.restoreCallingIdentity(identity); 3548 } 3549 } 3550 } 3551 3552 @Override 3553 public void setMagnificationCallbackEnabled(boolean enabled) { 3554 mInvocationHandler.setMagnificationCallbackEnabled(enabled); 3555 } 3556 3557 @Override 3558 public boolean setSoftKeyboardShowMode(int showMode) { 3559 final UserState userState; 3560 synchronized (mLock) { 3561 if (!isCalledForCurrentUserLocked()) { 3562 return false; 3563 } 3564 3565 userState = getCurrentUserStateLocked(); 3566 } 3567 3568 final long identity = Binder.clearCallingIdentity(); 3569 try { 3570 // Keep track of the last service to request a non-default show mode. The show mode 3571 // should be restored to default should this service be disabled. 3572 if (showMode == Settings.Secure.SHOW_MODE_AUTO) { 3573 userState.mServiceChangingSoftKeyboardMode = null; 3574 } else { 3575 userState.mServiceChangingSoftKeyboardMode = mComponentName; 3576 } 3577 3578 Settings.Secure.putIntForUser(mContext.getContentResolver(), 3579 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode, 3580 userState.mUserId); 3581 } finally { 3582 Binder.restoreCallingIdentity(identity); 3583 } 3584 return true; 3585 } 3586 3587 @Override 3588 public void setSoftKeyboardCallbackEnabled(boolean enabled) { 3589 mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled); 3590 } 3591 3592 @Override 3593 public boolean isAccessibilityButtonAvailable() { 3594 final UserState userState; 3595 synchronized (mLock) { 3596 if (!isCalledForCurrentUserLocked()) { 3597 return false; 3598 } 3599 userState = getCurrentUserStateLocked(); 3600 return isAccessibilityButtonAvailableLocked(userState); 3601 } 3602 } 3603 3604 @Override 3605 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 3606 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 3607 synchronized (mLock) { 3608 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo() 3609 .loadLabel(mContext.getPackageManager())); 3610 pw.append(", feedbackType" 3611 + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); 3612 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); 3613 pw.append(", eventTypes=" 3614 + AccessibilityEvent.eventTypeToString(mEventTypes)); 3615 pw.append(", notificationTimeout=" + mNotificationTimeout); 3616 pw.append("]"); 3617 } 3618 } 3619 3620 @Override 3621 public void onServiceDisconnected(ComponentName componentName) { 3622 binderDied(); 3623 } 3624 3625 public void onAdded() throws RemoteException { 3626 final long identity = Binder.clearCallingIdentity(); 3627 try { 3628 mWindowManagerService.addWindowToken(mOverlayWindowToken, 3629 TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY); 3630 } finally { 3631 Binder.restoreCallingIdentity(identity); 3632 } 3633 } 3634 3635 public void onRemoved() { 3636 final long identity = Binder.clearCallingIdentity(); 3637 try { 3638 mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY); 3639 } finally { 3640 Binder.restoreCallingIdentity(identity); 3641 } 3642 } 3643 3644 public void resetLocked() { 3645 try { 3646 // Clear the proxy in the other process so this 3647 // IAccessibilityServiceConnection can be garbage collected. 3648 if (mServiceInterface != null) { 3649 mServiceInterface.init(null, mId, null); 3650 } 3651 } catch (RemoteException re) { 3652 /* ignore */ 3653 } 3654 if (mService != null) { 3655 mService.unlinkToDeath(this, 0); 3656 mService = null; 3657 } 3658 mServiceInterface = null; 3659 mReceivedAccessibilityButtonCallbackSinceBind = false; 3660 } 3661 3662 public boolean isConnectedLocked() { 3663 return (mService != null); 3664 } 3665 3666 public void binderDied() { 3667 synchronized (mLock) { 3668 // It is possible that this service's package was force stopped during 3669 // whose handling the death recipient is unlinked and still get a call 3670 // on binderDied since the call was made before we unlink but was 3671 // waiting on the lock we held during the force stop handling. 3672 if (!isConnectedLocked()) { 3673 return; 3674 } 3675 mWasConnectedAndDied = true; 3676 getKeyEventDispatcher().flush(this); 3677 UserState userState = getUserStateLocked(mUserId); 3678 resetLocked(); 3679 if (mIsAutomation) { 3680 // This is typically done when unbinding, but UiAutomation isn't bound. 3681 removeServiceLocked(this, userState); 3682 // We no longer have an automation service, so restore 3683 // the state based on values in the settings database. 3684 userState.mInstalledServices.remove(mAccessibilityServiceInfo); 3685 userState.mEnabledServices.remove(mComponentName); 3686 userState.destroyUiAutomationService(); 3687 readConfigurationForUserStateLocked(userState); 3688 } 3689 if (mId == getMagnificationController().getIdOfLastServiceToMagnify()) { 3690 getMagnificationController().resetIfNeeded(true); 3691 } 3692 onUserStateChangedLocked(userState); 3693 } 3694 } 3695 3696 /** 3697 * Performs a notification for an {@link AccessibilityEvent}. 3698 * 3699 * @param event The event. 3700 * @param serviceWantsEvent whether the event should be received by 3701 * {@link AccessibilityService#onAccessibilityEvent} (true), 3702 * as opposed to just {@link AccessibilityInteractionClient#onAccessibilityEvent} (false) 3703 */ 3704 public void notifyAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) { 3705 synchronized (mLock) { 3706 final int eventType = event.getEventType(); 3707 // Make a copy since during dispatch it is possible the event to 3708 // be modified to remove its source if the receiving service does 3709 // not have permission to access the window content. 3710 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); 3711 Message message; 3712 if ((mNotificationTimeout > 0) 3713 && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) { 3714 // Allow at most one pending event 3715 final AccessibilityEvent oldEvent = mPendingEvents.get(eventType); 3716 mPendingEvents.put(eventType, newEvent); 3717 if (oldEvent != null) { 3718 mEventDispatchHandler.removeMessages(eventType); 3719 oldEvent.recycle(); 3720 } 3721 message = mEventDispatchHandler.obtainMessage(eventType); 3722 } else { 3723 // Send all messages, bypassing mPendingEvents 3724 message = mEventDispatchHandler.obtainMessage(eventType, newEvent); 3725 } 3726 message.arg1 = serviceWantsEvent ? 1 : 0; 3727 3728 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout); 3729 } 3730 } 3731 3732 private boolean isAccessibilityButtonAvailableLocked(UserState userState) { 3733 // If the service does not request the accessibility button, it isn't available 3734 if (!mRequestAccessibilityButton) { 3735 return false; 3736 } 3737 3738 // If the accessibility button isn't currently shown, it cannot be available to services 3739 if (!mIsAccessibilityButtonShown) { 3740 return false; 3741 } 3742 3743 // If magnification is on and assigned to the accessibility button, services cannot be 3744 if (userState.mIsNavBarMagnificationEnabled 3745 && userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { 3746 return false; 3747 } 3748 3749 int requestingServices = 0; 3750 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 3751 final Service service = userState.mBoundServices.get(i); 3752 if (service.mRequestAccessibilityButton) { 3753 requestingServices++; 3754 } 3755 } 3756 3757 if (requestingServices == 1) { 3758 // If only a single service is requesting, it must be this service, and the 3759 // accessibility button is available to it 3760 return true; 3761 } else { 3762 // With more than one active service, we derive the target from the user's settings 3763 if (userState.mServiceAssignedToAccessibilityButton == null) { 3764 // If the user has not made an assignment, we treat the button as available to 3765 // all services until the user interacts with the button to make an assignment 3766 return true; 3767 } else { 3768 // If an assignment was made, it defines availability 3769 return mComponentName.equals(userState.mServiceAssignedToAccessibilityButton); 3770 } 3771 } 3772 } 3773 3774 /** 3775 * Notifies an accessibility service client for a scheduled event given the event type. 3776 * 3777 * @param eventType The type of the event to dispatch. 3778 */ 3779 private void notifyAccessibilityEventInternal( 3780 int eventType, 3781 AccessibilityEvent event, 3782 boolean serviceWantsEvent) { 3783 IAccessibilityServiceClient listener; 3784 3785 synchronized (mLock) { 3786 listener = mServiceInterface; 3787 3788 // If the service died/was disabled while the message for dispatching 3789 // the accessibility event was propagating the listener may be null. 3790 if (listener == null) { 3791 return; 3792 } 3793 3794 // There are two ways we notify for events, throttled and non-throttled. If we 3795 // are not throttling, then messages come with events, which we handle with 3796 // minimal fuss. 3797 if (event == null) { 3798 // We are throttling events, so we'll send the event for this type in 3799 // mPendingEvents as long as it it's null. It can only null due to a race 3800 // condition: 3801 // 3802 // 1) A binder thread calls notifyAccessibilityServiceDelayedLocked 3803 // which posts a message for dispatching an event and stores the event 3804 // in mPendingEvents. 3805 // 2) The message is pulled from the queue by the handler on the service 3806 // thread and this method is just about to acquire the lock. 3807 // 3) Another binder thread acquires the lock in notifyAccessibilityEvent 3808 // 4) notifyAccessibilityEvent recycles the event that this method was about 3809 // to process, replaces it with a new one, and posts a second message 3810 // 5) This method grabs the new event, processes it, and removes it from 3811 // mPendingEvents 3812 // 6) The second message dispatched in (4) arrives, but the event has been 3813 // remvoved in (5). 3814 event = mPendingEvents.get(eventType); 3815 if (event == null) { 3816 return; 3817 } 3818 mPendingEvents.remove(eventType); 3819 } 3820 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) { 3821 event.setConnectionId(mId); 3822 } else { 3823 event.setSource((View) null); 3824 } 3825 event.setSealed(true); 3826 } 3827 3828 try { 3829 listener.onAccessibilityEvent(event, serviceWantsEvent); 3830 if (DEBUG) { 3831 Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); 3832 } 3833 } catch (RemoteException re) { 3834 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); 3835 } finally { 3836 event.recycle(); 3837 } 3838 } 3839 3840 public void notifyGesture(int gestureId) { 3841 mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, 3842 gestureId, 0).sendToTarget(); 3843 } 3844 3845 public void notifyClearAccessibilityNodeInfoCache() { 3846 mInvocationHandler.sendEmptyMessage( 3847 InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); 3848 } 3849 3850 public void notifyMagnificationChangedLocked(@NonNull Region region, 3851 float scale, float centerX, float centerY) { 3852 mInvocationHandler 3853 .notifyMagnificationChangedLocked(region, scale, centerX, centerY); 3854 } 3855 3856 public void notifySoftKeyboardShowModeChangedLocked(int showState) { 3857 mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState); 3858 } 3859 3860 public void notifyAccessibilityButtonClickedLocked() { 3861 mInvocationHandler.notifyAccessibilityButtonClickedLocked(); 3862 } 3863 3864 public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { 3865 mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available); 3866 } 3867 3868 /** 3869 * Called by the invocation handler to notify the service that the 3870 * state of magnification has changed. 3871 */ 3872 private void notifyMagnificationChangedInternal(@NonNull Region region, 3873 float scale, float centerX, float centerY) { 3874 final IAccessibilityServiceClient listener; 3875 synchronized (mLock) { 3876 listener = mServiceInterface; 3877 } 3878 if (listener != null) { 3879 try { 3880 listener.onMagnificationChanged(region, scale, centerX, centerY); 3881 } catch (RemoteException re) { 3882 Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re); 3883 } 3884 } 3885 } 3886 3887 /** 3888 * Called by the invocation handler to notify the service that the state of the soft 3889 * keyboard show mode has changed. 3890 */ 3891 private void notifySoftKeyboardShowModeChangedInternal(int showState) { 3892 final IAccessibilityServiceClient listener; 3893 synchronized (mLock) { 3894 listener = mServiceInterface; 3895 } 3896 if (listener != null) { 3897 try { 3898 listener.onSoftKeyboardShowModeChanged(showState); 3899 } catch (RemoteException re) { 3900 Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService, 3901 re); 3902 } 3903 } 3904 } 3905 3906 private void notifyAccessibilityButtonClickedInternal() { 3907 final IAccessibilityServiceClient listener; 3908 synchronized (mLock) { 3909 listener = mServiceInterface; 3910 } 3911 if (listener != null) { 3912 try { 3913 listener.onAccessibilityButtonClicked(); 3914 } catch (RemoteException re) { 3915 Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re); 3916 } 3917 } 3918 } 3919 3920 private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) { 3921 // Only notify the service if it's not been notified or the state has changed 3922 if (mReceivedAccessibilityButtonCallbackSinceBind 3923 && (mLastAccessibilityButtonCallbackState == available)) { 3924 return; 3925 } 3926 mReceivedAccessibilityButtonCallbackSinceBind = true; 3927 mLastAccessibilityButtonCallbackState = available; 3928 final IAccessibilityServiceClient listener; 3929 synchronized (mLock) { 3930 listener = mServiceInterface; 3931 } 3932 if (listener != null) { 3933 try { 3934 listener.onAccessibilityButtonAvailabilityChanged(available); 3935 } catch (RemoteException re) { 3936 Slog.e(LOG_TAG, 3937 "Error sending accessibility button availability change to " + mService, 3938 re); 3939 } 3940 } 3941 } 3942 3943 private void notifyGestureInternal(int gestureId) { 3944 final IAccessibilityServiceClient listener; 3945 synchronized (mLock) { 3946 listener = mServiceInterface; 3947 } 3948 if (listener != null) { 3949 try { 3950 listener.onGesture(gestureId); 3951 } catch (RemoteException re) { 3952 Slog.e(LOG_TAG, "Error during sending gesture " + gestureId 3953 + " to " + mService, re); 3954 } 3955 } 3956 } 3957 3958 private void notifyClearAccessibilityCacheInternal() { 3959 final IAccessibilityServiceClient listener; 3960 synchronized (mLock) { 3961 listener = mServiceInterface; 3962 } 3963 if (listener != null) { 3964 try { 3965 listener.clearAccessibilityCache(); 3966 } catch (RemoteException re) { 3967 Slog.e(LOG_TAG, "Error during requesting accessibility info cache" 3968 + " to be cleared.", re); 3969 } 3970 } 3971 } 3972 3973 private void sendDownAndUpKeyEvents(int keyCode) { 3974 final long token = Binder.clearCallingIdentity(); 3975 3976 // Inject down. 3977 final long downTime = SystemClock.uptimeMillis(); 3978 KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, 3979 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 3980 InputDevice.SOURCE_KEYBOARD, null); 3981 InputManager.getInstance().injectInputEvent(down, 3982 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 3983 down.recycle(); 3984 3985 // Inject up. 3986 final long upTime = SystemClock.uptimeMillis(); 3987 KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0, 3988 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 3989 InputDevice.SOURCE_KEYBOARD, null); 3990 InputManager.getInstance().injectInputEvent(up, 3991 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 3992 up.recycle(); 3993 3994 Binder.restoreCallingIdentity(token); 3995 } 3996 3997 private void expandNotifications() { 3998 final long token = Binder.clearCallingIdentity(); 3999 4000 StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 4001 android.app.Service.STATUS_BAR_SERVICE); 4002 statusBarManager.expandNotificationsPanel(); 4003 4004 Binder.restoreCallingIdentity(token); 4005 } 4006 4007 private void expandQuickSettings() { 4008 final long token = Binder.clearCallingIdentity(); 4009 4010 StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 4011 android.app.Service.STATUS_BAR_SERVICE); 4012 statusBarManager.expandSettingsPanel(); 4013 4014 Binder.restoreCallingIdentity(token); 4015 } 4016 4017 private boolean openRecents() { 4018 final long token = Binder.clearCallingIdentity(); 4019 try { 4020 StatusBarManagerInternal statusBarService = LocalServices.getService( 4021 StatusBarManagerInternal.class); 4022 if (statusBarService == null) { 4023 return false; 4024 } 4025 statusBarService.toggleRecentApps(); 4026 } finally { 4027 Binder.restoreCallingIdentity(token); 4028 } 4029 return true; 4030 } 4031 4032 private void showGlobalActions() { 4033 mWindowManagerService.showGlobalActions(); 4034 } 4035 4036 private void toggleSplitScreen() { 4037 LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen(); 4038 } 4039 4040 private IAccessibilityInteractionConnection getConnectionLocked(int windowId) { 4041 if (DEBUG) { 4042 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId); 4043 } 4044 AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId); 4045 if (wrapper == null) { 4046 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId); 4047 } 4048 if (wrapper != null && wrapper.mConnection != null) { 4049 return wrapper.mConnection; 4050 } 4051 if (DEBUG) { 4052 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId); 4053 } 4054 return null; 4055 } 4056 4057 private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { 4058 if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { 4059 return mSecurityPolicy.getActiveWindowId(); 4060 } 4061 return accessibilityWindowId; 4062 } 4063 4064 private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { 4065 if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { 4066 return mSecurityPolicy.mActiveWindowId; 4067 } 4068 if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) { 4069 if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) { 4070 return mSecurityPolicy.mFocusedWindowId; 4071 } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) { 4072 return mSecurityPolicy.mAccessibilityFocusedWindowId; 4073 } 4074 } 4075 return windowId; 4076 } 4077 4078 private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded( 4079 IAccessibilityInteractionConnectionCallback originalCallback, 4080 int resolvedWindowId, int interactionId, int interrogatingPid, 4081 long interrogatingTid) { 4082 AccessibilityWindowInfo windowInfo = mSecurityPolicy.findWindowById(resolvedWindowId); 4083 if ((windowInfo == null) || !windowInfo.inPictureInPicture() 4084 || (mPictureInPictureActionReplacingConnection == null)) { 4085 return originalCallback; 4086 } 4087 return new ActionReplacingCallback(originalCallback, 4088 mPictureInPictureActionReplacingConnection.mConnection, interactionId, 4089 interrogatingPid, interrogatingTid); 4090 } 4091 4092 private final class InvocationHandler extends Handler { 4093 public static final int MSG_ON_GESTURE = 1; 4094 public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2; 4095 4096 private static final int MSG_ON_MAGNIFICATION_CHANGED = 5; 4097 private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6; 4098 private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7; 4099 private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8; 4100 4101 private boolean mIsMagnificationCallbackEnabled = false; 4102 private boolean mIsSoftKeyboardCallbackEnabled = false; 4103 4104 public InvocationHandler(Looper looper) { 4105 super(looper, null, true); 4106 } 4107 4108 @Override 4109 public void handleMessage(Message message) { 4110 final int type = message.what; 4111 switch (type) { 4112 case MSG_ON_GESTURE: { 4113 final int gestureId = message.arg1; 4114 notifyGestureInternal(gestureId); 4115 } break; 4116 4117 case MSG_CLEAR_ACCESSIBILITY_CACHE: { 4118 notifyClearAccessibilityCacheInternal(); 4119 } break; 4120 4121 case MSG_ON_MAGNIFICATION_CHANGED: { 4122 final SomeArgs args = (SomeArgs) message.obj; 4123 final Region region = (Region) args.arg1; 4124 final float scale = (float) args.arg2; 4125 final float centerX = (float) args.arg3; 4126 final float centerY = (float) args.arg4; 4127 notifyMagnificationChangedInternal(region, scale, centerX, centerY); 4128 } break; 4129 4130 case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: { 4131 final int showState = (int) message.arg1; 4132 notifySoftKeyboardShowModeChangedInternal(showState); 4133 } break; 4134 4135 case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: { 4136 notifyAccessibilityButtonClickedInternal(); 4137 } break; 4138 4139 case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: { 4140 final boolean available = (message.arg1 != 0); 4141 notifyAccessibilityButtonAvailabilityChangedInternal(available); 4142 } break; 4143 4144 default: { 4145 throw new IllegalArgumentException("Unknown message: " + type); 4146 } 4147 } 4148 } 4149 4150 public void notifyMagnificationChangedLocked(@NonNull Region region, float scale, 4151 float centerX, float centerY) { 4152 if (!mIsMagnificationCallbackEnabled) { 4153 // Callback is disabled, don't bother packing args. 4154 return; 4155 } 4156 4157 final SomeArgs args = SomeArgs.obtain(); 4158 args.arg1 = region; 4159 args.arg2 = scale; 4160 args.arg3 = centerX; 4161 args.arg4 = centerY; 4162 4163 final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args); 4164 msg.sendToTarget(); 4165 } 4166 4167 public void setMagnificationCallbackEnabled(boolean enabled) { 4168 mIsMagnificationCallbackEnabled = enabled; 4169 } 4170 4171 public void notifySoftKeyboardShowModeChangedLocked(int showState) { 4172 if (!mIsSoftKeyboardCallbackEnabled) { 4173 return; 4174 } 4175 4176 final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0); 4177 msg.sendToTarget(); 4178 } 4179 4180 public void setSoftKeyboardCallbackEnabled(boolean enabled) { 4181 mIsSoftKeyboardCallbackEnabled = enabled; 4182 } 4183 4184 public void notifyAccessibilityButtonClickedLocked() { 4185 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED); 4186 msg.sendToTarget(); 4187 } 4188 4189 public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { 4190 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, 4191 (available ? 1 : 0), 0); 4192 msg.sendToTarget(); 4193 } 4194 } 4195 } 4196 4197 final class WindowsForAccessibilityCallback implements 4198 WindowManagerInternal.WindowsForAccessibilityCallback { 4199 4200 @Override 4201 public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) { 4202 synchronized (mLock) { 4203 // Populate the windows to report. 4204 List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>(); 4205 final int receivedWindowCount = windows.size(); 4206 for (int i = 0; i < receivedWindowCount; i++) { 4207 WindowInfo receivedWindow = windows.get(i); 4208 AccessibilityWindowInfo reportedWindow = populateReportedWindow( 4209 receivedWindow); 4210 if (reportedWindow != null) { 4211 reportedWindows.add(reportedWindow); 4212 } 4213 } 4214 4215 if (DEBUG) { 4216 Slog.i(LOG_TAG, "Windows changed: " + reportedWindows); 4217 } 4218 4219 // Let the policy update the focused and active windows. 4220 mSecurityPolicy.updateWindowsLocked(reportedWindows); 4221 4222 // Someone may be waiting for the windows - advertise it. 4223 mLock.notifyAll(); 4224 } 4225 } 4226 4227 private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) { 4228 final int windowId = findWindowIdLocked(window.token); 4229 if (windowId < 0) { 4230 return null; 4231 } 4232 4233 AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain(); 4234 4235 reportedWindow.setId(windowId); 4236 reportedWindow.setType(getTypeForWindowManagerWindowType(window.type)); 4237 reportedWindow.setLayer(window.layer); 4238 reportedWindow.setFocused(window.focused); 4239 reportedWindow.setBoundsInScreen(window.boundsInScreen); 4240 reportedWindow.setTitle(window.title); 4241 reportedWindow.setAnchorId(window.accessibilityIdOfAnchor); 4242 reportedWindow.setPictureInPicture(window.inPictureInPicture); 4243 4244 final int parentId = findWindowIdLocked(window.parentToken); 4245 if (parentId >= 0) { 4246 reportedWindow.setParentId(parentId); 4247 } 4248 4249 if (window.childTokens != null) { 4250 final int childCount = window.childTokens.size(); 4251 for (int i = 0; i < childCount; i++) { 4252 IBinder childToken = window.childTokens.get(i); 4253 final int childId = findWindowIdLocked(childToken); 4254 if (childId >= 0) { 4255 reportedWindow.addChild(childId); 4256 } 4257 } 4258 } 4259 4260 return reportedWindow; 4261 } 4262 4263 private int getTypeForWindowManagerWindowType(int windowType) { 4264 switch (windowType) { 4265 case WindowManager.LayoutParams.TYPE_APPLICATION: 4266 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA: 4267 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL: 4268 case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING: 4269 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL: 4270 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL: 4271 case WindowManager.LayoutParams.TYPE_BASE_APPLICATION: 4272 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION: 4273 case WindowManager.LayoutParams.TYPE_PHONE: 4274 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE: 4275 case WindowManager.LayoutParams.TYPE_TOAST: 4276 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: { 4277 return AccessibilityWindowInfo.TYPE_APPLICATION; 4278 } 4279 4280 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 4281 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: { 4282 return AccessibilityWindowInfo.TYPE_INPUT_METHOD; 4283 } 4284 4285 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG: 4286 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 4287 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: 4288 case WindowManager.LayoutParams.TYPE_SEARCH_BAR: 4289 case WindowManager.LayoutParams.TYPE_STATUS_BAR: 4290 case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL: 4291 case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL: 4292 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY: 4293 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT: 4294 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG: 4295 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR: 4296 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: 4297 case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY: 4298 case WindowManager.LayoutParams.TYPE_SCREENSHOT: { 4299 return AccessibilityWindowInfo.TYPE_SYSTEM; 4300 } 4301 4302 case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: { 4303 return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER; 4304 } 4305 4306 case TYPE_ACCESSIBILITY_OVERLAY: { 4307 return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY; 4308 } 4309 4310 default: { 4311 return -1; 4312 } 4313 } 4314 } 4315 } 4316 4317 private final class InteractionBridge { 4318 private final Display mDefaultDisplay; 4319 private final int mConnectionId; 4320 private final AccessibilityInteractionClient mClient; 4321 4322 public InteractionBridge() { 4323 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 4324 info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 4325 info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; 4326 info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 4327 Service service = new Service(UserHandle.USER_NULL, 4328 sFakeAccessibilityServiceComponentName, info); 4329 4330 mConnectionId = service.mId; 4331 4332 mClient = AccessibilityInteractionClient.getInstance(); 4333 mClient.addConnection(mConnectionId, service); 4334 4335 //TODO: (multi-display) We need to support multiple displays. 4336 DisplayManager displayManager = (DisplayManager) 4337 mContext.getSystemService(Context.DISPLAY_SERVICE); 4338 mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); 4339 } 4340 4341 public void clearAccessibilityFocusNotLocked(int windowId) { 4342 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId); 4343 if (focus != null) { 4344 focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 4345 } 4346 } 4347 4348 /** 4349 * Perform an accessibility action on the view that currently has accessibility focus. 4350 * Has no effect if no item has accessibility focus, if the item with accessibility 4351 * focus does not expose the specified action, or if the action fails. 4352 * 4353 * @param actionId The id of the action to perform. 4354 * 4355 * @return {@code true} if the action was performed. {@code false} if it was not. 4356 */ 4357 public boolean performActionOnAccessibilityFocusedItemNotLocked( 4358 AccessibilityNodeInfo.AccessibilityAction action) { 4359 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(); 4360 if ((focus == null) || !focus.getActionList().contains(action)) { 4361 return false; 4362 } 4363 return focus.performAction(action.getId()); 4364 } 4365 4366 public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) { 4367 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(); 4368 if (focus == null) { 4369 return false; 4370 } 4371 4372 synchronized (mLock) { 4373 Rect boundsInScreen = mTempRect; 4374 focus.getBoundsInScreen(boundsInScreen); 4375 4376 // Apply magnification if needed. 4377 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId()); 4378 if (spec != null && !spec.isNop()) { 4379 boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY); 4380 boundsInScreen.scale(1 / spec.scale); 4381 } 4382 4383 // Clip to the window bounds. 4384 Rect windowBounds = mTempRect1; 4385 getWindowBounds(focus.getWindowId(), windowBounds); 4386 if (!boundsInScreen.intersect(windowBounds)) { 4387 return false; 4388 } 4389 4390 // Clip to the screen bounds. 4391 Point screenSize = mTempPoint; 4392 mDefaultDisplay.getRealSize(screenSize); 4393 if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) { 4394 return false; 4395 } 4396 4397 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY()); 4398 } 4399 4400 return true; 4401 } 4402 4403 private AccessibilityNodeInfo getAccessibilityFocusNotLocked() { 4404 final int focusedWindowId; 4405 synchronized (mLock) { 4406 focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId; 4407 if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) { 4408 return null; 4409 } 4410 } 4411 return getAccessibilityFocusNotLocked(focusedWindowId); 4412 } 4413 4414 private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) { 4415 return mClient.findFocus(mConnectionId, 4416 windowId, AccessibilityNodeInfo.ROOT_NODE_ID, 4417 AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); 4418 } 4419 } 4420 4421 final class SecurityPolicy { 4422 public static final int INVALID_WINDOW_ID = -1; 4423 4424 private static final int RETRIEVAL_ALLOWING_EVENT_TYPES = 4425 AccessibilityEvent.TYPE_VIEW_CLICKED 4426 | AccessibilityEvent.TYPE_VIEW_FOCUSED 4427 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 4428 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 4429 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 4430 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 4431 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 4432 | AccessibilityEvent.TYPE_VIEW_SELECTED 4433 | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED 4434 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 4435 | AccessibilityEvent.TYPE_VIEW_SCROLLED 4436 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 4437 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED 4438 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 4439 4440 // In Z order 4441 public List<AccessibilityWindowInfo> mWindows; 4442 public SparseArray<AccessibilityWindowInfo> mWindowsById = new SparseArray<>(); 4443 4444 public int mActiveWindowId = INVALID_WINDOW_ID; 4445 public int mFocusedWindowId = INVALID_WINDOW_ID; 4446 public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; 4447 public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 4448 4449 private boolean mTouchInteractionInProgress; 4450 4451 private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) { 4452 final int eventType = event.getEventType(); 4453 switch (eventType) { 4454 // All events that are for changes in a global window 4455 // state should *always* be dispatched. 4456 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: 4457 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: 4458 case AccessibilityEvent.TYPE_ANNOUNCEMENT: 4459 // All events generated by the user touching the 4460 // screen should *always* be dispatched. 4461 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: 4462 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: 4463 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START: 4464 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END: 4465 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START: 4466 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END: 4467 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: 4468 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: 4469 // Also always dispatch the event that assist is reading context. 4470 case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT: 4471 // Also windows changing should always be anounced. 4472 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: { 4473 return true; 4474 } 4475 // All events for changes in window content should be 4476 // dispatched *only* if this window is one of the windows 4477 // the accessibility layer reports which are windows 4478 // that a sighted user can touch. 4479 default: { 4480 return isRetrievalAllowingWindow(event.getWindowId()); 4481 } 4482 } 4483 } 4484 4485 public void clearWindowsLocked() { 4486 List<AccessibilityWindowInfo> windows = Collections.emptyList(); 4487 final int activeWindowId = mActiveWindowId; 4488 updateWindowsLocked(windows); 4489 mActiveWindowId = activeWindowId; 4490 mWindows = null; 4491 } 4492 4493 public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) { 4494 if (mWindows == null) { 4495 mWindows = new ArrayList<>(); 4496 } 4497 4498 final int oldWindowCount = mWindows.size(); 4499 for (int i = oldWindowCount - 1; i >= 0; i--) { 4500 mWindows.remove(i).recycle(); 4501 } 4502 mWindowsById.clear(); 4503 4504 mFocusedWindowId = INVALID_WINDOW_ID; 4505 if (!mTouchInteractionInProgress) { 4506 mActiveWindowId = INVALID_WINDOW_ID; 4507 } 4508 4509 // If the active window goes away while the user is touch exploring we 4510 // reset the active window id and wait for the next hover event from 4511 // under the user's finger to determine which one is the new one. It 4512 // is possible that the finger is not moving and the input system 4513 // filters out such events. 4514 boolean activeWindowGone = true; 4515 4516 final int windowCount = windows.size(); 4517 if (windowCount > 0) { 4518 for (int i = 0; i < windowCount; i++) { 4519 AccessibilityWindowInfo window = windows.get(i); 4520 final int windowId = window.getId(); 4521 if (window.isFocused()) { 4522 mFocusedWindowId = windowId; 4523 if (!mTouchInteractionInProgress) { 4524 mActiveWindowId = windowId; 4525 window.setActive(true); 4526 } else if (windowId == mActiveWindowId) { 4527 activeWindowGone = false; 4528 } 4529 } 4530 mWindows.add(window); 4531 mWindowsById.put(windowId, window); 4532 } 4533 4534 if (mTouchInteractionInProgress && activeWindowGone) { 4535 mActiveWindowId = mFocusedWindowId; 4536 } 4537 4538 // Focused window may change the active one, so set the 4539 // active window once we decided which it is. 4540 for (int i = 0; i < windowCount; i++) { 4541 AccessibilityWindowInfo window = mWindows.get(i); 4542 if (window.getId() == mActiveWindowId) { 4543 window.setActive(true); 4544 } 4545 if (window.getId() == mAccessibilityFocusedWindowId) { 4546 window.setAccessibilityFocused(true); 4547 } 4548 } 4549 } 4550 4551 notifyWindowsChanged(); 4552 } 4553 4554 public boolean computePartialInteractiveRegionForWindowLocked(int windowId, 4555 Region outRegion) { 4556 if (mWindows == null) { 4557 return false; 4558 } 4559 4560 // Windows are ordered in z order so start from the bottom and find 4561 // the window of interest. After that all windows that cover it should 4562 // be subtracted from the resulting region. Note that for accessibility 4563 // we are returning only interactive windows. 4564 Region windowInteractiveRegion = null; 4565 boolean windowInteractiveRegionChanged = false; 4566 4567 final int windowCount = mWindows.size(); 4568 for (int i = windowCount - 1; i >= 0; i--) { 4569 AccessibilityWindowInfo currentWindow = mWindows.get(i); 4570 if (windowInteractiveRegion == null) { 4571 if (currentWindow.getId() == windowId) { 4572 Rect currentWindowBounds = mTempRect; 4573 currentWindow.getBoundsInScreen(currentWindowBounds); 4574 outRegion.set(currentWindowBounds); 4575 windowInteractiveRegion = outRegion; 4576 continue; 4577 } 4578 } else if (currentWindow.getType() 4579 != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) { 4580 Rect currentWindowBounds = mTempRect; 4581 currentWindow.getBoundsInScreen(currentWindowBounds); 4582 if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) { 4583 windowInteractiveRegionChanged = true; 4584 } 4585 } 4586 } 4587 4588 return windowInteractiveRegionChanged; 4589 } 4590 4591 public void updateEventSourceLocked(AccessibilityEvent event) { 4592 if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) { 4593 event.setSource((View) null); 4594 } 4595 } 4596 4597 public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, 4598 int eventType, int eventAction) { 4599 // The active window is either the window that has input focus or 4600 // the window that the user is currently touching. If the user is 4601 // touching a window that does not have input focus as soon as the 4602 // the user stops touching that window the focused window becomes 4603 // the active one. Here we detect the touched window and make it 4604 // active. In updateWindowsLocked() we update the focused window 4605 // and if the user is not touching the screen, we make the focused 4606 // window the active one. 4607 switch (eventType) { 4608 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: { 4609 // If no service has the capability to introspect screen, 4610 // we do not register callback in the window manager for 4611 // window changes, so we have to ask the window manager 4612 // what the focused window is to update the active one. 4613 // The active window also determined events from which 4614 // windows are delivered. 4615 synchronized (mLock) { 4616 if (mWindowsForAccessibilityCallback == null) { 4617 mFocusedWindowId = getFocusedWindowId(); 4618 if (windowId == mFocusedWindowId) { 4619 mActiveWindowId = windowId; 4620 } 4621 } 4622 } 4623 } break; 4624 4625 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: { 4626 // Do not allow delayed hover events to confuse us 4627 // which the active window is. 4628 synchronized (mLock) { 4629 if (mTouchInteractionInProgress && mActiveWindowId != windowId) { 4630 setActiveWindowLocked(windowId); 4631 } 4632 } 4633 } break; 4634 4635 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: { 4636 synchronized (mLock) { 4637 if (mAccessibilityFocusedWindowId != windowId) { 4638 mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, 4639 mAccessibilityFocusedWindowId, 0).sendToTarget(); 4640 mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId); 4641 mAccessibilityFocusNodeId = nodeId; 4642 } 4643 } 4644 } break; 4645 4646 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: { 4647 synchronized (mLock) { 4648 if (mAccessibilityFocusNodeId == nodeId) { 4649 mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 4650 } 4651 // Clear the window with focus if it no longer has focus and we aren't 4652 // just moving focus from one view to the other in the same window 4653 if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) 4654 && (mAccessibilityFocusedWindowId == windowId) 4655 && (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) 4656 ) { 4657 mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; 4658 } 4659 } 4660 } break; 4661 } 4662 } 4663 4664 public void onTouchInteractionStart() { 4665 synchronized (mLock) { 4666 mTouchInteractionInProgress = true; 4667 } 4668 } 4669 4670 public void onTouchInteractionEnd() { 4671 synchronized (mLock) { 4672 mTouchInteractionInProgress = false; 4673 // We want to set the active window to be current immediately 4674 // after the user has stopped touching the screen since if the 4675 // user types with the IME he should get a feedback for the 4676 // letter typed in the text view which is in the input focused 4677 // window. Note that we always deliver hover accessibility events 4678 // (they are a result of user touching the screen) so change of 4679 // the active window before all hover accessibility events from 4680 // the touched window are delivered is fine. 4681 final int oldActiveWindow = mSecurityPolicy.mActiveWindowId; 4682 setActiveWindowLocked(mFocusedWindowId); 4683 4684 // If there is no service that can operate with active windows 4685 // we keep accessibility focus behavior to constrain it only in 4686 // the active window. Look at updateAccessibilityFocusBehaviorLocked 4687 // for details. 4688 if (oldActiveWindow != mSecurityPolicy.mActiveWindowId 4689 && mAccessibilityFocusedWindowId == oldActiveWindow 4690 && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) { 4691 mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, 4692 oldActiveWindow, 0).sendToTarget(); 4693 } 4694 } 4695 } 4696 4697 public int getActiveWindowId() { 4698 if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) { 4699 mActiveWindowId = getFocusedWindowId(); 4700 } 4701 return mActiveWindowId; 4702 } 4703 4704 private void setActiveWindowLocked(int windowId) { 4705 if (mActiveWindowId != windowId) { 4706 mActiveWindowId = windowId; 4707 if (mWindows != null) { 4708 final int windowCount = mWindows.size(); 4709 for (int i = 0; i < windowCount; i++) { 4710 AccessibilityWindowInfo window = mWindows.get(i); 4711 window.setActive(window.getId() == windowId); 4712 } 4713 } 4714 notifyWindowsChanged(); 4715 } 4716 } 4717 4718 private void setAccessibilityFocusedWindowLocked(int windowId) { 4719 if (mAccessibilityFocusedWindowId != windowId) { 4720 mAccessibilityFocusedWindowId = windowId; 4721 if (mWindows != null) { 4722 final int windowCount = mWindows.size(); 4723 for (int i = 0; i < windowCount; i++) { 4724 AccessibilityWindowInfo window = mWindows.get(i); 4725 window.setAccessibilityFocused(window.getId() == windowId); 4726 } 4727 } 4728 4729 notifyWindowsChanged(); 4730 } 4731 } 4732 4733 public void notifyWindowsChanged() { 4734 if (mWindowsForAccessibilityCallback == null) { 4735 return; 4736 } 4737 final long identity = Binder.clearCallingIdentity(); 4738 try { 4739 // Let the client know the windows changed. 4740 AccessibilityEvent event = AccessibilityEvent.obtain( 4741 AccessibilityEvent.TYPE_WINDOWS_CHANGED); 4742 event.setEventTime(SystemClock.uptimeMillis()); 4743 sendAccessibilityEvent(event, mCurrentUserId); 4744 } finally { 4745 Binder.restoreCallingIdentity(identity); 4746 } 4747 } 4748 4749 public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) { 4750 return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId); 4751 } 4752 4753 public boolean canRetrieveWindowsLocked(Service service) { 4754 return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows; 4755 } 4756 4757 public boolean canRetrieveWindowContentLocked(Service service) { 4758 return (service.mAccessibilityServiceInfo.getCapabilities() 4759 & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; 4760 } 4761 4762 public boolean canControlMagnification(Service service) { 4763 return (service.mAccessibilityServiceInfo.getCapabilities() 4764 & AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0; 4765 } 4766 4767 public boolean canPerformGestures(Service service) { 4768 return (service.mAccessibilityServiceInfo.getCapabilities() 4769 & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0; 4770 } 4771 4772 public boolean canCaptureFingerprintGestures(Service service) { 4773 return (service.mAccessibilityServiceInfo.getCapabilities() 4774 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES) != 0; 4775 } 4776 4777 private int resolveProfileParentLocked(int userId) { 4778 if (userId != mCurrentUserId) { 4779 final long identity = Binder.clearCallingIdentity(); 4780 try { 4781 UserInfo parent = mUserManager.getProfileParent(userId); 4782 if (parent != null) { 4783 return parent.getUserHandle().getIdentifier(); 4784 } 4785 } finally { 4786 Binder.restoreCallingIdentity(identity); 4787 } 4788 } 4789 return userId; 4790 } 4791 4792 public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) { 4793 final int callingUid = Binder.getCallingUid(); 4794 if (callingUid == 0 4795 || callingUid == Process.SYSTEM_UID 4796 || callingUid == Process.SHELL_UID) { 4797 if (userId == UserHandle.USER_CURRENT 4798 || userId == UserHandle.USER_CURRENT_OR_SELF) { 4799 return mCurrentUserId; 4800 } 4801 return resolveProfileParentLocked(userId); 4802 } 4803 final int callingUserId = UserHandle.getUserId(callingUid); 4804 if (callingUserId == userId) { 4805 return resolveProfileParentLocked(userId); 4806 } 4807 final int callingUserParentId = resolveProfileParentLocked(callingUserId); 4808 if (callingUserParentId == mCurrentUserId && 4809 (userId == UserHandle.USER_CURRENT 4810 || userId == UserHandle.USER_CURRENT_OR_SELF)) { 4811 return mCurrentUserId; 4812 } 4813 if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS) 4814 && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) { 4815 throw new SecurityException("Call from user " + callingUserId + " as user " 4816 + userId + " without permission INTERACT_ACROSS_USERS or " 4817 + "INTERACT_ACROSS_USERS_FULL not allowed."); 4818 } 4819 if (userId == UserHandle.USER_CURRENT 4820 || userId == UserHandle.USER_CURRENT_OR_SELF) { 4821 return mCurrentUserId; 4822 } 4823 throw new IllegalArgumentException("Calling user can be changed to only " 4824 + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF."); 4825 } 4826 4827 public boolean isCallerInteractingAcrossUsers(int userId) { 4828 final int callingUid = Binder.getCallingUid(); 4829 return (Binder.getCallingPid() == android.os.Process.myPid() 4830 || callingUid == Process.SHELL_UID 4831 || userId == UserHandle.USER_CURRENT 4832 || userId == UserHandle.USER_CURRENT_OR_SELF); 4833 } 4834 4835 private boolean isRetrievalAllowingWindow(int windowId) { 4836 // The system gets to interact with any window it wants. 4837 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 4838 return true; 4839 } 4840 if (windowId == mActiveWindowId) { 4841 return true; 4842 } 4843 return findWindowById(windowId) != null; 4844 } 4845 4846 private AccessibilityWindowInfo findWindowById(int windowId) { 4847 return mWindowsById.get(windowId); 4848 } 4849 4850 private AccessibilityWindowInfo getPictureInPictureWindow() { 4851 if (mWindows != null) { 4852 final int windowCount = mWindows.size(); 4853 for (int i = 0; i < windowCount; i++) { 4854 AccessibilityWindowInfo window = mWindows.get(i); 4855 if (window.inPictureInPicture()) { 4856 return window; 4857 } 4858 } 4859 } 4860 return null; 4861 } 4862 4863 private void enforceCallingPermission(String permission, String function) { 4864 if (OWN_PROCESS_ID == Binder.getCallingPid()) { 4865 return; 4866 } 4867 if (!hasPermission(permission)) { 4868 throw new SecurityException("You do not have " + permission 4869 + " required to call " + function + " from pid=" 4870 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 4871 } 4872 } 4873 4874 private boolean hasPermission(String permission) { 4875 return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED; 4876 } 4877 4878 private int getFocusedWindowId() { 4879 IBinder token = mWindowManagerService.getFocusedWindowToken(); 4880 synchronized (mLock) { 4881 return findWindowIdLocked(token); 4882 } 4883 } 4884 } 4885 4886 private class UserState { 4887 public final int mUserId; 4888 4889 // Non-transient state. 4890 4891 public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients = 4892 new RemoteCallbackList<>(); 4893 4894 public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections = 4895 new SparseArray<>(); 4896 4897 public final SparseArray<IBinder> mWindowTokens = new SparseArray<>(); 4898 4899 // Transient state. 4900 4901 public final CopyOnWriteArrayList<Service> mBoundServices = 4902 new CopyOnWriteArrayList<>(); 4903 4904 public int mLastSentRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK; 4905 4906 public final Map<ComponentName, Service> mComponentNameToServiceMap = 4907 new HashMap<>(); 4908 4909 public final List<AccessibilityServiceInfo> mInstalledServices = 4910 new ArrayList<>(); 4911 4912 public final Set<ComponentName> mBindingServices = new HashSet<>(); 4913 4914 public final Set<ComponentName> mEnabledServices = new HashSet<>(); 4915 4916 public final Set<ComponentName> mTouchExplorationGrantedServices = 4917 new HashSet<>(); 4918 4919 public ComponentName mServiceChangingSoftKeyboardMode; 4920 4921 public ComponentName mServiceToEnableWithShortcut; 4922 4923 public int mLastSentClientState = -1; 4924 4925 public int mSoftKeyboardShowMode = 0; 4926 4927 public boolean mIsNavBarMagnificationAssignedToAccessibilityButton; 4928 public ComponentName mServiceAssignedToAccessibilityButton; 4929 4930 public boolean mIsTouchExplorationEnabled; 4931 public boolean mIsTextHighContrastEnabled; 4932 public boolean mIsDisplayMagnificationEnabled; 4933 public boolean mIsNavBarMagnificationEnabled; 4934 public boolean mIsAutoclickEnabled; 4935 public boolean mIsPerformGesturesEnabled; 4936 public boolean mIsFilterKeyEventsEnabled; 4937 public boolean mAccessibilityFocusOnlyInActiveWindow; 4938 4939 private Service mUiAutomationService; 4940 private int mUiAutomationFlags; 4941 private IAccessibilityServiceClient mUiAutomationServiceClient; 4942 4943 private IBinder mUiAutomationServiceOwner; 4944 private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient = 4945 new DeathRecipient() { 4946 @Override 4947 public void binderDied() { 4948 mUiAutomationServiceOwner.unlinkToDeath( 4949 mUiAutomationSerivceOnwerDeathRecipient, 0); 4950 mUiAutomationServiceOwner = null; 4951 if (mUiAutomationService != null) { 4952 mUiAutomationService.binderDied(); 4953 } 4954 } 4955 }; 4956 4957 public UserState(int userId) { 4958 mUserId = userId; 4959 } 4960 4961 public int getClientState() { 4962 int clientState = 0; 4963 if (isHandlingAccessibilityEvents()) { 4964 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED; 4965 } 4966 // Touch exploration relies on enabled accessibility. 4967 if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) { 4968 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; 4969 } 4970 if (mIsTextHighContrastEnabled) { 4971 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; 4972 } 4973 return clientState; 4974 } 4975 4976 public boolean isHandlingAccessibilityEvents() { 4977 return !mBoundServices.isEmpty() || !mBindingServices.isEmpty(); 4978 } 4979 4980 public void onSwitchToAnotherUser() { 4981 // Clear UI test automation state. 4982 if (mUiAutomationService != null) { 4983 mUiAutomationService.binderDied(); 4984 } 4985 4986 // Unbind all services. 4987 unbindAllServicesLocked(this); 4988 4989 // Clear service management state. 4990 mBoundServices.clear(); 4991 mBindingServices.clear(); 4992 4993 // Clear event management state. 4994 mLastSentClientState = -1; 4995 4996 // Clear state persisted in settings. 4997 mEnabledServices.clear(); 4998 mTouchExplorationGrantedServices.clear(); 4999 mIsTouchExplorationEnabled = false; 5000 mIsDisplayMagnificationEnabled = false; 5001 mIsNavBarMagnificationEnabled = false; 5002 mServiceAssignedToAccessibilityButton = null; 5003 mIsNavBarMagnificationAssignedToAccessibilityButton = false; 5004 mIsAutoclickEnabled = false; 5005 mSoftKeyboardShowMode = 0; 5006 } 5007 5008 public void destroyUiAutomationService() { 5009 mUiAutomationService = null; 5010 mUiAutomationFlags = 0; 5011 mUiAutomationServiceClient = null; 5012 if (mUiAutomationServiceOwner != null) { 5013 mUiAutomationServiceOwner.unlinkToDeath( 5014 mUiAutomationSerivceOnwerDeathRecipient, 0); 5015 mUiAutomationServiceOwner = null; 5016 } 5017 } 5018 5019 boolean isUiAutomationSuppressingOtherServices() { 5020 return ((mUiAutomationService != null) && (mUiAutomationFlags 5021 & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0); 5022 } 5023 } 5024 5025 private final class AccessibilityContentObserver extends ContentObserver { 5026 5027 private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor( 5028 Settings.Secure.TOUCH_EXPLORATION_ENABLED); 5029 5030 private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor( 5031 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); 5032 5033 private final Uri mNavBarMagnificationEnabledUri = Settings.Secure.getUriFor( 5034 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); 5035 5036 private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor( 5037 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED); 5038 5039 private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor( 5040 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 5041 5042 private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure 5043 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); 5044 5045 private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor( 5046 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 5047 5048 private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor( 5049 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED); 5050 5051 private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor( 5052 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER); 5053 5054 private final Uri mHighTextContrastUri = Settings.Secure.getUriFor( 5055 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED); 5056 5057 private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor( 5058 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE); 5059 5060 private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor( 5061 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); 5062 5063 private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor( 5064 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); 5065 5066 public AccessibilityContentObserver(Handler handler) { 5067 super(handler); 5068 } 5069 5070 public void register(ContentResolver contentResolver) { 5071 contentResolver.registerContentObserver(mTouchExplorationEnabledUri, 5072 false, this, UserHandle.USER_ALL); 5073 contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri, 5074 false, this, UserHandle.USER_ALL); 5075 contentResolver.registerContentObserver(mNavBarMagnificationEnabledUri, 5076 false, this, UserHandle.USER_ALL); 5077 contentResolver.registerContentObserver(mAutoclickEnabledUri, 5078 false, this, UserHandle.USER_ALL); 5079 contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri, 5080 false, this, UserHandle.USER_ALL); 5081 contentResolver.registerContentObserver( 5082 mTouchExplorationGrantedAccessibilityServicesUri, 5083 false, this, UserHandle.USER_ALL); 5084 contentResolver.registerContentObserver( 5085 mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL); 5086 contentResolver.registerContentObserver( 5087 mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL); 5088 contentResolver.registerContentObserver( 5089 mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL); 5090 contentResolver.registerContentObserver( 5091 mHighTextContrastUri, false, this, UserHandle.USER_ALL); 5092 contentResolver.registerContentObserver( 5093 mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL); 5094 contentResolver.registerContentObserver( 5095 mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL); 5096 contentResolver.registerContentObserver( 5097 mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL); 5098 } 5099 5100 @Override 5101 public void onChange(boolean selfChange, Uri uri) { 5102 synchronized (mLock) { 5103 // Profiles share the accessibility state of the parent. Therefore, 5104 // we are checking for changes only the parent settings. 5105 UserState userState = getCurrentUserStateLocked(); 5106 5107 // If the automation service is suppressing, we will update when it dies. 5108 if (userState.isUiAutomationSuppressingOtherServices()) { 5109 return; 5110 } 5111 5112 if (mTouchExplorationEnabledUri.equals(uri)) { 5113 if (readTouchExplorationEnabledSettingLocked(userState)) { 5114 onUserStateChangedLocked(userState); 5115 } 5116 } else if (mDisplayMagnificationEnabledUri.equals(uri) 5117 || mNavBarMagnificationEnabledUri.equals(uri)) { 5118 if (readMagnificationEnabledSettingsLocked(userState)) { 5119 onUserStateChangedLocked(userState); 5120 } 5121 } else if (mAutoclickEnabledUri.equals(uri)) { 5122 if (readAutoclickEnabledSettingLocked(userState)) { 5123 onUserStateChangedLocked(userState); 5124 } 5125 } else if (mEnabledAccessibilityServicesUri.equals(uri)) { 5126 if (readEnabledAccessibilityServicesLocked(userState)) { 5127 onUserStateChangedLocked(userState); 5128 } 5129 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) { 5130 if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) { 5131 onUserStateChangedLocked(userState); 5132 } 5133 } else if (mDisplayDaltonizerEnabledUri.equals(uri) 5134 || mDisplayDaltonizerUri.equals(uri)) { 5135 updateDisplayDaltonizerLocked(userState); 5136 } else if (mDisplayInversionEnabledUri.equals(uri)) { 5137 updateDisplayInversionLocked(userState); 5138 } else if (mHighTextContrastUri.equals(uri)) { 5139 if (readHighTextContrastEnabledSettingLocked(userState)) { 5140 onUserStateChangedLocked(userState); 5141 } 5142 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) { 5143 if (readSoftKeyboardShowModeChangedLocked(userState)) { 5144 notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode); 5145 onUserStateChangedLocked(userState); 5146 } 5147 } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) { 5148 if (readAccessibilityShortcutSettingLocked(userState)) { 5149 onUserStateChangedLocked(userState); 5150 } 5151 } else if (mAccessibilityButtonComponentIdUri.equals(uri)) { 5152 if (readAccessibilityButtonSettingsLocked(userState)) { 5153 onUserStateChangedLocked(userState); 5154 } 5155 } 5156 } 5157 } 5158 } 5159 } 5160