Add a state for Staged Sessions.

The state is only kept up-to-date for staged sessions. Clients are in
charge of checking whether the session has the isStaged bit set, before
considering reading the StagedSessionState associated to that session.

Test: retrieved mock staged session from a small app and verified state
is correctly set.
Bug: 118865310
Bug: 112669193
Bug: 120487127
Change-Id: I03590476dc353fee6d6edffb7ae579a9f9664664
This commit is contained in:
Dario Freni
2018-12-06 15:47:16 +00:00
parent 2ec8b91026
commit 71eee5ef91
3 changed files with 101 additions and 0 deletions

View File

@@ -11366,13 +11366,20 @@ package android.content.pm {
method public android.net.Uri getReferrerUri();
method public int getSessionId();
method public long getSize();
method public int getStagedSessionErrorCode();
method public boolean isActive();
method public boolean isMultiPackage();
method public boolean isSealed();
method public boolean isSessionApplied();
method public boolean isSessionFailed();
method public boolean isSessionReady();
method public boolean isStaged();
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTIVATION_FAILED = 2; // 0x2
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
field public static final int INVALID_ID = -1; // 0xffffffff
field public static final int NO_ERROR = 0; // 0x0
field public static final int VERIFICATION_FAILED = 1; // 0x1
}
public static class PackageInstaller.SessionParams implements android.os.Parcelable {

View File

@@ -17,6 +17,7 @@
package android.content.pm;
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -54,6 +55,8 @@ import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Iterator;
@@ -1594,6 +1597,29 @@ public class PackageInstaller {
public static final int INVALID_ID = -1;
/** {@hide} */
private static final int[] NO_SESSIONS = {};
/** @hide */
@IntDef(value = {NO_ERROR, VERIFICATION_FAILED, ACTIVATION_FAILED})
@Retention(RetentionPolicy.SOURCE)
public @interface StagedSessionErrorCode{}
/**
* Constant indicating that no error occurred during the preparation or the activation of
* this staged session.
*/
public static final int NO_ERROR = 0;
/**
* Constant indicating that an error occurred during the verification phase (pre-reboot) of
* this staged session.
*/
public static final int VERIFICATION_FAILED = 1;
/**
* Constant indicating that an error occurred during the activation phase (post-reboot) of
* this staged session.
*/
public static final int ACTIVATION_FAILED = 2;
/** {@hide} */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public int sessionId;
@@ -1652,6 +1678,14 @@ public class PackageInstaller {
/** {@hide} */
public int[] childSessionIds = NO_SESSIONS;
/** {@hide} */
public boolean isSessionApplied;
/** {@hide} */
public boolean isSessionReady;
/** {@hide} */
public boolean isSessionFailed;
private int mStagedSessionErrorCode;
/** {@hide} */
@UnsupportedAppUsage
public SessionInfo() {
@@ -1686,6 +1720,10 @@ public class PackageInstaller {
if (childSessionIds == null) {
childSessionIds = NO_SESSIONS;
}
isSessionApplied = source.readBoolean();
isSessionReady = source.readBoolean();
isSessionFailed = source.readBoolean();
mStagedSessionErrorCode = source.readInt();
}
/**
@@ -1970,6 +2008,44 @@ public class PackageInstaller {
return childSessionIds;
}
/**
* Whether the staged session has been applied successfully, meaning that all of its
* packages have been activated and no further action is required.
* Only meaningful if {@code isStaged} is true.
*/
public boolean isSessionApplied() {
return isSessionApplied;
}
/**
* Whether the staged session is ready to be applied at next reboot. Only meaningful if
* {@code isStaged} is true.
*/
public boolean isSessionReady() {
return isSessionReady;
}
/**
* Whether something went wrong and the staged session is declared as failed, meaning that
* it will be ignored at next reboot. Only meaningful if {@code isStaged} is true.
*/
public boolean isSessionFailed() {
return isSessionFailed;
}
/**
* If something went wrong with a staged session, clients can check this error code to
* understand which kind of failure happened. Only meaningful if {@code isStaged} is true.
*/
public int getStagedSessionErrorCode() {
return mStagedSessionErrorCode;
}
/** {@hide} */
public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode) {
mStagedSessionErrorCode = errorCode;
}
@Override
public int describeContents() {
return 0;
@@ -2001,6 +2077,10 @@ public class PackageInstaller {
dest.writeBoolean(isStaged);
dest.writeInt(parentSessionId);
dest.writeIntArray(childSessionIds);
dest.writeBoolean(isSessionApplied);
dest.writeBoolean(isSessionReady);
dest.writeBoolean(isSessionFailed);
dest.writeInt(mStagedSessionErrorCode);
}
public static final Parcelable.Creator<SessionInfo>

View File

@@ -250,6 +250,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@GuardedBy("mLock")
private int mParentSessionId;
@GuardedBy("mLock")
private boolean mStagedSessionApplied;
@GuardedBy("mLock")
private boolean mStagedSessionReady;
@GuardedBy("mLock")
private boolean mStagedSessionFailed;
@GuardedBy("mLock")
private int mStagedSessionErrorCode = SessionInfo.NO_ERROR;
/**
* Path to the validated base APK for this session, which may point at an
* APK inside the session (when the session defines the base), or it may
@@ -470,6 +479,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (info.childSessionIds == null) {
info.childSessionIds = EMPTY_CHILD_SESSION_ARRAY;
}
info.isSessionApplied = mStagedSessionApplied;
info.isSessionReady = mStagedSessionReady;
info.isSessionFailed = mStagedSessionFailed;
info.setStagedSessionErrorCode(mStagedSessionErrorCode);
}
return info;
}
@@ -1051,6 +1064,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
if (isStaged()) {
// STOPSHIP: implement staged sessions
mStagedSessionReady = true;
dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
return;
}