Skip to content

Commit 7767eac

Browse files
author
Dianne Hackborn
committed
Keep track of whether an app is installed for each user.
This add a new per-user state for an app, indicating whether it is installed for that user. All system apps are always installed for all users (we still use disable to "uninstall" them). Now when you call into the package manager to install an app, it will only install the app for that user unless you supply a flag saying to install for all users. Only being installed for the user is just the normal install state, but all other users have marked in their state for that app that it is not installed. When you call the package manager APIs for information about apps, uninstalled apps are treated as really being not visible (somewhat more-so than disabled apps), unless you use the GET_UNINSTALLED_PACKAGES flag. If another user calls to install an app that is already installed, just not for them, then the normal install process takes place but in addition that user's installed state is toggled on. The package manager will not send PACKAGE_ADDED, PACKAGE_REMOVED, PACKAGE_REPLACED etc broadcasts to users who don't have a package installed or not being involved in a change in the install state. There are a few things that are not quite right with this -- for example if you go through a full install (with a new apk) of an app for one user who doesn't have it already installed, you will still get the PACKAGED_REPLACED messages even though this is technically the first install for your user. I'm not sure how much of an issue this is. When you call the existing API to uninstall an app, this toggles the installed state of the app for that user to be off. Only if that is the last user user that has the app uinstalled will it actually be removed from the device. Again there is a new flag you can pass in to force the app to be uninstalled for all users. Also fixed issues with cleaning external storage of apps, which was not dealing with multiple users. We now keep track of cleaning each user for each package. Change-Id: I00e66452b149defc08c5e0183fa673f532465ed5
1 parent 1552586 commit 7767eac

File tree

31 files changed

+1176
-456
lines changed

31 files changed

+1176
-456
lines changed

