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