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

Commit 8e6dc3b7 authored by Richard Uhler's avatar Richard Uhler Committed by Android (Google) Code Review
Browse files

Merge changes I5062993d,I74063a62,Id95e9dd6,Ie8496976

* changes:
  RollbackManager: Check for applied staged sessions on boot.
  Handle enable rollback for the apk session part of a staged install
  Track the apkSessionId associated with a staged install.
  Notify RollbackManager of the apk session for a staged install.
parents fe9f8eb8 b2c5cacd
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -47,4 +47,8 @@ interface IRollbackManager {
    //
    // NOTE: This call is synchronous.
    boolean notifyStagedSession(int sessionId);

    // Used by the staging manager to notify the RollbackManager of the apk
    // session for a staged session.
    void notifyStagedApkSession(int originalSessionId, int apkSessionId);
}
+13 −0
Original line number Diff line number Diff line
@@ -380,6 +380,19 @@ public class StagingManager {

    private boolean commitApkSession(@NonNull PackageInstallerSession apkSession,
                                     int originalSessionId) {

        if ((apkSession.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
            // If rollback is available for this session, notify the rollback
            // manager of the apk session so it can properly enable rollback.
            final IRollbackManager rm = IRollbackManager.Stub.asInterface(
                    ServiceManager.getService(Context.ROLLBACK_SERVICE));
            try {
                rm.notifyStagedApkSession(originalSessionId, apkSession.sessionId);
            } catch (RemoteException re) {
                // Cannot happen, the rollback manager is in the same process.
            }
        }

        final LocalIntentReceiver receiver = new LocalIntentReceiver();
        apkSession.commit(receiver.getIntentSender(), false);
        final Intent result = receiver.getResult();
+5 −0
Original line number Diff line number Diff line
@@ -63,6 +63,11 @@ class RollbackData {
     */
    public boolean isAvailable;

    /**
     * The id of the post-reboot apk session for a staged install, if any.
     */
    public int apkSessionId = -1;

    /**
     * Whether this Rollback is currently in progress. This field is true from the point
     * we commit a {@code PackageInstaller} session containing these packages to the point the
+7 −0
Original line number Diff line number Diff line
@@ -44,4 +44,11 @@ public final class RollbackManagerService extends SystemService {
    public void onUnlockUser(int user) {
        mService.onUnlockUser(user);
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_BOOT_COMPLETED) {
            mService.onBootCompleted();
        }
    }
}
+118 −0
Original line number Diff line number Diff line
@@ -486,6 +486,47 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        });
    }

    void onBootCompleted() {
        getHandler().post(() -> {
            // Check to see if any staged sessions with rollback enabled have
            // been applied.
            List<RollbackData> staged = new ArrayList<>();
            synchronized (mLock) {
                ensureRollbackDataLoadedLocked();
                for (RollbackData data : mAvailableRollbacks) {
                    if (data.stagedSessionId != -1) {
                        staged.add(data);
                    }
                }
            }

            for (RollbackData data : staged) {
                PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
                PackageInstaller.SessionInfo session = installer.getSessionInfo(
                        data.stagedSessionId);
                if (session != null) {
                    if (session.isSessionApplied()) {
                        synchronized (mLock) {
                            data.isAvailable = true;
                        }
                        try {
                            mRollbackStore.saveAvailableRollback(data);
                        } catch (IOException ioe) {
                            Log.e(TAG, "Unable to save rollback info for : "
                                    + data.rollbackId, ioe);
                        }
                    } else if (session.isSessionFailed()) {
                        // TODO: Do we need to remove this from
                        // mAvailableRollbacks, or is it okay to leave as
                        // unavailable until the next reboot when it will go
                        // away on its own?
                        mRollbackStore.deleteAvailableRollback(data);
                    }
                }
            }
        });
    }

    /**
     * Load rollback data from storage if it has not already been loaded.
     * After calling this funciton, mAvailableRollbacks and
@@ -725,6 +766,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        // ourselves.
        PackageInstaller.SessionInfo session = null;

        int parentSessionId = -1;
        PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
        for (PackageInstaller.SessionInfo info : installer.getAllSessions()) {
            if (info.isMultiPackage()) {
@@ -732,12 +774,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                    PackageInstaller.SessionInfo child = installer.getSessionInfo(childId);
                    if (sessionMatchesForEnableRollback(child, installFlags, newPackageCodePath)) {
                        // TODO: Check we only have one matching session?
                        parentSessionId = info.getSessionId();
                        session = child;
                        break;
                    }
                }
            } else if (sessionMatchesForEnableRollback(info, installFlags, newPackageCodePath)) {
                // TODO: Check we only have one matching session?
                parentSessionId = info.getSessionId();
                session = info;
                break;
            }
@@ -748,6 +792,54 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
            return false;
        }

        // Check to see if this is the apk session for a staged session with
        // rollback enabled.
        // TODO: This check could be made more efficient.
        RollbackData rd = null;
        synchronized (mLock) {
            ensureRollbackDataLoadedLocked();
            for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
                RollbackData data = mAvailableRollbacks.get(i);
                if (data.apkSessionId == parentSessionId) {
                    rd = data;
                    break;
                }
            }
        }

        if (rd != null) {
            // This is the apk session for a staged session. We have already
            // backed up the apks, we just need to do user data backup.
            PackageParser.PackageLite newPackage = null;
            try {
                newPackage = PackageParser.parsePackageLite(
                        new File(session.resolvedBaseCodePath), 0);
            } catch (PackageParser.PackageParserException e) {
                Log.e(TAG, "Unable to parse new package", e);
                return false;
            }
            String packageName = newPackage.packageName;
            for (PackageRollbackInfo info : rd.packages) {
                if (info.getPackageName().equals(packageName)) {
                    IntArray pendingBackups = mUserdataHelper.snapshotAppData(
                            packageName, installedUsers);
                    info.getPendingBackups().addAll(pendingBackups);
                    try {
                        mRollbackStore.saveAvailableRollback(rd);
                    } catch (IOException ioe) {
                        // TODO: Hopefully this is okay because we will try
                        // again to save the rollback when the staged session
                        // is applied. Just so long as the device doesn't
                        // reboot before then.
                        Log.e(TAG, "Unable to save rollback info for : " + rd.rollbackId, ioe);
                    }
                    return true;
                }
            }
            Log.e(TAG, "Unable to find package in apk session");
            return false;
        }

        return enableRollbackForSession(session, installedUsers, true);
    }

@@ -928,6 +1020,32 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        }
    }

    @Override
    public void notifyStagedApkSession(int originalSessionId, int apkSessionId) {
        getHandler().post(() -> {
            RollbackData rd = null;
            synchronized (mLock) {
                ensureRollbackDataLoadedLocked();
                for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
                    RollbackData data = mAvailableRollbacks.get(i);
                    if (data.stagedSessionId == originalSessionId) {
                        data.apkSessionId = apkSessionId;
                        rd = data;
                        break;
                    }
                }
            }

            if (rd != null) {
                try {
                    mRollbackStore.saveAvailableRollback(rd);
                } catch (IOException ioe) {
                    Log.e(TAG, "Unable to save rollback info for : " + rd.rollbackId, ioe);
                }
            }
        });
    }

    /**
     * Gets the version of the package currently installed.
     * Returns null if the package is not currently installed.
Loading