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

Commit f1910c5a authored by Richard Uhler's avatar Richard Uhler
Browse files

Add support for rollback of multiPackage installs.

The RollbackManager APIs still need to be updated to expose information
about dependant rollbacks.

Test: atest RollbackTest, with multiPackage test now enabled.
Bug: 112431924
Change-Id: Ib05902aa2bc8b8e228ad6faf3d9418190c5bc946
parent 01b06151
Loading
Loading
Loading
Loading
+43 −16
Original line number Diff line number Diff line
@@ -93,6 +93,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
    @GuardedBy("mLock")
    private final Map<Integer, RollbackData> mPendingRollbacks = new HashMap<>();

    // Map from child session id's for enabled rollbacks to their
    // corresponding parent session ids.
    @GuardedBy("mLock")
    private final Map<Integer, Integer> mChildSessions = new HashMap<>();

    // Package rollback data available to be used for rolling back a package.
    // This list is null until the rollback data has been loaded.
    @GuardedBy("mLock")
@@ -771,16 +776,29 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        Log.i(TAG, "Enabling rollback for install of " + packageName);

        // Figure out the session id associated with this install.
        int sessionId = PackageInstaller.SessionInfo.INVALID_ID;
        int parentSessionId = PackageInstaller.SessionInfo.INVALID_ID;
        int childSessionId = PackageInstaller.SessionInfo.INVALID_ID;
        PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
        for (PackageInstaller.SessionInfo info : installer.getAllSessions()) {
            if (info.isMultiPackage()) {
                for (int childId : info.getChildSessionIds()) {
                    PackageInstaller.SessionInfo child = installer.getSessionInfo(childId);
                    if (sessionMatchesForEnableRollback(child, installFlags, newPackageCodePath)) {
                        // TODO: Check we only have one matching session?
                        parentSessionId = info.getSessionId();
                        childSessionId = childId;
                    }
                }
            } else {
                if (sessionMatchesForEnableRollback(info, installFlags, newPackageCodePath)) {
                    // TODO: Check we only have one matching session?
                sessionId = info.getSessionId();
                    parentSessionId = info.getSessionId();
                    childSessionId = parentSessionId;
                }
            }
        }

        if (sessionId == PackageInstaller.SessionInfo.INVALID_ID) {
        if (parentSessionId == PackageInstaller.SessionInfo.INVALID_ID) {
            Log.e(TAG, "Unable to find session id for enabled rollback.");
            return false;
        }
@@ -800,16 +818,28 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        PackageRollbackInfo.PackageVersion installedVersion =
                new PackageRollbackInfo.PackageVersion(installedPackage.getLongVersionCode());

        File backupDir;
        PackageRollbackInfo info = new PackageRollbackInfo(
                packageName, newVersion, installedVersion);

        RollbackData data;
        try {
            backupDir = Files.createTempDirectory(
            synchronized (mLock) {
                mChildSessions.put(childSessionId, parentSessionId);
                data = mPendingRollbacks.get(parentSessionId);
                if (data == null) {
                    File backupDir = Files.createTempDirectory(
                            mAvailableRollbacksDir.toPath(), null).toFile();
                    data = new RollbackData(backupDir);
                    mPendingRollbacks.put(parentSessionId, data);
                }
                data.packages.add(info);
            }
        } catch (IOException e) {
            Log.e(TAG, "Unable to create rollback for " + packageName, e);
            return false;
        }

        File packageDir = new File(backupDir, packageName);
        File packageDir = new File(data.backupDir, packageName);
        packageDir.mkdirs();
        try {
            JSONObject json = new JSONObject();
@@ -835,13 +865,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
            return false;
        }

        RollbackData data = new RollbackData(backupDir);
        data.packages.add(new PackageRollbackInfo(packageName, newVersion, installedVersion));

        synchronized (mLock) {
            mPendingRollbacks.put(sessionId, data);
        }

        return true;
    }

@@ -924,6 +947,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        public void onFinished(int sessionId, boolean success) {
            RollbackData data = null;
            synchronized (mLock) {
                Integer parentSessionId = mChildSessions.remove(sessionId);
                if (parentSessionId != null) {
                    sessionId = parentSessionId;
                }
                data = mPendingRollbacks.remove(sessionId);
            }

+3 −1
Original line number Diff line number Diff line
@@ -190,6 +190,8 @@ public class RollbackTest {

            RollbackManager rm = RollbackTestUtils.getRollbackManager();

            // TODO: Test this with multi-package rollback, not just single
            // package rollback.
            // Prep installation of TEST_APP_A
            RollbackTestUtils.uninstall(TEST_APP_A);
            RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
@@ -511,7 +513,7 @@ public class RollbackTest {
     * TODO: Stop ignoring this test once support for multi-package rollback
     * is implemented.
     */
    @Ignore @Test
    @Test
    public void testMultiPackage() throws Exception {
        try {
            RollbackTestUtils.adoptShellPermissionIdentity(