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

Commit aa0cebd8 authored by Mohammad Samiul Islam's avatar Mohammad Samiul Islam Committed by Automerger Merge Worker
Browse files

Prevent staging multiple sessions on devices not supporting checkpoint am: 8c7142a6

Change-Id: I42c180ae216777624b4ad204466f0f64fccecbb9
parents 2c7ea538 8c7142a6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -36015,6 +36015,7 @@ package android.os.storage {
    method public boolean isAllocationSupported(@NonNull java.io.FileDescriptor);
    method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
    method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
    method public boolean isCheckpointSupported();
    method public boolean isEncrypted(java.io.File);
    method public boolean isObbMounted(String);
    method public boolean mountObb(String, String, android.os.storage.OnObbStateChangeListener);
+13 −0
Original line number Diff line number Diff line
@@ -2304,6 +2304,19 @@ public class StorageManager {
        }
    }

    /**
     * Check whether the device supports filesystem checkpoint.
     *
     * @return true if the device supports filesystem checkpoint, false otherwise.
     */
    public boolean isCheckpointSupported() {
        try {
            return mStorageManager.supportsCheckpoint();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private final Object mFuseAppLoopLock = new Object();

    @GuardedBy("mFuseAppLoopLock")
+0 −7
Original line number Diff line number Diff line
@@ -2648,13 +2648,6 @@ class StorageManagerService extends IStorageManager.Stub
     */
    @Override
    public boolean supportsCheckpoint() throws RemoteException {
        // Only the root, system_server and shell processes are permitted to start checkpoints
        final int callingUid = Binder.getCallingUid();
        if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID
                && callingUid != Process.SHELL_UID) {
            throw new SecurityException("no permission to start filesystem checkpoint");
        }

        return mVold.supportsCheckpoint();
    }

+21 −1
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.os.ParcelableException;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.storage.StorageManager;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -76,6 +77,7 @@ public class StagingManager {
    private final PackageInstallerService mPi;
    private final ApexManager mApexManager;
    private final PowerManager mPowerManager;
    private final Context mContext;
    private final PreRebootVerificationHandler mPreRebootVerificationHandler;

    @GuardedBy("mStagedSessions")
@@ -84,6 +86,7 @@ public class StagingManager {
    StagingManager(PackageInstallerService pi, ApexManager am, Context context) {
        mPi = pi;
        mApexManager = am;
        mContext = context;
        mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mPreRebootVerificationHandler = new PreRebootVerificationHandler(
                BackgroundThread.get().getLooper());
@@ -539,6 +542,10 @@ public class StagingManager {
        mPreRebootVerificationHandler.startPreRebootVerification(session.sessionId);
    }

    private int parentOrOwnSessionId(PackageInstallerSession session) {
        return session.hasParentSessionId() ? session.getParentSessionId() : session.sessionId;
    }

    /**
     * <p> Check if the session provided is non-overlapping with the active staged sessions.
     *
@@ -561,6 +568,9 @@ public class StagingManager {
                    "Cannot stage session " + session.sessionId + " with package name null");
        }

        boolean supportsCheckpoint = ((StorageManager) mContext.getSystemService(
                Context.STORAGE_SERVICE)).isCheckpointSupported();

        synchronized (mStagedSessions) {
            for (int i = 0; i < mStagedSessions.size(); i++) {
                final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
@@ -601,7 +611,17 @@ public class StagingManager {
                                    + stagedSession.sessionId, null);
                }

                // TODO(b/141843321): Add support for staging multiple sessions in apexd
                // Staging multiple root sessions is not allowed if device doesn't support
                // checkpoint. If session and stagedSession do not have common ancestor, they are
                // from two different root sessions.
                if (!supportsCheckpoint
                        && parentOrOwnSessionId(session) != parentOrOwnSessionId(stagedSession)) {
                    throw new PackageManagerException(
                            PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
                            "Cannot stage multiple sessions without checkpoint support", null);
                }

                // TODO:b/141843321 Add support for staging multiple sessions in apexd
                // Since apexd doesn't support multiple staged sessions yet, we have to careful how
                // we handle apex sessions. We want to allow a set of apex sessions under the same
                // parent to be staged when there is no previously staged apex sessions.