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

Commit 8e7d0ecb authored by Dario Freni's avatar Dario Freni
Browse files

Persist staged sessions upon commit.

This change prevents staged sessions from being completely forgotten
upon commit, and leaves them in the XML storage even after commit. This
would allow resuming the state of the sessions upon reboot.

Bug: 118865310
Test: submitted a staged session, verified it was written on file on
reboot.

Change-Id: Iea600b66eac6f8655d671ae98a3a74f5003e5378
parent 959d407a
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -329,6 +329,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements

                        if (valid) {
                            mSessions.put(session.sessionId, session);
                            if (session.isStaged()) {
                                mStagingManager.restoreSession(session);
                            }
                        } else {
                            // Since this is early during boot we don't send
                            // any observer events about the session, but we
@@ -533,7 +536,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
        session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
                mInstallThread.getLooper(), mStagingManager, sessionId, userId,
                installerPackageName, callingUid, params, createdMillis, stageDir, stageCid, false,
                false, null, SessionInfo.INVALID_ID);
                false, null, SessionInfo.INVALID_ID, false, false, false, SessionInfo.NO_ERROR);

        synchronized (mSessions) {
            mSessions.put(sessionId, session);
@@ -1131,7 +1134,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
                        }
                    }
                    synchronized (mSessions) {
                        if (!session.isStaged() || !success) {
                            mSessions.remove(session.sessionId);
                        }
                        addHistoricalSessionLocked(session);

                        final File appIconFile = buildAppIconFile(session.sessionId);
+24 −5
Original line number Diff line number Diff line
@@ -151,6 +151,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private static final String ATTR_MULTI_PACKAGE = "multiPackage";
    private static final String ATTR_PARENT_SESSION_ID = "parentSessionId";
    private static final String ATTR_STAGED_SESSION = "stagedSession";
    private static final String ATTR_IS_READY = "isReady";
    private static final String ATTR_IS_FAILED = "isFailed";
    private static final String ATTR_IS_APPLIED = "isApplied";
    private static final String ATTR_STAGED_SESSION_ERROR_CODE = "errorCode";
    private static final String ATTR_MODE = "mode";
    private static final String ATTR_INSTALL_FLAGS = "installFlags";
    private static final String ATTR_INSTALL_LOCATION = "installLocation";
@@ -408,7 +412,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            int sessionId, int userId,
            String installerPackageName, int installerUid, SessionParams params, long createdMillis,
            File stageDir, String stageCid, boolean prepared, boolean sealed,
            @Nullable int[] childSessionIds, int parentSessionId) {
            @Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
            boolean isFailed, boolean isApplied, int stagedSessionErrorCode) {
        mCallback = callback;
        mContext = context;
        mPm = pm;
@@ -438,7 +443,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }

        mPrepared = prepared;

        mStagedSessionReady = isReady;
        mStagedSessionFailed = isFailed;
        mStagedSessionApplied = isApplied;
        mStagedSessionErrorCode = stagedSessionErrorCode;
        if (sealed) {
            synchronized (mLock) {
                try {
@@ -2023,8 +2031,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private void destroyInternal() {
        synchronized (mLock) {
            mSealed = true;
            if (!params.isStaged) {
                mDestroyed = true;

            }
            // Force shut down all bridges
            for (RevocableFileDescriptor fd : mFds) {
                fd.revoke();
@@ -2131,6 +2140,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

            writeBooleanAttribute(out, ATTR_MULTI_PACKAGE, params.isMultiPackage);
            writeBooleanAttribute(out, ATTR_STAGED_SESSION, params.isStaged);
            writeBooleanAttribute(out, ATTR_IS_READY, mStagedSessionReady);
            writeBooleanAttribute(out, ATTR_IS_FAILED, mStagedSessionFailed);
            writeBooleanAttribute(out, ATTR_IS_APPLIED, mStagedSessionApplied);
            writeIntAttribute(out, ATTR_STAGED_SESSION_ERROR_CODE, mStagedSessionErrorCode);
            // TODO(patb,109941548): avoid writing to xml and instead infer / validate this after
            //                       we've read all sessions.
            writeIntAttribute(out, ATTR_PARENT_SESSION_ID, mParentSessionId);
@@ -2269,10 +2282,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            params.appIcon = BitmapFactory.decodeFile(appIconFile.getAbsolutePath());
            params.appIconLastModified = appIconFile.lastModified();
        }
        final boolean isReady = readBooleanAttribute(in, ATTR_IS_READY);
        final boolean isFailed = readBooleanAttribute(in, ATTR_IS_FAILED);
        final boolean isApplied = readBooleanAttribute(in, ATTR_IS_APPLIED);
        final int stagedSessionErrorCode = readIntAttribute(in, ATTR_STAGED_SESSION_ERROR_CODE);

        return new PackageInstallerSession(callback, context, pm, sessionProvider,
                installerThread, stagingManager, sessionId, userId, installerPackageName,
                installerUid, params, createdMillis, stageDir, stageCid, prepared, sealed,
                EMPTY_CHILD_SESSION_ARRAY, parentSessionId);
                EMPTY_CHILD_SESSION_ARRAY, parentSessionId, isReady, isFailed, isApplied,
                stagedSessionErrorCode);
    }

    /**
+7 −3
Original line number Diff line number Diff line
@@ -53,9 +53,6 @@ public class StagingManager {
    private final PackageManagerService mPm;
    private final Handler mBgHandler;

    // STOPSHIP: This is a temporary mock implementation of staged sessions. This variable
    //           shouldn't be needed at all.
    // TODO(b/118865310): Implement staged sessions logic.
    @GuardedBy("mStagedSessions")
    private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();

@@ -191,4 +188,11 @@ public class StagingManager {
            mStagedSessions.remove(sessionInfo.sessionId);
        }
    }

    void restoreSession(@NonNull PackageInstallerSession session) {
        updateStoredSession(session);
        // TODO(b/118865310): This method is called when PackageInstaller is re-instantiated, e.g.
        // at reboot. Staging manager should at this point recover state from apexd and decide what
        // to do with the session.
    }
}