diff options
-rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 151 | ||||
-rw-r--r-- | core/java/android/app/ActivityManager.java | 6 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 24 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 9 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 2 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActiveServices.java | 62 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 171 | ||||
-rw-r--r-- | services/java/com/android/server/pm/UserManagerService.java | 2 |
8 files changed, 269 insertions, 158 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index bb108c8..89287ad 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -63,7 +63,7 @@ public class Am { private boolean mStopOption = false; private int mRepeat = 0; - private int mUserId = 0; + private int mUserId; private String mProfileFile; @@ -160,7 +160,7 @@ public class Am { return userId; } - private Intent makeIntent() throws URISyntaxException { + private Intent makeIntent(int defUser) throws URISyntaxException { Intent intent = new Intent(); Intent baseIntent = intent; boolean hasIntentInfo = false; @@ -170,7 +170,7 @@ public class Am { mStopOption = false; mRepeat = 0; mProfileFile = null; - mUserId = 0; + mUserId = defUser; Uri data = null; String type = null; @@ -404,7 +404,7 @@ public class Am { } private void runStartService() throws Exception { - Intent intent = makeIntent(); + Intent intent = makeIntent(UserHandle.USER_CURRENT); if (mUserId == UserHandle.USER_ALL) { System.err.println("Error: Can't start activity with user 'all'"); return; @@ -417,7 +417,7 @@ public class Am { } private void runStart() throws Exception { - Intent intent = makeIntent(); + Intent intent = makeIntent(UserHandle.USER_CURRENT); if (mUserId == UserHandle.USER_ALL) { System.err.println("Error: Can't start service with user 'all'"); @@ -456,7 +456,7 @@ public class Am { packageName = activities.get(0).activityInfo.packageName; } System.out.println("Stopping: " + packageName); - mAm.forceStopPackage(packageName); + mAm.forceStopPackage(packageName, mUserId); Thread.sleep(250); } @@ -570,11 +570,33 @@ public class Am { } private void runForceStop() throws Exception { - mAm.forceStopPackage(nextArgRequired()); + int userId = UserHandle.USER_ALL; + + String opt; + while ((opt=nextOption()) != null) { + if (opt.equals("--user")) { + userId = parseUserArg(nextArgRequired()); + } else { + System.err.println("Error: Unknown option: " + opt); + return; + } + } + mAm.forceStopPackage(nextArgRequired(), userId); } private void runKill() throws Exception { - mAm.killBackgroundProcesses(nextArgRequired()); + int userId = UserHandle.USER_ALL; + + String opt; + while ((opt=nextOption()) != null) { + if (opt.equals("--user")) { + userId = parseUserArg(nextArgRequired()); + } else { + System.err.println("Error: Unknown option: " + opt); + return; + } + } + mAm.killBackgroundProcesses(nextArgRequired(), userId); } private void runKillAll() throws Exception { @@ -582,7 +604,7 @@ public class Am { } private void sendBroadcast() throws Exception { - Intent intent = makeIntent(); + Intent intent = makeIntent(UserHandle.USER_ALL); IntentReceiver receiver = new IntentReceiver(); System.out.println("Broadcasting: " + intent); mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false, @@ -595,7 +617,7 @@ public class Am { boolean wait = false; boolean rawMode = false; boolean no_window_animation = false; - int userId = 0; + int userId = UserHandle.USER_CURRENT; Bundle args = new Bundle(); String argKey = null, argValue = null; IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); @@ -672,17 +694,37 @@ public class Am { String profileFile = null; boolean start = false; boolean wall = false; + int userId = UserHandle.USER_CURRENT; int profileType = 0; - + String process = null; - + String cmd = nextArgRequired(); if ("start".equals(cmd)) { start = true; - wall = "--wall".equals(nextOption()); + String opt; + while ((opt=nextOption()) != null) { + if (opt.equals("--user")) { + userId = parseUserArg(nextArgRequired()); + } else if (opt.equals("--wall")) { + wall = true; + } else { + System.err.println("Error: Unknown option: " + opt); + return; + } + } process = nextArgRequired(); } else if ("stop".equals(cmd)) { + String opt; + while ((opt=nextOption()) != null) { + if (opt.equals("--user")) { + userId = parseUserArg(nextArgRequired()); + } else { + System.err.println("Error: Unknown option: " + opt); + return; + } + } process = nextArg(); } else { // Compatibility with old syntax: process is specified first. @@ -694,7 +736,12 @@ public class Am { throw new IllegalArgumentException("Profile command " + process + " not valid"); } } - + + if (userId == UserHandle.USER_ALL) { + System.err.println("Error: Can't profile with user 'all'"); + return; + } + ParcelFileDescriptor fd = null; if (start) { @@ -722,7 +769,7 @@ public class Am { } else if (start) { //removeWallOption(); } - if (!mAm.profileControl(process, start, profileFile, fd, profileType)) { + if (!mAm.profileControl(process, userId, start, profileFile, fd, profileType)) { wall = false; throw new AndroidException("PROFILE FAILED on process " + process); } @@ -734,7 +781,24 @@ public class Am { } private void runDumpHeap() throws Exception { - boolean managed = !"-n".equals(nextOption()); + boolean managed = true; + int userId = UserHandle.USER_CURRENT; + + String opt; + while ((opt=nextOption()) != null) { + if (opt.equals("--user")) { + userId = parseUserArg(nextArgRequired()); + if (userId == UserHandle.USER_ALL) { + System.err.println("Error: Can't dump heap with user 'all'"); + return; + } + } else if (opt.equals("-n")) { + managed = false; + } else { + System.err.println("Error: Unknown option: " + opt); + return; + } + } String process = nextArgRequired(); String heapFile = nextArgRequired(); ParcelFileDescriptor fd = null; @@ -750,7 +814,7 @@ public class Am { return; } - if (!mAm.dumpHeap(process, managed, heapFile, fd)) { + if (!mAm.dumpHeap(process, userId, managed, heapFile, fd)) { throw new AndroidException("HEAP DUMP FAILED on process " + process); } } @@ -1204,7 +1268,7 @@ public class Am { } private void runToUri(boolean intentScheme) throws Exception { - Intent intent = makeIntent(); + Intent intent = makeIntent(UserHandle.USER_CURRENT); System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0)); } @@ -1363,18 +1427,19 @@ public class Am { System.err.println( "usage: am [subcommand] [options]\n" + "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + - " [--R COUNT] [-S] [--opengl-trace] <INTENT>\n" + - " am startservice <INTENT>\n" + - " am force-stop <PACKAGE>\n" + - " am kill <PACKAGE>\n" + + " [--R COUNT] [-S] [--opengl-trace]\n" + + " [--user <USER_ID> | current] <INTENT>\n" + + " am startservice [--user <USER_ID> | current] <INTENT>\n" + + " am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" + + " am kill [--user <USER_ID> | all | current] <PACKAGE>\n" + " am kill-all\n" + - " am broadcast <INTENT>\n" + + " am broadcast [--user <USER_ID> | all | current] <INTENT>\n" + " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" + - " [--user <USER_ID> | all | current]\n" + + " [--user <USER_ID> | current]\n" + " [--no-window-animation] <COMPONENT>\n" + - " am profile start <PROCESS> <FILE>\n" + - " am profile stop [<PROCESS>]\n" + - " am dumpheap [flags] <PROCESS> <FILE>\n" + + " am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" + + " am profile stop [--user <USER_ID> current] [<PROCESS>]\n" + + " am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" + " am set-debug-app [-w] [--persistent] <PACKAGE>\n" + " am clear-debug-app\n" + " am monitor [--gdb <port>]\n" + @@ -1395,18 +1460,28 @@ public class Am { " the top activity will be finished.\n" + " -S: force stop the target app before starting the activity\n" + " --opengl-trace: enable tracing of OpenGL functions\n" + + " --user <USER_ID> | current: Specify which user to run as; if not\n" + + " specified then run as the current user.\n" + "\n" + - "am startservice: start a Service.\n" + + "am startservice: start a Service. Options are:\n" + + " --user <USER_ID> | current: Specify which user to run as; if not\n" + + " specified then run as the current user.\n" + "\n" + "am force-stop: force stop everything associated with <PACKAGE>.\n" + + " --user <USER_ID> | all | current: Specify user to force stop;\n" + + " all users if not specified.\n" + "\n" + "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" + " processes that are safe to kill -- that is, will not impact the user\n" + " experience.\n" + + " --user <USER_ID> | all | current: Specify user whose processes to kill;\n" + + " all users if not specified.\n" + "\n" + "am kill-all: Kill all background processes.\n" + "\n" + - "am broadcast: send a broadcast Intent.\n" + + "am broadcast: send a broadcast Intent. Options are:\n" + + " --user <USER_ID> | all | current: Specify which user to send to; if not\n" + + " specified then send to all users.\n" + "\n" + "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" + " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" + @@ -1417,13 +1492,20 @@ public class Am { " -p <FILE>: write profiling data to <FILE>\n" + " -w: wait for instrumentation to finish before returning. Required for\n" + " test runners.\n" + - " --user [<USER_ID> | all | current]: Specify user instrumentation runs in.\n" + + " --user <USER_ID> | current: Specify user instrumentation runs in;\n" + + " current user if not specified.\n" + " --no-window-animation: turn off window animations will running.\n" + "\n" + - "am profile: start and stop profiler on a process.\n" + + "am profile: start and stop profiler on a process. The given <PROCESS> argument\n" + + " may be either a process name or pid. Options are:\n" + + " --user <USER_ID> | current: When supplying a process name,\n" + + " specify user of process to profile; uses current user if not specified.\n" + "\n" + - "am dumpheap: dump the heap of a process. Options are:\n" + + "am dumpheap: dump the heap of a process. The given <PROCESS> argument may\n" + + " be either a process name or pid. Options are:\n" + " -n: dump native heap instead of managed heap\n" + + " --user <USER_ID> | current: When supplying a process name,\n" + + " specify user of process to dump; uses current user if not specified.\n" + "\n" + "am set-debug-app: set application <PACKAGE> to debug. Options are:\n" + " -w: wait for debugger when application starts\n" + @@ -1444,10 +1526,10 @@ public class Am { "\n" + "am to-intent-uri: print the given Intent specification as an intent: URI.\n" + "\n" + - "am switch-user: switch to put USER_ID in the foreground, starting" + + "am switch-user: switch to put USER_ID in the foreground, starting\n" + " execution of that user if it is currently stopped.\n" + "\n" + - "am stop-user: stop execution of USER_ID, not allowing it to run any" + + "am stop-user: stop execution of USER_ID, not allowing it to run any\n" + " code until a later explicit switch to it.\n" + "\n" + "<INTENT> specifications include these flags and arguments:\n" + @@ -1465,7 +1547,6 @@ public class Am { " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" + " [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" + " [-n <COMPONENT>] [-f <FLAGS>]\n" + - " [--user [<USER_ID> | all | current]\n" + " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" + " [--debug-log-resolution] [--exclude-stopped-packages]\n" + " [--include-stopped-packages]\n" + diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index bb3c56a..06f79e7 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1693,7 +1693,8 @@ public class ActivityManager { */ public void killBackgroundProcesses(String packageName) { try { - ActivityManagerNative.getDefault().killBackgroundProcesses(packageName); + ActivityManagerNative.getDefault().killBackgroundProcesses(packageName, + UserHandle.myUserId()); } catch (RemoteException e) { } } @@ -1718,7 +1719,8 @@ public class ActivityManager { */ public void forceStopPackage(String packageName) { try { - ActivityManagerNative.getDefault().forceStopPackage(packageName); + ActivityManagerNative.getDefault().forceStopPackage(packageName, + UserHandle.myUserId()); } catch (RemoteException e) { } } diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index e5dd7b1..bf77f6e 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1214,7 +1214,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case KILL_BACKGROUND_PROCESSES_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String packageName = data.readString(); - killBackgroundProcesses(packageName); + int userId = data.readInt(); + killBackgroundProcesses(packageName, userId); reply.writeNoException(); return true; } @@ -1229,7 +1230,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case FORCE_STOP_PACKAGE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String packageName = data.readString(); - forceStopPackage(packageName); + int userId = data.readInt(); + forceStopPackage(packageName, userId); reply.writeNoException(); return true; } @@ -1255,12 +1257,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case PROFILE_CONTROL_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String process = data.readString(); + int userId = data.readInt(); boolean start = data.readInt() != 0; int profileType = data.readInt(); String path = data.readString(); ParcelFileDescriptor fd = data.readInt() != 0 ? data.readFileDescriptor() : null; - boolean res = profileControl(process, start, path, fd, profileType); + boolean res = profileControl(process, userId, start, path, fd, profileType); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -1484,9 +1487,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM String process = data.readString(); boolean managed = data.readInt() != 0; String path = data.readString(); + int userId = data.readInt(); ParcelFileDescriptor fd = data.readInt() != 0 ? data.readFileDescriptor() : null; - boolean res = dumpHeap(process, managed, path, fd); + boolean res = dumpHeap(process, userId, managed, path, fd); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -3264,11 +3268,12 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } - public void killBackgroundProcesses(String packageName) throws RemoteException { + public void killBackgroundProcesses(String packageName, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeString(packageName); + data.writeInt(userId); mRemote.transact(KILL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); @@ -3285,11 +3290,12 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } - public void forceStopPackage(String packageName) throws RemoteException { + public void forceStopPackage(String packageName, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeString(packageName); + data.writeInt(userId); mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); @@ -3322,13 +3328,14 @@ class ActivityManagerProxy implements IActivityManager return res; } - public boolean profileControl(String process, boolean start, + public boolean profileControl(String process, int userId, boolean start, String path, ParcelFileDescriptor fd, int profileType) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeString(process); + data.writeInt(userId); data.writeInt(start ? 1 : 0); data.writeInt(profileType); data.writeString(path); @@ -3601,12 +3608,13 @@ class ActivityManagerProxy implements IActivityManager return res; } - public boolean dumpHeap(String process, boolean managed, + public boolean dumpHeap(String process, int userId, boolean managed, String path, ParcelFileDescriptor fd) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeString(process); + data.writeInt(userId); data.writeInt(managed ? 1 : 0); data.writeString(path); if (fd != null) { diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 9cb3621..4c0e2a7 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -208,9 +208,10 @@ public interface IActivityManager extends IInterface { public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException; - public void killBackgroundProcesses(final String packageName) throws RemoteException; + public void killBackgroundProcesses(final String packageName, int userId) + throws RemoteException; public void killAllBackgroundProcesses() throws RemoteException; - public void forceStopPackage(final String packageName) throws RemoteException; + public void forceStopPackage(final String packageName, int userId) throws RemoteException; // Note: probably don't want to allow applications access to these. public void goingToSleep() throws RemoteException; @@ -267,7 +268,7 @@ public interface IActivityManager extends IInterface { public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException; // Turn on/off profiling in a particular process. - public boolean profileControl(String process, boolean start, + public boolean profileControl(String process, int userId, boolean start, String path, ParcelFileDescriptor fd, int profileType) throws RemoteException; public boolean shutdown(int timeout) throws RemoteException; @@ -308,7 +309,7 @@ public interface IActivityManager extends IInterface { Uri uri, int modeFlags) throws RemoteException; // Cause the specified process to dump the specified heap. - public boolean dumpHeap(String process, boolean managed, String path, + public boolean dumpHeap(String process, int userId, boolean managed, String path, ParcelFileDescriptor fd) throws RemoteException; public int startActivities(IApplicationThread caller, diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index c28afb2..73e82ab 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -37,14 +37,12 @@ import android.os.ServiceManager; import android.os.StrictMode; import android.os.SystemClock; import android.os.SystemProperties; -import android.provider.Settings; import android.server.search.SearchManagerService; import android.service.dreams.DreamManagerService; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.util.Slog; -import android.view.Display; import android.view.WindowManager; import com.android.internal.os.BinderInternal; diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index 2975880..3bb95a8 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -1763,12 +1763,11 @@ public class ActiveServices { if (ActivityManager.checkUidPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid) == PackageManager.PERMISSION_GRANTED) { - List<UserInfo> users = mAm.getUserManager().getUsers(); - for (int ui=0; ui<users.size() && res.size() < maxNum; ui++) { - final UserInfo user = users.get(ui); - if (mServiceMap.getAllServices(user.id).size() > 0) { + int[] users = mAm.getUsersLocked(); + for (int ui=0; ui<users.length && res.size() < maxNum; ui++) { + if (mServiceMap.getAllServices(users[ui]).size() > 0) { Iterator<ServiceRecord> it = mServiceMap.getAllServices( - user.id).iterator(); + users[ui]).iterator(); while (it.hasNext() && res.size() < maxNum) { res.add(makeRunningServiceInfoLocked(it.next())); } @@ -1873,14 +1872,13 @@ public class ActiveServices { pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)"); try { - List<UserInfo> users = mAm.getUserManager().getUsers(); - for (int ui=0; ui<users.size(); ui++) { - final UserInfo user = users.get(ui); - if (mServiceMap.getAllServices(user.id).size() > 0) { + int[] users = mAm.getUsersLocked(); + for (int user : users) { + if (mServiceMap.getAllServices(user).size() > 0) { boolean printed = false; long nowReal = SystemClock.elapsedRealtime(); Iterator<ServiceRecord> it = mServiceMap.getAllServices( - user.id).iterator(); + user).iterator(); needSep = false; while (it.hasNext()) { ServiceRecord r = it.next(); @@ -1891,10 +1889,10 @@ public class ActiveServices { continue; } if (!printed) { - if (ui > 0) { + if (user != 0) { pw.println(); } - pw.println(" User " + user.id + " active services:"); + pw.println(" User " + user + " active services:"); printed = true; } if (needSep) { @@ -2070,32 +2068,30 @@ public class ActiveServices { int opti, boolean dumpAll) { ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>(); - List<UserInfo> users = mAm.getUserManager().getUsers(); - if ("all".equals(name)) { - synchronized (this) { - for (UserInfo user : users) { - for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) { + synchronized (this) { + int[] users = mAm.getUsersLocked(); + if ("all".equals(name)) { + for (int user : users) { + for (ServiceRecord r1 : mServiceMap.getAllServices(user)) { services.add(r1); } } - } - } else { - ComponentName componentName = name != null - ? ComponentName.unflattenFromString(name) : null; - int objectId = 0; - if (componentName == null) { - // Not a '/' separated full component name; maybe an object ID? - try { - objectId = Integer.parseInt(name, 16); - name = null; - componentName = null; - } catch (RuntimeException e) { + } else { + ComponentName componentName = name != null + ? ComponentName.unflattenFromString(name) : null; + int objectId = 0; + if (componentName == null) { + // Not a '/' separated full component name; maybe an object ID? + try { + objectId = Integer.parseInt(name, 16); + name = null; + componentName = null; + } catch (RuntimeException e) { + } } - } - synchronized (this) { - for (UserInfo user : users) { - for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) { + for (int user : users) { + for (ServiceRecord r1 : mServiceMap.getAllServices(user)) { if (componentName != null) { if (r1.name.equals(componentName)) { services.add(r1); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 0b2d769..ca90368 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -27,6 +27,7 @@ import com.android.server.ProcessMap; import com.android.server.SystemServer; import com.android.server.Watchdog; import com.android.server.am.ActivityStack.ActivityState; +import com.android.server.pm.UserManagerService; import com.android.server.wm.WindowManagerService; import dalvik.system.Zygote; @@ -99,6 +100,7 @@ import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; import android.os.IPermissionController; +import android.os.IUserManager; import android.os.Looper; import android.os.Message; import android.os.Parcel; @@ -112,7 +114,6 @@ import android.os.StrictMode; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; -import android.os.UserManager; import android.provider.Settings; import android.text.format.Time; import android.util.EventLog; @@ -811,7 +812,7 @@ public final class ActivityManagerService extends ActivityManagerNative static ActivityThread mSystemThread; private int mCurrentUserId; - private UserManager mUserManager; + private UserManagerService mUserManager; private final class AppDeathRecipient implements IBinder.DeathRecipient { final ProcessRecord mApp; @@ -3401,10 +3402,12 @@ public final class ActivityManagerService extends ActivityManagerNative } public boolean clearApplicationUserData(final String packageName, - final IPackageDataObserver observer, final int userId) { + final IPackageDataObserver observer, int userId) { enforceNotIsolatedCaller("clearApplicationUserData"); int uid = Binder.getCallingUid(); int pid = Binder.getCallingPid(); + userId = handleIncomingUserLocked(pid, uid, + userId, false, true, "clearApplicationUserData", null); long callingId = Binder.clearCallingIdentity(); try { IPackageManager pm = AppGlobals.getPackageManager(); @@ -3446,7 +3449,7 @@ public final class ActivityManagerService extends ActivityManagerNative return true; } - public void killBackgroundProcesses(final String packageName) { + public void killBackgroundProcesses(final String packageName, int userId) { if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) != PackageManager.PERMISSION_GRANTED && checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES) @@ -3458,22 +3461,23 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, msg); throw new SecurityException(msg); } - - int userId = UserHandle.getCallingUserId(); + + userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), + userId, true, true, "killBackgroundProcesses", null); long callingId = Binder.clearCallingIdentity(); try { IPackageManager pm = AppGlobals.getPackageManager(); - int pkgUid = -1; synchronized(this) { + int appId = -1; try { - pkgUid = pm.getPackageUid(packageName, userId); + appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0)); } catch (RemoteException e) { } - if (pkgUid == -1) { + if (appId == -1) { Slog.w(TAG, "Invalid packageName: " + packageName); return; } - killPackageProcessesLocked(packageName, pkgUid, -1, + killPackageProcessesLocked(packageName, appId, userId, ProcessList.SERVICE_ADJ, false, true, true, false, "kill background"); } } finally { @@ -3523,7 +3527,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - public void forceStopPackage(final String packageName) { + public void forceStopPackage(final String packageName, int userId) { if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: forceStopPackage() from pid=" @@ -3533,27 +3537,34 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, msg); throw new SecurityException(msg); } - final int userId = UserHandle.getCallingUserId(); + userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), + userId, true, true, "forceStopPackage", null); long callingId = Binder.clearCallingIdentity(); try { IPackageManager pm = AppGlobals.getPackageManager(); - int pkgUid = -1; synchronized(this) { - try { - pkgUid = pm.getPackageUid(packageName, userId); - } catch (RemoteException e) { - } - if (pkgUid == -1) { - Slog.w(TAG, "Invalid packageName: " + packageName); - return; - } - forceStopPackageLocked(packageName, pkgUid); - try { - pm.setPackageStoppedState(packageName, true, userId); - } catch (RemoteException e) { - } catch (IllegalArgumentException e) { - Slog.w(TAG, "Failed trying to unstop package " - + packageName + ": " + e); + int[] users = userId == UserHandle.USER_ALL + ? getUsersLocked() : new int[] { userId }; + for (int user : users) { + int pkgUid = -1; + try { + pkgUid = pm.getPackageUid(packageName, user); + } catch (RemoteException e) { + } + if (pkgUid == -1) { + Slog.w(TAG, "Invalid packageName: " + packageName); + continue; + } + try { + pm.setPackageStoppedState(packageName, true, user); + } catch (RemoteException e) { + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Failed trying to unstop package " + + packageName + ": " + e); + } + if (isUserRunningLocked(user)) { + forceStopPackageLocked(packageName, pkgUid); + } } } } finally { @@ -3685,8 +3696,8 @@ public final class ActivityManagerService extends ActivityManagerNative } private void forceStopPackageLocked(final String packageName, int uid) { - forceStopPackageLocked(packageName, uid, false, false, true, false, - UserHandle.getUserId(uid)); + forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false, + false, true, false, UserHandle.getUserId(uid)); Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED, Uri.fromParts("package", packageName, null)); if (!mProcessesReady) { @@ -13688,7 +13699,7 @@ public final class ActivityManagerService extends ActivityManagerNative mAutoStopProfiler = false; } - public boolean profileControl(String process, boolean start, + public boolean profileControl(String process, int userId, boolean start, String path, ParcelFileDescriptor fd, int profileType) throws RemoteException { try { @@ -13707,22 +13718,7 @@ public final class ActivityManagerService extends ActivityManagerNative ProcessRecord proc = null; if (process != null) { - try { - int pid = Integer.parseInt(process); - synchronized (mPidsSelfLocked) { - proc = mPidsSelfLocked.get(pid); - } - } catch (NumberFormatException e) { - } - - if (proc == null) { - HashMap<String, SparseArray<ProcessRecord>> all - = mProcessNames.getMap(); - SparseArray<ProcessRecord> procs = all.get(process); - if (procs != null && procs.size() > 0) { - proc = procs.valueAt(0); - } - } + proc = findProcessLocked(process, userId, "profileControl"); } if (start && (proc == null || proc.thread == null)) { @@ -13766,7 +13762,40 @@ public final class ActivityManagerService extends ActivityManagerNative } } - public boolean dumpHeap(String process, boolean managed, + private ProcessRecord findProcessLocked(String process, int userId, String callName) { + userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), + userId, true, true, callName, null); + ProcessRecord proc = null; + try { + int pid = Integer.parseInt(process); + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(pid); + } + } catch (NumberFormatException e) { + } + + if (proc == null) { + HashMap<String, SparseArray<ProcessRecord>> all + = mProcessNames.getMap(); + SparseArray<ProcessRecord> procs = all.get(process); + if (procs != null && procs.size() > 0) { + proc = procs.valueAt(0); + if (userId != UserHandle.USER_ALL && proc.userId != userId) { + for (int i=1; i<procs.size(); i++) { + ProcessRecord thisProc = procs.valueAt(i); + if (thisProc.userId == userId) { + proc = thisProc; + break; + } + } + } + } + } + + return proc; + } + + public boolean dumpHeap(String process, int userId, boolean managed, String path, ParcelFileDescriptor fd) throws RemoteException { try { @@ -13783,24 +13812,7 @@ public final class ActivityManagerService extends ActivityManagerNative throw new IllegalArgumentException("null fd"); } - ProcessRecord proc = null; - try { - int pid = Integer.parseInt(process); - synchronized (mPidsSelfLocked) { - proc = mPidsSelfLocked.get(pid); - } - } catch (NumberFormatException e) { - } - - if (proc == null) { - HashMap<String, SparseArray<ProcessRecord>> all - = mProcessNames.getMap(); - SparseArray<ProcessRecord> procs = all.get(process); - if (procs != null && procs.size() > 0) { - proc = procs.valueAt(0); - } - } - + ProcessRecord proc = findProcessLocked(process, userId, "dumpHeap"); if (proc == null || proc.thread == null) { throw new IllegalArgumentException("Unknown process: " + process); } @@ -14018,7 +14030,7 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException(msg); } synchronized (this) { - return getUserManager().getUserInfo(mCurrentUserId); + return getUserManagerLocked().getUserInfo(mCurrentUserId); } } @@ -14034,19 +14046,32 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException(msg); } synchronized (this) { - UserStartedState state = mStartedUsers.get(userId); - return state != null && state.mState != UserStartedState.STATE_STOPPING; + return isUserRunningLocked(userId); } } + boolean isUserRunningLocked(int userId) { + UserStartedState state = mStartedUsers.get(userId); + return state != null && state.mState != UserStartedState.STATE_STOPPING; + } + private boolean userExists(int userId) { - UserInfo user = getUserManager().getUserInfo(userId); - return user != null; + if (userId == 0) { + return true; + } + UserManagerService ums = getUserManagerLocked(); + return ums != null ? (ums.getUserInfo(userId) != null) : false; + } + + int[] getUsersLocked() { + UserManagerService ums = getUserManagerLocked(); + return ums != null ? ums.getUserIds() : new int[] { 0 }; } - UserManager getUserManager() { + UserManagerService getUserManagerLocked() { if (mUserManager == null) { - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + IBinder b = ServiceManager.getService(Context.USER_SERVICE); + mUserManager = (UserManagerService)IUserManager.Stub.asInterface(b); } return mUserManager; } diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java index a13c16e..3391668 100644 --- a/services/java/com/android/server/pm/UserManagerService.java +++ b/services/java/com/android/server/pm/UserManagerService.java @@ -281,7 +281,7 @@ public class UserManagerService extends IUserManager.Stub { * cache it elsewhere. * @return the array of user ids. */ - int[] getUserIds() { + public int[] getUserIds() { synchronized (mPackagesLock) { return mUserIds; } |