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

Commit 07b53113 authored by Mohammad Samiul Islam's avatar Mohammad Samiul Islam Committed by Android (Google) Code Review
Browse files

Merge "Prevent staging multiple sessions on devices not supporting checkpoint"

parents 563151db cc4c7d8c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -35911,6 +35911,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
@@ -2362,6 +2362,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 −5
Original line number Diff line number Diff line
@@ -2771,11 +2771,6 @@ class StorageManagerService extends IStorageManager.Stub
     */
    @Override
    public boolean supportsCheckpoint() throws RemoteException {
        // Only the system process is permitted to start checkpoints
        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
            throw new SecurityException("no permission to check filesystem checkpoint support");
        }

        return mVold.supportsCheckpoint();
    }

+21 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.os.ParcelFileDescriptor;
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;
@@ -75,6 +76,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")
@@ -83,6 +85,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.