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