summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-09-10 14:52:30 -0700
committerDianne Hackborn <hackbod@google.com>2012-09-10 14:52:30 -0700
commit1676c856d61b97c871dc2be0cb1f1fb1e12e24e9 (patch)
tree7352f5bccdec8d7b9d90f9fb1d43dfa901e00f4a
parent41bd89f6b61296492d3775e5ef30e94c5f18d34f (diff)
downloadframeworks_base-1676c856d61b97c871dc2be0cb1f1fb1e12e24e9.zip
frameworks_base-1676c856d61b97c871dc2be0cb1f1fb1e12e24e9.tar.gz
frameworks_base-1676c856d61b97c871dc2be0cb1f1fb1e12e24e9.tar.bz2
Flesh out multi-user in am commands.
Now we default to the current user instead of user 0 for most commands (except where we can do the command for all users). Many more commands take a user argument: force-stop, kill, profile, dumpheap. Improved help text. Change-Id: I719a13b4d31b668f57ca21e51d7043ac3e0d4e1b
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java151
-rw-r--r--core/java/android/app/ActivityManager.java6
-rw-r--r--core/java/android/app/ActivityManagerNative.java24
-rw-r--r--core/java/android/app/IActivityManager.java9
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--services/java/com/android/server/am/ActiveServices.java62
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java171
-rw-r--r--services/java/com/android/server/pm/UserManagerService.java2
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;
}