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
(cherry picked from commit 33c37cb37c885a18f073a3fb68eba1c3498e812d)
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 81cddba..f138ddb 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -35,22 +35,22 @@
 
     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 0000000..daa297d
--- /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 b3f4453..5fce1a8 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -156,6 +156,11 @@
     }
 
     /** @hide */
+    public static @AppIdInt int getCallingAppId() {
+        return getAppId(Binder.getCallingUid());
+    }
+
+    /** @hide */
     @SystemApi
     public static UserHandle of(@UserIdInt int userId) {
         return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 195786d..fb27b57 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -7258,6 +7258,7 @@
             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 1406fbd..7b40bf9 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -28,6 +28,8 @@
 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 @@
                 }
                 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 @@
             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 @@
             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 @@
             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 @@
             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 @@
                 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 @@
      *
      * @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 @@
      *
      * @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 81ec330..71d3556 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -570,7 +570,7 @@
      * @hide
      */
     public int addAccessibilityInteractionConnection(IWindow windowToken,
-            IAccessibilityInteractionConnection connection) {
+            String packageName, IAccessibilityInteractionConnection connection) {
         final IAccessibilityManager service;
         final int userId;
         synchronized (mLock) {
@@ -581,7 +581,8 @@
             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 7f44bac..da06a11 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -46,7 +46,7 @@
     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 f039e1e..8a35ff8 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -29,6 +29,7 @@
 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.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 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 @@
 
     private final WindowManagerInternal mWindowManagerService;
 
+    private AppWidgetManagerInternal mAppWidgetService;
+
     private final SecurityPolicy mSecurityPolicy;
 
     private final MainHandler mMainHandler;
@@ -207,7 +213,7 @@
     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 @@
             // 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 @@
 
     @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 @@
             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 @@
 
     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 @@
         }
     }
 
-    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 @@
         }
 
         @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 @@
                 }
             }
             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 @@
             } 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 @@
                 }
             }
             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 @@
             } 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 @@
                 }
             }
             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 @@
             } 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 @@
                 }
             }
             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 @@
             } 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 @@
                 }
             }
             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 @@
             } 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 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId;
-            IAccessibilityInteractionConnection connection = null;
+            RemoteAccessibilityConnection connection;
             synchronized (mLock) {
                 if (!isCalledForCurrentUserLocked()) {
                     return false;
@@ -2824,8 +2871,9 @@
                 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 @@
             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 @@
         }
     }
 
+    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 @@
             }
         }
 
+        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 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 2a30229..cef51e0 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -29,6 +29,7 @@
 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.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.policy.IconUtilities;
 
 import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -240,6 +243,8 @@
         computeMaximumWidgetBitmapMemory();
         registerBroadcastReceiver();
         registerOnCrossProfileProvidersChangedListener();
+
+        LocalServices.addService(AppWidgetManagerInternal.class, new AppWidgetManagerLocal());
     }
 
     private void computeMaximumWidgetBitmapMemory() {
@@ -4551,4 +4556,24 @@
             }
         }
     }
+
+    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;
+            }
+        }
+    }
 }