More multi-user stuff:
- New (hidden) isUserRunning() API.
- Maintain LRU list of visited users.
- New FLAG_IS_DATA_ONLY for ApplicationInfo.
- Clean up pending intent records when force-stopping a user (or package).
(Also fixes bug #6880627: PendingIntent.getService() returns stale
intent of force stopped app)
- Fix force-stopping when installing an app to do the force-stop across
all users for that app.
- When selecting which processes to kill during a force stop, do this
based on the actual packages loaded in the process, not just process
name matching.
- You can now use --user option in am when starting activities, services,
and instrumentation.
- The am --user option accepts "current" and "all" as arguments.
- The pm uninstall command now uninstalls for all users, so it matches
the semantics of the install command.
- PhoneWindowManager now explicitly says to start home in the current
user.
- Activity manager call to retrieve the MIME type from a content provider
now takes a user argument, so it will direct this to the proper user.
- The package manager uninstall paths are now implemented around
PackageSetting, not PackageParser.Package. This allows them to work
even if the application's apk has been removed (in which case it only
exists as a PackageSetting, not the PackageParser.Package parsed from
the apk).
Change-Id: I3522f6fcf32603090bd6e01cc90ce70b6c5aae40
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 6a3010b..7144808 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -185,7 +185,7 @@
}
private HashMap<ComponentName, ServiceRecord> getServices(int callingUser) {
- HashMap map = mServicesByNamePerUser.get(callingUser);
+ HashMap<ComponentName, ServiceRecord> map = mServicesByNamePerUser.get(callingUser);
if (map == null) {
map = new HashMap<ComponentName, ServiceRecord>();
mServicesByNamePerUser.put(callingUser, map);
@@ -195,7 +195,8 @@
private HashMap<Intent.FilterComparison, ServiceRecord> getServicesByIntent(
int callingUser) {
- HashMap map = mServicesByIntentPerUser.get(callingUser);
+ HashMap<Intent.FilterComparison, ServiceRecord> map
+ = mServicesByIntentPerUser.get(callingUser);
if (map == null) {
map = new HashMap<Intent.FilterComparison, ServiceRecord>();
mServicesByIntentPerUser.put(callingUser, map);
@@ -1514,10 +1515,12 @@
}
}
- boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
+ private boolean collectForceStopServicesLocked(String name, int userId,
+ boolean evenPersistent, boolean doit,
+ HashMap<ComponentName, ServiceRecord> services,
+ ArrayList<ServiceRecord> result) {
boolean didSomething = false;
- ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
- for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
+ for (ServiceRecord service : services.values()) {
if ((name == null || service.packageName.equals(name))
&& (service.app == null || evenPersistent || !service.app.persistent)) {
if (!doit) {
@@ -1530,9 +1533,27 @@
}
service.app = null;
service.isolatedProc = null;
- services.add(service);
+ result.add(service);
}
}
+ return didSomething;
+ }
+
+ boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
+ boolean didSomething = false;
+ ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+ if (userId == UserHandle.USER_ALL) {
+ for (int i=0; i<mServiceMap.mServicesByNamePerUser.size(); i++) {
+ didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent,
+ doit, mServiceMap.mServicesByNamePerUser.valueAt(i), services);
+ if (!doit && didSomething) {
+ return true;
+ }
+ }
+ } else {
+ didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
+ doit, mServiceMap.mServicesByNamePerUser.get(userId), services);
+ }
int N = services.size();
for (int i=0; i<N; i++) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 614b93a..76a4f15a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -116,13 +116,11 @@
import android.provider.Settings;
import android.text.format.Time;
import android.util.EventLog;
-import android.util.LocaleUtil;
import android.util.Log;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -434,6 +432,11 @@
final SparseArray<UserStartedState> mStartedUsers = new SparseArray<UserStartedState>();
/**
+ * LRU list of history of current users. Most recently current is at the end.
+ */
+ final ArrayList<Integer> mUserLru = new ArrayList<Integer>();
+
+ /**
* Packages that the user has asked to have run in screen size
* compatibility mode instead of filling the screen.
*/
@@ -1094,11 +1097,11 @@
} break;
case KILL_APPLICATION_MSG: {
synchronized (ActivityManagerService.this) {
- int uid = msg.arg1;
+ int appid = msg.arg1;
boolean restart = (msg.arg2 == 1);
String pkg = (String) msg.obj;
- forceStopPackageLocked(pkg, uid, restart, false, true, false,
- UserHandle.getUserId(uid));
+ forceStopPackageLocked(pkg, appid, restart, false, true, false,
+ UserHandle.USER_ALL);
}
} break;
case FINALIZE_PENDING_INTENT_MSG: {
@@ -1526,6 +1529,7 @@
// User 0 is the first and only user that runs at boot.
mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));
+ mUserLru.add(Integer.valueOf(0));
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
@@ -2385,8 +2389,10 @@
public final WaitResult startActivityAndWait(IApplicationThread caller,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
- ParcelFileDescriptor profileFd, Bundle options) {
+ ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivityAndWait");
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ false, true, "startActivityAndWait", null);
WaitResult res = new WaitResult();
mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
@@ -3542,16 +3548,15 @@
}
/*
- * The pkg name and uid have to be specified.
- * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
+ * The pkg name and app id have to be specified.
*/
- public void killApplicationWithUid(String pkg, int uid) {
+ public void killApplicationWithAppId(String pkg, int appid) {
if (pkg == null) {
return;
}
// Make sure the uid is valid.
- if (uid < 0) {
- Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
+ if (appid < 0) {
+ Slog.w(TAG, "Invalid appid specified for pkg : " + pkg);
return;
}
int callerUid = Binder.getCallingUid();
@@ -3559,7 +3564,7 @@
if (callerUid == Process.SYSTEM_UID) {
// Post an aysnc message to kill the application
Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
- msg.arg1 = uid;
+ msg.arg1 = appid;
msg.arg2 = 0;
msg.obj = pkg;
mHandler.sendMessage(msg);
@@ -3691,7 +3696,7 @@
MY_PID, Process.SYSTEM_UID, userId);
}
- private final boolean killPackageProcessesLocked(String packageName, int uid,
+ private final boolean killPackageProcessesLocked(String packageName, int appId,
int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
boolean doit, boolean evenPersistent, String reason) {
ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
@@ -3712,32 +3717,41 @@
if (doit) {
procs.add(app);
}
+ continue;
+ }
+
+ // Skip process if it doesn't meet our oom adj requirement.
+ if (app.setAdj < minOomAdj) {
+ continue;
+ }
+
// If no package is specified, we call all processes under the
// give user id.
- } else if (packageName == null) {
- if (app.userId == userId) {
- if (app.setAdj >= minOomAdj) {
- if (!doit) {
- return true;
- }
- app.removed = true;
- procs.add(app);
- }
+ if (packageName == null) {
+ if (app.userId != userId) {
+ continue;
}
- // If uid is specified and the uid and process name match
- // Or, the uid is not specified and the process name matches
- } else if (((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
- || ((app.processName.equals(packageName)
- || app.processName.startsWith(procNamePrefix))
- && uid < 0))) {
- if (app.setAdj >= minOomAdj) {
- if (!doit) {
- return true;
- }
- app.removed = true;
- procs.add(app);
+ // Package has been specified, we want to hit all processes
+ // that match it. We need to qualify this by the processes
+ // that are running under the specified app and user ID.
+ } else {
+ if (UserHandle.getAppId(app.uid) != appId) {
+ continue;
+ }
+ if (userId != UserHandle.USER_ALL && app.userId != userId) {
+ continue;
+ }
+ if (!app.pkgList.contains(packageName)) {
+ continue;
}
}
+
+ // Process has passed all conditions, kill it!
+ if (!doit) {
+ return true;
+ }
+ app.removed = true;
+ procs.add(app);
}
}
@@ -3748,22 +3762,28 @@
return N > 0;
}
- private final boolean forceStopPackageLocked(String name, int uid,
+ private final boolean forceStopPackageLocked(String name, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
boolean evenPersistent, int userId) {
int i;
int N;
- if (uid < 0 && name != null) {
+ if (userId == UserHandle.USER_ALL && name == null) {
+ Slog.w(TAG, "Can't force stop all processes of all users, that is insane!");
+ }
+
+ if (appId < 0 && name != null) {
try {
- uid = AppGlobals.getPackageManager().getPackageUid(name, userId);
+ appId = UserHandle.getAppId(
+ AppGlobals.getPackageManager().getPackageUid(name, 0));
} catch (RemoteException e) {
}
}
if (doit) {
if (name != null) {
- Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
+ Slog.i(TAG, "Force stopping package " + name + " appid=" + appId
+ + " user=" + userId);
} else {
Slog.i(TAG, "Force stopping user " + userId);
}
@@ -3775,8 +3795,14 @@
boolean remove = false;
final int entUid = ba.keyAt(i);
if (name != null) {
- if (entUid == uid) {
- remove = true;
+ if (userId == UserHandle.USER_ALL) {
+ if (UserHandle.getAppId(entUid) == appId) {
+ remove = true;
+ }
+ } else {
+ if (entUid == UserHandle.getUid(userId, appId)) {
+ remove = true;
+ }
}
} else if (UserHandle.getUserId(entUid) == userId) {
remove = true;
@@ -3791,9 +3817,8 @@
}
}
- boolean didSomething = killPackageProcessesLocked(name, uid,
- name == null ? userId : -1 , -100, callerWillRestart, false,
- doit, evenPersistent,
+ boolean didSomething = killPackageProcessesLocked(name, appId, userId,
+ -100, callerWillRestart, false, doit, evenPersistent,
name == null ? ("force stop user " + userId) : ("force stop " + name));
TaskRecord lastTask = null;
@@ -3801,7 +3826,7 @@
ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
final boolean samePackage = r.packageName.equals(name)
|| (name == null && r.userId == userId);
- if (r.userId == userId
+ if ((userId == UserHandle.USER_ALL || r.userId == userId)
&& (samePackage || r.task == lastTask)
&& (r.app == null || evenPersistent || !r.app.persistent)) {
if (!doit) {
@@ -3841,22 +3866,64 @@
}
ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
- for (ContentProviderRecord provider : mProviderMap.getProvidersByClass(userId).values()) {
- if ((name == null || provider.info.packageName.equals(name))
- && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
+ if (mProviderMap.collectForceStopProviders(name, appId, doit, evenPersistent,
+ userId, providers)) {
+ if (!doit) {
+ return true;
+ }
+ didSomething = true;
+ }
+ N = providers.size();
+ for (i=0; i<N; i++) {
+ removeDyingProviderLocked(null, providers.get(i), true);
+ }
+
+ if (mIntentSenderRecords.size() > 0) {
+ Iterator<WeakReference<PendingIntentRecord>> it
+ = mIntentSenderRecords.values().iterator();
+ while (it.hasNext()) {
+ WeakReference<PendingIntentRecord> wpir = it.next();
+ if (wpir == null) {
+ it.remove();
+ continue;
+ }
+ PendingIntentRecord pir = wpir.get();
+ if (pir == null) {
+ it.remove();
+ continue;
+ }
+ if (name == null) {
+ // Stopping user, remove all objects for the user.
+ if (pir.key.userId != userId) {
+ // Not the same user, skip it.
+ continue;
+ }
+ } else {
+ if (UserHandle.getAppId(pir.uid) != appId) {
+ // Different app id, skip it.
+ continue;
+ }
+ if (userId != UserHandle.USER_ALL && pir.key.userId != userId) {
+ // Different user, skip it.
+ continue;
+ }
+ if (!pir.key.packageName.equals(name)) {
+ // Different package, skip it.
+ continue;
+ }
+ }
if (!doit) {
return true;
}
didSomething = true;
- providers.add(provider);
+ it.remove();
+ pir.canceled = true;
+ if (pir.key.activity != null) {
+ pir.key.activity.pendingResults.remove(pir.ref);
+ }
}
}
- N = providers.size();
- for (i=0; i<N; i++) {
- removeDyingProviderLocked(null, providers.get(i), true);
- }
-
if (doit) {
if (purgeCache && name != null) {
AttributeCache ac = AttributeCache.instance();
@@ -6778,10 +6845,11 @@
* Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
* src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
*/
- public String getProviderMimeType(Uri uri) {
+ public String getProviderMimeType(Uri uri, int userId) {
enforceNotIsolatedCaller("getProviderMimeType");
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, true, "getProviderMimeType", null);
final String name = uri.getAuthority();
- final int userId = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
ContentProviderHolder holder = null;
@@ -7134,7 +7202,8 @@
mDebugTransient = !persistent;
if (packageName != null) {
final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(packageName, -1, false, false, true, true, 0);
+ forceStopPackageLocked(packageName, -1, false, false, true, true,
+ UserHandle.USER_ALL);
Binder.restoreCallingIdentity(origId);
}
}
@@ -9129,9 +9198,14 @@
for (int i=0; i<mStartedUsers.size(); i++) {
UserStartedState uss = mStartedUsers.valueAt(i);
pw.print(" User #"); pw.print(uss.mHandle.getIdentifier());
- pw.println(":");
- uss.dump(" ", pw);
+ pw.print(": "); uss.dump("", pw);
}
+ pw.print(" mUserLru: [");
+ for (int i=0; i<mUserLru.size(); i++) {
+ if (i > 0) pw.print(", ");
+ pw.print(mUserLru.get(i));
+ }
+ pw.println("]");
pw.println(" mHomeProcess: " + mHomeProcess);
pw.println(" mPreviousProcess: " + mPreviousProcess);
if (dumpAll) {
@@ -11815,8 +11889,10 @@
public boolean startInstrumentation(ComponentName className,
String profileFile, int flags, Bundle arguments,
- IInstrumentationWatcher watcher) {
+ IInstrumentationWatcher watcher, int userId) {
enforceNotIsolatedCaller("startInstrumentation");
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, true, "startInstrumentation", null);
// Refuse possible leaked file descriptors
if (arguments != null && arguments.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Bundle");
@@ -11828,9 +11904,10 @@
try {
ii = mContext.getPackageManager().getInstrumentationInfo(
className, STOCK_PM_FLAGS);
- ai = mContext.getPackageManager().getApplicationInfo(
- ii.targetPackage, STOCK_PM_FLAGS);
+ ai = AppGlobals.getPackageManager().getApplicationInfo(
+ ii.targetPackage, STOCK_PM_FLAGS, userId);
} catch (PackageManager.NameNotFoundException e) {
+ } catch (RemoteException e) {
}
if (ii == null) {
reportStartInstrumentationFailure(watcher, className,
@@ -11857,7 +11934,6 @@
throw new SecurityException(msg);
}
- int userId = UserHandle.getCallingUserId();
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId);
@@ -13780,6 +13856,9 @@
}
mCurrentUserId = userId;
+ Integer userIdInt = Integer.valueOf(userId);
+ mUserLru.remove(userIdInt);
+ mUserLru.add(userIdInt);
boolean haveActivities = mMainStack.switchUser(userId);
if (!haveActivities) {
startHomeActivityLocked(userId, mStartedUsers.get(userId));
@@ -13928,6 +14007,23 @@
}
}
+ @Override
+ public boolean isUserRunning(int userId) {
+ if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: isUserRunning() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ synchronized (this) {
+ UserStartedState state = mStartedUsers.get(userId);
+ return state != null && state.mState != UserStartedState.STATE_STOPPING;
+ }
+ }
+
private boolean userExists(int userId) {
UserInfo user = getUserManager().getUserInfo(userId);
return user != null;
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 0f72409..c61f13c 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -25,7 +25,6 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Slog;
import java.io.PrintWriter;
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 7a4fef6..2d7167b 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -180,6 +180,49 @@
}
}
+ private boolean collectForceStopProvidersLocked(String name, int appId,
+ boolean doit, boolean evenPersistent, int userId,
+ HashMap<ComponentName, ContentProviderRecord> providers,
+ ArrayList<ContentProviderRecord> result) {
+ boolean didSomething = false;
+ for (ContentProviderRecord provider : providers.values()) {
+ if ((name == null || provider.info.packageName.equals(name))
+ && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
+ if (!doit) {
+ return true;
+ }
+ didSomething = true;
+ result.add(provider);
+ }
+ }
+ return didSomething;
+ }
+
+ boolean collectForceStopProviders(String name, int appId,
+ boolean doit, boolean evenPersistent, int userId,
+ ArrayList<ContentProviderRecord> result) {
+ boolean didSomething = collectForceStopProvidersLocked(name, appId, doit,
+ evenPersistent, userId, mSingletonByClass, result);
+ if (!doit && didSomething) {
+ return true;
+ }
+ if (userId == UserHandle.USER_ALL) {
+ for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
+ if (collectForceStopProvidersLocked(name, appId, doit, evenPersistent,
+ userId, mProvidersByClassPerUser.valueAt(i), result)) {
+ if (!doit) {
+ return true;
+ }
+ didSomething = true;
+ }
+ }
+ } else {
+ didSomething |= collectForceStopProvidersLocked(name, appId, doit, evenPersistent,
+ userId, getProvidersByClass(userId), result);
+ }
+ return didSomething;
+ }
+
private void dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll,
HashMap<ComponentName, ContentProviderRecord> map) {
Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it = map.entrySet().iterator();
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 55da11f..5ddf3c3 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1193,7 +1193,7 @@
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
Slog.i(TAG, "Expecting better updatd system app for " + ps.name
+ "; removing system app");
- removePackageLI(scannedPkg, true);
+ removePackageLI(ps, true);
}
continue;
@@ -1822,7 +1822,7 @@
}
pkg = new PackageParser.Package(packageName);
pkg.applicationInfo.packageName = packageName;
- pkg.applicationInfo.flags = ps.pkgFlags;
+ pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
pkg.applicationInfo.sourceDir = ps.codePathString;
pkg.applicationInfo.dataDir =
@@ -4429,20 +4429,40 @@
return pkg;
}
- private void killApplication(String pkgName, int uid) {
+ private void killApplication(String pkgName, int appId) {
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- am.killApplicationWithUid(pkgName, uid);
+ am.killApplicationWithAppId(pkgName, appId);
} catch (RemoteException e) {
}
}
}
- void removePackageLI(PackageParser.Package pkg, boolean chatty) {
+ void removePackageLI(PackageSetting ps, boolean chatty) {
+ if (DEBUG_INSTALL) {
+ if (chatty)
+ Log.d(TAG, "Removing package " + ps.name);
+ }
+
+ // writer
+ synchronized (mPackages) {
+ mPackages.remove(ps.name);
+ if (ps.codePathString != null) {
+ mAppDirs.remove(ps.codePathString);
+ }
+
+ final PackageParser.Package pkg = ps.pkg;
+ if (pkg != null) {
+ cleanPackageDataStructuresLILPw(pkg, chatty);
+ }
+ }
+ }
+
+ void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
if (DEBUG_INSTALL) {
if (chatty)
Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
@@ -4454,34 +4474,115 @@
if (pkg.mPath != null) {
mAppDirs.remove(pkg.mPath);
}
+ cleanPackageDataStructuresLILPw(pkg, chatty);
+ }
+ }
- int N = pkg.providers.size();
- StringBuilder r = null;
- int i;
- for (i=0; i<N; i++) {
- PackageParser.Provider p = pkg.providers.get(i);
- mProvidersByComponent.remove(new ComponentName(p.info.packageName,
- p.info.name));
- if (p.info.authority == null) {
+ void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
+ int N = pkg.providers.size();
+ StringBuilder r = null;
+ int i;
+ for (i=0; i<N; i++) {
+ PackageParser.Provider p = pkg.providers.get(i);
+ mProvidersByComponent.remove(new ComponentName(p.info.packageName,
+ p.info.name));
+ if (p.info.authority == null) {
- /* The is another ContentProvider with this authority when
- * this app was installed so this authority is null,
- * Ignore it as we don't have to unregister the provider.
- */
- continue;
- }
- String names[] = p.info.authority.split(";");
- for (int j = 0; j < names.length; j++) {
- if (mProviders.get(names[j]) == p) {
- mProviders.remove(names[j]);
- if (DEBUG_REMOVE) {
- if (chatty)
- Log.d(TAG, "Unregistered content provider: " + names[j]
- + ", className = " + p.info.name + ", isSyncable = "
- + p.info.isSyncable);
- }
+ /* There was another ContentProvider with this authority when
+ * this app was installed so this authority is null,
+ * Ignore it as we don't have to unregister the provider.
+ */
+ continue;
+ }
+ String names[] = p.info.authority.split(";");
+ for (int j = 0; j < names.length; j++) {
+ if (mProviders.get(names[j]) == p) {
+ mProviders.remove(names[j]);
+ if (DEBUG_REMOVE) {
+ if (chatty)
+ Log.d(TAG, "Unregistered content provider: " + names[j]
+ + ", className = " + p.info.name + ", isSyncable = "
+ + p.info.isSyncable);
}
}
+ }
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(p.info.name);
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
+ }
+
+ N = pkg.services.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Service s = pkg.services.get(i);
+ mServices.removeService(s);
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(s.info.name);
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
+ }
+
+ N = pkg.receivers.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Activity a = pkg.receivers.get(i);
+ mReceivers.removeActivity(a, "receiver");
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(a.info.name);
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
+ }
+
+ N = pkg.activities.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Activity a = pkg.activities.get(i);
+ mActivities.removeActivity(a, "activity");
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(a.info.name);
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
+ }
+
+ N = pkg.permissions.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Permission p = pkg.permissions.get(i);
+ BasePermission bp = mSettings.mPermissions.get(p.info.name);
+ if (bp == null) {
+ bp = mSettings.mPermissionTrees.get(p.info.name);
+ }
+ if (bp != null && bp.perm == p) {
+ bp.perm = null;
if (chatty) {
if (r == null) {
r = new StringBuilder(256);
@@ -4491,105 +4592,27 @@
r.append(p.info.name);
}
}
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
- }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
+ }
- N = pkg.services.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Service s = pkg.services.get(i);
- mServices.removeService(s);
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(s.info.name);
+ N = pkg.instrumentation.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Instrumentation a = pkg.instrumentation.get(i);
+ mInstrumentation.remove(a.getComponentName());
+ if (chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
}
+ r.append(a.info.name);
}
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
- }
-
- N = pkg.receivers.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Activity a = pkg.receivers.get(i);
- mReceivers.removeActivity(a, "receiver");
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(a.info.name);
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
- }
-
- N = pkg.activities.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Activity a = pkg.activities.get(i);
- mActivities.removeActivity(a, "activity");
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(a.info.name);
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
- }
-
- N = pkg.permissions.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Permission p = pkg.permissions.get(i);
- BasePermission bp = mSettings.mPermissions.get(p.info.name);
- if (bp == null) {
- bp = mSettings.mPermissionTrees.get(p.info.name);
- }
- if (bp != null && bp.perm == p) {
- bp.perm = null;
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(p.info.name);
- }
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
- }
-
- N = pkg.instrumentation.size();
- r = null;
- for (i=0; i<N; i++) {
- PackageParser.Instrumentation a = pkg.instrumentation.get(i);
- mInstrumentation.remove(a.getComponentName());
- if (chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(a.info.name);
- }
- }
- if (r != null) {
- if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
- }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
}
}
@@ -5424,10 +5447,10 @@
public void onEvent(int event, String path) {
String removedPackage = null;
- int removedUid = -1;
+ int removedAppId = -1;
int[] removedUsers = null;
String addedPackage = null;
- int addedUid = -1;
+ int addedAppId = -1;
int[] addedUsers = null;
// TODO post a message to the handler to obtain serial ordering
@@ -5454,11 +5477,12 @@
return;
}
PackageParser.Package p = null;
+ PackageSetting ps = null;
// reader
synchronized (mPackages) {
p = mAppDirs.get(fullPathStr);
if (p != null) {
- PackageSetting ps = mSettings.mPackages.get(p.applicationInfo.packageName);
+ ps = mSettings.mPackages.get(p.applicationInfo.packageName);
if (ps != null) {
removedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
} else {
@@ -5468,10 +5492,10 @@
addedUsers = sUserManager.getUserIds();
}
if ((event&REMOVE_EVENTS) != 0) {
- if (p != null) {
- removePackageLI(p, true);
- removedPackage = p.applicationInfo.packageName;
- removedUid = p.applicationInfo.uid;
+ if (ps != null) {
+ removePackageLI(ps, true);
+ removedPackage = ps.name;
+ removedAppId = ps.appId;
}
}
@@ -5496,7 +5520,7 @@
p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
}
addedPackage = p.applicationInfo.packageName;
- addedUid = p.applicationInfo.uid;
+ addedAppId = UserHandle.getAppId(p.applicationInfo.uid);
}
}
}
@@ -5509,14 +5533,14 @@
if (removedPackage != null) {
Bundle extras = new Bundle(1);
- extras.putInt(Intent.EXTRA_UID, removedUid);
+ extras.putInt(Intent.EXTRA_UID, removedAppId);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
extras, null, null, removedUsers);
}
if (addedPackage != null) {
Bundle extras = new Bundle(1);
- extras.putInt(Intent.EXTRA_UID, addedUid);
+ extras.putInt(Intent.EXTRA_UID, addedAppId);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
extras, null, null, addedUsers);
}
@@ -7527,7 +7551,7 @@
res.removedInfo.uid = oldPkg.applicationInfo.uid;
res.removedInfo.removedPackage = packageName;
// Remove existing system package
- removePackageLI(oldPkg, true);
+ removePackageLI(oldPkgSetting, true);
// writer
synchronized (mPackages) {
if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
@@ -7566,7 +7590,7 @@
// Re installation failed. Restore old information
// Remove new pkg information
if (newPackage != null) {
- removePackageLI(newPackage, true);
+ removeInstalledPackageLI(newPackage, true);
}
// Add back the old system package
scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
@@ -7967,10 +7991,10 @@
* make sure this flag is set for partially installed apps. If not its meaningless to
* delete a partially installed application.
*/
- private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
+ private void removePackageDataLI(PackageSetting ps, PackageRemovedInfo outInfo,
int flags, boolean writeSettings) {
- String packageName = p.packageName;
- removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
+ String packageName = ps.name;
+ removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
// Retrieve object to delete permissions for shared user later on
final PackageSetting deletedPs;
// reader
@@ -8015,38 +8039,32 @@
/*
* Tries to delete system package.
*/
- private boolean deleteSystemPackageLI(PackageParser.Package p,
+ private boolean deleteSystemPackageLI(PackageSetting newPs,
int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
- ApplicationInfo applicationInfo = p.applicationInfo;
- //applicable for non-partially installed applications only
- if (applicationInfo == null) {
- Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
- return false;
- }
- PackageSetting ps = null;
+ PackageSetting disabledPs = null;
// Confirm if the system package has been updated
// An updated system app can be deleted. This will also have to restore
// the system pkg from system partition
// reader
synchronized (mPackages) {
- ps = mSettings.getDisabledSystemPkgLPr(p.packageName);
+ disabledPs = mSettings.getDisabledSystemPkgLPr(newPs.name);
}
- if (ps == null) {
- Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
+ if (disabledPs == null) {
+ Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name);
return false;
} else {
Log.i(TAG, "Deleting system pkg from data partition");
}
// Delete the updated package
outInfo.isRemovedPackageSystemUpdate = true;
- if (ps.versionCode < p.mVersionCode) {
+ if (disabledPs.versionCode < newPs.versionCode) {
// Delete data for downgrades
flags &= ~PackageManager.DELETE_KEEP_DATA;
} else {
// Preserve data by setting flag
flags |= PackageManager.DELETE_KEEP_DATA;
}
- boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
+ boolean ret = deleteInstalledPackageLI(newPs, true, flags, outInfo,
writeSettings);
if (!ret) {
return false;
@@ -8054,17 +8072,18 @@
// writer
synchronized (mPackages) {
// Reinstate the old system package
- mSettings.enableSystemPackageLPw(p.packageName);
+ mSettings.enableSystemPackageLPw(newPs.name);
// Remove any native libraries from the upgraded package.
- NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
+ NativeLibraryHelper.removeNativeBinariesLI(newPs.nativeLibraryPathString);
}
// Install the system package
- PackageParser.Package newPkg = scanPackageLI(ps.codePath,
+ PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
if (newPkg == null) {
- Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
+ Slog.w(TAG, "Failed to restore system package:" + newPs.name
+ + " with error:" + mLastScanError);
return false;
}
// writer
@@ -8079,28 +8098,23 @@
return true;
}
- private boolean deleteInstalledPackageLI(PackageParser.Package p,
+ private boolean deleteInstalledPackageLI(PackageSetting ps,
boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
boolean writeSettings) {
- ApplicationInfo applicationInfo = p.applicationInfo;
- if (applicationInfo == null) {
- Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
- return false;
- }
if (outInfo != null) {
- outInfo.uid = applicationInfo.uid;
+ outInfo.uid = ps.appId;
}
// Delete package data from internal structures and also remove data if flag is set
- removePackageDataLI(p, outInfo, flags, writeSettings);
+ removePackageDataLI(ps, outInfo, flags, writeSettings);
// Delete application code and resources
if (deleteCodeAndResources) {
// TODO can pick up from PackageSettings as well
- int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
- installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
- outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
- applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
+ int installFlags = isExternal(ps) ? PackageManager.INSTALL_EXTERNAL : 0;
+ installFlags |= isForwardLocked(ps) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
+ outInfo.args = createInstallArgs(installFlags, ps.codePathString,
+ ps.resourcePathString, ps.nativeLibraryPathString);
}
return true;
}
@@ -8115,28 +8129,17 @@
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
}
- PackageParser.Package p;
+ PackageSetting ps;
boolean dataOnly = false;
int removeUser = -1;
int appId = -1;
synchronized (mPackages) {
- p = mPackages.get(packageName);
- if (p == null) {
- //this retrieves partially installed apps
- dataOnly = true;
- PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps == null) {
- Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
- return false;
- }
- p = ps.pkg;
- }
- if (p == null) {
+ ps = mSettings.mPackages.get(packageName);
+ if (ps == null) {
Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
return false;
}
- final PackageSetting ps = (PackageSetting)p.mExtras;
- if (!isSystemApp(p) && ps != null && user != null
+ if (!isSystemApp(ps) && user != null
&& user.getIdentifier() != UserHandle.USER_ALL) {
// The caller is asking that the package only be deleted for a single
// user. To do this, we just mark its uninstalled state and delete
@@ -8177,25 +8180,20 @@
if (dataOnly) {
// Delete application data first
- removePackageDataLI(p, outInfo, flags, writeSettings);
+ removePackageDataLI(ps, outInfo, flags, writeSettings);
return true;
}
- // At this point the package should have ApplicationInfo associated with it
- if (p.applicationInfo == null) {
- Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
- return false;
- }
boolean ret = false;
- if (isSystemApp(p)) {
- Log.i(TAG, "Removing system package:"+p.packageName);
+ if (isSystemApp(ps)) {
+ Log.i(TAG, "Removing system package:" + ps.name);
// When an updated system application is deleted we delete the existing resources as well and
// fall back to existing code in system partition
- ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
+ ret = deleteSystemPackageLI(ps, flags, outInfo, writeSettings);
} else {
- Log.i(TAG, "Removing non-system package:"+p.packageName);
+ Log.i(TAG, "Removing non-system package:" + ps.name);
// Kill application pre-emptively especially for apps on sd.
- killApplication(packageName, p.applicationInfo.uid);
- ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
+ killApplication(packageName, ps.appId);
+ ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, outInfo,
writeSettings);
}
return ret;
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 5f10d44..d058a82 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -32,7 +32,6 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
-import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -50,7 +49,6 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
@@ -2603,8 +2601,8 @@
first = false;
pw.print("anyDensity");
}
+ pw.println("]");
}
- pw.println("]");
pw.print(" timeStamp=");
date.setTime(ps.timeStamp);
pw.println(sdf.format(date));