summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl10
-rw-r--r--core/java/android/appwidget/AppWidgetManagerInternal.java39
-rw-r--r--core/java/android/os/UserHandle.java5
-rw-r--r--core/java/android/view/ViewRootImpl.java1
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java119
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java5
-rw-r--r--core/java/android/view/accessibility/IAccessibilityManager.aidl2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java276
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java25
9 files changed, 365 insertions, 117 deletions
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 5f7a17d33bd1..cb600536ec64 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -32,22 +32,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,
diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java
new file mode 100644
index 000000000000..daa297de8727
--- /dev/null
+++ b/core/java/android/appwidget/AppWidgetManagerInternal.java
@@ -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);
+}
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index bfca719555f9..fc6e4b665fdd 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -130,6 +130,11 @@ public final class UserHandle implements Parcelable {
}
/** @hide */
+ public static final int getCallingAppId() {
+ return getAppId(Binder.getCallingUid());
+ }
+
+ /** @hide */
public static final UserHandle getCallingUserHandle() {
int userId = getUserId(Binder.getCallingUid());
UserHandle userHandle = userHandles.get(userId);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 42402ebdc746..2e4dc117dc63 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6970,6 +6970,7 @@ public final class ViewRootImpl implements ViewParent,
if (!registered) {
mAttachInfo.mAccessibilityWindowId =
mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
+ mContext.getPackageName(),
new AccessibilityInteractionConnection(ViewRootImpl.this));
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index b49cbc6245ba..8d473f71d50c 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -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;
@@ -287,16 +289,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);
}
}
@@ -335,15 +344,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;
}
}
@@ -383,15 +398,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;
}
}
@@ -430,14 +451,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 {
@@ -474,14 +500,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 {
@@ -582,7 +613,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 {
@@ -698,13 +729,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);
+ }
}
}
@@ -713,14 +756,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);
}
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index e77b862618e6..b42e34eb5243 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -571,7 +571,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) {
@@ -582,7 +582,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);
}
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index b6570cc37467..41048167700f 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -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);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 57769e709bc3..15bf53fc4ce1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -26,6 +26,7 @@ import android.accessibilityservice.IAccessibilityServiceConnection;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.StatusBarManager;
+import android.appwidget.AppWidgetManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -63,6 +64,7 @@ import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
+import android.util.ArraySet;
import android.util.Pools.Pool;
import android.util.Pools.SimplePool;
import android.util.Slog;
@@ -91,9 +93,11 @@ import android.view.accessibility.IAccessibilityManagerClient;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
+import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileDescriptor;
@@ -176,6 +180,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final WindowManagerInternal mWindowManagerService;
+ private AppWidgetManagerInternal mAppWidgetService;
+
private final SecurityPolicy mSecurityPolicy;
private final MainHandler mMainHandler;
@@ -196,7 +202,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<>();
@@ -422,6 +428,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
@@ -529,30 +540,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);
@@ -581,7 +600,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;
}
@@ -605,13 +625,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;
@@ -1714,18 +1734,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);
}
@@ -2233,12 +2270,12 @@ 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) {
// We treat calls from a profile as if made by its parent as profiles
@@ -2248,17 +2285,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.USER_CURRENT);
if (resolvedUserId != mCurrentUserId) {
- 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(
@@ -2268,13 +2305,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().");
@@ -2282,20 +2321,20 @@ 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) {
// We treat calls from a profile as if made by its parent as profiles
@@ -2305,17 +2344,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.USER_CURRENT);
if (resolvedUserId != mCurrentUserId) {
- 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(
@@ -2325,13 +2364,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()");
@@ -2339,20 +2380,20 @@ 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) {
// We treat calls from a profile as if made by its parent as profiles
@@ -2362,17 +2403,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.USER_CURRENT);
if (resolvedUserId != mCurrentUserId) {
- 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(
@@ -2382,13 +2423,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()");
@@ -2396,20 +2439,20 @@ 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) {
// We treat calls from a profile as if made by its parent as profiles
@@ -2419,18 +2462,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.USER_CURRENT);
if (resolvedUserId != mCurrentUserId) {
- 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(
@@ -2440,13 +2483,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()");
@@ -2454,20 +2499,20 @@ 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) {
// We treat calls from a profile as if made by its parent as profiles
@@ -2477,17 +2522,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.USER_CURRENT);
if (resolvedUserId != mCurrentUserId) {
- 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(
@@ -2497,13 +2542,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()");
@@ -2511,11 +2558,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
@@ -2524,7 +2571,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
final int resolvedWindowId;
- IAccessibilityInteractionConnection connection = null;
+ RemoteAccessibilityConnection connection;
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
@@ -2550,8 +2597,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
final int interrogatingPid = Binder.getCallingPid();
final long identityToken = Binder.clearCallingIdentity();
try {
- 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()");
@@ -2894,16 +2942,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
mWindowManagerService.showGlobalActions();
}
- 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);
@@ -3109,6 +3157,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 {
@@ -3367,6 +3425,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;
@@ -3751,7 +3881,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<>();
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index fa87270d6984..b49c313439a3 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -23,6 +23,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;
@@ -76,6 +77,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;
@@ -83,6 +85,7 @@ import com.android.internal.widget.IRemoteViewsFactory;
import com.android.server.LocalServices;
import com.android.server.WidgetBackupProvider;
import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -210,6 +213,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
computeMaximumWidgetBitmapMemory();
registerBroadcastReceiver();
registerOnCrossProfileProvidersChangedListener();
+
+ LocalServices.addService(AppWidgetManagerInternal.class, new AppWidgetManagerLocal());
}
private void computeMaximumWidgetBitmapMemory() {
@@ -4175,4 +4180,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;
+ }
+ }
+ }
}