summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/am/ActivityManagerService.java
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2011-05-04 14:49:28 -0700
committerAmith Yamasani <yamasani@google.com>2012-02-03 12:01:47 -0800
commit742a67127366c376fdf188ff99ba30b27d3bf90c (patch)
tree4a801b0b2e9ee10fb322e3b450e2af9eb6e3002f /services/java/com/android/server/am/ActivityManagerService.java
parent8ca8a69d5801ad4b809e7b9dbf53bd728820924b (diff)
downloadframeworks_base-742a67127366c376fdf188ff99ba30b27d3bf90c.zip
frameworks_base-742a67127366c376fdf188ff99ba30b27d3bf90c.tar.gz
frameworks_base-742a67127366c376fdf188ff99ba30b27d3bf90c.tar.bz2
Multi-user - 1st major checkin
Switching activity stacks Cache ContentProvider per user Long-press power to switch users (on phone) Added ServiceMap for separating services by user Launch PendingIntents on the correct user's uid Fix task switching from Recents list AppWidgetService is mostly working. Commands added to pm and am to allow creating and switching profiles. Change-Id: I15810e8cfbe50a04bd3323a7ef5a8ff4230870ed
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;
+ }
+ }
}