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