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
diff --git a/api/current.txt b/api/current.txt
index 7ad9cad..d3c12a6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6327,6 +6327,7 @@
field public static final int FLAG_FACTORY_TEST = 16; // 0x10
field public static final int FLAG_HAS_CODE = 4; // 0x4
field public static final int FLAG_INSTALLED = 8388608; // 0x800000
+ field public static final int FLAG_IS_DATA_ONLY = 16777216; // 0x1000000
field public static final int FLAG_KILL_AFTER_RESTORE = 65536; // 0x10000
field public static final int FLAG_LARGE_HEAP = 1048576; // 0x100000
field public static final int FLAG_PERSISTENT = 8; // 0x8
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index bcd4588..f4dcc3a 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -36,6 +36,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.util.AndroidException;
import android.view.Display;
import android.view.IWindowManager;
@@ -147,6 +148,18 @@
}
}
+ int parseUserArg(String arg) {
+ int userId;
+ if ("all".equals(arg)) {
+ userId = UserHandle.USER_ALL;
+ } else if ("current".equals(arg) || "cur".equals(arg)) {
+ userId = UserHandle.USER_CURRENT;
+ } else {
+ userId = Integer.parseInt(arg);
+ }
+ return userId;
+ }
+
private Intent makeIntent() throws URISyntaxException {
Intent intent = new Intent();
Intent baseIntent = intent;
@@ -321,7 +334,7 @@
} else if (opt.equals("--opengl-trace")) {
mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
} else if (opt.equals("--user")) {
- mUserId = Integer.parseInt(nextArgRequired());
+ mUserId = parseUserArg(nextArgRequired());
} else {
System.err.println("Error: Unknown option: " + opt);
return null;
@@ -392,8 +405,12 @@
private void runStartService() throws Exception {
Intent intent = makeIntent();
+ if (mUserId == UserHandle.USER_ALL) {
+ System.err.println("Error: Can't start activity with user 'all'");
+ return;
+ }
System.out.println("Starting service: " + intent);
- ComponentName cn = mAm.startService(null, intent, intent.getType(), 0);
+ ComponentName cn = mAm.startService(null, intent, intent.getType(), mUserId);
if (cn == null) {
System.err.println("Error: Not found; no service started.");
}
@@ -402,10 +419,15 @@
private void runStart() throws Exception {
Intent intent = makeIntent();
+ if (mUserId == UserHandle.USER_ALL) {
+ System.err.println("Error: Can't start service with user 'all'");
+ return;
+ }
+
String mimeType = intent.getType();
if (mimeType == null && intent.getData() != null
&& "content".equals(intent.getData().getScheme())) {
- mimeType = mAm.getProviderMimeType(intent.getData());
+ mimeType = mAm.getProviderMimeType(intent.getData(), mUserId);
}
do {
@@ -460,11 +482,11 @@
int res;
if (mWaitOption) {
result = mAm.startActivityAndWait(null, intent, mimeType,
- null, null, 0, mStartFlags, mProfileFile, fd, null);
+ null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId);
res = result.result;
} else {
- res = mAm.startActivity(null, intent, mimeType,
- null, null, 0, mStartFlags, mProfileFile, fd, null);
+ res = mAm.startActivityAsUser(null, intent, mimeType,
+ null, null, 0, mStartFlags, mProfileFile, fd, null, mUserId);
}
PrintStream out = mWaitOption ? System.out : System.err;
boolean launched = false;
@@ -573,6 +595,7 @@
boolean wait = false;
boolean rawMode = false;
boolean no_window_animation = false;
+ int userId = 0;
Bundle args = new Bundle();
String argKey = null, argValue = null;
IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
@@ -592,12 +615,19 @@
} else if (opt.equals("--no_window_animation")
|| opt.equals("--no-window-animation")) {
no_window_animation = true;
+ } else if (opt.equals("--user")) {
+ userId = parseUserArg(nextArgRequired());
} else {
System.err.println("Error: Unknown option: " + opt);
return;
}
}
+ if (userId == UserHandle.USER_ALL) {
+ System.err.println("Error: Can't start instrumentation with user 'all'");
+ return;
+ }
+
String cnArg = nextArgRequired();
ComponentName cn = ComponentName.unflattenFromString(cnArg);
if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
@@ -614,7 +644,7 @@
wm.setAnimationScale(1, 0.0f);
}
- if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
+ if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, userId)) {
throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
}
@@ -1338,6 +1368,7 @@
" am kill-all\n" +
" am broadcast <INTENT>\n" +
" am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
+ " [--user <USER_ID> | all | current]\n" +
" [--no-window-animation] <COMPONENT>\n" +
" am profile start <PROCESS> <FILE>\n" +
" am profile stop [<PROCESS>]\n" +
@@ -1384,6 +1415,7 @@
" -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" +
" --no-window-animation: turn off window animations will running.\n" +
"\n" +
"am profile: start and stop profiler on a process.\n" +
@@ -1431,6 +1463,7 @@
" [--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/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 36bf38a..8570f27 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -20,7 +20,6 @@
import android.app.ActivityManagerNative;
import android.content.ComponentName;
-import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ContainerEncryptionParams;
import android.content.pm.FeatureInfo;
@@ -40,12 +39,9 @@
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
-import android.os.Binder;
import android.os.IUserManager;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserManager;
import java.io.File;
import java.lang.reflect.Field;
@@ -74,7 +70,6 @@
private static final String PM_NOT_RUNNING_ERR =
"Error: Could not access the Package Manager. Is the system running?";
- private static final int ROOT_UID = 0;
public static void main(String[] args) {
new Pm().run(args);
@@ -1054,11 +1049,16 @@
}
private void runUninstall() {
- int unInstallFlags = 0;
+ int unInstallFlags = PackageManager.DELETE_ALL_USERS;
- String opt = nextOption();
- if (opt != null && opt.equals("-k")) {
- unInstallFlags = PackageManager.DELETE_KEEP_DATA;
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-k")) {
+ unInstallFlags |= PackageManager.DELETE_KEEP_DATA;
+ } else {
+ System.err.println("Error: Unknown option: " + opt);
+ return;
+ }
}
String pkg = nextArg();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index cd22aad..bb3c56a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1957,4 +1957,21 @@
return false;
}
}
+
+ /**
+ * Return whether the given user is actively running. This means that
+ * the user is in the "started" state, not "stopped" -- it is currently
+ * allowed to run code through scheduled alarms, receiving broadcasts,
+ * etc. A started user may be either the current foreground user or a
+ * background user; the result here does not distinguish between the two.
+ * @param userid the user's id. Zero indicates the default user.
+ * @hide
+ */
+ public boolean isUserRunning(int userid) {
+ try {
+ return ActivityManagerNative.getDefault().isUserRunning(userid);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index eed9254..e5dd7b1 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -177,9 +177,10 @@
? data.readFileDescriptor() : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
+ int userId = data.readInt();
WaitResult result = startActivityAndWait(app, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags,
- profileFile, profileFd, options);
+ profileFile, profileFd, options, userId);
reply.writeNoException();
result.writeToParcel(reply, 0);
return true;
@@ -811,7 +812,8 @@
Bundle arguments = data.readBundle();
IBinder b = data.readStrongBinder();
IInstrumentationWatcher w = IInstrumentationWatcher.Stub.asInterface(b);
- boolean res = startInstrumentation(className, profileFile, fl, arguments, w);
+ int userId = data.readInt();
+ boolean res = startInstrumentation(className, profileFile, fl, arguments, w, userId);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -1323,11 +1325,11 @@
return true;
}
- case KILL_APPLICATION_WITH_UID_TRANSACTION: {
+ case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String pkg = data.readString();
- int uid = data.readInt();
- killApplicationWithUid(pkg, uid);
+ int appid = data.readInt();
+ killApplicationWithAppId(pkg, appid);
reply.writeNoException();
return true;
}
@@ -1424,7 +1426,8 @@
case GET_PROVIDER_MIME_TYPE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
Uri uri = Uri.CREATOR.createFromParcel(data);
- String type = getProviderMimeType(uri);
+ int userId = data.readInt();
+ String type = getProviderMimeType(uri, userId);
reply.writeNoException();
reply.writeString(type);
return true;
@@ -1573,6 +1576,15 @@
return true;
}
+ case IS_USER_RUNNING_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int userid = data.readInt();
+ boolean result = isUserRunning(userid);
+ reply.writeNoException();
+ reply.writeInt(result ? 1 : 0);
+ return true;
+ }
+
case REMOVE_SUB_TASK_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
@@ -1827,7 +1839,7 @@
public WaitResult startActivityAndWait(IApplicationThread caller, Intent intent,
String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int startFlags, String profileFile,
- ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
+ ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -1851,6 +1863,7 @@
} else {
data.writeInt(0);
}
+ data.writeInt(userId);
mRemote.transact(START_ACTIVITY_AND_WAIT_TRANSACTION, data, reply, 0);
reply.readException();
WaitResult result = WaitResult.CREATOR.createFromParcel(reply);
@@ -2719,7 +2732,7 @@
}
public boolean startInstrumentation(ComponentName className, String profileFile,
- int flags, Bundle arguments, IInstrumentationWatcher watcher)
+ int flags, Bundle arguments, IInstrumentationWatcher watcher, int userId)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -2729,6 +2742,7 @@
data.writeInt(flags);
data.writeBundle(arguments);
data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
+ data.writeInt(userId);
mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
@@ -3366,13 +3380,13 @@
data.recycle();
}
- public void killApplicationWithUid(String pkg, int uid) throws RemoteException {
+ public void killApplicationWithAppId(String pkg, int appid) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeString(pkg);
- data.writeInt(uid);
- mRemote.transact(KILL_APPLICATION_WITH_UID_TRANSACTION, data, reply, 0);
+ data.writeInt(appid);
+ mRemote.transact(KILL_APPLICATION_WITH_APPID_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
@@ -3507,12 +3521,12 @@
reply.recycle();
}
- public String getProviderMimeType(Uri uri)
- throws RemoteException {
+ public String getProviderMimeType(Uri uri, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
uri.writeToParcel(data, 0);
+ data.writeInt(userId);
mRemote.transact(GET_PROVIDER_MIME_TYPE_TRANSACTION, data, reply, 0);
reply.readException();
String res = reply.readString();
@@ -3747,6 +3761,19 @@
return userInfo;
}
+ public boolean isUserRunning(int userid) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(userid);
+ mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean result = reply.readInt() != 0;
+ reply.recycle();
+ data.recycle();
+ return result;
+ }
+
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 65ea6a0..3498919 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1428,7 +1428,7 @@
arguments.setAllowFds(false);
}
return ActivityManagerNative.getDefault().startInstrumentation(
- className, profileFile, 0, arguments, null);
+ className, profileFile, 0, arguments, null, UserHandle.myUserId());
} catch (RemoteException e) {
// System has crashed, nothing we can do.
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 7a633ed..9cb3621 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -62,7 +62,7 @@
public WaitResult startActivityAndWait(IApplicationThread caller,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int flags, String profileFile,
- ParcelFileDescriptor profileFd, Bundle options) throws RemoteException;
+ ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
public int startActivityWithConfig(IApplicationThread caller,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int startFlags, Configuration newConfig,
@@ -160,7 +160,7 @@
public void killApplicationProcess(String processName, int uid) throws RemoteException;
public boolean startInstrumentation(ComponentName className, String profileFile,
- int flags, Bundle arguments, IInstrumentationWatcher watcher)
+ int flags, Bundle arguments, IInstrumentationWatcher watcher, int userId)
throws RemoteException;
public void finishInstrumentation(IApplicationThread target,
int resultCode, Bundle results) throws RemoteException;
@@ -275,7 +275,7 @@
public void stopAppSwitches() throws RemoteException;
public void resumeAppSwitches() throws RemoteException;
- public void killApplicationWithUid(String pkg, int uid) throws RemoteException;
+ public void killApplicationWithAppId(String pkg, int appid) throws RemoteException;
public void closeSystemDialogs(String reason) throws RemoteException;
@@ -296,7 +296,7 @@
public void crashApplication(int uid, int initialPid, String packageName,
String message) throws RemoteException;
- public String getProviderMimeType(Uri uri) throws RemoteException;
+ public String getProviderMimeType(Uri uri, int userId) throws RemoteException;
public IBinder newUriPermissionOwner(String name) throws RemoteException;
public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
@@ -328,6 +328,7 @@
public boolean switchUser(int userid) throws RemoteException;
public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
public UserInfo getCurrentUser() throws RemoteException;
+ public boolean isUserRunning(int userid) throws RemoteException;
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException;
@@ -548,7 +549,7 @@
int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
- int KILL_APPLICATION_WITH_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
+ int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
@@ -574,7 +575,7 @@
int CHECK_GRANT_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+118;
int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+119;
int START_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+120;
-
+ int IS_USER_RUNNING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
int ACTIVITY_SLEPT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+122;
int GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+123;
int SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+124;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0a5a26a9..ece8841 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -39,6 +39,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
@@ -230,7 +231,8 @@
}
try {
- String type = ActivityManagerNative.getDefault().getProviderMimeType(url);
+ String type = ActivityManagerNative.getDefault().getProviderMimeType(
+ url, UserHandle.myUserId());
return type;
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1a82d58..a0283d3 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -308,6 +308,13 @@
public static final int FLAG_INSTALLED = 1<<23;
/**
+ * Value for {@link #flags}: true if the application only has its
+ * data installed; the application package itself does not currently
+ * exist on the device.
+ */
+ public static final int FLAG_IS_DATA_ONLY = 1<<24;
+
+ /**
* Value for {@link #flags}: Set to true if the application has been
* installed using the forward lock option.
*
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index ea47e8e..a977e41 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -18,10 +18,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.text.Collator;
-import java.util.Comparator;
/**
* Information you can retrieve about a particular piece of test
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 54cf73a..db2d450 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -4181,22 +4181,22 @@
Intent dock = createHomeDockIntent();
if (dock != null) {
int result = ActivityManagerNative.getDefault()
- .startActivity(null, dock,
+ .startActivityAsUser(null, dock,
dock.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0,
ActivityManager.START_FLAG_ONLY_IF_NEEDED,
- null, null, null);
+ null, null, null, UserHandle.USER_CURRENT);
if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
return false;
}
}
}
int result = ActivityManagerNative.getDefault()
- .startActivity(null, mHomeIntent,
+ .startActivityAsUser(null, mHomeIntent,
mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0,
ActivityManager.START_FLAG_ONLY_IF_NEEDED,
- null, null, null);
+ null, null, null, UserHandle.USER_CURRENT);
if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
return false;
}
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 6a3010b..7144808 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -185,7 +185,7 @@
}
private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
- HashMap map = mServicesByNamePerUser.get(callingUser);
+ HashMap<ComponentName, ServiceRecord> map = mServicesByNamePerUser.get(callingUser);
if (map == null) {
map = new HashMap<ComponentName, ServiceRecord>();
mServicesByNamePerUser.put(callingUser, map);
@@ -195,7 +195,8 @@
private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
int callingUser) {
- HashMap map = mServicesByIntentPerUser.get(callingUser);
+ HashMap<Intent.FilterComparison, ServiceRecord> map
+ = mServicesByIntentPerUser.get(callingUser);
if (map == null) {
map = new HashMap<Intent.FilterComparison, ServiceRecord>();
mServicesByIntentPerUser.put(callingUser, map);
@@ -1514,10 +1515,12 @@
}
}
- boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
+ private boolean collectForceStopServicesLocked(String name, int userId,
+ boolean evenPersistent, boolean doit,
+ HashMap<ComponentName, ServiceRecord> services,
+ ArrayList<ServiceRecord> result) {
boolean didSomething = false;
- ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
- for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
+ for (ServiceRecord service : services.values()) {
if ((name == null || service.packageName.equals(name))
&& (service.app == null || evenPersistent || !service.app.persistent)) {
if (!doit) {
@@ -1530,9 +1533,27 @@
}
service.app = null;
service.isolatedProc = null;
- services.add(service);
+ result.add(service);
}
}
+ return didSomething;
+ }
+
+ boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
+ boolean didSomething = false;
+ ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+ if (userId == UserHandle.USER_ALL) {
+ for (int i=0; i<mServiceMap.mServicesByNamePerUser.size(); i++) {
+ didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent,
+ doit, mServiceMap.mServicesByNamePerUser.valueAt(i), services);
+ if (!doit && didSomething) {
+ return true;
+ }
+ }
+ } else {
+ didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
+ doit, mServiceMap.mServicesByNamePerUser.get(userId), services);
+ }
int N = services.size();
for (int i=0; i<N; i++) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 614b93a..76a4f15a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -116,13 +116,11 @@
import android.provider.Settings;
import android.text.format.Time;
import android.util.EventLog;
-import android.util.LocaleUtil;
import android.util.Log;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -434,6 +432,11 @@
final SparseArray<UserStartedState> mStartedUsers = new SparseArray<UserStartedState>();
/**
+ * LRU list of history of current users. Most recently current is at the end.
+ */
+ final ArrayList<Integer> mUserLru = new ArrayList<Integer>();
+
+ /**
* Packages that the user has asked to have run in screen size
* compatibility mode instead of filling the screen.
*/
@@ -1094,11 +1097,11 @@
} break;
case KILL_APPLICATION_MSG: {
synchronized (ActivityManagerService.this) {
- int uid = msg.arg1;
+ int appid = msg.arg1;
boolean restart = (msg.arg2 == 1);
String pkg = (String) msg.obj;
- forceStopPackageLocked(pkg, uid, restart, false, true, false,
- UserHandle.getUserId(uid));
+ forceStopPackageLocked(pkg, appid, restart, false, true, false,
+ UserHandle.USER_ALL);
}
} break;
case FINALIZE_PENDING_INTENT_MSG: {
@@ -1526,6 +1529,7 @@
// User 0 is the first and only user that runs at boot.
mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));
+ mUserLru.add(Integer.valueOf(0));
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
@@ -2385,8 +2389,10 @@
public final WaitResult startActivityAndWait(IApplicationThread caller,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
- ParcelFileDescriptor profileFd, Bundle options) {
+ ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivityAndWait");
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ false, true, "startActivityAndWait", null);
WaitResult res = new WaitResult();
mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
@@ -3542,16 +3548,15 @@
}
/*
- * The pkg name and uid have to be specified.
- * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
+ * The pkg name and app id have to be specified.
*/
- public void killApplicationWithUid(String pkg, int uid) {
+ public void killApplicationWithAppId(String pkg, int appid) {
if (pkg == null) {
return;
}
// Make sure the uid is valid.
- if (uid < 0) {
- Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
+ if (appid < 0) {
+ Slog.w(TAG, "Invalid appid specified for pkg : " + pkg);
return;
}
int callerUid = Binder.getCallingUid();
@@ -3559,7 +3564,7 @@
if (callerUid == Process.SYSTEM_UID) {
// Post an aysnc message to kill the application
Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
- msg.arg1 = uid;
+ msg.arg1 = appid;
msg.arg2 = 0;
msg.obj = pkg;
mHandler.sendMessage(msg);
@@ -3691,7 +3696,7 @@
MY_PID, Process.SYSTEM_UID, userId);
}
- private final boolean killPackageProcessesLocked(String packageName, int uid,
+ private final boolean killPackageProcessesLocked(String packageName, int appId,
int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
boolean doit, boolean evenPersistent, String reason) {
ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
@@ -3712,32 +3717,41 @@
if (doit) {
procs.add(app);
}
+ continue;
+ }
+
+ // Skip process if it doesn't meet our oom adj requirement.
+ if (app.setAdj < minOomAdj) {
+ continue;
+ }
+
// If no package is specified, we call all processes under the
// give user id.
- } else if (packageName == null) {
- if (app.userId == userId) {
- if (app.setAdj >= minOomAdj) {
- if (!doit) {
- return true;
- }
- app.removed = true;
- procs.add(app);
- }
+ if (packageName == null) {
+ if (app.userId != userId) {
+ continue;
}
- // If uid is specified and the uid and process name match
- // Or, the uid is not specified and the process name matches
- } else if (((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
- || ((app.processName.equals(packageName)
- || app.processName.startsWith(procNamePrefix))
- && uid < 0))) {
- if (app.setAdj >= minOomAdj) {
- if (!doit) {
- return true;
- }
- app.removed = true;
- procs.add(app);
+ // Package has been specified, we want to hit all processes
+ // that match it. We need to qualify this by the processes
+ // that are running under the specified app and user ID.
+ } else {
+ if (UserHandle.getAppId(app.uid) != appId) {
+ continue;
+ }
+ if (userId != UserHandle.USER_ALL && app.userId != userId) {
+ continue;
+ }
+ if (!app.pkgList.contains(packageName)) {
+ continue;
}
}
+
+ // Process has passed all conditions, kill it!
+ if (!doit) {
+ return true;
+ }
+ app.removed = true;
+ procs.add(app);
}
}
@@ -3748,22 +3762,28 @@
return N > 0;
}
- private final boolean forceStopPackageLocked(String name, int uid,
+ private final boolean forceStopPackageLocked(String name, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
boolean evenPersistent, int userId) {
int i;
int N;
- if (uid < 0 && name != null) {
+ if (userId == UserHandle.USER_ALL && name == null) {
+ Slog.w(TAG, "Can't force stop all processes of all users, that is insane!");
+ }
+
+ if (appId < 0 && name != null) {
try {
- uid = AppGlobals.getPackageManager().getPackageUid(name, userId);
+ appId = UserHandle.getAppId(
+ AppGlobals.getPackageManager().getPackageUid(name, 0));
} catch (RemoteException e) {
}
}
if (doit) {
if (name != null) {
- Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
+ Slog.i(TAG, "Force stopping package " + name + " appid=" + appId
+ + " user=" + userId);
} else {
Slog.i(TAG, "Force stopping user " + userId);
}
@@ -3775,8 +3795,14 @@
boolean remove = false;
final int entUid = ba.keyAt(i);
if (name != null) {
- if (entUid == uid) {
- remove = true;
+ if (userId == UserHandle.USER_ALL) {
+ if (UserHandle.getAppId(entUid) == appId) {
+ remove = true;
+ }
+ } else {
+ if (entUid == UserHandle.getUid(userId, appId)) {
+ remove = true;
+ }
}
} else if (UserHandle.getUserId(entUid) == userId) {
remove = true;
@@ -3791,9 +3817,8 @@
}
}
- boolean didSomething = killPackageProcessesLocked(name, uid,
- name == null ? userId : -1 , -100, callerWillRestart, false,
- doit, evenPersistent,
+ boolean didSomething = killPackageProcessesLocked(name, appId, userId,
+ -100, callerWillRestart, false, doit, evenPersistent,
name == null ? ("force stop user " + userId) : ("force stop " + name));
TaskRecord lastTask = null;
@@ -3801,7 +3826,7 @@
ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
final boolean samePackage = r.packageName.equals(name)
|| (name == null && r.userId == userId);
- if (r.userId == userId
+ if ((userId == UserHandle.USER_ALL || r.userId == userId)
&& (samePackage || r.task == lastTask)
&& (r.app == null || evenPersistent || !r.app.persistent)) {
if (!doit) {
@@ -3841,22 +3866,64 @@
}
ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
- for (ContentProviderRecord provider : mProviderMap.getProvidersByClass(userId).values()) {
- if ((name == null || provider.info.packageName.equals(name))
- && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
+ if (mProviderMap.collectForceStopProviders(name, appId, doit, evenPersistent,
+ userId, providers)) {
+ if (!doit) {
+ return true;
+ }
+ didSomething = true;
+ }
+ N = providers.size();
+ for (i=0; i<N; i++) {
+ removeDyingProviderLocked(null, providers.get(i), true);
+ }
+
+ if (mIntentSenderRecords.size() > 0) {
+ Iterator<WeakReference<PendingIntentRecord>> it
+ = mIntentSenderRecords.values().iterator();
+ while (it.hasNext()) {
+ WeakReference<PendingIntentRecord> wpir = it.next();
+ if (wpir == null) {
+ it.remove();
+ continue;
+ }
+ PendingIntentRecord pir = wpir.get();
+ if (pir == null) {
+ it.remove();
+ continue;
+ }
+ if (name == null) {
+ // Stopping user, remove all objects for the user.
+ if (pir.key.userId != userId) {
+ // Not the same user, skip it.
+ continue;
+ }
+ } else {
+ if (UserHandle.getAppId(pir.uid) != appId) {
+ // Different app id, skip it.
+ continue;
+ }
+ if (userId != UserHandle.USER_ALL && pir.key.userId != userId) {
+ // Different user, skip it.
+ continue;
+ }
+ if (!pir.key.packageName.equals(name)) {
+ // Different package, skip it.
+ continue;
+ }
+ }
if (!doit) {
return true;
}
didSomething = true;
- providers.add(provider);
+ it.remove();
+ pir.canceled = true;
+ if (pir.key.activity != null) {
+ pir.key.activity.pendingResults.remove(pir.ref);
+ }
}
}
- N = providers.size();
- for (i=0; i<N; i++) {
- removeDyingProviderLocked(null, providers.get(i), true);
- }
-
if (doit) {
if (purgeCache && name != null) {
AttributeCache ac = AttributeCache.instance();
@@ -6778,10 +6845,11 @@
* Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
* src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
*/
- public String getProviderMimeType(Uri uri) {
+ public String getProviderMimeType(Uri uri, int userId) {
enforceNotIsolatedCaller("getProviderMimeType");
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, true, "getProviderMimeType", null);
final String name = uri.getAuthority();
- final int userId = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
ContentProviderHolder holder = null;
@@ -7134,7 +7202,8 @@
mDebugTransient = !persistent;
if (packageName != null) {
final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(packageName, -1, false, false, true, true, 0);
+ forceStopPackageLocked(packageName, -1, false, false, true, true,
+ UserHandle.USER_ALL);
Binder.restoreCallingIdentity(origId);
}
}
@@ -9129,9 +9198,14 @@
for (int i=0; i<mStartedUsers.size(); i++) {
UserStartedState uss = mStartedUsers.valueAt(i);
pw.print(" User #"); pw.print(uss.mHandle.getIdentifier());
- pw.println(":");
- uss.dump(" ", pw);
+ pw.print(": "); uss.dump("", pw);
}
+ pw.print(" mUserLru: [");
+ for (int i=0; i<mUserLru.size(); i++) {
+ if (i > 0) pw.print(", ");
+ pw.print(mUserLru.get(i));
+ }
+ pw.println("]");
pw.println(" mHomeProcess: " + mHomeProcess);
pw.println(" mPreviousProcess: " + mPreviousProcess);
if (dumpAll) {
@@ -11815,8 +11889,10 @@
public boolean startInstrumentation(ComponentName className,
String profileFile, int flags, Bundle arguments,
- IInstrumentationWatcher watcher) {
+ IInstrumentationWatcher watcher, int userId) {
enforceNotIsolatedCaller("startInstrumentation");
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, true, "startInstrumentation", null);
// Refuse possible leaked file descriptors
if (arguments != null && arguments.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Bundle");
@@ -11828,9 +11904,10 @@
try {
ii = mContext.getPackageManager().getInstrumentationInfo(
className, STOCK_PM_FLAGS);
- ai = mContext.getPackageManager().getApplicationInfo(
- ii.targetPackage, STOCK_PM_FLAGS);
+ ai = AppGlobals.getPackageManager().getApplicationInfo(
+ ii.targetPackage, STOCK_PM_FLAGS, userId);
} catch (PackageManager.NameNotFoundException e) {
+ } catch (RemoteException e) {
}
if (ii == null) {
reportStartInstrumentationFailure(watcher, className,
@@ -11857,7 +11934,6 @@
throw new SecurityException(msg);
}
- int userId = UserHandle.getCallingUserId();
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId);
@@ -13780,6 +13856,9 @@
}
mCurrentUserId = userId;
+ Integer userIdInt = Integer.valueOf(userId);
+ mUserLru.remove(userIdInt);
+ mUserLru.add(userIdInt);
boolean haveActivities = mMainStack.switchUser(userId);
if (!haveActivities) {
startHomeActivityLocked(userId, mStartedUsers.get(userId));
@@ -13928,6 +14007,23 @@
}
}
+ @Override
+ public boolean isUserRunning(int userId) {
+ if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: isUserRunning() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ synchronized (this) {
+ 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;
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 0f72409..c61f13c 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -25,7 +25,6 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Slog;
import java.io.PrintWriter;
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 7a4fef6..2d7167b 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -180,6 +180,49 @@
}
}
+ private boolean collectForceStopProvidersLocked(String name, int appId,
+ boolean doit, boolean evenPersistent, int userId,
+ HashMap<ComponentName, ContentProviderRecord> providers,
+ ArrayList<ContentProviderRecord> result) {
+ boolean didSomething = false;
+ for (ContentProviderRecord provider : providers.values()) {
+ if ((name == null || provider.info.packageName.equals(name))
+ && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
+ if (!doit) {
+ return true;
+ }
+ didSomething = true;
+ result.add(provider);
+ }
+ }
+ return didSomething;
+ }
+
+ boolean collectForceStopProviders(String name, int appId,
+ boolean doit, boolean evenPersistent, int userId,
+ ArrayList<ContentProviderRecord> result) {
+ boolean didSomething = collectForceStopProvidersLocked(name, appId, doit,
+ evenPersistent, userId, mSingletonByClass, result);
+ if (!doit && didSomething) {
+ return true;
+ }
+ if (userId == UserHandle.USER_ALL) {
+ for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
+ if (collectForceStopProvidersLocked(name, appId, doit, evenPersistent,
+ userId, mProvidersByClassPerUser.valueAt(i), result)) {
+ if (!doit) {
+ return true;
+ }
+ didSomething = true;
+ }
+ }
+ } else {
+ didSomething |= collectForceStopProvidersLocked(name, appId, doit, evenPersistent,
+ userId, getProvidersByClass(userId), result);
+ }
+ return didSomething;
+ }
+
private void dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll,
HashMap<ComponentName, ContentProviderRecord> map) {
Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it = map.entrySet().iterator();
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 55da11f..5ddf3c3 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1193,7 +1193,7 @@
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
Slog.i(TAG, "Expecting better updatd system app for " + ps.name
+ "; removing system app");
- removePackageLI(scannedPkg, true);
+ removePackageLI(ps, true);
}
continue;
@@ -1822,7 +1822,7 @@
}
pkg = new PackageParser.Package(packageName);
pkg.applicationInfo.packageName = packageName;
- pkg.applicationInfo.flags = ps.pkgFlags;
+ pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
pkg.applicationInfo.sourceDir = ps.codePathString;
pkg.applicationInfo.dataDir =
@@ -4429,20 +4429,40 @@
return pkg;
}
- private void killApplication(String pkgName, int uid) {
+ private void killApplication(String pkgName, int appId) {
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- am.killApplicationWithUid(pkgName, uid);
+ am.killApplicationWithAppId(pkgName, appId);
} catch (RemoteException e) {
}
}
}
- void removePackageLI(PackageParser.Package pkg, boolean chatty) {
+ void removePackageLI(PackageSetting ps, boolean chatty) {
+ if (DEBUG_INSTALL) {
+ if (chatty)
+ Log.d(TAG, "Removing package " + ps.name);
+ }
+
+ // writer
+ synchronized (mPackages) {
+ mPackages.remove(ps.name);
+ if (ps.codePathString != null) {
+ mAppDirs.remove(ps.codePathString);
+ }
+
+ final PackageParser.Package pkg = ps.pkg;
+ if (pkg != null) {
+ cleanPackageDataStructuresLILPw(pkg, chatty);
+ }
+ }
+ }
+
+ void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
if (DEBUG_INSTALL) {
if (chatty)
Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
@@ -4454,34 +4474,115 @@
if (pkg.mPath != null) {
mAppDirs.remove(pkg.mPath);
}
+ cleanPackageDataStructuresLILPw(pkg, chatty);
+ }
+ }
- int N = pkg.providers.size();
- StringBuilder r = null;
- int i;
- for (i=0; i<N; i++) {
- PackageParser.Provider p = pkg.providers.get(i);
- mProvidersByComponent.remove(new ComponentName(p.info.packageName,
- p.info.name));
- if (p.info.authority == null) {
+ void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
+ int N = pkg.providers.size();
+ StringBuilder r = null;
+ int i;
+ for (i=0; i<N; i++) {
+ PackageParser.Provider p = pkg.providers.get(i);
+ mProvidersByComponent.remove(new ComponentName(p.info.packageName,
+ p.info.name));
+ if (p.info.authority == null) {
- /* The is another ContentProvider with this authority when
- * this app was installed so this authority is null,
- * Ignore it as we don't have to unregister the provider.
- */
- continue;
- }
- String names[] = p.info.authority.split(";");
- for (int j = 0; j < names.length; j++) {
- if (mProviders.get(names[j]) == p) {
- mProviders.remove(names[j]);
- if (DEBUG_REMOVE) {
- if (chatty)
- Log.d(TAG, "Unregistered content provider: " + names[j]
- + ", className = " + p.info.name + ", isSyncable = "
- + p.info.isSyncable);
- }
+ /* There was another ContentProvider with this authority when
+ * this app was installed so this authority is null,
+ * Ignore it as we don't have to unregister the provider.
+ */
+ continue;
+ }
+ String names[] = p.info.authority.split(";");
+ for (int j = 0; j < names.length; j++) {
+ if (mProviders.get(names[j]) == p) {
+ mProviders.remove(names[j]);
+ if (DEBUG_REMOVE) {
+ if (chatty)
+ Log.d(TAG, "Unregistered content provider: " + names[j]
+ + ", className = " + p.info.name + ", isSyncable = "
+ + p.info.isSyncable);
}
}
+ }
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(p.info.name);
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
+ }
+
+ N = pkg.services.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Service s = pkg.services.get(i);
+ mServices.removeService(s);
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(s.info.name);
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
+ }
+
+ N = pkg.receivers.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Activity a = pkg.receivers.get(i);
+ mReceivers.removeActivity(a, "receiver");
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(a.info.name);
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
+ }
+
+ N = pkg.activities.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Activity a = pkg.activities.get(i);
+ mActivities.removeActivity(a, "activity");
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(a.info.name);
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
+ }
+
+ N = pkg.permissions.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Permission p = pkg.permissions.get(i);
+ BasePermission bp = mSettings.mPermissions.get(p.info.name);
+ if (bp == null) {
+ bp = mSettings.mPermissionTrees.get(p.info.name);
+ }
+ if (bp != null && bp.perm == p) {
+ bp.perm = null;
if (chatty) {
if (r == null) {
r = new StringBuilder(256);
@@ -4491,105 +4592,27 @@
r.append(p.info.name);
}
}
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
- }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
+ }
- N = pkg.services.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Service s = pkg.services.get(i);
- mServices.removeService(s);
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(s.info.name);
+ N = pkg.instrumentation.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Instrumentation a = pkg.instrumentation.get(i);
+ mInstrumentation.remove(a.getComponentName());
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
}
+ r.append(a.info.name);
}
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
- }
-
- N = pkg.receivers.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Activity a = pkg.receivers.get(i);
- mReceivers.removeActivity(a, "receiver");
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(a.info.name);
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
- }
-
- N = pkg.activities.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Activity a = pkg.activities.get(i);
- mActivities.removeActivity(a, "activity");
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(a.info.name);
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
- }
-
- N = pkg.permissions.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Permission p = pkg.permissions.get(i);
- BasePermission bp = mSettings.mPermissions.get(p.info.name);
- if (bp == null) {
- bp = mSettings.mPermissionTrees.get(p.info.name);
- }
- if (bp != null && bp.perm == p) {
- bp.perm = null;
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(p.info.name);
- }
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
- }
-
- N = pkg.instrumentation.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Instrumentation a = pkg.instrumentation.get(i);
- mInstrumentation.remove(a.getComponentName());
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(a.info.name);
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
- }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
}
}
@@ -5424,10 +5447,10 @@
public void onEvent(int event, String path) {
String removedPackage = null;
- int removedUid = -1;
+ int removedAppId = -1;
int[] removedUsers = null;
String addedPackage = null;
- int addedUid = -1;
+ int addedAppId = -1;
int[] addedUsers = null;
// TODO post a message to the handler to obtain serial ordering
@@ -5454,11 +5477,12 @@
return;
}
PackageParser.Package p = null;
+ PackageSetting ps = null;
// reader
synchronized (mPackages) {
p = mAppDirs.get(fullPathStr);
if (p != null) {
- PackageSetting ps = mSettings.mPackages.get(p.applicationInfo.packageName);
+ ps = mSettings.mPackages.get(p.applicationInfo.packageName);
if (ps != null) {
removedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
} else {
@@ -5468,10 +5492,10 @@
addedUsers = sUserManager.getUserIds();
}
if ((event&REMOVE_EVENTS) != 0) {
- if (p != null) {
- removePackageLI(p, true);
- removedPackage = p.applicationInfo.packageName;
- removedUid = p.applicationInfo.uid;
+ if (ps != null) {
+ removePackageLI(ps, true);
+ removedPackage = ps.name;
+ removedAppId = ps.appId;
}
}
@@ -5496,7 +5520,7 @@
p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
}
addedPackage = p.applicationInfo.packageName;
- addedUid = p.applicationInfo.uid;
+ addedAppId = UserHandle.getAppId(p.applicationInfo.uid);
}
}
}
@@ -5509,14 +5533,14 @@
if (removedPackage != null) {
Bundle extras = new Bundle(1);
- extras.putInt(Intent.EXTRA_UID, removedUid);
+ extras.putInt(Intent.EXTRA_UID, removedAppId);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
extras, null, null, removedUsers);
}
if (addedPackage != null) {
Bundle extras = new Bundle(1);
- extras.putInt(Intent.EXTRA_UID, addedUid);
+ extras.putInt(Intent.EXTRA_UID, addedAppId);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
extras, null, null, addedUsers);
}
@@ -7527,7 +7551,7 @@
res.removedInfo.uid = oldPkg.applicationInfo.uid;
res.removedInfo.removedPackage = packageName;
// Remove existing system package
- removePackageLI(oldPkg, true);
+ removePackageLI(oldPkgSetting, true);
// writer
synchronized (mPackages) {
if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
@@ -7566,7 +7590,7 @@
// Re installation failed. Restore old information
// Remove new pkg information
if (newPackage != null) {
- removePackageLI(newPackage, true);
+ removeInstalledPackageLI(newPackage, true);
}
// Add back the old system package
scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
@@ -7967,10 +7991,10 @@
* make sure this flag is set for partially installed apps. If not its meaningless to
* delete a partially installed application.
*/
- private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
+ private void removePackageDataLI(PackageSetting ps, PackageRemovedInfo outInfo,
int flags, boolean writeSettings) {
- String packageName = p.packageName;
- removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
+ String packageName = ps.name;
+ removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
// Retrieve object to delete permissions for shared user later on
final PackageSetting deletedPs;
// reader
@@ -8015,38 +8039,32 @@
/*
* Tries to delete system package.
*/
- private boolean deleteSystemPackageLI(PackageParser.Package p,
+ private boolean deleteSystemPackageLI(PackageSetting newPs,
int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
- ApplicationInfo applicationInfo = p.applicationInfo;
- //applicable for non-partially installed applications only
- if (applicationInfo == null) {
- Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
- return false;
- }
- PackageSetting ps = null;
+ PackageSetting disabledPs = null;
// Confirm if the system package has been updated
// An updated system app can be deleted. This will also have to restore
// the system pkg from system partition
// reader
synchronized (mPackages) {
- ps = mSettings.getDisabledSystemPkgLPr(p.packageName);
+ disabledPs = mSettings.getDisabledSystemPkgLPr(newPs.name);
}
- if (ps == null) {
- Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
+ if (disabledPs == null) {
+ Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name);
return false;
} else {
Log.i(TAG, "Deleting system pkg from data partition");
}
// Delete the updated package
outInfo.isRemovedPackageSystemUpdate = true;
- if (ps.versionCode < p.mVersionCode) {
+ if (disabledPs.versionCode < newPs.versionCode) {
// Delete data for downgrades
flags &= ~PackageManager.DELETE_KEEP_DATA;
} else {
// Preserve data by setting flag
flags |= PackageManager.DELETE_KEEP_DATA;
}
- boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
+ boolean ret = deleteInstalledPackageLI(newPs, true, flags, outInfo,
writeSettings);
if (!ret) {
return false;
@@ -8054,17 +8072,18 @@
// writer
synchronized (mPackages) {
// Reinstate the old system package
- mSettings.enableSystemPackageLPw(p.packageName);
+ mSettings.enableSystemPackageLPw(newPs.name);
// Remove any native libraries from the upgraded package.
- NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
+ NativeLibraryHelper.removeNativeBinariesLI(newPs.nativeLibraryPathString);
}
// Install the system package
- PackageParser.Package newPkg = scanPackageLI(ps.codePath,
+ PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
if (newPkg == null) {
- Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
+ Slog.w(TAG, "Failed to restore system package:" + newPs.name
+ + " with error:" + mLastScanError);
return false;
}
// writer
@@ -8079,28 +8098,23 @@
return true;
}
- private boolean deleteInstalledPackageLI(PackageParser.Package p,
+ private boolean deleteInstalledPackageLI(PackageSetting ps,
boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
boolean writeSettings) {
- ApplicationInfo applicationInfo = p.applicationInfo;
- if (applicationInfo == null) {
- Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
- return false;
- }
if (outInfo != null) {
- outInfo.uid = applicationInfo.uid;
+ outInfo.uid = ps.appId;
}
// Delete package data from internal structures and also remove data if flag is set
- removePackageDataLI(p, outInfo, flags, writeSettings);
+ removePackageDataLI(ps, outInfo, flags, writeSettings);
// Delete application code and resources
if (deleteCodeAndResources) {
// TODO can pick up from PackageSettings as well
- int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
- installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
- outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
- applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
+ int installFlags = isExternal(ps) ? PackageManager.INSTALL_EXTERNAL : 0;
+ installFlags |= isForwardLocked(ps) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
+ outInfo.args = createInstallArgs(installFlags, ps.codePathString,
+ ps.resourcePathString, ps.nativeLibraryPathString);
}
return true;
}
@@ -8115,28 +8129,17 @@
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
}
- PackageParser.Package p;
+ PackageSetting ps;
boolean dataOnly = false;
int removeUser = -1;
int appId = -1;
synchronized (mPackages) {
- p = mPackages.get(packageName);
- if (p == null) {
- //this retrieves partially installed apps
- dataOnly = true;
- PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps == null) {
- Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
- return false;
- }
- p = ps.pkg;
- }
- if (p == null) {
+ ps = mSettings.mPackages.get(packageName);
+ if (ps == null) {
Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
return false;
}
- final PackageSetting ps = (PackageSetting)p.mExtras;
- if (!isSystemApp(p) && ps != null && user != null
+ if (!isSystemApp(ps) && user != null
&& user.getIdentifier() != UserHandle.USER_ALL) {
// The caller is asking that the package only be deleted for a single
// user. To do this, we just mark its uninstalled state and delete
@@ -8177,25 +8180,20 @@
if (dataOnly) {
// Delete application data first
- removePackageDataLI(p, outInfo, flags, writeSettings);
+ removePackageDataLI(ps, outInfo, flags, writeSettings);
return true;
}
- // At this point the package should have ApplicationInfo associated with it
- if (p.applicationInfo == null) {
- Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
- return false;
- }
boolean ret = false;
- if (isSystemApp(p)) {
- Log.i(TAG, "Removing system package:"+p.packageName);
+ if (isSystemApp(ps)) {
+ Log.i(TAG, "Removing system package:" + ps.name);
// When an updated system application is deleted we delete the existing resources as well and
// fall back to existing code in system partition
- ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
+ ret = deleteSystemPackageLI(ps, flags, outInfo, writeSettings);
} else {
- Log.i(TAG, "Removing non-system package:"+p.packageName);
+ Log.i(TAG, "Removing non-system package:" + ps.name);
// Kill application pre-emptively especially for apps on sd.
- killApplication(packageName, p.applicationInfo.uid);
- ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
+ killApplication(packageName, ps.appId);
+ ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, outInfo,
writeSettings);
}
return ret;
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 5f10d44..d058a82 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -32,7 +32,6 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
-import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -50,7 +49,6 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
@@ -2603,8 +2601,8 @@
first = false;
pw.print("anyDensity");
}
+ pw.println("]");
}
- pw.println("]");
pw.print(" timeStamp=");
date.setTime(ps.timeStamp);
pw.println(sdf.format(date));