From fcd672fca3e48cc5ce1e82aacec26ac391cedd01 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Mon, 23 Jan 2017 23:34:25 -0800 Subject: Notify DexManager about new package installs This will update the internal cache so that the secondary dex files of the new package can be found when loaded. Test: runtest -x .../DexManagerTests.java Bug: 32871170 (cherry picked from commit 0d4b8f8b0c963d9a1f5cb6aff11a11195a3df225) Change-Id: I34008f6d262f19e88a346a36b83e4093b4129105 Merged-In: I0cb7158af249feeb01cf578a7544dda978eede9d --- .../android/server/pm/PackageManagerService.java | 12 +++++++ .../java/com/android/server/pm/dex/DexManager.java | 27 ++++++++++----- .../com/android/server/pm/dex/DexManagerTests.java | 40 ++++++++++++++++++++++ 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ca0f85d51f3e..b9e8582b0052 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1787,6 +1787,18 @@ public class PackageManagerService extends IPackageManager.Stub { res.removedInfo.args.doPostDeleteLI(true); } } + + if (!isEphemeral(res.pkg)) { + // Notify DexManager that the package was installed for new users. + // The updated users should already be indexed and the package code paths + // should not change. + // Don't notify the manager for ephemeral apps as they are not expected to + // survive long enough to benefit of background optimizations. + for (int userId : firstUsers) { + PackageInfo info = getPackageInfo(packageName, /*flags*/ 0, userId); + mDexManager.notifyPackageInstalled(info, userId); + } + } } // If someone is watching installs - notify them diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 6d06838cd24f..e8092131a74f 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -132,8 +132,8 @@ public class DexManager { // - new installed splits // If we can't find the owner of the dex we simply do not track it. The impact is // that the dex file will not be considered for offline optimizations. - // TODO(calin): add hooks for install/uninstall notifications to - // capture new or obsolete packages. + // TODO(calin): add hooks for move/uninstall notifications to + // capture package moves or obsolete packages. if (DEBUG) { Slog.i(TAG, "Could not find owning package for dex file: " + dexPath); } @@ -157,6 +157,20 @@ public class DexManager { } } + public void notifyPackageInstalled(PackageInfo info, int userId) { + cachePackageCodeLocation(info, userId); + } + + private void cachePackageCodeLocation(PackageInfo info, int userId) { + PackageCodeLocations pcl = mPackageCodeLocationsCache.get(info.packageName); + if (pcl != null) { + pcl.mergeAppDataDirs(info.applicationInfo, userId); + } else { + mPackageCodeLocationsCache.put(info.packageName, + new PackageCodeLocations(info.applicationInfo, userId)); + } + } + private void loadInternal(Map> existingPackages) { Map> packageToUsersMap = new HashMap<>(); // Cache the code locations for the installed packages. This allows for @@ -166,13 +180,8 @@ public class DexManager { int userId = entry.getKey(); for (PackageInfo pi : packageInfoList) { // Cache the code locations. - PackageCodeLocations pcl = mPackageCodeLocationsCache.get(pi.packageName); - if (pcl != null) { - pcl.mergeAppDataDirs(pi.applicationInfo, userId); - } else { - mPackageCodeLocationsCache.put(pi.packageName, - new PackageCodeLocations(pi.applicationInfo, userId)); - } + cachePackageCodeLocation(pi, userId); + // Cache a map from package name to the set of user ids who installed the package. // We will use it to sync the data and remove obsolete entries from // mPackageDexUsage. diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java index b655f3af3a24..2d07e651fdd1 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -204,6 +204,46 @@ public class DexManagerTests { assertNull(getPackageUseInfo(mBarUser1)); } + @Test + public void testNotifyPackageInstallUsedByOther() { + TestData newPackage = new TestData("newPackage", + VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]), mUser0); + + List newSecondaries = newPackage.getSecondaryDexPaths(); + // Before we notify about the installation of the newPackage if mFoo + // is trying to load something from it we should not find it. + notifyDexLoad(mFooUser0, newSecondaries, mUser0); + assertNull(getPackageUseInfo(newPackage)); + + // Notify about newPackage install and let mFoo load its dexes. + mDexManager.notifyPackageInstalled(newPackage.mPackageInfo, mUser0); + notifyDexLoad(mFooUser0, newSecondaries, mUser0); + + // We should get back the right info. + PackageUseInfo pui = getPackageUseInfo(newPackage); + assertNotNull(pui); + assertFalse(pui.isUsedByOtherApps()); + assertEquals(newSecondaries.size(), pui.getDexUseInfoMap().size()); + assertSecondaryUse(newPackage, pui, newSecondaries, /*isUsedByOtherApps*/true, mUser0); + } + + @Test + public void testNotifyPackageInstallSelfUse() { + TestData newPackage = new TestData("newPackage", + VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]), mUser0); + + List newSecondaries = newPackage.getSecondaryDexPaths(); + // Packages should be able to find their own dex files even if the notification about + // their installation is delayed. + notifyDexLoad(newPackage, newSecondaries, mUser0); + + PackageUseInfo pui = getPackageUseInfo(newPackage); + assertNotNull(pui); + assertFalse(pui.isUsedByOtherApps()); + assertEquals(newSecondaries.size(), pui.getDexUseInfoMap().size()); + assertSecondaryUse(newPackage, pui, newSecondaries, /*isUsedByOtherApps*/false, mUser0); + } + private void assertSecondaryUse(TestData testData, PackageUseInfo pui, List secondaries, boolean isUsedByOtherApps, int ownerUserId) { for (String dex : secondaries) { -- cgit v1.2.3-59-g8ed1b