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