From 161bd9aae46088cb62e78af428ef9f2b1172c0dc Mon Sep 17 00:00:00 2001 From: oleksii stepanian Date: Fri, 19 Jun 2015 15:32:41 -0700 Subject: [PATCH] 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 --- .../server/pm/PackageManagerService.java | 22 ++++++++++++------- 1 file 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 06e27fc55f314..ef833cb65a321 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 mRunningInstalls = new SparseArray(); 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) {