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.AccessibilityTrace.FLAGS_ACCESSIBILITY_MANAGER; 20 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_MANAGER_CLIENT; 21 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CLIENT; 22 import static android.accessibilityservice.AccessibilityTrace.FLAGS_FINGERPRINT; 23 import static android.accessibilityservice.AccessibilityTrace.FLAGS_INPUT_FILTER; 24 import static android.accessibilityservice.AccessibilityTrace.FLAGS_PACKAGE_BROADCAST_RECEIVER; 25 import static android.accessibilityservice.AccessibilityTrace.FLAGS_USER_BROADCAST_RECEIVER; 26 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION; 27 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL; 28 import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED; 29 import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID; 30 import static android.content.Context.DEVICE_ID_DEFAULT; 31 import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED; 32 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON; 33 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; 34 import static android.view.accessibility.AccessibilityManager.FlashNotificationReason; 35 import static android.view.accessibility.AccessibilityManager.ShortcutType; 36 37 import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME; 38 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME; 39 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; 40 import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME; 41 import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils.logAccessibilityShortcutActivated; 42 import static com.android.internal.util.FunctionalUtils.ignoreRemoteException; 43 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; 44 import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain; 45 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 46 47 import android.Manifest; 48 import android.accessibilityservice.AccessibilityGestureEvent; 49 import android.accessibilityservice.AccessibilityService; 50 import android.accessibilityservice.AccessibilityServiceInfo; 51 import android.accessibilityservice.AccessibilityShortcutInfo; 52 import android.accessibilityservice.IAccessibilityServiceClient; 53 import android.accessibilityservice.MagnificationConfig; 54 import android.accessibilityservice.TouchInteractionController; 55 import android.annotation.NonNull; 56 import android.annotation.Nullable; 57 import android.annotation.RequiresPermission; 58 import android.annotation.UserIdInt; 59 import android.app.ActivityOptions; 60 import android.app.AlertDialog; 61 import android.app.AppOpsManager; 62 import android.app.PendingIntent; 63 import android.app.RemoteAction; 64 import android.app.admin.DevicePolicyManager; 65 import android.appwidget.AppWidgetManagerInternal; 66 import android.content.ActivityNotFoundException; 67 import android.content.BroadcastReceiver; 68 import android.content.ComponentName; 69 import android.content.ContentResolver; 70 import android.content.Context; 71 import android.content.DialogInterface; 72 import android.content.DialogInterface.OnClickListener; 73 import android.content.Intent; 74 import android.content.IntentFilter; 75 import android.content.pm.PackageManager; 76 import android.content.pm.PackageManagerInternal; 77 import android.content.pm.ResolveInfo; 78 import android.content.pm.ServiceInfo; 79 import android.database.ContentObserver; 80 import android.graphics.Matrix; 81 import android.graphics.Point; 82 import android.graphics.Rect; 83 import android.graphics.Region; 84 import android.hardware.display.DisplayManager; 85 import android.hardware.fingerprint.IFingerprintService; 86 import android.media.AudioManagerInternal; 87 import android.net.Uri; 88 import android.os.Binder; 89 import android.os.Build; 90 import android.os.Bundle; 91 import android.os.Handler; 92 import android.os.IBinder; 93 import android.os.Looper; 94 import android.os.Message; 95 import android.os.PowerManager; 96 import android.os.Process; 97 import android.os.RemoteCallbackList; 98 import android.os.RemoteException; 99 import android.os.ResultReceiver; 100 import android.os.ServiceManager; 101 import android.os.ShellCallback; 102 import android.os.SystemClock; 103 import android.os.UserHandle; 104 import android.os.UserManager; 105 import android.provider.Settings; 106 import android.provider.SettingsStringUtil.SettingStringHelper; 107 import android.safetycenter.SafetyCenterManager; 108 import android.text.TextUtils; 109 import android.text.TextUtils.SimpleStringSplitter; 110 import android.util.ArraySet; 111 import android.util.IntArray; 112 import android.util.Pair; 113 import android.util.Slog; 114 import android.util.SparseArray; 115 import android.util.SparseBooleanArray; 116 import android.view.Display; 117 import android.view.IWindow; 118 import android.view.InputDevice; 119 import android.view.InputEvent; 120 import android.view.KeyEvent; 121 import android.view.MagnificationSpec; 122 import android.view.MotionEvent; 123 import android.view.SurfaceControl; 124 import android.view.WindowInfo; 125 import android.view.WindowManager; 126 import android.view.accessibility.AccessibilityEvent; 127 import android.view.accessibility.AccessibilityInteractionClient; 128 import android.view.accessibility.AccessibilityManager; 129 import android.view.accessibility.AccessibilityNodeInfo; 130 import android.view.accessibility.AccessibilityWindowAttributes; 131 import android.view.accessibility.AccessibilityWindowInfo; 132 import android.view.accessibility.IAccessibilityInteractionConnection; 133 import android.view.accessibility.IAccessibilityManager; 134 import android.view.accessibility.IAccessibilityManagerClient; 135 import android.view.accessibility.IWindowMagnificationConnection; 136 import android.view.inputmethod.EditorInfo; 137 138 import com.android.internal.R; 139 import com.android.internal.accessibility.AccessibilityShortcutController; 140 import com.android.internal.accessibility.AccessibilityShortcutController.FrameworkFeatureInfo; 141 import com.android.internal.accessibility.AccessibilityShortcutController.LaunchableFrameworkFeatureInfo; 142 import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity; 143 import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity; 144 import com.android.internal.accessibility.util.AccessibilityUtils; 145 import com.android.internal.annotations.GuardedBy; 146 import com.android.internal.annotations.VisibleForTesting; 147 import com.android.internal.content.PackageMonitor; 148 import com.android.internal.inputmethod.IAccessibilityInputMethodSession; 149 import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; 150 import com.android.internal.os.BackgroundThread; 151 import com.android.internal.util.ArrayUtils; 152 import com.android.internal.util.DumpUtils; 153 import com.android.internal.util.IntPair; 154 import com.android.server.AccessibilityManagerInternal; 155 import com.android.server.LocalServices; 156 import com.android.server.SystemService; 157 import com.android.server.accessibility.magnification.MagnificationController; 158 import com.android.server.accessibility.magnification.MagnificationProcessor; 159 import com.android.server.accessibility.magnification.MagnificationScaleProvider; 160 import com.android.server.accessibility.magnification.WindowMagnificationManager; 161 import com.android.server.inputmethod.InputMethodManagerInternal; 162 import com.android.server.pm.UserManagerInternal; 163 import com.android.server.policy.WindowManagerPolicy; 164 import com.android.server.utils.Slogf; 165 import com.android.server.wm.ActivityTaskManagerInternal; 166 import com.android.server.wm.WindowManagerInternal; 167 import com.android.settingslib.RestrictedLockUtils; 168 169 import org.xmlpull.v1.XmlPullParserException; 170 171 import java.io.FileDescriptor; 172 import java.io.IOException; 173 import java.io.PrintWriter; 174 import java.util.ArrayList; 175 import java.util.Arrays; 176 import java.util.Collections; 177 import java.util.HashSet; 178 import java.util.Iterator; 179 import java.util.List; 180 import java.util.Map; 181 import java.util.Set; 182 import java.util.concurrent.Executors; 183 import java.util.function.Consumer; 184 import java.util.function.Function; 185 import java.util.function.Predicate; 186 187 /** 188 * This class is instantiated by the system as a system level service and can be 189 * accessed only by the system. The task of this service is to be a centralized 190 * event dispatch for {@link AccessibilityEvent}s generated across all processes 191 * on the device. Events are dispatched to {@link AccessibilityService}s. 192 */ 193 public class AccessibilityManagerService extends IAccessibilityManager.Stub 194 implements AbstractAccessibilityServiceConnection.SystemSupport, 195 AccessibilityUserState.ServiceInfoChangeListener, 196 AccessibilityWindowManager.AccessibilityEventSender, 197 AccessibilitySecurityPolicy.AccessibilityUserManager, 198 SystemActionPerformer.SystemActionsChangedListener, 199 SystemActionPerformer.DisplayUpdateCallBack, ProxyManager.SystemSupport { 200 201 private static final boolean DEBUG = false; 202 203 private static final String LOG_TAG = "AccessibilityManagerService"; 204 205 // TODO: This is arbitrary. When there is time implement this by watching 206 // when that accessibility services are bound. 207 private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000; 208 209 // TODO: Restructure service initialization so services aren't connected before all of 210 // their capabilities are ready. 211 private static final int WAIT_INPUT_FILTER_INSTALL_TIMEOUT_MS = 1000; 212 213 214 // This postpones state changes events when a window doesn't exist with the expectation that 215 // a race condition will resolve. It is determined by observing elapsed time of the 216 // corresponding window added. 217 //TODO(b/230810909) : Fix it with a better idea. 218 private static final int POSTPONE_WINDOW_STATE_CHANGED_EVENT_TIMEOUT_MILLIS = 500; 219 220 private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE = 221 "registerUiTestAutomationService"; 222 223 private static final String GET_WINDOW_TOKEN = "getWindowToken"; 224 225 private static final String SET_PIP_ACTION_REPLACEMENT = 226 "setPictureInPictureActionReplacingConnection"; 227 228 private static final char COMPONENT_NAME_SEPARATOR = ':'; 229 230 private static final int OWN_PROCESS_ID = android.os.Process.myPid(); 231 232 public static final int INVALID_SERVICE_ID = -1; 233 234 // Each service has an ID. Also provide one for magnification gesture handling 235 public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0; 236 237 private static int sIdCounter = MAGNIFICATION_GESTURE_HANDLER_ID + 1; 238 239 private final Context mContext; 240 241 private final Object mLock = new Object(); 242 243 private final SimpleStringSplitter mStringColonSplitter = 244 new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); 245 246 private final Rect mTempRect = new Rect(); 247 private final Rect mTempRect1 = new Rect(); 248 249 private final PackageManager mPackageManager; 250 251 private final PowerManager mPowerManager; 252 253 private final WindowManagerInternal mWindowManagerService; 254 255 private final AccessibilitySecurityPolicy mSecurityPolicy; 256 257 private final AccessibilityWindowManager mA11yWindowManager; 258 259 private final AccessibilityDisplayListener mA11yDisplayListener; 260 261 private final ActivityTaskManagerInternal mActivityTaskManagerService; 262 263 private final MagnificationController mMagnificationController; 264 private final MagnificationProcessor mMagnificationProcessor; 265 266 private final Handler mMainHandler; 267 268 // Lazily initialized - access through getSystemActionPerformer() 269 private SystemActionPerformer mSystemActionPerformer; 270 271 private InteractionBridge mInteractionBridge; 272 273 private AlertDialog mEnableTouchExplorationDialog; 274 275 private AccessibilityInputFilter mInputFilter; 276 277 private boolean mHasInputFilter; 278 279 private boolean mInputFilterInstalled; 280 281 private KeyEventDispatcher mKeyEventDispatcher; 282 283 private SparseArray<MotionEventInjector> mMotionEventInjectors; 284 285 private FingerprintGestureDispatcher mFingerprintGestureDispatcher; 286 287 private final Set<ComponentName> mTempComponentNameSet = new HashSet<>(); 288 289 private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList = 290 new ArrayList<>(); 291 292 private final IntArray mTempIntArray = new IntArray(0); 293 294 private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients = 295 new RemoteCallbackList<>(); 296 297 @VisibleForTesting 298 final SparseArray<AccessibilityUserState> mUserStates = new SparseArray<>(); 299 300 private final UiAutomationManager mUiAutomationManager = new UiAutomationManager(mLock); 301 private final ProxyManager mProxyManager; 302 private final AccessibilityTraceManager mTraceManager; 303 private final CaptioningManagerImpl mCaptioningManagerImpl; 304 305 private final List<SendWindowStateChangedEventRunnable> mSendWindowStateChangedEventRunnables = 306 new ArrayList<>(); 307 308 @GuardedBy("mLock") 309 private @UserIdInt int mCurrentUserId = UserHandle.USER_SYSTEM; 310 311 // TODO(b/255426725): temporary workaround to support visible background users for UiAutomation: 312 // when the UiAutomation is set in a visible background user, mCurrentUserId points to that user 313 // and mRealCurrentUserId points to the "real" current user; otherwise, mRealCurrentUserId 314 // is set as UserHandle.USER_CURRENT. 315 @GuardedBy("mLock") 316 private @UserIdInt int mRealCurrentUserId = UserHandle.USER_CURRENT; 317 318 // TODO(b/255426725): temporary workaround to support visible background users for UiAutomation 319 // purposes - in the long term, the whole service should be refactored so it handles "visible" 320 // users, not current user. Notice that because this is temporary, it's not trying to optimize 321 // performance / utilization (for example, it's not using an IntArray) 322 @GuardedBy("mLock") 323 @Nullable // only set when device supports visible background users 324 private final SparseBooleanArray mVisibleBgUserIds; 325 326 //TODO: Remove this hack 327 private boolean mInitialized; 328 329 private Point mTempPoint = new Point(); 330 private boolean mIsAccessibilityButtonShown; 331 private boolean mInputBound; 332 IRemoteAccessibilityInputConnection mRemoteInputConnection; 333 EditorInfo mEditorInfo; 334 boolean mRestarting; 335 boolean mInputSessionRequested; 336 private SparseArray<SurfaceControl> mA11yOverlayLayers = new SparseArray<>(); 337 338 private final FlashNotificationsController mFlashNotificationsController; 339 private final UserManagerInternal mUmi; 340 getCurrentUserStateLocked()341 private AccessibilityUserState getCurrentUserStateLocked() { 342 return getUserStateLocked(mCurrentUserId); 343 } 344 345 /** 346 * Changes the magnification mode on the given display. 347 * 348 * @param displayId the logical display 349 * @param magnificationMode the target magnification mode 350 */ changeMagnificationMode(int displayId, int magnificationMode)351 public void changeMagnificationMode(int displayId, int magnificationMode) { 352 synchronized (mLock) { 353 if (displayId == Display.DEFAULT_DISPLAY) { 354 persistMagnificationModeSettingsLocked(magnificationMode); 355 } else { 356 final AccessibilityUserState userState = getCurrentUserStateLocked(); 357 final int currentMode = userState.getMagnificationModeLocked(displayId); 358 if (magnificationMode != currentMode) { 359 userState.setMagnificationModeLocked(displayId, magnificationMode); 360 updateMagnificationModeChangeSettingsLocked(userState, displayId); 361 } 362 } 363 } 364 } 365 366 private static final class LocalServiceImpl extends AccessibilityManagerInternal { 367 @NonNull 368 private final AccessibilityManagerService mService; 369 LocalServiceImpl(@onNull AccessibilityManagerService service)370 LocalServiceImpl(@NonNull AccessibilityManagerService service) { 371 mService = service; 372 } 373 374 @Override setImeSessionEnabled(SparseArray<IAccessibilityInputMethodSession> sessions, boolean enabled)375 public void setImeSessionEnabled(SparseArray<IAccessibilityInputMethodSession> sessions, 376 boolean enabled) { 377 mService.scheduleSetImeSessionEnabled(sessions, enabled); 378 } 379 380 @Override unbindInput()381 public void unbindInput() { 382 mService.scheduleUnbindInput(); 383 } 384 385 @Override bindInput()386 public void bindInput() { 387 mService.scheduleBindInput(); 388 } 389 390 @Override createImeSession(ArraySet<Integer> ignoreSet)391 public void createImeSession(ArraySet<Integer> ignoreSet) { 392 mService.scheduleCreateImeSession(ignoreSet); 393 } 394 395 @Override startInput( IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection, EditorInfo editorInfo, boolean restarting)396 public void startInput( 397 IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection, 398 EditorInfo editorInfo, boolean restarting) { 399 mService.scheduleStartInput(remoteAccessibilityInputConnection, editorInfo, restarting); 400 } 401 402 @Override performSystemAction(int actionId)403 public void performSystemAction(int actionId) { 404 mService.getSystemActionPerformer().performSystemAction(actionId); 405 } 406 407 @Override isTouchExplorationEnabled(@serIdInt int userId)408 public boolean isTouchExplorationEnabled(@UserIdInt int userId) { 409 synchronized (mService.mLock) { 410 return mService.getUserStateLocked(userId).isTouchExplorationEnabledLocked(); 411 } 412 } 413 } 414 415 public static final class Lifecycle extends SystemService { 416 private final AccessibilityManagerService mService; 417 Lifecycle(Context context)418 public Lifecycle(Context context) { 419 super(context); 420 mService = new AccessibilityManagerService(context); 421 } 422 423 @Override onStart()424 public void onStart() { 425 LocalServices.addService(AccessibilityManagerInternal.class, 426 new LocalServiceImpl(mService)); 427 publishBinderService(Context.ACCESSIBILITY_SERVICE, mService); 428 } 429 430 @Override onBootPhase(int phase)431 public void onBootPhase(int phase) { 432 mService.onBootPhase(phase); 433 } 434 } 435 436 @VisibleForTesting AccessibilityManagerService( Context context, Handler handler, PackageManager packageManager, AccessibilitySecurityPolicy securityPolicy, SystemActionPerformer systemActionPerformer, AccessibilityWindowManager a11yWindowManager, AccessibilityDisplayListener a11yDisplayListener, MagnificationController magnificationController, @Nullable AccessibilityInputFilter inputFilter, ProxyManager proxyManager)437 AccessibilityManagerService( 438 Context context, 439 Handler handler, 440 PackageManager packageManager, 441 AccessibilitySecurityPolicy securityPolicy, 442 SystemActionPerformer systemActionPerformer, 443 AccessibilityWindowManager a11yWindowManager, 444 AccessibilityDisplayListener a11yDisplayListener, 445 MagnificationController magnificationController, 446 @Nullable AccessibilityInputFilter inputFilter, 447 ProxyManager proxyManager) { 448 mContext = context; 449 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 450 mWindowManagerService = LocalServices.getService(WindowManagerInternal.class); 451 mTraceManager = AccessibilityTraceManager.getInstance( 452 mWindowManagerService.getAccessibilityController(), this, mLock); 453 mMainHandler = handler; 454 mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class); 455 mPackageManager = packageManager; 456 mSecurityPolicy = securityPolicy; 457 mSystemActionPerformer = systemActionPerformer; 458 mA11yWindowManager = a11yWindowManager; 459 mA11yDisplayListener = a11yDisplayListener; 460 mMagnificationController = magnificationController; 461 mMagnificationProcessor = new MagnificationProcessor(mMagnificationController); 462 mCaptioningManagerImpl = new CaptioningManagerImpl(mContext); 463 mProxyManager = proxyManager; 464 if (inputFilter != null) { 465 mInputFilter = inputFilter; 466 mHasInputFilter = true; 467 } 468 mFlashNotificationsController = new FlashNotificationsController(mContext); 469 mUmi = LocalServices.getService(UserManagerInternal.class); 470 // TODO(b/255426725): not used on tests 471 mVisibleBgUserIds = null; 472 473 init(); 474 } 475 476 /** 477 * Creates a new instance. 478 * 479 * @param context A {@link Context} instance. 480 */ AccessibilityManagerService(Context context)481 public AccessibilityManagerService(Context context) { 482 mContext = context; 483 mPowerManager = context.getSystemService(PowerManager.class); 484 mWindowManagerService = LocalServices.getService(WindowManagerInternal.class); 485 mTraceManager = AccessibilityTraceManager.getInstance( 486 mWindowManagerService.getAccessibilityController(), this, mLock); 487 mMainHandler = new MainHandler(mContext.getMainLooper()); 488 mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class); 489 mPackageManager = mContext.getPackageManager(); 490 final PolicyWarningUIController policyWarningUIController = new PolicyWarningUIController( 491 mMainHandler, context, 492 new PolicyWarningUIController.NotificationController(context)); 493 mSecurityPolicy = new AccessibilitySecurityPolicy(policyWarningUIController, mContext, 494 this, LocalServices.getService(PackageManagerInternal.class)); 495 mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler, 496 mWindowManagerService, this, mSecurityPolicy, this, mTraceManager); 497 mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler); 498 mMagnificationController = new MagnificationController( 499 this, 500 mLock, 501 mContext, 502 new MagnificationScaleProvider(mContext), 503 Executors.newSingleThreadExecutor() 504 ); 505 mMagnificationProcessor = new MagnificationProcessor(mMagnificationController); 506 mCaptioningManagerImpl = new CaptioningManagerImpl(mContext); 507 mProxyManager = new ProxyManager(mLock, mA11yWindowManager, mContext, mMainHandler, 508 mUiAutomationManager, this); 509 mFlashNotificationsController = new FlashNotificationsController(mContext); 510 mUmi = LocalServices.getService(UserManagerInternal.class); 511 512 if (UserManager.isVisibleBackgroundUsersEnabled()) { 513 mVisibleBgUserIds = new SparseBooleanArray(); 514 mUmi.addUserVisibilityListener((u, v) -> onUserVisibilityChanged(u, v)); 515 } else { 516 mVisibleBgUserIds = null; 517 } 518 519 init(); 520 } 521 init()522 private void init() { 523 mSecurityPolicy.setAccessibilityWindowManager(mA11yWindowManager); 524 registerBroadcastReceivers(); 525 new AccessibilityContentObserver(mMainHandler).register( 526 mContext.getContentResolver()); 527 disableAccessibilityMenuToMigrateIfNeeded(); 528 } 529 530 @Override getCurrentUserIdLocked()531 public int getCurrentUserIdLocked() { 532 return mCurrentUserId; 533 } 534 535 @GuardedBy("mLock") 536 @Override getVisibleUserIdsLocked()537 public SparseBooleanArray getVisibleUserIdsLocked() { 538 return mVisibleBgUserIds; 539 } 540 541 @Override isAccessibilityButtonShown()542 public boolean isAccessibilityButtonShown() { 543 return mIsAccessibilityButtonShown; 544 } 545 546 @Override getWindowTransformationMatrixAndMagnificationSpec( int windowId)547 public Pair<float[], MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec( 548 int windowId) { 549 WindowInfo windowInfo; 550 synchronized (mLock) { 551 windowInfo = mA11yWindowManager.findWindowInfoByIdLocked(windowId); 552 } 553 if (windowInfo != null) { 554 final MagnificationSpec spec = new MagnificationSpec(); 555 spec.setTo(windowInfo.mMagnificationSpec); 556 return new Pair<>(windowInfo.mTransformMatrix, spec); 557 } else { 558 // If the framework doesn't track windows, we fall back to get the pair of 559 // transformation matrix and MagnificationSpe from the WindowManagerService's 560 // WindowState. 561 IBinder token; 562 synchronized (mLock) { 563 token = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(mCurrentUserId, 564 windowId); 565 } 566 Pair<Matrix, MagnificationSpec> pair = 567 mWindowManagerService.getWindowTransformationMatrixAndMagnificationSpec(token); 568 final float[] outTransformationMatrix = new float[9]; 569 final Matrix tmpMatrix = pair.first; 570 final MagnificationSpec spec = pair.second; 571 if (!spec.isNop()) { 572 tmpMatrix.postScale(spec.scale, spec.scale); 573 tmpMatrix.postTranslate(spec.offsetX, spec.offsetY); 574 } 575 tmpMatrix.getValues(outTransformationMatrix); 576 577 return new Pair<>(outTransformationMatrix, pair.second); 578 } 579 } 580 581 @Override getWindowTransformationSpec( int windowId)582 public IAccessibilityManager.WindowTransformationSpec getWindowTransformationSpec( 583 int windowId) { 584 IAccessibilityManager.WindowTransformationSpec windowTransformationSpec = 585 new IAccessibilityManager.WindowTransformationSpec(); 586 Pair<float[], MagnificationSpec> result = 587 getWindowTransformationMatrixAndMagnificationSpec(windowId); 588 windowTransformationSpec.transformationMatrix = result.first; 589 windowTransformationSpec.magnificationSpec = result.second; 590 return windowTransformationSpec; 591 } 592 593 @Override onServiceInfoChangedLocked(AccessibilityUserState userState)594 public void onServiceInfoChangedLocked(AccessibilityUserState userState) { 595 mSecurityPolicy.onBoundServicesChangedLocked(userState.mUserId, 596 userState.mBoundServices); 597 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 598 } 599 600 @Nullable getFingerprintGestureDispatcher()601 public FingerprintGestureDispatcher getFingerprintGestureDispatcher() { 602 return mFingerprintGestureDispatcher; 603 } 604 605 /** 606 * Called by the {@link AccessibilityInputFilter} when the filter install state changes. 607 */ onInputFilterInstalled(boolean installed)608 public void onInputFilterInstalled(boolean installed) { 609 synchronized (mLock) { 610 mInputFilterInstalled = installed; 611 mLock.notifyAll(); 612 } 613 } 614 onBootPhase(int phase)615 private void onBootPhase(int phase) { 616 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 617 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) { 618 mSecurityPolicy.setAppWidgetManager( 619 LocalServices.getService(AppWidgetManagerInternal.class)); 620 } 621 } 622 623 // SafetyCenterService is ready after this phase. 624 if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { 625 setNonA11yToolNotificationToMatchSafetyCenter(); 626 } 627 } 628 setNonA11yToolNotificationToMatchSafetyCenter()629 private void setNonA11yToolNotificationToMatchSafetyCenter() { 630 final boolean sendNotification = !mContext.getSystemService( 631 SafetyCenterManager.class).isSafetyCenterEnabled(); 632 synchronized (mLock) { 633 mSecurityPolicy.setSendingNonA11yToolNotificationLocked(sendNotification); 634 } 635 } 636 getCurrentUserState()637 AccessibilityUserState getCurrentUserState() { 638 synchronized (mLock) { 639 return getCurrentUserStateLocked(); 640 } 641 } 642 getUserState(int userId)643 private AccessibilityUserState getUserState(int userId) { 644 synchronized (mLock) { 645 return getUserStateLocked(userId); 646 } 647 } 648 649 @NonNull getUserStateLocked(int userId)650 private AccessibilityUserState getUserStateLocked(int userId) { 651 AccessibilityUserState state = mUserStates.get(userId); 652 if (state == null) { 653 state = new AccessibilityUserState(userId, mContext, this); 654 mUserStates.put(userId, state); 655 } 656 return state; 657 } 658 getBindInstantServiceAllowed(int userId)659 boolean getBindInstantServiceAllowed(int userId) { 660 synchronized (mLock) { 661 final AccessibilityUserState userState = getUserStateLocked(userId); 662 return userState.getBindInstantServiceAllowedLocked(); 663 } 664 } 665 setBindInstantServiceAllowed(int userId, boolean allowed)666 void setBindInstantServiceAllowed(int userId, boolean allowed) { 667 mContext.enforceCallingOrSelfPermission( 668 Manifest.permission.MANAGE_BIND_INSTANT_SERVICE, 669 "setBindInstantServiceAllowed"); 670 synchronized (mLock) { 671 final AccessibilityUserState userState = getUserStateLocked(userId); 672 if (allowed != userState.getBindInstantServiceAllowedLocked()) { 673 userState.setBindInstantServiceAllowedLocked(allowed); 674 onUserStateChangedLocked(userState); 675 } 676 } 677 } 678 onSomePackagesChangedLocked()679 private void onSomePackagesChangedLocked() { 680 final AccessibilityUserState userState = getCurrentUserStateLocked(); 681 // Reload the installed services since some services may have different attributes 682 // or resolve info (does not support equals), etc. Remove them then to force reload. 683 userState.mInstalledServices.clear(); 684 if (readConfigurationForUserStateLocked(userState)) { 685 onUserStateChangedLocked(userState); 686 } 687 } 688 registerBroadcastReceivers()689 private void registerBroadcastReceivers() { 690 PackageMonitor monitor = new PackageMonitor() { 691 @Override 692 public void onSomePackagesChanged() { 693 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_PACKAGE_BROADCAST_RECEIVER)) { 694 mTraceManager.logTrace(LOG_TAG + ".PM.onSomePackagesChanged", 695 FLAGS_PACKAGE_BROADCAST_RECEIVER); 696 } 697 698 synchronized (mLock) { 699 // Only the profile parent can install accessibility services. 700 // Therefore we ignore packages from linked profiles. 701 if (getChangingUserId() != mCurrentUserId) { 702 return; 703 } 704 onSomePackagesChangedLocked(); 705 } 706 } 707 708 @Override 709 public void onPackageUpdateFinished(String packageName, int uid) { 710 // The package should already be removed from mBoundServices, and added into 711 // mBindingServices in binderDied() during updating. Remove services from this 712 // package from mBindingServices, and then update the user state to re-bind new 713 // versions of them. 714 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_PACKAGE_BROADCAST_RECEIVER)) { 715 mTraceManager.logTrace(LOG_TAG + ".PM.onPackageUpdateFinished", 716 FLAGS_PACKAGE_BROADCAST_RECEIVER, 717 "packageName=" + packageName + ";uid=" + uid); 718 } 719 synchronized (mLock) { 720 final int userId = getChangingUserId(); 721 if (userId != mCurrentUserId) { 722 return; 723 } 724 final AccessibilityUserState userState = getUserStateLocked(userId); 725 final boolean reboundAService = userState.getBindingServicesLocked().removeIf( 726 component -> component != null 727 && component.getPackageName().equals(packageName)) 728 || userState.mCrashedServices.removeIf(component -> component != null 729 && component.getPackageName().equals(packageName)); 730 // Reloads the installed services info to make sure the rebound service could 731 // get a new one. 732 userState.mInstalledServices.clear(); 733 final boolean configurationChanged = 734 readConfigurationForUserStateLocked(userState); 735 if (reboundAService || configurationChanged) { 736 onUserStateChangedLocked(userState); 737 } 738 // Passing 0 for restoreFromSdkInt to have this migration check execute each 739 // time. It can make sure a11y button settings are correctly if there's an a11y 740 // service updated and modifies the a11y button configuration. 741 migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, packageName, 742 /* restoreFromSdkInt = */0); 743 } 744 } 745 746 @Override 747 public void onPackageRemoved(String packageName, int uid) { 748 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_PACKAGE_BROADCAST_RECEIVER)) { 749 mTraceManager.logTrace(LOG_TAG + ".PM.onPackageRemoved", 750 FLAGS_PACKAGE_BROADCAST_RECEIVER, 751 "packageName=" + packageName + ";uid=" + uid); 752 } 753 754 synchronized (mLock) { 755 final int userId = getChangingUserId(); 756 // Only the profile parent can install accessibility services. 757 // Therefore we ignore packages from linked profiles. 758 if (userId != mCurrentUserId) { 759 return; 760 } 761 final AccessibilityUserState userState = getUserStateLocked(userId); 762 final Predicate<ComponentName> filter = 763 component -> component != null && component.getPackageName().equals( 764 packageName); 765 userState.mBindingServices.removeIf(filter); 766 userState.mCrashedServices.removeIf(filter); 767 final Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 768 boolean anyServiceRemoved = false; 769 while (it.hasNext()) { 770 final ComponentName comp = it.next(); 771 final String compPkg = comp.getPackageName(); 772 if (compPkg.equals(packageName)) { 773 it.remove(); 774 userState.mTouchExplorationGrantedServices.remove(comp); 775 anyServiceRemoved = true; 776 } 777 } 778 if (anyServiceRemoved) { 779 // Update the enabled services setting. 780 persistComponentNamesToSettingLocked( 781 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 782 userState.mEnabledServices, userId); 783 // Update the touch exploration granted services setting. 784 persistComponentNamesToSettingLocked( 785 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 786 userState.mTouchExplorationGrantedServices, userId); 787 onUserStateChangedLocked(userState); 788 } 789 } 790 } 791 792 @Override 793 public boolean onHandleForceStop(Intent intent, String[] packages, 794 int uid, boolean doit) { 795 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_PACKAGE_BROADCAST_RECEIVER)) { 796 mTraceManager.logTrace(LOG_TAG + ".PM.onHandleForceStop", 797 FLAGS_PACKAGE_BROADCAST_RECEIVER, 798 "intent=" + intent + ";packages=" + Arrays.toString(packages) 799 + ";uid=" + uid + ";doit=" + doit); 800 } 801 synchronized (mLock) { 802 final int userId = getChangingUserId(); 803 // Only the profile parent can install accessibility services. 804 // Therefore we ignore packages from linked profiles. 805 if (userId != mCurrentUserId) { 806 return false; 807 } 808 final AccessibilityUserState userState = getUserStateLocked(userId); 809 final Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 810 while (it.hasNext()) { 811 final ComponentName comp = it.next(); 812 final String compPkg = comp.getPackageName(); 813 for (String pkg : packages) { 814 if (compPkg.equals(pkg)) { 815 if (!doit) { 816 return true; 817 } 818 it.remove(); 819 userState.getBindingServicesLocked().remove(comp); 820 userState.getCrashedServicesLocked().remove(comp); 821 persistComponentNamesToSettingLocked( 822 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 823 userState.mEnabledServices, userId); 824 onUserStateChangedLocked(userState); 825 } 826 } 827 } 828 return false; 829 } 830 } 831 }; 832 833 // package changes 834 monitor.register(mContext, null, UserHandle.ALL, true); 835 836 // Register an additional observer for new packages using PackageManagerInternal, which 837 // generally notifies observers much sooner than the BroadcastReceiver-based PackageMonitor. 838 final PackageManagerInternal pm = LocalServices.getService( 839 PackageManagerInternal.class); 840 if (pm != null) { 841 pm.getPackageList(new PackageManagerInternal.PackageListObserver() { 842 @Override 843 public void onPackageAdded(String packageName, int uid) { 844 final int userId = UserHandle.getUserId(uid); 845 synchronized (mLock) { 846 if (userId == mCurrentUserId) { 847 onSomePackagesChangedLocked(); 848 } 849 } 850 } 851 }); 852 } 853 854 // user change and unlock 855 IntentFilter intentFilter = new IntentFilter(); 856 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 857 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); 858 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 859 intentFilter.addAction(Intent.ACTION_SETTING_RESTORED); 860 861 mContext.registerReceiverAsUser(new BroadcastReceiver() { 862 @Override 863 public void onReceive(Context context, Intent intent) { 864 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_USER_BROADCAST_RECEIVER)) { 865 mTraceManager.logTrace(LOG_TAG + ".BR.onReceive", FLAGS_USER_BROADCAST_RECEIVER, 866 "context=" + context + ";intent=" + intent); 867 } 868 869 String action = intent.getAction(); 870 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 871 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 872 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { 873 unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 874 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 875 removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 876 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { 877 final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); 878 if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) { 879 synchronized (mLock) { 880 restoreEnabledAccessibilityServicesLocked( 881 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE), 882 intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE), 883 intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, 884 0)); 885 } 886 } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) { 887 synchronized (mLock) { 888 restoreLegacyDisplayMagnificationNavBarIfNeededLocked( 889 intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE), 890 intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, 891 0)); 892 } 893 } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) { 894 synchronized (mLock) { 895 restoreAccessibilityButtonTargetsLocked( 896 intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE), 897 intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)); 898 } 899 } 900 } 901 } 902 }, UserHandle.ALL, intentFilter, null, null); 903 904 final IntentFilter filter = new IntentFilter(); 905 filter.addAction(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED); 906 final BroadcastReceiver receiver = new BroadcastReceiver() { 907 @Override 908 public void onReceive(Context context, Intent intent) { 909 setNonA11yToolNotificationToMatchSafetyCenter(); 910 } 911 }; 912 mContext.registerReceiverAsUser(receiver, UserHandle.ALL, filter, null, mMainHandler, 913 Context.RECEIVER_EXPORTED); 914 915 final BroadcastReceiver virtualDeviceReceiver = new BroadcastReceiver() { 916 @Override 917 public void onReceive(Context context, Intent intent) { 918 final int deviceId = intent.getIntExtra( 919 EXTRA_VIRTUAL_DEVICE_ID, DEVICE_ID_DEFAULT); 920 mProxyManager.clearConnections(deviceId); 921 } 922 }; 923 924 final IntentFilter virtualDeviceFilter = new IntentFilter(ACTION_VIRTUAL_DEVICE_REMOVED); 925 mContext.registerReceiver(virtualDeviceReceiver, virtualDeviceFilter, 926 Context.RECEIVER_NOT_EXPORTED); 927 } 928 929 /** 930 * Disables the component returned by 931 * {@link AccessibilityUtils#getAccessibilityMenuComponentToMigrate} so that it does not appear 932 * in Settings or other places that query for installed accessibility services. 933 * 934 * <p> 935 * SettingsProvider is responsible for migrating users off of Menu-outside-system, 936 * which it performs in its initialization before AccessibilityManagerService is started. 937 * </p> 938 */ disableAccessibilityMenuToMigrateIfNeeded()939 private void disableAccessibilityMenuToMigrateIfNeeded() { 940 int userId; 941 synchronized (mLock) { 942 userId = mCurrentUserId; 943 } 944 final ComponentName menuToMigrate = 945 AccessibilityUtils.getAccessibilityMenuComponentToMigrate(mPackageManager, userId); 946 if (menuToMigrate != null) { 947 mPackageManager.setComponentEnabledSetting( 948 menuToMigrate, 949 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 950 PackageManager.DONT_KILL_APP); 951 } 952 } 953 954 // Called only during settings restore; currently supports only the owner user 955 // TODO: b/22388012 restoreLegacyDisplayMagnificationNavBarIfNeededLocked(String newSetting, int restoreFromSdkInt)956 private void restoreLegacyDisplayMagnificationNavBarIfNeededLocked(String newSetting, 957 int restoreFromSdkInt) { 958 if (restoreFromSdkInt >= Build.VERSION_CODES.R) { 959 return; 960 } 961 962 boolean displayMagnificationNavBarEnabled; 963 try { 964 displayMagnificationNavBarEnabled = Integer.parseInt(newSetting) == 1; 965 } catch (NumberFormatException e) { 966 Slog.w(LOG_TAG, "number format is incorrect" + e); 967 return; 968 } 969 970 final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); 971 final Set<String> targetsFromSetting = new ArraySet<>(); 972 readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, 973 userState.mUserId, str -> str, targetsFromSetting); 974 final boolean targetsContainMagnification = targetsFromSetting.contains( 975 MAGNIFICATION_CONTROLLER_NAME); 976 if (targetsContainMagnification == displayMagnificationNavBarEnabled) { 977 return; 978 } 979 980 if (displayMagnificationNavBarEnabled) { 981 targetsFromSetting.add(MAGNIFICATION_CONTROLLER_NAME); 982 } else { 983 targetsFromSetting.remove(MAGNIFICATION_CONTROLLER_NAME); 984 } 985 persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, 986 userState.mUserId, targetsFromSetting, str -> str); 987 readAccessibilityButtonTargetsLocked(userState); 988 onUserStateChangedLocked(userState); 989 } 990 991 @Override addClient(IAccessibilityManagerClient callback, int userId)992 public long addClient(IAccessibilityManagerClient callback, int userId) { 993 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 994 mTraceManager.logTrace(LOG_TAG + ".addClient", FLAGS_ACCESSIBILITY_MANAGER, 995 "callback=" + callback + ";userId=" + userId); 996 } 997 998 synchronized (mLock) { 999 // We treat calls from a profile as if made by its parent as profiles 1000 // share the accessibility state of the parent. The call below 1001 // performs the current profile parent resolution. 1002 final int resolvedUserId = mSecurityPolicy 1003 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 1004 1005 AccessibilityUserState userState = getUserStateLocked(resolvedUserId); 1006 // Support a process moving from the default device to a single virtual 1007 // device. 1008 final int deviceId = mProxyManager.getFirstDeviceIdForUidLocked( 1009 Binder.getCallingUid()); 1010 Client client = new Client(callback, Binder.getCallingUid(), userState, deviceId); 1011 // If the client is from a process that runs across users such as 1012 // the system UI or the system we add it to the global state that 1013 // is shared across users. 1014 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 1015 if (mProxyManager.isProxyedDeviceId(deviceId)) { 1016 if (DEBUG) { 1017 Slog.v(LOG_TAG, "Added global client for proxy-ed pid: " 1018 + Binder.getCallingPid() + " for device id " + deviceId 1019 + " with package names " + Arrays.toString(client.mPackageNames)); 1020 } 1021 return IntPair.of(mProxyManager.getStateLocked(deviceId), 1022 client.mLastSentRelevantEventTypes); 1023 } 1024 mGlobalClients.register(callback, client); 1025 if (DEBUG) { 1026 Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid()); 1027 } 1028 } else { 1029 // If the display belongs to a proxy connections 1030 if (mProxyManager.isProxyedDeviceId(deviceId)) { 1031 if (DEBUG) { 1032 Slog.v(LOG_TAG, "Added user client for proxy-ed pid: " 1033 + Binder.getCallingPid() + " for device id " + deviceId 1034 + " with package names " + Arrays.toString(client.mPackageNames)); 1035 } 1036 return IntPair.of(mProxyManager.getStateLocked(deviceId), 1037 client.mLastSentRelevantEventTypes); 1038 } 1039 userState.mUserClients.register(callback, client); 1040 // If this client is not for the current user we do not 1041 // return a state since it is not for the foreground user. 1042 // We will send the state to the client on a user switch. 1043 if (DEBUG) { 1044 Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid() 1045 + " and userId:" + mCurrentUserId); 1046 } 1047 } 1048 return IntPair.of( 1049 (resolvedUserId == mCurrentUserId) ? getClientStateLocked(userState) : 0, 1050 client.mLastSentRelevantEventTypes); 1051 } 1052 } 1053 1054 @Override removeClient(IAccessibilityManagerClient callback, int userId)1055 public boolean removeClient(IAccessibilityManagerClient callback, int userId) { 1056 // TODO(b/190216606): Add tracing for removeClient when implementation is the same in master 1057 1058 synchronized (mLock) { 1059 final int resolvedUserId = mSecurityPolicy 1060 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 1061 1062 AccessibilityUserState userState = getUserStateLocked(resolvedUserId); 1063 if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 1064 boolean unregistered = mGlobalClients.unregister(callback); 1065 if (DEBUG) { 1066 Slog.i(LOG_TAG, 1067 "Removed global client for pid:" + Binder.getCallingPid() + "state: " 1068 + unregistered); 1069 } 1070 return unregistered; 1071 } else { 1072 boolean unregistered = userState.mUserClients.unregister(callback); 1073 if (DEBUG) { 1074 Slog.i(LOG_TAG, "Removed user client for pid:" + Binder.getCallingPid() 1075 + " and userId:" + resolvedUserId + "state: " + unregistered); 1076 } 1077 return unregistered; 1078 } 1079 } 1080 } 1081 1082 @Override sendAccessibilityEvent(AccessibilityEvent event, int userId)1083 public void sendAccessibilityEvent(AccessibilityEvent event, int userId) { 1084 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1085 mTraceManager.logTrace(LOG_TAG + ".sendAccessibilityEvent", FLAGS_ACCESSIBILITY_MANAGER, 1086 "event=" + event + ";userId=" + userId); 1087 } 1088 boolean dispatchEvent = false; 1089 int resolvedUserId; 1090 1091 synchronized (mLock) { 1092 if (event.getWindowId() == 1093 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) { 1094 // The replacer window isn't shown to services. Move its events into the pip. 1095 AccessibilityWindowInfo pip = mA11yWindowManager.getPictureInPictureWindowLocked(); 1096 if (pip != null) { 1097 int pipId = pip.getId(); 1098 event.setWindowId(pipId); 1099 } 1100 } 1101 1102 // We treat calls from a profile as if made by its parent as profiles 1103 // share the accessibility state of the parent. The call below 1104 // performs the current profile parent resolution. 1105 resolvedUserId = mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(userId); 1106 1107 // Make sure the reported package is one the caller has access to. 1108 event.setPackageName(mSecurityPolicy.resolveValidReportedPackageLocked( 1109 event.getPackageName(), UserHandle.getCallingAppId(), resolvedUserId, 1110 getCallingPid())); 1111 1112 // This method does nothing for a background user. 1113 if (resolvedUserId == mCurrentUserId) { 1114 if (mSecurityPolicy.canDispatchAccessibilityEventLocked(mCurrentUserId, event)) { 1115 mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked( 1116 mCurrentUserId, event.getWindowId(), event.getSourceNodeId(), 1117 event.getEventType(), event.getAction()); 1118 mSecurityPolicy.updateEventSourceLocked(event); 1119 dispatchEvent = true; 1120 } 1121 if (mHasInputFilter && mInputFilter != null) { 1122 mMainHandler.sendMessage(obtainMessage( 1123 AccessibilityManagerService::sendAccessibilityEventToInputFilter, 1124 this, AccessibilityEvent.obtain(event))); 1125 } 1126 } 1127 } 1128 1129 if (dispatchEvent) { 1130 // Make sure clients receiving this event will be able to get the 1131 // current state of the windows as the window manager may be delaying 1132 // the computation for performance reasons. 1133 boolean shouldComputeWindows = false; 1134 int displayId = event.getDisplayId(); 1135 synchronized (mLock) { 1136 final int windowId = event.getWindowId(); 1137 if (windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID 1138 && displayId == Display.INVALID_DISPLAY) { 1139 displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked( 1140 resolvedUserId, windowId); 1141 event.setDisplayId(displayId); 1142 } 1143 1144 if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 1145 && displayId != Display.INVALID_DISPLAY 1146 && mA11yWindowManager.isTrackingWindowsLocked(displayId)) { 1147 shouldComputeWindows = true; 1148 } 1149 } 1150 if (shouldComputeWindows) { 1151 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MANAGER_INTERNAL)) { 1152 mTraceManager.logTrace("WindowManagerInternal.computeWindowsForAccessibility", 1153 FLAGS_WINDOW_MANAGER_INTERNAL, "display=" + displayId); 1154 } 1155 final WindowManagerInternal wm = LocalServices.getService( 1156 WindowManagerInternal.class); 1157 wm.computeWindowsForAccessibility(displayId); 1158 // The App side sends a event to notify that the window visible or focused, 1159 // but the window information in framework is not updated yet, so we postpone it. 1160 if (postponeWindowStateEvent(event)) { 1161 return; 1162 } 1163 } 1164 1165 synchronized (mLock) { 1166 dispatchAccessibilityEventLocked(event); 1167 } 1168 } 1169 1170 if (OWN_PROCESS_ID != Binder.getCallingPid()) { 1171 event.recycle(); 1172 } 1173 } 1174 dispatchAccessibilityEventLocked(AccessibilityEvent event)1175 private void dispatchAccessibilityEventLocked(AccessibilityEvent event) { 1176 if (mProxyManager.isProxyedDisplay(event.getDisplayId())) { 1177 mProxyManager.sendAccessibilityEventLocked(event); 1178 } else { 1179 notifyAccessibilityServicesDelayedLocked(event, false); 1180 notifyAccessibilityServicesDelayedLocked(event, true); 1181 } 1182 mUiAutomationManager.sendAccessibilityEventLocked(event); 1183 } 1184 sendAccessibilityEventToInputFilter(AccessibilityEvent event)1185 private void sendAccessibilityEventToInputFilter(AccessibilityEvent event) { 1186 synchronized (mLock) { 1187 if (mHasInputFilter && mInputFilter != null) { 1188 mInputFilter.notifyAccessibilityEvent(event); 1189 } 1190 } 1191 event.recycle(); 1192 } 1193 1194 /** 1195 * This is the implementation of AccessibilityManager system API. 1196 * System UI calls into this method through AccessibilityManager system API to register a 1197 * system action. 1198 */ 1199 @Override registerSystemAction(RemoteAction action, int actionId)1200 public void registerSystemAction(RemoteAction action, int actionId) { 1201 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1202 mTraceManager.logTrace(LOG_TAG + ".registerSystemAction", 1203 FLAGS_ACCESSIBILITY_MANAGER, "action=" + action + ";actionId=" + actionId); 1204 } 1205 mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY); 1206 getSystemActionPerformer().registerSystemAction(actionId, action); 1207 } 1208 1209 /** 1210 * This is the implementation of AccessibilityManager system API. 1211 * System UI calls into this method through AccessibilityManager system API to unregister a 1212 * system action. 1213 */ 1214 @Override unregisterSystemAction(int actionId)1215 public void unregisterSystemAction(int actionId) { 1216 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1217 mTraceManager.logTrace(LOG_TAG + ".unregisterSystemAction", 1218 FLAGS_ACCESSIBILITY_MANAGER, "actionId=" + actionId); 1219 } 1220 mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY); 1221 getSystemActionPerformer().unregisterSystemAction(actionId); 1222 } 1223 getSystemActionPerformer()1224 private SystemActionPerformer getSystemActionPerformer() { 1225 if (mSystemActionPerformer == null) { 1226 mSystemActionPerformer = 1227 new SystemActionPerformer(mContext, mWindowManagerService, null, this, this); 1228 } 1229 return mSystemActionPerformer; 1230 } 1231 1232 @Override getInstalledAccessibilityServiceList(int userId)1233 public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) { 1234 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1235 mTraceManager.logTrace(LOG_TAG + ".getInstalledAccessibilityServiceList", 1236 FLAGS_ACCESSIBILITY_MANAGER, "userId=" + userId); 1237 } 1238 1239 final int resolvedUserId; 1240 final List<AccessibilityServiceInfo> serviceInfos; 1241 synchronized (mLock) { 1242 final int deviceId = mProxyManager.getFirstDeviceIdForUidLocked( 1243 Binder.getCallingUid()); 1244 if (mProxyManager.isProxyedDeviceId(deviceId)) { 1245 return mProxyManager.getInstalledAndEnabledServiceInfosLocked( 1246 AccessibilityServiceInfo.FEEDBACK_ALL_MASK, deviceId); 1247 } 1248 // We treat calls from a profile as if made by its parent as profiles 1249 // share the accessibility state of the parent. The call below 1250 // performs the current profile parent resolution. 1251 resolvedUserId = mSecurityPolicy 1252 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 1253 serviceInfos = new ArrayList<>( 1254 getUserStateLocked(resolvedUserId).mInstalledServices); 1255 } 1256 1257 if (Binder.getCallingPid() == OWN_PROCESS_ID) { 1258 return serviceInfos; 1259 } 1260 final PackageManagerInternal pm = LocalServices.getService( 1261 PackageManagerInternal.class); 1262 final int callingUid = Binder.getCallingUid(); 1263 for (int i = serviceInfos.size() - 1; i >= 0; i--) { 1264 final AccessibilityServiceInfo serviceInfo = serviceInfos.get(i); 1265 if (pm.filterAppAccess(serviceInfo.getComponentName().getPackageName(), callingUid, 1266 resolvedUserId)) { 1267 serviceInfos.remove(i); 1268 } 1269 } 1270 return serviceInfos; 1271 } 1272 1273 @Override getEnabledAccessibilityServiceList(int feedbackType, int userId)1274 public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, 1275 int userId) { 1276 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1277 mTraceManager.logTrace(LOG_TAG + ".getEnabledAccessibilityServiceList", 1278 FLAGS_ACCESSIBILITY_MANAGER, 1279 "feedbackType=" + feedbackType + ";userId=" + userId); 1280 } 1281 1282 synchronized (mLock) { 1283 final int deviceId = mProxyManager.getFirstDeviceIdForUidLocked( 1284 Binder.getCallingUid()); 1285 if (mProxyManager.isProxyedDeviceId(deviceId)) { 1286 return mProxyManager.getInstalledAndEnabledServiceInfosLocked(feedbackType, 1287 deviceId); 1288 } 1289 // We treat calls from a profile as if made by its parent as profiles 1290 // share the accessibility state of the parent. The call below 1291 // performs the current profile parent resolution. 1292 final int resolvedUserId = mSecurityPolicy 1293 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 1294 1295 // The automation service can suppress other services. 1296 final AccessibilityUserState userState = getUserStateLocked(resolvedUserId); 1297 if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) { 1298 return Collections.emptyList(); 1299 } 1300 1301 final List<AccessibilityServiceConnection> services = userState.mBoundServices; 1302 final int serviceCount = services.size(); 1303 final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount); 1304 for (int i = 0; i < serviceCount; ++i) { 1305 final AccessibilityServiceConnection service = services.get(i); 1306 if ((service.mFeedbackType & feedbackType) != 0 1307 || feedbackType == AccessibilityServiceInfo.FEEDBACK_ALL_MASK) { 1308 result.add(service.getServiceInfo()); 1309 } 1310 } 1311 return result; 1312 } 1313 } 1314 1315 @Override interrupt(int userId)1316 public void interrupt(int userId) { 1317 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1318 mTraceManager.logTrace(LOG_TAG + ".interrupt", 1319 FLAGS_ACCESSIBILITY_MANAGER, "userId=" + userId); 1320 } 1321 1322 List<IAccessibilityServiceClient> interfacesToInterrupt; 1323 synchronized (mLock) { 1324 // We treat calls from a profile as if made by its parent as profiles 1325 // share the accessibility state of the parent. The call below 1326 // performs the current profile parent resolution. 1327 final int resolvedUserId = mSecurityPolicy 1328 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 1329 // This method does nothing for a background user. 1330 if (resolvedUserId != mCurrentUserId) { 1331 return; 1332 } 1333 1334 final int deviceId = mProxyManager.getFirstDeviceIdForUidLocked( 1335 Binder.getCallingUid()); 1336 if (mProxyManager.isProxyedDeviceId(deviceId)) { 1337 interfacesToInterrupt = new ArrayList<>(); 1338 mProxyManager.addServiceInterfacesLocked(interfacesToInterrupt, deviceId); 1339 } else { 1340 List<AccessibilityServiceConnection> services = 1341 getUserStateLocked(resolvedUserId).mBoundServices; 1342 interfacesToInterrupt = new ArrayList<>(services.size()); 1343 for (int i = 0; i < services.size(); i++) { 1344 AccessibilityServiceConnection service = services.get(i); 1345 IBinder a11yServiceBinder = service.mService; 1346 IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface; 1347 if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) { 1348 interfacesToInterrupt.add(a11yServiceInterface); 1349 } 1350 } 1351 } 1352 } 1353 for (int i = 0, count = interfacesToInterrupt.size(); i < count; i++) { 1354 try { 1355 if (mTraceManager.isA11yTracingEnabledForTypes( 1356 FLAGS_ACCESSIBILITY_SERVICE_CLIENT)) { 1357 mTraceManager.logTrace(LOG_TAG + ".IAccessibilityServiceClient.onInterrupt", 1358 FLAGS_ACCESSIBILITY_SERVICE_CLIENT); 1359 } 1360 interfacesToInterrupt.get(i).onInterrupt(); 1361 } catch (RemoteException re) { 1362 Slog.e(LOG_TAG, "Error sending interrupt request to " 1363 + interfacesToInterrupt.get(i), re); 1364 } 1365 } 1366 } 1367 1368 @Override addAccessibilityInteractionConnection(IWindow windowToken, IBinder leashToken, IAccessibilityInteractionConnection connection, String packageName, int userId)1369 public int addAccessibilityInteractionConnection(IWindow windowToken, IBinder leashToken, 1370 IAccessibilityInteractionConnection connection, String packageName, 1371 int userId) throws RemoteException { 1372 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1373 mTraceManager.logTrace(LOG_TAG + ".addAccessibilityInteractionConnection", 1374 FLAGS_ACCESSIBILITY_MANAGER, 1375 "windowToken=" + windowToken + "leashToken=" + leashToken + ";connection=" 1376 + connection + "; packageName=" + packageName + ";userId=" + userId); 1377 } 1378 1379 return mA11yWindowManager.addAccessibilityInteractionConnection( 1380 windowToken, leashToken, connection, packageName, userId); 1381 } 1382 1383 @Override removeAccessibilityInteractionConnection(IWindow window)1384 public void removeAccessibilityInteractionConnection(IWindow window) { 1385 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1386 mTraceManager.logTrace(LOG_TAG + ".removeAccessibilityInteractionConnection", 1387 FLAGS_ACCESSIBILITY_MANAGER, "window=" + window); 1388 } 1389 mA11yWindowManager.removeAccessibilityInteractionConnection(window); 1390 } 1391 1392 @Override setPictureInPictureActionReplacingConnection( IAccessibilityInteractionConnection connection)1393 public void setPictureInPictureActionReplacingConnection( 1394 IAccessibilityInteractionConnection connection) throws RemoteException { 1395 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1396 mTraceManager.logTrace(LOG_TAG + ".setPictureInPictureActionReplacingConnection", 1397 FLAGS_ACCESSIBILITY_MANAGER, "connection=" + connection); 1398 } 1399 mSecurityPolicy.enforceCallingPermission(Manifest.permission.MODIFY_ACCESSIBILITY_DATA, 1400 SET_PIP_ACTION_REPLACEMENT); 1401 mA11yWindowManager.setPictureInPictureActionReplacingConnection(connection); 1402 } 1403 1404 @Override registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient serviceClient, AccessibilityServiceInfo accessibilityServiceInfo, int userId, int flags)1405 public void registerUiTestAutomationService(IBinder owner, 1406 IAccessibilityServiceClient serviceClient, 1407 AccessibilityServiceInfo accessibilityServiceInfo, 1408 int userId, 1409 int flags) { 1410 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1411 mTraceManager.logTrace(LOG_TAG + ".registerUiTestAutomationService", 1412 FLAGS_ACCESSIBILITY_MANAGER, 1413 "owner=" + owner + ";serviceClient=" + serviceClient 1414 + ";accessibilityServiceInfo=" + accessibilityServiceInfo + ";flags=" + flags); 1415 } 1416 1417 mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT, 1418 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE); 1419 1420 synchronized (mLock) { 1421 changeCurrentUserForTestAutomationIfNeededLocked(userId); 1422 mUiAutomationManager.registerUiTestAutomationServiceLocked(owner, serviceClient, 1423 mContext, accessibilityServiceInfo, sIdCounter++, mMainHandler, 1424 mSecurityPolicy, this, getTraceManager(), mWindowManagerService, 1425 getSystemActionPerformer(), mA11yWindowManager, flags); 1426 onUserStateChangedLocked(getCurrentUserStateLocked()); 1427 } 1428 } 1429 1430 @Override unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient)1431 public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) { 1432 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1433 mTraceManager.logTrace(LOG_TAG + ".unregisterUiTestAutomationService", 1434 FLAGS_ACCESSIBILITY_MANAGER, "serviceClient=" + serviceClient); 1435 } 1436 synchronized (mLock) { 1437 mUiAutomationManager.unregisterUiTestAutomationServiceLocked(serviceClient); 1438 restoreCurrentUserAfterTestAutomationIfNeededLocked(); 1439 } 1440 } 1441 1442 // TODO(b/255426725): temporary workaround to support visible background users for UiAutomation 1443 @GuardedBy("mLock") changeCurrentUserForTestAutomationIfNeededLocked(@serIdInt int userId)1444 private void changeCurrentUserForTestAutomationIfNeededLocked(@UserIdInt int userId) { 1445 if (mVisibleBgUserIds == null) { 1446 Slogf.d(LOG_TAG, "changeCurrentUserForTestAutomationIfNeededLocked(%d): ignoring " 1447 + "because device doesn't support visible background users", userId); 1448 return; 1449 } 1450 if (!mVisibleBgUserIds.get(userId)) { 1451 Slogf.wtf(LOG_TAG, "changeCurrentUserForTestAutomationIfNeededLocked(): cannot change " 1452 + "current user to %d as it's not visible (mVisibleUsers=%s)", 1453 userId, mVisibleBgUserIds); 1454 return; 1455 } 1456 if (mCurrentUserId == userId) { 1457 Slogf.d(LOG_TAG, "changeCurrentUserForTestAutomationIfNeededLocked(): NOT changing " 1458 + "current user for test automation purposes as it is already %d", 1459 mCurrentUserId); 1460 return; 1461 } 1462 Slogf.i(LOG_TAG, "changeCurrentUserForTestAutomationIfNeededLocked(): changing current user" 1463 + " from %d to %d for test automation purposes", mCurrentUserId, userId); 1464 mRealCurrentUserId = mCurrentUserId; 1465 switchUser(userId); 1466 } 1467 1468 // TODO(b/255426725): temporary workaround to support visible background users for UiAutomation 1469 @GuardedBy("mLock") restoreCurrentUserAfterTestAutomationIfNeededLocked()1470 private void restoreCurrentUserAfterTestAutomationIfNeededLocked() { 1471 if (mVisibleBgUserIds == null) { 1472 Slogf.d(LOG_TAG, "restoreCurrentUserForTestAutomationIfNeededLocked(): ignoring " 1473 + "because device doesn't support visible background users"); 1474 return; 1475 } 1476 if (mRealCurrentUserId == UserHandle.USER_CURRENT) { 1477 Slogf.d(LOG_TAG, "restoreCurrentUserForTestAutomationIfNeededLocked(): ignoring " 1478 + "because mRealCurrentUserId is already USER_CURRENT"); 1479 return; 1480 } 1481 Slogf.i(LOG_TAG, "restoreCurrentUserForTestAutomationIfNeededLocked(): restoring current " 1482 + "user to %d after using %d for test automation purposes", 1483 mRealCurrentUserId, mCurrentUserId); 1484 int currentUserId = mRealCurrentUserId; 1485 mRealCurrentUserId = UserHandle.USER_CURRENT; 1486 switchUser(currentUserId); 1487 } 1488 1489 @Override getWindowToken(int windowId, int userId)1490 public IBinder getWindowToken(int windowId, int userId) { 1491 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1492 mTraceManager.logTrace(LOG_TAG + ".getWindowToken", 1493 FLAGS_ACCESSIBILITY_MANAGER, "windowId=" + windowId + ";userId=" + userId); 1494 } 1495 1496 mSecurityPolicy.enforceCallingPermission( 1497 Manifest.permission.RETRIEVE_WINDOW_TOKEN, 1498 GET_WINDOW_TOKEN); 1499 synchronized (mLock) { 1500 // We treat calls from a profile as if made by its parent as profiles 1501 // share the accessibility state of the parent. The call below 1502 // performs the current profile parent resolution. 1503 final int resolvedUserId = mSecurityPolicy 1504 .resolveCallingUserIdEnforcingPermissionsLocked(userId); 1505 if (resolvedUserId != mCurrentUserId) { 1506 return null; 1507 } 1508 final AccessibilityWindowInfo accessibilityWindowInfo = mA11yWindowManager 1509 .findA11yWindowInfoByIdLocked(windowId); 1510 if (accessibilityWindowInfo == null) { 1511 return null; 1512 } 1513 // We use AccessibilityWindowInfo#getId instead of windowId. When the windowId comes 1514 // from an embedded hierarchy, the system can't find correct window token because 1515 // embedded hierarchy doesn't have windowInfo. Calling 1516 // AccessibilityWindowManager#findA11yWindowInfoByIdLocked can look for its parent's 1517 // windowInfo, so it is safer to use AccessibilityWindowInfo#getId 1518 // to get window token to find real window. 1519 return mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(userId, 1520 accessibilityWindowInfo.getId()); 1521 } 1522 } 1523 1524 /** 1525 * Invoked remotely over AIDL by SysUi when the accessibility button within the system's 1526 * navigation area has been clicked. 1527 * 1528 * @param displayId The logical display id. 1529 * @param targetName The flattened {@link ComponentName} string or the class name of a system 1530 * class implementing a supported accessibility feature, or {@code null} if there's no 1531 * specified target. 1532 */ 1533 @Override notifyAccessibilityButtonClicked(int displayId, String targetName)1534 public void notifyAccessibilityButtonClicked(int displayId, String targetName) { 1535 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1536 mTraceManager.logTrace(LOG_TAG + ".notifyAccessibilityButtonClicked", 1537 FLAGS_ACCESSIBILITY_MANAGER, 1538 "displayId=" + displayId + ";targetName=" + targetName); 1539 } 1540 1541 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE) 1542 != PackageManager.PERMISSION_GRANTED) { 1543 throw new SecurityException("Caller does not hold permission " 1544 + android.Manifest.permission.STATUS_BAR_SERVICE); 1545 } 1546 if (targetName == null) { 1547 synchronized (mLock) { 1548 final AccessibilityUserState userState = getCurrentUserStateLocked(); 1549 targetName = userState.getTargetAssignedToAccessibilityButton(); 1550 } 1551 } 1552 mMainHandler.sendMessage(obtainMessage( 1553 AccessibilityManagerService::performAccessibilityShortcutInternal, this, 1554 displayId, ACCESSIBILITY_BUTTON, targetName)); 1555 } 1556 1557 /** 1558 * Invoked remotely over AIDL by SysUi when the visibility of the accessibility 1559 * button within the system's navigation area has changed. 1560 * 1561 * @param shown {@code true} if the accessibility button is shown to the 1562 * user, {@code false} otherwise 1563 */ 1564 @Override notifyAccessibilityButtonVisibilityChanged(boolean shown)1565 public void notifyAccessibilityButtonVisibilityChanged(boolean shown) { 1566 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 1567 mTraceManager.logTrace(LOG_TAG + ".notifyAccessibilityButtonVisibilityChanged", 1568 FLAGS_ACCESSIBILITY_MANAGER, "shown=" + shown); 1569 } 1570 1571 mSecurityPolicy.enforceCallingOrSelfPermission( 1572 android.Manifest.permission.STATUS_BAR_SERVICE); 1573 synchronized (mLock) { 1574 notifyAccessibilityButtonVisibilityChangedLocked(shown); 1575 } 1576 } 1577 1578 /** 1579 * Called when a gesture is detected on a display by the framework. 1580 * 1581 * @param gestureEvent the detail of the gesture. 1582 * @return true if the event is handled. 1583 */ onGesture(AccessibilityGestureEvent gestureEvent)1584 public boolean onGesture(AccessibilityGestureEvent gestureEvent) { 1585 synchronized (mLock) { 1586 boolean handled = notifyGestureLocked(gestureEvent, false); 1587 if (!handled) { 1588 handled = notifyGestureLocked(gestureEvent, true); 1589 } 1590 return handled; 1591 } 1592 } 1593 1594 /** Send a motion event to the services. */ sendMotionEventToListeningServices(MotionEvent event)1595 public boolean sendMotionEventToListeningServices(MotionEvent event) { 1596 boolean result; 1597 event = MotionEvent.obtain(event); 1598 if (DEBUG) { 1599 Slog.d(LOG_TAG, "Sending event to service: " + event); 1600 } 1601 result = scheduleNotifyMotionEvent(event); 1602 return result; 1603 } 1604 1605 /** 1606 * Notifies services that the touch state on a given display has changed. 1607 */ onTouchStateChanged(int displayId, int state)1608 public boolean onTouchStateChanged(int displayId, int state) { 1609 if (DEBUG) { 1610 Slog.d(LOG_TAG, "Notifying touch state:" 1611 + TouchInteractionController.stateToString(state)); 1612 } 1613 return scheduleNotifyTouchState(displayId, state); 1614 } 1615 1616 /** 1617 * Called when the system action list is changed. 1618 */ 1619 @Override onSystemActionsChanged()1620 public void onSystemActionsChanged() { 1621 synchronized (mLock) { 1622 AccessibilityUserState state = getCurrentUserStateLocked(); 1623 notifySystemActionsChangedLocked(state); 1624 } 1625 } 1626 1627 @Override 1628 // TODO(b/276459590): Remove when this is resolved at the virtual device/input level. moveNonProxyTopFocusedDisplayToTopIfNeeded()1629 public void moveNonProxyTopFocusedDisplayToTopIfNeeded() { 1630 mA11yWindowManager.moveNonProxyTopFocusedDisplayToTopIfNeeded(); 1631 } 1632 1633 @Override 1634 // TODO(b/276459590): Remove when this is resolved at the virtual device/input level. getLastNonProxyTopFocusedDisplayId()1635 public int getLastNonProxyTopFocusedDisplayId() { 1636 return mA11yWindowManager.getLastNonProxyTopFocusedDisplayId(); 1637 } 1638 1639 @VisibleForTesting notifySystemActionsChangedLocked(AccessibilityUserState userState)1640 void notifySystemActionsChangedLocked(AccessibilityUserState userState) { 1641 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 1642 AccessibilityServiceConnection service = userState.mBoundServices.get(i); 1643 service.notifySystemActionsChangedLocked(); 1644 } 1645 } 1646 1647 @VisibleForTesting notifyKeyEvent(KeyEvent event, int policyFlags)1648 public boolean notifyKeyEvent(KeyEvent event, int policyFlags) { 1649 synchronized (mLock) { 1650 List<AccessibilityServiceConnection> boundServices = 1651 getCurrentUserStateLocked().mBoundServices; 1652 if (boundServices.isEmpty()) { 1653 return false; 1654 } 1655 return getKeyEventDispatcher().notifyKeyEventLocked(event, policyFlags, boundServices); 1656 } 1657 } 1658 1659 /** 1660 * Called by the MagnificationController when the state of display 1661 * magnification changes. 1662 * 1663 * <p> 1664 * It can notify window magnification change if the service supports controlling all the 1665 * magnification mode. 1666 * </p> 1667 * 1668 * @param displayId The logical display id 1669 * @param region The magnification region. 1670 * If the config mode is 1671 * {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN}, 1672 * it is the region of the screen currently active for magnification. 1673 * the returned region will be empty if the magnification is not active 1674 * (e.g. scale is 1. And the magnification is active if magnification 1675 * gestures are enabled or if a service is running that can control 1676 * magnification. 1677 * If the config mode is 1678 * {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW}, 1679 * it is the region of screen projected on the magnification window. 1680 * The region will be empty if magnification is not activated. 1681 * @param config The magnification config. That has magnification mode, the new scale and the 1682 * new screen-relative center position 1683 */ notifyMagnificationChanged(int displayId, @NonNull Region region, @NonNull MagnificationConfig config)1684 public void notifyMagnificationChanged(int displayId, @NonNull Region region, 1685 @NonNull MagnificationConfig config) { 1686 synchronized (mLock) { 1687 notifyClearAccessibilityCacheLocked(); 1688 notifyMagnificationChangedLocked(displayId, region, config); 1689 } 1690 } 1691 1692 /** 1693 * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector. 1694 * Not using a getter because the AccessibilityInputFilter isn't thread-safe 1695 * 1696 * @param motionEventInjectors The array of motionEventInjectors. May be null. 1697 * 1698 */ setMotionEventInjectors(SparseArray<MotionEventInjector> motionEventInjectors)1699 void setMotionEventInjectors(SparseArray<MotionEventInjector> motionEventInjectors) { 1700 synchronized (mLock) { 1701 mMotionEventInjectors = motionEventInjectors; 1702 // We may be waiting on this object being set 1703 mLock.notifyAll(); 1704 } 1705 } 1706 1707 @Override getMotionEventInjectorForDisplayLocked(int displayId)1708 public @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId) { 1709 final long endMillis = SystemClock.uptimeMillis() + WAIT_INPUT_FILTER_INSTALL_TIMEOUT_MS; 1710 MotionEventInjector motionEventInjector = null; 1711 while ((mMotionEventInjectors == null) && (SystemClock.uptimeMillis() < endMillis)) { 1712 try { 1713 mLock.wait(endMillis - SystemClock.uptimeMillis()); 1714 } catch (InterruptedException ie) { 1715 /* ignore */ 1716 } 1717 } 1718 if (mMotionEventInjectors == null) { 1719 Slog.e(LOG_TAG, "MotionEventInjector installation timed out"); 1720 } else { 1721 motionEventInjector = mMotionEventInjectors.get(displayId); 1722 } 1723 return motionEventInjector; 1724 } 1725 1726 /** 1727 * Gets a point within the accessibility focused node where we can send down 1728 * and up events to perform a click. 1729 * 1730 * @param outPoint The click point to populate. 1731 * @return Whether accessibility a click point was found and set. 1732 */ 1733 // TODO: (multi-display) Make sure this works for multiple displays. getAccessibilityFocusClickPointInScreen(Point outPoint)1734 public boolean getAccessibilityFocusClickPointInScreen(Point outPoint) { 1735 return getInteractionBridge().getAccessibilityFocusClickPointInScreenNotLocked(outPoint); 1736 } 1737 1738 /** 1739 * Perform an accessibility action on the view that currently has accessibility focus. 1740 * Has no effect if no item has accessibility focus, if the item with accessibility 1741 * focus does not expose the specified action, or if the action fails. 1742 * 1743 * @param action The action to perform. 1744 * 1745 * @return {@code true} if the action was performed. {@code false} if it was not. 1746 */ performActionOnAccessibilityFocusedItem( AccessibilityNodeInfo.AccessibilityAction action)1747 public boolean performActionOnAccessibilityFocusedItem( 1748 AccessibilityNodeInfo.AccessibilityAction action) { 1749 return getInteractionBridge().performActionOnAccessibilityFocusedItemNotLocked(action); 1750 } 1751 1752 /** 1753 * Returns true if accessibility focus is confined to the active window. 1754 */ accessibilityFocusOnlyInActiveWindow()1755 public boolean accessibilityFocusOnlyInActiveWindow() { 1756 synchronized (mLock) { 1757 return mA11yWindowManager.accessibilityFocusOnlyInActiveWindowLocked(); 1758 } 1759 } 1760 1761 /** 1762 * Gets the bounds of a window. 1763 * 1764 * @param outBounds The output to which to write the bounds. 1765 */ getWindowBounds(int windowId, Rect outBounds)1766 boolean getWindowBounds(int windowId, Rect outBounds) { 1767 IBinder token; 1768 synchronized (mLock) { 1769 token = getWindowToken(windowId, mCurrentUserId); 1770 } 1771 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MANAGER_INTERNAL)) { 1772 mTraceManager.logTrace("WindowManagerInternal.getWindowFrame", 1773 FLAGS_WINDOW_MANAGER_INTERNAL, "token=" + token + ";outBounds=" + outBounds); 1774 } 1775 mWindowManagerService.getWindowFrame(token, outBounds); 1776 if (!outBounds.isEmpty()) { 1777 return true; 1778 } 1779 return false; 1780 } 1781 getActiveWindowId()1782 public int getActiveWindowId() { 1783 return mA11yWindowManager.getActiveWindowId(mCurrentUserId); 1784 } 1785 onTouchInteractionStart()1786 public void onTouchInteractionStart() { 1787 mA11yWindowManager.onTouchInteractionStart(); 1788 } 1789 onTouchInteractionEnd()1790 public void onTouchInteractionEnd() { 1791 mA11yWindowManager.onTouchInteractionEnd(); 1792 } 1793 switchUser(int userId)1794 private void switchUser(int userId) { 1795 mMagnificationController.updateUserIdIfNeeded(userId); 1796 synchronized (mLock) { 1797 if (mCurrentUserId == userId && mInitialized) { 1798 return; 1799 } 1800 1801 // Disconnect from services for the old user. 1802 AccessibilityUserState oldUserState = getCurrentUserStateLocked(); 1803 oldUserState.onSwitchToAnotherUserLocked(); 1804 1805 // Disable the local managers for the old user. 1806 if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) { 1807 mMainHandler.sendMessage(obtainMessage( 1808 AccessibilityManagerService::sendStateToClients, 1809 this, 0, oldUserState.mUserId)); 1810 } 1811 1812 // Announce user changes only if more that one exist. 1813 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1814 final boolean announceNewUser = userManager.getUsers().size() > 1; 1815 1816 // The user changed. 1817 mCurrentUserId = userId; 1818 AccessibilityUserState userState = getCurrentUserStateLocked(); 1819 1820 readConfigurationForUserStateLocked(userState); 1821 mSecurityPolicy.onSwitchUserLocked(mCurrentUserId, userState.mEnabledServices); 1822 // Even if reading did not yield change, we have to update 1823 // the state since the context in which the current user 1824 // state was used has changed since it was inactive. 1825 onUserStateChangedLocked(userState); 1826 // It's better to have this migration in SettingsProvider. Unfortunately, 1827 // SettingsProvider migrated database in a very early stage which A11yManagerService 1828 // haven't finished or started the initialization. We cannot get enough information from 1829 // A11yManagerService to execute these migrations in SettingsProvider. Passing 0 for 1830 // restoreFromSdkInt to have this migration check execute every time, because we did not 1831 // find out a way to detect the device finished the OTA and switch the user. 1832 migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null, 1833 /* restoreFromSdkInt = */0); 1834 1835 if (announceNewUser) { 1836 // Schedule announcement of the current user if needed. 1837 mMainHandler.sendMessageDelayed( 1838 obtainMessage(AccessibilityManagerService::announceNewUserIfNeeded, this), 1839 WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS); 1840 } 1841 } 1842 } 1843 announceNewUserIfNeeded()1844 private void announceNewUserIfNeeded() { 1845 synchronized (mLock) { 1846 AccessibilityUserState userState = getCurrentUserStateLocked(); 1847 if (userState.isHandlingAccessibilityEventsLocked()) { 1848 UserManager userManager = (UserManager) mContext.getSystemService( 1849 Context.USER_SERVICE); 1850 String message = mContext.getString(R.string.user_switched, 1851 userManager.getUserInfo(mCurrentUserId).name); 1852 AccessibilityEvent event = AccessibilityEvent.obtain( 1853 AccessibilityEvent.TYPE_ANNOUNCEMENT); 1854 event.getText().add(message); 1855 sendAccessibilityEventLocked(event, mCurrentUserId); 1856 } 1857 } 1858 } 1859 unlockUser(int userId)1860 private void unlockUser(int userId) { 1861 synchronized (mLock) { 1862 int parentUserId = mSecurityPolicy.resolveProfileParentLocked(userId); 1863 if (parentUserId == mCurrentUserId) { 1864 AccessibilityUserState userState = getUserStateLocked(mCurrentUserId); 1865 onUserStateChangedLocked(userState); 1866 } 1867 } 1868 } 1869 removeUser(int userId)1870 private void removeUser(int userId) { 1871 synchronized (mLock) { 1872 mUserStates.remove(userId); 1873 } 1874 getMagnificationController().onUserRemoved(userId); 1875 } 1876 1877 // Called only during settings restore; currently supports only the owner user 1878 // TODO: http://b/22388012 restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting, int restoreFromSdkInt)1879 void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting, 1880 int restoreFromSdkInt) { 1881 readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false); 1882 readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true); 1883 1884 AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); 1885 userState.mEnabledServices.clear(); 1886 userState.mEnabledServices.addAll(mTempComponentNameSet); 1887 persistComponentNamesToSettingLocked( 1888 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 1889 userState.mEnabledServices, 1890 UserHandle.USER_SYSTEM); 1891 onUserStateChangedLocked(userState); 1892 migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null, restoreFromSdkInt); 1893 } 1894 1895 /** 1896 * User could enable accessibility services and configure accessibility button during the SUW. 1897 * Merges current value of accessibility button settings into the restored one to make sure 1898 * user's preferences of accessibility button updated in SUW are not lost. 1899 * 1900 * Called only during settings restore; currently supports only the owner user 1901 * TODO: http://b/22388012 1902 */ restoreAccessibilityButtonTargetsLocked(String oldSetting, String newSetting)1903 void restoreAccessibilityButtonTargetsLocked(String oldSetting, String newSetting) { 1904 final Set<String> targetsFromSetting = new ArraySet<>(); 1905 readColonDelimitedStringToSet(oldSetting, str -> str, targetsFromSetting, 1906 /* doMerge = */false); 1907 readColonDelimitedStringToSet(newSetting, str -> str, targetsFromSetting, 1908 /* doMerge = */true); 1909 1910 final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM); 1911 userState.mAccessibilityButtonTargets.clear(); 1912 userState.mAccessibilityButtonTargets.addAll(targetsFromSetting); 1913 persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, 1914 UserHandle.USER_SYSTEM, userState.mAccessibilityButtonTargets, str -> str); 1915 1916 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 1917 onUserStateChangedLocked(userState); 1918 } 1919 getClientStateLocked(AccessibilityUserState userState)1920 private int getClientStateLocked(AccessibilityUserState userState) { 1921 return userState.getClientStateLocked( 1922 mUiAutomationManager.isUiAutomationRunningLocked(), 1923 mTraceManager.getTraceStateForAccessibilityManagerClientState()); 1924 } 1925 getInteractionBridge()1926 private InteractionBridge getInteractionBridge() { 1927 synchronized (mLock) { 1928 if (mInteractionBridge == null) { 1929 mInteractionBridge = new InteractionBridge(); 1930 } 1931 return mInteractionBridge; 1932 } 1933 } 1934 notifyGestureLocked(AccessibilityGestureEvent gestureEvent, boolean isDefault)1935 private boolean notifyGestureLocked(AccessibilityGestureEvent gestureEvent, boolean isDefault) { 1936 // TODO: Now we are giving the gestures to the last enabled 1937 // service that can handle them which is the last one 1938 // in our list since we write the last enabled as the 1939 // last record in the enabled services setting. Ideally, 1940 // the user should make the call which service handles 1941 // gestures. However, only one service should handle 1942 // gestures to avoid user frustration when different 1943 // behavior is observed from different combinations of 1944 // enabled accessibility services. 1945 AccessibilityUserState state = getCurrentUserStateLocked(); 1946 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1947 AccessibilityServiceConnection service = state.mBoundServices.get(i); 1948 if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) { 1949 service.notifyGesture(gestureEvent); 1950 return true; 1951 } 1952 } 1953 return false; 1954 } 1955 scheduleNotifyMotionEvent(MotionEvent event)1956 private boolean scheduleNotifyMotionEvent(MotionEvent event) { 1957 boolean result = false; 1958 int displayId = event.getDisplayId(); 1959 synchronized (mLock) { 1960 AccessibilityUserState state = getCurrentUserStateLocked(); 1961 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1962 AccessibilityServiceConnection service = state.mBoundServices.get(i); 1963 if (service.wantsGenericMotionEvent(event) 1964 || (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN) 1965 && service.isServiceDetectsGesturesEnabled(displayId))) { 1966 service.notifyMotionEvent(event); 1967 result = true; 1968 } 1969 } 1970 } 1971 return result; 1972 } 1973 scheduleNotifyTouchState(int displayId, int touchState)1974 private boolean scheduleNotifyTouchState(int displayId, int touchState) { 1975 boolean result = false; 1976 synchronized (mLock) { 1977 AccessibilityUserState state = getCurrentUserStateLocked(); 1978 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1979 AccessibilityServiceConnection service = state.mBoundServices.get(i); 1980 if (service.isServiceDetectsGesturesEnabled(displayId)) { 1981 service.notifyTouchState(displayId, touchState); 1982 result = true; 1983 } 1984 } 1985 } 1986 return result; 1987 } 1988 1989 @Override notifyClearAccessibilityCacheLocked()1990 public void notifyClearAccessibilityCacheLocked() { 1991 AccessibilityUserState state = getCurrentUserStateLocked(); 1992 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 1993 AccessibilityServiceConnection service = state.mBoundServices.get(i); 1994 service.notifyClearAccessibilityNodeInfoCache(); 1995 } 1996 1997 mProxyManager.clearCacheLocked(); 1998 } 1999 notifyMagnificationChangedLocked(int displayId, @NonNull Region region, @NonNull MagnificationConfig config)2000 private void notifyMagnificationChangedLocked(int displayId, @NonNull Region region, 2001 @NonNull MagnificationConfig config) { 2002 final AccessibilityUserState state = getCurrentUserStateLocked(); 2003 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 2004 final AccessibilityServiceConnection service = state.mBoundServices.get(i); 2005 service.notifyMagnificationChangedLocked(displayId, region, config); 2006 } 2007 } 2008 sendAccessibilityButtonToInputFilter(int displayId)2009 private void sendAccessibilityButtonToInputFilter(int displayId) { 2010 synchronized (mLock) { 2011 if (mHasInputFilter && mInputFilter != null) { 2012 mInputFilter.notifyAccessibilityButtonClicked(displayId); 2013 } 2014 } 2015 } 2016 showAccessibilityTargetsSelection(int displayId, @ShortcutType int shortcutType)2017 private void showAccessibilityTargetsSelection(int displayId, 2018 @ShortcutType int shortcutType) { 2019 final Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON); 2020 final String chooserClassName = (shortcutType == ACCESSIBILITY_SHORTCUT_KEY) 2021 ? AccessibilityShortcutChooserActivity.class.getName() 2022 : AccessibilityButtonChooserActivity.class.getName(); 2023 intent.setClassName(CHOOSER_PACKAGE_NAME, chooserClassName); 2024 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 2025 final Bundle bundle = ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle(); 2026 mContext.startActivityAsUser(intent, bundle, UserHandle.of(mCurrentUserId)); 2027 } 2028 launchShortcutTargetActivity(int displayId, ComponentName name)2029 private void launchShortcutTargetActivity(int displayId, ComponentName name) { 2030 final Intent intent = new Intent(); 2031 final Bundle bundle = ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle(); 2032 intent.setComponent(name); 2033 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2034 try { 2035 mContext.startActivityAsUser(intent, bundle, UserHandle.of(mCurrentUserId)); 2036 } catch (ActivityNotFoundException ignore) { 2037 // ignore the exception 2038 } 2039 } 2040 launchAccessibilitySubSettings(int displayId, ComponentName name)2041 private void launchAccessibilitySubSettings(int displayId, ComponentName name) { 2042 final Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_DETAILS_SETTINGS); 2043 final Bundle bundle = ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle(); 2044 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 2045 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, name.flattenToString()); 2046 try { 2047 mContext.startActivityAsUser(intent, bundle, UserHandle.of(mCurrentUserId)); 2048 } catch (ActivityNotFoundException ignore) { 2049 // ignore the exception 2050 } 2051 } 2052 notifyAccessibilityButtonVisibilityChangedLocked(boolean available)2053 private void notifyAccessibilityButtonVisibilityChangedLocked(boolean available) { 2054 final AccessibilityUserState state = getCurrentUserStateLocked(); 2055 mIsAccessibilityButtonShown = available; 2056 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 2057 final AccessibilityServiceConnection clientConnection = state.mBoundServices.get(i); 2058 if (clientConnection.mRequestAccessibilityButton) { 2059 clientConnection.notifyAccessibilityButtonAvailabilityChangedLocked( 2060 clientConnection.isAccessibilityButtonAvailableLocked(state)); 2061 } 2062 } 2063 } 2064 readInstalledAccessibilityServiceLocked(AccessibilityUserState userState)2065 private boolean readInstalledAccessibilityServiceLocked(AccessibilityUserState userState) { 2066 mTempAccessibilityServiceInfoList.clear(); 2067 2068 int flags = PackageManager.GET_SERVICES 2069 | PackageManager.GET_META_DATA 2070 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 2071 | PackageManager.MATCH_DIRECT_BOOT_AWARE 2072 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; 2073 2074 if (userState.getBindInstantServiceAllowedLocked()) { 2075 flags |= PackageManager.MATCH_INSTANT; 2076 } 2077 2078 List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser( 2079 new Intent(AccessibilityService.SERVICE_INTERFACE), flags, mCurrentUserId); 2080 2081 for (int i = 0, count = installedServices.size(); i < count; i++) { 2082 ResolveInfo resolveInfo = installedServices.get(i); 2083 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 2084 2085 if (!mSecurityPolicy.canRegisterService(serviceInfo)) { 2086 continue; 2087 } 2088 2089 AccessibilityServiceInfo accessibilityServiceInfo; 2090 try { 2091 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext); 2092 if (!accessibilityServiceInfo.isWithinParcelableSize()) { 2093 Slog.e(LOG_TAG, "Skipping service " 2094 + accessibilityServiceInfo.getResolveInfo().getComponentInfo() 2095 + " because service info size is larger than safe parcelable limits."); 2096 continue; 2097 } 2098 if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) { 2099 // Restore the crashed attribute. 2100 accessibilityServiceInfo.crashed = true; 2101 } 2102 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo); 2103 } catch (XmlPullParserException | IOException xppe) { 2104 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe); 2105 } 2106 } 2107 2108 if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) { 2109 userState.mInstalledServices.clear(); 2110 userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList); 2111 mTempAccessibilityServiceInfoList.clear(); 2112 return true; 2113 } 2114 2115 mTempAccessibilityServiceInfoList.clear(); 2116 return false; 2117 } 2118 readInstalledAccessibilityShortcutLocked(AccessibilityUserState userState)2119 private boolean readInstalledAccessibilityShortcutLocked(AccessibilityUserState userState) { 2120 final List<AccessibilityShortcutInfo> shortcutInfos = AccessibilityManager 2121 .getInstance(mContext).getInstalledAccessibilityShortcutListAsUser( 2122 mContext, mCurrentUserId); 2123 if (!shortcutInfos.equals(userState.mInstalledShortcuts)) { 2124 userState.mInstalledShortcuts.clear(); 2125 userState.mInstalledShortcuts.addAll(shortcutInfos); 2126 return true; 2127 } 2128 return false; 2129 } 2130 readEnabledAccessibilityServicesLocked(AccessibilityUserState userState)2131 private boolean readEnabledAccessibilityServicesLocked(AccessibilityUserState userState) { 2132 mTempComponentNameSet.clear(); 2133 readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 2134 userState.mUserId, mTempComponentNameSet); 2135 if (!mTempComponentNameSet.equals(userState.mEnabledServices)) { 2136 userState.mEnabledServices.clear(); 2137 userState.mEnabledServices.addAll(mTempComponentNameSet); 2138 mTempComponentNameSet.clear(); 2139 return true; 2140 } 2141 mTempComponentNameSet.clear(); 2142 return false; 2143 } 2144 readTouchExplorationGrantedAccessibilityServicesLocked( AccessibilityUserState userState)2145 private boolean readTouchExplorationGrantedAccessibilityServicesLocked( 2146 AccessibilityUserState userState) { 2147 mTempComponentNameSet.clear(); 2148 readComponentNamesFromSettingLocked( 2149 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 2150 userState.mUserId, mTempComponentNameSet); 2151 if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) { 2152 userState.mTouchExplorationGrantedServices.clear(); 2153 userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet); 2154 mTempComponentNameSet.clear(); 2155 return true; 2156 } 2157 mTempComponentNameSet.clear(); 2158 return false; 2159 } 2160 2161 /** 2162 * Performs {@link AccessibilityService}s delayed notification. The delay is configurable 2163 * and denotes the period after the last event before notifying the service. 2164 * 2165 * @param event The event. 2166 * @param isDefault True to notify default listeners, not default services. 2167 */ notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, boolean isDefault)2168 private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, 2169 boolean isDefault) { 2170 try { 2171 AccessibilityUserState state = getCurrentUserStateLocked(); 2172 for (int i = 0, count = state.mBoundServices.size(); i < count; i++) { 2173 AccessibilityServiceConnection service = state.mBoundServices.get(i); 2174 2175 if (service.mIsDefault == isDefault) { 2176 service.notifyAccessibilityEvent(event); 2177 } 2178 } 2179 } catch (IndexOutOfBoundsException oobe) { 2180 // An out of bounds exception can happen if services are going away 2181 // as the for loop is running. If that happens, just bail because 2182 // there are no more services to notify. 2183 } 2184 } 2185 updateRelevantEventsLocked(AccessibilityUserState userState)2186 private void updateRelevantEventsLocked(AccessibilityUserState userState) { 2187 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CLIENT)) { 2188 mTraceManager.logTrace(LOG_TAG + ".updateRelevantEventsLocked", 2189 FLAGS_ACCESSIBILITY_SERVICE_CLIENT, "userState=" + userState); 2190 } 2191 mMainHandler.post(() -> { 2192 broadcastToClients(userState, ignoreRemoteException(client -> { 2193 int relevantEventTypes; 2194 synchronized (mLock) { 2195 relevantEventTypes = computeRelevantEventTypesLocked(userState, client); 2196 if (!mProxyManager.isProxyedDeviceId(client.mDeviceId)) { 2197 if (client.mLastSentRelevantEventTypes != relevantEventTypes) { 2198 client.mLastSentRelevantEventTypes = relevantEventTypes; 2199 client.mCallback.setRelevantEventTypes(relevantEventTypes); 2200 } 2201 } 2202 } 2203 })); 2204 }); 2205 } 2206 computeRelevantEventTypesLocked(AccessibilityUserState userState, Client client)2207 private int computeRelevantEventTypesLocked(AccessibilityUserState userState, Client client) { 2208 int relevantEventTypes = 0; 2209 2210 int serviceCount = userState.mBoundServices.size(); 2211 for (int i = 0; i < serviceCount; i++) { 2212 AccessibilityServiceConnection service = userState.mBoundServices.get(i); 2213 relevantEventTypes |= isClientInPackageAllowlist(service.getServiceInfo(), client) 2214 ? service.getRelevantEventTypes() 2215 : 0; 2216 } 2217 2218 relevantEventTypes |= isClientInPackageAllowlist( 2219 mUiAutomationManager.getServiceInfo(), client) 2220 ? mUiAutomationManager.getRelevantEventTypes() 2221 : 0; 2222 return relevantEventTypes; 2223 } 2224 updateMagnificationModeChangeSettingsLocked(AccessibilityUserState userState, int displayId)2225 private void updateMagnificationModeChangeSettingsLocked(AccessibilityUserState userState, 2226 int displayId) { 2227 if (userState.mUserId != mCurrentUserId) { 2228 return; 2229 } 2230 // New mode is invalid, so ignore and restore it. 2231 if (fallBackMagnificationModeSettingsLocked(userState, displayId)) { 2232 return; 2233 } 2234 mMagnificationController.transitionMagnificationModeLocked( 2235 displayId, userState.getMagnificationModeLocked(displayId), 2236 this::onMagnificationTransitionEndedLocked); 2237 } 2238 2239 /** 2240 * Called when the magnification mode transition is completed. If the given display is default 2241 * display, we also need to fall back the mode in user settings. 2242 */ onMagnificationTransitionEndedLocked(int displayId, boolean success)2243 void onMagnificationTransitionEndedLocked(int displayId, boolean success) { 2244 final AccessibilityUserState userState = getCurrentUserStateLocked(); 2245 final int previousMode = userState.getMagnificationModeLocked(displayId) 2246 ^ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL; 2247 if (!success && previousMode != 0) { 2248 userState.setMagnificationModeLocked(displayId, previousMode); 2249 if (displayId == Display.DEFAULT_DISPLAY) { 2250 persistMagnificationModeSettingsLocked(previousMode); 2251 } 2252 } else { 2253 mMainHandler.sendMessage(obtainMessage( 2254 AccessibilityManagerService::notifyRefreshMagnificationModeToInputFilter, 2255 this, displayId)); 2256 } 2257 } 2258 notifyRefreshMagnificationModeToInputFilter(int displayId)2259 private void notifyRefreshMagnificationModeToInputFilter(int displayId) { 2260 synchronized (mLock) { 2261 if (!mHasInputFilter) { 2262 return; 2263 } 2264 final ArrayList<Display> displays = getValidDisplayList(); 2265 for (int i = 0; i < displays.size(); i++) { 2266 final Display display = displays.get(i); 2267 if (display != null && display.getDisplayId() == displayId) { 2268 mInputFilter.refreshMagnificationMode(display); 2269 return; 2270 } 2271 } 2272 } 2273 } 2274 isClientInPackageAllowlist( @ullable AccessibilityServiceInfo serviceInfo, Client client)2275 static boolean isClientInPackageAllowlist( 2276 @Nullable AccessibilityServiceInfo serviceInfo, Client client) { 2277 if (serviceInfo == null) return false; 2278 2279 String[] clientPackages = client.mPackageNames; 2280 boolean result = ArrayUtils.isEmpty(serviceInfo.packageNames); 2281 if (!result && clientPackages != null) { 2282 for (String packageName : clientPackages) { 2283 if (ArrayUtils.contains(serviceInfo.packageNames, packageName)) { 2284 result = true; 2285 break; 2286 } 2287 } 2288 } 2289 if (!result) { 2290 if (DEBUG) { 2291 Slog.d(LOG_TAG, "Dropping events: " 2292 + Arrays.toString(clientPackages) + " -> " 2293 + serviceInfo.getComponentName().flattenToShortString() 2294 + " due to not being in package allowlist " 2295 + Arrays.toString(serviceInfo.packageNames)); 2296 } 2297 } 2298 2299 return result; 2300 } 2301 broadcastToClients( AccessibilityUserState userState, Consumer<Client> clientAction)2302 private void broadcastToClients( 2303 AccessibilityUserState userState, Consumer<Client> clientAction) { 2304 mGlobalClients.broadcastForEachCookie(clientAction); 2305 userState.mUserClients.broadcastForEachCookie(clientAction); 2306 } 2307 2308 /** 2309 * Populates a set with the {@link ComponentName}s stored in a colon 2310 * separated value setting for a given user. 2311 * 2312 * @param settingName The setting to parse. 2313 * @param userId The user id. 2314 * @param outComponentNames The output component names. 2315 */ readComponentNamesFromSettingLocked(String settingName, int userId, Set<ComponentName> outComponentNames)2316 private void readComponentNamesFromSettingLocked(String settingName, int userId, 2317 Set<ComponentName> outComponentNames) { 2318 readColonDelimitedSettingToSet(settingName, userId, 2319 str -> ComponentName.unflattenFromString(str), outComponentNames); 2320 } 2321 2322 /** 2323 * Populates a set with the {@link ComponentName}s contained in a colon-delimited string. 2324 * 2325 * @param names The colon-delimited string to parse. 2326 * @param outComponentNames The set of component names to be populated based on 2327 * the contents of the <code>names</code> string. 2328 * @param doMerge If true, the parsed component names will be merged into the output 2329 * set, rather than replacing the set's existing contents entirely. 2330 */ readComponentNamesFromStringLocked(String names, Set<ComponentName> outComponentNames, boolean doMerge)2331 private void readComponentNamesFromStringLocked(String names, 2332 Set<ComponentName> outComponentNames, 2333 boolean doMerge) { 2334 readColonDelimitedStringToSet(names, str -> ComponentName.unflattenFromString(str), 2335 outComponentNames, doMerge); 2336 } 2337 2338 @Override persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)2339 public void persistComponentNamesToSettingLocked(String settingName, 2340 Set<ComponentName> componentNames, int userId) { 2341 persistColonDelimitedSetToSettingLocked(settingName, userId, componentNames, 2342 componentName -> componentName.flattenToShortString()); 2343 } 2344 readColonDelimitedSettingToSet(String settingName, int userId, Function<String, T> toItem, Set<T> outSet)2345 private <T> void readColonDelimitedSettingToSet(String settingName, int userId, 2346 Function<String, T> toItem, Set<T> outSet) { 2347 final String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(), 2348 settingName, userId); 2349 readColonDelimitedStringToSet(settingValue, toItem, outSet, false); 2350 } 2351 readColonDelimitedStringToSet(String names, Function<String, T> toItem, Set<T> outSet, boolean doMerge)2352 private <T> void readColonDelimitedStringToSet(String names, Function<String, T> toItem, 2353 Set<T> outSet, boolean doMerge) { 2354 if (!doMerge) { 2355 outSet.clear(); 2356 } 2357 if (!TextUtils.isEmpty(names)) { 2358 final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; 2359 splitter.setString(names); 2360 while (splitter.hasNext()) { 2361 final String str = splitter.next(); 2362 if (TextUtils.isEmpty(str)) { 2363 continue; 2364 } 2365 final T item = toItem.apply(str); 2366 if (item != null) { 2367 outSet.add(item); 2368 } 2369 } 2370 } 2371 } 2372 persistColonDelimitedSetToSettingLocked(String settingName, int userId, Set<T> set, Function<T, String> toString)2373 private <T> void persistColonDelimitedSetToSettingLocked(String settingName, int userId, 2374 Set<T> set, Function<T, String> toString) { 2375 final StringBuilder builder = new StringBuilder(); 2376 for (T item : set) { 2377 final String str = (item != null ? toString.apply(item) : null); 2378 if (TextUtils.isEmpty(str)) { 2379 continue; 2380 } 2381 if (builder.length() > 0) { 2382 builder.append(COMPONENT_NAME_SEPARATOR); 2383 } 2384 builder.append(str); 2385 } 2386 final long identity = Binder.clearCallingIdentity(); 2387 try { 2388 final String settingValue = builder.toString(); 2389 Settings.Secure.putStringForUser(mContext.getContentResolver(), 2390 settingName, TextUtils.isEmpty(settingValue) ? null : settingValue, userId); 2391 } finally { 2392 Binder.restoreCallingIdentity(identity); 2393 } 2394 } 2395 updateServicesLocked(AccessibilityUserState userState)2396 private void updateServicesLocked(AccessibilityUserState userState) { 2397 Map<ComponentName, AccessibilityServiceConnection> componentNameToServiceMap = 2398 userState.mComponentNameToServiceMap; 2399 boolean isUnlockingOrUnlocked = mUmi.isUserUnlockingOrUnlocked(userState.mUserId); 2400 2401 for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) { 2402 AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i); 2403 ComponentName componentName = ComponentName.unflattenFromString( 2404 installedService.getId()); 2405 2406 AccessibilityServiceConnection service = componentNameToServiceMap.get(componentName); 2407 2408 // Ignore non-encryption-aware services until user is unlocked 2409 if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) { 2410 Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName); 2411 continue; 2412 } 2413 2414 // Skip the component since it may be in process or crashed. 2415 if (userState.getBindingServicesLocked().contains(componentName) 2416 || userState.getCrashedServicesLocked().contains(componentName)) { 2417 continue; 2418 } 2419 if (userState.mEnabledServices.contains(componentName) 2420 && !mUiAutomationManager.suppressingAccessibilityServicesLocked()) { 2421 // Skip the enabling service disallowed by device admin policy. 2422 if (!isAccessibilityTargetAllowed(componentName.getPackageName(), 2423 installedService.getResolveInfo().serviceInfo.applicationInfo.uid, 2424 userState.mUserId)) { 2425 Slog.d(LOG_TAG, "Skipping enabling service disallowed by device admin policy: " 2426 + componentName); 2427 disableAccessibilityServiceLocked(componentName, userState.mUserId); 2428 continue; 2429 } 2430 if (service == null) { 2431 service = new AccessibilityServiceConnection(userState, mContext, componentName, 2432 installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy, 2433 this, getTraceManager(), mWindowManagerService, 2434 getSystemActionPerformer(), mA11yWindowManager, 2435 mActivityTaskManagerService); 2436 } else if (userState.mBoundServices.contains(service)) { 2437 continue; 2438 } 2439 service.bindLocked(); 2440 } else { 2441 if (service != null) { 2442 service.unbindLocked(); 2443 removeShortcutTargetForUnboundServiceLocked(userState, service); 2444 } 2445 } 2446 } 2447 2448 final int count = userState.mBoundServices.size(); 2449 mTempIntArray.clear(); 2450 for (int i = 0; i < count; i++) { 2451 final ResolveInfo resolveInfo = 2452 userState.mBoundServices.get(i).mAccessibilityServiceInfo.getResolveInfo(); 2453 if (resolveInfo != null) { 2454 mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid); 2455 } 2456 } 2457 // Calling out with lock held, but to lower-level services 2458 final AudioManagerInternal audioManager = 2459 LocalServices.getService(AudioManagerInternal.class); 2460 if (audioManager != null) { 2461 audioManager.setAccessibilityServiceUids(mTempIntArray); 2462 } 2463 mActivityTaskManagerService.setAccessibilityServiceUids(mTempIntArray); 2464 updateAccessibilityEnabledSettingLocked(userState); 2465 } 2466 scheduleUpdateClientsIfNeededLocked(AccessibilityUserState userState)2467 void scheduleUpdateClientsIfNeededLocked(AccessibilityUserState userState) { 2468 scheduleUpdateClientsIfNeededLocked(userState, false); 2469 } 2470 scheduleUpdateClientsIfNeededLocked(AccessibilityUserState userState, boolean forceUpdate)2471 void scheduleUpdateClientsIfNeededLocked(AccessibilityUserState userState, 2472 boolean forceUpdate) { 2473 final int clientState = getClientStateLocked(userState); 2474 if (((userState.getLastSentClientStateLocked() != clientState || forceUpdate)) 2475 && (mGlobalClients.getRegisteredCallbackCount() > 0 2476 || userState.mUserClients.getRegisteredCallbackCount() > 0)) { 2477 userState.setLastSentClientStateLocked(clientState); 2478 mMainHandler.sendMessage(obtainMessage( 2479 AccessibilityManagerService::sendStateToAllClients, 2480 this, clientState, 2481 userState.mUserId)); 2482 } 2483 } 2484 sendStateToAllClients(int clientState, int userId)2485 private void sendStateToAllClients(int clientState, int userId) { 2486 sendStateToClients(clientState, mGlobalClients); 2487 sendStateToClients(clientState, userId); 2488 } 2489 sendStateToClients(int clientState, int userId)2490 private void sendStateToClients(int clientState, int userId) { 2491 sendStateToClients(clientState, getUserState(userId).mUserClients); 2492 } 2493 sendStateToClients(int clientState, RemoteCallbackList<IAccessibilityManagerClient> clients)2494 private void sendStateToClients(int clientState, 2495 RemoteCallbackList<IAccessibilityManagerClient> clients) { 2496 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER_CLIENT)) { 2497 mTraceManager.logTrace(LOG_TAG + ".sendStateToClients", 2498 FLAGS_ACCESSIBILITY_MANAGER_CLIENT, "clientState=" + clientState); 2499 } 2500 clients.broadcastForEachCookie(ignoreRemoteException( 2501 client -> { 2502 Client managerClient = ((Client) client); 2503 if (!mProxyManager.isProxyedDeviceId(managerClient.mDeviceId)) { 2504 managerClient.mCallback.setState(clientState); 2505 } 2506 })); 2507 } 2508 scheduleNotifyClientsOfServicesStateChangeLocked( AccessibilityUserState userState)2509 private void scheduleNotifyClientsOfServicesStateChangeLocked( 2510 AccessibilityUserState userState) { 2511 updateRecommendedUiTimeoutLocked(userState); 2512 mMainHandler.sendMessage(obtainMessage( 2513 AccessibilityManagerService::sendServicesStateChanged, 2514 this, userState.mUserClients, getRecommendedTimeoutMillisLocked(userState))); 2515 } 2516 sendServicesStateChanged( RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout)2517 private void sendServicesStateChanged( 2518 RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout) { 2519 notifyClientsOfServicesStateChange(mGlobalClients, uiTimeout); 2520 notifyClientsOfServicesStateChange(userClients, uiTimeout); 2521 } 2522 notifyClientsOfServicesStateChange( RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout)2523 private void notifyClientsOfServicesStateChange( 2524 RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout) { 2525 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER_CLIENT)) { 2526 mTraceManager.logTrace(LOG_TAG + ".notifyClientsOfServicesStateChange", 2527 FLAGS_ACCESSIBILITY_MANAGER_CLIENT, "uiTimeout=" + uiTimeout); 2528 } 2529 2530 clients.broadcastForEachCookie(ignoreRemoteException( 2531 client -> { 2532 Client managerClient = ((Client) client); 2533 if (!mProxyManager.isProxyedDeviceId(managerClient.mDeviceId)) { 2534 managerClient.mCallback.notifyServicesStateChanged(uiTimeout); 2535 } 2536 })); 2537 } 2538 scheduleUpdateInputFilter(AccessibilityUserState userState)2539 private void scheduleUpdateInputFilter(AccessibilityUserState userState) { 2540 mMainHandler.sendMessage(obtainMessage( 2541 AccessibilityManagerService::updateInputFilter, this, userState)); 2542 } 2543 scheduleUpdateFingerprintGestureHandling(AccessibilityUserState userState)2544 private void scheduleUpdateFingerprintGestureHandling(AccessibilityUserState userState) { 2545 mMainHandler.sendMessage(obtainMessage( 2546 AccessibilityManagerService::updateFingerprintGestureHandling, 2547 this, userState)); 2548 } 2549 updateInputFilter(AccessibilityUserState userState)2550 private void updateInputFilter(AccessibilityUserState userState) { 2551 if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return; 2552 2553 boolean setInputFilter = false; 2554 AccessibilityInputFilter inputFilter = null; 2555 synchronized (mLock) { 2556 int flags = 0; 2557 if (userState.isDisplayMagnificationEnabledLocked()) { 2558 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER; 2559 } 2560 if (userState.isShortcutMagnificationEnabledLocked()) { 2561 flags |= AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER; 2562 } 2563 if (userHasMagnificationServicesLocked(userState)) { 2564 flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER; 2565 } 2566 // Touch exploration without accessibility makes no sense. 2567 if (userState.isHandlingAccessibilityEventsLocked() 2568 && userState.isTouchExplorationEnabledLocked()) { 2569 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION; 2570 if (userState.isServiceHandlesDoubleTapEnabledLocked()) { 2571 flags |= AccessibilityInputFilter.FLAG_SERVICE_HANDLES_DOUBLE_TAP; 2572 } 2573 if (userState.isMultiFingerGesturesEnabledLocked()) { 2574 flags |= AccessibilityInputFilter.FLAG_REQUEST_MULTI_FINGER_GESTURES; 2575 } 2576 if (userState.isTwoFingerPassthroughEnabledLocked()) { 2577 flags |= AccessibilityInputFilter.FLAG_REQUEST_2_FINGER_PASSTHROUGH; 2578 } 2579 } 2580 if (userState.isFilterKeyEventsEnabledLocked()) { 2581 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS; 2582 } 2583 if (userState.isSendMotionEventsEnabled()) { 2584 flags |= AccessibilityInputFilter.FLAG_SEND_MOTION_EVENTS; 2585 } 2586 if (userState.isAutoclickEnabledLocked()) { 2587 flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK; 2588 } 2589 if (userState.isPerformGesturesEnabledLocked()) { 2590 flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS; 2591 } 2592 int combinedGenericMotionEventSources = 0; 2593 for (AccessibilityServiceConnection connection : userState.mBoundServices) { 2594 combinedGenericMotionEventSources |= connection.mGenericMotionEventSources; 2595 } 2596 if (combinedGenericMotionEventSources != 0) { 2597 flags |= AccessibilityInputFilter.FLAG_FEATURE_INTERCEPT_GENERIC_MOTION_EVENTS; 2598 } 2599 if (flags != 0) { 2600 if (!mHasInputFilter) { 2601 mHasInputFilter = true; 2602 if (mInputFilter == null) { 2603 mInputFilter = 2604 new AccessibilityInputFilter( 2605 mContext, AccessibilityManagerService.this); 2606 } 2607 inputFilter = mInputFilter; 2608 setInputFilter = true; 2609 } 2610 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags); 2611 mInputFilter.setCombinedGenericMotionEventSources( 2612 combinedGenericMotionEventSources); 2613 } else { 2614 if (mHasInputFilter) { 2615 mHasInputFilter = false; 2616 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, 0); 2617 mInputFilter.resetServiceDetectsGestures(); 2618 if (userState.isTouchExplorationEnabledLocked()) { 2619 // Service gesture detection is turned on and off on a per-display 2620 // basis. 2621 final ArrayList<Display> displays = getValidDisplayList(); 2622 for (Display display : displays) { 2623 int displayId = display.getDisplayId(); 2624 boolean mode = userState.isServiceDetectsGesturesEnabled(displayId); 2625 mInputFilter.setServiceDetectsGesturesEnabled(displayId, mode); 2626 } 2627 } 2628 inputFilter = null; 2629 setInputFilter = true; 2630 } 2631 } 2632 } 2633 if (setInputFilter) { 2634 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MANAGER_INTERNAL 2635 | FLAGS_INPUT_FILTER)) { 2636 mTraceManager.logTrace("WindowManagerInternal.setInputFilter", 2637 FLAGS_WINDOW_MANAGER_INTERNAL | FLAGS_INPUT_FILTER, 2638 "inputFilter=" + inputFilter); 2639 } 2640 mWindowManagerService.setInputFilter(inputFilter); 2641 mProxyManager.setAccessibilityInputFilter(inputFilter); 2642 } 2643 } 2644 showEnableTouchExplorationDialog(final AccessibilityServiceConnection service)2645 private void showEnableTouchExplorationDialog(final AccessibilityServiceConnection service) { 2646 synchronized (mLock) { 2647 String label = service.getServiceInfo().getResolveInfo() 2648 .loadLabel(mContext.getPackageManager()).toString(); 2649 2650 final AccessibilityUserState userState = getCurrentUserStateLocked(); 2651 if (userState.isTouchExplorationEnabledLocked()) { 2652 return; 2653 } 2654 if (mEnableTouchExplorationDialog != null 2655 && mEnableTouchExplorationDialog.isShowing()) { 2656 return; 2657 } 2658 mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext) 2659 .setIconAttribute(android.R.attr.alertDialogIcon) 2660 .setPositiveButton(android.R.string.ok, new OnClickListener() { 2661 @Override 2662 public void onClick(DialogInterface dialog, int which) { 2663 // The user allowed the service to toggle touch exploration. 2664 userState.mTouchExplorationGrantedServices.add(service.mComponentName); 2665 persistComponentNamesToSettingLocked( 2666 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 2667 userState.mTouchExplorationGrantedServices, userState.mUserId); 2668 // Enable touch exploration. 2669 userState.setTouchExplorationEnabledLocked(true); 2670 final long identity = Binder.clearCallingIdentity(); 2671 try { 2672 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2673 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, 2674 userState.mUserId); 2675 } finally { 2676 Binder.restoreCallingIdentity(identity); 2677 } 2678 onUserStateChangedLocked(userState); 2679 } 2680 }) 2681 .setNegativeButton(android.R.string.cancel, new OnClickListener() { 2682 @Override 2683 public void onClick(DialogInterface dialog, int which) { 2684 dialog.dismiss(); 2685 } 2686 }) 2687 .setTitle(R.string.enable_explore_by_touch_warning_title) 2688 .setMessage(mContext.getString( 2689 R.string.enable_explore_by_touch_warning_message, label)) 2690 .create(); 2691 mEnableTouchExplorationDialog.getWindow().setType( 2692 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 2693 mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags 2694 |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; 2695 mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true); 2696 mEnableTouchExplorationDialog.show(); 2697 } 2698 } 2699 onUserVisibilityChanged(@serIdInt int userId, boolean visible)2700 private void onUserVisibilityChanged(@UserIdInt int userId, boolean visible) { 2701 if (DEBUG) { 2702 Slogf.d(LOG_TAG, "onUserVisibilityChanged(): %d => %b", userId, visible); 2703 } 2704 synchronized (mLock) { 2705 if (visible) { 2706 mVisibleBgUserIds.put(userId, visible); 2707 } else { 2708 mVisibleBgUserIds.delete(userId); 2709 } 2710 } 2711 } 2712 2713 /** 2714 * Called when any property of the user state has changed. 2715 * 2716 * @param userState the new user state 2717 */ onUserStateChangedLocked(AccessibilityUserState userState)2718 private void onUserStateChangedLocked(AccessibilityUserState userState) { 2719 onUserStateChangedLocked(userState, false); 2720 } 2721 2722 /** 2723 * Called when any property of the user state has changed. 2724 * 2725 * @param userState the new user state 2726 * @param forceUpdate whether to force an update of the app Clients. 2727 */ onUserStateChangedLocked(AccessibilityUserState userState, boolean forceUpdate)2728 private void onUserStateChangedLocked(AccessibilityUserState userState, boolean forceUpdate) { 2729 if (DEBUG) { 2730 Slog.v(LOG_TAG, "onUserStateChangedLocked for user " + userState.mUserId + " with " 2731 + "forceUpdate: " + forceUpdate); 2732 } 2733 // TODO: Remove this hack 2734 mInitialized = true; 2735 updateLegacyCapabilitiesLocked(userState); 2736 updateServicesLocked(userState); 2737 updateWindowsForAccessibilityCallbackLocked(userState); 2738 updateFilterKeyEventsLocked(userState); 2739 updateTouchExplorationLocked(userState); 2740 updatePerformGesturesLocked(userState); 2741 updateMagnificationLocked(userState); 2742 scheduleUpdateFingerprintGestureHandling(userState); 2743 scheduleUpdateInputFilter(userState); 2744 updateRelevantEventsLocked(userState); 2745 scheduleUpdateClientsIfNeededLocked(userState, forceUpdate); 2746 updateAccessibilityShortcutKeyTargetsLocked(userState); 2747 updateAccessibilityButtonTargetsLocked(userState); 2748 // Update the capabilities before the mode because we will check the current mode is 2749 // invalid or not.. 2750 updateMagnificationCapabilitiesSettingsChangeLocked(userState); 2751 updateMagnificationModeChangeSettingsForAllDisplaysLocked(userState); 2752 updateFocusAppearanceDataLocked(userState); 2753 } 2754 updateMagnificationModeChangeSettingsForAllDisplaysLocked( AccessibilityUserState userState)2755 private void updateMagnificationModeChangeSettingsForAllDisplaysLocked( 2756 AccessibilityUserState userState) { 2757 final ArrayList<Display> displays = getValidDisplayList(); 2758 for (int i = 0; i < displays.size(); i++) { 2759 final int displayId = displays.get(i).getDisplayId(); 2760 updateMagnificationModeChangeSettingsLocked(userState, displayId); 2761 } 2762 } 2763 updateWindowsForAccessibilityCallbackLocked(AccessibilityUserState userState)2764 private void updateWindowsForAccessibilityCallbackLocked(AccessibilityUserState userState) { 2765 // We observe windows for accessibility only if there is at least 2766 // one bound service that can retrieve window content that specified 2767 // it is interested in accessing such windows. For services that are 2768 // binding we do an update pass after each bind event, so we run this 2769 // code and register the callback if needed. 2770 2771 boolean observingWindows = mUiAutomationManager.canRetrieveInteractiveWindowsLocked() 2772 || mProxyManager.canRetrieveInteractiveWindowsLocked(); 2773 List<AccessibilityServiceConnection> boundServices = userState.mBoundServices; 2774 final int boundServiceCount = boundServices.size(); 2775 for (int i = 0; !observingWindows && (i < boundServiceCount); i++) { 2776 AccessibilityServiceConnection boundService = boundServices.get(i); 2777 if (boundService.canRetrieveInteractiveWindowsLocked()) { 2778 userState.setAccessibilityFocusOnlyInActiveWindow(false); 2779 observingWindows = true; 2780 } 2781 } 2782 userState.setAccessibilityFocusOnlyInActiveWindow(true); 2783 2784 // Gets all valid displays and start tracking windows of each display if there is at least 2785 // one bound service that can retrieve window content. 2786 final ArrayList<Display> displays = getValidDisplayList(); 2787 for (int i = 0; i < displays.size(); i++) { 2788 final Display display = displays.get(i); 2789 if (display != null) { 2790 if (observingWindows) { 2791 mA11yWindowManager.startTrackingWindows(display.getDisplayId(), 2792 mProxyManager.isProxyedDisplay(display.getDisplayId())); 2793 } else { 2794 mA11yWindowManager.stopTrackingWindows(display.getDisplayId()); 2795 } 2796 } 2797 } 2798 } 2799 updateLegacyCapabilitiesLocked(AccessibilityUserState userState)2800 private void updateLegacyCapabilitiesLocked(AccessibilityUserState userState) { 2801 // Up to JB-MR1 we had a allowlist with services that can enable touch 2802 // exploration. When a service is first started we show a dialog to the 2803 // use to get a permission to allowlist the service. 2804 final int installedServiceCount = userState.mInstalledServices.size(); 2805 for (int i = 0; i < installedServiceCount; i++) { 2806 AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i); 2807 ResolveInfo resolveInfo = serviceInfo.getResolveInfo(); 2808 if ((serviceInfo.getCapabilities() 2809 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0 2810 && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion 2811 <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 2812 ComponentName componentName = new ComponentName( 2813 resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); 2814 if (userState.mTouchExplorationGrantedServices.contains(componentName)) { 2815 serviceInfo.setCapabilities(serviceInfo.getCapabilities() 2816 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION); 2817 } 2818 } 2819 } 2820 } 2821 updatePerformGesturesLocked(AccessibilityUserState userState)2822 private void updatePerformGesturesLocked(AccessibilityUserState userState) { 2823 final int serviceCount = userState.mBoundServices.size(); 2824 for (int i = 0; i < serviceCount; i++) { 2825 AccessibilityServiceConnection service = userState.mBoundServices.get(i); 2826 if ((service.getCapabilities() 2827 & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) { 2828 userState.setPerformGesturesEnabledLocked(true); 2829 return; 2830 } 2831 } 2832 userState.setPerformGesturesEnabledLocked(false); 2833 } 2834 updateFilterKeyEventsLocked(AccessibilityUserState userState)2835 private void updateFilterKeyEventsLocked(AccessibilityUserState userState) { 2836 final int serviceCount = userState.mBoundServices.size(); 2837 for (int i = 0; i < serviceCount; i++) { 2838 AccessibilityServiceConnection service = userState.mBoundServices.get(i); 2839 if (service.mRequestFilterKeyEvents 2840 && (service.getCapabilities() 2841 & AccessibilityServiceInfo 2842 .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) { 2843 userState.setFilterKeyEventsEnabledLocked(true); 2844 return; 2845 } 2846 } 2847 userState.setFilterKeyEventsEnabledLocked(false); 2848 } 2849 readConfigurationForUserStateLocked(AccessibilityUserState userState)2850 private boolean readConfigurationForUserStateLocked(AccessibilityUserState userState) { 2851 boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState); 2852 somethingChanged |= readInstalledAccessibilityShortcutLocked(userState); 2853 somethingChanged |= readEnabledAccessibilityServicesLocked(userState); 2854 somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState); 2855 somethingChanged |= readTouchExplorationEnabledSettingLocked(userState); 2856 somethingChanged |= readHighTextContrastEnabledSettingLocked(userState); 2857 somethingChanged |= readAudioDescriptionEnabledSettingLocked(userState); 2858 somethingChanged |= readMagnificationEnabledSettingsLocked(userState); 2859 somethingChanged |= readAutoclickEnabledSettingLocked(userState); 2860 somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState); 2861 somethingChanged |= readAccessibilityButtonTargetsLocked(userState); 2862 somethingChanged |= readAccessibilityButtonTargetComponentLocked(userState); 2863 somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState); 2864 somethingChanged |= readMagnificationModeForDefaultDisplayLocked(userState); 2865 somethingChanged |= readMagnificationCapabilitiesLocked(userState); 2866 somethingChanged |= readMagnificationFollowTypingLocked(userState); 2867 somethingChanged |= readAlwaysOnMagnificationLocked(userState); 2868 return somethingChanged; 2869 } 2870 updateAccessibilityEnabledSettingLocked(AccessibilityUserState userState)2871 private void updateAccessibilityEnabledSettingLocked(AccessibilityUserState userState) { 2872 final boolean isA11yEnabled = mUiAutomationManager.isUiAutomationRunningLocked() 2873 || userState.isHandlingAccessibilityEventsLocked(); 2874 final long identity = Binder.clearCallingIdentity(); 2875 try { 2876 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2877 Settings.Secure.ACCESSIBILITY_ENABLED, 2878 (isA11yEnabled) ? 1 : 0, 2879 userState.mUserId); 2880 } finally { 2881 Binder.restoreCallingIdentity(identity); 2882 } 2883 } 2884 readTouchExplorationEnabledSettingLocked(AccessibilityUserState userState)2885 private boolean readTouchExplorationEnabledSettingLocked(AccessibilityUserState userState) { 2886 final boolean touchExplorationEnabled = Settings.Secure.getIntForUser( 2887 mContext.getContentResolver(), 2888 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1; 2889 if (touchExplorationEnabled != userState.isTouchExplorationEnabledLocked()) { 2890 userState.setTouchExplorationEnabledLocked(touchExplorationEnabled); 2891 return true; 2892 } 2893 return false; 2894 } 2895 readMagnificationEnabledSettingsLocked(AccessibilityUserState userState)2896 private boolean readMagnificationEnabledSettingsLocked(AccessibilityUserState userState) { 2897 final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser( 2898 mContext.getContentResolver(), 2899 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 2900 0, userState.mUserId) == 1; 2901 if ((displayMagnificationEnabled != userState.isDisplayMagnificationEnabledLocked())) { 2902 userState.setDisplayMagnificationEnabledLocked(displayMagnificationEnabled); 2903 return true; 2904 } 2905 return false; 2906 } 2907 readAutoclickEnabledSettingLocked(AccessibilityUserState userState)2908 private boolean readAutoclickEnabledSettingLocked(AccessibilityUserState userState) { 2909 final boolean autoclickEnabled = Settings.Secure.getIntForUser( 2910 mContext.getContentResolver(), 2911 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, 2912 0, userState.mUserId) == 1; 2913 if (autoclickEnabled != userState.isAutoclickEnabledLocked()) { 2914 userState.setAutoclickEnabledLocked(autoclickEnabled); 2915 return true; 2916 } 2917 return false; 2918 } 2919 readHighTextContrastEnabledSettingLocked(AccessibilityUserState userState)2920 private boolean readHighTextContrastEnabledSettingLocked(AccessibilityUserState userState) { 2921 final boolean highTextContrastEnabled = Settings.Secure.getIntForUser( 2922 mContext.getContentResolver(), 2923 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0, 2924 userState.mUserId) == 1; 2925 if (highTextContrastEnabled != userState.isTextHighContrastEnabledLocked()) { 2926 userState.setTextHighContrastEnabledLocked(highTextContrastEnabled); 2927 return true; 2928 } 2929 return false; 2930 } 2931 readAudioDescriptionEnabledSettingLocked(AccessibilityUserState userState)2932 private boolean readAudioDescriptionEnabledSettingLocked(AccessibilityUserState userState) { 2933 final boolean audioDescriptionByDefaultEnabled = Settings.Secure.getIntForUser( 2934 mContext.getContentResolver(), 2935 Settings.Secure.ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT, 0, 2936 userState.mUserId) == 1; 2937 if (audioDescriptionByDefaultEnabled 2938 != userState.isAudioDescriptionByDefaultEnabledLocked()) { 2939 userState.setAudioDescriptionByDefaultEnabledLocked(audioDescriptionByDefaultEnabled); 2940 return true; 2941 } 2942 return false; 2943 } 2944 updateTouchExplorationLocked(AccessibilityUserState userState)2945 private void updateTouchExplorationLocked(AccessibilityUserState userState) { 2946 boolean touchExplorationEnabled = mUiAutomationManager.isTouchExplorationEnabledLocked(); 2947 boolean serviceHandlesDoubleTapEnabled = false; 2948 boolean requestMultiFingerGestures = false; 2949 boolean requestTwoFingerPassthrough = false; 2950 boolean sendMotionEvents = false; 2951 final int serviceCount = userState.mBoundServices.size(); 2952 for (int i = 0; i < serviceCount; i++) { 2953 AccessibilityServiceConnection service = userState.mBoundServices.get(i); 2954 if (canRequestAndRequestsTouchExplorationLocked(service, userState)) { 2955 touchExplorationEnabled = true; 2956 serviceHandlesDoubleTapEnabled = service.isServiceHandlesDoubleTapEnabled(); 2957 requestMultiFingerGestures = service.isMultiFingerGesturesEnabled(); 2958 requestTwoFingerPassthrough = service.isTwoFingerPassthroughEnabled(); 2959 sendMotionEvents = service.isSendMotionEventsEnabled(); 2960 break; 2961 } 2962 } 2963 if (touchExplorationEnabled != userState.isTouchExplorationEnabledLocked()) { 2964 userState.setTouchExplorationEnabledLocked(touchExplorationEnabled); 2965 final long identity = Binder.clearCallingIdentity(); 2966 try { 2967 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2968 Settings.Secure.TOUCH_EXPLORATION_ENABLED, touchExplorationEnabled ? 1 : 0, 2969 userState.mUserId); 2970 } finally { 2971 Binder.restoreCallingIdentity(identity); 2972 } 2973 } 2974 // Service gesture detection is turned on and off on a per-display 2975 // basis. 2976 userState.resetServiceDetectsGestures(); 2977 final ArrayList<Display> displays = getValidDisplayList(); 2978 for (AccessibilityServiceConnection service: userState.mBoundServices) { 2979 for (Display display : displays) { 2980 int displayId = display.getDisplayId(); 2981 if (service.isServiceDetectsGesturesEnabled(displayId)) { 2982 userState.setServiceDetectsGesturesEnabled(displayId, true); 2983 } 2984 } 2985 } 2986 userState.setServiceHandlesDoubleTapLocked(serviceHandlesDoubleTapEnabled); 2987 userState.setMultiFingerGesturesLocked(requestMultiFingerGestures); 2988 userState.setTwoFingerPassthroughLocked(requestTwoFingerPassthrough); 2989 userState.setSendMotionEventsEnabled(sendMotionEvents); 2990 } 2991 readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState)2992 private boolean readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState) { 2993 final String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(), 2994 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userState.mUserId); 2995 final Set<String> targetsFromSetting = new ArraySet<>(); 2996 readColonDelimitedStringToSet(settingValue, str -> str, targetsFromSetting, false); 2997 // Fall back to device's default a11y service, only when setting is never updated. 2998 if (settingValue == null) { 2999 final String defaultService = mContext.getString( 3000 R.string.config_defaultAccessibilityService); 3001 if (!TextUtils.isEmpty(defaultService)) { 3002 targetsFromSetting.add(defaultService); 3003 } 3004 } 3005 3006 final Set<String> currentTargets = 3007 userState.getShortcutTargetsLocked(ACCESSIBILITY_SHORTCUT_KEY); 3008 if (targetsFromSetting.equals(currentTargets)) { 3009 return false; 3010 } 3011 currentTargets.clear(); 3012 currentTargets.addAll(targetsFromSetting); 3013 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 3014 return true; 3015 } 3016 readAccessibilityButtonTargetsLocked(AccessibilityUserState userState)3017 private boolean readAccessibilityButtonTargetsLocked(AccessibilityUserState userState) { 3018 final Set<String> targetsFromSetting = new ArraySet<>(); 3019 readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, 3020 userState.mUserId, str -> str, targetsFromSetting); 3021 3022 final Set<String> currentTargets = 3023 userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON); 3024 if (targetsFromSetting.equals(currentTargets)) { 3025 return false; 3026 } 3027 currentTargets.clear(); 3028 currentTargets.addAll(targetsFromSetting); 3029 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 3030 return true; 3031 } 3032 readAccessibilityButtonTargetComponentLocked(AccessibilityUserState userState)3033 private boolean readAccessibilityButtonTargetComponentLocked(AccessibilityUserState userState) { 3034 final String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(), 3035 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId); 3036 if (TextUtils.isEmpty(componentId)) { 3037 if (userState.getTargetAssignedToAccessibilityButton() == null) { 3038 return false; 3039 } 3040 userState.setTargetAssignedToAccessibilityButton(null); 3041 return true; 3042 } 3043 if (componentId.equals(userState.getTargetAssignedToAccessibilityButton())) { 3044 return false; 3045 } 3046 userState.setTargetAssignedToAccessibilityButton(componentId); 3047 return true; 3048 } 3049 readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState)3050 private boolean readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState) { 3051 final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser( 3052 mContext.getContentResolver(), 3053 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, 0, 3054 userState.mUserId); 3055 final int interactiveUiTimeout = Settings.Secure.getIntForUser( 3056 mContext.getContentResolver(), 3057 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, 0, 3058 userState.mUserId); 3059 3060 mProxyManager.updateTimeoutsIfNeeded(nonInteractiveUiTimeout, interactiveUiTimeout); 3061 if (nonInteractiveUiTimeout != userState.getUserNonInteractiveUiTimeoutLocked() 3062 || interactiveUiTimeout != userState.getUserInteractiveUiTimeoutLocked()) { 3063 userState.setUserNonInteractiveUiTimeoutLocked(nonInteractiveUiTimeout); 3064 userState.setUserInteractiveUiTimeoutLocked(interactiveUiTimeout); 3065 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 3066 return true; 3067 } 3068 return false; 3069 } 3070 3071 /** 3072 * Check if the target that will be enabled by the accessibility shortcut key is installed. 3073 * If it isn't, remove it from the list and associated setting so a side loaded service can't 3074 * spoof the package name of the default service. 3075 */ updateAccessibilityShortcutKeyTargetsLocked(AccessibilityUserState userState)3076 private void updateAccessibilityShortcutKeyTargetsLocked(AccessibilityUserState userState) { 3077 final Set<String> currentTargets = 3078 userState.getShortcutTargetsLocked(ACCESSIBILITY_SHORTCUT_KEY); 3079 final int lastSize = currentTargets.size(); 3080 if (lastSize == 0) { 3081 return; 3082 } 3083 currentTargets.removeIf( 3084 name -> !userState.isShortcutTargetInstalledLocked(name)); 3085 if (lastSize == currentTargets.size()) { 3086 return; 3087 } 3088 3089 // Update setting key with new value. 3090 persistColonDelimitedSetToSettingLocked( 3091 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, 3092 userState.mUserId, currentTargets, str -> str); 3093 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 3094 } 3095 canRequestAndRequestsTouchExplorationLocked( AccessibilityServiceConnection service, AccessibilityUserState userState)3096 private boolean canRequestAndRequestsTouchExplorationLocked( 3097 AccessibilityServiceConnection service, AccessibilityUserState userState) { 3098 // Service not ready or cannot request the feature - well nothing to do. 3099 if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) { 3100 return false; 3101 } 3102 if (service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion 3103 <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 3104 // Up to JB-MR1 we had a allowlist with services that can enable touch 3105 // exploration. When a service is first started we show a dialog to the 3106 // use to get a permission to allowlist the service. 3107 if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) { 3108 return true; 3109 } else if (mEnableTouchExplorationDialog == null 3110 || !mEnableTouchExplorationDialog.isShowing()) { 3111 mMainHandler.sendMessage(obtainMessage( 3112 AccessibilityManagerService::showEnableTouchExplorationDialog, 3113 this, service)); 3114 } 3115 } else { 3116 // Starting in JB-MR2 we request an accessibility service to declare 3117 // certain capabilities in its meta-data to allow it to enable the 3118 // corresponding features. 3119 if ((service.getCapabilities() 3120 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) { 3121 return true; 3122 } 3123 } 3124 return false; 3125 } 3126 updateMagnificationLocked(AccessibilityUserState userState)3127 private void updateMagnificationLocked(AccessibilityUserState userState) { 3128 if (userState.mUserId != mCurrentUserId) { 3129 return; 3130 } 3131 3132 if (mUiAutomationManager.suppressingAccessibilityServicesLocked() 3133 && mMagnificationController.isFullScreenMagnificationControllerInitialized()) { 3134 getMagnificationController().getFullScreenMagnificationController().unregisterAll(); 3135 return; 3136 } 3137 3138 // Get all valid displays and register them if global magnification is enabled. 3139 // We would skip overlay display because it uses overlay window to simulate secondary 3140 // displays in one display. It's not a real display and there's no input events for it. 3141 final ArrayList<Display> displays = getValidDisplayList(); 3142 if (userState.isDisplayMagnificationEnabledLocked() 3143 || userState.isShortcutMagnificationEnabledLocked()) { 3144 for (int i = 0; i < displays.size(); i++) { 3145 final Display display = displays.get(i); 3146 getMagnificationController().getFullScreenMagnificationController().register( 3147 display.getDisplayId()); 3148 } 3149 return; 3150 } 3151 3152 // Register if display has listening magnification services. 3153 for (int i = 0; i < displays.size(); i++) { 3154 final Display display = displays.get(i); 3155 final int displayId = display.getDisplayId(); 3156 if (userHasListeningMagnificationServicesLocked(userState, displayId)) { 3157 getMagnificationController().getFullScreenMagnificationController().register( 3158 displayId); 3159 } else if (mMagnificationController.isFullScreenMagnificationControllerInitialized()) { 3160 getMagnificationController().getFullScreenMagnificationController().unregister( 3161 displayId); 3162 } 3163 } 3164 } 3165 updateWindowMagnificationConnectionIfNeeded(AccessibilityUserState userState)3166 private void updateWindowMagnificationConnectionIfNeeded(AccessibilityUserState userState) { 3167 if (!mMagnificationController.supportWindowMagnification()) { 3168 return; 3169 } 3170 final boolean connect = (userState.isShortcutMagnificationEnabledLocked() 3171 || userState.isDisplayMagnificationEnabledLocked()) 3172 && (userState.getMagnificationCapabilitiesLocked() 3173 != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) 3174 || userHasMagnificationServicesLocked(userState); 3175 getWindowMagnificationMgr().requestConnection(connect); 3176 } 3177 3178 /** 3179 * Returns whether the specified user has any services that are capable of 3180 * controlling magnification. 3181 */ userHasMagnificationServicesLocked(AccessibilityUserState userState)3182 private boolean userHasMagnificationServicesLocked(AccessibilityUserState userState) { 3183 final List<AccessibilityServiceConnection> services = userState.mBoundServices; 3184 for (int i = 0, count = services.size(); i < count; i++) { 3185 final AccessibilityServiceConnection service = services.get(i); 3186 if (mSecurityPolicy.canControlMagnification(service)) { 3187 return true; 3188 } 3189 } 3190 return false; 3191 } 3192 3193 /** 3194 * Returns whether the specified user has any services that are capable of 3195 * controlling magnification and are actively listening for magnification updates. 3196 */ userHasListeningMagnificationServicesLocked(AccessibilityUserState userState, int displayId)3197 private boolean userHasListeningMagnificationServicesLocked(AccessibilityUserState userState, 3198 int displayId) { 3199 final List<AccessibilityServiceConnection> services = userState.mBoundServices; 3200 for (int i = 0, count = services.size(); i < count; i++) { 3201 final AccessibilityServiceConnection service = services.get(i); 3202 if (mSecurityPolicy.canControlMagnification(service) 3203 && service.isMagnificationCallbackEnabled(displayId)) { 3204 return true; 3205 } 3206 } 3207 return false; 3208 } 3209 updateFingerprintGestureHandling(AccessibilityUserState userState)3210 private void updateFingerprintGestureHandling(AccessibilityUserState userState) { 3211 final List<AccessibilityServiceConnection> services; 3212 synchronized (mLock) { 3213 services = userState.mBoundServices; 3214 if ((mFingerprintGestureDispatcher == null) 3215 && mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 3216 // Only create the controller when a service wants to use the feature 3217 int numServices = services.size(); 3218 for (int i = 0; i < numServices; i++) { 3219 if (services.get(i).isCapturingFingerprintGestures()) { 3220 IFingerprintService service = null; 3221 final long identity = Binder.clearCallingIdentity(); 3222 try { 3223 service = IFingerprintService.Stub.asInterface( 3224 ServiceManager.getService(Context.FINGERPRINT_SERVICE)); 3225 } finally { 3226 Binder.restoreCallingIdentity(identity); 3227 } 3228 if (service != null) { 3229 mFingerprintGestureDispatcher = new FingerprintGestureDispatcher( 3230 service, mContext.getResources(), mLock); 3231 break; 3232 } 3233 } 3234 } 3235 } 3236 } 3237 if (mFingerprintGestureDispatcher != null) { 3238 mFingerprintGestureDispatcher.updateClientList(services); 3239 } 3240 } 3241 3242 /** 3243 * 1) Update accessibility button availability to accessibility services. 3244 * 2) Check if the target that will be enabled by the accessibility button is installed. 3245 * If it isn't, remove it from the list and associated setting so a side loaded service can't 3246 * spoof the package name of the default service. 3247 */ updateAccessibilityButtonTargetsLocked(AccessibilityUserState userState)3248 private void updateAccessibilityButtonTargetsLocked(AccessibilityUserState userState) { 3249 // Update accessibility button availability. 3250 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 3251 final AccessibilityServiceConnection service = userState.mBoundServices.get(i); 3252 if (service.mRequestAccessibilityButton) { 3253 service.notifyAccessibilityButtonAvailabilityChangedLocked( 3254 service.isAccessibilityButtonAvailableLocked(userState)); 3255 } 3256 } 3257 3258 final Set<String> currentTargets = 3259 userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON); 3260 final int lastSize = currentTargets.size(); 3261 if (lastSize == 0) { 3262 return; 3263 } 3264 currentTargets.removeIf( 3265 name -> !userState.isShortcutTargetInstalledLocked(name)); 3266 if (lastSize == currentTargets.size()) { 3267 return; 3268 } 3269 3270 // Update setting key with new value. 3271 persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, 3272 userState.mUserId, currentTargets, str -> str); 3273 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 3274 } 3275 3276 /** 3277 * 1) Check if the service assigned to accessibility button target sdk version > Q. 3278 * If it isn't, remove it from the list and associated setting. 3279 * (It happens when an accessibility service package is downgraded.) 3280 * 2) For a service targeting sdk version > Q and requesting a11y button, it should be in the 3281 * enabled list if's assigned to a11y button. 3282 * (It happens when an accessibility service package is same graded, and updated requesting 3283 * a11y button flag) 3284 * 3) Check if an enabled service targeting sdk version > Q and requesting a11y button is 3285 * assigned to a shortcut. If it isn't, assigns it to the accessibility button. 3286 * (It happens when an enabled accessibility service package is upgraded.) 3287 * 3288 * @param packageName The package name to check, or {@code null} to check all services. 3289 * @param restoreFromSdkInt The target sdk version of the restored source device, or {@code 0} 3290 * if the caller is not related to the restore. 3291 */ migrateAccessibilityButtonSettingsIfNecessaryLocked( AccessibilityUserState userState, @Nullable String packageName, int restoreFromSdkInt)3292 private void migrateAccessibilityButtonSettingsIfNecessaryLocked( 3293 AccessibilityUserState userState, @Nullable String packageName, int restoreFromSdkInt) { 3294 // No need to migrate settings if they are restored from a version after Q. 3295 if (restoreFromSdkInt > Build.VERSION_CODES.Q) { 3296 return; 3297 } 3298 final Set<String> buttonTargets = 3299 userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON); 3300 int lastSize = buttonTargets.size(); 3301 buttonTargets.removeIf(name -> { 3302 if (packageName != null && name != null && !name.contains(packageName)) { 3303 return false; 3304 } 3305 final ComponentName componentName = ComponentName.unflattenFromString(name); 3306 if (componentName == null) { 3307 return false; 3308 } 3309 final AccessibilityServiceInfo serviceInfo = 3310 userState.getInstalledServiceInfoLocked(componentName); 3311 if (serviceInfo == null) { 3312 return false; 3313 } 3314 if (serviceInfo.getResolveInfo().serviceInfo.applicationInfo 3315 .targetSdkVersion <= Build.VERSION_CODES.Q) { 3316 // A11y services targeting sdk version <= Q should not be in the list. 3317 Slog.v(LOG_TAG, "Legacy service " + componentName 3318 + " should not in the button"); 3319 return true; 3320 } 3321 final boolean requestA11yButton = (serviceInfo.flags 3322 & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; 3323 if (requestA11yButton && !userState.mEnabledServices.contains(componentName)) { 3324 // An a11y service targeting sdk version > Q and request A11y button and is assigned 3325 // to a11y btn should be in the enabled list. 3326 Slog.v(LOG_TAG, "Service requesting a11y button and be assigned to the button" 3327 + componentName + " should be enabled state"); 3328 return true; 3329 } 3330 return false; 3331 }); 3332 boolean changed = (lastSize != buttonTargets.size()); 3333 lastSize = buttonTargets.size(); 3334 3335 final Set<String> shortcutKeyTargets = 3336 userState.getShortcutTargetsLocked(ACCESSIBILITY_SHORTCUT_KEY); 3337 userState.mEnabledServices.forEach(componentName -> { 3338 if (packageName != null && componentName != null 3339 && !packageName.equals(componentName.getPackageName())) { 3340 return; 3341 } 3342 final AccessibilityServiceInfo serviceInfo = 3343 userState.getInstalledServiceInfoLocked(componentName); 3344 if (serviceInfo == null) { 3345 return; 3346 } 3347 final boolean requestA11yButton = (serviceInfo.flags 3348 & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; 3349 if (!(serviceInfo.getResolveInfo().serviceInfo.applicationInfo 3350 .targetSdkVersion > Build.VERSION_CODES.Q && requestA11yButton)) { 3351 return; 3352 } 3353 final String serviceName = componentName.flattenToString(); 3354 if (TextUtils.isEmpty(serviceName)) { 3355 return; 3356 } 3357 if (doesShortcutTargetsStringContain(buttonTargets, serviceName) 3358 || doesShortcutTargetsStringContain(shortcutKeyTargets, serviceName)) { 3359 return; 3360 } 3361 // For enabled a11y services targeting sdk version > Q and requesting a11y button should 3362 // be assigned to a shortcut. 3363 Slog.v(LOG_TAG, "A enabled service requesting a11y button " + componentName 3364 + " should be assign to the button or shortcut."); 3365 buttonTargets.add(serviceName); 3366 }); 3367 changed |= (lastSize != buttonTargets.size()); 3368 if (!changed) { 3369 return; 3370 } 3371 3372 // Update setting key with new value. 3373 persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, 3374 userState.mUserId, buttonTargets, str -> str); 3375 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 3376 } 3377 3378 /** 3379 * Remove the shortcut target for the unbound service which is requesting accessibility button 3380 * and targeting sdk > Q from the accessibility button and shortcut. 3381 * 3382 * @param userState The accessibility user state. 3383 * @param service The unbound service. 3384 */ removeShortcutTargetForUnboundServiceLocked(AccessibilityUserState userState, AccessibilityServiceConnection service)3385 private void removeShortcutTargetForUnboundServiceLocked(AccessibilityUserState userState, 3386 AccessibilityServiceConnection service) { 3387 if (!service.mRequestAccessibilityButton 3388 || service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo 3389 .targetSdkVersion <= Build.VERSION_CODES.Q) { 3390 return; 3391 } 3392 final ComponentName serviceName = service.getComponentName(); 3393 if (userState.removeShortcutTargetLocked(ACCESSIBILITY_SHORTCUT_KEY, serviceName)) { 3394 final Set<String> currentTargets = userState.getShortcutTargetsLocked( 3395 ACCESSIBILITY_SHORTCUT_KEY); 3396 persistColonDelimitedSetToSettingLocked( 3397 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, 3398 userState.mUserId, currentTargets, str -> str); 3399 } 3400 if (userState.removeShortcutTargetLocked(ACCESSIBILITY_BUTTON, serviceName)) { 3401 final Set<String> currentTargets = userState.getShortcutTargetsLocked( 3402 ACCESSIBILITY_BUTTON); 3403 persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, 3404 userState.mUserId, currentTargets, str -> str); 3405 } 3406 } 3407 updateRecommendedUiTimeoutLocked(AccessibilityUserState userState)3408 private void updateRecommendedUiTimeoutLocked(AccessibilityUserState userState) { 3409 int newNonInteractiveUiTimeout = userState.getUserNonInteractiveUiTimeoutLocked(); 3410 int newInteractiveUiTimeout = userState.getUserInteractiveUiTimeoutLocked(); 3411 // read from a11y services if user does not specify value 3412 if (newNonInteractiveUiTimeout == 0 || newInteractiveUiTimeout == 0) { 3413 int serviceNonInteractiveUiTimeout = 0; 3414 int serviceInteractiveUiTimeout = 0; 3415 final List<AccessibilityServiceConnection> services = userState.mBoundServices; 3416 for (int i = 0; i < services.size(); i++) { 3417 int timeout = services.get(i).getServiceInfo().getInteractiveUiTimeoutMillis(); 3418 if (serviceInteractiveUiTimeout < timeout) { 3419 serviceInteractiveUiTimeout = timeout; 3420 } 3421 timeout = services.get(i).getServiceInfo().getNonInteractiveUiTimeoutMillis(); 3422 if (serviceNonInteractiveUiTimeout < timeout) { 3423 serviceNonInteractiveUiTimeout = timeout; 3424 } 3425 } 3426 if (newNonInteractiveUiTimeout == 0) { 3427 newNonInteractiveUiTimeout = serviceNonInteractiveUiTimeout; 3428 } 3429 if (newInteractiveUiTimeout == 0) { 3430 newInteractiveUiTimeout = serviceInteractiveUiTimeout; 3431 } 3432 } 3433 userState.setNonInteractiveUiTimeoutLocked(newNonInteractiveUiTimeout); 3434 userState.setInteractiveUiTimeoutLocked(newInteractiveUiTimeout); 3435 } 3436 3437 @Override getKeyEventDispatcher()3438 public KeyEventDispatcher getKeyEventDispatcher() { 3439 if (mKeyEventDispatcher == null) { 3440 mKeyEventDispatcher = new KeyEventDispatcher( 3441 mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock, 3442 mPowerManager); 3443 } 3444 return mKeyEventDispatcher; 3445 } 3446 3447 @Override 3448 @SuppressWarnings("AndroidFrameworkPendingIntentMutability") getPendingIntentActivity(Context context, int requestCode, Intent intent, int flags)3449 public PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent, 3450 int flags) { 3451 return PendingIntent.getActivity(context, requestCode, intent, flags); 3452 } 3453 3454 /** 3455 * AIDL-exposed method to be called when the accessibility shortcut key is enabled. Requires 3456 * permission to write secure settings, since someone with that permission can enable 3457 * accessibility services themselves. 3458 * 3459 * @param targetName The flattened {@link ComponentName} string or the class name of a system 3460 * class implementing a supported accessibility feature, or {@code null} if there's no 3461 * specified target. 3462 */ 3463 @Override performAccessibilityShortcut(String targetName)3464 public void performAccessibilityShortcut(String targetName) { 3465 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3466 mTraceManager.logTrace(LOG_TAG + ".performAccessibilityShortcut", 3467 FLAGS_ACCESSIBILITY_MANAGER, "targetName=" + targetName); 3468 } 3469 3470 if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) 3471 && (mContext.checkCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY) 3472 != PackageManager.PERMISSION_GRANTED)) { 3473 throw new SecurityException( 3474 "performAccessibilityShortcut requires the MANAGE_ACCESSIBILITY permission"); 3475 } 3476 mMainHandler.sendMessage(obtainMessage( 3477 AccessibilityManagerService::performAccessibilityShortcutInternal, this, 3478 Display.DEFAULT_DISPLAY, ACCESSIBILITY_SHORTCUT_KEY, targetName)); 3479 } 3480 3481 /** 3482 * Perform the accessibility shortcut action. 3483 * 3484 * @param shortcutType The shortcut type. 3485 * @param displayId The display id of the accessibility button. 3486 * @param targetName The flattened {@link ComponentName} string or the class name of a system 3487 * class implementing a supported accessibility feature, or {@code null} if there's no 3488 * specified target. 3489 */ performAccessibilityShortcutInternal(int displayId, @ShortcutType int shortcutType, @Nullable String targetName)3490 private void performAccessibilityShortcutInternal(int displayId, 3491 @ShortcutType int shortcutType, @Nullable String targetName) { 3492 final List<String> shortcutTargets = getAccessibilityShortcutTargetsInternal(shortcutType); 3493 if (shortcutTargets.isEmpty()) { 3494 Slog.d(LOG_TAG, "No target to perform shortcut, shortcutType=" + shortcutType); 3495 return; 3496 } 3497 // In case the caller specified a target name 3498 if (targetName != null && !doesShortcutTargetsStringContain(shortcutTargets, targetName)) { 3499 Slog.v(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName); 3500 targetName = null; 3501 } 3502 if (targetName == null) { 3503 // In case there are many targets assigned to the given shortcut. 3504 if (shortcutTargets.size() > 1) { 3505 showAccessibilityTargetsSelection(displayId, shortcutType); 3506 return; 3507 } 3508 targetName = shortcutTargets.get(0); 3509 } 3510 // In case user assigned magnification to the given shortcut. 3511 if (targetName.equals(MAGNIFICATION_CONTROLLER_NAME)) { 3512 final boolean enabled = 3513 !getMagnificationController().getFullScreenMagnificationController() 3514 .isActivated(displayId); 3515 logAccessibilityShortcutActivated(mContext, MAGNIFICATION_COMPONENT_NAME, shortcutType, 3516 enabled); 3517 sendAccessibilityButtonToInputFilter(displayId); 3518 return; 3519 } 3520 final ComponentName targetComponentName = ComponentName.unflattenFromString(targetName); 3521 if (targetComponentName == null) { 3522 Slog.d(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName); 3523 return; 3524 } 3525 // In case user assigned an accessibility framework feature to the given shortcut. 3526 if (performAccessibilityFrameworkFeature(displayId, targetComponentName, shortcutType)) { 3527 return; 3528 } 3529 // In case user assigned an accessibility shortcut target to the given shortcut. 3530 if (performAccessibilityShortcutTargetActivity(displayId, targetComponentName)) { 3531 logAccessibilityShortcutActivated(mContext, targetComponentName, shortcutType); 3532 return; 3533 } 3534 // in case user assigned an accessibility service to the given shortcut. 3535 if (performAccessibilityShortcutTargetService( 3536 displayId, shortcutType, targetComponentName)) { 3537 return; 3538 } 3539 } 3540 performAccessibilityFrameworkFeature(int displayId, ComponentName assignedTarget, @ShortcutType int shortcutType)3541 private boolean performAccessibilityFrameworkFeature(int displayId, 3542 ComponentName assignedTarget, @ShortcutType int shortcutType) { 3543 final Map<ComponentName, FrameworkFeatureInfo> frameworkFeatureMap = 3544 AccessibilityShortcutController.getFrameworkShortcutFeaturesMap(); 3545 if (!frameworkFeatureMap.containsKey(assignedTarget)) { 3546 return false; 3547 } 3548 final FrameworkFeatureInfo featureInfo = frameworkFeatureMap.get(assignedTarget); 3549 final SettingStringHelper setting = new SettingStringHelper(mContext.getContentResolver(), 3550 featureInfo.getSettingKey(), mCurrentUserId); 3551 3552 if (featureInfo instanceof LaunchableFrameworkFeatureInfo) { 3553 logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType, 3554 /* serviceEnabled= */ true); 3555 launchAccessibilityFrameworkFeature(displayId, assignedTarget); 3556 return true; 3557 } 3558 3559 // Assuming that the default state will be to have the feature off 3560 if (!TextUtils.equals(featureInfo.getSettingOnValue(), setting.read())) { 3561 logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType, 3562 /* serviceEnabled= */ true); 3563 setting.write(featureInfo.getSettingOnValue()); 3564 } else { 3565 logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType, 3566 /* serviceEnabled= */ false); 3567 setting.write(featureInfo.getSettingOffValue()); 3568 } 3569 return true; 3570 } 3571 performAccessibilityShortcutTargetActivity(int displayId, ComponentName assignedTarget)3572 private boolean performAccessibilityShortcutTargetActivity(int displayId, 3573 ComponentName assignedTarget) { 3574 synchronized (mLock) { 3575 final AccessibilityUserState userState = getCurrentUserStateLocked(); 3576 for (int i = 0; i < userState.mInstalledShortcuts.size(); i++) { 3577 final AccessibilityShortcutInfo shortcutInfo = userState.mInstalledShortcuts.get(i); 3578 if (!shortcutInfo.getComponentName().equals(assignedTarget)) { 3579 continue; 3580 } 3581 launchShortcutTargetActivity(displayId, assignedTarget); 3582 return true; 3583 } 3584 } 3585 return false; 3586 } 3587 3588 /** 3589 * Perform accessibility service shortcut action. 3590 * 3591 * 1) For {@link AccessibilityManager#ACCESSIBILITY_BUTTON} type and services targeting sdk 3592 * version <= Q: callbacks to accessibility service if service is bounded and requests 3593 * accessibility button. 3594 * 2) For {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY} type and service targeting sdk 3595 * version <= Q: turns on / off the accessibility service. 3596 * 3) For {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY} type and service targeting sdk 3597 * version > Q and request accessibility button: turn on the accessibility service if it's 3598 * not in the enabled state. 3599 * (It'll happen when a service is disabled and assigned to shortcut then upgraded.) 3600 * 4) For services targeting sdk version > Q: 3601 * a) Turns on / off the accessibility service, if service does not request accessibility 3602 * button. 3603 * b) Callbacks to accessibility service if service is bounded and requests accessibility 3604 * button. 3605 */ performAccessibilityShortcutTargetService(int displayId, @ShortcutType int shortcutType, ComponentName assignedTarget)3606 private boolean performAccessibilityShortcutTargetService(int displayId, 3607 @ShortcutType int shortcutType, ComponentName assignedTarget) { 3608 synchronized (mLock) { 3609 final AccessibilityUserState userState = getCurrentUserStateLocked(); 3610 final AccessibilityServiceInfo installedServiceInfo = 3611 userState.getInstalledServiceInfoLocked(assignedTarget); 3612 if (installedServiceInfo == null) { 3613 Slog.d(LOG_TAG, "Perform shortcut failed, invalid component name:" 3614 + assignedTarget); 3615 return false; 3616 } 3617 3618 final AccessibilityServiceConnection serviceConnection = 3619 userState.getServiceConnectionLocked(assignedTarget); 3620 final int targetSdk = installedServiceInfo.getResolveInfo() 3621 .serviceInfo.applicationInfo.targetSdkVersion; 3622 final boolean requestA11yButton = (installedServiceInfo.flags 3623 & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; 3624 // Turns on / off the accessibility service 3625 if ((targetSdk <= Build.VERSION_CODES.Q && shortcutType == ACCESSIBILITY_SHORTCUT_KEY) 3626 || (targetSdk > Build.VERSION_CODES.Q && !requestA11yButton)) { 3627 if (serviceConnection == null) { 3628 logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType, 3629 /* serviceEnabled= */ true); 3630 enableAccessibilityServiceLocked(assignedTarget, mCurrentUserId); 3631 3632 } else { 3633 logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType, 3634 /* serviceEnabled= */ false); 3635 disableAccessibilityServiceLocked(assignedTarget, mCurrentUserId); 3636 } 3637 return true; 3638 } 3639 if (shortcutType == ACCESSIBILITY_SHORTCUT_KEY && targetSdk > Build.VERSION_CODES.Q 3640 && requestA11yButton) { 3641 if (!userState.getEnabledServicesLocked().contains(assignedTarget)) { 3642 enableAccessibilityServiceLocked(assignedTarget, mCurrentUserId); 3643 return true; 3644 } 3645 } 3646 // Callbacks to a11y service if it's bounded and requests a11y button. 3647 if (serviceConnection == null 3648 || !userState.mBoundServices.contains(serviceConnection) 3649 || !serviceConnection.mRequestAccessibilityButton) { 3650 Slog.d(LOG_TAG, "Perform shortcut failed, service is not ready:" 3651 + assignedTarget); 3652 return false; 3653 } 3654 // ServiceConnection means service enabled. 3655 logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType, 3656 /* serviceEnabled= */ true); 3657 serviceConnection.notifyAccessibilityButtonClickedLocked(displayId); 3658 return true; 3659 } 3660 } 3661 launchAccessibilityFrameworkFeature(int displayId, ComponentName assignedTarget)3662 private void launchAccessibilityFrameworkFeature(int displayId, ComponentName assignedTarget) { 3663 if (assignedTarget.equals(ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME)) { 3664 launchAccessibilitySubSettings(displayId, ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME); 3665 } 3666 } 3667 3668 @Override getAccessibilityShortcutTargets(@hortcutType int shortcutType)3669 public List<String> getAccessibilityShortcutTargets(@ShortcutType int shortcutType) { 3670 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3671 mTraceManager.logTrace(LOG_TAG + ".getAccessibilityShortcutTargets", 3672 FLAGS_ACCESSIBILITY_MANAGER, "shortcutType=" + shortcutType); 3673 } 3674 3675 if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY) 3676 != PackageManager.PERMISSION_GRANTED) { 3677 throw new SecurityException( 3678 "getAccessibilityShortcutService requires the MANAGE_ACCESSIBILITY permission"); 3679 } 3680 return getAccessibilityShortcutTargetsInternal(shortcutType); 3681 } 3682 getAccessibilityShortcutTargetsInternal(@hortcutType int shortcutType)3683 private List<String> getAccessibilityShortcutTargetsInternal(@ShortcutType int shortcutType) { 3684 synchronized (mLock) { 3685 final AccessibilityUserState userState = getCurrentUserStateLocked(); 3686 final ArrayList<String> shortcutTargets = new ArrayList<>( 3687 userState.getShortcutTargetsLocked(shortcutType)); 3688 if (shortcutType != ACCESSIBILITY_BUTTON) { 3689 return shortcutTargets; 3690 } 3691 // Adds legacy a11y services requesting a11y button into the list. 3692 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 3693 final AccessibilityServiceConnection service = userState.mBoundServices.get(i); 3694 if (!service.mRequestAccessibilityButton 3695 || service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo 3696 .targetSdkVersion > Build.VERSION_CODES.Q) { 3697 continue; 3698 } 3699 final String serviceName = service.getComponentName().flattenToString(); 3700 if (!TextUtils.isEmpty(serviceName)) { 3701 shortcutTargets.add(serviceName); 3702 } 3703 } 3704 return shortcutTargets; 3705 } 3706 } 3707 3708 /** 3709 * Enables accessibility service specified by {@param componentName} for the {@param userId}. 3710 */ enableAccessibilityServiceLocked(ComponentName componentName, int userId)3711 private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) { 3712 mTempComponentNameSet.clear(); 3713 readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 3714 userId, mTempComponentNameSet); 3715 mTempComponentNameSet.add(componentName); 3716 persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 3717 mTempComponentNameSet, userId); 3718 3719 AccessibilityUserState userState = getUserStateLocked(userId); 3720 if (userState.mEnabledServices.add(componentName)) { 3721 onUserStateChangedLocked(userState); 3722 } 3723 } 3724 3725 /** 3726 * Disables accessibility service specified by {@param componentName} for the {@param userId}. 3727 */ disableAccessibilityServiceLocked(ComponentName componentName, int userId)3728 private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) { 3729 mTempComponentNameSet.clear(); 3730 readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 3731 userId, mTempComponentNameSet); 3732 mTempComponentNameSet.remove(componentName); 3733 persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 3734 mTempComponentNameSet, userId); 3735 3736 AccessibilityUserState userState = getUserStateLocked(userId); 3737 if (userState.mEnabledServices.remove(componentName)) { 3738 onUserStateChangedLocked(userState); 3739 } 3740 } 3741 3742 @Override sendAccessibilityEventForCurrentUserLocked(AccessibilityEvent event)3743 public void sendAccessibilityEventForCurrentUserLocked(AccessibilityEvent event) { 3744 if (event.getWindowChanges() == AccessibilityEvent.WINDOWS_CHANGE_ADDED) { 3745 // We need to ensure the window is available before sending pending 3746 // window_state_changed events. 3747 sendPendingWindowStateChangedEventsForAvailableWindowLocked(event.getWindowId()); 3748 } 3749 sendAccessibilityEventLocked(event, mCurrentUserId); 3750 } 3751 sendAccessibilityEventLocked(AccessibilityEvent event, int userId)3752 private void sendAccessibilityEventLocked(AccessibilityEvent event, int userId) { 3753 // Resync to avoid calling out with the lock held 3754 event.setEventTime(SystemClock.uptimeMillis()); 3755 mMainHandler.sendMessage(obtainMessage( 3756 AccessibilityManagerService::sendAccessibilityEvent, 3757 this, event, userId)); 3758 } 3759 3760 /** 3761 * AIDL-exposed method. System only. 3762 * Inform accessibility that a fingerprint gesture was performed 3763 * 3764 * @param gestureKeyCode The key code corresponding to the fingerprint gesture. 3765 * @return {@code true} if accessibility consumes the fingerprint gesture, {@code false} if it 3766 * doesn't. 3767 */ 3768 @Override sendFingerprintGesture(int gestureKeyCode)3769 public boolean sendFingerprintGesture(int gestureKeyCode) { 3770 if (mTraceManager.isA11yTracingEnabledForTypes( 3771 FLAGS_ACCESSIBILITY_MANAGER | FLAGS_FINGERPRINT)) { 3772 mTraceManager.logTrace(LOG_TAG + ".sendFingerprintGesture", 3773 FLAGS_ACCESSIBILITY_MANAGER | FLAGS_FINGERPRINT, 3774 "gestureKeyCode=" + gestureKeyCode); 3775 } 3776 3777 synchronized(mLock) { 3778 if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) { 3779 throw new SecurityException("Only SYSTEM can call sendFingerprintGesture"); 3780 } 3781 } 3782 if (mFingerprintGestureDispatcher == null) { 3783 return false; 3784 } 3785 return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode); 3786 } 3787 3788 /** 3789 * AIDL-exposed method. System only. 3790 * Gets accessibility window id from window token. 3791 * 3792 * @param windowToken Window token to get accessibility window id. 3793 * @return Accessibility window id for the window token. Returns -1 if no such token is 3794 * registered. 3795 */ 3796 @Override getAccessibilityWindowId(@ullable IBinder windowToken)3797 public int getAccessibilityWindowId(@Nullable IBinder windowToken) { 3798 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3799 mTraceManager.logTrace(LOG_TAG + ".getAccessibilityWindowId", 3800 FLAGS_ACCESSIBILITY_MANAGER, "windowToken=" + windowToken); 3801 } 3802 3803 synchronized (mLock) { 3804 if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) { 3805 throw new SecurityException("Only SYSTEM can call getAccessibilityWindowId"); 3806 } 3807 3808 return mA11yWindowManager.findWindowIdLocked(mCurrentUserId, windowToken); 3809 } 3810 } 3811 3812 /** 3813 * Get the recommended timeout of interactive controls and non-interactive controls. 3814 * 3815 * @return A long for pair of {@code int}s. First integer for interactive one, and second 3816 * integer for non-interactive one. 3817 */ 3818 @Override getRecommendedTimeoutMillis()3819 public long getRecommendedTimeoutMillis() { 3820 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3821 mTraceManager.logTrace( 3822 LOG_TAG + ".getRecommendedTimeoutMillis", FLAGS_ACCESSIBILITY_MANAGER); 3823 } 3824 3825 synchronized(mLock) { 3826 final int deviceId = mProxyManager.getFirstDeviceIdForUidLocked( 3827 Binder.getCallingUid()); 3828 if (mProxyManager.isProxyedDeviceId(deviceId)) { 3829 return mProxyManager.getRecommendedTimeoutMillisLocked(deviceId); 3830 } else { 3831 final AccessibilityUserState userState = getCurrentUserStateLocked(); 3832 return getRecommendedTimeoutMillisLocked(userState); 3833 } 3834 } 3835 } 3836 getRecommendedTimeoutMillisLocked(AccessibilityUserState userState)3837 private long getRecommendedTimeoutMillisLocked(AccessibilityUserState userState) { 3838 return IntPair.of(userState.getInteractiveUiTimeoutLocked(), 3839 userState.getNonInteractiveUiTimeoutLocked()); 3840 } 3841 3842 @Override setWindowMagnificationConnection( IWindowMagnificationConnection connection)3843 public void setWindowMagnificationConnection( 3844 IWindowMagnificationConnection connection) throws RemoteException { 3845 if (mTraceManager.isA11yTracingEnabledForTypes( 3846 FLAGS_ACCESSIBILITY_MANAGER | FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) { 3847 mTraceManager.logTrace(LOG_TAG + ".setWindowMagnificationConnection", 3848 FLAGS_ACCESSIBILITY_MANAGER | FLAGS_WINDOW_MAGNIFICATION_CONNECTION, 3849 "connection=" + connection); 3850 } 3851 3852 mSecurityPolicy.enforceCallingOrSelfPermission( 3853 android.Manifest.permission.STATUS_BAR_SERVICE); 3854 3855 getWindowMagnificationMgr().setConnection(connection); 3856 } 3857 3858 /** 3859 * Getter of {@link WindowMagnificationManager}. 3860 * 3861 * @return WindowMagnificationManager 3862 */ getWindowMagnificationMgr()3863 public WindowMagnificationManager getWindowMagnificationMgr() { 3864 synchronized (mLock) { 3865 return mMagnificationController.getWindowMagnificationMgr(); 3866 } 3867 } 3868 3869 /** 3870 * Getter of {@link MagnificationController}. 3871 * 3872 * @return MagnificationController 3873 */ getMagnificationController()3874 MagnificationController getMagnificationController() { 3875 return mMagnificationController; 3876 } 3877 3878 @Override associateEmbeddedHierarchy(@onNull IBinder host, @NonNull IBinder embedded)3879 public void associateEmbeddedHierarchy(@NonNull IBinder host, @NonNull IBinder embedded) { 3880 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3881 mTraceManager.logTrace(LOG_TAG + ".associateEmbeddedHierarchy", 3882 FLAGS_ACCESSIBILITY_MANAGER, "host=" + host + ";embedded=" + embedded); 3883 } 3884 3885 synchronized (mLock) { 3886 mA11yWindowManager.associateEmbeddedHierarchyLocked(host, embedded); 3887 } 3888 } 3889 3890 @Override disassociateEmbeddedHierarchy(@onNull IBinder token)3891 public void disassociateEmbeddedHierarchy(@NonNull IBinder token) { 3892 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3893 mTraceManager.logTrace(LOG_TAG + ".disassociateEmbeddedHierarchy", 3894 FLAGS_ACCESSIBILITY_MANAGER, "token=" + token); 3895 } 3896 3897 synchronized (mLock) { 3898 mA11yWindowManager.disassociateEmbeddedHierarchyLocked(token); 3899 } 3900 } 3901 3902 /** 3903 * Gets the stroke width of the focus rectangle. 3904 * @return The stroke width. 3905 */ 3906 @Override getFocusStrokeWidth()3907 public int getFocusStrokeWidth() { 3908 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3909 mTraceManager.logTrace(LOG_TAG + ".getFocusStrokeWidth", FLAGS_ACCESSIBILITY_MANAGER); 3910 } 3911 synchronized (mLock) { 3912 final int deviceId = mProxyManager.getFirstDeviceIdForUidLocked( 3913 Binder.getCallingUid()); 3914 if (mProxyManager.isProxyedDeviceId(deviceId)) { 3915 return mProxyManager.getFocusStrokeWidthLocked(deviceId); 3916 } 3917 final AccessibilityUserState userState = getCurrentUserStateLocked(); 3918 3919 return userState.getFocusStrokeWidthLocked(); 3920 } 3921 } 3922 3923 /** 3924 * Gets the color of the focus rectangle. 3925 * @return The color. 3926 */ 3927 @Override getFocusColor()3928 public int getFocusColor() { 3929 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3930 mTraceManager.logTrace(LOG_TAG + ".getFocusColor", FLAGS_ACCESSIBILITY_MANAGER); 3931 } 3932 synchronized (mLock) { 3933 final int deviceId = mProxyManager.getFirstDeviceIdForUidLocked( 3934 Binder.getCallingUid()); 3935 if (mProxyManager.isProxyedDeviceId(deviceId)) { 3936 return mProxyManager.getFocusColorLocked(deviceId); 3937 } 3938 final AccessibilityUserState userState = getCurrentUserStateLocked(); 3939 3940 return userState.getFocusColorLocked(); 3941 } 3942 } 3943 3944 /** 3945 * Gets the status of the audio description preference. 3946 * @return {@code true} if the audio description is enabled, {@code false} otherwise. 3947 */ 3948 @Override isAudioDescriptionByDefaultEnabled()3949 public boolean isAudioDescriptionByDefaultEnabled() { 3950 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3951 mTraceManager.logTrace(LOG_TAG + ".isAudioDescriptionByDefaultEnabled", 3952 FLAGS_ACCESSIBILITY_MANAGER); 3953 } 3954 synchronized (mLock) { 3955 final AccessibilityUserState userState = getCurrentUserStateLocked(); 3956 3957 return userState.isAudioDescriptionByDefaultEnabledLocked(); 3958 } 3959 } 3960 3961 /** 3962 * Sets the {@link AccessibilityWindowAttributes} to the window associated with the given 3963 * window id. 3964 * 3965 * @param displayId The display id of the window. 3966 * @param windowId The id of the window 3967 * @param userId The user id. 3968 * @param attributes The accessibility window attributes. 3969 */ 3970 @Override setAccessibilityWindowAttributes(int displayId, int windowId, int userId, AccessibilityWindowAttributes attributes)3971 public void setAccessibilityWindowAttributes(int displayId, int windowId, int userId, 3972 AccessibilityWindowAttributes attributes) { 3973 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) { 3974 mTraceManager.logTrace(LOG_TAG + ".setAccessibilityWindowAttributes", 3975 FLAGS_ACCESSIBILITY_MANAGER); 3976 } 3977 mA11yWindowManager.setAccessibilityWindowAttributes(displayId, windowId, userId, 3978 attributes); 3979 } 3980 3981 @Override 3982 @RequiresPermission(Manifest.permission.SET_SYSTEM_AUDIO_CAPTION) setSystemAudioCaptioningEnabled(boolean isEnabled, int userId)3983 public void setSystemAudioCaptioningEnabled(boolean isEnabled, int userId) { 3984 mContext.enforceCallingOrSelfPermission( 3985 Manifest.permission.SET_SYSTEM_AUDIO_CAPTION, 3986 "setSystemAudioCaptioningEnabled"); 3987 3988 mCaptioningManagerImpl.setSystemAudioCaptioningEnabled(isEnabled, userId); 3989 } 3990 3991 @Override isSystemAudioCaptioningUiEnabled(int userId)3992 public boolean isSystemAudioCaptioningUiEnabled(int userId) { 3993 return mCaptioningManagerImpl.isSystemAudioCaptioningUiEnabled(userId); 3994 } 3995 3996 @Override 3997 @RequiresPermission(Manifest.permission.SET_SYSTEM_AUDIO_CAPTION) setSystemAudioCaptioningUiEnabled(boolean isEnabled, int userId)3998 public void setSystemAudioCaptioningUiEnabled(boolean isEnabled, int userId) { 3999 mContext.enforceCallingOrSelfPermission( 4000 Manifest.permission.SET_SYSTEM_AUDIO_CAPTION, 4001 "setSystemAudioCaptioningUiEnabled"); 4002 4003 mCaptioningManagerImpl.setSystemAudioCaptioningUiEnabled(isEnabled, userId); 4004 } 4005 4006 @Override registerProxyForDisplay(IAccessibilityServiceClient client, int displayId)4007 public boolean registerProxyForDisplay(IAccessibilityServiceClient client, int displayId) 4008 throws RemoteException { 4009 mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE); 4010 mSecurityPolicy.checkForAccessibilityPermissionOrRole(); 4011 if (client == null) { 4012 return false; 4013 } 4014 if (displayId < 0) { 4015 throw new IllegalArgumentException("The display id " + displayId + " is invalid."); 4016 } 4017 if (!isTrackedDisplay(displayId)) { 4018 throw new IllegalArgumentException("The display " + displayId + " does not exist or is" 4019 + " not tracked by accessibility."); 4020 } 4021 if (mProxyManager.isProxyedDisplay(displayId)) { 4022 throw new IllegalArgumentException("The display " + displayId + " is already being" 4023 + " proxy-ed"); 4024 } 4025 if (!mProxyManager.displayBelongsToCaller(Binder.getCallingUid(), displayId)) { 4026 throw new SecurityException("The display " + displayId + " does not belong to" 4027 + " the caller."); 4028 } 4029 4030 final long identity = Binder.clearCallingIdentity(); 4031 try { 4032 mProxyManager.registerProxy(client, displayId, sIdCounter++, mSecurityPolicy, 4033 this, getTraceManager(), mWindowManagerService); 4034 4035 synchronized (mLock) { 4036 notifyClearAccessibilityCacheLocked(); 4037 } 4038 } finally { 4039 Binder.restoreCallingIdentity(identity); 4040 } 4041 return true; 4042 } 4043 4044 @Override unregisterProxyForDisplay(int displayId)4045 public boolean unregisterProxyForDisplay(int displayId) { 4046 mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE); 4047 mSecurityPolicy.checkForAccessibilityPermissionOrRole(); 4048 final long identity = Binder.clearCallingIdentity(); 4049 try { 4050 return mProxyManager.unregisterProxy(displayId); 4051 } finally { 4052 Binder.restoreCallingIdentity(identity); 4053 } 4054 } 4055 isDisplayProxyed(int displayId)4056 boolean isDisplayProxyed(int displayId) { 4057 return mProxyManager.isProxyedDisplay(displayId); 4058 } 4059 4060 @Override startFlashNotificationSequence(String opPkg, @FlashNotificationReason int reason, IBinder token)4061 public boolean startFlashNotificationSequence(String opPkg, 4062 @FlashNotificationReason int reason, IBinder token) { 4063 final long identity = Binder.clearCallingIdentity(); 4064 try { 4065 return mFlashNotificationsController.startFlashNotificationSequence(opPkg, 4066 reason, token); 4067 } finally { 4068 Binder.restoreCallingIdentity(identity); 4069 } 4070 } 4071 4072 @Override stopFlashNotificationSequence(String opPkg)4073 public boolean stopFlashNotificationSequence(String opPkg) { 4074 final long identity = Binder.clearCallingIdentity(); 4075 try { 4076 return mFlashNotificationsController.stopFlashNotificationSequence(opPkg); 4077 } finally { 4078 Binder.restoreCallingIdentity(identity); 4079 } 4080 } 4081 4082 @Override startFlashNotificationEvent(String opPkg, @FlashNotificationReason int reason, String reasonPkg)4083 public boolean startFlashNotificationEvent(String opPkg, 4084 @FlashNotificationReason int reason, String reasonPkg) { 4085 final long identity = Binder.clearCallingIdentity(); 4086 try { 4087 return mFlashNotificationsController.startFlashNotificationEvent(opPkg, 4088 reason, reasonPkg); 4089 } finally { 4090 Binder.restoreCallingIdentity(identity); 4091 } 4092 } 4093 4094 @Override isAccessibilityTargetAllowed(String packageName, int uid, int userId)4095 public boolean isAccessibilityTargetAllowed(String packageName, int uid, int userId) { 4096 final long identity = Binder.clearCallingIdentity(); 4097 try { 4098 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); 4099 final List<String> permittedServices = dpm.getPermittedAccessibilityServices(userId); 4100 4101 // permittedServices null means all accessibility services are allowed. 4102 boolean allowed = permittedServices == null || permittedServices.contains(packageName); 4103 if (allowed) { 4104 final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); 4105 final int mode = appOps.noteOpNoThrow( 4106 AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, 4107 uid, packageName, /* attributionTag= */ null, /* message= */ null); 4108 final boolean ecmEnabled = mContext.getResources().getBoolean( 4109 R.bool.config_enhancedConfirmationModeEnabled); 4110 return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED; 4111 } 4112 return false; 4113 } finally { 4114 Binder.restoreCallingIdentity(identity); 4115 } 4116 } 4117 4118 @Override sendRestrictedDialogIntent(String packageName, int uid, int userId)4119 public boolean sendRestrictedDialogIntent(String packageName, int uid, int userId) { 4120 // The accessibility service is allowed. Don't show the restricted dialog. 4121 if (isAccessibilityTargetAllowed(packageName, uid, userId)) { 4122 return false; 4123 } 4124 4125 final EnforcedAdmin admin = 4126 RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed( 4127 mContext, packageName, userId); 4128 if (admin != null) { 4129 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, admin); 4130 return true; 4131 } 4132 4133 RestrictedLockUtils.sendShowRestrictedSettingDialogIntent(mContext, 4134 packageName, uid); 4135 return true; 4136 } 4137 4138 @Override dump(FileDescriptor fd, final PrintWriter pw, String[] args)4139 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 4140 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 4141 synchronized (mLock) { 4142 pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)"); 4143 pw.println(); 4144 pw.append("currentUserId=").append(String.valueOf(mCurrentUserId)); 4145 if (mRealCurrentUserId != UserHandle.USER_CURRENT 4146 && mCurrentUserId != mRealCurrentUserId) { 4147 pw.append(" (set for UiAutomation purposes; \"real\" current user is ") 4148 .append(String.valueOf(mRealCurrentUserId)).append(")"); 4149 } 4150 pw.println(); 4151 if (mVisibleBgUserIds != null) { 4152 pw.append("visibleBgUserIds=").append(mVisibleBgUserIds.toString()); 4153 pw.println(); 4154 } 4155 pw.append("hasWindowMagnificationConnection=").append( 4156 String.valueOf(getWindowMagnificationMgr().isConnected())); 4157 pw.println(); 4158 mMagnificationProcessor.dump(pw, getValidDisplayList()); 4159 final int userCount = mUserStates.size(); 4160 for (int i = 0; i < userCount; i++) { 4161 mUserStates.valueAt(i).dump(fd, pw, args); 4162 } 4163 if (mUiAutomationManager.isUiAutomationRunningLocked()) { 4164 mUiAutomationManager.dumpUiAutomationService(fd, pw, args); 4165 pw.println(); 4166 } 4167 mA11yWindowManager.dump(fd, pw, args); 4168 if (mHasInputFilter && mInputFilter != null) { 4169 mInputFilter.dump(fd, pw, args); 4170 } 4171 pw.println("Global client list info:{"); 4172 mGlobalClients.dump(pw, " Client list "); 4173 pw.println(" Registered clients:{"); 4174 for (int i = 0; i < mGlobalClients.getRegisteredCallbackCount(); i++) { 4175 AccessibilityManagerService.Client client = (AccessibilityManagerService.Client) 4176 mGlobalClients.getRegisteredCallbackCookie(i); 4177 pw.append(Arrays.toString(client.mPackageNames)); 4178 } 4179 pw.println(); 4180 mProxyManager.dump(fd, pw, args); 4181 mA11yDisplayListener.dump(fd, pw, args); 4182 } 4183 } 4184 4185 //TODO remove after refactoring KeyEventDispatcherTest 4186 final class MainHandler extends Handler { 4187 public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8; 4188 MainHandler(Looper looper)4189 public MainHandler(Looper looper) { 4190 super(looper); 4191 } 4192 4193 @Override handleMessage(Message msg)4194 public void handleMessage(Message msg) { 4195 if (msg.what == MSG_SEND_KEY_EVENT_TO_INPUT_FILTER) { 4196 KeyEvent event = (KeyEvent) msg.obj; 4197 final int policyFlags = msg.arg1; 4198 synchronized (mLock) { 4199 if (mHasInputFilter && mInputFilter != null) { 4200 mInputFilter.sendInputEvent(event, policyFlags); 4201 } 4202 } 4203 event.recycle(); 4204 } 4205 } 4206 } 4207 4208 @Override getMagnificationProcessor()4209 public MagnificationProcessor getMagnificationProcessor() { 4210 return mMagnificationProcessor; 4211 } 4212 4213 @Override onClientChangeLocked(boolean serviceInfoChanged)4214 public void onClientChangeLocked(boolean serviceInfoChanged) { 4215 onClientChangeLocked(serviceInfoChanged, false); 4216 } 4217 4218 /** 4219 * Called when the state of a service or proxy has changed 4220 * @param serviceInfoChanged if the service info has changed 4221 * @param forceUpdate whether to force an update of state for app clients 4222 */ onClientChangeLocked(boolean serviceInfoChanged, boolean forceUpdate)4223 public void onClientChangeLocked(boolean serviceInfoChanged, boolean forceUpdate) { 4224 AccessibilityUserState userState = getUserStateLocked(mCurrentUserId); 4225 onUserStateChangedLocked(userState, forceUpdate); 4226 if (serviceInfoChanged) { 4227 scheduleNotifyClientsOfServicesStateChangeLocked(userState); 4228 } 4229 } 4230 4231 4232 @Override onProxyChanged(int deviceId)4233 public void onProxyChanged(int deviceId) { 4234 mProxyManager.onProxyChanged(deviceId); 4235 } 4236 4237 /** 4238 * Removes the device from tracking. This will reset any AccessibilityManagerClients to be 4239 * associated with the default user id. 4240 */ 4241 @Override removeDeviceIdLocked(int deviceId)4242 public void removeDeviceIdLocked(int deviceId) { 4243 resetClientsLocked(deviceId, getCurrentUserStateLocked().mUserClients); 4244 resetClientsLocked(deviceId, mGlobalClients); 4245 // Force an update of A11yManagers if the state was previously a proxy state and needs to be 4246 // returned to the default device state. 4247 onClientChangeLocked(true, true); 4248 } 4249 resetClientsLocked(int deviceId, RemoteCallbackList<IAccessibilityManagerClient> clients)4250 private void resetClientsLocked(int deviceId, 4251 RemoteCallbackList<IAccessibilityManagerClient> clients) { 4252 if (clients == null || clients.getRegisteredCallbackCount() == 0) { 4253 return; 4254 } 4255 synchronized (mLock) { 4256 for (int i = 0; i < clients.getRegisteredCallbackCount(); i++) { 4257 final Client appClient = ((Client) clients.getRegisteredCallbackCookie(i)); 4258 if (appClient.mDeviceId == deviceId) { 4259 appClient.mDeviceId = DEVICE_ID_DEFAULT; 4260 } 4261 } 4262 } 4263 } 4264 4265 @Override updateWindowsForAccessibilityCallbackLocked()4266 public void updateWindowsForAccessibilityCallbackLocked() { 4267 updateWindowsForAccessibilityCallbackLocked(getUserStateLocked(mCurrentUserId)); 4268 } 4269 4270 @Override getGlobalClientsLocked()4271 public RemoteCallbackList<IAccessibilityManagerClient> getGlobalClientsLocked() { 4272 return mGlobalClients; 4273 } 4274 4275 @Override getCurrentUserClientsLocked()4276 public RemoteCallbackList<IAccessibilityManagerClient> getCurrentUserClientsLocked() { 4277 return getCurrentUserState().mUserClients; 4278 } 4279 4280 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)4281 public void onShellCommand(FileDescriptor in, FileDescriptor out, 4282 FileDescriptor err, String[] args, ShellCallback callback, 4283 ResultReceiver resultReceiver) { 4284 new AccessibilityShellCommand(this, mSystemActionPerformer).exec(this, in, out, err, args, 4285 callback, resultReceiver); 4286 } 4287 4288 private final class InteractionBridge { 4289 private final ComponentName COMPONENT_NAME = 4290 new ComponentName("com.android.server.accessibility", "InteractionBridge"); 4291 4292 private final Display mDefaultDisplay; 4293 private final int mConnectionId; 4294 private final AccessibilityInteractionClient mClient; 4295 InteractionBridge()4296 public InteractionBridge() { 4297 final AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 4298 info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 4299 info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; 4300 info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 4301 info.setAccessibilityTool(true); 4302 final AccessibilityUserState userState; 4303 synchronized (mLock) { 4304 userState = getCurrentUserStateLocked(); 4305 } 4306 AccessibilityServiceConnection service = new AccessibilityServiceConnection( 4307 userState, mContext, 4308 COMPONENT_NAME, info, sIdCounter++, mMainHandler, mLock, mSecurityPolicy, 4309 AccessibilityManagerService.this, 4310 AccessibilityManagerService.this.getTraceManager(), mWindowManagerService, 4311 getSystemActionPerformer(), mA11yWindowManager, mActivityTaskManagerService) { 4312 @Override 4313 public boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) { 4314 return true; 4315 } 4316 }; 4317 4318 mConnectionId = service.mId; 4319 4320 mClient = AccessibilityInteractionClient.getInstance(mContext); 4321 mClient.addConnection(mConnectionId, service, /*initializeCache=*/false); 4322 4323 //TODO: (multi-display) We need to support multiple displays. 4324 DisplayManager displayManager = (DisplayManager) 4325 mContext.getSystemService(Context.DISPLAY_SERVICE); 4326 mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); 4327 } 4328 4329 /** 4330 * Gets a point within the accessibility focused node where we can send down and up events 4331 * to perform a click. 4332 * 4333 * @param outPoint The click point to populate. 4334 * @return Whether accessibility a click point was found and set. 4335 */ 4336 // TODO: (multi-display) Make sure this works for multiple displays. getAccessibilityFocusClickPointInScreen(Point outPoint)4337 boolean getAccessibilityFocusClickPointInScreen(Point outPoint) { 4338 return getInteractionBridge() 4339 .getAccessibilityFocusClickPointInScreenNotLocked(outPoint); 4340 } 4341 4342 /** 4343 * Perform an accessibility action on the view that currently has accessibility focus. 4344 * Has no effect if no item has accessibility focus, if the item with accessibility 4345 * focus does not expose the specified action, or if the action fails. 4346 * 4347 * @param action The action to perform. 4348 * 4349 * @return {@code true} if the action was performed. {@code false} if it was not. 4350 */ performActionOnAccessibilityFocusedItemNotLocked( AccessibilityNodeInfo.AccessibilityAction action)4351 public boolean performActionOnAccessibilityFocusedItemNotLocked( 4352 AccessibilityNodeInfo.AccessibilityAction action) { 4353 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(); 4354 if ((focus == null) || !focus.getActionList().contains(action)) { 4355 return false; 4356 } 4357 return focus.performAction(action.getId()); 4358 } 4359 getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint)4360 public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) { 4361 AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(); 4362 if (focus == null) { 4363 return false; 4364 } 4365 4366 synchronized (mLock) { 4367 Rect boundsInScreenBeforeMagnification = mTempRect; 4368 4369 focus.getBoundsInScreen(boundsInScreenBeforeMagnification); 4370 final Point nodeCenter = new Point(boundsInScreenBeforeMagnification.centerX(), 4371 boundsInScreenBeforeMagnification.centerY()); 4372 4373 // Invert magnification if needed. 4374 final Pair<float[], MagnificationSpec> pair = 4375 getWindowTransformationMatrixAndMagnificationSpec(focus.getWindowId()); 4376 MagnificationSpec spec = null; 4377 if (pair != null && pair.second != null) { 4378 spec = new MagnificationSpec(); 4379 spec.setTo(pair.second); 4380 } 4381 4382 if (spec != null && !spec.isNop()) { 4383 boundsInScreenBeforeMagnification.offset((int) -spec.offsetX, 4384 (int) -spec.offsetY); 4385 boundsInScreenBeforeMagnification.scale(1 / spec.scale); 4386 } 4387 4388 //Clip to the window bounds. 4389 Rect windowBounds = mTempRect1; 4390 getWindowBounds(focus.getWindowId(), windowBounds); 4391 if (!boundsInScreenBeforeMagnification.intersect(windowBounds)) { 4392 return false; 4393 } 4394 4395 //Clip to the screen bounds. 4396 Point screenSize = mTempPoint; 4397 mDefaultDisplay.getRealSize(screenSize); 4398 if (!boundsInScreenBeforeMagnification.intersect(0, 0, screenSize.x, 4399 screenSize.y)) { 4400 return false; 4401 } 4402 4403 outPoint.set(nodeCenter.x, nodeCenter.y); 4404 } 4405 4406 return true; 4407 } 4408 getAccessibilityFocusNotLocked()4409 private AccessibilityNodeInfo getAccessibilityFocusNotLocked() { 4410 final int focusedWindowId; 4411 synchronized (mLock) { 4412 focusedWindowId = mA11yWindowManager.getFocusedWindowId( 4413 AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); 4414 if (focusedWindowId == AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) { 4415 return null; 4416 } 4417 } 4418 return getAccessibilityFocusNotLocked(focusedWindowId); 4419 } 4420 getAccessibilityFocusNotLocked(int windowId)4421 private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) { 4422 return mClient.findFocus(mConnectionId, 4423 windowId, AccessibilityNodeInfo.ROOT_NODE_ID, 4424 AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); 4425 } 4426 } 4427 4428 /** 4429 * Gets all currently valid logical displays. 4430 * 4431 * @return An array list containing all valid logical displays. 4432 */ getValidDisplayList()4433 public ArrayList<Display> getValidDisplayList() { 4434 return mA11yDisplayListener.getValidDisplayList(); 4435 } 4436 4437 4438 /** 4439 * Returns {@code true} if the display id is in the list of currently valid logical displays 4440 * being tracked by a11y. 4441 */ isTrackedDisplay(int displayId)4442 private boolean isTrackedDisplay(int displayId) { 4443 final ArrayList<Display> displays = getValidDisplayList(); 4444 for (Display display : displays) { 4445 if (display.getDisplayId() == displayId) { 4446 return true; 4447 } 4448 } 4449 return false; 4450 } 4451 4452 /** 4453 * A Utility class to handle display state. 4454 */ 4455 public class AccessibilityDisplayListener implements DisplayManager.DisplayListener { 4456 private final DisplayManager mDisplayManager; 4457 private final ArrayList<Display> mDisplaysList = new ArrayList<>(); 4458 private int mSystemUiUid = 0; 4459 AccessibilityDisplayListener(Context context, Handler handler)4460 AccessibilityDisplayListener(Context context, Handler handler) { 4461 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 4462 mDisplayManager.registerDisplayListener(this, handler); 4463 initializeDisplayList(); 4464 4465 final PackageManagerInternal pm = 4466 LocalServices.getService(PackageManagerInternal.class); 4467 if (pm != null) { 4468 mSystemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(), 4469 PackageManager.MATCH_SYSTEM_ONLY, mCurrentUserId); 4470 } 4471 } 4472 4473 /** 4474 * Gets all currently valid logical displays. 4475 * 4476 * @return An array list containing all valid logical displays. 4477 */ getValidDisplayList()4478 public ArrayList<Display> getValidDisplayList() { 4479 synchronized (mLock) { 4480 return mDisplaysList; 4481 } 4482 } 4483 initializeDisplayList()4484 private void initializeDisplayList() { 4485 final Display[] displays = mDisplayManager.getDisplays(); 4486 synchronized (mLock) { 4487 mDisplaysList.clear(); 4488 for (int i = 0; i < displays.length; i++) { 4489 // Exclude overlay virtual displays. The display list is for A11yInputFilter 4490 // to create event handler per display. The events should be handled by the 4491 // display which is overlaid by it. 4492 final Display display = displays[i]; 4493 if (isValidDisplay(display)) { 4494 mDisplaysList.add(display); 4495 } 4496 } 4497 } 4498 } 4499 4500 @Override onDisplayAdded(int displayId)4501 public void onDisplayAdded(int displayId) { 4502 final Display display = mDisplayManager.getDisplay(displayId); 4503 if (!isValidDisplay(display)) { 4504 return; 4505 } 4506 4507 synchronized (mLock) { 4508 mDisplaysList.add(display); 4509 mA11yOverlayLayers.put( 4510 displayId, mWindowManagerService.getA11yOverlayLayer(displayId)); 4511 if (mInputFilter != null) { 4512 mInputFilter.onDisplayAdded(display); 4513 } 4514 AccessibilityUserState userState = getCurrentUserStateLocked(); 4515 if (displayId != Display.DEFAULT_DISPLAY) { 4516 final List<AccessibilityServiceConnection> services = userState.mBoundServices; 4517 for (int i = 0; i < services.size(); i++) { 4518 AccessibilityServiceConnection boundClient = services.get(i); 4519 boundClient.onDisplayAdded(displayId); 4520 } 4521 } 4522 updateMagnificationLocked(userState); 4523 updateWindowsForAccessibilityCallbackLocked(userState); 4524 notifyClearAccessibilityCacheLocked(); 4525 } 4526 } 4527 4528 @Override onDisplayRemoved(int displayId)4529 public void onDisplayRemoved(int displayId) { 4530 synchronized (mLock) { 4531 if (!removeDisplayFromList(displayId)) { 4532 return; 4533 } 4534 mA11yOverlayLayers.remove(displayId); 4535 if (mInputFilter != null) { 4536 mInputFilter.onDisplayRemoved(displayId); 4537 } 4538 AccessibilityUserState userState = getCurrentUserStateLocked(); 4539 if (displayId != Display.DEFAULT_DISPLAY) { 4540 final List<AccessibilityServiceConnection> services = userState.mBoundServices; 4541 for (int i = 0; i < services.size(); i++) { 4542 AccessibilityServiceConnection boundClient = services.get(i); 4543 boundClient.onDisplayRemoved(displayId); 4544 } 4545 } 4546 } 4547 mMagnificationController.onDisplayRemoved(displayId); 4548 mA11yWindowManager.stopTrackingWindows(displayId); 4549 } 4550 4551 @GuardedBy("mLock") removeDisplayFromList(int displayId)4552 private boolean removeDisplayFromList(int displayId) { 4553 for (int i = 0; i < mDisplaysList.size(); i++) { 4554 if (mDisplaysList.get(i).getDisplayId() == displayId) { 4555 mDisplaysList.remove(i); 4556 return true; 4557 } 4558 } 4559 return false; 4560 } 4561 4562 @Override onDisplayChanged(int displayId)4563 public void onDisplayChanged(int displayId) { 4564 /* do nothing */ 4565 } 4566 dump(FileDescriptor fd, PrintWriter pw, String[] args)4567 void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4568 pw.println("Accessibility Display Listener:"); 4569 pw.println(" SystemUI uid: " + mSystemUiUid); 4570 int size = mDisplaysList.size(); 4571 pw.printf(" %d valid display%s: ", size, (size == 1 ? "" : "s")); 4572 for (int i = 0; i < size; i++) { 4573 pw.print(mDisplaysList.get(i).getDisplayId()); 4574 if (i < size - 1) { 4575 pw.print(", "); 4576 } 4577 } 4578 pw.println(); 4579 } 4580 isValidDisplay(@ullable Display display)4581 private boolean isValidDisplay(@Nullable Display display) { 4582 if (display == null || display.getType() == Display.TYPE_OVERLAY) { 4583 return false; 4584 } 4585 // Private virtual displays are created by the ap and is not allowed to access by other 4586 // aps. We assume we could ignore them. 4587 // The exceptional case is for bubbles. Because the bubbles use the activityView, and 4588 // the virtual display of the activityView is private, so if the owner UID of the 4589 // private virtual display is the one of system ui which creates the virtual display of 4590 // bubbles, then this private virtual display should track the windows. 4591 if (display.getType() == Display.TYPE_VIRTUAL 4592 && (display.getFlags() & Display.FLAG_PRIVATE) != 0 4593 && display.getOwnerUid() != mSystemUiUid) { 4594 return false; 4595 } 4596 return true; 4597 } 4598 } 4599 4600 /** Represents an {@link AccessibilityManager} */ 4601 class Client { 4602 final IAccessibilityManagerClient mCallback; 4603 final String[] mPackageNames; 4604 int mLastSentRelevantEventTypes; 4605 int mUid; 4606 int mDeviceId = DEVICE_ID_DEFAULT; 4607 Client(IAccessibilityManagerClient callback, int clientUid, AccessibilityUserState userState, int deviceId)4608 private Client(IAccessibilityManagerClient callback, int clientUid, 4609 AccessibilityUserState userState, int deviceId) { 4610 mCallback = callback; 4611 mPackageNames = mPackageManager.getPackagesForUid(clientUid); 4612 mUid = clientUid; 4613 mDeviceId = deviceId; 4614 synchronized (mLock) { 4615 if (mProxyManager.isProxyedDeviceId(deviceId)) { 4616 mLastSentRelevantEventTypes = 4617 mProxyManager.computeRelevantEventTypesLocked(this); 4618 } else { 4619 mLastSentRelevantEventTypes = computeRelevantEventTypesLocked(userState, this); 4620 } 4621 } 4622 } 4623 } 4624 4625 private final class AccessibilityContentObserver extends ContentObserver { 4626 4627 private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor( 4628 Settings.Secure.TOUCH_EXPLORATION_ENABLED); 4629 4630 private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor( 4631 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); 4632 4633 private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor( 4634 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED); 4635 4636 private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor( 4637 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 4638 4639 private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure 4640 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); 4641 4642 private final Uri mHighTextContrastUri = Settings.Secure.getUriFor( 4643 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED); 4644 4645 private final Uri mAudioDescriptionByDefaultUri = Settings.Secure.getUriFor( 4646 Settings.Secure.ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT); 4647 4648 private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor( 4649 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE); 4650 4651 private final Uri mShowImeWithHardKeyboardUri = Settings.Secure.getUriFor( 4652 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD); 4653 4654 private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor( 4655 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); 4656 4657 private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor( 4658 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); 4659 4660 private final Uri mAccessibilityButtonTargetsUri = Settings.Secure.getUriFor( 4661 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); 4662 4663 private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor( 4664 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS); 4665 4666 private final Uri mUserInteractiveUiTimeoutUri = Settings.Secure.getUriFor( 4667 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS); 4668 4669 private final Uri mMagnificationModeUri = Settings.Secure.getUriFor( 4670 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE); 4671 4672 private final Uri mMagnificationCapabilityUri = Settings.Secure.getUriFor( 4673 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY); 4674 4675 private final Uri mMagnificationFollowTypingUri = Settings.Secure.getUriFor( 4676 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED); 4677 4678 private final Uri mAlwaysOnMagnificationUri = Settings.Secure.getUriFor( 4679 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED); 4680 AccessibilityContentObserver(Handler handler)4681 public AccessibilityContentObserver(Handler handler) { 4682 super(handler); 4683 } 4684 register(ContentResolver contentResolver)4685 public void register(ContentResolver contentResolver) { 4686 contentResolver.registerContentObserver(mTouchExplorationEnabledUri, 4687 false, this, UserHandle.USER_ALL); 4688 contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri, 4689 false, this, UserHandle.USER_ALL); 4690 contentResolver.registerContentObserver(mAutoclickEnabledUri, 4691 false, this, UserHandle.USER_ALL); 4692 contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri, 4693 false, this, UserHandle.USER_ALL); 4694 contentResolver.registerContentObserver( 4695 mTouchExplorationGrantedAccessibilityServicesUri, 4696 false, this, UserHandle.USER_ALL); 4697 contentResolver.registerContentObserver( 4698 mHighTextContrastUri, false, this, UserHandle.USER_ALL); 4699 contentResolver.registerContentObserver( 4700 mAudioDescriptionByDefaultUri, false, this, UserHandle.USER_ALL); 4701 contentResolver.registerContentObserver( 4702 mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL); 4703 contentResolver.registerContentObserver( 4704 mShowImeWithHardKeyboardUri, false, this, UserHandle.USER_ALL); 4705 contentResolver.registerContentObserver( 4706 mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL); 4707 contentResolver.registerContentObserver( 4708 mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL); 4709 contentResolver.registerContentObserver( 4710 mAccessibilityButtonTargetsUri, false, this, UserHandle.USER_ALL); 4711 contentResolver.registerContentObserver( 4712 mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL); 4713 contentResolver.registerContentObserver( 4714 mUserInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL); 4715 contentResolver.registerContentObserver( 4716 mMagnificationModeUri, false, this, UserHandle.USER_ALL); 4717 contentResolver.registerContentObserver( 4718 mMagnificationCapabilityUri, false, this, UserHandle.USER_ALL); 4719 contentResolver.registerContentObserver( 4720 mMagnificationFollowTypingUri, false, this, UserHandle.USER_ALL); 4721 contentResolver.registerContentObserver( 4722 mAlwaysOnMagnificationUri, false, this, UserHandle.USER_ALL); 4723 } 4724 4725 @Override onChange(boolean selfChange, Uri uri)4726 public void onChange(boolean selfChange, Uri uri) { 4727 synchronized (mLock) { 4728 // Profiles share the accessibility state of the parent. Therefore, 4729 // we are checking for changes only the parent settings. 4730 AccessibilityUserState userState = getCurrentUserStateLocked(); 4731 4732 if (mTouchExplorationEnabledUri.equals(uri)) { 4733 if (readTouchExplorationEnabledSettingLocked(userState)) { 4734 onUserStateChangedLocked(userState); 4735 } 4736 } else if (mDisplayMagnificationEnabledUri.equals(uri)) { 4737 if (readMagnificationEnabledSettingsLocked(userState)) { 4738 onUserStateChangedLocked(userState); 4739 } 4740 } else if (mAutoclickEnabledUri.equals(uri)) { 4741 if (readAutoclickEnabledSettingLocked(userState)) { 4742 onUserStateChangedLocked(userState); 4743 } 4744 } else if (mEnabledAccessibilityServicesUri.equals(uri)) { 4745 if (readEnabledAccessibilityServicesLocked(userState)) { 4746 mSecurityPolicy.onEnabledServicesChangedLocked(userState.mUserId, 4747 userState.mEnabledServices); 4748 userState.removeDisabledServicesFromTemporaryStatesLocked(); 4749 onUserStateChangedLocked(userState); 4750 } 4751 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) { 4752 if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) { 4753 onUserStateChangedLocked(userState); 4754 } 4755 } else if (mHighTextContrastUri.equals(uri)) { 4756 if (readHighTextContrastEnabledSettingLocked(userState)) { 4757 onUserStateChangedLocked(userState); 4758 } 4759 } else if (mAudioDescriptionByDefaultUri.equals(uri)) { 4760 if (readAudioDescriptionEnabledSettingLocked(userState)) { 4761 onUserStateChangedLocked(userState); 4762 } 4763 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri) 4764 || mShowImeWithHardKeyboardUri.equals(uri)) { 4765 userState.reconcileSoftKeyboardModeWithSettingsLocked(); 4766 } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) { 4767 if (readAccessibilityShortcutKeySettingLocked(userState)) { 4768 onUserStateChangedLocked(userState); 4769 } 4770 } else if (mAccessibilityButtonComponentIdUri.equals(uri)) { 4771 if (readAccessibilityButtonTargetComponentLocked(userState)) { 4772 onUserStateChangedLocked(userState); 4773 } 4774 } else if (mAccessibilityButtonTargetsUri.equals(uri)) { 4775 if (readAccessibilityButtonTargetsLocked(userState)) { 4776 onUserStateChangedLocked(userState); 4777 } 4778 } else if (mUserNonInteractiveUiTimeoutUri.equals(uri) 4779 || mUserInteractiveUiTimeoutUri.equals(uri)) { 4780 readUserRecommendedUiTimeoutSettingsLocked(userState); 4781 } else if (mMagnificationModeUri.equals(uri)) { 4782 if (readMagnificationModeForDefaultDisplayLocked(userState)) { 4783 updateMagnificationModeChangeSettingsLocked(userState, 4784 Display.DEFAULT_DISPLAY); 4785 } 4786 } else if (mMagnificationCapabilityUri.equals(uri)) { 4787 if (readMagnificationCapabilitiesLocked(userState)) { 4788 updateMagnificationCapabilitiesSettingsChangeLocked(userState); 4789 } 4790 } else if (mMagnificationFollowTypingUri.equals(uri)) { 4791 readMagnificationFollowTypingLocked(userState); 4792 } else if (mAlwaysOnMagnificationUri.equals(uri)) { 4793 readAlwaysOnMagnificationLocked(userState); 4794 } 4795 } 4796 } 4797 } 4798 updateMagnificationCapabilitiesSettingsChangeLocked( AccessibilityUserState userState)4799 private void updateMagnificationCapabilitiesSettingsChangeLocked( 4800 AccessibilityUserState userState) { 4801 final ArrayList<Display> displays = getValidDisplayList(); 4802 for (int i = 0; i < displays.size(); i++) { 4803 final int displayId = displays.get(i).getDisplayId(); 4804 if (fallBackMagnificationModeSettingsLocked(userState, displayId)) { 4805 updateMagnificationModeChangeSettingsLocked(userState, displayId); 4806 } 4807 } 4808 updateWindowMagnificationConnectionIfNeeded(userState); 4809 // Remove magnification button UI when the magnification capability is not all mode or 4810 // magnification is disabled. 4811 if (!(userState.isDisplayMagnificationEnabledLocked() 4812 || userState.isShortcutMagnificationEnabledLocked()) 4813 || userState.getMagnificationCapabilitiesLocked() 4814 != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL) { 4815 4816 for (int i = 0; i < displays.size(); i++) { 4817 final int displayId = displays.get(i).getDisplayId(); 4818 getWindowMagnificationMgr().removeMagnificationButton(displayId); 4819 } 4820 } 4821 } 4822 fallBackMagnificationModeSettingsLocked(AccessibilityUserState userState, int displayId)4823 private boolean fallBackMagnificationModeSettingsLocked(AccessibilityUserState userState, 4824 int displayId) { 4825 if (userState.isValidMagnificationModeLocked(displayId)) { 4826 return false; 4827 } 4828 Slog.w(LOG_TAG, "displayId " + displayId + ", invalid magnification mode:" 4829 + userState.getMagnificationModeLocked(displayId)); 4830 final int capabilities = userState.getMagnificationCapabilitiesLocked(); 4831 userState.setMagnificationModeLocked(displayId, capabilities); 4832 if (displayId == Display.DEFAULT_DISPLAY) { 4833 persistMagnificationModeSettingsLocked(capabilities); 4834 } 4835 return true; 4836 } 4837 persistMagnificationModeSettingsLocked(int mode)4838 private void persistMagnificationModeSettingsLocked(int mode) { 4839 BackgroundThread.getHandler().post(() -> { 4840 final long identity = Binder.clearCallingIdentity(); 4841 try { 4842 Settings.Secure.putIntForUser(mContext.getContentResolver(), 4843 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, mode, mCurrentUserId); 4844 } finally { 4845 Binder.restoreCallingIdentity(identity); 4846 } 4847 }); 4848 } 4849 4850 /** 4851 * Gets the magnification mode of the specified display. 4852 * 4853 * @param displayId The logical displayId. 4854 * @return magnification mode. It's either ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN or 4855 * ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW. 4856 */ getMagnificationMode(int displayId)4857 public int getMagnificationMode(int displayId) { 4858 synchronized (mLock) { 4859 return getCurrentUserStateLocked().getMagnificationModeLocked(displayId); 4860 } 4861 } 4862 4863 // Only the value of the default display is from user settings because not each of displays has 4864 // a unique id. readMagnificationModeForDefaultDisplayLocked(AccessibilityUserState userState)4865 private boolean readMagnificationModeForDefaultDisplayLocked(AccessibilityUserState userState) { 4866 final int magnificationMode = Settings.Secure.getIntForUser( 4867 mContext.getContentResolver(), 4868 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 4869 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, userState.mUserId); 4870 if (magnificationMode != userState.getMagnificationModeLocked(Display.DEFAULT_DISPLAY)) { 4871 userState.setMagnificationModeLocked(Display.DEFAULT_DISPLAY, magnificationMode); 4872 return true; 4873 } 4874 return false; 4875 } 4876 readMagnificationCapabilitiesLocked(AccessibilityUserState userState)4877 private boolean readMagnificationCapabilitiesLocked(AccessibilityUserState userState) { 4878 final int capabilities = Settings.Secure.getIntForUser( 4879 mContext.getContentResolver(), 4880 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY, 4881 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, userState.mUserId); 4882 if (capabilities != userState.getMagnificationCapabilitiesLocked()) { 4883 userState.setMagnificationCapabilitiesLocked(capabilities); 4884 mMagnificationController.setMagnificationCapabilities(capabilities); 4885 return true; 4886 } 4887 return false; 4888 } 4889 readMagnificationFollowTypingLocked(AccessibilityUserState userState)4890 boolean readMagnificationFollowTypingLocked(AccessibilityUserState userState) { 4891 final boolean followTypeEnabled = Settings.Secure.getIntForUser( 4892 mContext.getContentResolver(), 4893 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED, 4894 1, userState.mUserId) == 1; 4895 if (followTypeEnabled != userState.isMagnificationFollowTypingEnabled()) { 4896 userState.setMagnificationFollowTypingEnabled(followTypeEnabled); 4897 mMagnificationController.setMagnificationFollowTypingEnabled(followTypeEnabled); 4898 return true; 4899 } 4900 return false; 4901 } 4902 4903 /** 4904 * Called when always on magnification feature flag flips to check if the feature should be 4905 * enabled for current user state. 4906 */ updateAlwaysOnMagnification()4907 public void updateAlwaysOnMagnification() { 4908 synchronized (mLock) { 4909 readAlwaysOnMagnificationLocked(getCurrentUserState()); 4910 } 4911 } 4912 4913 @GuardedBy("mLock") readAlwaysOnMagnificationLocked(AccessibilityUserState userState)4914 boolean readAlwaysOnMagnificationLocked(AccessibilityUserState userState) { 4915 final boolean isSettingsAlwaysOnEnabled = Settings.Secure.getIntForUser( 4916 mContext.getContentResolver(), 4917 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED, 4918 1, userState.mUserId) == 1; 4919 final boolean isAlwaysOnFeatureFlagEnabled = mMagnificationController 4920 .isAlwaysOnMagnificationFeatureFlagEnabled(); 4921 final boolean isAlwaysOnEnabled = isAlwaysOnFeatureFlagEnabled && isSettingsAlwaysOnEnabled; 4922 if (isAlwaysOnEnabled != userState.isAlwaysOnMagnificationEnabled()) { 4923 userState.setAlwaysOnMagnificationEnabled(isAlwaysOnEnabled); 4924 mMagnificationController.setAlwaysOnMagnificationEnabled(isAlwaysOnEnabled); 4925 return true; 4926 } 4927 return false; 4928 } 4929 4930 @Override setGestureDetectionPassthroughRegion(int displayId, Region region)4931 public void setGestureDetectionPassthroughRegion(int displayId, Region region) { 4932 mMainHandler.sendMessage( 4933 obtainMessage( 4934 AccessibilityManagerService::setGestureDetectionPassthroughRegionInternal, 4935 this, 4936 displayId, 4937 region)); 4938 } 4939 4940 @Override setTouchExplorationPassthroughRegion(int displayId, Region region)4941 public void setTouchExplorationPassthroughRegion(int displayId, Region region) { 4942 mMainHandler.sendMessage( 4943 obtainMessage( 4944 AccessibilityManagerService::setTouchExplorationPassthroughRegionInternal, 4945 this, 4946 displayId, 4947 region)); 4948 } 4949 setTouchExplorationPassthroughRegionInternal(int displayId, Region region)4950 private void setTouchExplorationPassthroughRegionInternal(int displayId, Region region) { 4951 synchronized (mLock) { 4952 if (mHasInputFilter && mInputFilter != null) { 4953 mInputFilter.setTouchExplorationPassthroughRegion(displayId, region); 4954 } 4955 } 4956 } 4957 setGestureDetectionPassthroughRegionInternal(int displayId, Region region)4958 private void setGestureDetectionPassthroughRegionInternal(int displayId, Region region) { 4959 synchronized (mLock) { 4960 if (mHasInputFilter && mInputFilter != null) { 4961 mInputFilter.setGestureDetectionPassthroughRegion(displayId, region); 4962 } 4963 } 4964 } 4965 4966 @Override setServiceDetectsGesturesEnabled(int displayId, boolean mode)4967 public void setServiceDetectsGesturesEnabled(int displayId, boolean mode) { 4968 mMainHandler.sendMessage( 4969 obtainMessage(AccessibilityManagerService::setServiceDetectsGesturesInternal, this, 4970 displayId, mode)); 4971 } 4972 setServiceDetectsGesturesInternal(int displayId, boolean mode)4973 private void setServiceDetectsGesturesInternal(int displayId, boolean mode) { 4974 synchronized (mLock) { 4975 getCurrentUserStateLocked().setServiceDetectsGesturesEnabled(displayId, mode); 4976 if (mHasInputFilter && mInputFilter != null) { 4977 mInputFilter.setServiceDetectsGesturesEnabled(displayId, mode); 4978 } 4979 } 4980 } 4981 4982 @Override requestTouchExploration(int displayId)4983 public void requestTouchExploration(int displayId) { 4984 mMainHandler.sendMessage(obtainMessage( 4985 AccessibilityManagerService::requestTouchExplorationInternal, this, displayId)); 4986 } 4987 requestTouchExplorationInternal(int displayId)4988 private void requestTouchExplorationInternal(int displayId) { 4989 synchronized (mLock) { 4990 if (mHasInputFilter && mInputFilter != null) { 4991 mInputFilter.requestTouchExploration(displayId); 4992 } 4993 } 4994 } 4995 4996 @Override requestDragging(int displayId, int pointerId)4997 public void requestDragging(int displayId, int pointerId) { 4998 mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::requestDraggingInternal, 4999 this, displayId, pointerId)); 5000 } 5001 requestDraggingInternal(int displayId, int pointerId)5002 private void requestDraggingInternal(int displayId, int pointerId) { 5003 synchronized (mLock) { 5004 if (mHasInputFilter && mInputFilter != null) { 5005 mInputFilter.requestDragging(displayId, pointerId); 5006 } 5007 } 5008 } 5009 5010 @Override requestDelegating(int displayId)5011 public void requestDelegating(int displayId) { 5012 mMainHandler.sendMessage( 5013 obtainMessage( 5014 AccessibilityManagerService::requestDelegatingInternal, this, displayId)); 5015 } 5016 requestDelegatingInternal(int displayId)5017 private void requestDelegatingInternal(int displayId) { 5018 synchronized (mLock) { 5019 if (mHasInputFilter && mInputFilter != null) { 5020 mInputFilter.requestDelegating(displayId); 5021 } 5022 } 5023 } 5024 5025 @Override onDoubleTap(int displayId)5026 public void onDoubleTap(int displayId) { 5027 mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::onDoubleTapInternal, 5028 this, displayId)); 5029 } 5030 onDoubleTapInternal(int displayId)5031 private void onDoubleTapInternal(int displayId) { 5032 AccessibilityInputFilter inputFilter = null; 5033 synchronized (mLock) { 5034 if (mHasInputFilter && mInputFilter != null) { 5035 inputFilter = mInputFilter; 5036 } 5037 } 5038 if (inputFilter != null) { 5039 inputFilter.onDoubleTap(displayId); 5040 } 5041 } 5042 5043 @Override onDoubleTapAndHold(int displayId)5044 public void onDoubleTapAndHold(int displayId) { 5045 mMainHandler 5046 .sendMessage(obtainMessage(AccessibilityManagerService::onDoubleTapAndHoldInternal, 5047 this, displayId)); 5048 } 5049 5050 @Override requestImeLocked(AbstractAccessibilityServiceConnection connection)5051 public void requestImeLocked(AbstractAccessibilityServiceConnection connection) { 5052 mMainHandler.sendMessage(obtainMessage( 5053 AccessibilityManagerService::createSessionForConnection, this, connection)); 5054 mMainHandler.sendMessage(obtainMessage( 5055 AccessibilityManagerService::bindAndStartInputForConnection, this, connection)); 5056 } 5057 5058 @Override unbindImeLocked(AbstractAccessibilityServiceConnection connection)5059 public void unbindImeLocked(AbstractAccessibilityServiceConnection connection) { 5060 mMainHandler.sendMessage(obtainMessage( 5061 AccessibilityManagerService::unbindInputForConnection, this, connection)); 5062 } 5063 createSessionForConnection(AbstractAccessibilityServiceConnection connection)5064 private void createSessionForConnection(AbstractAccessibilityServiceConnection connection) { 5065 synchronized (mLock) { 5066 if (mInputSessionRequested) { 5067 connection.createImeSessionLocked(); 5068 } 5069 } 5070 } 5071 bindAndStartInputForConnection(AbstractAccessibilityServiceConnection connection)5072 private void bindAndStartInputForConnection(AbstractAccessibilityServiceConnection connection) { 5073 synchronized (mLock) { 5074 if (mInputBound) { 5075 connection.bindInputLocked(); 5076 connection.startInputLocked(mRemoteInputConnection, mEditorInfo, mRestarting); 5077 } 5078 } 5079 } 5080 unbindInputForConnection(AbstractAccessibilityServiceConnection connection)5081 private void unbindInputForConnection(AbstractAccessibilityServiceConnection connection) { 5082 InputMethodManagerInternal.get().unbindAccessibilityFromCurrentClient(connection.mId); 5083 synchronized (mLock) { 5084 connection.unbindInputLocked(); 5085 } 5086 } 5087 onDoubleTapAndHoldInternal(int displayId)5088 private void onDoubleTapAndHoldInternal(int displayId) { 5089 synchronized (mLock) { 5090 if (mHasInputFilter && mInputFilter != null) { 5091 mInputFilter.onDoubleTapAndHold(displayId); 5092 } 5093 } 5094 } 5095 updateFocusAppearanceDataLocked(AccessibilityUserState userState)5096 private void updateFocusAppearanceDataLocked(AccessibilityUserState userState) { 5097 if (userState.mUserId != mCurrentUserId) { 5098 return; 5099 } 5100 if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CLIENT)) { 5101 mTraceManager.logTrace(LOG_TAG + ".updateFocusAppearanceDataLocked", 5102 FLAGS_ACCESSIBILITY_SERVICE_CLIENT, "userState=" + userState); 5103 } 5104 mMainHandler.post(() -> { 5105 broadcastToClients(userState, ignoreRemoteException(client -> { 5106 if (!mProxyManager.isProxyedDeviceId(client.mDeviceId)) { 5107 client.mCallback.setFocusAppearance(userState.getFocusStrokeWidthLocked(), 5108 userState.getFocusColorLocked()); 5109 } 5110 })); 5111 }); 5112 5113 } 5114 getTraceManager()5115 public AccessibilityTraceManager getTraceManager() { 5116 return mTraceManager; 5117 } 5118 5119 /** 5120 * Bind input for accessibility services which request ime capabilities. 5121 */ scheduleBindInput()5122 public void scheduleBindInput() { 5123 mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::bindInput, this)); 5124 } 5125 bindInput()5126 private void bindInput() { 5127 synchronized (mLock) { 5128 // Keep records of these in case new Accessibility Services are enabled. 5129 mInputBound = true; 5130 AccessibilityUserState userState = getCurrentUserStateLocked(); 5131 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 5132 final AccessibilityServiceConnection service = userState.mBoundServices.get(i); 5133 if (service.requestImeApis()) { 5134 service.bindInputLocked(); 5135 } 5136 } 5137 } 5138 } 5139 5140 /** 5141 * Unbind input for accessibility services which request ime capabilities. 5142 */ scheduleUnbindInput()5143 public void scheduleUnbindInput() { 5144 mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::unbindInput, this)); 5145 } 5146 unbindInput()5147 private void unbindInput() { 5148 synchronized (mLock) { 5149 mInputBound = false; 5150 AccessibilityUserState userState = getCurrentUserStateLocked(); 5151 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 5152 final AccessibilityServiceConnection service = userState.mBoundServices.get(i); 5153 if (service.requestImeApis()) { 5154 service.unbindInputLocked(); 5155 } 5156 } 5157 } 5158 } 5159 5160 /** 5161 * Start input for accessibility services which request ime capabilities. 5162 */ scheduleStartInput(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)5163 public void scheduleStartInput(IRemoteAccessibilityInputConnection connection, 5164 EditorInfo editorInfo, boolean restarting) { 5165 mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::startInput, this, 5166 connection, editorInfo, restarting)); 5167 } 5168 startInput(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)5169 private void startInput(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, 5170 boolean restarting) { 5171 synchronized (mLock) { 5172 // Keep records of these in case new Accessibility Services are enabled. 5173 mRemoteInputConnection = connection; 5174 mEditorInfo = editorInfo; 5175 mRestarting = restarting; 5176 AccessibilityUserState userState = getCurrentUserStateLocked(); 5177 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 5178 final AccessibilityServiceConnection service = userState.mBoundServices.get(i); 5179 if (service.requestImeApis()) { 5180 service.startInputLocked(connection, editorInfo, restarting); 5181 } 5182 } 5183 } 5184 } 5185 5186 /** 5187 * Request input sessions from all accessibility services which request ime capabilities and 5188 * whose id is not in the ignoreSet 5189 */ scheduleCreateImeSession(ArraySet<Integer> ignoreSet)5190 public void scheduleCreateImeSession(ArraySet<Integer> ignoreSet) { 5191 mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::createImeSession, 5192 this, ignoreSet)); 5193 } 5194 createImeSession(ArraySet<Integer> ignoreSet)5195 private void createImeSession(ArraySet<Integer> ignoreSet) { 5196 synchronized (mLock) { 5197 mInputSessionRequested = true; 5198 AccessibilityUserState userState = getCurrentUserStateLocked(); 5199 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 5200 final AccessibilityServiceConnection service = userState.mBoundServices.get(i); 5201 if ((!ignoreSet.contains(service.mId)) && service.requestImeApis()) { 5202 service.createImeSessionLocked(); 5203 } 5204 } 5205 } 5206 } 5207 5208 /** 5209 * Enable or disable the sessions. 5210 * 5211 * @param sessions Sessions to enable or disable. 5212 * @param enabled True if enable the sessions or false if disable the sessions. 5213 */ scheduleSetImeSessionEnabled(SparseArray<IAccessibilityInputMethodSession> sessions, boolean enabled)5214 public void scheduleSetImeSessionEnabled(SparseArray<IAccessibilityInputMethodSession> sessions, 5215 boolean enabled) { 5216 mMainHandler.sendMessage(obtainMessage(AccessibilityManagerService::setImeSessionEnabled, 5217 this, sessions, enabled)); 5218 } 5219 setImeSessionEnabled(SparseArray<IAccessibilityInputMethodSession> sessions, boolean enabled)5220 private void setImeSessionEnabled(SparseArray<IAccessibilityInputMethodSession> sessions, 5221 boolean enabled) { 5222 synchronized (mLock) { 5223 AccessibilityUserState userState = getCurrentUserStateLocked(); 5224 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 5225 final AccessibilityServiceConnection service = userState.mBoundServices.get(i); 5226 if (sessions.contains(service.mId) && service.requestImeApis()) { 5227 service.setImeSessionEnabledLocked(sessions.get(service.mId), enabled); 5228 } 5229 } 5230 } 5231 } 5232 5233 @Override injectInputEventToInputFilter(InputEvent event)5234 public void injectInputEventToInputFilter(InputEvent event) { 5235 mSecurityPolicy.enforceCallingPermission(Manifest.permission.INJECT_EVENTS, 5236 "injectInputEventToInputFilter"); 5237 synchronized (mLock) { 5238 final long endMillis = 5239 SystemClock.uptimeMillis() + WAIT_INPUT_FILTER_INSTALL_TIMEOUT_MS; 5240 while (!mInputFilterInstalled && (SystemClock.uptimeMillis() < endMillis)) { 5241 try { 5242 mLock.wait(endMillis - SystemClock.uptimeMillis()); 5243 } catch (InterruptedException ie) { 5244 /* ignore */ 5245 } 5246 } 5247 } 5248 5249 if (mInputFilterInstalled && mInputFilter != null) { 5250 mInputFilter.onInputEvent(event, 5251 WindowManagerPolicy.FLAG_PASS_TO_USER | WindowManagerPolicy.FLAG_INJECTED); 5252 } else { 5253 Slog.w(LOG_TAG, "Cannot injectInputEventToInputFilter because the " 5254 + "AccessibilityInputFilter is not installed."); 5255 } 5256 } 5257 5258 private final class SendWindowStateChangedEventRunnable implements Runnable { 5259 5260 private final AccessibilityEvent mPendingEvent; 5261 private final int mWindowId; 5262 SendWindowStateChangedEventRunnable(@onNull AccessibilityEvent event)5263 SendWindowStateChangedEventRunnable(@NonNull AccessibilityEvent event) { 5264 mPendingEvent = event; 5265 mWindowId = event.getWindowId(); 5266 } 5267 5268 @Override run()5269 public void run() { 5270 synchronized (mLock) { 5271 Slog.w(LOG_TAG, " wait for adding window timeout: " + mWindowId); 5272 sendPendingEventLocked(); 5273 } 5274 } 5275 sendPendingEventLocked()5276 private void sendPendingEventLocked() { 5277 mSendWindowStateChangedEventRunnables.remove(this); 5278 dispatchAccessibilityEventLocked(mPendingEvent); 5279 } 5280 getWindowId()5281 private int getWindowId() { 5282 return mWindowId; 5283 } 5284 } 5285 sendPendingWindowStateChangedEventsForAvailableWindowLocked(int windowId)5286 void sendPendingWindowStateChangedEventsForAvailableWindowLocked(int windowId) { 5287 final int eventSize = mSendWindowStateChangedEventRunnables.size(); 5288 for (int i = eventSize - 1; i >= 0; i--) { 5289 final SendWindowStateChangedEventRunnable runnable = 5290 mSendWindowStateChangedEventRunnables.get(i); 5291 if (runnable.getWindowId() == windowId) { 5292 mMainHandler.removeCallbacks(runnable); 5293 runnable.sendPendingEventLocked(); 5294 } 5295 } 5296 } 5297 5298 /** 5299 * Postpones the {@link AccessibilityEvent} with 5300 * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} 5301 * which doesn't have the corresponding window until the window is added or timeout. 5302 * 5303 * @return {@code true} if the event is postponed. 5304 */ postponeWindowStateEvent(AccessibilityEvent event)5305 private boolean postponeWindowStateEvent(AccessibilityEvent event) { 5306 synchronized (mLock) { 5307 final int resolvedWindowId = mA11yWindowManager.resolveParentWindowIdLocked( 5308 event.getWindowId()); 5309 if (mA11yWindowManager.findWindowInfoByIdLocked(resolvedWindowId) != null) { 5310 return false; 5311 } 5312 final SendWindowStateChangedEventRunnable pendingRunnable = 5313 new SendWindowStateChangedEventRunnable(new AccessibilityEvent(event)); 5314 mMainHandler.postDelayed(pendingRunnable, 5315 POSTPONE_WINDOW_STATE_CHANGED_EVENT_TIMEOUT_MILLIS); 5316 mSendWindowStateChangedEventRunnables.add(pendingRunnable); 5317 return true; 5318 } 5319 } 5320 5321 @Override attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc)5322 public void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc) { 5323 mMainHandler.sendMessage( 5324 obtainMessage( 5325 AccessibilityManagerService::attachAccessibilityOverlayToDisplayInternal, 5326 this, 5327 displayId, 5328 sc)); 5329 } 5330 attachAccessibilityOverlayToDisplayInternal(int displayId, SurfaceControl sc)5331 void attachAccessibilityOverlayToDisplayInternal(int displayId, SurfaceControl sc) { 5332 if (!mA11yOverlayLayers.contains(displayId)) { 5333 mA11yOverlayLayers.put(displayId, mWindowManagerService.getA11yOverlayLayer(displayId)); 5334 } 5335 SurfaceControl parent = mA11yOverlayLayers.get(displayId); 5336 if (parent == null) { 5337 Slog.e(LOG_TAG, "Unable to get accessibility overlay SurfaceControl."); 5338 mA11yOverlayLayers.remove(displayId); 5339 return; 5340 } 5341 SurfaceControl.Transaction t = new SurfaceControl.Transaction(); 5342 t.reparent(sc, parent).setTrustedOverlay(sc, true).apply(); 5343 t.close(); 5344 } 5345 } 5346