Start the correct settings from the status bar.
Added a new method to Context: startActivityAsUser() requiring the
INTERACT_ACROSS_USERS_FULL permission.
Show the correct Recents list, based on current user.
Added a getRecentTasksForUser() in ActivityManager. Hidden and requires
the INTERACT_ACROSS_USERS_FULL permission.
Change-Id: If5b56465efdd3ead36601a3b51ed4af157bbf35c
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 05f38a5..375f7f1 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2305,19 +2305,48 @@
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
+ return startActivityAsUser(caller, intent, resolvedType, resultTo, resultWho, requestCode,
+ startFlags, profileFile, profileFd, options, UserId.getCallingUserId());
+ }
+
+ public final int startActivityAsUser(IApplicationThread caller,
+ Intent intent, String resolvedType, IBinder resultTo,
+ String resultWho, int requestCode, int startFlags,
+ String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
- int userId = 0;
- if (intent.getCategories() != null && intent.getCategories().contains(Intent.CATEGORY_HOME)) {
- // Requesting home, set the identity to the current user
- // HACK!
- userId = mCurrentUserId;
- } else {
- // TODO: Fix this in a better way - calls coming from SystemUI should probably carry
- // the current user's userId
- if (Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {
- userId = 0;
+ if (userId != UserId.getCallingUserId()) {
+ // Requesting a different user, make sure that they have the permission
+ if (checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
+ == PackageManager.PERMISSION_GRANTED) {
+ // Translate to the current user id, if caller wasn't aware
+ if (userId == UserId.USER_CURRENT) {
+ userId = mCurrentUserId;
+ }
} else {
- userId = Binder.getOrigCallingUser();
+ String msg = "Permission Denial: "
+ + "Request to startActivity as user " + userId
+ + " but is calling from user " + UserId.getCallingUserId()
+ + "; this requires "
+ + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ } else {
+ if (intent.getCategories() != null
+ && intent.getCategories().contains(Intent.CATEGORY_HOME)) {
+ // Requesting home, set the identity to the current user
+ // HACK!
+ userId = mCurrentUserId;
+ } else {
+ // TODO: Fix this in a better way - calls coming from SystemUI should probably carry
+ // the current user's userId
+ if (Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {
+ userId = 0;
+ } else {
+ userId = Binder.getOrigCallingUser();
+ }
}
}
return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
@@ -5470,13 +5499,28 @@
}
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
- int flags) {
+ int flags, int userId) {
final int callingUid = Binder.getCallingUid();
- // If it's the system uid asking, then use the current user id.
- // TODO: Make sure that there aren't any other legitimate calls from the system uid that
- // require the entire list.
- final int callingUserId = callingUid == Process.SYSTEM_UID
- ? mCurrentUserId : UserId.getUserId(callingUid);
+ if (userId != UserId.getCallingUserId()) {
+ // Check if the caller is holding permissions for cross-user requests.
+ if (checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Binder.getCallingPid(), callingUid, -1, true)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: "
+ + "Request to get recent tasks for user " + userId
+ + " but is calling from user " + UserId.getUserId(callingUid)
+ + "; this requires "
+ + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ } else {
+ if (userId == UserId.USER_CURRENT) {
+ userId = mCurrentUserId;
+ }
+ }
+ }
+
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.GET_TASKS,
"getRecentTasks()");
@@ -5485,7 +5529,7 @@
== PackageManager.PERMISSION_GRANTED;
IPackageManager pm = AppGlobals.getPackageManager();
-
+
final int N = mRecentTasks.size();
ArrayList<ActivityManager.RecentTaskInfo> res
= new ArrayList<ActivityManager.RecentTaskInfo>(
@@ -5493,7 +5537,7 @@
for (int i=0; i<N && maxNum > 0; i++) {
TaskRecord tr = mRecentTasks.get(i);
// Only add calling user's recent tasks
- if (tr.userId != callingUserId) continue;
+ if (tr.userId != userId) continue;
// Return the entry if desired by the caller. We always return
// the first entry, because callers always expect this to be the
// foreground app. We may filter others if the caller has
@@ -5521,13 +5565,13 @@
// Check whether this activity is currently available.
try {
if (rti.origActivity != null) {
- if (pm.getActivityInfo(rti.origActivity, 0, callingUserId)
+ if (pm.getActivityInfo(rti.origActivity, 0, userId)
== null) {
continue;
}
} else if (rti.baseIntent != null) {
if (pm.queryIntentActivities(rti.baseIntent,
- null, 0, callingUserId) == null) {
+ null, 0, userId) == null) {
continue;
}
}