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