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