summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-09-06 14:21:19 -0700
committerDianne Hackborn <hackbod@google.com>2012-09-07 13:55:23 -0700
commit5e03e2ca7d25b899b129baad2dd5eca6bf99d88a (patch)
tree10c601a58b0bbeb6902d43e0862c58f3ec121c78
parent970683c5d42a1d8588d656d4e570ce4f0f6e0abc (diff)
downloadframeworks_base-5e03e2ca7d25b899b129baad2dd5eca6bf99d88a.zip
frameworks_base-5e03e2ca7d25b899b129baad2dd5eca6bf99d88a.tar.gz
frameworks_base-5e03e2ca7d25b899b129baad2dd5eca6bf99d88a.tar.bz2
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
-rw-r--r--api/current.txt1
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java47
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java18
-rw-r--r--core/java/android/app/ActivityManager.java17
-rw-r--r--core/java/android/app/ActivityManagerNative.java53
-rw-r--r--core/java/android/app/ContextImpl.java2
-rw-r--r--core/java/android/app/IActivityManager.java13
-rw-r--r--core/java/android/content/ContentResolver.java4
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java7
-rw-r--r--core/java/android/content/pm/InstrumentationInfo.java4
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java8
-rw-r--r--services/java/com/android/server/am/ActiveServices.java33
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java220
-rw-r--r--services/java/com/android/server/am/PendingIntentRecord.java1
-rw-r--r--services/java/com/android/server/am/ProviderMap.java43
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java372
-rw-r--r--services/java/com/android/server/pm/Settings.java4
17 files changed, 543 insertions, 304 deletions
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 @@ package android.content.pm {
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.ParcelFileDescriptor;
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 @@ public class Am {
}
}
+ 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 @@ public class Am {
} 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 @@ public class Am {
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 @@ public class Am {
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 @@ public class Am {
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 @@ public class Am {
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 @@ public class Am {
} 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 @@ public class Am {
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 @@ public class Am {
" 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 @@ public class Am {
" -p <FILE>: write profiling data to <FILE>\n" +
" -w: wait for instrumentation to finish before returning. Required for\n" +
" test runners.\n" +
+ " --user [<USER_ID> | all | current]: Specify user instrumentation runs in.\n" +
" --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 @@ public class Am {
" [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
" [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
" [-n <COMPONENT>] [-f <FLAGS>]\n" +
+ " [--user [<USER_ID> | all | current]\n" +
" [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
" [--debug-log-resolution] [--exclude-stopped-packages]\n" +
" [--include-stopped-packages]\n" +
diff --git a/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 com.android.internal.content.PackageHelper;
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.pm.VerificationParams;
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 @@ public final class Pm {
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 @@ public final class Pm {
}
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 @@ public class ActivityManager {
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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
? 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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
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 @@ class ActivityManagerProxy implements IActivityManager
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 @@ class ActivityManagerProxy implements IActivityManager
} 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 @@ class ActivityManagerProxy implements IActivityManager
}
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 @@ class ActivityManagerProxy implements IActivityManager
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 @@ class ActivityManagerProxy implements IActivityManager
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 @@ class ActivityManagerProxy implements IActivityManager
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 @@ class ActivityManagerProxy implements IActivityManager
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 @@ class ContextImpl extends Context {
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 interface IActivityManager extends IInterface {
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 interface IActivityManager extends IInterface {
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 interface IActivityManager extends IInterface {
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 interface IActivityManager extends IInterface {
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 interface IActivityManager extends IInterface {
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 @@ public interface IActivityManager extends IInterface {
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 @@ public interface IActivityManager extends IInterface {
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 0a5a26a..ece8841 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -39,6 +39,7 @@ import android.os.ParcelFileDescriptor;
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 @@ public abstract class ContentResolver {
}
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 class ApplicationInfo extends PackageItemInfo implements Parcelable {
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 @@ package android.content.pm;
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 @@ public class PhoneWindowManager implements WindowManagerPolicy {
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 @@ public class ActiveServices {
}
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 @@ public class ActiveServices {
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 @@ public class ActiveServices {
}
}
- 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 @@ public class ActiveServices {
}
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..76a4f15 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.os.UserManager;
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
} 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 @@ public final class ActivityManagerService extends ActivityManagerNative
// 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 class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
}
/*
- * 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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- 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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
}
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 (!doit) {
- return true;
- }
- didSomething = true;
- providers.add(provider);
+ 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;
+ it.remove();
+ pir.canceled = true;
+ if (pir.key.activity != null) {
+ pir.key.activity.pendingResults.remove(pir.ref);
+ }
+ }
+ }
+
if (doit) {
if (purgeCache && name != null) {
AttributeCache ac = AttributeCache.instance();
@@ -6778,10 +6845,11 @@ public final class ActivityManagerService extends ActivityManagerNative
* 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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
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 @@ public final class ActivityManagerService extends ActivityManagerNative
}
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 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ @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.Binder;
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 @@ public class ProviderMap {
}
}
+ 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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
}
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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,143 +4474,146 @@ public class PackageManagerService extends IPackageManager.Stub {
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) {
-
- /* 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);
- }
- }
- }
- 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);
+ 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) {
+
+ /* 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;
}
-
- 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(' ');
+ 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);
}
- r.append(s.info.name);
}
}
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
+ 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.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);
+ 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, " Receivers: " + r);
- }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Services: " + 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);
+ 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, " Activities: " + r);
- }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + 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);
- }
+ 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, " Permissions: " + r);
- }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
+ }
- N = pkg.instrumentation.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Instrumentation a = pkg.instrumentation.get(i);
- mInstrumentation.remove(a.getComponentName());
+ 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(a.info.name);
+ r.append(p.info.name);
}
}
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
+ }
+ 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);
+ }
}
private static final boolean isPackageFilename(String name) {
@@ -5424,10 +5447,10 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
// 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 @@ public class PackageManagerService extends IPackageManager.Stub {
* 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 @@ public class PackageManagerService extends IPackageManager.Stub {
/*
* 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 @@ public class PackageManagerService extends IPackageManager.Stub {
// 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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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.XmlPullParser;
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.Binder;
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 @@ final class Settings {
first = false;
pw.print("anyDensity");
}
+ pw.println("]");
}
- pw.println("]");
pw.print(" timeStamp=");
date.setTime(ps.timeStamp);
pw.println(sdf.format(date));