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