RESTRICT AUTOMERGE: Prevent reporting fake package name - framework (backport to nyc-dev)

Test: added AccessibilityEndToEndTest#testPackageNameCannotBeFaked
      cts-tradefed run cts -m CtsAccessibilityServiceTestCases
      cts-tradefed run cts -m CtsAccessibilityTestCases

Bug: 69981755
Change-Id: I187e3e9839f654cea9e06e5de93e10e4d1de3109
This commit is contained in:
akirilov
2018-03-27 13:08:47 -07:00
committed by Atanas Kirilov
parent 815008072e
commit 33c37cb37c
9 changed files with 365 additions and 117 deletions

View File

@@ -35,22 +35,22 @@ interface IAccessibilityServiceConnection {
void setServiceInfo(in AccessibilityServiceInfo info);
boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, long threadId);
boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
long threadId);
boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
long accessibilityNodeId, String viewId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long threadId);
boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.appwidget;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArraySet;
import java.util.Set;
/**
* App widget manager local system service interface.
*
* @hide Only for use within the system server.
*/
public abstract class AppWidgetManagerInternal {
/**
* Gets the packages from which the uid hosts widgets.
*
* @param uid The potential host UID.
* @return Whether the UID hosts widgets from the package.
*/
public abstract @Nullable ArraySet<String> getHostedWidgetPackages(int uid);
}

View File

@@ -155,6 +155,11 @@ public final class UserHandle implements Parcelable {
return getUserId(Binder.getCallingUid());
}
/** @hide */
public static @AppIdInt int getCallingAppId() {
return getAppId(Binder.getCallingUid());
}
/** @hide */
@SystemApi
public static UserHandle of(@UserIdInt int userId) {

View File

@@ -7258,6 +7258,7 @@ public final class ViewRootImpl implements ViewParent,
if (!registered) {
mAttachInfo.mAccessibilityWindowId =
mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
mContext.getPackageName(),
new AccessibilityInteractionConnection(ViewRootImpl.this));
}
}

View File

