Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d4b8f8b authored by Calin Juravle's avatar Calin Juravle
Browse files

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
Change-Id: I0cb7158af249feeb01cf578a7544dda978eede9d
parent 04e7b6c6
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1847,6 +1847,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
+18 −9
Original line number Diff line number Diff line
@@ -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.
+40 −0
Original line number Diff line number Diff line
@@ -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) {