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