summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroleksii stepanian <aste@google.com>2015-06-19 15:32:41 -0700
committeroleksii stepanian <aste@google.com>2015-06-19 15:32:41 -0700
commit161bd9aae46088cb62e78af428ef9f2b1172c0dc (patch)
treeecf29d41e5ffac8b978a291b11e999a4a6fb12f7
parentb0ff3a6cb37aa45add4b0c5135bd978442fcc441 (diff)
downloadframeworks_base-161bd9aae46088cb62e78af428ef9f2b1172c0dc.zip
frameworks_base-161bd9aae46088cb62e78af428ef9f2b1172c0dc.tar.gz
frameworks_base-161bd9aae46088cb62e78af428ef9f2b1172c0dc.tar.bz2
Fix race condition in PackageManager.
When Google Play installs 2 apps concurrently (e.g. personal and work profile) PackageManager can hit a race condition when connection to media container has not yet been established but the MCS_BOUND event is triggered from MCS_UNBIND. Detailed step by step scenario: 1. package1 comes in 2. INIT_COPY (initiate bind, add pending install) 3. onServiceConnected triggers (MSC_BOUND) 4. MSC_BOUND, process pending package and schedule MSC_UNBIND 5. MSC_UNBIND is triggered once the package is verified 6. service is diconnected 7. package2 comes in 8. INIT_COPY (initiate bind, add pending install) 9. MSC_UNBIND scheduled at step 4 10. MSC_UNBIND sees that there is a pending package, schedules MSC_BIND 11. MSC_BIND arrives before service is connected and we fail. Solution: do not fail if we wait for connection. Bug: 21849046 Change-Id: I39928e1efc81ba64e45c622cc08cb786801d6569
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java22
1 files changed, 14 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 06e27fc..ef833cb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -866,7 +866,7 @@ public class PackageManagerService extends IPackageManager.Stub {
public void onServiceDisconnected(ComponentName name) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
}
- };
+ }
// Recordkeeping of restore-after-install operations that are currently in flight
// between the Package Manager and the Backup Manager
@@ -878,7 +878,8 @@ public class PackageManagerService extends IPackageManager.Stub {
args = _a;
res = _r;
}
- };
+ }
+
final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
@@ -1104,13 +1105,18 @@ public class PackageManagerService extends IPackageManager.Stub {
mContainerService = (IMediaContainerService) msg.obj;
}
if (mContainerService == null) {
- // Something seriously wrong. Bail out
- Slog.e(TAG, "Cannot bind to media container service");
- for (HandlerParams params : mPendingInstalls) {
- // Indicate service bind error
- params.serviceError();
+ if (!mBound) {
+ // Something seriously wrong since we are not bound and we are not
+ // waiting for connection. Bail out.
+ Slog.e(TAG, "Cannot bind to media container service");
+ for (HandlerParams params : mPendingInstalls) {
+ // Indicate service bind error
+ params.serviceError();
+ }
+ mPendingInstalls.clear();
+ } else {
+ Slog.w(TAG, "Waiting to connect to media container service");
}
- mPendingInstalls.clear();
} else if (mPendingInstalls.size() > 0) {
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {