Skip to content

Commit a8afa69

Browse files
committed
Regression in screen introspection APIs due to the multi-user change.
1. The initial user was set to USER_NULL but some clients were registering before the user change callback happens. Since the initial user is the owner the current user id defaults to USER_OWNER. 2. The check for global clients and window connections was using the calling UID but there are processes that run in a per user basis as system UID (Setting for example). Now the check is stronger and comparing the caller PID with that of the system process. 3. The code for finding the focused window id was not checking the global window token list in addition to that of the current user. 4. The code updating the active window id was calling out into the window manager with a lock held. bug:7224670 Change-Id: I9f4b7ea67eb5598b30ee7d1b68a1d3ce0cf8cfb4
1 parent 1ab8a08 commit a8afa69

File tree

1 file changed

+65
-25
lines changed

1 file changed

+65
-25
lines changed

services/java/com/android/server/accessibility/AccessibilityManagerService.java

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
157157

158158
private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
159159

160-
private int mCurrentUserId = UserHandle.USER_NULL;
160+
private int mCurrentUserId = UserHandle.USER_OWNER;
161161

162162
private UserState getCurrentUserStateLocked() {
163163
return getUserStateLocked(mCurrentUserId);
@@ -296,12 +296,19 @@ public int addClient(IAccessibilityManagerClient client, int userId) {
296296
UserState userState = getUserStateLocked(resolvedUserId);
297297
if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
298298
mGlobalClients.register(client);
299+
if (DEBUG) {
300+
Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
301+
}
299302
return getClientState(userState);
300303
} else {
301304
userState.mClients.register(client);
302305
// If this client is not for the current user we do not
303306
// return a state since it is not for the foreground user.
304307
// We will send the state to the client on a user switch.
308+
if (DEBUG) {
309+
Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid()
310+
+ " and userId:" + mCurrentUserId);
311+
}
305312
return (resolvedUserId == mCurrentUserId) ? getClientState(userState) : 0;
306313
}
307314
}
@@ -316,7 +323,9 @@ public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
316323
return true; // yes, recycle the event
317324
}
318325
if (mSecurityPolicy.canDispatchAccessibilityEvent(event)) {
319-
mSecurityPolicy.updateActiveWindowAndEventSourceLocked(event);
326+
mSecurityPolicy.updateEventSourceLocked(event);
327+
mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_ACTIVE_WINDOW,
328+
event.getWindowId(), event.getEventType()).sendToTarget();
320329
notifyAccessibilityServicesDelayedLocked(event, false);
321330
notifyAccessibilityServicesDelayedLocked(event, true);
322331
}
@@ -399,13 +408,21 @@ public int addAccessibilityInteractionConnection(IWindow windowToken,
399408
wrapper.linkToDeath();
400409
mGlobalInteractionConnections.put(windowId, wrapper);
401410
mGlobalWindowTokens.put(windowId, windowToken.asBinder());
411+
if (DEBUG) {
412+
Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
413+
+ " with windowId: " + windowId);
414+
}
402415
} else {
403416
AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
404417
windowId, connection, resolvedUserId);
405418
wrapper.linkToDeath();
406419
UserState userState = getUserStateLocked(resolvedUserId);
407420
userState.mInteractionConnections.put(windowId, wrapper);
408421
userState.mWindowTokens.put(windowId, windowToken.asBinder());
422+
if (DEBUG) {
423+
Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid()
424+
+ " with windowId: " + windowId + " and userId:" + mCurrentUserId);
425+
}
409426
}
410427
if (DEBUG) {
411428
Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
@@ -419,26 +436,34 @@ public void removeAccessibilityInteractionConnection(IWindow window) {
419436
mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
420437
UserHandle.getCallingUserId());
421438
IBinder token = window.asBinder();
422-
final boolean removedGlobal =
423-
removeAccessibilityInteractionConnectionInternalLocked(
439+
final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked(
424440
token, mGlobalWindowTokens, mGlobalInteractionConnections);
425-
if (removedGlobal) {
441+
if (removedWindowId >= 0) {
442+
if (DEBUG) {
443+
Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
444+
+ " with windowId: " + removedWindowId);
445+
}
426446
return;
427447
}
428448
final int userCount = mUserStates.size();
429449
for (int i = 0; i < userCount; i++) {
430450
UserState userState = mUserStates.valueAt(i);
431-
final boolean removedForUser =
451+
final int removedWindowIdForUser =
432452
removeAccessibilityInteractionConnectionInternalLocked(
433453
token, userState.mWindowTokens, userState.mInteractionConnections);
434-
if (removedForUser) {
454+
if (removedWindowIdForUser >= 0) {
455+
if (DEBUG) {
456+
Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
457+
+ " with windowId: " + removedWindowIdForUser + " and userId:"
458+
+ mUserStates.keyAt(i));
459+
}
435460
return;
436461
}
437462
}
438463
}
439464
}
440465

