175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov/* 275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** Copyright 2009, The Android Open Source Project 375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** 475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** Licensed under the Apache License, Version 2.0 (the "License"); 575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** you may not use this file except in compliance with the License. 675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** You may obtain a copy of the License at 775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** 875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** http://www.apache.org/licenses/LICENSE-2.0 975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** 1075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** Unless required by applicable law or agreed to in writing, software 1175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** distributed under the License is distributed on an "AS IS" BASIS, 1275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** See the License for the specific language governing permissions and 1475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ** limitations under the License. 1575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 1675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 176e6cd7a5660af1a4b5a9ad091c41ef1c72ad2000Jeff Brownpackage com.android.server.accessibility; 1875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 194213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganovimport static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; 204213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 218643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport android.Manifest; 2275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.accessibilityservice.AccessibilityService; 2375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.accessibilityservice.AccessibilityServiceInfo; 244213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganovimport android.accessibilityservice.IAccessibilityServiceClient; 2575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.accessibilityservice.IAccessibilityServiceConnection; 26447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganovimport android.app.AlertDialog; 27dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackbornimport android.app.PendingIntent; 285c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganovimport android.app.StatusBarManager; 2975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.BroadcastReceiver; 3075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.ComponentName; 3175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.ContentResolver; 3275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.Context; 33447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganovimport android.content.DialogInterface; 34447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganovimport android.content.DialogInterface.OnClickListener; 3575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.Intent; 3675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.IntentFilter; 3775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.ServiceConnection; 3875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.pm.PackageManager; 3975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.pm.ResolveInfo; 4053e184d34e7c5b1a65c74fac55f9a635d8131ddaSvetoslav Ganovimport android.content.pm.ServiceInfo; 410425d7f56b5c14484777357075b285d59996e6e9Svetoslavimport android.content.pm.UserInfo; 4275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.database.ContentObserver; 43a94c3194ffa896632f025b983ca57095cd4ba277Svetoslav Ganovimport android.graphics.Point; 447961be75f4161769f620e44dec3f5911e50ebe03Svetoslav Ganovimport android.graphics.Rect; 459ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslavimport android.graphics.Region; 46a94c3194ffa896632f025b983ca57095cd4ba277Svetoslav Ganovimport android.hardware.display.DisplayManager; 47005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganovimport android.hardware.input.InputManager; 4875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.net.Uri; 4975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Binder; 504213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganovimport android.os.Build; 51aa780c110922148a6a4ba06734bb2b0bb8c98f93Svetoslav Ganovimport android.os.Bundle; 5275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Handler; 5375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.IBinder; 541cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganovimport android.os.Looper; 5575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Message; 5658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganovimport android.os.Process; 5758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganovimport android.os.RemoteCallbackList; 5875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.RemoteException; 590029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.os.ServiceManager; 60005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganovimport android.os.SystemClock; 6158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganovimport android.os.UserHandle; 627befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganovimport android.os.UserManager; 6375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.provider.Settings; 6475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.text.TextUtils; 6575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.text.TextUtils.SimpleStringSplitter; 66c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslavimport android.util.Pools.Pool; 67c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslavimport android.util.Pools.SimplePool; 688a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 6975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.util.SparseArray; 70a94c3194ffa896632f025b983ca57095cd4ba277Svetoslav Ganovimport android.view.Display; 718643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport android.view.IWindow; 72005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganovimport android.view.InputDevice; 73c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslavimport android.view.InputEventConsistencyVerifier; 74005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganovimport android.view.KeyCharacterMap; 75005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganovimport android.view.KeyEvent; 76152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganovimport android.view.MagnificationSpec; 778e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslavimport android.view.WindowInfo; 78447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganovimport android.view.WindowManager; 798e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslavimport android.view.WindowManagerInternal; 80c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslavimport android.view.WindowManagerPolicy; 8175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.view.accessibility.AccessibilityEvent; 82e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganovimport android.view.accessibility.AccessibilityInteractionClient; 8300aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganovimport android.view.accessibility.AccessibilityManager; 848643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 858e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslavimport android.view.accessibility.AccessibilityWindowInfo; 868643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport android.view.accessibility.IAccessibilityInteractionConnection; 878643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport android.view.accessibility.IAccessibilityInteractionConnectionCallback; 8875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.view.accessibility.IAccessibilityManager; 8975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.view.accessibility.IAccessibilityManagerClient; 9075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 91e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganovimport com.android.internal.R; 928643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport com.android.internal.content.PackageMonitor; 93c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganovimport com.android.internal.statusbar.IStatusBarService; 9416e4a1aade2b73edfdaa42aa86a3893fd039fc62Svetoslavimport com.android.internal.widget.LockPatternUtils; 958e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslavimport com.android.server.LocalServices; 968643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 978643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport org.xmlpull.v1.XmlPullParserException; 988643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 996ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganovimport java.io.FileDescriptor; 100cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport java.io.IOException; 1016ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganovimport java.io.PrintWriter; 10275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.ArrayList; 10375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.Arrays; 104319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganovimport java.util.Collections; 10575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.HashMap; 10675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.HashSet; 10721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport java.util.Iterator; 10875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.List; 10975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.Map; 11075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.Set; 11158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganovimport java.util.concurrent.CopyOnWriteArrayList; 11275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 11375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov/** 11475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * This class is instantiated by the system as a system level service and can be 11575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * accessed only by the system. The task of this service is to be a centralized 11675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * event dispatch for {@link AccessibilityEvent}s generated across all processes 11775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * on the device. Events are dispatched to {@link AccessibilityService}s. 11875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 119e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganovpublic class AccessibilityManagerService extends IAccessibilityManager.Stub { 12075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 121736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov private static final boolean DEBUG = false; 122736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov 12375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov private static final String LOG_TAG = "AccessibilityManagerService"; 12475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1257befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov // TODO: This is arbitrary. When there is time implement this by watching 1267befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov // when that accessibility services are bound. 12759f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000; 1287befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov 12904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000; 13004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav 1310d04e245534cf777dfaf16dce3c51553837c14ffSvetoslav Ganov private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE = 1320d04e245534cf777dfaf16dce3c51553837c14ffSvetoslav Ganov "registerUiTestAutomationService"; 1338643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 1347befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED = 1357befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov "temporaryEnableAccessibilityStateUntilKeyguardRemoved"; 1367befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov 1371376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav private static final String GET_WINDOW_TOKEN = "getWindowToken"; 1381376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav 13957bf88508e0491caced22c4c592d33aba6d88129Svetoslav private static final ComponentName sFakeAccessibilityServiceComponentName = 14057bf88508e0491caced22c4c592d33aba6d88129Svetoslav new ComponentName("foo.bar", "FakeService"); 14157bf88508e0491caced22c4c592d33aba6d88129Svetoslav 1426ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov private static final String FUNCTION_DUMP = "dump"; 1436ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov 1449a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov private static final char COMPONENT_NAME_SEPARATOR = ':'; 1459a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov 14675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov private static final int OWN_PROCESS_ID = android.os.Process.myPid(); 14775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 148c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private static final int MAX_POOL_SIZE = 10; 149c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 150d5b0842a1ddbfc2ea5335854fe2834b6e9b965deSvet Ganov private static final int WINDOW_ID_UNKNOWN = -1; 151d5b0842a1ddbfc2ea5335854fe2834b6e9b965deSvet Ganov 152fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov private static int sIdCounter = 0; 153fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov 1548643aa0179e598e78d938c59035389054535a229Svetoslav Ganov private static int sNextWindowId; 1558643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 15658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final Context mContext; 15775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 15858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final Object mLock = new Object(); 15975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 160c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private final Pool<PendingEvent> mPendingEventPool = 161a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new SimplePool<>(MAX_POOL_SIZE); 162c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 16358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final SimpleStringSplitter mStringColonSplitter = 16458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); 16575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 16658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = 167a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new ArrayList<>(); 16875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1699ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav private final Region mTempRegion = new Region(); 1709ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav 171a94c3194ffa896632f025b983ca57095cd4ba277Svetoslav Ganov private final Rect mTempRect = new Rect(); 172a94c3194ffa896632f025b983ca57095cd4ba277Svetoslav Ganov 173ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav private final Rect mTempRect1 = new Rect(); 174ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav 175a94c3194ffa896632f025b983ca57095cd4ba277Svetoslav Ganov private final Point mTempPoint = new Point(); 176a94c3194ffa896632f025b983ca57095cd4ba277Svetoslav Ganov 17758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final PackageManager mPackageManager; 17875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1798e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private final WindowManagerInternal mWindowManagerService; 1809a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov 18158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final SecurityPolicy mSecurityPolicy; 1828643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 18358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final MainHandler mMainHandler; 18475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1851e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private InteractionBridge mInteractionBridge; 18675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 187447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov private AlertDialog mEnableTouchExplorationDialog; 188447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 1890029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown private AccessibilityInputFilter mInputFilter; 19075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 19100aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov private boolean mHasInputFilter; 19200aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov 193a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav private final Set<ComponentName> mTempComponentNameSet = new HashSet<>(); 19457bf88508e0491caced22c4c592d33aba6d88129Svetoslav 19557bf88508e0491caced22c4c592d33aba6d88129Svetoslav private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList = 196a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new ArrayList<>(); 19757bf88508e0491caced22c4c592d33aba6d88129Svetoslav 19858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients = 199a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new RemoteCallbackList<>(); 200f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov 20158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections = 202a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new SparseArray<>(); 2031cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov 204a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>(); 2058643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 206a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav private final SparseArray<UserState> mUserStates = new SparseArray<>(); 207e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2080425d7f56b5c14484777357075b285d59996e6e9Svetoslav private final UserManager mUserManager; 2090425d7f56b5c14484777357075b285d59996e6e9Svetoslav 21016e4a1aade2b73edfdaa42aa86a3893fd039fc62Svetoslav private final LockPatternUtils mLockPatternUtils; 21116e4a1aade2b73edfdaa42aa86a3893fd039fc62Svetoslav 212a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov private int mCurrentUserId = UserHandle.USER_OWNER; 2139b666d0faadd26827ca5b7cf6af3aa94af6adcd9Svetoslav Ganov 2143b817aed7dba4405c764784baaf7308196d16481Svetoslav //TODO: Remove this hack 2153b817aed7dba4405c764784baaf7308196d16481Svetoslav private boolean mInitialized; 2163b817aed7dba4405c764784baaf7308196d16481Svetoslav 2178e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private WindowsForAccessibilityCallback mWindowsForAccessibilityCallback; 2188e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 21958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private UserState getCurrentUserStateLocked() { 22058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return getUserStateLocked(mCurrentUserId); 22158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 22275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 22375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov /** 22475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * Creates a new instance. 22575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * 22675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @param context A {@link Context} instance. 22775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 2286e6cd7a5660af1a4b5a9ad091c41ef1c72ad2000Jeff Brown public AccessibilityManagerService(Context context) { 22975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov mContext = context; 23075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov mPackageManager = mContext.getPackageManager(); 2318e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mWindowManagerService = LocalServices.getService(WindowManagerInternal.class); 2320425d7f56b5c14484777357075b285d59996e6e9Svetoslav mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 2338643aa0179e598e78d938c59035389054535a229Svetoslav Ganov mSecurityPolicy = new SecurityPolicy(); 2341cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov mMainHandler = new MainHandler(mContext.getMainLooper()); 23516e4a1aade2b73edfdaa42aa86a3893fd039fc62Svetoslav mLockPatternUtils = new LockPatternUtils(context); 23658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov registerBroadcastReceivers(); 23758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov new AccessibilityContentObserver(mMainHandler).register( 23858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov context.getContentResolver()); 23975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 24075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 2410425d7f56b5c14484777357075b285d59996e6e9Svetoslav private UserState getUserStateLocked(int userId) { 2420425d7f56b5c14484777357075b285d59996e6e9Svetoslav UserState state = mUserStates.get(userId); 2430425d7f56b5c14484777357075b285d59996e6e9Svetoslav if (state == null) { 2440425d7f56b5c14484777357075b285d59996e6e9Svetoslav state = new UserState(userId); 2450425d7f56b5c14484777357075b285d59996e6e9Svetoslav mUserStates.put(userId, state); 2460425d7f56b5c14484777357075b285d59996e6e9Svetoslav } 2470425d7f56b5c14484777357075b285d59996e6e9Svetoslav return state; 2480425d7f56b5c14484777357075b285d59996e6e9Svetoslav } 2490425d7f56b5c14484777357075b285d59996e6e9Svetoslav 25058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private void registerBroadcastReceivers() { 25121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn PackageMonitor monitor = new PackageMonitor() { 25275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov @Override 25321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn public void onSomePackagesChanged() { 25475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov synchronized (mLock) { 2550425d7f56b5c14484777357075b285d59996e6e9Svetoslav // Only the profile parent can install accessibility services. 2560425d7f56b5c14484777357075b285d59996e6e9Svetoslav // Therefore we ignore packages from linked profiles. 25758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (getChangingUserId() != mCurrentUserId) { 25858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return; 25958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 2604074e8a3f429f62aff3312083d1d925d794ffaccSvetoslav Ganov // We will update when the automation service dies. 26157bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getCurrentUserStateLocked(); 2620ecfa017decd230051d5e42d9f49129afd58838bSvetoslav Ganov // We have to reload the installed services since some services may 2630ecfa017decd230051d5e42d9f49129afd58838bSvetoslav Ganov // have different attributes, resolve info (does not support equals), 2640ecfa017decd230051d5e42d9f49129afd58838bSvetoslav Ganov // etc. Remove them then to force reload. Do it even if automation is 2650ecfa017decd230051d5e42d9f49129afd58838bSvetoslav Ganov // running since when it goes away, we will have to reload as well. 2660ecfa017decd230051d5e42d9f49129afd58838bSvetoslav Ganov userState.mInstalledServices.clear(); 26757bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService == null) { 26857bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (readConfigurationForUserStateLocked(userState)) { 26957bf88508e0491caced22c4c592d33aba6d88129Svetoslav onUserStateChangedLocked(userState); 27057bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 2714074e8a3f429f62aff3312083d1d925d794ffaccSvetoslav Ganov } 27221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 27321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 27400aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov 27521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn @Override 276d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov public void onPackageRemoved(String packageName, int uid) { 277d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov synchronized (mLock) { 27858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int userId = getChangingUserId(); 2790425d7f56b5c14484777357075b285d59996e6e9Svetoslav // Only the profile parent can install accessibility services. 2800425d7f56b5c14484777357075b285d59996e6e9Svetoslav // Therefore we ignore packages from linked profiles. 28158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (userId != mCurrentUserId) { 28258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return; 28358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 28457bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getUserStateLocked(userId); 28557bf88508e0491caced22c4c592d33aba6d88129Svetoslav Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 286d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov while (it.hasNext()) { 287d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov ComponentName comp = it.next(); 288d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov String compPkg = comp.getPackageName(); 289d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov if (compPkg.equals(packageName)) { 290d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov it.remove(); 2919a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov // Update the enabled services setting. 2929a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov persistComponentNamesToSettingLocked( 2939a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 29457bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mEnabledServices, userId); 295447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov // Update the touch exploration granted services setting. 29657bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mTouchExplorationGrantedServices.remove(comp); 297447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov persistComponentNamesToSettingLocked( 298447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov Settings.Secure. 299447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 30057bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mTouchExplorationGrantedServices, userId); 30157bf88508e0491caced22c4c592d33aba6d88129Svetoslav // We will update when the automation service dies. 30257bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService == null) { 30357bf88508e0491caced22c4c592d33aba6d88129Svetoslav onUserStateChangedLocked(userState); 30457bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 305d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov return; 306d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov } 307d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov } 308d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov } 309d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov } 310d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov 311d07d60b9bc0fd2e88f58d6e68dbfadad1bdd31cfSvetoslav Ganov @Override 31221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn public boolean onHandleForceStop(Intent intent, String[] packages, 31321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn int uid, boolean doit) { 31421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn synchronized (mLock) { 31558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int userId = getChangingUserId(); 3160425d7f56b5c14484777357075b285d59996e6e9Svetoslav // Only the profile parent can install accessibility services. 3170425d7f56b5c14484777357075b285d59996e6e9Svetoslav // Therefore we ignore packages from linked profiles. 31858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (userId != mCurrentUserId) { 31958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return false; 32058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 32157bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getUserStateLocked(userId); 32257bf88508e0491caced22c4c592d33aba6d88129Svetoslav Iterator<ComponentName> it = userState.mEnabledServices.iterator(); 32321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn while (it.hasNext()) { 32421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn ComponentName comp = it.next(); 32521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn String compPkg = comp.getPackageName(); 32621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn for (String pkg : packages) { 32721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (compPkg.equals(pkg)) { 32821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (!doit) { 32921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn return true; 33021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 33121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn it.remove(); 3329a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov persistComponentNamesToSettingLocked( 3339a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 33457bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mEnabledServices, userId); 33557bf88508e0491caced22c4c592d33aba6d88129Svetoslav // We will update when the automation service dies. 33657bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService == null) { 33757bf88508e0491caced22c4c592d33aba6d88129Svetoslav onUserStateChangedLocked(userState); 33857bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 33921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 34021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 34121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 34221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn return false; 34321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 34421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 34575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov }; 34675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 34775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov // package changes 34858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov monitor.register(mContext, null, UserHandle.ALL, true); 34975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 3507befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov // user change and unlock 3517befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov IntentFilter intentFilter = new IntentFilter(); 3527befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 3537befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov intentFilter.addAction(Intent.ACTION_USER_REMOVED); 3547befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov intentFilter.addAction(Intent.ACTION_USER_PRESENT); 35575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 3567befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov mContext.registerReceiverAsUser(new BroadcastReceiver() { 35758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov @Override 35858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public void onReceive(Context context, Intent intent) { 35958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov String action = intent.getAction(); 36058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (Intent.ACTION_USER_SWITCHED.equals(action)) { 36158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 36258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 36358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 3647befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov } else if (Intent.ACTION_USER_PRESENT.equals(action)) { 36557bf88508e0491caced22c4c592d33aba6d88129Svetoslav // We will update when the automation service dies. 36657bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getCurrentUserStateLocked(); 36757bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService == null) { 36857bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (readConfigurationForUserStateLocked(userState)) { 36957bf88508e0491caced22c4c592d33aba6d88129Svetoslav onUserStateChangedLocked(userState); 37057bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 37157bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 37275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 37358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 3747befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov }, UserHandle.ALL, intentFilter, null, null); 37575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 37675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 3771376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 37858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public int addClient(IAccessibilityManagerClient client, int userId) { 37975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov synchronized (mLock) { 3800425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 3810425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 3820425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 38358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 38458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked(userId); 38558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // If the client is from a process that runs across users such as 38658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // the system UI or the system we add it to the global state that 38758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // is shared across users. 38858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov UserState userState = getUserStateLocked(resolvedUserId); 38958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 39058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mGlobalClients.register(client); 391a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if (DEBUG) { 392a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid()); 393a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov } 39457bf88508e0491caced22c4c592d33aba6d88129Svetoslav return userState.getClientState(); 39558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } else { 39658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState.mClients.register(client); 39758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // If this client is not for the current user we do not 39858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // return a state since it is not for the foreground user. 39958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // We will send the state to the client on a user switch. 400a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if (DEBUG) { 401a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid() 402a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov + " and userId:" + mCurrentUserId); 403a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov } 40457bf88508e0491caced22c4c592d33aba6d88129Svetoslav return (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0; 40558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 40675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 40775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 40875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 4091376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 41058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) { 41175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov synchronized (mLock) { 4120425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 4130425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 4140425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution.. 41558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 41658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked(userId); 41758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // This method does nothing for a background user. 41858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 41958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return true; // yes, recycle the event 42058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 4218e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) { 4221e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(event.getWindowId(), 4231e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav event.getSourceNodeId(), event.getEventType()); 424a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov mSecurityPolicy.updateEventSourceLocked(event); 425eeee4d2c01d3c4ed99e4891dbc75c7de69a803faSvetoslav Ganov notifyAccessibilityServicesDelayedLocked(event, false); 426eeee4d2c01d3c4ed99e4891dbc75c7de69a803faSvetoslav Ganov notifyAccessibilityServicesDelayedLocked(event, true); 427eeee4d2c01d3c4ed99e4891dbc75c7de69a803faSvetoslav Ganov } 42886783474fdec98a22bc22e224462767eab13e273Svetoslav Ganov if (mHasInputFilter && mInputFilter != null) { 42958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER, 430e45c0b230ba92d7daf8bf625a59bd87d5948101bSvetoslav Ganov AccessibilityEvent.obtain(event)).sendToTarget(); 43186783474fdec98a22bc22e224462767eab13e273Svetoslav Ganov } 432cd94caf2bb94f07522ea5bbf0e37dea960b38220Svetoslav Ganov event.recycle(); 43358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0; 43475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 43575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov return (OWN_PROCESS_ID != Binder.getCallingPid()); 43675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 43775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 4381376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 43958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) { 44075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov synchronized (mLock) { 4410425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 4420425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 4430425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 44458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 44558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked(userId); 446319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov // The automation service is a fake one and should not be reported 447319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov // to clients as being installed - it really is not. 448319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov UserState userState = getUserStateLocked(resolvedUserId); 449319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov if (userState.mUiAutomationService != null) { 450a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav List<AccessibilityServiceInfo> installedServices = new ArrayList<>(); 451319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov installedServices.addAll(userState.mInstalledServices); 452a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo); 453319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov return installedServices; 454319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov } 455319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov return userState.mInstalledServices; 45675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 45775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 45875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 4591376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 46058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, 46158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov int userId) { 46258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov List<AccessibilityServiceInfo> result = null; 463736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov synchronized (mLock) { 4640425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 4650425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 4660425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 46758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 46858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked(userId); 469319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov 470319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov // The automation service is a fake one and should not be reported 471319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov // to clients as being enabled. The automation service is always the 472319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov // only active one, if it exists. 473319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov UserState userState = getUserStateLocked(resolvedUserId); 474319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov if (userState.mUiAutomationService != null) { 475319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov return Collections.emptyList(); 476319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov } 477319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov 47858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov result = mEnabledServicesForFeedbackTempList; 47958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov result.clear(); 480319d55bd15721982db7563711c876bb000490b7dSvetoslav Ganov List<Service> services = userState.mBoundServices; 481cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov while (feedbackType != 0) { 482cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType)); 483cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov feedbackType &= ~feedbackTypeBit; 484f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov final int serviceCount = services.size(); 485f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov for (int i = 0; i < serviceCount; i++) { 486f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov Service service = services.get(i); 487c321c19fc91bfec9a74039ed4d37b815dd4ef379Svetoslav Ganov if ((service.mFeedbackType & feedbackTypeBit) != 0) { 488f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov result.add(service.mAccessibilityServiceInfo); 489f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov } 490cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov } 491736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov } 492736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov } 493f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov return result; 494736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov } 495736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov 4961376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 49758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public void interrupt(int userId) { 49858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov CopyOnWriteArrayList<Service> services; 49975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov synchronized (mLock) { 5000425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 5010425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 5020425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 50358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 50458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked(userId); 50558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // This method does nothing for a background user. 50658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 50758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return; 50858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 50957bf88508e0491caced22c4c592d33aba6d88129Svetoslav services = getUserStateLocked(resolvedUserId).mBoundServices; 51058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 51158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov for (int i = 0, count = services.size(); i < count; i++) { 51258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Service service = services.get(i); 51358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov try { 51458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov service.mServiceInterface.onInterrupt(); 51558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } catch (RemoteException re) { 51658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Slog.e(LOG_TAG, "Error during sending interrupt request to " 51758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov + service.mService, re); 51875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 51975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 52075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 52175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 5221376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 5238643aa0179e598e78d938c59035389054535a229Svetoslav Ganov public int addAccessibilityInteractionConnection(IWindow windowToken, 52458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov IAccessibilityInteractionConnection connection, int userId) throws RemoteException { 5258643aa0179e598e78d938c59035389054535a229Svetoslav Ganov synchronized (mLock) { 5260425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 5270425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 5280425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 52958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 53058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked(userId); 5318643aa0179e598e78d938c59035389054535a229Svetoslav Ganov final int windowId = sNextWindowId++; 53258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // If the window is from a process that runs across users such as 53358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // the system UI or the system we add it to the global state that 53458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // is shared across users. 53558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { 53658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 53758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov windowId, connection, UserHandle.USER_ALL); 53858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov wrapper.linkToDeath(); 53958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mGlobalInteractionConnections.put(windowId, wrapper); 54058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mGlobalWindowTokens.put(windowId, windowToken.asBinder()); 541a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if (DEBUG) { 542a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid() 543cbcc9695f0a701d620f48de75eaee05c4fef6f22Svetoslav + " with windowId: " + windowId + " and token: " + windowToken.asBinder()); 544a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov } 54558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } else { 54658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( 54758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov windowId, connection, resolvedUserId); 54858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov wrapper.linkToDeath(); 54958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov UserState userState = getUserStateLocked(resolvedUserId); 55058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState.mInteractionConnections.put(windowId, wrapper); 55158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState.mWindowTokens.put(windowId, windowToken.asBinder()); 552a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if (DEBUG) { 553a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid() 554cbcc9695f0a701d620f48de75eaee05c4fef6f22Svetoslav + " with windowId: " + windowId + " and userId:" + mCurrentUserId 555cbcc9695f0a701d620f48de75eaee05c4fef6f22Svetoslav + " and token: " + windowToken.asBinder()); 556a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov } 55758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 5588643aa0179e598e78d938c59035389054535a229Svetoslav Ganov return windowId; 5598643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 5608643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 5618643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 5621376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 56358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public void removeAccessibilityInteractionConnection(IWindow window) { 5648643aa0179e598e78d938c59035389054535a229Svetoslav Ganov synchronized (mLock) { 5650425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 5660425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 5670425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 56858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( 56958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov UserHandle.getCallingUserId()); 57058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov IBinder token = window.asBinder(); 571a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked( 57258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov token, mGlobalWindowTokens, mGlobalInteractionConnections); 573a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if (removedWindowId >= 0) { 574a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if (DEBUG) { 575a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid() 576cbcc9695f0a701d620f48de75eaee05c4fef6f22Svetoslav + " with windowId: " + removedWindowId + " and token: " + window.asBinder()); 577a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov } 57858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return; 57958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 58058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int userCount = mUserStates.size(); 58158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov for (int i = 0; i < userCount; i++) { 58258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov UserState userState = mUserStates.valueAt(i); 583a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov final int removedWindowIdForUser = 58458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov removeAccessibilityInteractionConnectionInternalLocked( 58558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov token, userState.mWindowTokens, userState.mInteractionConnections); 586a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if (removedWindowIdForUser >= 0) { 587a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if (DEBUG) { 588a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid() 589a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov + " with windowId: " + removedWindowIdForUser + " and userId:" 590cbcc9695f0a701d620f48de75eaee05c4fef6f22Svetoslav + mUserStates.keyAt(i) + " and token: " + window.asBinder()); 591a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov } 5928643aa0179e598e78d938c59035389054535a229Svetoslav Ganov return; 5938643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 5948643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 5958643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 5968643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 5978643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 598a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, 59958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov SparseArray<IBinder> windowTokens, 60058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov SparseArray<AccessibilityConnectionWrapper> interactionConnections) { 60158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int count = windowTokens.size(); 60258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov for (int i = 0; i < count; i++) { 60358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (windowTokens.valueAt(i) == windowToken) { 60458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int windowId = windowTokens.keyAt(i); 60558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov windowTokens.removeAt(i); 60658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId); 60758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov wrapper.unlinkToDeath(); 60858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov interactionConnections.remove(windowId); 609a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov return windowId; 61058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 61158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 612a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov return -1; 61358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 61458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 6151376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 616db7da0eb8b7d515c168d5b410764e24c9a0f9431Svetoslav public void registerUiTestAutomationService(IBinder owner, 617db7da0eb8b7d515c168d5b410764e24c9a0f9431Svetoslav IAccessibilityServiceClient serviceClient, 61879311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov AccessibilityServiceInfo accessibilityServiceInfo) { 6198643aa0179e598e78d938c59035389054535a229Svetoslav Ganov mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT, 6200d04e245534cf777dfaf16dce3c51553837c14ffSvetoslav Ganov FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE); 62157bf88508e0491caced22c4c592d33aba6d88129Svetoslav 62257bf88508e0491caced22c4c592d33aba6d88129Svetoslav accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName); 62357bf88508e0491caced22c4c592d33aba6d88129Svetoslav 6248643aa0179e598e78d938c59035389054535a229Svetoslav Ganov synchronized (mLock) { 62557bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getCurrentUserStateLocked(); 62657bf88508e0491caced22c4c592d33aba6d88129Svetoslav 62757bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService != null) { 62880943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov throw new IllegalStateException("UiAutomationService " + serviceClient 62980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov + "already registered!"); 63080943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov } 631b6eca6e6691d4563d8395b3c3843d9932a2a6560Svetoslav Ganov 6323c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav try { 6333c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0); 6343c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav } catch (RemoteException re) { 6353c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav Slog.e(LOG_TAG, "Couldn't register for the death of a" 6363c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav + " UiTestAutomationService!", re); 6373c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav return; 6383c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav } 6393c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav 6403c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav userState.mUiAutomationServiceOwner = owner; 64157bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mUiAutomationServiceClient = serviceClient; 642657968a65f29e9319c39b833fefc2ae7472c3e53Svetoslav Ganov 64357bf88508e0491caced22c4c592d33aba6d88129Svetoslav // Set the temporary state. 64457bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mIsAccessibilityEnabled = true; 64557bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mIsTouchExplorationEnabled = false; 6463822896e226567c6cd3ef84518d318abd33a7624Svetoslav userState.mIsEnhancedWebAccessibilityEnabled = false; 64757bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mIsDisplayMagnificationEnabled = false; 64857bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mInstalledServices.add(accessibilityServiceInfo); 64957bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mEnabledServices.clear(); 65057bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName); 65157bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName); 6523822896e226567c6cd3ef84518d318abd33a7624Svetoslav 65357bf88508e0491caced22c4c592d33aba6d88129Svetoslav // Use the new state instead of settings. 65457bf88508e0491caced22c4c592d33aba6d88129Svetoslav onUserStateChangedLocked(userState); 65557bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 65657bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 657657968a65f29e9319c39b833fefc2ae7472c3e53Svetoslav Ganov 6581376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 65957bf88508e0491caced22c4c592d33aba6d88129Svetoslav public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) { 66057bf88508e0491caced22c4c592d33aba6d88129Svetoslav synchronized (mLock) { 66157bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getCurrentUserStateLocked(); 66257bf88508e0491caced22c4c592d33aba6d88129Svetoslav // Automation service is not bound, so pretend it died to perform clean up. 66357bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService != null 66457bf88508e0491caced22c4c592d33aba6d88129Svetoslav && serviceClient != null 6650726843ea088e7c6754fe6ac410749a852316aacSvetoslav && userState.mUiAutomationService.mServiceInterface != null 66657bf88508e0491caced22c4c592d33aba6d88129Svetoslav && userState.mUiAutomationService.mServiceInterface.asBinder() 66757bf88508e0491caced22c4c592d33aba6d88129Svetoslav == serviceClient.asBinder()) { 66857bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mUiAutomationService.binderDied(); 66957bf88508e0491caced22c4c592d33aba6d88129Svetoslav } else { 67057bf88508e0491caced22c4c592d33aba6d88129Svetoslav throw new IllegalStateException("UiAutomationService " + serviceClient 67157bf88508e0491caced22c4c592d33aba6d88129Svetoslav + " not registered!"); 67257bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 6738643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 674d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 675d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov 6761376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 6777befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov public void temporaryEnableAccessibilityStateUntilKeyguardRemoved( 6787befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov ComponentName service, boolean touchExplorationEnabled) { 6797befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov mSecurityPolicy.enforceCallingPermission( 6807befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY, 6817befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED); 6828e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (!mWindowManagerService.isKeyguardLocked()) { 6837befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov return; 6847befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov } 6857befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov synchronized (mLock) { 6867befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov // Set the temporary state. 68757bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getCurrentUserStateLocked(); 68857bf88508e0491caced22c4c592d33aba6d88129Svetoslav 68957bf88508e0491caced22c4c592d33aba6d88129Svetoslav // This is a nop if UI automation is enabled. 69057bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService != null) { 69157bf88508e0491caced22c4c592d33aba6d88129Svetoslav return; 69257bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 69357bf88508e0491caced22c4c592d33aba6d88129Svetoslav 6947befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov userState.mIsAccessibilityEnabled = true; 6953822896e226567c6cd3ef84518d318abd33a7624Svetoslav userState.mIsTouchExplorationEnabled = touchExplorationEnabled; 6963822896e226567c6cd3ef84518d318abd33a7624Svetoslav userState.mIsEnhancedWebAccessibilityEnabled = false; 6977befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov userState.mIsDisplayMagnificationEnabled = false; 6987befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov userState.mEnabledServices.clear(); 6997befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov userState.mEnabledServices.add(service); 70057bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mBindingServices.clear(); 701447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov userState.mTouchExplorationGrantedServices.clear(); 702447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov userState.mTouchExplorationGrantedServices.add(service); 7037befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov 70457bf88508e0491caced22c4c592d33aba6d88129Svetoslav // User the current state instead settings. 70557bf88508e0491caced22c4c592d33aba6d88129Svetoslav onUserStateChangedLocked(userState); 70679311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov } 70779311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov } 70879311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov 7091376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav @Override 7101376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav public IBinder getWindowToken(int windowId) { 7111376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav mSecurityPolicy.enforceCallingPermission( 7121376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav Manifest.permission.RETRIEVE_WINDOW_TOKEN, 7131376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav GET_WINDOW_TOKEN); 7141376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav synchronized (mLock) { 7150425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 7160425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 7170425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 7181376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav final int resolvedUserId = mSecurityPolicy 7191376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav .resolveCallingUserIdEnforcingPermissionsLocked( 7201376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav UserHandle.getCallingUserId()); 7211376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav if (resolvedUserId != mCurrentUserId) { 7221376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return null; 7231376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 7241376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav if (mSecurityPolicy.findWindowById(windowId) == null) { 7251376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return null; 7261376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 7271376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav IBinder token = mGlobalWindowTokens.get(windowId); 7281376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav if (token != null) { 7291376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return token; 7301376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 7311376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav return getCurrentUserStateLocked().mWindowTokens.get(windowId); 7321376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 7331376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav } 7341376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav 735e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov boolean onGesture(int gestureId) { 7364213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov synchronized (mLock) { 737fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov boolean handled = notifyGestureLocked(gestureId, false); 738fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov if (!handled) { 739fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov handled = notifyGestureLocked(gestureId, true); 7404213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 741fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov return handled; 742fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov } 743fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov } 744fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov 745c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav boolean notifyKeyEvent(KeyEvent event, int policyFlags) { 746c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav synchronized (mLock) { 747c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav KeyEvent localClone = KeyEvent.obtain(event); 748c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav boolean handled = notifyKeyEventLocked(localClone, policyFlags, false); 749c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (!handled) { 750c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav handled = notifyKeyEventLocked(localClone, policyFlags, true); 751c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 752c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav return handled; 753c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 754c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 755c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 756e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov /** 7577498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov * Gets a point within the accessibility focused node where we can send down 7587498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov * and up events to perform a click. 759e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov * 7607498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov * @param outPoint The click point to populate. 7617498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov * @return Whether accessibility a click point was found and set. 762e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov */ 7631376d600d8e0eefdbc0aa11d398cf7517fc77129Svetoslav // TODO: (multi-display) Make sure this works for multiple displays. 7647498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov boolean getAccessibilityFocusClickPointInScreen(Point outPoint) { 7657498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov return getInteractionBridgeLocked() 7667498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov .getAccessibilityFocusClickPointInScreenNotLocked(outPoint); 767e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 768e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 76976716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov /** 77010a053e474e2a566b49a1e4c9e2ec4c8cc0013bdSvetoslav * Gets the bounds of a window. 77176716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov * 77276716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov * @param outBounds The output to which to write the bounds. 77376716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov */ 77410a053e474e2a566b49a1e4c9e2ec4c8cc0013bdSvetoslav boolean getWindowBounds(int windowId, Rect outBounds) { 77576716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov IBinder token; 77676716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov synchronized (mLock) { 77776716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov token = mGlobalWindowTokens.get(windowId); 77876716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov if (token == null) { 77976716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov token = getCurrentUserStateLocked().mWindowTokens.get(windowId); 78076716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov } 78176716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov } 78276716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov mWindowManagerService.getWindowFrame(token, outBounds); 78376716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov if (!outBounds.isEmpty()) { 78476716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov return true; 78576716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov } 78676716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov return false; 78776716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov } 78876716c5a180aa471c6973ca7aa03c7f2da677823Svetoslav Ganov 78947b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav boolean accessibilityFocusOnlyInActiveWindow() { 79047b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav synchronized (mLock) { 79147b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav return mWindowsForAccessibilityCallback == null; 79247b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav } 79347b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav } 79447b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav 79558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov int getActiveWindowId() { 7963f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav return mSecurityPolicy.getActiveWindowId(); 797385d9f24b5ce2acb86c0dc192ce702718ab01c39Svetoslav Ganov } 798385d9f24b5ce2acb86c0dc192ce702718ab01c39Svetoslav Ganov 7996ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov void onTouchInteractionStart() { 8006ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov mSecurityPolicy.onTouchInteractionStart(); 8016ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov } 8026ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov 803f772cba59760d1ad9eb5cb9205b2e2e9126e488dSvetoslav Ganov void onTouchInteractionEnd() { 804f772cba59760d1ad9eb5cb9205b2e2e9126e488dSvetoslav Ganov mSecurityPolicy.onTouchInteractionEnd(); 805f772cba59760d1ad9eb5cb9205b2e2e9126e488dSvetoslav Ganov } 806f772cba59760d1ad9eb5cb9205b2e2e9126e488dSvetoslav Ganov 807152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov void onMagnificationStateChanged() { 8088e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav notifyClearAccessibilityCacheLocked(); 809152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov } 810152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov 81158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private void switchUser(int userId) { 81258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov synchronized (mLock) { 8133b817aed7dba4405c764784baaf7308196d16481Svetoslav if (mCurrentUserId == userId && mInitialized) { 8143b817aed7dba4405c764784baaf7308196d16481Svetoslav return; 8153b817aed7dba4405c764784baaf7308196d16481Svetoslav } 8163b817aed7dba4405c764784baaf7308196d16481Svetoslav 81758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // Disconnect from services for the old user. 8180425d7f56b5c14484777357075b285d59996e6e9Svetoslav UserState oldUserState = getCurrentUserStateLocked(); 8195fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav oldUserState.onSwitchToAnotherUser(); 82058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 82158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // Disable the local managers for the old user. 82258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (oldUserState.mClients.getRegisteredCallbackCount() > 0) { 82358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER, 82458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov oldUserState.mUserId, 0).sendToTarget(); 82558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 82658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 82759f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov // Announce user changes only if more that one exist. 82859f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 82959f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov final boolean announceNewUser = userManager.getUsers().size() > 1; 83059f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov 83158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // The user changed. 83258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mCurrentUserId = userId; 83358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 83457bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getCurrentUserStateLocked(); 83557bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService != null) { 83657bf88508e0491caced22c4c592d33aba6d88129Svetoslav // Switching users disables the UI automation service. 83757bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mUiAutomationService.binderDied(); 83857bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 8397befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov 8405fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav readConfigurationForUserStateLocked(userState); 8415fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // Even if reading did not yield change, we have to update 8425fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // the state since the context in which the current user 8435fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // state was used has changed since it was inactive. 8445fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav onUserStateChangedLocked(userState); 8455fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 84659f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov if (announceNewUser) { 84759f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov // Schedule announcement of the current user if needed. 84859f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED, 84959f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS); 85059f07690c2bdd97b9e486b776d2175d914818d06Svetoslav Ganov } 85158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 85258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 85358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 85458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private void removeUser(int userId) { 85558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov synchronized (mLock) { 85658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mUserStates.remove(userId); 85758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 85858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 85958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 8601e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private InteractionBridge getInteractionBridgeLocked() { 8611e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (mInteractionBridge == null) { 8621e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mInteractionBridge = new InteractionBridge(); 863e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 8641e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return mInteractionBridge; 865e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 866e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 8674213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov private boolean notifyGestureLocked(int gestureId, boolean isDefault) { 868fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov // TODO: Now we are giving the gestures to the last enabled 869fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov // service that can handle them which is the last one 870fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov // in our list since we write the last enabled as the 871fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov // last record in the enabled services setting. Ideally, 872fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov // the user should make the call which service handles 873fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov // gestures. However, only one service should handle 874e4abc512aa6474f0106f407f7b399832da34483fSvetoslav Ganov // gestures to avoid user frustration when different 875e4abc512aa6474f0106f407f7b399832da34483fSvetoslav Ganov // behavior is observed from different combinations of 876fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov // enabled accessibility services. 87758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov UserState state = getCurrentUserStateLocked(); 87857bf88508e0491caced22c4c592d33aba6d88129Svetoslav for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 87957bf88508e0491caced22c4c592d33aba6d88129Svetoslav Service service = state.mBoundServices.get(i); 880a43ef3d1c553007b3fa158fe1d3ec4ddb99a71afSvetoslav Ganov if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) { 881e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov service.notifyGesture(gestureId); 882fefd20e927b7252d63acb7bb1852c5188e3c1b2eSvetoslav Ganov return true; 8834213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 8844213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 8854213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov return false; 8864213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 8874213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 888c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private boolean notifyKeyEventLocked(KeyEvent event, int policyFlags, boolean isDefault) { 889c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // TODO: Now we are giving the key events to the last enabled 890688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // service that can handle them Ideally, the user should 891688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // make the call which service handles key events. However, 892688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // only one service should handle key events to avoid user 893688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // frustration when different behavior is observed from 894688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // different combinations of enabled accessibility services. 895c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav UserState state = getCurrentUserStateLocked(); 896c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 897c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav Service service = state.mBoundServices.get(i); 898688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // Key events are handled only by services that declared 899688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // this capability and requested to filter key events. 900688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav if (!service.mRequestFilterKeyEvents || 901688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo 902688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { 903688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav continue; 904688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav } 905c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (service.mIsDefault == isDefault) { 906c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav service.notifyKeyEvent(event, policyFlags); 907c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav return true; 908c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 909c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 910c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav return false; 911c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 912c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 9138e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private void notifyClearAccessibilityCacheLocked() { 914152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov UserState state = getCurrentUserStateLocked(); 91557bf88508e0491caced22c4c592d33aba6d88129Svetoslav for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { 91657bf88508e0491caced22c4c592d33aba6d88129Svetoslav Service service = state.mBoundServices.get(i); 917152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov service.notifyClearAccessibilityNodeInfoCache(); 918152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov } 919152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov } 920152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov 921d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov /** 922d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov * Removes an AccessibilityInteractionConnection. 923d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov * 924d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov * @param windowId The id of the window to which the connection is targeted. 92558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov * @param userId The id of the user owning the connection. UserHandle.USER_ALL 92658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov * if global. 927d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov */ 92858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) { 92958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (userId == UserHandle.USER_ALL) { 93058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mGlobalWindowTokens.remove(windowId); 93158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mGlobalInteractionConnections.remove(windowId); 93258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } else { 93358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov UserState userState = getCurrentUserStateLocked(); 93458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState.mWindowTokens.remove(windowId); 93558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState.mInteractionConnections.remove(windowId); 93658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 937d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov if (DEBUG) { 938d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId); 939d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 9408643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 9418643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 94257bf88508e0491caced22c4c592d33aba6d88129Svetoslav private boolean readInstalledAccessibilityServiceLocked(UserState userState) { 94357bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempAccessibilityServiceInfoList.clear(); 94475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 94558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser( 946cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov new Intent(AccessibilityService.SERVICE_INTERFACE), 94758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, 94858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mCurrentUserId); 94975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 95075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov for (int i = 0, count = installedServices.size(); i < count; i++) { 951cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov ResolveInfo resolveInfo = installedServices.get(i); 95253e184d34e7c5b1a65c74fac55f9a635d8131ddaSvetoslav Ganov ServiceInfo serviceInfo = resolveInfo.serviceInfo; 95358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals( 95458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov serviceInfo.permission)) { 95553e184d34e7c5b1a65c74fac55f9a635d8131ddaSvetoslav Ganov Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName( 95653e184d34e7c5b1a65c74fac55f9a635d8131ddaSvetoslav Ganov serviceInfo.packageName, serviceInfo.name).flattenToShortString() 95753e184d34e7c5b1a65c74fac55f9a635d8131ddaSvetoslav Ganov + ": it does not require the permission " 95853e184d34e7c5b1a65c74fac55f9a635d8131ddaSvetoslav Ganov + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE); 95953e184d34e7c5b1a65c74fac55f9a635d8131ddaSvetoslav Ganov continue; 96053e184d34e7c5b1a65c74fac55f9a635d8131ddaSvetoslav Ganov } 961cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov AccessibilityServiceInfo accessibilityServiceInfo; 962cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov try { 963cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext); 96457bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo); 965a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav } catch (XmlPullParserException | IOException xppe) { 966cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe); 967cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov } 96875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 96957bf88508e0491caced22c4c592d33aba6d88129Svetoslav 97057bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) { 97157bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mInstalledServices.clear(); 97257bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList); 97357bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempAccessibilityServiceInfoList.clear(); 97457bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 97557bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 97657bf88508e0491caced22c4c592d33aba6d88129Svetoslav 97757bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempAccessibilityServiceInfoList.clear(); 97857bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 97975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 98075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 98157bf88508e0491caced22c4c592d33aba6d88129Svetoslav private boolean readEnabledAccessibilityServicesLocked(UserState userState) { 98257bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempComponentNameSet.clear(); 98357bf88508e0491caced22c4c592d33aba6d88129Svetoslav readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 98457bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mUserId, mTempComponentNameSet); 98557bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (!mTempComponentNameSet.equals(userState.mEnabledServices)) { 98657bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mEnabledServices.clear(); 98757bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mEnabledServices.addAll(mTempComponentNameSet); 98857bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempComponentNameSet.clear(); 98957bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 99057bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 99157bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempComponentNameSet.clear(); 99257bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 9939a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov } 9949a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov 99557bf88508e0491caced22c4c592d33aba6d88129Svetoslav private boolean readTouchExplorationGrantedAccessibilityServicesLocked( 99657bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState) { 99757bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempComponentNameSet.clear(); 99857bf88508e0491caced22c4c592d33aba6d88129Svetoslav readComponentNamesFromSettingLocked( 999447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 100057bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mUserId, mTempComponentNameSet); 100157bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) { 100257bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mTouchExplorationGrantedServices.clear(); 100357bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet); 100457bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempComponentNameSet.clear(); 100557bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 100657bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 100757bf88508e0491caced22c4c592d33aba6d88129Svetoslav mTempComponentNameSet.clear(); 100857bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 1009447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1010447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 101175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov /** 101275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * Performs {@link AccessibilityService}s delayed notification. The delay is configurable 101375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * and denotes the period after the last event before notifying the service. 101475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * 101575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @param event The event. 101675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @param isDefault True to notify default listeners, not default services. 101775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 101875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, 101975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov boolean isDefault) { 102085b598beda98706fafd05c7de9866d83d4a19965Charles Chen try { 102158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov UserState state = getCurrentUserStateLocked(); 102257bf88508e0491caced22c4c592d33aba6d88129Svetoslav for (int i = 0, count = state.mBoundServices.size(); i < count; i++) { 102357bf88508e0491caced22c4c592d33aba6d88129Svetoslav Service service = state.mBoundServices.get(i); 102475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 102585b598beda98706fafd05c7de9866d83d4a19965Charles Chen if (service.mIsDefault == isDefault) { 10268e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (canDispatchEventToServiceLocked(service, event, 10278e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav state.mHandledFeedbackTypes)) { 102858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov state.mHandledFeedbackTypes |= service.mFeedbackType; 1029e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov service.notifyAccessibilityEvent(event); 103085b598beda98706fafd05c7de9866d83d4a19965Charles Chen } 103175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 103275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 103385b598beda98706fafd05c7de9866d83d4a19965Charles Chen } catch (IndexOutOfBoundsException oobe) { 103485b598beda98706fafd05c7de9866d83d4a19965Charles Chen // An out of bounds exception can happen if services are going away 103585b598beda98706fafd05c7de9866d83d4a19965Charles Chen // as the for loop is running. If that happens, just bail because 103685b598beda98706fafd05c7de9866d83d4a19965Charles Chen // there are no more services to notify. 103775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 103875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 103975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 104057bf88508e0491caced22c4c592d33aba6d88129Svetoslav private void addServiceLocked(Service service, UserState userState) { 1041f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov try { 10423a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav service.onAdded(); 104357bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mBoundServices.add(service); 104458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState.mComponentNameToServiceMap.put(service.mComponentName, service); 104557bf88508e0491caced22c4c592d33aba6d88129Svetoslav } catch (RemoteException re) { 1046f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov /* do nothing */ 104775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 104875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 104975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 105075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov /** 1051f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov * Removes a service. 105275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * 105375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @param service The service. 105475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 10556f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav private void removeServiceLocked(Service service, UserState userState) { 105657bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mBoundServices.remove(service); 105758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState.mComponentNameToServiceMap.remove(service.mComponentName); 10583a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav service.onRemoved(); 105975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 106075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 106175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov /** 106275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * Determines if given event can be dispatched to a service based on the package of the 106375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * event source and already notified services for that event type. Specifically, a 106475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * service is notified if it is interested in events from the package and no other service 106575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * providing the same feedback type has been notified. Exception are services the 106675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * provide generic feedback (feedback type left as a safety net for unforeseen feedback 106775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * types) which are always notified. 106875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * 106975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @param service The potential receiver. 107075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @param event The event. 107175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @param handledFeedbackTypes The feedback types for which services have been notified. 107275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @return True if the listener should be notified, false otherwise. 107375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 10748e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private boolean canDispatchEventToServiceLocked(Service service, AccessibilityEvent event, 107575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov int handledFeedbackTypes) { 107675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 10773822896e226567c6cd3ef84518d318abd33a7624Svetoslav if (!service.canReceiveEventsLocked()) { 107875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov return false; 107975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 108075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1081d5b0842a1ddbfc2ea5335854fe2834b6e9b965deSvet Ganov if (event.getWindowId() != WINDOW_ID_UNKNOWN && !event.isImportantForAccessibility() 108280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov && (service.mFetchFlags 108380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) { 10844213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov return false; 10854213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 10864213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 108775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov int eventType = event.getEventType(); 108875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov if ((service.mEventTypes & eventType) != eventType) { 108975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov return false; 109075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 109175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 109275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov Set<String> packageNames = service.mPackageNames; 1093a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav String packageName = (event.getPackageName() != null) 1094a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav ? event.getPackageName().toString() : null; 109575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 109675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov if (packageNames.isEmpty() || packageNames.contains(packageName)) { 109775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov int feedbackType = service.mFeedbackType; 109875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov if ((handledFeedbackTypes & feedbackType) != feedbackType 109975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov || feedbackType == AccessibilityServiceInfo.FEEDBACK_GENERIC) { 110075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov return true; 110175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 110275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 110375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 110475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov return false; 110575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 110675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 110758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private void unbindAllServicesLocked(UserState userState) { 110857bf88508e0491caced22c4c592d33aba6d88129Svetoslav List<Service> services = userState.mBoundServices; 110975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov for (int i = 0, count = services.size(); i < count; i++) { 111075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov Service service = services.get(i); 111157bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (service.unbindLocked()) { 11126ff5f103545f90aee3176ad6ca06d9233f899c51Svetoslav Ganov i--; 11136ff5f103545f90aee3176ad6ca06d9233f899c51Svetoslav Ganov count--; 11146ff5f103545f90aee3176ad6ca06d9233f899c51Svetoslav Ganov } 111575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 111675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 111775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 111875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov /** 11199a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov * Populates a set with the {@link ComponentName}s stored in a colon 112058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov * separated value setting for a given user. 112175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * 11229a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov * @param settingName The setting to parse. 112358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov * @param userId The user id. 11249a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov * @param outComponentNames The output component names. 112575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 112657bf88508e0491caced22c4c592d33aba6d88129Svetoslav private void readComponentNamesFromSettingLocked(String settingName, int userId, 11279a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov Set<ComponentName> outComponentNames) { 112858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(), 112958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov settingName, userId); 11309a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov outComponentNames.clear(); 11319a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov if (settingValue != null) { 113275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; 11339a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov splitter.setString(settingValue); 113475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov while (splitter.hasNext()) { 113521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn String str = splitter.next(); 113621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (str == null || str.length() <= 0) { 113721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn continue; 113821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 113921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn ComponentName enabledService = ComponentName.unflattenFromString(str); 114021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (enabledService != null) { 11419a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov outComponentNames.add(enabledService); 114221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 114375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 114475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 114575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 114675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 114775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov /** 11489a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov * Persists the component names in the specified setting in a 11499a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov * colon separated fashion. 11509a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov * 11519a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov * @param settingName The setting name. 11529a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov * @param componentNames The component names. 11539a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov */ 11549a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov private void persistComponentNamesToSettingLocked(String settingName, 115558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Set<ComponentName> componentNames, int userId) { 11569a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov StringBuilder builder = new StringBuilder(); 11579a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov for (ComponentName componentName : componentNames) { 11589a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov if (builder.length() > 0) { 11599a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov builder.append(COMPONENT_NAME_SEPARATOR); 11609a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov } 11619a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov builder.append(componentName.flattenToShortString()); 11629a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov } 116358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Settings.Secure.putStringForUser(mContext.getContentResolver(), 116458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov settingName, builder.toString(), userId); 11659a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov } 11669a4c5cd19106c3021eeead27fbc2aa05ad7d0d18Svetoslav Ganov 116757bf88508e0491caced22c4c592d33aba6d88129Svetoslav private void manageServicesLocked(UserState userState) { 116858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Map<ComponentName, Service> componentNameToServiceMap = 116958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState.mComponentNameToServiceMap; 117058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov boolean isEnabled = userState.mIsAccessibilityEnabled; 117175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 117258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) { 117358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i); 1174cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov ComponentName componentName = ComponentName.unflattenFromString( 1175cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov installedService.getId()); 117675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov Service service = componentNameToServiceMap.get(componentName); 117775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1178f2245aa5d7f5d6f0ea6d55fb2acc66624b2ef13fSvetoslav Ganov if (isEnabled) { 117957bf88508e0491caced22c4c592d33aba6d88129Svetoslav // Wait for the binding if it is in process. 118057bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mBindingServices.contains(componentName)) { 118157bf88508e0491caced22c4c592d33aba6d88129Svetoslav continue; 118257bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 118358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (userState.mEnabledServices.contains(componentName)) { 1184563d78401dc6ed58dd606ac744555151f1cc0ef1Svetoslav Ganov if (service == null) { 118557bf88508e0491caced22c4c592d33aba6d88129Svetoslav service = new Service(userState.mUserId, componentName, installedService); 118657bf88508e0491caced22c4c592d33aba6d88129Svetoslav } else if (userState.mBoundServices.contains(service)) { 118757bf88508e0491caced22c4c592d33aba6d88129Svetoslav continue; 1188563d78401dc6ed58dd606ac744555151f1cc0ef1Svetoslav Ganov } 118957bf88508e0491caced22c4c592d33aba6d88129Svetoslav service.bindLocked(); 119035bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov } else { 1191563d78401dc6ed58dd606ac744555151f1cc0ef1Svetoslav Ganov if (service != null) { 119257bf88508e0491caced22c4c592d33aba6d88129Svetoslav service.unbindLocked(); 1193563d78401dc6ed58dd606ac744555151f1cc0ef1Svetoslav Ganov } 119475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 119575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } else { 119675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov if (service != null) { 119757bf88508e0491caced22c4c592d33aba6d88129Svetoslav service.unbindLocked(); 119857bf88508e0491caced22c4c592d33aba6d88129Svetoslav } else { 119957bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mBindingServices.remove(componentName); 120075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 120175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 120275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 1203cefac5acc845bc0fd36cb2c7e9e0992ecda33230Svetoslav 1204cefac5acc845bc0fd36cb2c7e9e0992ecda33230Svetoslav // No enabled installed services => disable accessibility to avoid 1205cefac5acc845bc0fd36cb2c7e9e0992ecda33230Svetoslav // sending accessibility events with no recipient across processes. 12068aeb0912945ae103223b76d81579073e51579efeSvetoslav if (isEnabled && userState.mBoundServices.isEmpty() 12078aeb0912945ae103223b76d81579073e51579efeSvetoslav && userState.mBindingServices.isEmpty()) { 1208cefac5acc845bc0fd36cb2c7e9e0992ecda33230Svetoslav userState.mIsAccessibilityEnabled = false; 1209cefac5acc845bc0fd36cb2c7e9e0992ecda33230Svetoslav Settings.Secure.putIntForUser(mContext.getContentResolver(), 1210cefac5acc845bc0fd36cb2c7e9e0992ecda33230Svetoslav Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId); 1211cefac5acc845bc0fd36cb2c7e9e0992ecda33230Svetoslav } 121237fedf8b78dea969b97188fd3079fea5e71704beSvetoslav Ganov } 121337fedf8b78dea969b97188fd3079fea5e71704beSvetoslav Ganov 121457bf88508e0491caced22c4c592d33aba6d88129Svetoslav private void scheduleUpdateClientsIfNeededLocked(UserState userState) { 121557bf88508e0491caced22c4c592d33aba6d88129Svetoslav final int clientState = userState.getClientState(); 121657bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mLastSentClientState != clientState 121757bf88508e0491caced22c4c592d33aba6d88129Svetoslav && (mGlobalClients.getRegisteredCallbackCount() > 0 121857bf88508e0491caced22c4c592d33aba6d88129Svetoslav || userState.mClients.getRegisteredCallbackCount() > 0)) { 121957bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mLastSentClientState = clientState; 122058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS, 122158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov clientState, userState.mUserId) .sendToTarget(); 122258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 122358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 122458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 1225545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov private void scheduleUpdateInputFilter(UserState userState) { 1226545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget(); 1227545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov } 1228545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov 1229545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov private void updateInputFilter(UserState userState) { 123058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov boolean setInputFilter = false; 123158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov AccessibilityInputFilter inputFilter = null; 123258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov synchronized (mLock) { 1233ca523d6e95061f99455589512100839118044d43Svetoslav int flags = 0; 1234ca523d6e95061f99455589512100839118044d43Svetoslav if (userState.mIsDisplayMagnificationEnabled) { 1235ca523d6e95061f99455589512100839118044d43Svetoslav flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER; 1236ca523d6e95061f99455589512100839118044d43Svetoslav } 1237ca523d6e95061f99455589512100839118044d43Svetoslav // Touch exploration without accessibility makes no sense. 1238ca523d6e95061f99455589512100839118044d43Svetoslav if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) { 1239ca523d6e95061f99455589512100839118044d43Svetoslav flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION; 1240ca523d6e95061f99455589512100839118044d43Svetoslav } 1241ca523d6e95061f99455589512100839118044d43Svetoslav if (userState.mIsFilterKeyEventsEnabled) { 1242ca523d6e95061f99455589512100839118044d43Svetoslav flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS; 1243ca523d6e95061f99455589512100839118044d43Svetoslav } 1244ca523d6e95061f99455589512100839118044d43Svetoslav if (flags != 0) { 124558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (!mHasInputFilter) { 124658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mHasInputFilter = true; 124758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (mInputFilter == null) { 124858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mInputFilter = new AccessibilityInputFilter(mContext, 124958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov AccessibilityManagerService.this); 125058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 125158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov inputFilter = mInputFilter; 125258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov setInputFilter = true; 125358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 125458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mInputFilter.setEnabledFeatures(flags); 125558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } else { 125658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (mHasInputFilter) { 125758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mHasInputFilter = false; 1258ca523d6e95061f99455589512100839118044d43Svetoslav mInputFilter.disableFeatures(); 125958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov inputFilter = null; 126058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov setInputFilter = true; 126158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 126258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 126358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 126458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (setInputFilter) { 12658e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mWindowManagerService.setInputFilter(inputFilter); 126675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 126775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 126875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1269447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov private void showEnableTouchExplorationDialog(final Service service) { 1270447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov synchronized (mLock) { 127157bf88508e0491caced22c4c592d33aba6d88129Svetoslav String label = service.mResolveInfo.loadLabel( 127257bf88508e0491caced22c4c592d33aba6d88129Svetoslav mContext.getPackageManager()).toString(); 127357bf88508e0491caced22c4c592d33aba6d88129Svetoslav 1274447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov final UserState state = getCurrentUserStateLocked(); 1275447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov if (state.mIsTouchExplorationEnabled) { 1276447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov return; 1277447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1278447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov if (mEnableTouchExplorationDialog != null 1279447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov && mEnableTouchExplorationDialog.isShowing()) { 1280447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov return; 1281447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1282447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext) 1283447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov .setIconAttribute(android.R.attr.alertDialogIcon) 1284447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov .setPositiveButton(android.R.string.ok, new OnClickListener() { 1285447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov @Override 1286447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov public void onClick(DialogInterface dialog, int which) { 1287447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov // The user allowed the service to toggle touch exploration. 1288447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov state.mTouchExplorationGrantedServices.add(service.mComponentName); 1289447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov persistComponentNamesToSettingLocked( 1290447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, 1291447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov state.mTouchExplorationGrantedServices, state.mUserId); 1292447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov // Enable touch exploration. 129357bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getUserStateLocked(service.mUserId); 129457bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mIsTouchExplorationEnabled = true; 1295447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov Settings.Secure.putIntForUser(mContext.getContentResolver(), 1296447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, 1297447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov service.mUserId); 129857bf88508e0491caced22c4c592d33aba6d88129Svetoslav onUserStateChangedLocked(userState); 1299447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1300447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov }) 1301447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov .setNegativeButton(android.R.string.cancel, new OnClickListener() { 1302447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov @Override 1303447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov public void onClick(DialogInterface dialog, int which) { 1304447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov dialog.dismiss(); 1305447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1306447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov }) 1307447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov .setTitle(R.string.enable_explore_by_touch_warning_title) 1308447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov .setMessage(mContext.getString( 1309447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov R.string.enable_explore_by_touch_warning_message, label)) 1310447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov .create(); 1311447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov mEnableTouchExplorationDialog.getWindow().setType( 1312447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 1313447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags 1314447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 1315447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true); 1316447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov mEnableTouchExplorationDialog.show(); 1317447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1318447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1319447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 132057bf88508e0491caced22c4c592d33aba6d88129Svetoslav private void onUserStateChangedLocked(UserState userState) { 13213b817aed7dba4405c764784baaf7308196d16481Svetoslav // TODO: Remove this hack 13223b817aed7dba4405c764784baaf7308196d16481Svetoslav mInitialized = true; 13231e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav updateLegacyCapabilitiesLocked(userState); 132457bf88508e0491caced22c4c592d33aba6d88129Svetoslav updateServicesLocked(userState); 13251e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav updateWindowsForAccessibilityCallbackLocked(userState); 13261e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav updateAccessibilityFocusBehaviorLocked(userState); 1327ca523d6e95061f99455589512100839118044d43Svetoslav updateFilterKeyEventsLocked(userState); 132857bf88508e0491caced22c4c592d33aba6d88129Svetoslav updateTouchExplorationLocked(userState); 132957bf88508e0491caced22c4c592d33aba6d88129Svetoslav updateEnhancedWebAccessibilityLocked(userState); 1330410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette updateDisplayColorAdjustmentSettingsLocked(userState); 133157bf88508e0491caced22c4c592d33aba6d88129Svetoslav scheduleUpdateInputFilter(userState); 133257bf88508e0491caced22c4c592d33aba6d88129Svetoslav scheduleUpdateClientsIfNeededLocked(userState); 133357bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 133457bf88508e0491caced22c4c592d33aba6d88129Svetoslav 13351e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private void updateAccessibilityFocusBehaviorLocked(UserState userState) { 13361e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // If there is no service that can operate with interactive windows 13371e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // then we keep the old behavior where a window loses accessibility 13381e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // focus if it is no longer active. This still changes the behavior 13391e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // for services that do not operate with interactive windows and run 13401e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // at the same time as the one(s) which does. In practice however, 13411e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // there is only one service that uses accessibility focus and it 13421e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // is typically the one that operates with interactive windows, So, 13431e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // this is fine. Note that to allow a service to work across windows 13441e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // we have to allow accessibility focus stay in any of them. Sigh... 13451e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav List<Service> boundServices = userState.mBoundServices; 13461e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav final int boundServiceCount = boundServices.size(); 13471e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav for (int i = 0; i < boundServiceCount; i++) { 13481e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav Service boundService = boundServices.get(i); 13491e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (boundService.canRetrieveInteractiveWindowsLocked()) { 13501e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav userState.mAccessibilityFocusOnlyInActiveWindow = false; 13511e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return; 13521e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 13531e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 13541e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav userState.mAccessibilityFocusOnlyInActiveWindow = true; 13551e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 13561e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 13571e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private void updateWindowsForAccessibilityCallbackLocked(UserState userState) { 13588e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (userState.mIsAccessibilityEnabled) { 13598e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // We observe windows for accessibility only if there is at least 13608e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // one bound service that can retrieve window content that specified 13618e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // it is interested in accessing such windows. For services that are 13628e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // binding we do an update pass after each bind event, so we run this 13638e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // code and register the callback if needed. 13648e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav boolean boundServiceCanRetrieveInteractiveWindows = false; 13658e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 13668e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav List<Service> boundServices = userState.mBoundServices; 13678e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int boundServiceCount = boundServices.size(); 13688e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav for (int i = 0; i < boundServiceCount; i++) { 13698e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav Service boundService = boundServices.get(i); 13701e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (boundService.canRetrieveInteractiveWindowsLocked()) { 13718e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav boundServiceCanRetrieveInteractiveWindows = true; 13728e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav break; 13738e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 13748e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 13758e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 13768e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (boundServiceCanRetrieveInteractiveWindows) { 13778e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (mWindowsForAccessibilityCallback == null) { 13788e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback(); 13798e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mWindowManagerService.setWindowsForAccessibilityCallback( 13808e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mWindowsForAccessibilityCallback); 13818e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 13828e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return; 13838e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 13848e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 13858e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 13868e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (mWindowsForAccessibilityCallback != null) { 13878e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mWindowsForAccessibilityCallback = null; 1388a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav mWindowManagerService.setWindowsForAccessibilityCallback(null); 138904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav // Drop all windows we know about. 139004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav mSecurityPolicy.clearWindowsLocked(); 13918e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 13928e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 13938e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 13941e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private void updateLegacyCapabilitiesLocked(UserState userState) { 139511adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav // Up to JB-MR1 we had a white list with services that can enable touch 139611adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav // exploration. When a service is first started we show a dialog to the 139711adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav // use to get a permission to white list the service. 139811adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav final int installedServiceCount = userState.mInstalledServices.size(); 139911adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav for (int i = 0; i < installedServiceCount; i++) { 140011adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i); 140111adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav ResolveInfo resolveInfo = serviceInfo.getResolveInfo(); 140211adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav if ((serviceInfo.getCapabilities() 140311adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0 140411adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion 140511adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 140611adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav ComponentName componentName = new ComponentName( 140711adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); 140811adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav if (userState.mTouchExplorationGrantedServices.contains(componentName)) { 140911adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav serviceInfo.setCapabilities(serviceInfo.getCapabilities() 141011adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION); 141111adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav } 141211adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav } 141311adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav } 141411adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav } 141511adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav 1416ca523d6e95061f99455589512100839118044d43Svetoslav private void updateFilterKeyEventsLocked(UserState userState) { 1417ca523d6e95061f99455589512100839118044d43Svetoslav final int serviceCount = userState.mBoundServices.size(); 1418ca523d6e95061f99455589512100839118044d43Svetoslav for (int i = 0; i < serviceCount; i++) { 1419ca523d6e95061f99455589512100839118044d43Svetoslav Service service = userState.mBoundServices.get(i); 1420ca523d6e95061f99455589512100839118044d43Svetoslav if (service.mRequestFilterKeyEvents 1421ca523d6e95061f99455589512100839118044d43Svetoslav && (service.mAccessibilityServiceInfo.getCapabilities() 1422ca523d6e95061f99455589512100839118044d43Svetoslav & AccessibilityServiceInfo 1423ca523d6e95061f99455589512100839118044d43Svetoslav .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) { 1424ca523d6e95061f99455589512100839118044d43Svetoslav userState.mIsFilterKeyEventsEnabled = true; 1425ca523d6e95061f99455589512100839118044d43Svetoslav return; 1426ca523d6e95061f99455589512100839118044d43Svetoslav } 1427ca523d6e95061f99455589512100839118044d43Svetoslav } 1428ca523d6e95061f99455589512100839118044d43Svetoslav userState.mIsFilterKeyEventsEnabled = false; 1429ca523d6e95061f99455589512100839118044d43Svetoslav } 1430ca523d6e95061f99455589512100839118044d43Svetoslav 143157bf88508e0491caced22c4c592d33aba6d88129Svetoslav private void updateServicesLocked(UserState userState) { 143258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (userState.mIsAccessibilityEnabled) { 143357bf88508e0491caced22c4c592d33aba6d88129Svetoslav manageServicesLocked(userState); 143457bf88508e0491caced22c4c592d33aba6d88129Svetoslav } else { 143557bf88508e0491caced22c4c592d33aba6d88129Svetoslav unbindAllServicesLocked(userState); 143658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 14371cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov } 14381cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov 143957bf88508e0491caced22c4c592d33aba6d88129Svetoslav private boolean readConfigurationForUserStateLocked(UserState userState) { 1440a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav boolean somthingChanged = readAccessibilityEnabledSettingLocked(userState); 144157bf88508e0491caced22c4c592d33aba6d88129Svetoslav somthingChanged |= readInstalledAccessibilityServiceLocked(userState); 144257bf88508e0491caced22c4c592d33aba6d88129Svetoslav somthingChanged |= readEnabledAccessibilityServicesLocked(userState); 144357bf88508e0491caced22c4c592d33aba6d88129Svetoslav somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState); 144457bf88508e0491caced22c4c592d33aba6d88129Svetoslav somthingChanged |= readTouchExplorationEnabledSettingLocked(userState); 1445cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik somthingChanged |= readHighTextContrastEnabledSettingLocked(userState); 144657bf88508e0491caced22c4c592d33aba6d88129Svetoslav somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState); 144757bf88508e0491caced22c4c592d33aba6d88129Svetoslav somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState); 1448410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState); 144957bf88508e0491caced22c4c592d33aba6d88129Svetoslav return somthingChanged; 14500029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown } 14510029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown 145257bf88508e0491caced22c4c592d33aba6d88129Svetoslav private boolean readAccessibilityEnabledSettingLocked(UserState userState) { 145357bf88508e0491caced22c4c592d33aba6d88129Svetoslav final boolean accessibilityEnabled = Settings.Secure.getIntForUser( 145458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mContext.getContentResolver(), 145558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1; 145657bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (accessibilityEnabled != userState.mIsAccessibilityEnabled) { 145757bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mIsAccessibilityEnabled = accessibilityEnabled; 145857bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 1459b6eca6e6691d4563d8395b3c3843d9932a2a6560Svetoslav Ganov } 146057bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 14610d04e245534cf777dfaf16dce3c51553837c14ffSvetoslav Ganov } 14620d04e245534cf777dfaf16dce3c51553837c14ffSvetoslav Ganov 146357bf88508e0491caced22c4c592d33aba6d88129Svetoslav private boolean readTouchExplorationEnabledSettingLocked(UserState userState) { 146457bf88508e0491caced22c4c592d33aba6d88129Svetoslav final boolean touchExplorationEnabled = Settings.Secure.getIntForUser( 14650d04e245534cf777dfaf16dce3c51553837c14ffSvetoslav Ganov mContext.getContentResolver(), 146658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1; 146757bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) { 146857bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mIsTouchExplorationEnabled = touchExplorationEnabled; 146957bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 147057bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 147157bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 1472b6eca6e6691d4563d8395b3c3843d9932a2a6560Svetoslav Ganov } 1473b6eca6e6691d4563d8395b3c3843d9932a2a6560Svetoslav Ganov 147457bf88508e0491caced22c4c592d33aba6d88129Svetoslav private boolean readDisplayMagnificationEnabledSettingLocked(UserState userState) { 147557bf88508e0491caced22c4c592d33aba6d88129Svetoslav final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser( 14761cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov mContext.getContentResolver(), 147758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 147858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 0, userState.mUserId) == 1; 147957bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled) { 148057bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled; 148157bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 1482447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 148357bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 1484447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1485447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 148657bf88508e0491caced22c4c592d33aba6d88129Svetoslav private boolean readEnhancedWebAccessibilityEnabledChangedLocked(UserState userState) { 148757bf88508e0491caced22c4c592d33aba6d88129Svetoslav final boolean enhancedWeAccessibilityEnabled = Settings.Secure.getIntForUser( 1488447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 1489447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 0, userState.mUserId) == 1; 149057bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (enhancedWeAccessibilityEnabled != userState.mIsEnhancedWebAccessibilityEnabled) { 149157bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mIsEnhancedWebAccessibilityEnabled = enhancedWeAccessibilityEnabled; 149257bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 149357bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 149457bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 149557bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 149657bf88508e0491caced22c4c592d33aba6d88129Svetoslav 1497410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette private boolean readDisplayColorAdjustmentSettingsLocked(UserState userState) { 1498f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette final boolean displayAdjustmentsEnabled = DisplayAdjustmentUtils.hasAdjustments(mContext, 1499f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette userState.mUserId); 1500f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette if (displayAdjustmentsEnabled != userState.mHasDisplayColorAdjustment) { 1501f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette userState.mHasDisplayColorAdjustment = displayAdjustmentsEnabled; 1502410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette return true; 1503410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette } 1504f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette // If display adjustment is enabled, always assume there was a change in 1505f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette // the adjustment settings. 1506f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette return displayAdjustmentsEnabled; 1507410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette } 1508410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette 1509cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik private boolean readHighTextContrastEnabledSettingLocked(UserState userState) { 1510cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik final boolean highTextContrastEnabled = Settings.Secure.getIntForUser( 1511cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik mContext.getContentResolver(), 1512cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0, 1513cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik userState.mUserId) == 1; 1514cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) { 1515cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik userState.mIsTextHighContrastEnabled = highTextContrastEnabled; 1516cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik return true; 1517cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 1518cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik return false; 1519cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 1520cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 152157bf88508e0491caced22c4c592d33aba6d88129Svetoslav private void updateTouchExplorationLocked(UserState userState) { 1522042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav boolean enabled = false; 152357bf88508e0491caced22c4c592d33aba6d88129Svetoslav final int serviceCount = userState.mBoundServices.size(); 152457bf88508e0491caced22c4c592d33aba6d88129Svetoslav for (int i = 0; i < serviceCount; i++) { 152557bf88508e0491caced22c4c592d33aba6d88129Svetoslav Service service = userState.mBoundServices.get(i); 1526042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav if (canRequestAndRequestsTouchExplorationLocked(service)) { 1527042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav enabled = true; 152857bf88508e0491caced22c4c592d33aba6d88129Svetoslav break; 152957bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 153057bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 1531042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav if (enabled != userState.mIsTouchExplorationEnabled) { 1532042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav userState.mIsTouchExplorationEnabled = enabled; 1533042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav Settings.Secure.putIntForUser(mContext.getContentResolver(), 1534042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0, 1535042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav userState.mUserId); 1536042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav } 1537447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1538447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 1539042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav private boolean canRequestAndRequestsTouchExplorationLocked(Service service) { 1540042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav // Service not ready or cannot request the feature - well nothing to do. 1541447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) { 154257bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 1543a43ef3d1c553007b3fa158fe1d3ec4ddb99a71afSvetoslav Ganov } 1544447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov // UI test automation service can always enable it. 1545447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov if (service.mIsAutomation) { 154657bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 1547447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1548447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion 1549447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov <= Build.VERSION_CODES.JELLY_BEAN_MR1) { 1550447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov // Up to JB-MR1 we had a white list with services that can enable touch 1551447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov // exploration. When a service is first started we show a dialog to the 1552447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov // use to get a permission to white list the service. 1553042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav UserState userState = getUserStateLocked(service.mUserId); 1554042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) { 155557bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 1556042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav } else if (mEnableTouchExplorationDialog == null 1557042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav || !mEnableTouchExplorationDialog.isShowing()) { 1558042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav mMainHandler.obtainMessage( 1559042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG, 1560042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav service).sendToTarget(); 1561447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 1562447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } else { 1563688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // Starting in JB-MR2 we request an accessibility service to declare 1564688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // certain capabilities in its meta-data to allow it to enable the 1565688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav // corresponding features. 1566042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav if ((service.mAccessibilityServiceInfo.getCapabilities() 1567688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) { 156857bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 1569447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 15703822896e226567c6cd3ef84518d318abd33a7624Svetoslav } 157157bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 15723822896e226567c6cd3ef84518d318abd33a7624Svetoslav } 15733822896e226567c6cd3ef84518d318abd33a7624Svetoslav 157457bf88508e0491caced22c4c592d33aba6d88129Svetoslav private void updateEnhancedWebAccessibilityLocked(UserState userState) { 1575042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav boolean enabled = false; 157657bf88508e0491caced22c4c592d33aba6d88129Svetoslav final int serviceCount = userState.mBoundServices.size(); 1577447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov for (int i = 0; i < serviceCount; i++) { 157857bf88508e0491caced22c4c592d33aba6d88129Svetoslav Service service = userState.mBoundServices.get(i); 1579042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav if (canRequestAndRequestsEnhancedWebAccessibilityLocked(service)) { 1580042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav enabled = true; 1581042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav break; 15823822896e226567c6cd3ef84518d318abd33a7624Svetoslav } 1583a43ef3d1c553007b3fa158fe1d3ec4ddb99a71afSvetoslav Ganov } 1584042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav if (enabled != userState.mIsEnhancedWebAccessibilityEnabled) { 1585042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav userState.mIsEnhancedWebAccessibilityEnabled = enabled; 1586042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav Settings.Secure.putIntForUser(mContext.getContentResolver(), 1587042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, enabled ? 1 : 0, 1588042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav userState.mUserId); 1589042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav } 1590a43ef3d1c553007b3fa158fe1d3ec4ddb99a71afSvetoslav Ganov } 1591a43ef3d1c553007b3fa158fe1d3ec4ddb99a71afSvetoslav Ganov 1592042ccec5a0921b749b38fed021b82b224ce5a70aSvetoslav private boolean canRequestAndRequestsEnhancedWebAccessibilityLocked(Service service) { 1593447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov if (!service.canReceiveEventsLocked() || !service.mRequestEnhancedWebAccessibility ) { 159457bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 15953822896e226567c6cd3ef84518d318abd33a7624Svetoslav } 1596688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav if (service.mIsAutomation || (service.mAccessibilityServiceInfo.getCapabilities() 1597688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0) { 159857bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 1599e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 160057bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 1601e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 1602e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 1603f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette private void updateDisplayColorAdjustmentSettingsLocked(UserState userState) { 1604f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId); 1605f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette } 1606f242659afc6539f9f1104833a88e37b5f9203417Alan Viverette 160716e4a1aade2b73edfdaa42aa86a3893fd039fc62Svetoslav private boolean hasRunningServicesLocked(UserState userState) { 160816e4a1aade2b73edfdaa42aa86a3893fd039fc62Svetoslav return !userState.mBoundServices.isEmpty() || !userState.mBindingServices.isEmpty(); 160916e4a1aade2b73edfdaa42aa86a3893fd039fc62Svetoslav } 161016e4a1aade2b73edfdaa42aa86a3893fd039fc62Svetoslav 16111e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) { 16121e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav IBinder windowToken = mGlobalWindowTokens.get(windowId); 16131e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (windowToken == null) { 16141e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId); 16151e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 16161e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (windowToken != null) { 16171e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return mWindowManagerService.getCompatibleMagnificationSpecForWindow( 16181e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav windowToken); 16191e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 16201e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return null; 16211e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 16221e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 16236ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov @Override 16246ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 16256ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP); 16266ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov synchronized (mLock) { 16276ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)"); 16286ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.println(); 16296ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov final int userCount = mUserStates.size(); 16306ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov for (int i = 0; i < userCount; i++) { 16316ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov UserState userState = mUserStates.valueAt(i); 16326ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append("User state[attributes:{id=" + userState.mUserId); 16336ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId)); 16346ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled); 16356ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled); 16366ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(", displayMagnificationEnabled=" 16376ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov + userState.mIsDisplayMagnificationEnabled); 163857bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (userState.mUiAutomationService != null) { 163957bf88508e0491caced22c4c592d33aba6d88129Svetoslav pw.append(", "); 164057bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mUiAutomationService.dump(fd, pw, args); 164157bf88508e0491caced22c4c592d33aba6d88129Svetoslav pw.println(); 164257bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 16436ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append("}"); 16446ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.println(); 16456ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(" services:{"); 164657bf88508e0491caced22c4c592d33aba6d88129Svetoslav final int serviceCount = userState.mBoundServices.size(); 16476ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov for (int j = 0; j < serviceCount; j++) { 16486ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov if (j > 0) { 16496ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(", "); 16506ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.println(); 16516ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(" "); 16526ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov } 165357bf88508e0491caced22c4c592d33aba6d88129Svetoslav Service service = userState.mBoundServices.get(j); 16546ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov service.dump(fd, pw, args); 16556ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov } 16566ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.println("}]"); 16576ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.println(); 16586ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov } 165904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mSecurityPolicy.mWindows != null) { 166004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav final int windowCount = mSecurityPolicy.mWindows.size(); 166104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav for (int j = 0; j < windowCount; j++) { 166204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (j > 0) { 166304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav pw.append(','); 166404cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav pw.println(); 166504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 166604cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav pw.append("Window["); 166704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j); 166804cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav pw.append(window.toString()); 166904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav pw.append(']'); 16704604abc97d7dd757bb76ff9b7fcf343dc4a15212Svetoslav } 16714604abc97d7dd757bb76ff9b7fcf343dc4a15212Svetoslav } 16726ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov } 16736ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov } 16746ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov 1675d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov private class AccessibilityConnectionWrapper implements DeathRecipient { 1676d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov private final int mWindowId; 167758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final int mUserId; 1678d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov private final IAccessibilityInteractionConnection mConnection; 1679d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov 1680d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov public AccessibilityConnectionWrapper(int windowId, 168158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov IAccessibilityInteractionConnection connection, int userId) { 1682d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov mWindowId = windowId; 168358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mUserId = userId; 1684d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov mConnection = connection; 1685d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 1686d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov 1687d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov public void linkToDeath() throws RemoteException { 1688d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov mConnection.asBinder().linkToDeath(this, 0); 1689d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 1690d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov 1691d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov public void unlinkToDeath() { 1692d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov mConnection.asBinder().unlinkToDeath(this, 0); 1693d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 1694d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov 1695d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov @Override 1696d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov public void binderDied() { 1697d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov unlinkToDeath(); 1698d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov synchronized (mLock) { 169958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId); 1700d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 1701d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 1702d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 1703d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov 170458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final class MainHandler extends Handler { 170558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1; 170658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public static final int MSG_SEND_STATE_TO_CLIENTS = 2; 170758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3; 170857bf88508e0491caced22c4c592d33aba6d88129Svetoslav public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5; 170957bf88508e0491caced22c4c592d33aba6d88129Svetoslav public static final int MSG_UPDATE_INPUT_FILTER = 6; 171057bf88508e0491caced22c4c592d33aba6d88129Svetoslav public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7; 1711c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8; 17121e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public static final int MSG_CLEAR_ACCESSIBILITY_FOCUS = 9; 17131cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov 17141cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov public MainHandler(Looper looper) { 17151cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov super(looper); 17161cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov } 17171cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov 1718e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov @Override 1719e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov public void handleMessage(Message msg) { 1720e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov final int type = msg.what; 1721e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov switch (type) { 1722e45c0b230ba92d7daf8bf625a59bd87d5948101bSvetoslav Ganov case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: { 1723e45c0b230ba92d7daf8bf625a59bd87d5948101bSvetoslav Ganov AccessibilityEvent event = (AccessibilityEvent) msg.obj; 172458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov synchronized (mLock) { 172558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (mHasInputFilter && mInputFilter != null) { 172658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mInputFilter.notifyAccessibilityEvent(event); 172758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 1728e45c0b230ba92d7daf8bf625a59bd87d5948101bSvetoslav Ganov } 1729e45c0b230ba92d7daf8bf625a59bd87d5948101bSvetoslav Ganov event.recycle(); 1730e45c0b230ba92d7daf8bf625a59bd87d5948101bSvetoslav Ganov } break; 17318e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 1732c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: { 1733c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav KeyEvent event = (KeyEvent) msg.obj; 1734c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav final int policyFlags = msg.arg1; 1735c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav synchronized (mLock) { 1736c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (mHasInputFilter && mInputFilter != null) { 1737c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mInputFilter.sendInputEvent(event, policyFlags); 1738c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 1739c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 1740c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav event.recycle(); 1741c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } break; 17428e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 174358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov case MSG_SEND_STATE_TO_CLIENTS: { 174458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int clientState = msg.arg1; 174558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int userId = msg.arg2; 174658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov sendStateToClients(clientState, mGlobalClients); 174758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov sendStateToClientsForUser(clientState, userId); 174858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } break; 17498e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 175058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: { 175158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int userId = msg.arg1; 175258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov sendStateToClientsForUser(0, userId); 175358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } break; 17548e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 17557befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: { 17567befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov announceNewUserIfNeeded(); 17577befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov } break; 17588e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 1759545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov case MSG_UPDATE_INPUT_FILTER: { 1760545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov UserState userState = (UserState) msg.obj; 1761447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov updateInputFilter(userState); 1762545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov } break; 17638e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 176457bf88508e0491caced22c4c592d33aba6d88129Svetoslav case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: { 176557bf88508e0491caced22c4c592d33aba6d88129Svetoslav Service service = (Service) msg.obj; 176657bf88508e0491caced22c4c592d33aba6d88129Svetoslav showEnableTouchExplorationDialog(service); 176757bf88508e0491caced22c4c592d33aba6d88129Svetoslav } break; 17681e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 17691e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav case MSG_CLEAR_ACCESSIBILITY_FOCUS: { 17701e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav final int windowId = msg.arg1; 17711e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav InteractionBridge bridge; 17721e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav synchronized (mLock) { 17731e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav bridge = getInteractionBridgeLocked(); 17741e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 17751e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav bridge.clearAccessibilityFocusNotLocked(windowId); 17761e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } break; 17777befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov } 17787befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov } 17797befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov 17807befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov private void announceNewUserIfNeeded() { 17817befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov synchronized (mLock) { 17827befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov UserState userState = getCurrentUserStateLocked(); 17837befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov if (userState.mIsAccessibilityEnabled) { 17847befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov UserManager userManager = (UserManager) mContext.getSystemService( 17857befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov Context.USER_SERVICE); 17867befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov String message = mContext.getString(R.string.user_switched, 17877befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov userManager.getUserInfo(mCurrentUserId).name); 17887befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov AccessibilityEvent event = AccessibilityEvent.obtain( 17897befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov AccessibilityEvent.TYPE_ANNOUNCEMENT); 17907befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov event.getText().add(message); 17917befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov sendAccessibilityEvent(event, mCurrentUserId); 17927befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov } 1793e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 1794e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 179558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 179658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private void sendStateToClientsForUser(int clientState, int userId) { 179758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final UserState userState; 179858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov synchronized (mLock) { 179958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov userState = getUserStateLocked(userId); 180058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 180158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov sendStateToClients(clientState, userState.mClients); 180258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 180358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 180458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private void sendStateToClients(int clientState, 180558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov RemoteCallbackList<IAccessibilityManagerClient> clients) { 180658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov try { 180758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int userClientCount = clients.beginBroadcast(); 180858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov for (int i = 0; i < userClientCount; i++) { 180958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov IAccessibilityManagerClient client = clients.getBroadcastItem(i); 181058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov try { 181158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov client.setState(clientState); 181258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } catch (RemoteException re) { 181358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov /* ignore */ 181458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 181558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 181658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } finally { 181758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov clients.finishBroadcast(); 181858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 181958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 1820e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 1821e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 1822c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private PendingEvent obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence) { 1823c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav PendingEvent pendingEvent = mPendingEventPool.acquire(); 1824c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (pendingEvent == null) { 1825c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent = new PendingEvent(); 1826c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 1827c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent.event = event; 1828c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent.policyFlags = policyFlags; 1829c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent.sequence = sequence; 1830c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav return pendingEvent; 1831c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 1832c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 1833c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private void recyclePendingEventLocked(PendingEvent pendingEvent) { 1834c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent.clear(); 1835c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mPendingEventPool.release(pendingEvent); 1836c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 1837c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 18388e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private int findWindowIdLocked(IBinder token) { 18398e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int globalIndex = mGlobalWindowTokens.indexOfValue(token); 18408e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (globalIndex >= 0) { 18418e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return mGlobalWindowTokens.keyAt(globalIndex); 18428e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 18438e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav UserState userState = getCurrentUserStateLocked(); 18448e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int userIndex = userState.mWindowTokens.indexOfValue(token); 18458e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (userIndex >= 0) { 18468e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return userState.mWindowTokens.keyAt(userIndex); 18478e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 18488e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return -1; 18498e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 18508e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 185104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav private void ensureWindowsAvailableTimed() { 185204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav synchronized (mLock) { 185304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mSecurityPolicy.mWindows != null) { 185404cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav return; 185504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 185604cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav // If we have no registered callback, update the state we 185704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav // we may have to register one but it didn't happen yet. 185804cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mWindowsForAccessibilityCallback == null) { 185904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav UserState userState = getCurrentUserStateLocked(); 186004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav onUserStateChangedLocked(userState); 186104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 186204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav // We have no windows but do not care about them, done. 186304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mWindowsForAccessibilityCallback == null) { 186404cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav return; 186504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 186604cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav 186704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav // Wait for the windows with a timeout. 186804cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav final long startMillis = SystemClock.uptimeMillis(); 186904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav while (mSecurityPolicy.mWindows == null) { 187004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 187104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis; 187204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (remainMillis <= 0) { 187304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav return; 187404cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 187504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav try { 187604cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav mLock.wait(remainMillis); 187704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } catch (InterruptedException ie) { 187804cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav /* ignore */ 187904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 188004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 188104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 188204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 188304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav 1884b6eca6e6691d4563d8395b3c3843d9932a2a6560Svetoslav Ganov /** 188575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * This class represents an accessibility service. It stores all per service 188675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * data required for the service management, provides API for starting/stopping the 188775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * service and is responsible for adding/removing the service in the data structures 188875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * for service management. The class also exposes configuration interface that is 188975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * passed to the service it represents as soon it is bound. It also serves as the 189075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * connection for the service. 189175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 1892f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov class Service extends IAccessibilityServiceConnection.Stub 1893c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav implements ServiceConnection, DeathRecipient {; 1894e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 189558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int mUserId; 189658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 189775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov int mId = 0; 189875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1899cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov AccessibilityServiceInfo mAccessibilityServiceInfo; 1900736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov 190175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov IBinder mService; 190275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 19034213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov IAccessibilityServiceClient mServiceInterface; 190475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 190575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov int mEventTypes; 190675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 190775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov int mFeedbackType; 190875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1909a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav Set<String> mPackageNames = new HashSet<>(); 191075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 191175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov boolean mIsDefault; 191275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1913e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov boolean mRequestTouchExplorationMode; 1914e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 19153822896e226567c6cd3ef84518d318abd33a7624Svetoslav boolean mRequestEnhancedWebAccessibility; 19163822896e226567c6cd3ef84518d318abd33a7624Svetoslav 1917688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav boolean mRequestFilterKeyEvents; 1918688a6977cf7673ed0542ab3d839053c4e38a4dbdSvetoslav 19198e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav boolean mRetrieveInteractiveWindows; 19208e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 192180943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov int mFetchFlags; 19224213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 192375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov long mNotificationTimeout; 192475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 192575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov ComponentName mComponentName; 192675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 192775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov Intent mIntent; 192875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1929e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov boolean mIsAutomation; 19308643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 1931e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov final ResolveInfo mResolveInfo; 1932e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 19333a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav final IBinder mOverlayWindowToken = new Binder(); 19343a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav 193575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov // the events pending events to be dispatched to this service 193675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov final SparseArray<AccessibilityEvent> mPendingEvents = 1937a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new SparseArray<>(); 193875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 1939c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher(); 1940c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 1941bfa1bf020859a03668f1af1d59f035c53a97c7e8Svetoslav Ganov boolean mWasConnectedAndDied; 1942bfa1bf020859a03668f1af1d59f035c53a97c7e8Svetoslav Ganov 1943c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // Handler only for dispatching accessibility events since we use event 1944c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // types as message types allowing us to remove messages per event type. 1945c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) { 1946e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov @Override 1947e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov public void handleMessage(Message message) { 1948c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav final int eventType = message.what; 1949c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav notifyAccessibilityEventInternal(eventType); 1950e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 1951e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov }; 1952e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 1953c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // Handler for scheduling method invocations on the main thread. 1954c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public InvocationHandler mInvocationHandler = new InvocationHandler( 1955c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mMainHandler.getLooper()); 1956c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 195758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public Service(int userId, ComponentName componentName, 195857bf88508e0491caced22c4c592d33aba6d88129Svetoslav AccessibilityServiceInfo accessibilityServiceInfo) { 195958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mUserId = userId; 1960e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov mResolveInfo = accessibilityServiceInfo.getResolveInfo(); 196175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov mId = sIdCounter++; 19628643aa0179e598e78d938c59035389054535a229Svetoslav Ganov mComponentName = componentName; 19638643aa0179e598e78d938c59035389054535a229Svetoslav Ganov mAccessibilityServiceInfo = accessibilityServiceInfo; 196457bf88508e0491caced22c4c592d33aba6d88129Svetoslav mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName)); 196557bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (!mIsAutomation) { 19668643aa0179e598e78d938c59035389054535a229Svetoslav Ganov mIntent = new Intent().setComponent(mComponentName); 19678643aa0179e598e78d938c59035389054535a229Svetoslav Ganov mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, 19688643aa0179e598e78d938c59035389054535a229Svetoslav Ganov com.android.internal.R.string.accessibility_binding_label); 19698643aa0179e598e78d938c59035389054535a229Svetoslav Ganov mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( 19708643aa0179e598e78d938c59035389054535a229Svetoslav Ganov mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); 19718643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 19728643aa0179e598e78d938c59035389054535a229Svetoslav Ganov setDynamicallyConfigurableProperties(accessibilityServiceInfo); 19738643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 19748643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 19758643aa0179e598e78d938c59035389054535a229Svetoslav Ganov public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { 1976cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov mEventTypes = info.eventTypes; 1977cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov mFeedbackType = info.feedbackType; 1978cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov String[] packageNames = info.packageNames; 1979cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov if (packageNames != null) { 1980cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov mPackageNames.addAll(Arrays.asList(packageNames)); 1981cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov } 1982cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov mNotificationTimeout = info.notificationTimeout; 19834213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov mIsDefault = (info.flags & DEFAULT) != 0; 19844213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 1985df549f83810c6fa76be1845363ef69809a30e569Guang Zhu if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion 19865a48f9758b990fe6c46359927a40aecb6a02b64cSvetoslav Ganov >= Build.VERSION_CODES.JELLY_BEAN) { 19879e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { 19889e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 19899e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav } else { 19909e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 19919e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav } 19924213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 1993c321c19fc91bfec9a74039ed4d37b815dd4ef379Svetoslav Ganov 19949e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { 19959e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 19969e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav } else { 19979e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; 19989e065121fa4cd7443c648f29c2f4c3a276041be8Svetoslav } 199980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov 2000db7da0eb8b7d515c168d5b410764e24c9a0f9431Svetoslav mRequestTouchExplorationMode = (info.flags 2001db7da0eb8b7d515c168d5b410764e24c9a0f9431Svetoslav & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; 2002db7da0eb8b7d515c168d5b410764e24c9a0f9431Svetoslav mRequestEnhancedWebAccessibility = (info.flags 2003db7da0eb8b7d515c168d5b410764e24c9a0f9431Svetoslav & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0; 2004db7da0eb8b7d515c168d5b410764e24c9a0f9431Svetoslav mRequestFilterKeyEvents = (info.flags 20058e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; 20068e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mRetrieveInteractiveWindows = (info.flags 20078e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; 2008cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov } 2009cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov 201075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov /** 201175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * Binds to the accessibility service. 20126ff5f103545f90aee3176ad6ca06d9233f899c51Svetoslav Ganov * 20136ff5f103545f90aee3176ad6ca06d9233f899c51Svetoslav Ganov * @return True if binding is successful. 201475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 201557bf88508e0491caced22c4c592d33aba6d88129Svetoslav public boolean bindLocked() { 201657bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getUserStateLocked(mUserId); 201757bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (!mIsAutomation) { 20186f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav if (mService == null && mContext.bindServiceAsUser( 20196f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav mIntent, this, Context.BIND_AUTO_CREATE, new UserHandle(mUserId))) { 20206f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav userState.mBindingServices.add(mComponentName); 202157bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 202257bf88508e0491caced22c4c592d33aba6d88129Svetoslav } else { 202357bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mBindingServices.add(mComponentName); 202457bf88508e0491caced22c4c592d33aba6d88129Svetoslav mService = userState.mUiAutomationServiceClient.asBinder(); 2025419036b560e79c11705e376ad171688ac496bb7dSvetoslav mMainHandler.post(new Runnable() { 2026419036b560e79c11705e376ad171688ac496bb7dSvetoslav @Override 2027419036b560e79c11705e376ad171688ac496bb7dSvetoslav public void run() { 2028419036b560e79c11705e376ad171688ac496bb7dSvetoslav // Simulate asynchronous connection since in onServiceConnected 2029419036b560e79c11705e376ad171688ac496bb7dSvetoslav // we may modify the state data in case of an error but bind is 2030419036b560e79c11705e376ad171688ac496bb7dSvetoslav // called while iterating over the data and bad things can happen. 2031419036b560e79c11705e376ad171688ac496bb7dSvetoslav onServiceConnected(mComponentName, mService); 2032419036b560e79c11705e376ad171688ac496bb7dSvetoslav } 2033419036b560e79c11705e376ad171688ac496bb7dSvetoslav }); 203457bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mUiAutomationService = this; 203575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 20366ff5f103545f90aee3176ad6ca06d9233f899c51Svetoslav Ganov return false; 203775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 203875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 203975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov /** 204075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * Unbinds form the accessibility service and removes it from the data 204175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * structures for service management. 20426ff5f103545f90aee3176ad6ca06d9233f899c51Svetoslav Ganov * 20436ff5f103545f90aee3176ad6ca06d9233f899c51Svetoslav Ganov * @return True if unbinding is successful. 204475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */ 204557bf88508e0491caced22c4c592d33aba6d88129Svetoslav public boolean unbindLocked() { 204657bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (mService == null) { 204757bf88508e0491caced22c4c592d33aba6d88129Svetoslav return false; 204875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 20496f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav UserState userState = getUserStateLocked(mUserId); 2050c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mKeyEventDispatcher.flush(); 205157bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (!mIsAutomation) { 205257bf88508e0491caced22c4c592d33aba6d88129Svetoslav mContext.unbindService(this); 205357bf88508e0491caced22c4c592d33aba6d88129Svetoslav } else { 20543c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav userState.destroyUiAutomationService(); 205557bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 20566f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav removeServiceLocked(this, userState); 20572602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav resetLocked(); 205857bf88508e0491caced22c4c592d33aba6d88129Svetoslav return true; 205975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 206075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 20613822896e226567c6cd3ef84518d318abd33a7624Svetoslav public boolean canReceiveEventsLocked() { 2062c321c19fc91bfec9a74039ed4d37b815dd4ef379Svetoslav Ganov return (mEventTypes != 0 && mFeedbackType != 0 && mService != null); 206375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 206475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 20654213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 2066c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public void setOnKeyEventResult(boolean handled, int sequence) { 2067c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mKeyEventDispatcher.setOnKeyEventResult(handled, sequence); 2068c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2069c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2070c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav @Override 20714213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov public AccessibilityServiceInfo getServiceInfo() { 20724213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov synchronized (mLock) { 20734213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov return mAccessibilityServiceInfo; 20744213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 20754213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 20764213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 20771e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public boolean canRetrieveInteractiveWindowsLocked() { 20781e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return mSecurityPolicy.canRetrieveWindowContentLocked(this) 20791e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav && mRetrieveInteractiveWindows; 20801e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 20811e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 20824213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 208375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov public void setServiceInfo(AccessibilityServiceInfo info) { 208458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 208558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov try { 208658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov synchronized (mLock) { 208758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // If the XML manifest had data to configure the service its info 208858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // should be already set. In such a case update only the dynamically 208958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov // configurable properties. 209058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; 209158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (oldInfo != null) { 209258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov oldInfo.updateDynamicallyConfigurableProperties(info); 209358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov setDynamicallyConfigurableProperties(oldInfo); 209458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } else { 209558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov setDynamicallyConfigurableProperties(info); 209658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 209757bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getUserStateLocked(mUserId); 209857bf88508e0491caced22c4c592d33aba6d88129Svetoslav onUserStateChangedLocked(userState); 20994213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 210058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } finally { 210158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Binder.restoreCallingIdentity(identity); 21024213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 210375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 210475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 21054213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 210675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov public void onServiceConnected(ComponentName componentName, IBinder service) { 210757bf88508e0491caced22c4c592d33aba6d88129Svetoslav synchronized (mLock) { 210857bf88508e0491caced22c4c592d33aba6d88129Svetoslav mService = service; 210957bf88508e0491caced22c4c592d33aba6d88129Svetoslav mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service); 211057bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getUserStateLocked(mUserId); 21116f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav addServiceLocked(this, userState); 2112bfa1bf020859a03668f1af1d59f035c53a97c7e8Svetoslav Ganov if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) { 211357bf88508e0491caced22c4c592d33aba6d88129Svetoslav userState.mBindingServices.remove(mComponentName); 2114bfa1bf020859a03668f1af1d59f035c53a97c7e8Svetoslav Ganov mWasConnectedAndDied = false; 2115a60fdfac9432972e520e8c53b3b0717b4c3a2973Svetoslav try { 21163a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav mServiceInterface.init(this, mId, mOverlayWindowToken); 2117072906eef827cd8d92b48f79975d4f2e21d1c958Svetoslav onUserStateChangedLocked(userState); 2118a60fdfac9432972e520e8c53b3b0717b4c3a2973Svetoslav } catch (RemoteException re) { 2119072906eef827cd8d92b48f79975d4f2e21d1c958Svetoslav Slog.w(LOG_TAG, "Error while setting connection for service: " 2120072906eef827cd8d92b48f79975d4f2e21d1c958Svetoslav + service, re); 2121072906eef827cd8d92b48f79975d4f2e21d1c958Svetoslav binderDied(); 2122a60fdfac9432972e520e8c53b3b0717b4c3a2973Svetoslav } 2123a60fdfac9432972e520e8c53b3b0717b4c3a2973Svetoslav } else { 2124a60fdfac9432972e520e8c53b3b0717b4c3a2973Svetoslav binderDied(); 212575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 212657bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 212775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 212875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov 21294213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 21308e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav public List<AccessibilityWindowInfo> getWindows() { 213104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav ensureWindowsAvailableTimed(); 21328e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 21330425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its perent as profiles 21340425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 21350425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 21368e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int resolvedUserId = mSecurityPolicy 21378e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav .resolveCallingUserIdEnforcingPermissionsLocked( 2138ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 21398e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (resolvedUserId != mCurrentUserId) { 21408e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return null; 21418e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21428e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final boolean permissionGranted = 21438e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mSecurityPolicy.canRetrieveWindowsLocked(this); 21448e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (!permissionGranted) { 21458e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return null; 21468e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 214709687064f4cf681d2aa299c393e32f22fc013c96Svet Ganov if (mSecurityPolicy.mWindows == null) { 214809687064f4cf681d2aa299c393e32f22fc013c96Svet Ganov return null; 214909687064f4cf681d2aa299c393e32f22fc013c96Svet Ganov } 2150a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav List<AccessibilityWindowInfo> windows = new ArrayList<>(); 21518e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int windowCount = mSecurityPolicy.mWindows.size(); 21528e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav for (int i = 0; i < windowCount; i++) { 21538e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i); 21548e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo windowClone = 21558e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo.obtain(window); 21568e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav windowClone.setConnectionId(mId); 21578e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav windows.add(windowClone); 21588e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21598e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return windows; 21608e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21618e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21628e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 21638e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav @Override 21648e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav public AccessibilityWindowInfo getWindow(int windowId) { 216504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav ensureWindowsAvailableTimed(); 21668e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 21670425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 21680425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 21690425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 21708e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int resolvedUserId = mSecurityPolicy 21718e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav .resolveCallingUserIdEnforcingPermissionsLocked( 2172ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 21738e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (resolvedUserId != mCurrentUserId) { 21748e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return null; 21758e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21768e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final boolean permissionGranted = 21778e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mSecurityPolicy.canRetrieveWindowsLocked(this); 21788e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (!permissionGranted) { 21798e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return null; 21808e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21818e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId); 21828e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (window != null) { 21838e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); 21848e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav windowClone.setConnectionId(mId); 21858e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return windowClone; 21868e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21878e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return null; 21888e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21898e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 21908e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 21918e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav @Override 219280943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId, 219380943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov long accessibilityNodeId, String viewIdResName, int interactionId, 219479311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 21954a49d9fe52a76c7f91f81113e0a8e9f97ac3f24cSvetoslav Ganov throws RemoteException { 219658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedWindowId; 21978643aa0179e598e78d938c59035389054535a229Svetoslav Ganov IAccessibilityInteractionConnection connection = null; 21989ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Region partialInteractiveRegion = mTempRegion; 21998643aa0179e598e78d938c59035389054535a229Svetoslav Ganov synchronized (mLock) { 22000425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 22010425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 22020425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 220358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 220458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked( 2205ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 220658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 2207152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 220858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 22098e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 22108e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final boolean permissionGranted = 22118e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 2212e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov if (!permissionGranted) { 2213152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 2214e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov } else { 221579311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov connection = getConnectionLocked(resolvedWindowId); 2216e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov if (connection == null) { 2217152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 2218e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov } 22198643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 22209ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 22219ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav resolvedWindowId, partialInteractiveRegion)) { 22229ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav partialInteractiveRegion = null; 22239ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 22248643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 22258bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int interrogatingPid = Binder.getCallingPid(); 22268643aa0179e598e78d938c59035389054535a229Svetoslav Ganov final long identityToken = Binder.clearCallingIdentity(); 22271e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 22288643aa0179e598e78d938c59035389054535a229Svetoslav Ganov try { 22299ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName, 22307498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov partialInteractiveRegion, interactionId, callback, mFetchFlags, 22317498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov interrogatingPid, interrogatingTid, spec); 2232152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return true; 22338643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } catch (RemoteException re) { 22348643aa0179e598e78d938c59035389054535a229Svetoslav Ganov if (DEBUG) { 223579311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); 22368643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 22378643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } finally { 22388643aa0179e598e78d938c59035389054535a229Svetoslav Ganov Binder.restoreCallingIdentity(identityToken); 22398643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 2240152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 2241eeee4d2c01d3c4ed99e4891dbc75c7de69a803faSvetoslav Ganov } 2242eeee4d2c01d3c4ed99e4891dbc75c7de69a803faSvetoslav Ganov 22434213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 2244152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, 224579311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov long accessibilityNodeId, String text, int interactionId, 22468bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 22478bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov throws RemoteException { 224858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedWindowId; 22498643aa0179e598e78d938c59035389054535a229Svetoslav Ganov IAccessibilityInteractionConnection connection = null; 22509ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Region partialInteractiveRegion = mTempRegion; 22518643aa0179e598e78d938c59035389054535a229Svetoslav Ganov synchronized (mLock) { 22520425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 22530425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 22540425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 225558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 225658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked( 2257ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 225858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 2259152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 226058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 226158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 2262eeee4d2c01d3c4ed99e4891dbc75c7de69a803faSvetoslav Ganov final boolean permissionGranted = 226379311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 2264e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov if (!permissionGranted) { 2265152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 2266e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov } else { 226779311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov connection = getConnectionLocked(resolvedWindowId); 2268e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov if (connection == null) { 2269152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 2270e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov } 22718643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 22729ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 22739ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav resolvedWindowId, partialInteractiveRegion)) { 22749ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav partialInteractiveRegion = null; 22759ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 22768643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 22778bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int interrogatingPid = Binder.getCallingPid(); 22788643aa0179e598e78d938c59035389054535a229Svetoslav Ganov final long identityToken = Binder.clearCallingIdentity(); 22791e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 22808643aa0179e598e78d938c59035389054535a229Svetoslav Ganov try { 2281c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, 22827498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov partialInteractiveRegion, interactionId, callback, mFetchFlags, 22837498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov interrogatingPid, interrogatingTid, spec); 2284152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return true; 22858643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } catch (RemoteException re) { 22868643aa0179e598e78d938c59035389054535a229Svetoslav Ganov if (DEBUG) { 228779311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); 22888643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 22898643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } finally { 22908643aa0179e598e78d938c59035389054535a229Svetoslav Ganov Binder.restoreCallingIdentity(identityToken); 22918643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 2292152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 22938643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 22948643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 22954213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 2296152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov public boolean findAccessibilityNodeInfoByAccessibilityId( 2297152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov int accessibilityWindowId, long accessibilityNodeId, int interactionId, 22984213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov IAccessibilityInteractionConnectionCallback callback, int flags, 22994213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov long interrogatingTid) throws RemoteException { 230058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedWindowId; 23018643aa0179e598e78d938c59035389054535a229Svetoslav Ganov IAccessibilityInteractionConnection connection = null; 23029ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Region partialInteractiveRegion = mTempRegion; 23038643aa0179e598e78d938c59035389054535a229Svetoslav Ganov synchronized (mLock) { 23040425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 23050425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 23060425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 230758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 230858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked( 2309ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 231058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 2311152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 231258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 231358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 23148643aa0179e598e78d938c59035389054535a229Svetoslav Ganov final boolean permissionGranted = 231579311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 2316e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov if (!permissionGranted) { 2317152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 2318e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov } else { 231979311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov connection = getConnectionLocked(resolvedWindowId); 232079311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov if (connection == null) { 2321152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 2322e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov } 23238643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 23249ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 23259ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav resolvedWindowId, partialInteractiveRegion)) { 23269ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav partialInteractiveRegion = null; 23279ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 23288643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 23298bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int interrogatingPid = Binder.getCallingPid(); 23308643aa0179e598e78d938c59035389054535a229Svetoslav Ganov final long identityToken = Binder.clearCallingIdentity(); 23311e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 23328643aa0179e598e78d938c59035389054535a229Svetoslav Ganov try { 2333021078554b902179442a345a9d080a165c3b5139Svetoslav Ganov connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, 23349ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav partialInteractiveRegion, interactionId, callback, mFetchFlags | flags, 23359ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav interrogatingPid, interrogatingTid, spec); 2336152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return true; 23378643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } catch (RemoteException re) { 23388643aa0179e598e78d938c59035389054535a229Svetoslav Ganov if (DEBUG) { 233979311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); 23408643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 23418643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } finally { 23428643aa0179e598e78d938c59035389054535a229Svetoslav Ganov Binder.restoreCallingIdentity(identityToken); 23438643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 2344152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 23458643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 23468643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 23474213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 2348152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, 23494213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov int focusType, int interactionId, 23504213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 23514213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov throws RemoteException { 235258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedWindowId; 23534213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov IAccessibilityInteractionConnection connection = null; 23549ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Region partialInteractiveRegion = mTempRegion; 23554213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov synchronized (mLock) { 23560425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 23570425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 23580425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 235958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 236058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked( 2361ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 236258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 2363152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 236458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 23651e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( 23661e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav accessibilityWindowId, focusType); 23674213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov final boolean permissionGranted = 23684213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 23694213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov if (!permissionGranted) { 2370152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 23714213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } else { 23724213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov connection = getConnectionLocked(resolvedWindowId); 23734213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov if (connection == null) { 2374152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 23754213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 23764213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 23779ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 23789ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav resolvedWindowId, partialInteractiveRegion)) { 23799ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav partialInteractiveRegion = null; 23809ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 23814213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 23824213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov final int interrogatingPid = Binder.getCallingPid(); 23834213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov final long identityToken = Binder.clearCallingIdentity(); 23841e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 23854213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov try { 23867498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, 23877498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, 23887498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov spec); 2389152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return true; 23904213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } catch (RemoteException re) { 23914213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov if (DEBUG) { 23921e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav Slog.e(LOG_TAG, "Error calling findFocus()"); 23934213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 23944213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } finally { 23954213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov Binder.restoreCallingIdentity(identityToken); 23964213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 2397152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 23984213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 23994213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 24004213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 2401152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, 24024213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov int direction, int interactionId, 24034213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 24044213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov throws RemoteException { 240558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedWindowId; 24064213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov IAccessibilityInteractionConnection connection = null; 24079ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Region partialInteractiveRegion = mTempRegion; 24084213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov synchronized (mLock) { 24090425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 24100425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 24110425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 241258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 241358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked( 2414ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 241558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 2416152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 241758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 241858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 24194213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov final boolean permissionGranted = 24204213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); 24214213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov if (!permissionGranted) { 2422152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 24234213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } else { 24244213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov connection = getConnectionLocked(resolvedWindowId); 24254213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov if (connection == null) { 2426152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 24274213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 24284213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 24299ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( 24309ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav resolvedWindowId, partialInteractiveRegion)) { 24319ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav partialInteractiveRegion = null; 24329ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 24334213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 24344213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov final int interrogatingPid = Binder.getCallingPid(); 24354213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov final long identityToken = Binder.clearCallingIdentity(); 24361e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); 24374213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov try { 24387498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, 24397498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, 24407498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov spec); 2441152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return true; 24424213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } catch (RemoteException re) { 24434213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov if (DEBUG) { 24444213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); 24454213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 24464213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } finally { 24474213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov Binder.restoreCallingIdentity(identityToken); 24484213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 2449152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov return false; 24504213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 24514213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 24524213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov @Override 24538643aa0179e598e78d938c59035389054535a229Svetoslav Ganov public boolean performAccessibilityAction(int accessibilityWindowId, 2454aa780c110922148a6a4ba06734bb2b0bb8c98f93Svetoslav Ganov long accessibilityNodeId, int action, Bundle arguments, int interactionId, 245558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) 245658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov throws RemoteException { 245758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedWindowId; 24588643aa0179e598e78d938c59035389054535a229Svetoslav Ganov IAccessibilityInteractionConnection connection = null; 24598643aa0179e598e78d938c59035389054535a229Svetoslav Ganov synchronized (mLock) { 24600425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 24610425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 24620425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 246358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 246458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked( 2465ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 246658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 246758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return false; 246858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 246958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); 24705c4cd189f298b3ddb9a5e8afc5f68546a9f96726Svetoslav final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked( 24715c4cd189f298b3ddb9a5e8afc5f68546a9f96726Svetoslav this, resolvedWindowId); 2472e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov if (!permissionGranted) { 2473e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov return false; 2474e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov } else { 247579311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov connection = getConnectionLocked(resolvedWindowId); 247679311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov if (connection == null) { 2477e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov return false; 2478e8f95352cf4fd2bb38fd124bf5fcefddddeb0692Svetoslav Ganov } 24798643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 24808643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 24819bf21873c900e7bf82d864172ab40527a48dae3eSvetoslav Ganov final int interrogatingPid = Binder.getCallingPid(); 24828643aa0179e598e78d938c59035389054535a229Svetoslav Ganov final long identityToken = Binder.clearCallingIdentity(); 24838643aa0179e598e78d938c59035389054535a229Svetoslav Ganov try { 2484aa780c110922148a6a4ba06734bb2b0bb8c98f93Svetoslav Ganov connection.performAccessibilityAction(accessibilityNodeId, action, arguments, 248580943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid); 24868643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } catch (RemoteException re) { 24878643aa0179e598e78d938c59035389054535a229Svetoslav Ganov if (DEBUG) { 248879311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov Slog.e(LOG_TAG, "Error calling performAccessibilityAction()"); 24898643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 24908643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } finally { 24918643aa0179e598e78d938c59035389054535a229Svetoslav Ganov Binder.restoreCallingIdentity(identityToken); 24928643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 24938bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return true; 24948643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 24958643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 24967498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov @Override 2497e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov public boolean performGlobalAction(int action) { 249858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov synchronized (mLock) { 24990425d7f56b5c14484777357075b285d59996e6e9Svetoslav // We treat calls from a profile as if made by its parent as profiles 25000425d7f56b5c14484777357075b285d59996e6e9Svetoslav // share the accessibility state of the parent. The call below 25010425d7f56b5c14484777357075b285d59996e6e9Svetoslav // performs the current profile parent resolution. 250258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int resolvedUserId = mSecurityPolicy 250358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov .resolveCallingUserIdEnforcingPermissionsLocked( 2504ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav UserHandle.USER_CURRENT); 250558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (resolvedUserId != mCurrentUserId) { 250658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return false; 250758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 250858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 250958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 251058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov try { 251158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov switch (action) { 251258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov case AccessibilityService.GLOBAL_ACTION_BACK: { 251358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK); 251458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } return true; 251558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov case AccessibilityService.GLOBAL_ACTION_HOME: { 251658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME); 251758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } return true; 251858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov case AccessibilityService.GLOBAL_ACTION_RECENTS: { 251958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov openRecents(); 252058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } return true; 252158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: { 2522e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov expandNotifications(); 2523e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov } return true; 2524e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: { 2525e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov expandQuickSettings(); 252658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } return true; 2527e34560b21989eea54a139a0586d156ba573cc2eaAlan Viverette case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: { 2528e34560b21989eea54a139a0586d156ba573cc2eaAlan Viverette showGlobalActions(); 2529e34560b21989eea54a139a0586d156ba573cc2eaAlan Viverette } return true; 253058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 253158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return false; 253258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } finally { 253358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Binder.restoreCallingIdentity(identity); 2534005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov } 2535005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov } 2536005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov 25376ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov @Override 25386ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 25396ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP); 25406ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov synchronized (mLock) { 25416ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo() 25426ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov .loadLabel(mContext.getPackageManager())); 25436ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(", feedbackType" 25446ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); 254511adf6dc2438260c3e0d79cc189bcb4f6f15e9f4Svetoslav pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); 25466ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(", eventTypes=" 25476ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov + AccessibilityEvent.eventTypeToString(mEventTypes)); 25486ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append(", notificationTimeout=" + mNotificationTimeout); 25496ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov pw.append("]"); 25506ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov } 25516ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov } 25526ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov 25536ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov @Override 255475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov public void onServiceDisconnected(ComponentName componentName) { 2555f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov /* do nothing - #binderDied takes care */ 2556f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov } 2557f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov 25583a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav public void onAdded() throws RemoteException { 25593a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav linkToOwnDeathLocked(); 25603a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav final long identity = Binder.clearCallingIdentity(); 25613a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav try { 25623a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav mWindowManagerService.addWindowToken(mOverlayWindowToken, 25633a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY); 25643a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav } finally { 25653a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav Binder.restoreCallingIdentity(identity); 25663a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav } 25673a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav } 25683a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav 25693a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav public void onRemoved() { 25703a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav final long identity = Binder.clearCallingIdentity(); 25713a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav try { 25723a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav mWindowManagerService.removeWindowToken(mOverlayWindowToken, true); 25733a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav } finally { 25743a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav Binder.restoreCallingIdentity(identity); 25753a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav } 25763a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav unlinkToOwnDeathLocked(); 25773a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav } 25783a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav 25792602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav public void linkToOwnDeathLocked() throws RemoteException { 2580f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov mService.linkToDeath(this, 0); 2581f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov } 2582f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov 25832602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav public void unlinkToOwnDeathLocked() { 2584f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov mService.unlinkToDeath(this, 0); 2585f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov } 2586f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov 25872602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav public void resetLocked() { 2588d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov try { 2589d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov // Clear the proxy in the other process so this 2590d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov // IAccessibilityServiceConnection can be garbage collected. 25913a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav mServiceInterface.init(null, mId, null); 2592d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } catch (RemoteException re) { 2593d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov /* ignore */ 2594d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 2595d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov mService = null; 2596d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov mServiceInterface = null; 2597d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov } 2598d116d7c78a9c53f30a73bf273bd7618312cf3847Svetoslav Ganov 2599bfa1bf020859a03668f1af1d59f035c53a97c7e8Svetoslav Ganov public boolean isConnectedLocked() { 26002602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav return (mService != null); 26012602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav } 26022602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav 2603f9886f3ee9db23cc5a553b92e2aeff0ae842c915Svetoslav Ganov public void binderDied() { 260475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov synchronized (mLock) { 26052602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav // It is possible that this service's package was force stopped during 26062602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav // whose handling the death recipient is unlinked and still get a call 26072602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav // on binderDied since the call was made before we unlink but was 26082602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav // waiting on the lock we held during the force stop handling. 2609bfa1bf020859a03668f1af1d59f035c53a97c7e8Svetoslav Ganov if (!isConnectedLocked()) { 26102602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav return; 26112602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav } 2612bfa1bf020859a03668f1af1d59f035c53a97c7e8Svetoslav Ganov mWasConnectedAndDied = true; 2613c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mKeyEventDispatcher.flush(); 261457bf88508e0491caced22c4c592d33aba6d88129Svetoslav UserState userState = getUserStateLocked(mUserId); 26156f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav // The death recipient is unregistered in removeServiceLocked 26166f8218a442a8de50ef33d20263a59cd47c513e62Svetoslav removeServiceLocked(this, userState); 26172602a3974aafc9e9be968e7bfcf5b1e61dd3d8feSvetoslav resetLocked(); 2618b6eca6e6691d4563d8395b3c3843d9932a2a6560Svetoslav Ganov if (mIsAutomation) { 261957bf88508e0491caced22c4c592d33aba6d88129Svetoslav // We no longer have an automation service, so restore 262057bf88508e0491caced22c4c592d33aba6d88129Svetoslav // the state based on values in the settings database. 26217379a95a0bb6bf430eaf3b84ddb94e4172dd0eeaSvetoslav userState.mInstalledServices.remove(mAccessibilityServiceInfo); 26227379a95a0bb6bf430eaf3b84ddb94e4172dd0eeaSvetoslav userState.mEnabledServices.remove(mComponentName); 26233c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav userState.destroyUiAutomationService(); 2624dd81183bbea34109e1ae2d75667fe4784be6132fSvetoslav if (readConfigurationForUserStateLocked(userState)) { 2625dd81183bbea34109e1ae2d75667fe4784be6132fSvetoslav onUserStateChangedLocked(userState); 2626dd81183bbea34109e1ae2d75667fe4784be6132fSvetoslav } 2627b6eca6e6691d4563d8395b3c3843d9932a2a6560Svetoslav Ganov } 262875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 262975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov } 26308643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 2631e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov /** 2632e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov * Performs a notification for an {@link AccessibilityEvent}. 2633e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov * 2634e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov * @param event The event. 2635e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov */ 2636e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov public void notifyAccessibilityEvent(AccessibilityEvent event) { 2637e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov synchronized (mLock) { 2638e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov final int eventType = event.getEventType(); 2639e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // Make a copy since during dispatch it is possible the event to 2640e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // be modified to remove its source if the receiving service does 2641e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // not have permission to access the window content. 2642e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); 2643e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov AccessibilityEvent oldEvent = mPendingEvents.get(eventType); 2644e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov mPendingEvents.put(eventType, newEvent); 2645e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2646e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov final int what = eventType; 2647e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov if (oldEvent != null) { 2648c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mEventDispatchHandler.removeMessages(what); 2649e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov oldEvent.recycle(); 2650e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2651e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2652c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav Message message = mEventDispatchHandler.obtainMessage(what); 2653c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout); 2654e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2655e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2656e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2657e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov /** 2658e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov * Notifies an accessibility service client for a scheduled event given the event type. 2659e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov * 2660e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov * @param eventType The type of the event to dispatch. 2661e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov */ 2662e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov private void notifyAccessibilityEventInternal(int eventType) { 2663e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov IAccessibilityServiceClient listener; 2664e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov AccessibilityEvent event; 2665e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2666e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov synchronized (mLock) { 2667e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov listener = mServiceInterface; 2668e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2669e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // If the service died/was disabled while the message for dispatching 2670e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // the accessibility event was propagating the listener may be null. 2671e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov if (listener == null) { 2672e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov return; 2673e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2674e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2675e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov event = mPendingEvents.get(eventType); 2676e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2677e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // Check for null here because there is a concurrent scenario in which this 2678e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked 2679e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // which posts a message for dispatching an event. 2) The message is pulled 2680e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // from the queue by the handler on the service thread and the latter is 2681e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // just about to acquire the lock and call this method. 3) Now another binder 2682e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked 2683e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // so the service thread waits for the lock; 4) The binder thread replaces 2684e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // the event with a more recent one (assume the same event type) and posts a 2685e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // dispatch request releasing the lock. 5) Now the main thread is unblocked and 2686e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // dispatches the event which is removed from the pending ones. 6) And ... now 2687e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // the service thread handles the last message posted by the last binder call 2688e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // but the event is already dispatched and hence looking it up in the pending 2689e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // ones yields null. This check is much simpler that keeping count for each 2690e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // event type of each service to catch such a scenario since only one message 2691e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // is processed at a time. 2692e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov if (event == null) { 2693e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov return; 2694e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2695e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2696e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov mPendingEvents.remove(eventType); 26978e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) { 2698e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov event.setConnectionId(mId); 2699e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } else { 2700e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov event.setSource(null); 2701e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2702e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov event.setSealed(true); 2703e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2704e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2705e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov try { 2706e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov listener.onAccessibilityEvent(event); 2707e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov if (DEBUG) { 2708e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); 2709e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2710e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } catch (RemoteException re) { 2711e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); 2712e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } finally { 2713e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov event.recycle(); 2714e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2715e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2716e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2717e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov public void notifyGesture(int gestureId) { 2718c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, 2719c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav gestureId, 0).sendToTarget(); 2720c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2721c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2722c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public void notifyKeyEvent(KeyEvent event, int policyFlags) { 2723c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_KEY_EVENT, 2724c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav policyFlags, 0, event).sendToTarget(); 2725e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2726e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2727152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov public void notifyClearAccessibilityNodeInfoCache() { 2728c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mInvocationHandler.sendEmptyMessage( 27298e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); 27308e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 27318e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 2732e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov private void notifyGestureInternal(int gestureId) { 27338e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final IAccessibilityServiceClient listener; 27348e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 27358e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav listener = mServiceInterface; 27368e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 2737e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov if (listener != null) { 2738e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov try { 2739e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov listener.onGesture(gestureId); 2740e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } catch (RemoteException re) { 2741e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov Slog.e(LOG_TAG, "Error during sending gesture " + gestureId 2742e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov + " to " + mService, re); 2743e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2744e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2745e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 2746e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 2747c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private void notifyKeyEventInternal(KeyEvent event, int policyFlags) { 2748c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mKeyEventDispatcher.notifyKeyEvent(event, policyFlags); 2749c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2750c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 27518e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private void notifyClearAccessibilityCacheInternal() { 27528e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final IAccessibilityServiceClient listener; 27538e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 27548e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav listener = mServiceInterface; 27558e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 2756152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov if (listener != null) { 2757152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov try { 27588e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav listener.clearAccessibilityCache(); 2759152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov } catch (RemoteException re) { 2760152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov Slog.e(LOG_TAG, "Error during requesting accessibility info cache" 2761152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov + " to be cleared.", re); 2762152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov } 2763152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov } 2764152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov } 2765152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov 2766005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov private void sendDownAndUpKeyEvents(int keyCode) { 2767005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov final long token = Binder.clearCallingIdentity(); 2768005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov 2769005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov // Inject down. 2770005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov final long downTime = SystemClock.uptimeMillis(); 2771005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, 2772005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 2773005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov InputDevice.SOURCE_KEYBOARD, null); 2774005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov InputManager.getInstance().injectInputEvent(down, 2775005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 2776005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov down.recycle(); 2777005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov 2778005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov // Inject up. 2779005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov final long upTime = SystemClock.uptimeMillis(); 2780005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0, 2781005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, 2782005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov InputDevice.SOURCE_KEYBOARD, null); 2783005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov InputManager.getInstance().injectInputEvent(up, 2784005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 2785005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov up.recycle(); 2786005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov 2787005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov Binder.restoreCallingIdentity(token); 2788005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov } 2789005b83b0c62d3d0538f0d566b08bd457015ec661Svetoslav Ganov 2790e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov private void expandNotifications() { 2791e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov final long token = Binder.clearCallingIdentity(); 2792e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov 2793e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 2794e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov android.app.Service.STATUS_BAR_SERVICE); 279511cf178100e71d3f9f34ab5865e03a277c5eadaaDaniel Sandler statusBarManager.expandNotificationsPanel(); 2796e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov 2797e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov Binder.restoreCallingIdentity(token); 2798e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov } 2799e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov 2800e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov private void expandQuickSettings() { 28015c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganov final long token = Binder.clearCallingIdentity(); 28025c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganov 28035c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganov StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( 28045c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganov android.app.Service.STATUS_BAR_SERVICE); 280511cf178100e71d3f9f34ab5865e03a277c5eadaaDaniel Sandler statusBarManager.expandSettingsPanel(); 28065c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganov 28075c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganov Binder.restoreCallingIdentity(token); 28085c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganov } 28095c89f44ea16667bf18297ccb9fb10aad639dab1fSvetoslav Ganov 2810c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov private void openRecents() { 2811c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov final long token = Binder.clearCallingIdentity(); 2812c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov 2813c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov IStatusBarService statusBarService = IStatusBarService.Stub.asInterface( 2814c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov ServiceManager.getService("statusbar")); 2815c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov try { 2816c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov statusBarService.toggleRecentApps(); 2817c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov } catch (RemoteException e) { 2818c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov Slog.e(LOG_TAG, "Error toggling recent apps."); 2819c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov } 2820c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov 2821c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov Binder.restoreCallingIdentity(token); 2822c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov } 2823c682fc965df2518a95d23e39ec51d788100d20ecSvetoslav Ganov 2824e34560b21989eea54a139a0586d156ba573cc2eaAlan Viverette private void showGlobalActions() { 2825e34560b21989eea54a139a0586d156ba573cc2eaAlan Viverette mWindowManagerService.showGlobalActions(); 2826e34560b21989eea54a139a0586d156ba573cc2eaAlan Viverette } 2827e34560b21989eea54a139a0586d156ba573cc2eaAlan Viverette 282879311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov private IAccessibilityInteractionConnection getConnectionLocked(int windowId) { 28298643aa0179e598e78d938c59035389054535a229Svetoslav Ganov if (DEBUG) { 28308643aa0179e598e78d938c59035389054535a229Svetoslav Ganov Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId); 28318643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 283258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId); 283358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (wrapper == null) { 283458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId); 283558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 283679311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov if (wrapper != null && wrapper.mConnection != null) { 283779311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov return wrapper.mConnection; 283879311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov } 283979311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov if (DEBUG) { 284079311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov Slog.e(LOG_TAG, "No interaction connection to window: " + windowId); 284179311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov } 284279311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov return null; 284379311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov } 284479311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov 284558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { 28460d04e245534cf777dfaf16dce3c51553837c14ffSvetoslav Ganov if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) { 28473f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav return mSecurityPolicy.getActiveWindowId(); 284879311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov } 284979311c4af8b54d3cd47ab37a120c648bfc990511Svetoslav Ganov return accessibilityWindowId; 28508643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 28517961be75f4161769f620e44dec3f5911e50ebe03Svetoslav Ganov 28521e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { 28531e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (windowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) { 28541e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return mSecurityPolicy.mActiveWindowId; 28558e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 28561e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (windowId == AccessibilityNodeInfo.ANY_WINDOW_ID) { 28571e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) { 28581e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return mSecurityPolicy.mFocusedWindowId; 28591e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) { 28601e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return mSecurityPolicy.mAccessibilityFocusedWindowId; 28611e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 2862c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov } 28631e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return windowId; 28647961be75f4161769f620e44dec3f5911e50ebe03Svetoslav Ganov } 2865c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2866c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private final class InvocationHandler extends Handler { 2867c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public static final int MSG_ON_GESTURE = 1; 2868c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public static final int MSG_ON_KEY_EVENT = 2; 28698e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 3; 2870c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public static final int MSG_ON_KEY_EVENT_TIMEOUT = 4; 2871c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2872c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public InvocationHandler(Looper looper) { 2873c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav super(looper, null, true); 2874c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2875c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2876c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav @Override 2877c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public void handleMessage(Message message) { 2878c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav final int type = message.what; 2879c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav switch (type) { 2880c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav case MSG_ON_GESTURE: { 2881c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav final int gestureId = message.arg1; 2882c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav notifyGestureInternal(gestureId); 2883c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } break; 28848e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 2885c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav case MSG_ON_KEY_EVENT: { 2886c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav KeyEvent event = (KeyEvent) message.obj; 2887c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav final int policyFlags = message.arg1; 2888c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav notifyKeyEventInternal(event, policyFlags); 2889c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } break; 28908e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 28918e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case MSG_CLEAR_ACCESSIBILITY_CACHE: { 28928e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav notifyClearAccessibilityCacheInternal(); 2893c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } break; 28948e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 2895c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav case MSG_ON_KEY_EVENT_TIMEOUT: { 2896c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav PendingEvent eventState = (PendingEvent) message.obj; 2897c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav setOnKeyEventResult(false, eventState.sequence); 2898c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } break; 28998e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 2900c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav default: { 2901c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav throw new IllegalArgumentException("Unknown message: " + type); 2902c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2903c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2904c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2905c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2906c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2907c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private final class KeyEventDispatcher { 2908c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2909c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private static final long ON_KEY_EVENT_TIMEOUT_MILLIS = 500; 2910c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2911c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private PendingEvent mPendingEvents; 2912c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2913c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private final InputEventConsistencyVerifier mSentEventsVerifier = 2914c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav InputEventConsistencyVerifier.isInstrumentationEnabled() 2915c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav ? new InputEventConsistencyVerifier( 2916c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav this, 0, KeyEventDispatcher.class.getSimpleName()) : null; 2917c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2918c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public void notifyKeyEvent(KeyEvent event, int policyFlags) { 2919c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav final PendingEvent pendingEvent; 2920c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2921c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav synchronized (mLock) { 2922c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent = addPendingEventLocked(event, policyFlags); 2923c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2924c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2925c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav Message message = mInvocationHandler.obtainMessage( 2926c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent); 2927c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mInvocationHandler.sendMessageDelayed(message, ON_KEY_EVENT_TIMEOUT_MILLIS); 2928c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2929c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav try { 2930c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // Accessibility services are exclusively not in the system 2931c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // process, therefore no need to clone the motion event to 2932c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // prevent tampering. It will be cloned in the IPC call. 2933c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mServiceInterface.onKeyEvent(pendingEvent.event, pendingEvent.sequence); 2934c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } catch (RemoteException re) { 2935c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav setOnKeyEventResult(false, pendingEvent.sequence); 2936c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2937c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2938c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2939c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public void setOnKeyEventResult(boolean handled, int sequence) { 2940c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav synchronized (mLock) { 2941c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav PendingEvent pendingEvent = removePendingEventLocked(sequence); 2942c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (pendingEvent != null) { 2943c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mInvocationHandler.removeMessages( 2944c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, 2945c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent); 2946c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent.handled = handled; 2947c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav finishPendingEventLocked(pendingEvent); 2948c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2949c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2950c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2951c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2952c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public void flush() { 2953c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav synchronized (mLock) { 2954c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav cancelAllPendingEventsLocked(); 29551487cd5afc23c4c8f0a069bbcf9cdb3f40692449Svetoslav if (mSentEventsVerifier != null) { 29561487cd5afc23c4c8f0a069bbcf9cdb3f40692449Svetoslav mSentEventsVerifier.reset(); 29571487cd5afc23c4c8f0a069bbcf9cdb3f40692449Svetoslav } 2958c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2959c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2960c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2961c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private PendingEvent addPendingEventLocked(KeyEvent event, int policyFlags) { 2962c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav final int sequence = event.getSequenceNumber(); 2963c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav PendingEvent pendingEvent = obtainPendingEventLocked(event, policyFlags, sequence); 2964c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent.next = mPendingEvents; 2965c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mPendingEvents = pendingEvent; 2966c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav return pendingEvent; 2967c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2968c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2969c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private PendingEvent removePendingEventLocked(int sequence) { 2970c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav PendingEvent previous = null; 2971c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav PendingEvent current = mPendingEvents; 2972c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2973c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav while (current != null) { 2974c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (current.sequence == sequence) { 2975c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (previous != null) { 2976c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav previous.next = current.next; 2977c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } else { 2978c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mPendingEvents = current.next; 2979c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2980c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav current.next = null; 2981c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav return current; 2982c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2983c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav previous = current; 2984c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav current = current.next; 2985c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2986c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav return null; 2987c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2988c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2989c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private void finishPendingEventLocked(PendingEvent pendingEvent) { 2990c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (!pendingEvent.handled) { 2991c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav sendKeyEventToInputFilter(pendingEvent.event, pendingEvent.policyFlags); 2992c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2993c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // Nullify the event since we do not want it to be 2994c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav // recycled yet. It will be sent to the input filter. 2995c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent.event = null; 2996c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav recyclePendingEventLocked(pendingEvent); 2997c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 2998c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 2999c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private void sendKeyEventToInputFilter(KeyEvent event, int policyFlags) { 3000c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (DEBUG) { 3001c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav Slog.i(LOG_TAG, "Injecting event: " + event); 3002c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 3003c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (mSentEventsVerifier != null) { 3004c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mSentEventsVerifier.onKeyEvent(event, 0); 3005c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 3006c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER; 3007c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mMainHandler.obtainMessage(MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, 3008c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav policyFlags, 0, event).sendToTarget(); 3009c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 3010c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 3011c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private void cancelAllPendingEventsLocked() { 3012c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav while (mPendingEvents != null) { 3013c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav PendingEvent pendingEvent = removePendingEventLocked(mPendingEvents.sequence); 3014c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent.handled = false; 3015c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav mInvocationHandler.removeMessages(InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, 3016c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav pendingEvent); 3017c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav finishPendingEventLocked(pendingEvent); 3018c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 3019c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 3020c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 3021c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 3022c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 3023c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav private static final class PendingEvent { 3024c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav PendingEvent next; 3025c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 3026c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav KeyEvent event; 3027c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav int policyFlags; 3028c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav int sequence; 3029c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav boolean handled; 3030c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav 3031c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav public void clear() { 3032c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav if (event != null) { 3033c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav event.recycle(); 3034c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav event = null; 3035c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 3036c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav next = null; 3037c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav policyFlags = 0; 3038c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav sequence = 0; 3039c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav handled = false; 3040c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav } 30418643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 30428643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 30438e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final class WindowsForAccessibilityCallback implements 30448e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav WindowManagerInternal.WindowsForAccessibilityCallback { 30458e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 30468e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav @Override 30478e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) { 30488e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 30498e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // Populate the windows to report. 3050a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>(); 3051a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav final int receivedWindowCount = windows.size(); 30528e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav for (int i = 0; i < receivedWindowCount; i++) { 3053a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav WindowInfo receivedWindow = windows.get(i); 30548e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo reportedWindow = populateReportedWindow( 30558e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav receivedWindow); 30568e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (reportedWindow != null) { 30578e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav reportedWindows.add(reportedWindow); 30588e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 30598e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 30608e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 30618e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (DEBUG) { 30628e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav Slog.i(LOG_TAG, "Windows changed: " + reportedWindows); 30638e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 30648e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 30658e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // Let the policy update the focused and active windows. 30668e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mSecurityPolicy.updateWindowsLocked(reportedWindows); 306704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav 306804cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav // Someone may be waiting for the windows - advertise it. 306904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav mLock.notifyAll(); 30708e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 30718e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 30728e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 30738e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) { 30748e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int windowId = findWindowIdLocked(window.token); 30758e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (windowId < 0) { 30768e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return null; 30778e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 30788e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 30798e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain(); 30808e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 30818e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav reportedWindow.setId(windowId); 30828e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav reportedWindow.setType(getTypeForWindowManagerWindowType(window.type)); 30838e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav reportedWindow.setLayer(window.layer); 30848e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav reportedWindow.setFocused(window.focused); 30858e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav reportedWindow.setBoundsInScreen(window.boundsInScreen); 30868e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 30878e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int parentId = findWindowIdLocked(window.parentToken); 30888e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (parentId >= 0) { 30898e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav reportedWindow.setParentId(parentId); 30908e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 30918e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 30928e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (window.childTokens != null) { 30938e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int childCount = window.childTokens.size(); 30948e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav for (int i = 0; i < childCount; i++) { 30958e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav IBinder childToken = window.childTokens.get(i); 30968e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int childId = findWindowIdLocked(childToken); 30978e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (childId >= 0) { 30988e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav reportedWindow.addChild(childId); 30998e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31008e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31018e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31028e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 31038e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return reportedWindow; 31048e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31058e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 31068e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private int getTypeForWindowManagerWindowType(int windowType) { 31078e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav switch (windowType) { 31088e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_APPLICATION: 31098e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA: 31108e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL: 31118e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING: 31128e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL: 31138e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_BASE_APPLICATION: 31148e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_PHONE: 31158e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE: 31168e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_TOAST: 31178e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: { 31188e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return AccessibilityWindowInfo.TYPE_APPLICATION; 31198e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31208e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 31218e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 31228e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: { 31238e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return AccessibilityWindowInfo.TYPE_INPUT_METHOD; 31248e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31258e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 31268e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG: 31278e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 31288e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: 31298e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_SEARCH_BAR: 31308e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_STATUS_BAR: 31318e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL: 31328e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL: 31338e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY: 31348e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT: 31358e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG: 31368e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR: 31378e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: { 31388e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return AccessibilityWindowInfo.TYPE_SYSTEM; 31398e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31408e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 31413a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: { 31423a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY; 31433a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav } 31443a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bbSvetoslav 31458e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav default: { 31468e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return -1; 31478e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31488e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31498e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31508e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 31518e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 31521e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private final class InteractionBridge { 31531e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private final Display mDefaultDisplay; 31541e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private final int mConnectionId; 31551e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private final AccessibilityInteractionClient mClient; 31561e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 31571e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public InteractionBridge() { 31581e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 31591e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 31601e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; 31611e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 31621e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav Service service = new Service(UserHandle.USER_NULL, 31631e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav sFakeAccessibilityServiceComponentName, info); 31641e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 31651e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mConnectionId = service.mId; 31661e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 31671e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mClient = AccessibilityInteractionClient.getInstance(); 31681e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mClient.addConnection(mConnectionId, service); 31691e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 31701e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav //TODO: (multi-display) We need to support multiple displays. 31711e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav DisplayManager displayManager = (DisplayManager) 31721e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mContext.getSystemService(Context.DISPLAY_SERVICE); 31731e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); 31741e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 31751e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 31761e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public void clearAccessibilityFocusNotLocked(int windowId) { 31771e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId); 31781e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (focus != null) { 31791e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 31801e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 31811e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 31821e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 31837498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) { 31841e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(); 31851e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (focus == null) { 31861e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return false; 31871e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 31881e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 31891e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav synchronized (mLock) { 3190ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav Rect boundsInScreen = mTempRect; 3191ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav focus.getBoundsInScreen(boundsInScreen); 31927498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov 3193ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav // Clip to the window bounds. 3194ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav Rect windowBounds = mTempRect1; 3195ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav getWindowBounds(focus.getWindowId(), windowBounds); 3196ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav boundsInScreen.intersect(windowBounds); 3197ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav if (boundsInScreen.isEmpty()) { 31987498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov return false; 31997498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov } 32001e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 3201ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav // Apply magnification if needed. 32021e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId()); 32031e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (spec != null && !spec.isNop()) { 3204ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY); 3205ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav boundsInScreen.scale(1 / spec.scale); 32061e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 32071e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 3208ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav // Clip to the screen bounds. 32097498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov Point screenSize = mTempPoint; 32107498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov mDefaultDisplay.getRealSize(screenSize); 3211ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y); 3212ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav if (boundsInScreen.isEmpty()) { 32137498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov return false; 32147498efdc5e163d6b4a11db941c7d13c169d37284Svet Ganov } 32151e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 3216ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY()); 32171e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 3218ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav 3219ded133c446fa9d0d23e6bde19a66fb2ce3980491Svetoslav return true; 32201e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 32211e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 32221e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private AccessibilityNodeInfo getAccessibilityFocusNotLocked() { 32231e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav final int focusedWindowId; 32241e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav synchronized (mLock) { 32251e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId; 32261e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) { 32271e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return null; 32281e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 32291e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 32301e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return getAccessibilityFocusNotLocked(focusedWindowId); 32311e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 32321e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 32331e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) { 32341e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav return mClient.findFocus(mConnectionId, 32351e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav windowId, AccessibilityNodeInfo.ROOT_NODE_ID, 32361e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); 32371e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 32381e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 32391e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 32408643aa0179e598e78d938c59035389054535a229Svetoslav Ganov final class SecurityPolicy { 32411e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public static final int INVALID_WINDOW_ID = -1; 32421e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 32438643aa0179e598e78d938c59035389054535a229Svetoslav Ganov private static final int RETRIEVAL_ALLOWING_EVENT_TYPES = 32444213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov AccessibilityEvent.TYPE_VIEW_CLICKED 32454213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_FOCUSED 32464213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 32474213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 32484213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 32494213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 32504213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 32514213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_SELECTED 3252a0156177cdc809795dd8bc5a19943dd2b6f82b66Svetoslav Ganov | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED 3253a0156177cdc809795dd8bc5a19943dd2b6f82b66Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 32544213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_SCROLLED 32554213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 32568e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED 32578e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 32588e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 325904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav public List<AccessibilityWindowInfo> mWindows; 32608e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 32611e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public int mActiveWindowId = INVALID_WINDOW_ID; 32621e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public int mFocusedWindowId = INVALID_WINDOW_ID; 32631e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; 32641e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 32651e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 32666ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov private boolean mTouchInteractionInProgress; 32678643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 32688e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) { 326958fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov final int eventType = event.getEventType(); 327058fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov switch (eventType) { 327158fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov // All events that are for changes in a global window 327258fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov // state should *always* be dispatched. 327358fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: 327458fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: 3275ba3787d849610a7c71fc6f0d9468855c3d369807Kristian Monsen case AccessibilityEvent.TYPE_ANNOUNCEMENT: 327658fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov // All events generated by the user touching the 327758fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov // screen should *always* be dispatched. 327858fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: 327958fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: 328058fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_GESTURE_DETECTION_START: 328158fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_GESTURE_DETECTION_END: 328258fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START: 328358fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END: 328458fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: 3285a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: 3286a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav // Also windows changing should always be anounced. 3287a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav case AccessibilityEvent.TYPE_WINDOWS_CHANGED: { 328858fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov return true; 328958fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov } 329058fd9f8d6ad6bf1975e834f1a69e68673db9a452Svetoslav Ganov // All events for changes in window content should be 32918e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // dispatched *only* if this window is one of the windows 32928e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // the accessibility layer reports which are windows 32938e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // that a sighted user can touch. 32948e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav default: { 32958e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return isRetrievalAllowingWindow(event.getWindowId()); 32968e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 32978e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 32988e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 32998e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 330004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav public void clearWindowsLocked() { 330104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav List<AccessibilityWindowInfo> windows = Collections.emptyList(); 33023f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav final int activeWindowId = mActiveWindowId; 330304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav updateWindowsLocked(windows); 33043f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav mActiveWindowId = activeWindowId; 330504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav mWindows = null; 330604cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 330704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav 33088e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) { 330904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mWindows == null) { 331004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav mWindows = new ArrayList<>(); 331104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 331204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav 33138e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int oldWindowCount = mWindows.size(); 33148e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav for (int i = oldWindowCount - 1; i >= 0; i--) { 33158e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mWindows.remove(i).recycle(); 33168e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 33178e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 33181e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mFocusedWindowId = INVALID_WINDOW_ID; 33198e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (!mTouchInteractionInProgress) { 33201e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mActiveWindowId = INVALID_WINDOW_ID; 33218e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 33228e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 33238e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // If the active window goes away while the user is touch exploring we 33248e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // reset the active window id and wait for the next hover event from 33258e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // under the user's finger to determine which one is the new one. It 33268e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // is possible that the finger is not moving and the input system 33278e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // filters out such events. 33288e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav boolean activeWindowGone = true; 33298e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 33308e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int windowCount = windows.size(); 33318e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (windowCount > 0) { 33328e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav for (int i = 0; i < windowCount; i++) { 33338e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo window = windows.get(i); 33348e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav final int windowId = window.getId(); 33358e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (window.isFocused()) { 33368e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mFocusedWindowId = windowId; 33378e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (!mTouchInteractionInProgress) { 33388e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mActiveWindowId = windowId; 33398e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav window.setActive(true); 33408e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } else if (windowId == mActiveWindowId) { 33418e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav activeWindowGone = false; 33428e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 33438e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 33448e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mWindows.add(window); 33458e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 33468e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 33478e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (mTouchInteractionInProgress && activeWindowGone) { 33484604abc97d7dd757bb76ff9b7fcf343dc4a15212Svetoslav mActiveWindowId = mFocusedWindowId; 33498e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 33508e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 33518e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // Focused window may change the active one, so set the 33528e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // active window once we decided which it is. 33538e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav for (int i = 0; i < windowCount; i++) { 33548e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav AccessibilityWindowInfo window = mWindows.get(i); 33558e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (window.getId() == mActiveWindowId) { 3356f7174e87b6007000777b0124de9cef70d8618788Svetoslav window.setActive(true); 33578e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 335804cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (window.getId() == mAccessibilityFocusedWindowId) { 335904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav window.setAccessibilityFocused(true); 336004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 33618e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 33628e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 33638e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 3364a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav notifyWindowsChanged(); 3365eeee4d2c01d3c4ed99e4891dbc75c7de69a803faSvetoslav Ganov } 3366eeee4d2c01d3c4ed99e4891dbc75c7de69a803faSvetoslav Ganov 33679ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav public boolean computePartialInteractiveRegionForWindowLocked(int windowId, 33689ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Region outRegion) { 33699ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (mWindows == null) { 33709ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav return false; 33719ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 33729ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav 337312b7328c0b7f83a233d9387eaa66d1a0ed403724Svet Ganov // Windows are ordered in z order so start from the bottom and find 33749ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav // the window of interest. After that all windows that cover it should 33759ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav // be subtracted from the resulting region. Note that for accessibility 33769ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav // we are returning only interactive windows. 33779ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Region windowInteractiveRegion = null; 33789ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav boolean windowInteractiveRegionChanged = false; 33799ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav 33809ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav final int windowCount = mWindows.size(); 33819ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav for (int i = windowCount - 1; i >= 0; i--) { 33829ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav AccessibilityWindowInfo currentWindow = mWindows.get(i); 33839ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (windowInteractiveRegion == null) { 33849ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (currentWindow.getId() == windowId) { 33859ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Rect currentWindowBounds = mTempRect; 33869ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav currentWindow.getBoundsInScreen(currentWindowBounds); 33879ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav outRegion.set(currentWindowBounds); 33889ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav windowInteractiveRegion = outRegion; 33899ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav continue; 33909ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 339112b7328c0b7f83a233d9387eaa66d1a0ed403724Svet Ganov } else if (currentWindow.getType() 339212b7328c0b7f83a233d9387eaa66d1a0ed403724Svet Ganov != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) { 33939ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav Rect currentWindowBounds = mTempRect; 33949ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav currentWindow.getBoundsInScreen(currentWindowBounds); 33959ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) { 33969ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav windowInteractiveRegionChanged = true; 33979ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 33989ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 33999ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 34009ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav 34019ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav return windowInteractiveRegionChanged; 34029ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav } 34039ae9ed24aa252acbc2e6288068b991dd5291967bSvetoslav 3404a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov public void updateEventSourceLocked(AccessibilityEvent event) { 3405a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) { 3406a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov event.setSource(null); 3407a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov } 3408a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov } 3409a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov 34101e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, 34111e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav int eventType) { 3412e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // The active window is either the window that has input focus or 3413e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // the window that the user is currently touching. If the user is 3414e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // touching a window that does not have input focus as soon as the 3415e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov // the user stops touching that window the focused window becomes 34168e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // the active one. Here we detect the touched window and make it 34178e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // active. In updateWindowsLocked() we update the focused window 34188e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // and if the user is not touching the screen, we make the focused 34198e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // window the active one. 3420e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov switch (eventType) { 3421e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: { 34228e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // If no service has the capability to introspect screen, 34238e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // we do not register callback in the window manager for 34248e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // window changes, so we have to ask the window manager 34258e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // what the focused window is to update the active one. 34268e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // The active window also determined events from which 34278e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // windows are delivered. 34288e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 34294604abc97d7dd757bb76ff9b7fcf343dc4a15212Svetoslav if (mWindowsForAccessibilityCallback == null) { 34304604abc97d7dd757bb76ff9b7fcf343dc4a15212Svetoslav mFocusedWindowId = getFocusedWindowId(); 34314604abc97d7dd757bb76ff9b7fcf343dc4a15212Svetoslav if (windowId == mFocusedWindowId) { 34324604abc97d7dd757bb76ff9b7fcf343dc4a15212Svetoslav mActiveWindowId = windowId; 34334604abc97d7dd757bb76ff9b7fcf343dc4a15212Svetoslav } 34348e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 3435e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 3436e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } break; 34378e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 3438f772cba59760d1ad9eb5cb9205b2e2e9126e488dSvetoslav Ganov case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: { 34396ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov // Do not allow delayed hover events to confuse us 34406ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov // which the active window is. 34418e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 34428e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (mTouchInteractionInProgress && mActiveWindowId != windowId) { 34438e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav setActiveWindowLocked(windowId); 34448e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 34456ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov } 3446e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } break; 34471e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 34481e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: { 34491e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav synchronized (mLock) { 34501e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (mAccessibilityFocusedWindowId != windowId) { 34511e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, 34521e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mAccessibilityFocusedWindowId, 0).sendToTarget(); 345304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId); 34541e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mAccessibilityFocusNodeId = nodeId; 34551e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 34561e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 34571e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } break; 34581e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 34591e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: { 34601e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav synchronized (mLock) { 34611e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (mAccessibilityFocusNodeId == nodeId) { 34621e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 34631e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 34641e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID 34651e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav && mAccessibilityFocusedWindowId == windowId) { 34661e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; 34671e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 34681e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 34691e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } break; 34704e2a762eae1f6981d32e6098a95498865ad7f795Svetoslav Ganov } 34718643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 34728643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 34736ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov public void onTouchInteractionStart() { 34748e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 34758e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mTouchInteractionInProgress = true; 34768e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 34776ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov } 34786ae8a24fc045bc7970f2843fa9baf06aff15e22dSvetoslav Ganov 3479f772cba59760d1ad9eb5cb9205b2e2e9126e488dSvetoslav Ganov public void onTouchInteractionEnd() { 34808e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav synchronized (mLock) { 34818e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mTouchInteractionInProgress = false; 34828e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // We want to set the active window to be current immediately 34838e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // after the user has stopped touching the screen since if the 34848e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // user types with the IME he should get a feedback for the 34858e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // letter typed in the text view which is in the input focused 34868e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // window. Note that we always deliver hover accessibility events 34878e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // (they are a result of user touching the screen) so change of 34888e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // the active window before all hover accessibility events from 34898e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav // the touched window are delivered is fine. 34901e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav final int oldActiveWindow = mSecurityPolicy.mActiveWindowId; 34918e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav setActiveWindowLocked(mFocusedWindowId); 34921e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav 34931e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // If there is no service that can operate with active windows 34941e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // we keep accessibility focus behavior to constrain it only in 34951e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // the active window. Look at updateAccessibilityFocusBehaviorLocked 34961e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav // for details. 34971e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav if (oldActiveWindow != mSecurityPolicy.mActiveWindowId 34981e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav && mAccessibilityFocusedWindowId == oldActiveWindow 34991e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) { 35001e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, 35011e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav oldActiveWindow, 0).sendToTarget(); 35021e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav } 35038e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 3504f772cba59760d1ad9eb5cb9205b2e2e9126e488dSvetoslav Ganov } 3505f772cba59760d1ad9eb5cb9205b2e2e9126e488dSvetoslav Ganov 35063f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav public int getActiveWindowId() { 35073f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) { 35083f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav mActiveWindowId = getFocusedWindowId(); 35093f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav } 35103f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav return mActiveWindowId; 35113f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav } 35123f92ffc369c31c98620e22b66366adb93c60a5f8Svetoslav 35138e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private void setActiveWindowLocked(int windowId) { 35148e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (mActiveWindowId != windowId) { 35158e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav mActiveWindowId = windowId; 351604cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mWindows != null) { 351704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav final int windowCount = mWindows.size(); 351804cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav for (int i = 0; i < windowCount; i++) { 351904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav AccessibilityWindowInfo window = mWindows.get(i); 352004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav window.setActive(window.getId() == windowId); 352104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 352204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 352304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav notifyWindowsChanged(); 352404cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 352504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 352604cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav 352704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav private void setAccessibilityFocusedWindowLocked(int windowId) { 352804cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mAccessibilityFocusedWindowId != windowId) { 352904cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav mAccessibilityFocusedWindowId = windowId; 353004cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mWindows != null) { 353104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav final int windowCount = mWindows.size(); 353204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav for (int i = 0; i < windowCount; i++) { 353304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav AccessibilityWindowInfo window = mWindows.get(i); 353404cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav window.setAccessibilityFocused(window.getId() == windowId); 353504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 35368e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 353704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav 3538a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav notifyWindowsChanged(); 35398e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 35408643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 35418643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 3542a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav private void notifyWindowsChanged() { 354347b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav if (mWindowsForAccessibilityCallback == null) { 354447b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav return; 354547b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav } 35469bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav final long identity = Binder.clearCallingIdentity(); 35479bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav try { 35489bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav // Let the client know the windows changed. 35499bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav AccessibilityEvent event = AccessibilityEvent.obtain( 35509bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav AccessibilityEvent.TYPE_WINDOWS_CHANGED); 35519bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav event.setEventTime(SystemClock.uptimeMillis()); 35529bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav sendAccessibilityEvent(event, mCurrentUserId); 35539bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav } finally { 35549bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav Binder.restoreCallingIdentity(identity); 35559bf08c7bc1844ec8130b47d0ec3783f374b21c46Svetoslav } 3556a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav } 3557a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav 35588643aa0179e598e78d938c59035389054535a229Svetoslav Ganov public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) { 35598e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId); 35608643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 35618643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 35628e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav public boolean canRetrieveWindowsLocked(Service service) { 35638e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows; 35648643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 35658643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 35668e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav public boolean canRetrieveWindowContentLocked(Service service) { 35678e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return (service.mAccessibilityServiceInfo.getCapabilities() 35688e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; 35694a49d9fe52a76c7f91f81113e0a8e9f97ac3f24cSvetoslav Ganov } 35704a49d9fe52a76c7f91f81113e0a8e9f97ac3f24cSvetoslav Ganov 35710425d7f56b5c14484777357075b285d59996e6e9Svetoslav private int resolveProfileParentLocked(int userId) { 35720425d7f56b5c14484777357075b285d59996e6e9Svetoslav if (userId != mCurrentUserId) { 35730425d7f56b5c14484777357075b285d59996e6e9Svetoslav final long identity = Binder.clearCallingIdentity(); 35740425d7f56b5c14484777357075b285d59996e6e9Svetoslav try { 35750425d7f56b5c14484777357075b285d59996e6e9Svetoslav UserInfo parent = mUserManager.getProfileParent(userId); 35760425d7f56b5c14484777357075b285d59996e6e9Svetoslav if (parent != null) { 35770425d7f56b5c14484777357075b285d59996e6e9Svetoslav return parent.getUserHandle().getIdentifier(); 35780425d7f56b5c14484777357075b285d59996e6e9Svetoslav } 35790425d7f56b5c14484777357075b285d59996e6e9Svetoslav } finally { 35800425d7f56b5c14484777357075b285d59996e6e9Svetoslav Binder.restoreCallingIdentity(identity); 35810425d7f56b5c14484777357075b285d59996e6e9Svetoslav } 35820425d7f56b5c14484777357075b285d59996e6e9Svetoslav } 35830425d7f56b5c14484777357075b285d59996e6e9Svetoslav return userId; 35840425d7f56b5c14484777357075b285d59996e6e9Svetoslav } 35850425d7f56b5c14484777357075b285d59996e6e9Svetoslav 358658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) { 358758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int callingUid = Binder.getCallingUid(); 3588d08d7ee4e9ce8c388e5dba392e2a6b156180dabcSvetoslav if (callingUid == 0 3589d08d7ee4e9ce8c388e5dba392e2a6b156180dabcSvetoslav || callingUid == Process.SYSTEM_UID 359058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov || callingUid == Process.SHELL_UID) { 35910425d7f56b5c14484777357075b285d59996e6e9Svetoslav if (userId == UserHandle.USER_CURRENT 35920425d7f56b5c14484777357075b285d59996e6e9Svetoslav || userId == UserHandle.USER_CURRENT_OR_SELF) { 35930425d7f56b5c14484777357075b285d59996e6e9Svetoslav return mCurrentUserId; 35940425d7f56b5c14484777357075b285d59996e6e9Svetoslav } 35950425d7f56b5c14484777357075b285d59996e6e9Svetoslav return resolveProfileParentLocked(userId); 359658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 359758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int callingUserId = UserHandle.getUserId(callingUid); 359858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (callingUserId == userId) { 35990425d7f56b5c14484777357075b285d59996e6e9Svetoslav return resolveProfileParentLocked(userId); 360058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 3601ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav final int callingUserParentId = resolveProfileParentLocked(callingUserId); 3602ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav if (callingUserParentId == mCurrentUserId && 3603ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav (userId == UserHandle.USER_CURRENT 3604ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav || userId == UserHandle.USER_CURRENT_OR_SELF)) { 3605ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav return mCurrentUserId; 3606ceac51deddb873956c647d1b2dc7b2cc251d404bSvetoslav } 360758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS) 360858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) { 360958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov throw new SecurityException("Call from user " + callingUserId + " as user " 361058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov + userId + " without permission INTERACT_ACROSS_USERS or " 361158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov + "INTERACT_ACROSS_USERS_FULL not allowed."); 361258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 361358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov if (userId == UserHandle.USER_CURRENT 361458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov || userId == UserHandle.USER_CURRENT_OR_SELF) { 361558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return mCurrentUserId; 361658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 361758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov throw new IllegalArgumentException("Calling user can be changed to only " 361858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF."); 361958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 362058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 362158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public boolean isCallerInteractingAcrossUsers(int userId) { 362258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov final int callingUid = Binder.getCallingUid(); 3623a8afa694d6881266ad762aacdac92b2047f9a86cSvetoslav Ganov return (Binder.getCallingPid() == android.os.Process.myPid() 362458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov || callingUid == Process.SHELL_UID 362558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov || userId == UserHandle.USER_CURRENT 362658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov || userId == UserHandle.USER_CURRENT_OR_SELF); 362758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 362858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 36298643aa0179e598e78d938c59035389054535a229Svetoslav Ganov private boolean isRetrievalAllowingWindow(int windowId) { 363047b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav // The system gets to interact with any window it wants. 363147b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav if (Binder.getCallingUid() == Process.SYSTEM_UID) { 363247b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav return true; 363347b9c1524fe20b9ae2b210acdcad64f764df68e0Svetoslav } 36348e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav if (windowId == mActiveWindowId) { 36358e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return true; 36368e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 36378e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return findWindowById(windowId) != null; 36388e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 36398e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav 36408e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav private AccessibilityWindowInfo findWindowById(int windowId) { 364104cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (mWindows != null) { 364204cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav final int windowCount = mWindows.size(); 364304cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav for (int i = 0; i < windowCount; i++) { 364404cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav AccessibilityWindowInfo window = mWindows.get(i); 364504cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav if (window.getId() == windowId) { 364604cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav return window; 364704cab1bcc46b05cbb72632c53ad83943f705b494Svetoslav } 36488e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 36498e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav } 36508e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav return null; 36518643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 36528643aa0179e598e78d938c59035389054535a229Svetoslav Ganov 36538643aa0179e598e78d938c59035389054535a229Svetoslav Ganov private void enforceCallingPermission(String permission, String function) { 36548643aa0179e598e78d938c59035389054535a229Svetoslav Ganov if (OWN_PROCESS_ID == Binder.getCallingPid()) { 36558643aa0179e598e78d938c59035389054535a229Svetoslav Ganov return; 36568643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 36579371a0a0c0cdf9be0e0a32e4c3037cc2e216cfa0Svetoslav Ganov if (!hasPermission(permission)) { 36588643aa0179e598e78d938c59035389054535a229Svetoslav Ganov throw new SecurityException("You do not have " + permission 36596ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov + " required to call " + function + " from pid=" 36606ce77cdd6aff7193c746cd1eb87d5babf9158bacSvetoslav Ganov + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 36618643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 36628643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 3663e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov 366458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private boolean hasPermission(String permission) { 366558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED; 366658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 366758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 3668e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov private int getFocusedWindowId() { 36698e3feb15c5aec2c72b0ef120a1da325e1e8f0ddaSvetoslav IBinder token = mWindowManagerService.getFocusedWindowToken(); 3670cbcc9695f0a701d620f48de75eaee05c4fef6f22Svetoslav synchronized (mLock) { 3671cbcc9695f0a701d620f48de75eaee05c4fef6f22Svetoslav return findWindowIdLocked(token); 3672cbcc9695f0a701d620f48de75eaee05c4fef6f22Svetoslav } 3673e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov } 36748643aa0179e598e78d938c59035389054535a229Svetoslav Ganov } 367558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 367658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private class UserState { 367758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public final int mUserId; 367858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 36795fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // Non-transient state. 368058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 368158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public final RemoteCallbackList<IAccessibilityManagerClient> mClients = 3682a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new RemoteCallbackList<>(); 368358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 36845fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections = 3685a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new SparseArray<>(); 36865fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 3687a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav public final SparseArray<IBinder> mWindowTokens = new SparseArray<>(); 36885fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 36895fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // Transient state. 36905fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 36915fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav public final CopyOnWriteArrayList<Service> mBoundServices = 3692a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new CopyOnWriteArrayList<>(); 36935fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 369458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public final Map<ComponentName, Service> mComponentNameToServiceMap = 3695a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new HashMap<>(); 369658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 369758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public final List<AccessibilityServiceInfo> mInstalledServices = 3698a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new ArrayList<>(); 369958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 3700a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav public final Set<ComponentName> mBindingServices = new HashSet<>(); 370157bf88508e0491caced22c4c592d33aba6d88129Svetoslav 3702a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav public final Set<ComponentName> mEnabledServices = new HashSet<>(); 370358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 3704447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov public final Set<ComponentName> mTouchExplorationGrantedServices = 3705a4725efd0bfa52cbddf6ca587d37fc4ebcbfaf72Svetoslav new HashSet<>(); 3706447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 370758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public int mHandledFeedbackTypes = 0; 370858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 37095fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav public int mLastSentClientState = -1; 371057bf88508e0491caced22c4c592d33aba6d88129Svetoslav 371158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public boolean mIsAccessibilityEnabled; 371258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public boolean mIsTouchExplorationEnabled; 3713cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik public boolean mIsTextHighContrastEnabled; 37143822896e226567c6cd3ef84518d318abd33a7624Svetoslav public boolean mIsEnhancedWebAccessibilityEnabled; 371558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public boolean mIsDisplayMagnificationEnabled; 3716ca523d6e95061f99455589512100839118044d43Svetoslav public boolean mIsFilterKeyEventsEnabled; 3717410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette public boolean mHasDisplayColorAdjustment; 37181e0d4af9986c8c2a658769a63bf8b385d25e0435Svetoslav public boolean mAccessibilityFocusOnlyInActiveWindow; 371958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 372057bf88508e0491caced22c4c592d33aba6d88129Svetoslav private Service mUiAutomationService; 372157bf88508e0491caced22c4c592d33aba6d88129Svetoslav private IAccessibilityServiceClient mUiAutomationServiceClient; 372257bf88508e0491caced22c4c592d33aba6d88129Svetoslav 37233c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav private IBinder mUiAutomationServiceOwner; 37243c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient = 37253c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav new DeathRecipient() { 37263c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav @Override 37273c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav public void binderDied() { 37283c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationServiceOwner.unlinkToDeath( 37293c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationSerivceOnwerDeathRecipient, 0); 37303c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationServiceOwner = null; 37313c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav if (mUiAutomationService != null) { 37323c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationService.binderDied(); 37333c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav } 37343c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav } 37353c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav }; 37363c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav 373758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public UserState(int userId) { 373858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov mUserId = userId; 373958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 37407befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov 374157bf88508e0491caced22c4c592d33aba6d88129Svetoslav public int getClientState() { 374257bf88508e0491caced22c4c592d33aba6d88129Svetoslav int clientState = 0; 374357bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (mIsAccessibilityEnabled) { 374457bf88508e0491caced22c4c592d33aba6d88129Svetoslav clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED; 374557bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 374657bf88508e0491caced22c4c592d33aba6d88129Svetoslav // Touch exploration relies on enabled accessibility. 374757bf88508e0491caced22c4c592d33aba6d88129Svetoslav if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) { 374857bf88508e0491caced22c4c592d33aba6d88129Svetoslav clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; 374957bf88508e0491caced22c4c592d33aba6d88129Svetoslav } 3750cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (mIsTextHighContrastEnabled) { 3751cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; 3752cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 375357bf88508e0491caced22c4c592d33aba6d88129Svetoslav return clientState; 37547befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov } 37555fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 37565fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav public void onSwitchToAnotherUser() { 37575fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // Clear UI test automation state. 37585fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav if (mUiAutomationService != null) { 37595fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mUiAutomationService.binderDied(); 37605fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav } 37615fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 37625fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // Unbind all services. 37635fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav unbindAllServicesLocked(this); 37645fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 37655fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // Clear service management state. 37665fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mBoundServices.clear(); 37675fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mBindingServices.clear(); 37685fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 37695fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // Clear event management state. 37705fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mHandledFeedbackTypes = 0; 37715fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mLastSentClientState = -1; 37725fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav 37735fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav // Clear state persisted in settings. 37745fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mEnabledServices.clear(); 37755fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mTouchExplorationGrantedServices.clear(); 37765fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mIsAccessibilityEnabled = false; 37775fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mIsTouchExplorationEnabled = false; 37785fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mIsEnhancedWebAccessibilityEnabled = false; 37795fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav mIsDisplayMagnificationEnabled = false; 37805fec0c5ee5bbd83fd651644c90ff78fe32680a42Svetoslav } 37813c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav 37823c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav public void destroyUiAutomationService() { 37833c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationService = null; 37843c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationServiceClient = null; 37853c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav if (mUiAutomationServiceOwner != null) { 37863c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationServiceOwner.unlinkToDeath( 37873c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationSerivceOnwerDeathRecipient, 0); 37883c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav mUiAutomationServiceOwner = null; 37893c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav } 37903c55e5c6595d28c64f5a760947c66fdefa2481e2Svetoslav } 37917befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov } 37927befb7deb2ac15134b3bb190520cba19165d16ddSvetoslav Ganov 379358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final class AccessibilityContentObserver extends ContentObserver { 379458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 379558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor( 379658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Settings.Secure.ACCESSIBILITY_ENABLED); 379758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 379858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor( 379958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Settings.Secure.TOUCH_EXPLORATION_ENABLED); 380058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 380158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor( 380258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); 380358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 380458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor( 380558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 380658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 3807447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure 3808447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); 3809447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 381057bf88508e0491caced22c4c592d33aba6d88129Svetoslav private final Uri mEnhancedWebAccessibilityUri = Settings.Secure 3811447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION); 3812447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov 3813410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor( 3814410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 3815410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette 3816410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor( 3817410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED); 3818cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 3819410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor( 3820410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER); 3821410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette 3822cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik private final Uri mHighTextContrastUri = Settings.Secure.getUriFor( 3823cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED); 3824cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 382558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public AccessibilityContentObserver(Handler handler) { 382658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov super(handler); 382758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 382858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 382958d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public void register(ContentResolver contentResolver) { 383058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov contentResolver.registerContentObserver(mAccessibilityEnabledUri, 383158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov false, this, UserHandle.USER_ALL); 383258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov contentResolver.registerContentObserver(mTouchExplorationEnabledUri, 383358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov false, this, UserHandle.USER_ALL); 383458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri, 383558d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov false, this, UserHandle.USER_ALL); 383658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri, 383758d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov false, this, UserHandle.USER_ALL); 3838447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov contentResolver.registerContentObserver( 3839447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov mTouchExplorationGrantedAccessibilityServicesUri, 3840447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov false, this, UserHandle.USER_ALL); 384157bf88508e0491caced22c4c592d33aba6d88129Svetoslav contentResolver.registerContentObserver(mEnhancedWebAccessibilityUri, 3842447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov false, this, UserHandle.USER_ALL); 3843410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette contentResolver.registerContentObserver( 3844410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL); 3845410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette contentResolver.registerContentObserver( 3846410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL); 3847410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette contentResolver.registerContentObserver( 3848410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL); 3849cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik contentResolver.registerContentObserver( 3850cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik mHighTextContrastUri, false, this, UserHandle.USER_ALL); 385158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 385258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov 385358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov @Override 385458d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov public void onChange(boolean selfChange, Uri uri) { 3855cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik synchronized (mLock) { 3856cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik // Profiles share the accessibility state of the parent. Therefore, 3857cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik // we are checking for changes only the parent settings. 3858cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik UserState userState = getCurrentUserStateLocked(); 3859cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 3860cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik // We will update when the automation service dies. 3861cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (userState.mUiAutomationService != null) { 3862cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik return; 386358d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 3864cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik 3865cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (mAccessibilityEnabledUri.equals(uri)) { 3866cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (readAccessibilityEnabledSettingLocked(userState)) { 3867cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik onUserStateChangedLocked(userState); 386858d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 3869cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } else if (mTouchExplorationEnabledUri.equals(uri)) { 3870cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (readTouchExplorationEnabledSettingLocked(userState)) { 3871cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik onUserStateChangedLocked(userState); 387258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 3873cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } else if (mDisplayMagnificationEnabledUri.equals(uri)) { 3874cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (readDisplayMagnificationEnabledSettingLocked(userState)) { 3875cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik onUserStateChangedLocked(userState); 387658d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 3877cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } else if (mEnabledAccessibilityServicesUri.equals(uri)) { 3878cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (readEnabledAccessibilityServicesLocked(userState)) { 3879cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik onUserStateChangedLocked(userState); 3880447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 3881cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) { 3882cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) { 3883cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik onUserStateChangedLocked(userState); 3884447d94684ee73046d769649d8247aacd581bd6e3Svetoslav Ganov } 3885cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } else if (mEnhancedWebAccessibilityUri.equals(uri)) { 3886cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) { 3887cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik onUserStateChangedLocked(userState); 3888cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 3889cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } else if (mDisplayInversionEnabledUri.equals(uri) 3890cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik || mDisplayDaltonizerEnabledUri.equals(uri) 3891cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik || mDisplayDaltonizerUri.equals(uri)) { 3892cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (readDisplayColorAdjustmentSettingsLocked(userState)) { 3893cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik updateDisplayColorAdjustmentSettingsLocked(userState); 3894cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } 3895cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik } else if (mHighTextContrastUri.equals(uri)) { 3896cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik if (readHighTextContrastEnabledSettingLocked(userState)) { 3897cce47eb580d666ead1f6095d1e3b65233592bbaaChris Craik onUserStateChangedLocked(userState); 3898410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette } 3899410d4e33c5542ccdeacdc8d0ac4aa0e194da688aAlan Viverette } 390058d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 390158d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 390258d37b55bd228032355360ea3303e46a804e0516Svetoslav Ganov } 390375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov} 3904