diff options
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 c8f4452..bb108c8 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()); } @@ -1340,6 +1370,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" + @@ -1386,6 +1417,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" + @@ -1433,6 +1465,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)); |