Prevent staging multiple sessions on devices not supporting checkpoint

Bug: 141843321
Test: atest StagedInstallTest#testFailStagingMultipleSessionsIfNoCheckPoint
Change-Id: I118ae628649e9bef82641ef18841205091e98a6a
Merged-In: I118ae628649e9bef82641ef18841205091e98a6a
(cherry picked from commit cc4c7d8cc6)
This commit is contained in:
Mohammad Samiul Islam
2019-11-05 18:18:28 +00:00
parent e87ec2bec8
commit 8c7142a658
4 changed files with 35 additions and 8 deletions

View File

@@ -36025,6 +36025,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);

View File

@@ -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")

View File

@@ -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();
}

View File

@@ -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.