api/current.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6293,6 +6293,7 @@ package android.content.pm {
62936293
field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000
62946294
field public static final int FLAG_FACTORY_TEST = 16; // 0x10
62956295
field public static final int FLAG_HAS_CODE = 4; // 0x4
6296+
field public static final int FLAG_INSTALLED = 8388608; // 0x800000
62966297
field public static final int FLAG_KILL_AFTER_RESTORE = 65536; // 0x10000
62976298
field public static final int FLAG_LARGE_HEAP = 1048576; // 0x100000
62986299
field public static final int FLAG_PERSISTENT = 8; // 0x8
@@ -6629,6 +6630,17 @@ package android.content.pm {
66296630
field public java.lang.String packageName;
66306631
}
66316632

6633+
public class PackageUserState {
6634+
ctor public PackageUserState();
6635+
ctor public PackageUserState(android.content.pm.PackageUserState);
6636+
field public java.util.HashSet disabledComponents;
6637+
field public int enabled;
6638+
field public java.util.HashSet enabledComponents;
6639+
field public boolean installed;
6640+
field public boolean notLaunched;
6641+
field public boolean stopped;
6642+
}
6643+
66326644
public class PathPermission extends android.os.PatternMatcher {
66336645
ctor public PathPermission(java.lang.String, int, java.lang.String, java.lang.String);
66346646
ctor public PathPermission(android.os.Parcel);
@@ -26928,6 +26940,7 @@ package android.webkit {
2692826940
method public synchronized int getDefaultFixedFontSize();
2692926941
method public synchronized int getDefaultFontSize();
2693026942
method public synchronized java.lang.String getDefaultTextEncodingName();
26943+
method public static java.lang.String getDefaultUserAgent(android.content.Context);
2693126944
method public android.webkit.WebSettings.ZoomDensity getDefaultZoom();
2693226945
method public boolean getDisplayZoomControls();
2693326946
method public synchronized boolean getDomStorageEnabled();
@@ -26958,7 +26971,6 @@ package android.webkit {
2695826971
method public synchronized boolean getUseWideViewPort();
2695926972
method public deprecated synchronized int getUserAgent();
2696026973
method public synchronized java.lang.String getUserAgentString();
26961-
method public static java.lang.String getDefaultUserAgent(android.content.Context);
2696226974
method public void setAllowContentAccess(boolean);
2696326975
method public void setAllowFileAccess(boolean);
2696426976
method public abstract void setAllowFileAccessFromFileURLs(boolean);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ private Intent makeIntent() throws URISyntaxException {
393393
private void runStartService() throws Exception {
394394
Intent intent = makeIntent();
395395
System.out.println("Starting service: " + intent);
396-
ComponentName cn = mAm.startService(null, intent, intent.getType());
396+
ComponentName cn = mAm.startService(null, intent, intent.getType(), 0);
397397
if (cn == null) {
398398
System.err.println("Error: Not found; no service started.");
399399
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ private void runGetInstallLocation() {
776776
}
777777

778778
private void runInstall() {
779-
int installFlags = 0;
779+
int installFlags = PackageManager.INSTALL_ALL_USERS;
780780
String installerPackageName = null;
781781

782782
String opt;
@@ -811,6 +811,8 @@ private void runInstall() {
811811
} else if (opt.equals("-f")) {
812812
// Override if -s option is specified.
813813
installFlags |= PackageManager.INSTALL_INTERNAL;
814+
} else if (opt.equals("-d")) {
815+
installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
814816
} else if (opt.equals("--algo")) {
815817
algo = nextOptionData();
816818
if (algo == null) {
@@ -1105,7 +1107,7 @@ private void runUninstall() {
11051107

11061108
String opt = nextOption();
11071109
if (opt != null && opt.equals("-k")) {
1108-
unInstallFlags = PackageManager.DONT_DELETE_DATA;
1110+
unInstallFlags = PackageManager.DELETE_KEEP_DATA;
11091111
}
11101112

11111113
String pkg = nextArg();
@@ -1525,6 +1527,7 @@ private static void showUsage() {
15251527
System.err.println(" -i: specify the installer package name.");
15261528
System.err.println(" -s: install package on sdcard.");
15271529
System.err.println(" -f: install package on internal flash.");
1530+
System.err.println(" -d: allow version code downgrade.");
15281531
System.err.println("");
15291532
System.err.println("pm uninstall: removes a package from the system. Options:");
15301533
System.err.println(" -k: keep the data and cache directories around after package removal.");

core/java/android/app/ActivityManagerNative.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,8 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
697697
IApplicationThread app = ApplicationThreadNative.asInterface(b);
698698
Intent service = Intent.CREATOR.createFromParcel(data);
699699
String resolvedType = data.readString();
700-
ComponentName cn = startService(app, service, resolvedType);
700+
int userId = data.readInt();
701+
ComponentName cn = startService(app, service, resolvedType, userId);
701702
reply.writeNoException();
702703
ComponentName.writeToParcel(cn, reply);
703704
return true;
@@ -709,7 +710,8 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
709710
IApplicationThread app = ApplicationThreadNative.asInterface(b);
710711
Intent service = Intent.CREATOR.createFromParcel(data);
711712
String resolvedType = data.readString();
712-
int res = stopService(app, service, resolvedType);
713+
int userId = data.readInt();
714+
int res = stopService(app, service, resolvedType, userId);
713715
reply.writeNoException();
714716
reply.writeInt(res);
715717
return true;
@@ -2523,14 +2525,15 @@ public PendingIntent getRunningServiceControlPanel(ComponentName service)
25232525
}
25242526

25252527
public ComponentName startService(IApplicationThread caller, Intent service,
2526-
String resolvedType) throws RemoteException
2528+
String resolvedType, int userId) throws RemoteException
25272529
{
25282530
Parcel data = Parcel.obtain();
25292531
Parcel reply = Parcel.obtain();
25302532
data.writeInterfaceToken(IActivityManager.descriptor);
25312533
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
25322534
service.writeToParcel(data, 0);
25332535
data.writeString(resolvedType);
2536+
data.writeInt(userId);
25342537
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
25352538
reply.readException();
25362539
ComponentName res = ComponentName.readFromParcel(reply);
@@ -2539,14 +2542,15 @@ public ComponentName startService(IApplicationThread caller, Intent service,
25392542
return res;
25402543
}
25412544
public int stopService(IApplicationThread caller, Intent service,
2542-
String resolvedType) throws RemoteException
2545+
String resolvedType, int userId) throws RemoteException
25432546
{
25442547
Parcel data = Parcel.obtain();
25452548
Parcel reply = Parcel.obtain();
25462549
data.writeInterfaceToken(IActivityManager.descriptor);
25472550
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
25482551
service.writeToParcel(data, 0);
25492552
data.writeString(resolvedType);
2553+
data.writeInt(userId);
25502554
mRemote.transact(STOP_SERVICE_TRANSACTION, data, reply, 0);
25512555
reply.readException();
25522556
int res = reply.readInt();

core/java/android/app/ApplicationPackageManager.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import android.content.pm.UserInfo;
4646
import android.content.pm.VerificationParams;
4747
import android.content.pm.VerifierDeviceIdentity;
48+
import android.content.pm.PackageManager.NameNotFoundException;
4849
import android.content.res.Resources;
4950
import android.content.res.XmlResourceParser;
5051
import android.graphics.drawable.Drawable;
@@ -996,6 +997,21 @@ public void installPackageWithVerificationAndEncryption(Uri packageURI,
996997
}
997998
}
998999

1000+
@Override
1001+
public int installExistingPackage(String packageName)
1002+
throws NameNotFoundException {
1003+
try {
1004+
int res = mPM.installExistingPackage(packageName);
1005+
if (res == INSTALL_FAILED_INVALID_URI) {
1006+
throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1007+
}
1008+
return res;
1009+
} catch (RemoteException e) {
1010+
// Should never happen!
1011+
throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1012+
}
1013+
}
1014+
9991015
@Override
10001016
public void verifyPendingInstall(int id, int response) {
10011017
try {

core/java/android/app/ContextImpl.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,11 +1220,21 @@ public void unregisterReceiver(BroadcastReceiver receiver) {
12201220

12211221
@Override
12221222
public ComponentName startService(Intent service) {
1223+
return startServiceAsUser(service, Process.myUserHandle());
1224+
}
1225+
1226+
@Override
1227+
public boolean stopService(Intent service) {
1228+
return stopServiceAsUser(service, Process.myUserHandle());
1229+
}
1230+
1231+
@Override
1232+
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
12231233
try {
12241234
service.setAllowFds(false);
12251235
ComponentName cn = ActivityManagerNative.getDefault().startService(
12261236
mMainThread.getApplicationThread(), service,
1227-
service.resolveTypeIfNeeded(getContentResolver()));
1237+
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
12281238
if (cn != null && cn.getPackageName().equals("!")) {
12291239
throw new SecurityException(
12301240
"Not allowed to start service " + service
@@ -1237,12 +1247,12 @@ public ComponentName startService(Intent service) {
12371247
}
12381248

12391249
@Override
1240-
public boolean stopService(Intent service) {
1250+
public boolean stopServiceAsUser(Intent service, UserHandle user) {
12411251
try {
12421252
service.setAllowFds(false);
12431253
int res = ActivityManagerNative.getDefault().stopService(
12441254
mMainThread.getApplicationThread(), service,
1245-
service.resolveTypeIfNeeded(getContentResolver()));
1255+
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
12461256
if (res < 0) {
12471257
throw new SecurityException(
12481258
"Not allowed to stop service " + service);

core/java/android/app/IActivityManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,9 @@ public boolean refContentProvider(IBinder connection, int stableDelta, int unsta
133133
public PendingIntent getRunningServiceControlPanel(ComponentName service)
134134
throws RemoteException;
135135
public ComponentName startService(IApplicationThread caller, Intent service,
136-
String resolvedType) throws RemoteException;
136+
String resolvedType, int userId) throws RemoteException;
137137
public int stopService(IApplicationThread caller, Intent service,
138-
String resolvedType) throws RemoteException;
138+
String resolvedType, int userId) throws RemoteException;
139139
public boolean stopServiceToken(ComponentName className, IBinder token,
140140
int startId) throws RemoteException;
141141
public void setServiceForeground(ComponentName className, IBinder token,

core/java/android/content/Context.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,16 @@ public abstract Intent registerReceiver(BroadcastReceiver receiver,
14131413
*/
14141414
public abstract boolean stopService(Intent service);
14151415

1416+
/**
1417+
* @hide like {@link #startService(Intent)} but for a specific user.
1418+
*/
1419+
public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
1420+
1421+
/**
1422+
* @hide like {@link #stopService(Intent)} but for a specific user.
1423+
*/
1424+
public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
1425+
14161426
/**
14171427
* Connect to an application service, creating it if needed. This defines
14181428
* a dependency between your application and the service. The given

core/java/android/content/ContextWrapper.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,18 @@ public boolean stopService(Intent name) {
410410
return mBase.stopService(name);
411411
}
412412

413+
/** @hide */
414+
@Override
415+
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
416+
return mBase.startServiceAsUser(service, user);
417+
}
418+
419+
/** @hide */
420+
@Override
421+
public boolean stopServiceAsUser(Intent name, UserHandle user) {
422+
return mBase.stopServiceAsUser(name, user);
423+
}
424+
413425
@Override
414426
public boolean bindService(Intent service, ServiceConnection conn,
415427
int flags) {

core/java/android/content/pm/ApplicationInfo.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,12 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
301301
*/
302302
public static final int FLAG_SUPPORTS_RTL = 1<<22;
303303

304+
/**
305+
* Value for {@link #flags}: true if the application is currently
306+
* installed for the calling user.
307+
*/
308+
public static final int FLAG_INSTALLED = 1<<23;
309+
304310
/**
305311
* Value for {@link #flags}: Set to true if the application has been
306312
* installed using the forward lock option.
@@ -334,7 +340,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
334340
* {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
335341
* {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_SUPPORTS_XLARGE_SCREENS},
336342
* {@link #FLAG_RESIZEABLE_FOR_SCREENS},
337-
* {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE}
343+
* {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE},
344+
* {@link #FLAG_INSTALLED}.
338345
*/
339346
public int flags = 0;
340347

0 commit comments

Comments
 (0)