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