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