Allow acquiring ContentProviders across users.
Otherwise services like SystemUI will always open content://-style
Uris as USER_OWNER. Surfaces through createPackageContextAsUser()
which points all ContentResolver operations towards a given user.
Start using in RemoteViews, so that Notifications correctly resolve
image Uris to the sending user. Also add user support for "content"
shell tool.
Bug: 7202982
Change-Id: I8cb7fb8a812e825bb0b5833799dba87055ff8699
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 3caba1f..71e6e66 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -63,6 +63,7 @@
import android.util.Xml;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import android.widget.RemoteViews;
import android.widget.Toast;
import com.android.internal.statusbar.StatusBarNotification;
@@ -877,7 +878,6 @@
return (x < low) ? low : ((x > high) ? high : x);
}
-
// Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
// uid/pid of another application)
public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,
@@ -992,8 +992,9 @@
}
if (notification.icon != 0) {
- StatusBarNotification n = new StatusBarNotification(pkg, id, tag,
- r.uid, r.initialPid, score, notification);
+ final UserHandle user = new UserHandle(userId);
+ final StatusBarNotification n = new StatusBarNotification(
+ pkg, id, tag, r.uid, r.initialPid, score, notification, user);
if (old != null && old.statusBarKey != null) {
r.statusBarKey = old.statusBarKey;
long identity = Binder.clearCallingIdentity();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f162dae..a6f2974 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6414,10 +6414,6 @@
+ " (pid=" + Binder.getCallingPid()
+ ") when getting content provider " + name);
}
- if (r.userId != userId) {
- throw new SecurityException("Calling requested user " + userId
- + " but app is user " + r.userId);
- }
}
// First check if this content provider has been published...
@@ -6666,7 +6662,7 @@
}
public final ContentProviderHolder getContentProvider(
- IApplicationThread caller, String name, boolean stable) {
+ IApplicationThread caller, String name, int userId, boolean stable) {
enforceNotIsolatedCaller("getContentProvider");
if (caller == null) {
String msg = "null IApplicationThread when getting content provider "
@@ -6675,14 +6671,18 @@
throw new SecurityException(msg);
}
- return getContentProviderImpl(caller, name, null, stable,
- UserHandle.getCallingUserId());
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ false, true, "getContentProvider", null);
+ return getContentProviderImpl(caller, name, null, stable, userId);
}
- public ContentProviderHolder getContentProviderExternal(String name, IBinder token) {
+ public ContentProviderHolder getContentProviderExternal(
+ String name, int userId, IBinder token) {
enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
"Do not have permission in call getContentProviderExternal()");
- return getContentProviderExternalUnchecked(name, token, UserHandle.getCallingUserId());
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ false, true, "getContentProvider", null);
+ return getContentProviderExternalUnchecked(name, token, userId);
}
private ContentProviderHolder getContentProviderExternalUnchecked(String name,