441-
private boolean removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
466+
private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
442467
SparseArray<IBinder> windowTokens,
443468
SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
444469
final int count = windowTokens.size();
@@ -449,10 +474,10 @@ private boolean removeAccessibilityInteractionConnectionInternalLocked(IBinder w
449474
AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
450475
wrapper.unlinkToDeath();
451476
interactionConnections.remove(windowId);
452-
return true;
477+
return windowId;
453478
}
454479
}
455-
return false;
480+
return -1;
456481
}
457482

458483
public void registerUiTestAutomationService(IAccessibilityServiceClient serviceClient,
@@ -1160,6 +1185,7 @@ private final class MainHandler extends Handler {
11601185
public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
11611186
public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
11621187
public static final int MSG_SEND_RECREATE_INTERNAL_STATE = 4;
1188+
public static final int MSG_UPDATE_ACTIVE_WINDOW = 5;
11631189

11641190
public MainHandler(Looper looper) {
11651191
super(looper);
@@ -1195,6 +1221,11 @@ public void handleMessage(Message msg) {
11951221
recreateInternalStateLocked(userState);
11961222
}
11971223
} break;
1224+
case MSG_UPDATE_ACTIVE_WINDOW: {
1225+
final int windowId = msg.arg1;
1226+
final int eventType = msg.arg2;
1227+
mSecurityPolicy.updateActiveWindow(windowId, eventType);
1228+
} break;
11981229
}
11991230
}
12001231

@@ -2006,14 +2037,18 @@ private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
20062037
|| event.getWindowId() == mActiveWindowId);
20072038
}
20082039

2009-
public void updateActiveWindowAndEventSourceLocked(AccessibilityEvent event) {
2040+
public void updateEventSourceLocked(AccessibilityEvent event) {
2041+
if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
2042+
event.setSource(null);
2043+
}
2044+
}
2045+
2046+
public void updateActiveWindow(int windowId, int eventType) {
20102047
// The active window is either the window that has input focus or
20112048
// the window that the user is currently touching. If the user is
20122049
// touching a window that does not have input focus as soon as the
20132050
// the user stops touching that window the focused window becomes
20142051
// the active one.
2015-
final int windowId = event.getWindowId();
2016-
final int eventType = event.getEventType();
20172052
switch (eventType) {
20182053
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
20192054
if (getFocusedWindowId() == windowId) {
@@ -2028,9 +2063,6 @@ public void updateActiveWindowAndEventSourceLocked(AccessibilityEvent event) {
20282063
mActiveWindowId = getFocusedWindowId();
20292064
} break;
20302065
}
2031-
if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
2032-
event.setSource(null);
2033-
}
20342066
}
20352067

20362068
public int getRetrievalAllowingWindowLocked() {
@@ -2087,7 +2119,7 @@ public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
20872119

20882120
public boolean isCallerInteractingAcrossUsers(int userId) {
20892121
final int callingUid = Binder.getCallingUid();
2090-
return (callingUid == Process.SYSTEM_UID
2122+
return (Binder.getCallingPid() == android.os.Process.myPid()
20912123
|| callingUid == Process.SHELL_UID
20922124
|| userId == UserHandle.USER_CURRENT
20932125
|| userId == UserHandle.USER_CURRENT_OR_SELF);
@@ -2116,25 +2148,33 @@ private boolean hasPermission(String permission) {
21162148
}
21172149

21182150
private int getFocusedWindowId() {
2119-
final long identity = Binder.clearCallingIdentity();
21202151
try {
21212152
// We call this only on window focus change or after touch
21222153
// exploration gesture end and the shown windows are not that
21232154
// many, so the linear look up is just fine.
21242155
IBinder token = mWindowManagerService.getFocusedWindowToken();
21252156
if (token != null) {
2126-
SparseArray<IBinder> windows = getCurrentUserStateLocked().mWindowTokens;
2127-
final int windowCount = windows.size();
2128-
for (int i = 0; i < windowCount; i++) {
2129-
if (windows.valueAt(i) == token) {
2130-
return windows.keyAt(i);
2157+
synchronized (mLock) {
2158+
int windowId = getFocusedWindowIdLocked(token, mGlobalWindowTokens);
2159+
if (windowId < 0) {
2160+
windowId = getFocusedWindowIdLocked(token,
2161+
getCurrentUserStateLocked().mWindowTokens);
21312162
}
2163+
return windowId;
21322164
}
21332165
}
21342166
} catch (RemoteException re) {
21352167
/* ignore */
2136-
} finally {
2137-
Binder.restoreCallingIdentity(identity);
2168+
}
2169+
return -1;
2170+
}
2171+
2172+
private int getFocusedWindowIdLocked(IBinder token, SparseArray<IBinder> windows) {
2173+
final int windowCount = windows.size();
2174+
for (int i = 0; i < windowCount; i++) {
2175+
if (windows.valueAt(i) == token) {
2176+
return windows.keyAt(i);
2177+
}
21382178
}
21392179
return -1;
21402180
}

0 commit comments

Comments
 (0)