summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/am/ActivityManagerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/am/ActivityManagerService.java')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java710
1 files changed, 463 insertions, 247 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3a6a3de..6fd5c07 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -75,6 +75,7 @@ import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -104,6 +105,7 @@ import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.UserId;
import android.provider.Settings;
import android.util.EventLog;
import android.util.Pair;
@@ -111,6 +113,7 @@ import android.util.Slog;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -135,6 +138,7 @@ import java.io.StringWriter;
import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -149,7 +153,9 @@ import java.util.concurrent.atomic.AtomicLong;
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
+ private static final String USER_DATA_DIR = "/data/user/";
static final String TAG = "ActivityManager";
+ static final String TAG_MU = "ActivityManagerServiceMU";
static final boolean DEBUG = false;
static final boolean localLOGV = DEBUG;
static final boolean DEBUG_SWITCH = localLOGV || false;
@@ -172,6 +178,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final boolean DEBUG_CONFIGURATION = localLOGV || false;
static final boolean DEBUG_POWER = localLOGV || false;
static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
+ static final boolean DEBUG_MU = localLOGV || false;
static final boolean VALIDATE_TOKENS = false;
static final boolean SHOW_ACTIVITY_START_TIME = true;
@@ -781,7 +788,16 @@ public final class ActivityManagerService extends ActivityManagerNative
r.curComponent = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
+ if (r.callingUid != Process.SYSTEM_UID) {
+ info.activityInfo = getActivityInfoForUser(info.activityInfo, UserId
+ .getUserId(r.callingUid));
+ }
r.curReceiver = info.activityInfo;
+ if (DEBUG_MU && r.callingUid > UserId.PER_USER_RANGE) {
+ Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
+ + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
+ + info.activityInfo.applicationInfo.uid);
+ }
// Broadcast is being executed, its package can't be stopped.
try {
@@ -1286,17 +1302,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
new HashMap<String, ArrayList<Intent>>();
- /**
- * All currently running services.
- */
- final HashMap<ComponentName, ServiceRecord> mServices =
- new HashMap<ComponentName, ServiceRecord>();
-
- /**
- * All currently running services indexed by the Intent used to start them.
- */
- final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
- new HashMap<Intent.FilterComparison, ServiceRecord>();
+ final ServiceMap mServiceMap = new ServiceMap();
/**
* All currently bound service connections. Keys are the IBinder of
@@ -1362,6 +1368,8 @@ public final class ActivityManagerService extends ActivityManagerNative
final HashMap<ComponentName, ContentProviderRecord> mProvidersByClass
= new HashMap<ComponentName, ContentProviderRecord>();
+ final ProviderMap mProviderMap = new ProviderMap();
+
/**
* List of content providers who have clients waiting for them. The
* application is currently being launched and the provider will be
@@ -1392,6 +1400,7 @@ public final class ActivityManagerService extends ActivityManagerNative
uid = _uid;
}
}
+
private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
/**
@@ -1688,7 +1697,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
- false, false, MY_PID, Process.SYSTEM_UID);
+ false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
mContext, proc, (ActivityRecord)data.get("activity"));
@@ -2587,6 +2596,7 @@ public final class ActivityManagerService extends ActivityManagerNative
processName);
return procs != null ? procs.valueAt(0) : null;
}
+ // uid = applyUserId(uid);
ProcessRecord proc = mProcessNames.get(processName, uid);
return proc;
}
@@ -2716,6 +2726,7 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
int uid = app.info.uid;
+
int[] gids = null;
try {
gids = mContext.getPackageManager().getPackageGids(
@@ -2827,7 +2838,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- boolean startHomeActivityLocked() {
+ boolean startHomeActivityLocked(int userId) {
if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
@@ -2850,6 +2861,8 @@ public final class ActivityManagerService extends ActivityManagerNative
aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
+ aInfo = new ActivityInfo(aInfo);
+ aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid);
if (app == null || app.instrumentationClass == null) {
@@ -2858,11 +2871,10 @@ public final class ActivityManagerService extends ActivityManagerNative
null, null, 0, 0, 0, false, false, null);
}
}
-
-
+
return true;
}
-
+
/**
* Starts the "new version setup screen" if appropriate.
*/
@@ -3026,10 +3038,23 @@ public final class ActivityManagerService extends ActivityManagerNative
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
+ 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;
+ } else {
+ userId = Binder.getOrigCallingUser();
+ }
+ }
return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
- grantedUriPermissions, grantedMode, resultTo, resultWho,
- requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
- null, null);
+ grantedUriPermissions, grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded,
+ debug, profileFile, profileFd, autoStopProfiler, null, null, userId);
}
public final WaitResult startActivityAndWait(IApplicationThread caller,
@@ -3038,10 +3063,11 @@ public final class ActivityManagerService extends ActivityManagerNative
String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
WaitResult res = new WaitResult();
+ int userId = Binder.getOrigCallingUser();
mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
- res, null);
+ res, null, userId);
return res;
}
@@ -3050,9 +3076,11 @@ public final class ActivityManagerService extends ActivityManagerNative
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded,
boolean debug, Configuration config) {
- return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
+ int ret = mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
- requestCode, onlyIfNeeded, debug, null, null, false, null, config);
+ requestCode, onlyIfNeeded,
+ debug, null, null, false, null, config, Binder.getOrigCallingUser());
+ return ret;
}
public int startActivityIntentSender(IApplicationThread caller,
@@ -3080,9 +3108,9 @@ public final class ActivityManagerService extends ActivityManagerNative
mAppSwitchesAllowedTime = 0;
}
}
-
- return pir.sendInner(0, fillInIntent, resolvedType, null,
+ int ret = pir.sendInner(0, fillInIntent, resolvedType, null,
null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
+ return ret;
}
public boolean startNextMatchingActivity(IBinder callingActivity,
@@ -3185,20 +3213,24 @@ public final class ActivityManagerService extends ActivityManagerNative
// This is so super not safe, that only the system (or okay root)
// can do it.
+ int userId = Binder.getOrigCallingUser();
final int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != Process.myUid()) {
throw new SecurityException(
"startActivityInPackage only available to the system");
}
- return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
+ int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false,
- null, null, false, null, null);
+ null, null, false, null, null, userId);
+ return ret;
}
public final int startActivities(IApplicationThread caller,
Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
- return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
+ int ret = mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo,
+ Binder.getOrigCallingUser());
+ return ret;
}
public final int startActivitiesInPackage(int uid,
@@ -3211,8 +3243,9 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(
"startActivityInPackage only available to the system");
}
-
- return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
+ int ret = mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo,
+ UserId.getUserId(uid));
+ return ret;
}
final void addRecentTaskLocked(TaskRecord task) {
@@ -3224,8 +3257,9 @@ public final class ActivityManagerService extends ActivityManagerNative
// Remove any existing entries that are the same kind of task.
for (int i=0; i<N; i++) {
TaskRecord tr = mRecentTasks.get(i);
- if ((task.affinity != null && task.affinity.equals(tr.affinity))
- || (task.intent != null && task.intent.filterEquals(tr.intent))) {
+ if (task.userId == tr.userId
+ && ((task.affinity != null && task.affinity.equals(tr.affinity))
+ || (task.intent != null && task.intent.filterEquals(tr.intent)))) {
mRecentTasks.remove(i);
i--;
N--;
@@ -3584,7 +3618,6 @@ public final class ActivityManagerService extends ActivityManagerNative
private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
IBinder threadBinder = thread.asBinder();
-
// Find the application record.
for (int i=mLruProcesses.size()-1; i>=0; i--) {
ProcessRecord rec = mLruProcesses.get(i);
@@ -3961,7 +3994,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public boolean clearApplicationUserData(final String packageName,
- final IPackageDataObserver observer) {
+ final IPackageDataObserver observer, final int userId) {
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
long callingId = Binder.clearCallingIdentity();
@@ -3996,7 +4029,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUid);
broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
- null, null, 0, null, null, null, false, false);
+ null, null, 0, null, null, null, false, false, userId);
} catch (RemoteException e) {
}
} finally {
@@ -4091,7 +4124,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
-
+ final int userId = Binder.getOrigCallingUser();
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
@@ -4099,6 +4132,8 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
try {
pkgUid = pm.getPackageUid(packageName);
+ // Convert the uid to the one for the calling user
+ pkgUid = UserId.getUid(userId, pkgUid);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -4181,7 +4216,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
broadcastIntentLocked(null, null, intent, null,
- null, 0, null, null, null, false, false, -1, uid);
+ null, 0, null, null, null, false, false, -1, uid, 0 /* TODO: Verify */);
}
Binder.restoreCallingIdentity(origId);
}
@@ -4241,7 +4276,8 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.putExtra(Intent.EXTRA_UID, uid);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
- false, false, MY_PID, Process.SYSTEM_UID);
+ false, false,
+ MY_PID, Process.SYSTEM_UID, UserId.getUserId(uid));
}
private final boolean killPackageProcessesLocked(String packageName, int uid,
@@ -4345,7 +4381,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
- for (ServiceRecord service : mServices.values()) {
+ int userId = UserId.getUserId(uid);
+ for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
if (service.packageName.equals(name)
&& (service.app == null || evenPersistent || !service.app.persistent)) {
if (!doit) {
@@ -4809,11 +4846,12 @@ public final class ActivityManagerService extends ActivityManagerNative
// Tell anyone interested that we are done booting!
SystemProperties.set("sys.boot_completed", "1");
SystemProperties.set("dev.bootcomplete", "1");
+ /* TODO: Send this to all users that are to be logged in on startup */
broadcastIntentLocked(null, null,
new Intent(Intent.ACTION_BOOT_COMPLETED, null),
null, null, 0, null, null,
android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
- false, false, MY_PID, Process.SYSTEM_UID);
+ false, false, MY_PID, Process.SYSTEM_UID, Binder.getOrigCallingUser());
}
}
}
@@ -4954,7 +4992,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
int uid = AppGlobals.getPackageManager()
.getPackageUid(packageName);
- if (uid != Binder.getCallingUid()) {
+ if (UserId.getAppId(callingUid) != uid) {
String msg = "Permission Denial: getIntentSender() from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
@@ -4965,7 +5003,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- return getIntentSenderLocked(type, packageName, callingUid,
+ if (DEBUG_MU)
+ Slog.i(TAG_MU, "Getting intent sender for origCallingUid="
+ + Binder.getOrigCallingUid());
+ return getIntentSenderLocked(type, packageName, Binder.getOrigCallingUid(),
token, resultWho, requestCode, intents, resolvedTypes, flags);
} catch (RemoteException e) {
@@ -4977,6 +5018,8 @@ public final class ActivityManagerService extends ActivityManagerNative
IIntentSender getIntentSenderLocked(int type,
String packageName, int callingUid, IBinder token, String resultWho,
int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "getIntentSenderLocked(): uid=" + callingUid);
ActivityRecord activity = null;
if (type == INTENT_SENDER_ACTIVITY_RESULT) {
activity = mMainStack.isInStackLocked(token);
@@ -5220,7 +5263,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// If there is a uid that owns whatever is being accessed, it has
// blanket access to it regardless of the permissions it requires.
- if (owningUid >= 0 && uid == owningUid) {
+ if (owningUid >= 0 && UserId.isSameApp(uid, owningUid)) {
return PackageManager.PERMISSION_GRANTED;
}
// If the target is not exported, then nobody else can get to it.
@@ -5254,7 +5297,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (permission == null) {
return PackageManager.PERMISSION_DENIED;
}
- return checkComponentPermission(permission, pid, uid, -1, true);
+ return checkComponentPermission(permission, pid, UserId.getAppId(uid), -1, true);
}
/**
@@ -5264,7 +5307,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int checkCallingPermission(String permission) {
return checkPermission(permission,
Binder.getCallingPid(),
- Binder.getCallingUid());
+ UserId.getAppId(Binder.getCallingUid()));
}
/**
@@ -5378,6 +5421,7 @@ public final class ActivityManagerService extends ActivityManagerNative
pid = tlsIdentity.pid;
}
+ uid = UserId.getAppId(uid);
// Our own process gets to do everything.
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
@@ -5420,7 +5464,8 @@ public final class ActivityManagerService extends ActivityManagerNative
String name = uri.getAuthority();
ProviderInfo pi = null;
- ContentProviderRecord cpr = mProvidersByName.get(name);
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(name,
+ UserId.getUserId(callingUid));
if (cpr != null) {
pi = cpr.info;
} else {
@@ -5676,7 +5721,8 @@ public final class ActivityManagerService extends ActivityManagerNative
final String authority = uri.getAuthority();
ProviderInfo pi = null;
- ContentProviderRecord cpr = mProvidersByName.get(authority);
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(authority,
+ UserId.getUserId(callingUid));
if (cpr != null) {
pi = cpr.info;
} else {
@@ -5770,7 +5816,8 @@ public final class ActivityManagerService extends ActivityManagerNative
final String authority = uri.getAuthority();
ProviderInfo pi = null;
- ContentProviderRecord cpr = mProvidersByName.get(authority);
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(authority,
+ UserId.getUserId(r.info.uid));
if (cpr != null) {
pi = cpr.info;
} else {
@@ -6009,6 +6056,12 @@ public final class ActivityManagerService extends ActivityManagerNative
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
int flags) {
+ 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);
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.GET_TASKS,
"getRecentTasks()");
@@ -6021,11 +6074,14 @@ public final class ActivityManagerService extends ActivityManagerNative
maxNum < N ? maxNum : N);
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;
// Return the entry if desired by the caller. We always return
// the first entry, because callers always expect this to be the
- // forground app. We may filter others if the caller has
+ // foreground app. We may filter others if the caller has
// not supplied RECENT_WITH_EXCLUDED and there is some reason
// we should exclude the entry.
+
if (i == 0
|| ((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
|| (tr.intent == null)
@@ -6114,7 +6170,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Find any running services associated with this app.
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
- for (ServiceRecord sr : mServices.values()) {
+ for (ServiceRecord sr : mServiceMap.getAllServices(root.userId)) {
if (sr.packageName.equals(component.getPackageName())) {
services.add(sr);
}
@@ -6485,17 +6541,23 @@ public final class ActivityManagerService extends ActivityManagerNative
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
} catch (RemoteException ex) {
}
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "generateApplicationProvidersLocked, app.info.uid = " + app.info.uid);
+ int userId = UserId.getUserId(app.info.uid);
if (providers != null) {
final int N = providers.size();
for (int i=0; i<N; i++) {
ProviderInfo cpi =
(ProviderInfo)providers.get(i);
+
ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
- ContentProviderRecord cpr = mProvidersByClass.get(comp);
+ ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
if (cpr == null) {
cpr = new ContentProviderRecord(cpi, app.info, comp);
- mProvidersByClass.put(comp, cpr);
+ mProviderMap.putProviderByClass(comp, cpr);
}
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
app.pubProviders.put(cpi.name, cpr);
app.addPackage(cpi.applicationInfo.packageName);
ensurePackageDexOpt(cpi.applicationInfo.packageName);
@@ -6605,8 +6667,8 @@ public final class ActivityManagerService extends ActivityManagerNative
return false;
}
- private final ContentProviderHolder getContentProviderImpl(
- IApplicationThread caller, String name) {
+ private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
+ String name) {
ContentProviderRecord cpr;
ProviderInfo cpi = null;
@@ -6623,7 +6685,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// First check if this content provider has been published...
- cpr = mProvidersByName.get(name);
+ int userId = UserId.getUserId(r != null ? r.info.uid : Binder.getCallingUid());
+ cpr = mProviderMap.getProviderByName(name, userId);
boolean providerRunning = cpr != null;
if (providerRunning) {
cpi = cpr.info;
@@ -6708,6 +6771,9 @@ public final class ActivityManagerService extends ActivityManagerNative
return null;
}
+ cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo,
+ Binder.getOrigCallingUser());
+
String msg;
if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
throw new SecurityException(msg);
@@ -6723,7 +6789,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
- cpr = mProvidersByClass.get(comp);
+ cpr = mProviderMap.getProviderByClass(comp, Binder.getOrigCallingUser());
final boolean firstClass = cpr == null;
if (firstClass) {
try {
@@ -6737,6 +6803,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ cpi.name);
return null;
}
+ ai = getAppInfoForUser(ai, Binder.getOrigCallingUser());
cpr = new ContentProviderRecord(cpi, ai, comp);
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
@@ -6805,9 +6872,9 @@ public final class ActivityManagerService extends ActivityManagerNative
// Make sure the provider is published (the same provider class
// may be published under multiple names).
if (firstClass) {
- mProvidersByClass.put(comp, cpr);
+ mProviderMap.putProviderByClass(comp, cpr);
}
- mProvidersByName.put(name, cpr);
+ mProviderMap.putProviderByName(name, cpr);
incProviderCount(r, cpr);
}
}
@@ -6826,6 +6893,10 @@ public final class ActivityManagerService extends ActivityManagerNative
return null;
}
try {
+ if (DEBUG_MU) {
+ Slog.v(TAG_MU, "Waiting to start provider " + cpr + " launchingApp="
+ + cpr.launchingApp);
+ }
cpr.wait();
} catch (InterruptedException ex) {
}
@@ -6843,7 +6914,8 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
- return getContentProviderImpl(caller, name);
+ ContentProviderHolder contentProvider = getContentProviderImpl(caller, name);
+ return contentProvider;
}
private ContentProviderHolder getContentProviderExternal(String name) {
@@ -6856,7 +6928,8 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
public void removeContentProvider(IApplicationThread caller, String name) {
synchronized (this) {
- ContentProviderRecord cpr = mProvidersByName.get(name);
+ int userId = UserId.getUserId(Binder.getCallingUid());
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(name, userId);
if(cpr == null) {
// remove from mProvidersByClass
if (DEBUG_PROVIDER) Slog.v(TAG, name +
@@ -6871,8 +6944,11 @@ public final class ActivityManagerService extends ActivityManagerNative
}
//update content provider record entry info
ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
- ContentProviderRecord localCpr = mProvidersByClass.get(comp);
- if (localCpr.proc == r) {
+ ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp, userId);
+ if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
+ + r.info.processName + " from process "
+ + localCpr.appInfo.processName);
+ if (localCpr.launchingApp == r) {
//should not happen. taken care of as a local provider
Slog.w(TAG, "removeContentProvider called on local provider: "
+ cpr.info.name + " in process " + r.processName);
@@ -6887,7 +6963,8 @@ public final class ActivityManagerService extends ActivityManagerNative
private void removeContentProviderExternal(String name) {
synchronized (this) {
- ContentProviderRecord cpr = mProvidersByName.get(name);
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(name,
+ Binder.getOrigCallingUser());
if(cpr == null) {
//remove from mProvidersByClass
if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
@@ -6896,7 +6973,8 @@ public final class ActivityManagerService extends ActivityManagerNative
//update content provider record entry info
ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
- ContentProviderRecord localCpr = mProvidersByClass.get(comp);
+ ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp,
+ Binder.getOrigCallingUser());
localCpr.externals--;
if (localCpr.externals < 0) {
Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
@@ -6913,6 +6991,8 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
final ProcessRecord r = getRecordForAppLocked(caller);
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "ProcessRecord uid = " + r.info.uid);
if (r == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
@@ -6929,12 +7009,14 @@ public final class ActivityManagerService extends ActivityManagerNative
continue;
}
ContentProviderRecord dst = r.pubProviders.get(src.info.name);
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);
if (dst != null) {
ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
- mProvidersByClass.put(comp, dst);
+ mProviderMap.putProviderByClass(comp, dst);
String names[] = dst.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
- mProvidersByName.put(names[j], dst);
+ mProviderMap.putProviderByName(names[j], dst);
}
int NL = mLaunchingProviders.size();
@@ -7679,8 +7761,10 @@ public final class ActivityManagerService extends ActivityManagerNative
};
}
Slog.i(TAG, "Sending system update to: " + intent.getComponent());
+ /* TODO: Send this to all users */
broadcastIntentLocked(null, null, intent, null, finisher,
- 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
+ 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
+ Process.SYSTEM_UID);
if (finisher != null) {
mWaitingUpdate = true;
}
@@ -9306,8 +9390,14 @@ public final class ActivityManagerService extends ActivityManagerNative
if ("all".equals(name)) {
synchronized (this) {
- for (ServiceRecord r1 : mServices.values()) {
- services.add(r1);
+ try {
+ List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
+ for (UserInfo user : users) {
+ for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
+ services.add(r1);
+ }
+ }
+ } catch (RemoteException re) {
}
}
} else {
@@ -9325,18 +9415,24 @@ public final class ActivityManagerService extends ActivityManagerNative
}
synchronized (this) {
- for (ServiceRecord r1 : mServices.values()) {
- if (componentName != null) {
- if (r1.name.equals(componentName)) {
- services.add(r1);
- }
- } else if (name != null) {
- if (r1.name.flattenToString().contains(name)) {
- services.add(r1);
+ try {
+ List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
+ for (UserInfo user : users) {
+ for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
+ if (componentName != null) {
+ if (r1.name.equals(componentName)) {
+ services.add(r1);
+ }
+ } else if (name != null) {
+ if (r1.name.flattenToString().contains(name)) {
+ services.add(r1);
+ }
+ } else if (System.identityHashCode(r1) == objectId) {
+ services.add(r1);
+ }
}
- } else if (System.identityHashCode(r1) == objectId) {
- services.add(r1);
}
+ } catch (RemoteException re) {
}
}
}
@@ -9778,75 +9874,87 @@ public final class ActivityManagerService extends ActivityManagerNative
matcher.build(args, opti);
pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
- if (mServices.size() > 0) {
- boolean printed = false;
- long nowReal = SystemClock.elapsedRealtime();
- Iterator<ServiceRecord> it = mServices.values().iterator();
- needSep = false;
- while (it.hasNext()) {
- ServiceRecord r = it.next();
- if (!matcher.match(r, r.name)) {
- continue;
- }
- if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
- continue;
- }
- if (!printed) {
- pw.println(" Active services:");
- printed = true;
- }
- if (needSep) {
- pw.println();
- }
- pw.print(" * "); pw.println(r);
- if (dumpAll) {
- r.dump(pw, " ");
- needSep = true;
- } else {
- pw.print(" app="); pw.println(r.app);
- pw.print(" created=");
- TimeUtils.formatDuration(r.createTime, nowReal, pw);
- pw.print(" started="); pw.print(r.startRequested);
- pw.print(" connections="); pw.println(r.connections.size());
- if (r.connections.size() > 0) {
- pw.println(" Connections:");
- for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
- for (int i=0; i<clist.size(); i++) {
- ConnectionRecord conn = clist.get(i);
- pw.print(" ");
- pw.print(conn.binding.intent.intent.getIntent().toShortString(
- false, false, false));
- pw.print(" -> ");
- ProcessRecord proc = conn.binding.client;
- pw.println(proc != null ? proc.toShortString() : "null");
+ try {
+ List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
+ for (UserInfo user : users) {
+ if (mServiceMap.getAllServices(user.id).size() > 0) {
+ boolean printed = false;
+ long nowReal = SystemClock.elapsedRealtime();
+ Iterator<ServiceRecord> it = mServiceMap.getAllServices(
+ user.id).iterator();
+ needSep = false;
+ while (it.hasNext()) {
+ ServiceRecord r = it.next();
+ if (!matcher.match(r, r.name)) {
+ continue;
+ }
+ if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+ continue;
+ }
+ if (!printed) {
+ pw.println(" Active services:");
+ printed = true;
+ }
+ if (needSep) {
+ pw.println();
+ }
+ pw.print(" * ");
+ pw.println(r);
+ if (dumpAll) {
+ r.dump(pw, " ");
+ needSep = true;
+ } else {
+ pw.print(" app=");
+ pw.println(r.app);
+ pw.print(" created=");
+ TimeUtils.formatDuration(r.createTime, nowReal, pw);
+ pw.print(" started=");
+ pw.print(r.startRequested);
+ pw.print(" connections=");
+ pw.println(r.connections.size());
+ if (r.connections.size() > 0) {
+ pw.println(" Connections:");
+ for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
+ for (int i = 0; i < clist.size(); i++) {
+ ConnectionRecord conn = clist.get(i);
+ pw.print(" ");
+ pw.print(conn.binding.intent.intent.getIntent()
+ .toShortString(false, false, false));
+ pw.print(" -> ");
+ ProcessRecord proc = conn.binding.client;
+ pw.println(proc != null ? proc.toShortString() : "null");
+ }
+ }
}
}
- }
- }
- if (dumpClient && r.app != null && r.app.thread != null) {
- pw.println(" Client:");
- pw.flush();
- try {
- TransferPipe tp = new TransferPipe();
- try {
- r.app.thread.dumpService(
- tp.getWriteFd().getFileDescriptor(), r, args);
- tp.setBufferPrefix(" ");
- // Short timeout, since blocking here can
- // deadlock with the application.
- tp.go(fd, 2000);
- } finally {
- tp.kill();
+ if (dumpClient && r.app != null && r.app.thread != null) {
+ pw.println(" Client:");
+ pw.flush();
+ try {
+ TransferPipe tp = new TransferPipe();
+ try {
+ r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(),
+ r, args);
+ tp.setBufferPrefix(" ");
+ // Short timeout, since blocking here can
+ // deadlock with the application.
+ tp.go(fd, 2000);
+ } finally {
+ tp.kill();
+ }
+ } catch (IOException e) {
+ pw.println(" Failure while dumping the service: " + e);
+ } catch (RemoteException e) {
+ pw.println(" Got a RemoteException while dumping the service");
+ }
+ needSep = true;
}
- } catch (IOException e) {
- pw.println(" Failure while dumping the service: " + e);
- } catch (RemoteException e) {
- pw.println(" Got a RemoteException while dumping the service");
}
- needSep = true;
+ needSep = printed;
}
}
- needSep = printed;
+ } catch (RemoteException re) {
+
}
if (mPendingServices.size() > 0) {
@@ -9956,76 +10064,8 @@ public final class ActivityManagerService extends ActivityManagerNative
matcher.build(args, opti);
pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
- if (mProvidersByClass.size() > 0) {
- boolean printed = false;
- Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it
- = mProvidersByClass.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
- ContentProviderRecord r = e.getValue();
- ComponentName comp = e.getKey();
- String cls = comp.getClassName();
- int end = cls.lastIndexOf('.');
- if (end > 0 && end < (cls.length()-2)) {
- cls = cls.substring(end+1);
- }
- if (!matcher.match(r, comp)) {
- continue;
- }
- if (dumpPackage != null && !dumpPackage.equals(comp.getPackageName())) {
- continue;
- }
- if (!printed) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Published content providers (by class):");
- printed = true;
- }
- pw.print(" * "); pw.print(cls); pw.print(" (");
- pw.print(comp.flattenToShortString()); pw.println(")");
- if (dumpAll) {
- r.dump(pw, " ");
- } else {
- if (r.proc != null) {
- pw.print(" "); pw.println(r.proc);
- } else {
- pw.println();
- }
- if (r.clients.size() > 0) {
- pw.println(" Clients:");
- for (ProcessRecord cproc : r.clients) {
- pw.print(" - "); pw.println(cproc);
- }
- }
- }
- }
- }
-
- if (dumpAll) {
- if (mProvidersByName.size() > 0) {
- boolean printed = false;
- Iterator<Map.Entry<String, ContentProviderRecord>> it
- = mProvidersByName.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<String, ContentProviderRecord> e = it.next();
- ContentProviderRecord r = e.getValue();
- if (!matcher.match(r, r.name)) {
- continue;
- }
- if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
- continue;
- }
- if (!printed) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Authority to provider mappings:");
- printed = true;
- }
- pw.print(" "); pw.print(e.getKey()); pw.println(":");
- pw.print(" "); pw.println(r);
- }
- }
- }
+
+ mProviderMap.dumpProvidersLocked(pw, dumpAll);
if (mLaunchingProviders.size() > 0) {
boolean printed = false;
@@ -10911,10 +10951,10 @@ public final class ActivityManagerService extends ActivityManagerNative
cpr.notifyAll();
}
- mProvidersByClass.remove(cpr.name);
+ mProviderMap.removeProviderByClass(cpr.name, UserId.getUserId(cpr.uid));
String names[] = cpr.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
- mProvidersByName.remove(names[j]);
+ mProviderMap.removeProviderByName(names[j], UserId.getUserId(cpr.uid));
}
Iterator<ProcessRecord> cit = cpr.clients.iterator();
@@ -11190,8 +11230,10 @@ public final class ActivityManagerService extends ActivityManagerNative
ArrayList<ActivityManager.RunningServiceInfo> res
= new ArrayList<ActivityManager.RunningServiceInfo>();
- if (mServices.size() > 0) {
- Iterator<ServiceRecord> it = mServices.values().iterator();
+ int userId = UserId.getUserId(Binder.getCallingUid());
+ if (mServiceMap.getAllServices(userId).size() > 0) {
+ Iterator<ServiceRecord> it
+ = mServiceMap.getAllServices(userId).iterator();
while (it.hasNext() && res.size() < maxNum) {
res.add(makeRunningServiceInfoLocked(it.next()));
}
@@ -11211,7 +11253,8 @@ public final class ActivityManagerService extends ActivityManagerNative
public PendingIntent getRunningServiceControlPanel(ComponentName name) {
synchronized (this) {
- ServiceRecord r = mServices.get(name);
+ int userId = UserId.getUserId(Binder.getCallingUid());
+ ServiceRecord r = mServiceMap.getServiceByName(name, userId);
if (r != null) {
for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
for (int i=0; i<conn.size(); i++) {
@@ -11227,7 +11270,7 @@ public final class ActivityManagerService extends ActivityManagerNative
private final ServiceRecord findServiceLocked(ComponentName name,
IBinder token) {
- ServiceRecord r = mServices.get(name);
+ ServiceRecord r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
return r == token ? r : null;
}
@@ -11245,11 +11288,11 @@ public final class ActivityManagerService extends ActivityManagerNative
String resolvedType) {
ServiceRecord r = null;
if (service.getComponent() != null) {
- r = mServices.get(service.getComponent());
+ r = mServiceMap.getServiceByName(service.getComponent(), Binder.getOrigCallingUser());
}
if (r == null) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
- r = mServicesByIntent.get(filter);
+ r = mServiceMap.getServiceByIntent(filter, Binder.getOrigCallingUser());
}
if (r == null) {
@@ -11265,7 +11308,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
- r = mServices.get(name);
+ r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
@@ -11312,11 +11355,17 @@ public final class ActivityManagerService extends ActivityManagerNative
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, int callingPid, int callingUid) {
ServiceRecord r = null;
+ if (DEBUG_SERVICE)
+ Slog.v(TAG, "retrieveServiceLocked: " + service + " type=" + resolvedType
+ + " origCallingUid=" + callingUid);
+
if (service.getComponent() != null) {
- r = mServices.get(service.getComponent());
+ r = mServiceMap.getServiceByName(service.getComponent(), Binder.getOrigCallingUser());
+ }
+ if (r == null) {
+ Intent.FilterComparison filter = new Intent.FilterComparison(service);
+ r = mServiceMap.getServiceByIntent(filter, Binder.getOrigCallingUser());
}
- Intent.FilterComparison filter = new Intent.FilterComparison(service);
- r = mServicesByIntent.get(filter);
if (r == null) {
try {
ResolveInfo rInfo =
@@ -11329,12 +11378,16 @@ public final class ActivityManagerService extends ActivityManagerNative
": not found");
return null;
}
-
+ if (Binder.getOrigCallingUser() > 0) {
+ sInfo.applicationInfo = getAppInfoForUser(sInfo.applicationInfo,
+ Binder.getOrigCallingUser());
+ }
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
- r = mServices.get(name);
+ r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
if (r == null) {
- filter = new Intent.FilterComparison(service.cloneFilter());
+ Intent.FilterComparison filter = new Intent.FilterComparison(
+ service.cloneFilter());
ServiceRestarter res = new ServiceRestarter();
BatteryStatsImpl.Uid.Pkg.Serv ss = null;
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
@@ -11345,8 +11398,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
r = new ServiceRecord(this, ss, name, filter, sInfo, res);
res.setService(r);
- mServices.put(name, r);
- mServicesByIntent.put(filter, r);
+ mServiceMap.putServiceByName(name, UserId.getUserId(r.appInfo.uid), r);
+ mServiceMap.putServiceByIntent(filter, UserId.getUserId(r.appInfo.uid), r);
// Make sure this component isn't in the pending list.
int N = mPendingServices.size();
@@ -11493,7 +11546,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (app.thread == null) {
throw new RemoteException();
}
-
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
+ + ", ProcessRecord.uid = " + app.info.uid);
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
@@ -11690,6 +11745,8 @@ public final class ActivityManagerService extends ActivityManagerNative
final String appName = r.processName;
ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName);
@@ -11794,8 +11851,8 @@ public final class ActivityManagerService extends ActivityManagerNative
System.identityHashCode(r), r.shortName,
(r.app != null) ? r.app.pid : -1);
- mServices.remove(r.name);
- mServicesByIntent.remove(r.intent);
+ mServiceMap.removeServiceByName(r.name, r.userId);
+ mServiceMap.removeServiceByIntent(r.intent, r.userId);
r.totalRestartCount = 0;
unscheduleServiceRestartLocked(r);
@@ -11909,6 +11966,8 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ if (DEBUG_SERVICE)
+ Slog.v(TAG, "startService: " + service + " type=" + resolvedType);
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
@@ -11923,6 +11982,8 @@ public final class ActivityManagerService extends ActivityManagerNative
ComponentName startServiceInPackage(int uid,
Intent service, String resolvedType) {
synchronized(this) {
+ if (DEBUG_SERVICE)
+ Slog.v(TAG, "startServiceInPackage: " + service + " type=" + resolvedType);
final long origId = Binder.clearCallingIdentity();
ComponentName res = startServiceLocked(null, service,
resolvedType, -1, uid);
@@ -12126,6 +12187,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
+ if (DEBUG_MU)
+ Slog.i(TAG_MU, "bindService uid=" + Binder.getCallingUid() + " origUid="
+ + Binder.getOrigCallingUid());
final ProcessRecord callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
@@ -12168,7 +12232,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
- Binder.getCallingPid(), Binder.getCallingUid());
+ Binder.getCallingPid(), Binder.getOrigCallingUid());
if (res == null) {
return 0;
}
@@ -12514,7 +12578,9 @@ public final class ActivityManagerService extends ActivityManagerNative
r.callStart = false;
}
}
-
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "before serviceDontExecutingLocked, uid="
+ + Binder.getOrigCallingUid());
final long origId = Binder.clearCallingIdentity();
serviceDoneExecutingLocked(r, inStopping);
Binder.restoreCallingIdentity(origId);
@@ -12927,7 +12993,8 @@ public final class ActivityManagerService extends ActivityManagerNative
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle map, String requiredPermission,
- boolean ordered, boolean sticky, int callingPid, int callingUid) {
+ boolean ordered, boolean sticky, int callingPid, int callingUid,
+ int userId) {
intent = new Intent(intent);
// By default broadcasts do not go to stopped apps.
@@ -13102,10 +13169,11 @@ public final class ActivityManagerService extends ActivityManagerNative
if (ai != null) {
receivers = new ArrayList();
ResolveInfo ri = new ResolveInfo();
- ri.activityInfo = ai;
+ ri.activityInfo = getActivityInfoForUser(ai, userId);
receivers.add(ri);
}
} else {
+ // TODO: Apply userId
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
@@ -13274,7 +13342,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized, boolean sticky) {
+ String requiredPermission, boolean serialized, boolean sticky, int userId) {
synchronized(this) {
intent = verifyBroadcastLocked(intent);
@@ -13285,8 +13353,8 @@ public final class ActivityManagerService extends ActivityManagerNative
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
- resultCode, resultData, map, requiredPermission, serialized,
- sticky, callingPid, callingUid);
+ resultCode, resultData, map, requiredPermission, serialized, sticky,
+ callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -13295,21 +13363,21 @@ public final class ActivityManagerService extends ActivityManagerNative
int broadcastIntentInPackage(String packageName, int uid,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized, boolean sticky) {
+ String requiredPermission, boolean serialized, boolean sticky, int userId) {
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
resultTo, resultCode, resultData, map, requiredPermission,
- serialized, sticky, -1, uid);
+ serialized, sticky, -1, uid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
- public final void unbroadcastIntent(IApplicationThread caller,
- Intent intent) {
+ // TODO: Use the userId; maybe mStickyBroadcasts need to be tied to the user.
+ public final void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -13514,7 +13582,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
-
// =========================================================
// INSTRUMENTATION
// =========================================================
@@ -13786,12 +13853,12 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
- null, false, false, MY_PID, Process.SYSTEM_UID);
+ null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
broadcastIntentLocked(null, null,
new Intent(Intent.ACTION_LOCALE_CHANGED),
null, null, 0, null, null,
- null, false, false, MY_PID, Process.SYSTEM_UID);
+ null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
}
}
}
@@ -15134,8 +15201,157 @@ public final class ActivityManagerService extends ActivityManagerNative
// Multi-user methods
- public boolean switchUser(int userid) {
- // TODO
+ private int mCurrentUserId;
+ private SparseIntArray mLoggedInUsers = new SparseIntArray(5);
+
+ public boolean switchUser(int userId) {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != 0 && callingUid != Process.myUid()) {
+ Slog.e(TAG, "Trying to switch user from unauthorized app");
+ return false;
+ }
+ if (mCurrentUserId == userId)
+ return true;
+
+ synchronized (this) {
+ // Check if user is already logged in, otherwise check if user exists first before
+ // adding to the list of logged in users.
+ if (mLoggedInUsers.indexOfKey(userId) < 0) {
+ if (!userExists(userId)) {
+ return false;
+ }
+ mLoggedInUsers.append(userId, userId);
+ }
+
+ mCurrentUserId = userId;
+ boolean haveActivities = mMainStack.switchUser(userId);
+ if (!haveActivities) {
+ startHomeActivityLocked(userId);
+ }
+ }
return true;
}
+
+ private boolean userExists(int userId) {
+ try {
+ List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
+ for (UserInfo user : users) {
+ if (user.id == userId) {
+ return true;
+ }
+ }
+ } catch (RemoteException re) {
+ // Won't happen, in same process
+ }
+
+ return false;
+ }
+
+
+ private int applyUserId(int uid, int userId) {
+ return UserId.getUid(userId, uid);
+ }
+
+ private ApplicationInfo getAppInfoForUser(ApplicationInfo info, int userId) {
+ ApplicationInfo newInfo = new ApplicationInfo(info);
+ newInfo.uid = applyUserId(info.uid, userId);
+ if (newInfo.uid >= Process.FIRST_APPLICATION_UID) {
+ newInfo.dataDir = USER_DATA_DIR + userId + "/"
+ + info.packageName;
+ }
+ return newInfo;
+ }
+
+ ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId) {
+ if (aInfo.applicationInfo.uid < Process.FIRST_APPLICATION_UID
+ || userId < 1) {
+ return aInfo;
+ }
+
+ ActivityInfo info = new ActivityInfo(aInfo);
+ info.applicationInfo = getAppInfoForUser(info.applicationInfo, userId);
+ return info;
+ }
+
+ static class ServiceMap {
+
+ private final SparseArray<HashMap<ComponentName, ServiceRecord>> mServicesByNamePerUser
+ = new SparseArray<HashMap<ComponentName, ServiceRecord>>();
+ private final SparseArray<HashMap<Intent.FilterComparison, ServiceRecord>>
+ mServicesByIntentPerUser = new SparseArray<
+ HashMap<Intent.FilterComparison, ServiceRecord>>();
+
+ ServiceRecord getServiceByName(ComponentName name, int callingUser) {
+ // TODO: Deal with global services
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "getServiceByName(" + name + "), callingUser = " + callingUser);
+ return getServices(callingUser).get(name);
+ }
+
+ ServiceRecord getServiceByName(ComponentName name) {
+ return getServiceByName(name, -1);
+ }
+
+ ServiceRecord getServiceByIntent(Intent.FilterComparison filter, int callingUser) {
+ // TODO: Deal with global services
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "getServiceByIntent(" + filter + "), callingUser = " + callingUser);
+ return getServicesByIntent(callingUser).get(filter);
+ }
+
+ ServiceRecord getServiceByIntent(Intent.FilterComparison filter) {
+ return getServiceByIntent(filter, -1);
+ }
+
+ void putServiceByName(ComponentName name, int callingUser, ServiceRecord value) {
+ // TODO: Deal with global services
+ getServices(callingUser).put(name, value);
+ }
+
+ void putServiceByIntent(Intent.FilterComparison filter, int callingUser,
+ ServiceRecord value) {
+ // TODO: Deal with global services
+ getServicesByIntent(callingUser).put(filter, value);
+ }
+
+ void removeServiceByName(ComponentName name, int callingUser) {
+ // TODO: Deal with global services
+ ServiceRecord removed = getServices(callingUser).remove(name);
+ if (DEBUG_MU)
+ Slog.v(TAG, "removeServiceByName user=" + callingUser + " name=" + name
+ + " removed=" + removed);
+ }
+
+ void removeServiceByIntent(Intent.FilterComparison filter, int callingUser) {
+ // TODO: Deal with global services
+ ServiceRecord removed = getServicesByIntent(callingUser).remove(filter);
+ if (DEBUG_MU)
+ Slog.v(TAG_MU, "removeServiceByIntent user=" + callingUser + " intent=" + filter
+ + " removed=" + removed);
+ }
+
+ Collection<ServiceRecord> getAllServices(int callingUser) {
+ // TODO: Deal with global services
+ return getServices(callingUser).values();
+ }
+
+ private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
+ HashMap map = mServicesByNamePerUser.get(callingUser);
+ if (map == null) {
+ map = new HashMap<ComponentName, ServiceRecord>();
+ mServicesByNamePerUser.put(callingUser, map);
+ }
+ return map;
+ }
+
+ private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
+ int callingUser) {
+ HashMap map = mServicesByIntentPerUser.get(callingUser);
+ if (map == null) {
+ map = new HashMap<Intent.FilterComparison, ServiceRecord>();
+ mServicesByIntentPerUser.put(callingUser, map);
+ }
+ return map;
+ }
+ }
}