Skip to content

Commit 5e03e2c

Browse files
author
Dianne Hackborn
committed
More multi-user stuff:
- New (hidden) isUserRunning() API. - Maintain LRU list of visited users. - New FLAG_IS_DATA_ONLY for ApplicationInfo. - Clean up pending intent records when force-stopping a user (or package). (Also fixes bug #6880627: PendingIntent.getService() returns stale intent of force stopped app) - Fix force-stopping when installing an app to do the force-stop across all users for that app. - When selecting which processes to kill during a force stop, do this based on the actual packages loaded in the process, not just process name matching. - You can now use --user option in am when starting activities, services, and instrumentation. - The am --user option accepts "current" and "all" as arguments. - The pm uninstall command now uninstalls for all users, so it matches the semantics of the install command. - PhoneWindowManager now explicitly says to start home in the current user. - Activity manager call to retrieve the MIME type from a content provider now takes a user argument, so it will direct this to the proper user. - The package manager uninstall paths are now implemented around PackageSetting, not PackageParser.Package. This allows them to work even if the application's apk has been removed (in which case it only exists as a PackageSetting, not the PackageParser.Package parsed from the apk). Change-Id: I3522f6fcf32603090bd6e01cc90ce70b6c5aae40
1 parent 970683c commit 5e03e2c

File tree

17 files changed

+543
-304
lines changed

17 files changed

+543
-304
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6327,6 +6327,7 @@ package android.content.pm {
63276327
field public static final int FLAG_FACTORY_TEST = 16; // 0x10
63286328
field public static final int FLAG_HAS_CODE = 4; // 0x4
63296329
field public static final int FLAG_INSTALLED = 8388608; // 0x800000
6330+
field public static final int FLAG_IS_DATA_ONLY = 16777216; // 0x1000000
63306331
field public static final int FLAG_KILL_AFTER_RESTORE = 65536; // 0x10000
63316332
field public static final int FLAG_LARGE_HEAP = 1048576; // 0x100000
63326333
field public static final int FLAG_PERSISTENT = 8; // 0x8

cmds/am/src/com/android/commands/am/Am.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import android.os.RemoteException;
3737
import android.os.ServiceManager;
3838
import android.os.SystemProperties;
39+
import android.os.UserHandle;
3940
import android.util.AndroidException;
4041
import android.view.Display;
4142
import android.view.IWindowManager;
@@ -147,6 +148,18 @@ private void run(String[] args) throws Exception {
147148
}
148149
}
149150

151+
int parseUserArg(String arg) {
152+
int userId;
153+
if ("all".equals(arg)) {
154+
userId = UserHandle.USER_ALL;
155+
} else if ("current".equals(arg) || "cur".equals(arg)) {
156+
userId = UserHandle.USER_CURRENT;
157+
} else {
158+
userId = Integer.parseInt(arg);
159+
}
160+
return userId;
161+
}
162+
150163
private Intent makeIntent() throws URISyntaxException {
151164
Intent intent = new Intent();
152165
Intent baseIntent = intent;
@@ -321,7 +334,7 @@ private Intent makeIntent() throws URISyntaxException {
321334
} else if (opt.equals("--opengl-trace")) {
322335
mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
323336
} else if (opt.equals("--user")) {
324-
mUserId = Integer.parseInt(nextArgRequired());
337+
mUserId = parseUserArg(nextArgRequired());
325338
} else {
326339
System.err.println("Error: Unknown option: " + opt);
327340
return null;
@@ -392,8 +405,12 @@ private Intent makeIntent() throws URISyntaxException {
392405

393406
private void runStartService() throws Exception {
394407
Intent intent = makeIntent();
408+
if (mUserId == UserHandle.USER_ALL) {
409+
System.err.println("Error: Can't start activity with user 'all'");
410+
return;
411+
}
395412
System.out.println("Starting service: " + intent);
396-
ComponentName cn = mAm.startService(null, intent, intent.getType(), 0);
413+
ComponentName cn = mAm.startService(null, intent, intent.getType(), mUserId);
397414
if (cn == null) {
398415
System.err.println("Error: Not found; no service started.");
399416
}
@@ -402,10 +419,15 @@ private void runStartService() throws Exception {
402419
private void runStart() throws Exception {
403420
Intent intent = makeIntent();
404421

422+
if (mUserId == UserHandle.USER_ALL) {
423+
System.err.println("Error: Can't start service with user 'all'");
424+
return;
425+
}
426+
405427
String mimeType = intent.getType();
406428
if (mimeType == null && intent.getData() != null
407429
&& "content".equals(intent.getData().getScheme())) {
408-
mimeType = mAm.getProviderMimeType(intent.getData());
430+
mimeType = mAm.getProviderMimeType(intent.getData(), mUserId);
409431
}
410432

411433
do {
@@ -460,11 +482,11 @@ private void runStart() throws Exception {
460482
int res;
461483
if (mWaitOption) {
462484
result = mAm.startActivityAndWait(null, intent, mimeType,
463-
null, null, 0, mStartFlags, mProfileFile, fd, null);
485+
null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId);
464486
res = result.result;
465487
} else {
466-
res = mAm.startActivity(null, intent, mimeType,
467-
null, null, 0, mStartFlags, mProfileFile, fd, null);
488+
res = mAm.startActivityAsUser(null, intent, mimeType,
489+
null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId);
468490
}
469491
PrintStream out = mWaitOption ? System.out : System.err;
470492
boolean launched = false;
@@ -573,6 +595,7 @@ private void runInstrument() throws Exception {
573595
boolean wait = false;
574596
boolean rawMode = false;
575597
boolean no_window_animation = false;
598+
int userId = 0;
576599
Bundle args = new Bundle();
577600
String argKey = null, argValue = null;
578601
IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
@@ -592,12 +615,19 @@ private void runInstrument() throws Exception {
592615
} else if (opt.equals("--no_window_animation")
593616
|| opt.equals("--no-window-animation")) {
594617
no_window_animation = true;
618+
} else if (opt.equals("--user")) {
619+
userId = parseUserArg(nextArgRequired());
595620
} else {
596621
System.err.println("Error: Unknown option: " + opt);
597622
return;
598623
}
599624
}
600625

626+
if (userId == UserHandle.USER_ALL) {
627+
System.err.println("Error: Can't start instrumentation with user 'all'");
628+
return;
629+
}
630+
601631
String cnArg = nextArgRequired();
602632
ComponentName cn = ComponentName.unflattenFromString(cnArg);
603633
if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
@@ -614,7 +644,7 @@ private void runInstrument() throws Exception {
614644
wm.setAnimationScale(1, 0.0f);
615645
}
616646

617-
if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
647+
if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, userId)) {
618648
throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
619649
}
620650

@@ -1338,6 +1368,7 @@ private static void showUsage() {
13381368
" am kill-all\n" +
13391369
" am broadcast <INTENT>\n" +
13401370
" am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
1371+
" [--user <USER_ID> | all | current]\n" +
13411372
" [--no-window-animation] <COMPONENT>\n" +
13421373
" am profile start <PROCESS> <FILE>\n" +
13431374
" am profile stop [<PROCESS>]\n" +
@@ -1384,6 +1415,7 @@ private static void showUsage() {
13841415
" -p <FILE>: write profiling data to <FILE>\n" +
13851416
" -w: wait for instrumentation to finish before returning. Required for\n" +
13861417
" test runners.\n" +
1418+
" --user [<USER_ID> | all | current]: Specify user instrumentation runs in.\n" +
13871419
" --no-window-animation: turn off window animations will running.\n" +
13881420
"\n" +
13891421
"am profile: start and stop profiler on a process.\n" +
@@ -1431,6 +1463,7 @@ private static void showUsage() {
14311463
" [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
14321464
" [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
14331465
" [-n <COMPONENT>] [-f <FLAGS>]\n" +
1466+
" [--user [<USER_ID> | all | current]\n" +
14341467
" [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
14351468
" [--debug-log-resolution] [--exclude-stopped-packages]\n" +
14361469
" [--include-stopped-packages]\n" +

cmds/pm/src/com/android/commands/pm/Pm.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import android.app.ActivityManagerNative;
2222
import android.content.ComponentName;
23-
import android.content.Context;
2423
import android.content.pm.ApplicationInfo;
2524
import android.content.pm.ContainerEncryptionParams;
2625
import android.content.pm.FeatureInfo;
@@ -40,12 +39,9 @@
4039
import android.content.res.AssetManager;
4140
import android.content.res.Resources;
4241
import android.net.Uri;
43-
import android.os.Binder;
4442
import android.os.IUserManager;
45-
import android.os.Process;
4643
import android.os.RemoteException;
4744
import android.os.ServiceManager;
48-
import android.os.UserManager;
4945

5046
import java.io.File;
5147
import java.lang.reflect.Field;
@@ -74,7 +70,6 @@ public final class Pm {
7470

7571
private static final String PM_NOT_RUNNING_ERR =
7672
"Error: Could not access the Package Manager. Is the system running?";
77-
private static final int ROOT_UID = 0;
7873

7974
public static void main(String[] args) {
8075
new Pm().run(args);
@@ -1054,11 +1049,16 @@ public void packageDeleted(String packageName, int returnCode) {
10541049
}
10551050

10561051
private void runUninstall() {
1057-
int unInstallFlags = 0;
1052+
int unInstallFlags = PackageManager.DELETE_ALL_USERS;
10581053

1059-
String opt = nextOption();
1060-
if (opt != null && opt.equals("-k")) {
1061-
unInstallFlags = PackageManager.DELETE_KEEP_DATA;
1054+
String opt;
1055+
while ((opt=nextOption()) != null) {
1056+
if (opt.equals("-k")) {
1057+
unInstallFlags |= PackageManager.DELETE_KEEP_DATA;
1058+
} else {
1059+
System.err.println("Error: Unknown option: " + opt);
1060+
return;
1061+
}
10621062
}
10631063

10641064
String pkg = nextArg();

core/java/android/app/ActivityManager.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,4 +1957,21 @@ public boolean switchUser(int userid) {
19571957
return false;
19581958
}
19591959
}
1960+
1961+
/**
1962+
* Return whether the given user is actively running. This means that
1963+
* the user is in the "started" state, not "stopped" -- it is currently
1964+
* allowed to run code through scheduled alarms, receiving broadcasts,
1965+
* etc. A started user may be either the current foreground user or a
1966+
* background user; the result here does not distinguish between the two.
1967+
* @param userid the user's id. Zero indicates the default user.
1968+
* @hide
1969+
*/
1970+
public boolean isUserRunning(int userid) {
1971+
try {
1972+
return ActivityManagerNative.getDefault().isUserRunning(userid);
1973+
} catch (RemoteException e) {
1974+
return false;
1975+
}
1976+
}
19601977
}

core/java/android/app/ActivityManagerNative.java

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,10 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
177177
? data.readFileDescriptor() : null;
178178
Bundle options = data.readInt() != 0
179179
? Bundle.CREATOR.createFromParcel(data) : null;
180+
int userId = data.readInt();
180181
WaitResult result = startActivityAndWait(app, intent, resolvedType,
181182
resultTo, resultWho, requestCode, startFlags,
182-
profileFile, profileFd, options);
183+
profileFile, profileFd, options, userId);
183184
reply.writeNoException();
184185
result.writeToParcel(reply, 0);
185186
return true;
@@ -811,7 +812,8 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
811812
Bundle arguments = data.readBundle();
812813
IBinder b = data.readStrongBinder();
813814
IInstrumentationWatcher w = IInstrumentationWatcher.Stub.asInterface(b);
814-
boolean res = startInstrumentation(className, profileFile, fl, arguments, w);
815+
int userId = data.readInt();
816+
boolean res = startInstrumentation(className, profileFile, fl, arguments, w, userId);
815817
reply.writeNoException();
816818
reply.writeInt(res ? 1 : 0);
817819
return true;
@@ -1323,11 +1325,11 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
13231325
return true;
13241326
}
13251327

1326-
case KILL_APPLICATION_WITH_UID_TRANSACTION: {
1328+
case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
13271329
data.enforceInterface(IActivityManager.descriptor);
13281330
String pkg = data.readString();
1329-
int uid = data.readInt();
1330-
killApplicationWithUid(pkg, uid);
1331+
int appid = data.readInt();
1332+
killApplicationWithAppId(pkg, appid);
13311333
reply.writeNoException();
13321334
return true;
13331335
}
@@ -1424,7 +1426,8 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
14241426
case GET_PROVIDER_MIME_TYPE_TRANSACTION: {
14251427
data.enforceInterface(IActivityManager.descriptor);
14261428
Uri uri = Uri.CREATOR.createFromParcel(data);
1427-
String type = getProviderMimeType(uri);
1429+
int userId = data.readInt();
1430+
String type = getProviderMimeType(uri, userId);
14281431
reply.writeNoException();
14291432
reply.writeString(type);
14301433
return true;
@@ -1573,6 +1576,15 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
15731576
return true;
15741577
}
15751578

1579+
case IS_USER_RUNNING_TRANSACTION: {
1580+
data.enforceInterface(IActivityManager.descriptor);
1581+
int userid = data.readInt();
1582+
boolean result = isUserRunning(userid);
1583+
reply.writeNoException();
1584+
reply.writeInt(result ? 1 : 0);
1585+
return true;
1586+
}
1587+
15761588
case REMOVE_SUB_TASK_TRANSACTION:
15771589
{
15781590
data.enforceInterface(IActivityManager.descriptor);
@@ -1827,7 +1839,7 @@ public int startActivityAsUser(IApplicationThread caller, Intent intent,
18271839
public WaitResult startActivityAndWait(IApplicationThread caller, Intent intent,
18281840
String resolvedType, IBinder resultTo, String resultWho,
18291841
int requestCode, int startFlags, String profileFile,
1830-
ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
1842+
ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException {
18311843
Parcel data = Parcel.obtain();
18321844
Parcel reply = Parcel.obtain();
18331845
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -1851,6 +1863,7 @@ public WaitResult startActivityAndWait(IApplicationThread caller, Intent intent,
18511863
} else {
18521864
data.writeInt(0);
18531865
}
1866+
data.writeInt(userId);
18541867
mRemote.transact(START_ACTIVITY_AND_WAIT_TRANSACTION, data, reply, 0);
18551868
reply.readException();
18561869
WaitResult result = WaitResult.CREATOR.createFromParcel(reply);
@@ -2719,7 +2732,7 @@ public void unbindBackupAgent(ApplicationInfo app) throws RemoteException {
27192732
}
27202733

27212734
public boolean startInstrumentation(ComponentName className, String profileFile,
2722-
int flags, Bundle arguments, IInstrumentationWatcher watcher)
2735+
int flags, Bundle arguments, IInstrumentationWatcher watcher, int userId)
27232736
throws RemoteException {
27242737
Parcel data = Parcel.obtain();
27252738
Parcel reply = Parcel.obtain();
@@ -2729,6 +2742,7 @@ public boolean startInstrumentation(ComponentName className, String profileFile,
27292742
data.writeInt(flags);
27302743
data.writeBundle(arguments);
27312744
data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
2745+
data.writeInt(userId);
27322746
mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0);
27332747
reply.readException();
27342748
boolean res = reply.readInt() != 0;
@@ -3366,13 +3380,13 @@ public void resumeAppSwitches() throws RemoteException {
33663380
data.recycle();
33673381
}
33683382

3369-
public void killApplicationWithUid(String pkg, int uid) throws RemoteException {
3383+
public void killApplicationWithAppId(String pkg, int appid) throws RemoteException {
33703384
Parcel data = Parcel.obtain();
33713385
Parcel reply = Parcel.obtain();
33723386
data.writeInterfaceToken(IActivityManager.descriptor);
33733387
data.writeString(pkg);
3374-
data.writeInt(uid);
3375-
mRemote.transact(KILL_APPLICATION_WITH_UID_TRANSACTION, data, reply, 0);
3388+
data.writeInt(appid);
3389+
mRemote.transact(KILL_APPLICATION_WITH_APPID_TRANSACTION, data, reply, 0);
33763390
reply.readException();
33773391
data.recycle();
33783392
reply.recycle();
@@ -3507,12 +3521,12 @@ public void crashApplication(int uid, int initialPid, String packageName,
35073521
reply.recycle();
35083522
}
35093523

3510-
public String getProviderMimeType(Uri uri)
3511-
throws RemoteException {
3524+
public String getProviderMimeType(Uri uri, int userId) throws RemoteException {
35123525
Parcel data = Parcel.obtain();
35133526
Parcel reply = Parcel.obtain();
35143527
data.writeInterfaceToken(IActivityManager.descriptor);
35153528
uri.writeToParcel(data, 0);
3529+
data.writeInt(userId);
35163530
mRemote.transact(GET_PROVIDER_MIME_TYPE_TRANSACTION, data, reply, 0);
35173531
reply.readException();
35183532
String res = reply.readString();
@@ -3747,6 +3761,19 @@ public UserInfo getCurrentUser() throws RemoteException {
37473761
return userInfo;
37483762
}
37493763

3764+
public boolean isUserRunning(int userid) throws RemoteException {
3765+
Parcel data = Parcel.obtain();
3766+
Parcel reply = Parcel.obtain();
3767+
data.writeInterfaceToken(IActivityManager.descriptor);
3768+
data.writeInt(userid);
3769+
mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
3770+
reply.readException();
3771+
boolean result = reply.readInt() != 0;
3772+
reply.recycle();
3773+
data.recycle();
3774+
return result;
3775+
}
3776+
37503777
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException {
37513778
Parcel data = Parcel.obtain();
37523779
Parcel reply = Parcel.obtain();

core/java/android/app/ContextImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1428,7 +1428,7 @@ public boolean startInstrumentation(ComponentName className,
14281428
arguments.setAllowFds(false);
14291429
}
14301430
return ActivityManagerNative.getDefault().startInstrumentation(
1431-
className, profileFile, 0, arguments, null);
1431+
className, profileFile, 0, arguments, null, UserHandle.myUserId());
14321432
} catch (RemoteException e) {
14331433
// System has crashed, nothing we can do.
14341434
}

0 commit comments

Comments
 (0)