From e1a6299b994bbdb304550e00d5b3b26a064bdf0c Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 17 Sep 2015 18:15:10 -0700 Subject: [PATCH] Relax locking when scanning private volumes. Private volumes with many large apps can take a long time to scan, which currently happens on the main thread with several large locks held, making it likely to trigger the system-wide watchdog. This change relaxes this locking by scanning on the PackageManager worker thread, and by only holding locks when required. In particular, we release the installer lock between each scan to give other apps waiting to dexopt a chance to breathe. Bug: 24172036 Change-Id: Ie28d3ff72d6be28fa2f72c57d5e4146c768df89d --- .../server/pm/PackageManagerService.java | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index af0cec7d21c17..25c4d42103709 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -15664,14 +15664,28 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private void loadPrivatePackages(VolumeInfo vol) { + private void loadPrivatePackages(final VolumeInfo vol) { + mHandler.post(new Runnable() { + @Override + public void run() { + loadPrivatePackagesInner(vol); + } + }); + } + + private void loadPrivatePackagesInner(VolumeInfo vol) { final ArrayList loaded = new ArrayList<>(); final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE; - synchronized (mInstallLock) { + + final VersionInfo ver; + final List packages; synchronized (mPackages) { - final VersionInfo ver = mSettings.findOrCreateVersion(vol.fsUuid); - final List packages = mSettings.getVolumePackagesLPr(vol.fsUuid); - for (PackageSetting ps : packages) { + ver = mSettings.findOrCreateVersion(vol.fsUuid); + packages = mSettings.getVolumePackagesLPr(vol.fsUuid); + } + + for (PackageSetting ps : packages) { + synchronized (mInstallLock) { final PackageParser.Package pkg; try { pkg = scanPackageLI(ps.codePath, parseFlags, SCAN_INITIAL, 0L, null); @@ -15684,7 +15698,9 @@ public class PackageManagerService extends IPackageManager.Stub { deleteCodeCacheDirsLI(ps.volumeUuid, ps.name); } } + } + synchronized (mPackages) { int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to " @@ -15698,13 +15714,21 @@ public class PackageManagerService extends IPackageManager.Stub { mSettings.writeLPr(); } - } if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded); sendResourcesChangedBroadcast(true, false, loaded, null); } - private void unloadPrivatePackages(VolumeInfo vol) { + private void unloadPrivatePackages(final VolumeInfo vol) { + mHandler.post(new Runnable() { + @Override + public void run() { + unloadPrivatePackagesInner(vol); + } + }); + } + + private void unloadPrivatePackagesInner(VolumeInfo vol) { final ArrayList unloaded = new ArrayList<>(); synchronized (mInstallLock) { synchronized (mPackages) {