@@ -28,6 +28,8 @@ import android.util.Log;
import android.util.LongSparseArray;
import android.util.SparseArray;
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -283,16 +285,23 @@ public final class AccessibilityInteractionClient
}
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.findAccessibilityNodeInfoByAccessibilityId(
accessibilityWindowId, accessibilityNodeId, interactionId, this,
prefetchFlags, Thread.currentThread().getId());
Binder.restoreCallingIdentity(identityToken);
// If the scale is zero the call has failed.
if (success) {
final String[] packageNames;
try {
packageNames = connection.findAccessibilityNodeInfoByAccessibilityId(
accessibilityWindowId, accessibilityNodeId, interactionId, this,
prefetchFlags, Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId);
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
bypassCache, packageNames);
if (infos != null && !infos.isEmpty()) {
for (int i = 1; i < infos.size(); i++) {
infos.get(i).recycle();
}
return infos.get(0);
}
}
@@ -331,15 +340,21 @@ public final class AccessibilityInteractionClient
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.findAccessibilityNodeInfosByViewId(
accessibilityWindowId, accessibilityNodeId, viewId, interactionId, this,
Thread.currentThread().getId());
Binder.restoreCallingIdentity(identityToken);
if (success) {
final String[] packageNames;
try {
packageNames = connection.findAccessibilityNodeInfosByViewId(
accessibilityWindowId, accessibilityNodeId, viewId, interactionId, this,
Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
if (infos != null) {
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId);
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
false, packageNames);
return infos;
}
}
@@ -379,15 +394,21 @@ public final class AccessibilityInteractionClient
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.findAccessibilityNodeInfosByText(
accessibilityWindowId, accessibilityNodeId, text, interactionId, this,
Thread.currentThread().getId());
Binder.restoreCallingIdentity(identityToken);
if (success) {
final String[] packageNames;
try {
packageNames = connection.findAccessibilityNodeInfosByText(
accessibilityWindowId, accessibilityNodeId, text, interactionId, this,
Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
if (packageNames != null) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
if (infos != null) {
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId);
finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
false, packageNames);
return infos;
}
}
@@ -426,14 +447,19 @@ public final class AccessibilityInteractionClient
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.findFocus(accessibilityWindowId,
accessibilityNodeId, focusType, interactionId, this,
Thread.currentThread().getId());
Binder.restoreCallingIdentity(identityToken);
if (success) {
final String[] packageNames;
try {
packageNames = connection.findFocus(accessibilityWindowId,
accessibilityNodeId, focusType, interactionId, this,
Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
if (packageNames != null) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
finalizeAndCacheAccessibilityNodeInfo(info, connectionId);
finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
return info;
}
} else {
@@ -470,14 +496,19 @@ public final class AccessibilityInteractionClient
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
final boolean success = connection.focusSearch(accessibilityWindowId,
accessibilityNodeId, direction, interactionId, this,
Thread.currentThread().getId());
Binder.restoreCallingIdentity(identityToken);
if (success) {
final String[] packageNames;
try {
packageNames = connection.focusSearch(accessibilityWindowId,
accessibilityNodeId, direction, interactionId, this,
Thread.currentThread().getId());
} finally {
Binder.restoreCallingIdentity(identityToken);
}
if (packageNames != null) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
finalizeAndCacheAccessibilityNodeInfo(info, connectionId);
finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
return info;
}
} else {
@@ -578,7 +609,7 @@ public final class AccessibilityInteractionClient
int interactionId) {
synchronized (mInstanceLock) {
final boolean success = waitForResultTimedLocked(interactionId);
List<AccessibilityNodeInfo> result = null;
final List<AccessibilityNodeInfo> result;
if (success) {
result = mFindAccessibilityNodeInfosResult;
} else {
@@ -694,13 +725,25 @@ public final class AccessibilityInteractionClient
*
* @param info The info.
* @param connectionId The id of the connection to the system.
* @param bypassCache Whether or not to bypass the cache. The node is added to the cache if
* this value is {@code false}
* @param packageNames The valid package names a node can come from.
*/
private void finalizeAndCacheAccessibilityNodeInfo(AccessibilityNodeInfo info,
int connectionId) {
int connectionId, boolean bypassCache, String[] packageNames) {
if (info != null) {
info.setConnectionId(connectionId);
// Empty array means any package name is Okay
if (!ArrayUtils.isEmpty(packageNames)
&& !ArrayUtils.contains(packageNames, info.getPackageName().toString())) {
// If the node package not one of the valid ones, pick the top one - this
// is one of the packages running in the introspected UID.
info.setPackageName(packageNames[0]);
}
info.setSealed(true);
sAccessibilityCache.add(info);
if (!bypassCache) {
sAccessibilityCache.add(info);
}
}
}
@@ -709,14 +752,18 @@ public final class AccessibilityInteractionClient
*
* @param infos The {@link AccessibilityNodeInfo}s.
* @param connectionId The id of the connection to the system.
* @param bypassCache Whether or not to bypass the cache. The nodes are added to the cache if
* this value is {@code false}
* @param packageNames The valid package names a node can come from.
*/
private void finalizeAndCacheAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos,
int connectionId) {
int connectionId, boolean bypassCache, String[] packageNames) {
if (infos != null) {
final int infosCount = infos.size();
for (int i = 0; i < infosCount; i++) {
AccessibilityNodeInfo info = infos.get(i);
finalizeAndCacheAccessibilityNodeInfo(info, connectionId);
finalizeAndCacheAccessibilityNodeInfo(info, connectionId,
bypassCache, packageNames);
}
}
}

View File

@@ -570,7 +570,7 @@ public final class AccessibilityManager {
* @hide
*/
public int addAccessibilityInteractionConnection(IWindow windowToken,
IAccessibilityInteractionConnection connection) {
String packageName, IAccessibilityInteractionConnection connection) {
final IAccessibilityManager service;
final int userId;
synchronized (mLock) {
@@ -581,7 +581,8 @@ public final class AccessibilityManager {
userId = mUserId;
}
try {
return service.addAccessibilityInteractionConnection(windowToken, connection, userId);
return service.addAccessibilityInteractionConnection(windowToken, connection,
packageName, userId);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
}

View File

@@ -46,7 +46,7 @@ interface IAccessibilityManager {
void interrupt(int userId);
int addAccessibilityInteractionConnection(IWindow windowToken,
in IAccessibilityInteractionConnection connection, int userId);
in IAccessibilityInteractionConnection connection, String packageName, int userId);
void removeAccessibilityInteractionConnection(IWindow windowToken);

View File

@@ -29,6 +29,7 @@ import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.UiAutomation;
import android.appwidget.AppWidgetManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -69,6 +70,7 @@ import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.ArraySet;
import android.view.Display;
import android.view.IWindow;
import android.view.InputDevice;
@@ -92,9 +94,11 @@ import android.view.accessibility.IAccessibilityManagerClient;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;
import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileDescriptor;
@@ -181,6 +185,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final WindowManagerInternal mWindowManagerService;
private AppWidgetManagerInternal mAppWidgetService;
private final SecurityPolicy mSecurityPolicy;
private final MainHandler mMainHandler;
@@ -207,7 +213,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
new RemoteCallbackList<>();
private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
private final SparseArray<RemoteAccessibilityConnection> mGlobalInteractionConnections =
new SparseArray<>();
private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>();
@@ -433,6 +439,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// performs the current profile parent resolution..
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
// Make sure the reported package is one the caller has access to.
event.setPackageName(mSecurityPolicy.resolveValidReportedPackageLocked(
event.getPackageName(), UserHandle.getCallingAppId(), resolvedUserId));
// This method does nothing for a background user.
if (resolvedUserId != mCurrentUserId) {
return true; // yes, recycle the event
@@ -539,30 +550,38 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
@Override
public int addAccessibilityInteractionConnection(IWindow windowToken,
IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
IAccessibilityInteractionConnection connection, String packageName,
int userId) throws RemoteException {
synchronized (mLock) {
// We treat calls from a profile as if made by its parent as profiles
// share the accessibility state of the parent. The call below
// performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
final int resolvedUid = UserHandle.getUid(resolvedUserId, UserHandle.getCallingAppId());
// Make sure the reported package is one the caller has access to.
packageName = mSecurityPolicy.resolveValidReportedPackageLocked(
packageName, UserHandle.getCallingAppId(), resolvedUserId);
final int windowId = sNextWindowId++;
// If the window is from a process that runs across users such as
// the system UI or the system we add it to the global state that
// is shared across users.
if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
windowId, connection, UserHandle.USER_ALL);
RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
windowId, connection, packageName, resolvedUid, UserHandle.USER_ALL);
wrapper.linkToDeath();
mGlobalInteractionConnections.put(windowId, wrapper);
mGlobalWindowTokens.put(windowId, windowToken.asBinder());
if (DEBUG) {
Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
+ " with windowId: " + windowId + " and token: " + windowToken.asBinder());
+ " with windowId: " + windowId + " and token: "
+ windowToken.asBinder());
}
} else {
AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
windowId, connection, resolvedUserId);
RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
windowId, connection, packageName, resolvedUid, resolvedUserId);
wrapper.linkToDeath();
UserState userState = getUserStateLocked(resolvedUserId);
userState.mInteractionConnections.put(windowId, wrapper);
@@ -591,7 +610,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (removedWindowId >= 0) {
if (DEBUG) {
Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
+ " with windowId: " + removedWindowId + " and token: " + window.asBinder());
+ " with windowId: " + removedWindowId + " and token: "
+ window.asBinder());
}
return;
}
@@ -615,13 +635,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
SparseArray<IBinder> windowTokens,
SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
SparseArray<RemoteAccessibilityConnection> interactionConnections) {
final int count = windowTokens.size();
for (int i = 0; i < count; i++) {
if (windowTokens.valueAt(i) == windowToken) {
final int windowId = windowTokens.keyAt(i);
windowTokens.removeAt(i);
AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
RemoteAccessibilityConnection wrapper = interactionConnections.get(windowId);
wrapper.unlinkToDeath();
interactionConnections.remove(windowId);
return windowId;
@@ -1963,18 +1983,35 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
private class AccessibilityConnectionWrapper implements DeathRecipient {
class RemoteAccessibilityConnection implements DeathRecipient {
private final int mUid;
private final String mPackageName;
private final int mWindowId;
private final int mUserId;
private final IAccessibilityInteractionConnection mConnection;
public AccessibilityConnectionWrapper(int windowId,
IAccessibilityInteractionConnection connection, int userId) {
RemoteAccessibilityConnection(int windowId,
IAccessibilityInteractionConnection connection,
String packageName, int uid, int userId) {
mWindowId = windowId;
mPackageName = packageName;
mUid = uid;
mUserId = userId;
mConnection = connection;
}
public int getUid() {
return mUid;
}
public String getPackageName() {
return mPackageName;
}
public IAccessibilityInteractionConnection getRemote() {
return mConnection;
}
public void linkToDeath() throws RemoteException {
mConnection.asBinder().linkToDeath(this, 0);
}
@@ -2500,26 +2537,26 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
@Override
public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
long accessibilityNodeId, String viewIdResName, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
RemoteAccessibilityConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
return null;
}
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
return false;
return null;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
return false;
return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -2529,13 +2566,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
final int interrogatingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
partialInteractiveRegion, interactionId, callback, mFetchFlags,
interrogatingPid, interrogatingTid, spec);
return true;
connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId,
viewIdResName, partialInteractiveRegion, interactionId, callback,
mFetchFlags, interrogatingPid, interrogatingTid, spec);
return mSecurityPolicy.computeValidReportedPackages(callingUid,
connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
@@ -2543,34 +2582,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
return false;
return null;
}
@Override
public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
long accessibilityNodeId, String text, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
RemoteAccessibilityConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
return null;
}
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
return false;
return null;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
return false;
return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -2580,13 +2619,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
final int interrogatingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId, text,
partialInteractiveRegion, interactionId, callback, mFetchFlags,
interrogatingPid, interrogatingTid, spec);
return true;
return mSecurityPolicy.computeValidReportedPackages(callingUid,
connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
@@ -2594,34 +2635,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
return false;
return null;
}
@Override
public boolean findAccessibilityNodeInfoByAccessibilityId(
public String[] findAccessibilityNodeInfoByAccessibilityId(
int accessibilityWindowId, long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
long interrogatingTid) throws RemoteException {
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
RemoteAccessibilityConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
return null;
}
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
return false;
return null;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
return false;
return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -2631,13 +2672,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
final int interrogatingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
interrogatingPid, interrogatingTid, spec);
return true;
connection.getRemote().findAccessibilityNodeInfoByAccessibilityId(
accessibilityNodeId, partialInteractiveRegion, interactionId, callback,
mFetchFlags | flags, interrogatingPid, interrogatingTid, spec);
return mSecurityPolicy.computeValidReportedPackages(callingUid,
connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
@@ -2645,35 +2688,35 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
return false;
return null;
}
@Override
public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId,
int focusType, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
RemoteAccessibilityConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
return null;
}
resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
accessibilityWindowId, focusType);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
return false;
return null;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
return false;
return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -2683,13 +2726,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
final int interrogatingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
spec);
return true;
connection.getRemote().findFocus(accessibilityNodeId, focusType,
partialInteractiveRegion, interactionId, callback, mFetchFlags,
interrogatingPid, interrogatingTid, spec);
return mSecurityPolicy.computeValidReportedPackages(callingUid,
connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findFocus()");
@@ -2697,34 +2742,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
return false;
return null;
}
@Override
public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId,
int direction, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
RemoteAccessibilityConnection connection = null;
Region partialInteractiveRegion = Region.obtain();
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
return null;
}
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
return false;
return null;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
return false;
return null;
}
}
if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -2734,13 +2779,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
final int interrogatingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
spec);
return true;
connection.getRemote().focusSearch(accessibilityNodeId, direction,
partialInteractiveRegion, interactionId, callback, mFetchFlags,
interrogatingPid, interrogatingTid, spec);
return mSecurityPolicy.computeValidReportedPackages(callingUid,
connection.getPackageName(), connection.getUid());
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
@@ -2748,11 +2795,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
// Recycle if passed to another process.
if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
partialInteractiveRegion.recycle();
}
}
return false;
return null;
}
@Override
@@ -2799,7 +2846,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
RemoteAccessibilityConnection connection;
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
@@ -2824,8 +2871,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
mPowerManager.userActivity(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
connection.mConnection.performAccessibilityAction(accessibilityNodeId, action,
arguments, interactionId, callback, mFetchFlags, interrogatingPid,
interrogatingTid);
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
@@ -3372,16 +3420,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen();
}
private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
private RemoteAccessibilityConnection getConnectionLocked(int windowId) {
if (DEBUG) {
Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
}
AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
RemoteAccessibilityConnection wrapper = mGlobalInteractionConnections.get(windowId);
if (wrapper == null) {
wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
}
if (wrapper != null && wrapper.mConnection != null) {
return wrapper.mConnection;
return wrapper;
}
if (DEBUG) {
Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
@@ -3493,6 +3541,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
private AppWidgetManagerInternal getAppWidgetManager() {
synchronized (mLock) {
if (mAppWidgetService == null
&& mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
mAppWidgetService = LocalServices.getService(AppWidgetManagerInternal.class);
}
return mAppWidgetService;
}
}
final class WindowsForAccessibilityCallback implements
WindowManagerInternal.WindowsForAccessibilityCallback {
@@ -3758,6 +3816,78 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
private boolean isValidPackageForUid(String packageName, int uid) {
try {
return uid == mPackageManager.getPackageUid(
packageName, UserHandle.getUserId(uid));
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
String resolveValidReportedPackageLocked(CharSequence packageName, int appId, int userId) {
// Okay to pass no package
if (packageName == null) {
return null;
}
// The system gets to pass any package
if (appId == Process.SYSTEM_UID) {
return packageName.toString();
}
// Passing a package in your UID is fine
final String packageNameStr = packageName.toString();
final int resolvedUid = UserHandle.getUid(userId, appId);
if (isValidPackageForUid(packageNameStr, resolvedUid)) {
return packageName.toString();
}
// Appwidget hosts get to pass packages for widgets they host
final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager();
if (appWidgetManager != null && ArrayUtils.contains(appWidgetManager
.getHostedWidgetPackages(resolvedUid), packageNameStr)) {
return packageName.toString();
}
// Otherwise, set the package to the first one in the UID
final String[] packageNames = mPackageManager.getPackagesForUid(resolvedUid);
if (ArrayUtils.isEmpty(packageNames)) {
return null;
}
// Okay, the caller reported a package it does not have access to.
// Instead of crashing the caller for better backwards compatibility
// we report the first package in the UID. Since most of the time apps
// don't use shared user id, this will yield correct results and for
// the edge case of using a shared user id we may report the wrong
// package but this is fine since first, this is a cheating app and
// second there is no way to get the correct package anyway.
return packageNames[0];
}
String[] computeValidReportedPackages(int callingUid,
String targetPackage, int targetUid) {
if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
// Empty array means any package is Okay
return EmptyArray.STRING;
}
// IMPORTANT: The target package is already vetted to be in the target UID
String[] uidPackages = new String[]{targetPackage};
// Appwidget hosts get to pass packages for widgets they host
final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager();
if (appWidgetManager != null) {
final ArraySet<String> widgetPackages = appWidgetManager
.getHostedWidgetPackages(targetUid);
if (widgetPackages != null && !widgetPackages.isEmpty()) {
final String[] validPackages = new String[uidPackages.length
+ widgetPackages.size()];
System.arraycopy(uidPackages, 0, validPackages, 0, uidPackages.length);
final int widgetPackageCount = widgetPackages.size();
for (int i = 0; i < widgetPackageCount; i++) {
validPackages[uidPackages.length + i] = widgetPackages.valueAt(i);
}
return validPackages;
}
}
return uidPackages;
}
public void clearWindowsLocked() {
List<AccessibilityWindowInfo> windows = Collections.emptyList();
final int activeWindowId = mActiveWindowId;
@@ -4156,7 +4286,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
new RemoteCallbackList<>();
public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
public final SparseArray<RemoteAccessibilityConnection> mInteractionConnections =
new SparseArray<>();
public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();

View File

@@ -29,6 +29,7 @@ import android.app.PendingIntent;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetManagerInternal;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -89,6 +90,7 @@ import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.widget.IRemoteViewsAdapterConnection;
import com.android.internal.widget.IRemoteViewsFactory;
@@ -97,6 +99,7 @@ import com.android.server.WidgetBackupProvider;
import com.android.server.policy.IconUtilities;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -240,6 +243,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
computeMaximumWidgetBitmapMemory();
registerBroadcastReceiver();
registerOnCrossProfileProvidersChangedListener();
LocalServices.addService(AppWidgetManagerInternal.class, new AppWidgetManagerLocal());
}
private void computeMaximumWidgetBitmapMemory() {
@@ -4551,4 +4556,24 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
}
}
private class AppWidgetManagerLocal extends AppWidgetManagerInternal {
@Override
public ArraySet<String> getHostedWidgetPackages(int uid) {
synchronized (mLock) {
ArraySet<String> widgetPackages = null;
final int widgetCount = mWidgets.size();
for (int i = 0; i < widgetCount; i++) {
final Widget widget = mWidgets.get(i);
if (widget.host.id.uid == uid) {
if (widgetPackages == null) {
widgetPackages = new ArraySet<>();
}
widgetPackages.add(widget.provider.id.componentName.getPackageName());
}
}
return widgetPackages;
}
}
}
}