Always bind to DefaultContainerService as OWNER.
When PackageManagerService deals with external storage, always bind
to DefaultContainerService as USER_OWNER. This avoids binding to a
stopped user, which would fail.
Bug: 7203111
Change-Id: I8e303c7558e8b5cbe4fea0acc9a472b598df0caa
diff --git a/core/java/android/content/pm/PackageCleanItem.java b/core/java/android/content/pm/PackageCleanItem.java
index eea3b9c..b1896aa 100644
--- a/core/java/android/content/pm/PackageCleanItem.java
+++ b/core/java/android/content/pm/PackageCleanItem.java
@@ -21,10 +21,12 @@
/** @hide */
public class PackageCleanItem {
+ public final int userId;
public final String packageName;
public final boolean andCode;
- public PackageCleanItem(String packageName, boolean andCode) {
+ public PackageCleanItem(int userId, String packageName, boolean andCode) {
+ this.userId = userId;
this.packageName = packageName;
this.andCode = andCode;
}
@@ -37,7 +39,8 @@
try {
if (obj != null) {
PackageCleanItem other = (PackageCleanItem)obj;
- return packageName.equals(other.packageName) && andCode == other.andCode;
+ return userId == other.userId && packageName.equals(other.packageName)
+ && andCode == other.andCode;
}
} catch (ClassCastException e) {
}
@@ -47,6 +50,7 @@
@Override
public int hashCode() {
int result = 17;
+ result = 31 * result + userId;
result = 31 * result + packageName.hashCode();
result = 31 * result + (andCode ? 1 : 0);
return result;
@@ -57,6 +61,7 @@
}
public void writeToParcel(Parcel dest, int parcelableFlags) {
+ dest.writeInt(userId);
dest.writeString(packageName);
dest.writeInt(andCode ? 1 : 0);
}
@@ -73,6 +78,7 @@
};
private PackageCleanItem(Parcel source) {
+ userId = source.readInt();
packageName = source.readString();
andCode = source.readInt() != 0;
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index b36bd55..24a9d71 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -35,6 +35,7 @@
import android.content.res.ObbScanner;
import android.net.Uri;
import android.os.Environment;
+import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -268,15 +269,16 @@
@Override
protected void onHandleIntent(Intent intent) {
if (PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE.equals(intent.getAction())) {
- IPackageManager pm = IPackageManager.Stub.asInterface(
+ final IPackageManager pm = IPackageManager.Stub.asInterface(
ServiceManager.getService("package"));
- PackageCleanItem pkg = null;
+ PackageCleanItem item = null;
try {
- while ((pkg=pm.nextPackageToClean(pkg)) != null) {
- eraseFiles(Environment.getExternalStorageAppDataDirectory(pkg.packageName));
- eraseFiles(Environment.getExternalStorageAppMediaDirectory(pkg.packageName));
- if (pkg.andCode) {
- eraseFiles(Environment.getExternalStorageAppObbDirectory(pkg.packageName));
+ while ((item = pm.nextPackageToClean(item)) != null) {
+ final UserEnvironment userEnv = new UserEnvironment(item.userId);
+ eraseFiles(userEnv.getExternalStorageAppDataDirectory(item.packageName));
+ eraseFiles(userEnv.getExternalStorageAppMediaDirectory(item.packageName));
+ if (item.andCode) {
+ eraseFiles(userEnv.getExternalStorageAppObbDirectory(item.packageName));
}
}
} catch (RemoteException e) {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 4b4febd..4800e7db 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -413,7 +413,6 @@
// package uri's from external media onto secure containers
// or internal storage.
private IMediaContainerService mContainerService = null;
- private int mContainerServiceUserId;
static final int SEND_PENDING_BROADCAST = 1;
static final int MCS_BOUND = 3;
@@ -482,15 +481,8 @@
" DefaultContainerService");
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
- mContainerServiceUserId = 0;
- if (mPendingInstalls.size() > 0) {
- mContainerServiceUserId = mPendingInstalls.get(0).getUser().getIdentifier();
- if (mContainerServiceUserId == UserHandle.USER_ALL) {
- mContainerServiceUserId = 0;
- }
- }
if (mContext.bindService(service, mDefContainerConn,
- Context.BIND_AUTO_CREATE, mContainerServiceUserId)) {
+ Context.BIND_AUTO_CREATE, UserHandle.USER_OWNER)) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mBound = true;
return true;
@@ -567,15 +559,6 @@
} else if (mPendingInstalls.size() > 0) {
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
- // Check if we're connected to the correct service, if it's an install
- // request.
- final int installFor = params.getUser().getIdentifier();
- if (installFor != mContainerServiceUserId
- && (installFor == UserHandle.USER_ALL
- && mContainerServiceUserId != 0)) {
- mHandler.sendEmptyMessage(MCS_RECONNECT);
- return;
- }
if (params.startCopy()) {
// We are done... look for more work or to
// go idle.
@@ -693,20 +676,23 @@
}
case START_CLEANING_PACKAGE: {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
- PackageCleanItem item = new PackageCleanItem((String)msg.obj,
- msg.arg2 != 0);
+ final String packageName = (String)msg.obj;
+ final int userId = msg.arg1;
+ final boolean andCode = msg.arg2 != 0;
synchronized (mPackages) {
- if (msg.arg1 == UserHandle.USER_ALL) {
+ if (userId == UserHandle.USER_ALL) {
int[] users = sUserManager.getUserIds();
for (int user : users) {
- mSettings.addPackageToCleanLPw(user, item);
+ mSettings.addPackageToCleanLPw(
+ new PackageCleanItem(user, packageName, andCode));
}
} else {
- mSettings.addPackageToCleanLPw(msg.arg1, item);
+ mSettings.addPackageToCleanLPw(
+ new PackageCleanItem(userId, packageName, andCode));
}
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- startCleaningPackages(-1);
+ startCleaningPackages();
} break;
case POST_INSTALL: {
if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
@@ -4193,10 +4179,14 @@
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
// Make sure we don't accidentally delete its data.
- for (int i=0; i<mSettings.mPackagesToBeCleaned.size(); i++) {
- mSettings.mPackagesToBeCleaned.valueAt(i).remove(pkgName);
+ final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
+ while (iter.hasNext()) {
+ PackageCleanItem item = iter.next();
+ if (pkgName.equals(item.packageName)) {
+ iter.remove();
+ }
}
-
+
// Take care of first install / last update times.
if (currentTime != 0) {
if (pkgSetting.firstInstallTime == 0) {
@@ -5443,7 +5433,6 @@
public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
// writer
- final int userId = UserHandle.getCallingUserId();
synchronized (mPackages) {
if (!isExternalMediaAvailable()) {
// If the external storage is no longer mounted at this point,
@@ -5451,23 +5440,13 @@
// packages files and can not delete any more. Bail.
return null;
}
- ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned.get(userId);
- if (pkgs != null) {
- if (lastPackage != null) {
- pkgs.remove(lastPackage);
- }
- if (pkgs.size() > 0) {
- return pkgs.get(0);
- }
+ final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
+ if (lastPackage != null) {
+ pkgs.remove(lastPackage);
}
- mSettings.mPackagesToBeCleaned.remove(userId);
- }
- // Move on to the next user to clean.
- long ident = Binder.clearCallingIdentity();
- try {
- startCleaningPackages(userId);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ if (pkgs.size() > 0) {
+ return pkgs.get(0);
+ }
}
return null;
}
@@ -5483,34 +5462,22 @@
userId, andCode ? 1 : 0, packageName));
}
- void startCleaningPackages(int lastUser) {
+ void startCleaningPackages() {
// reader
- int nextUser = -1;
synchronized (mPackages) {
if (!isExternalMediaAvailable()) {
return;
}
- final int N = mSettings.mPackagesToBeCleaned.size();
- if (N <= 0) {
+ if (mSettings.mPackagesToBeCleaned.isEmpty()) {
return;
}
- for (int i=0; i<N; i++) {
- int user = mSettings.mPackagesToBeCleaned.keyAt(i);
- if (user > lastUser) {
- nextUser = user;
- break;
- }
- }
- if (nextUser < 0) {
- nextUser = mSettings.mPackagesToBeCleaned.keyAt(0);
- }
}
Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- am.startService(null, intent, null, nextUser);
+ am.startService(null, intent, null, UserHandle.USER_OWNER);
} catch (RemoteException e) {
}
}
@@ -8399,10 +8366,11 @@
} else {
users = new int[] { userId };
}
- for (int curUser : users) {
- ClearStorageConnection conn = new ClearStorageConnection();
- if (mContext.bindService(containerIntent, conn, Context.BIND_AUTO_CREATE, curUser)) {
- try {
+ final ClearStorageConnection conn = new ClearStorageConnection();
+ if (mContext.bindService(
+ containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.USER_OWNER)) {
+ try {
+ for (int curUser : users) {
long timeout = SystemClock.uptimeMillis() + 5000;
synchronized (conn) {
long now = SystemClock.uptimeMillis();
@@ -8438,9 +8406,9 @@
} catch (RemoteException e) {
}
}
- } finally {
- mContext.unbindService(conn);
}
+ } finally {
+ mContext.unbindService(conn);
}
}
}
@@ -9596,7 +9564,7 @@
if (DEBUG_SD_INSTALL)
Log.i(TAG, "Loading packages");
loadMediaPackages(processCids, uidArr, removeCids);
- startCleaningPackages(-1);
+ startCleaningPackages();
} else {
if (DEBUG_SD_INSTALL)
Log.i(TAG, "Unloading packages");
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 23e54678..2fb853a 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -159,8 +159,7 @@
// Packages that have been uninstalled and still need their external
// storage data deleted.
- final SparseArray<ArrayList<PackageCleanItem>> mPackagesToBeCleaned
- = new SparseArray<ArrayList<PackageCleanItem>>();
+ final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>();
// Packages that have been renamed since they were first installed.
// Keys are the new names of the packages, values are the original
@@ -1257,18 +1256,13 @@
}
if (mPackagesToBeCleaned.size() > 0) {
- for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
- final int userId = mPackagesToBeCleaned.keyAt(i);
- final String userStr = Integer.toString(userId);
- final ArrayList<PackageCleanItem> pkgs = mPackagesToBeCleaned.valueAt(i);
- for (int j=0; j<pkgs.size(); j++) {
- serializer.startTag(null, "cleaning-package");
- PackageCleanItem item = pkgs.get(j);
- serializer.attribute(null, ATTR_NAME, item.packageName);
- serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
- serializer.attribute(null, ATTR_USER, userStr);
- serializer.endTag(null, "cleaning-package");
- }
+ for (PackageCleanItem item : mPackagesToBeCleaned) {
+ final String userStr = Integer.toString(item.userId);
+ serializer.startTag(null, "cleaning-package");
+ serializer.attribute(null, ATTR_NAME, item.packageName);
+ serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
+ serializer.attribute(null, ATTR_USER, userStr);
+ serializer.endTag(null, "cleaning-package");
}
}
@@ -1524,14 +1518,9 @@
return ret;
}
- void addPackageToCleanLPw(int userId, PackageCleanItem pkg) {
- ArrayList<PackageCleanItem> pkgs = mPackagesToBeCleaned.get(userId);
- if (pkgs == null) {
- pkgs = new ArrayList<PackageCleanItem>();
- mPackagesToBeCleaned.put(userId, pkgs);
- }
- if (!pkgs.contains(pkg)) {
- pkgs.add(pkg);
+ void addPackageToCleanLPw(PackageCleanItem pkg) {
+ if (!mPackagesToBeCleaned.contains(pkg)) {
+ mPackagesToBeCleaned.add(pkg);
}
}
@@ -1615,18 +1604,18 @@
String userStr = parser.getAttributeValue(null, ATTR_USER);
String codeStr = parser.getAttributeValue(null, ATTR_CODE);
if (name != null) {
- int user = 0;
+ int userId = 0;
boolean andCode = true;
try {
if (userStr != null) {
- user = Integer.parseInt(userStr);
+ userId = Integer.parseInt(userStr);
}
} catch (NumberFormatException e) {
}
if (codeStr != null) {
andCode = Boolean.parseBoolean(codeStr);
}
- addPackageToCleanLPw(user, new PackageCleanItem(name, andCode));
+ addPackageToCleanLPw(new PackageCleanItem(userId, name, andCode));
}
} else if (tagName.equals("renamed-package")) {
String nname = parser.getAttributeValue(null, "new");