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 0d4b8f8b0c)

Change-Id: I34008f6d262f19e88a346a36b83e4093b4129105

Merged-In: I0cb7158af249feeb01cf578a7544dda978eede9d
This commit is contained in:
Calin Juravle
2017-01-23 23:34:25 -08:00
parent 3d5504724f
commit fcd672fca3
3 changed files with 70 additions and 9 deletions

View File

@@ -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

View File

@@ -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<Integer, List<PackageInfo>> existingPackages) {
Map<String, Set<Integer>> 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.

View File

@@ -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<String> 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<String> 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<String> secondaries, boolean isUsedByOtherApps, int ownerUserId) {
for (String dex : secondaries) {