summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dario Freni <dariofreni@google.com> 2019-01-25 14:21:56 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2019-01-25 14:21:56 +0000
commit5cccc2bd8eae729c60c680fe397ed9472496e23c (patch)
treecd91c831860218d33f4dafadce594b3cb2f79db4
parent471530dd565ed378bb34fe271b3575d43985c371 (diff)
parent275b4aba7785a6d9778b3195125210d1bd7f8c6a (diff)
Merge "Add an error message to staged install session."
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/content/pm/PackageInstaller.java15
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java28
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java28
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java5
6 files changed, 63 insertions, 17 deletions
diff --git a/api/current.txt b/api/current.txt
index de5085e0b563..08b0e0385b8c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11431,6 +11431,7 @@ package android.content.pm {
method public int getSessionId();
method public long getSize();
method public int getStagedSessionErrorCode();
+ method public String getStagedSessionErrorMessage();
method public boolean isActive();
method public boolean isMultiPackage();
method public boolean isSealed();
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 73b1f4e7e536..2dc014c45fad 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1710,6 +1710,7 @@ public class PackageInstaller {
/** {@hide} */
public boolean isSessionFailed;
private int mStagedSessionErrorCode;
+ private String mStagedSessionErrorMessage;
/** {@hide} */
@UnsupportedAppUsage
@@ -1749,6 +1750,7 @@ public class PackageInstaller {
isSessionReady = source.readBoolean();
isSessionFailed = source.readBoolean();
mStagedSessionErrorCode = source.readInt();
+ mStagedSessionErrorMessage = source.readString();
}
/**
@@ -2066,9 +2068,19 @@ public class PackageInstaller {
return mStagedSessionErrorCode;
}
+ /**
+ * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
+ * empty string if no error was encountered.
+ */
+ public String getStagedSessionErrorMessage() {
+ return mStagedSessionErrorMessage;
+ }
+
/** {@hide} */
- public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode) {
+ public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode,
+ String errorMessage) {
mStagedSessionErrorCode = errorCode;
+ mStagedSessionErrorMessage = errorMessage;
}
@Override
@@ -2106,6 +2118,7 @@ public class PackageInstaller {
dest.writeBoolean(isSessionReady);
dest.writeBoolean(isSessionFailed);
dest.writeInt(mStagedSessionErrorCode);
+ dest.writeString(mStagedSessionErrorMessage);
}
public static final Parcelable.Creator<SessionInfo>
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 0ab2a7361ac0..eab5c8f866a8 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -537,7 +537,8 @@ 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, false, false, SessionInfo.NO_ERROR);
+ false, null, SessionInfo.INVALID_ID, false, false, false, SessionInfo.NO_ERROR,
+ "");
synchronized (mSessions) {
mSessions.put(sessionId, session);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index b8825bbd2d72..494ec3ff67aa 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -155,6 +155,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
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_STAGED_SESSION_ERROR_MESSAGE = "errorMessage";
private static final String ATTR_MODE = "mode";
private static final String ATTR_INSTALL_FLAGS = "installFlags";
private static final String ATTR_INSTALL_LOCATION = "installLocation";
@@ -267,6 +268,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private boolean mStagedSessionFailed;
@GuardedBy("mLock")
private int mStagedSessionErrorCode = SessionInfo.NO_ERROR;
+ @GuardedBy("mLock")
+ private String mStagedSessionErrorMessage;
/**
* Path to the validated base APK for this session, which may point at an
@@ -413,7 +416,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
String installerPackageName, int installerUid, SessionParams params, long createdMillis,
File stageDir, String stageCid, boolean prepared, boolean sealed,
@Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
- boolean isFailed, boolean isApplied, int stagedSessionErrorCode) {
+ boolean isFailed, boolean isApplied, int stagedSessionErrorCode,
+ String stagedSessionErrorMessage) {
mCallback = callback;
mContext = context;
mPm = pm;
@@ -447,6 +451,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mStagedSessionFailed = isFailed;
mStagedSessionApplied = isApplied;
mStagedSessionErrorCode = stagedSessionErrorCode;
+ mStagedSessionErrorMessage =
+ stagedSessionErrorMessage != null ? stagedSessionErrorMessage : "";
if (sealed) {
synchronized (mLock) {
try {
@@ -499,7 +505,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
info.isSessionApplied = mStagedSessionApplied;
info.isSessionReady = mStagedSessionReady;
info.isSessionFailed = mStagedSessionFailed;
- info.setStagedSessionErrorCode(mStagedSessionErrorCode);
+ info.setStagedSessionErrorCode(mStagedSessionErrorCode, mStagedSessionErrorMessage);
}
return info;
}
@@ -1971,17 +1977,21 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mStagedSessionApplied = false;
mStagedSessionFailed = false;
mStagedSessionErrorCode = SessionInfo.NO_ERROR;
+ mStagedSessionErrorMessage = "";
}
mCallback.onStagedSessionChanged(this);
}
/** {@hide} */
- void setStagedSessionFailed(@StagedSessionErrorCode int errorCode) {
+ void setStagedSessionFailed(@StagedSessionErrorCode int errorCode,
+ String errorMessage) {
synchronized (mLock) {
mStagedSessionReady = false;
mStagedSessionApplied = false;
mStagedSessionFailed = true;
mStagedSessionErrorCode = errorCode;
+ mStagedSessionErrorMessage = errorMessage;
+ Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
}
mCallback.onStagedSessionChanged(this);
}
@@ -1993,6 +2003,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mStagedSessionApplied = true;
mStagedSessionFailed = false;
mStagedSessionErrorCode = SessionInfo.NO_ERROR;
+ mStagedSessionErrorMessage = "";
}
mCallback.onStagedSessionChanged(this);
}
@@ -2017,6 +2028,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return mStagedSessionErrorCode;
}
+ /** {@hide} */
+ String getStagedSessionErrorMessage() {
+ return mStagedSessionErrorMessage;
+ }
+
private void destroyInternal() {
synchronized (mLock) {
mSealed = true;
@@ -2133,6 +2149,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
writeBooleanAttribute(out, ATTR_IS_FAILED, mStagedSessionFailed);
writeBooleanAttribute(out, ATTR_IS_APPLIED, mStagedSessionApplied);
writeIntAttribute(out, ATTR_STAGED_SESSION_ERROR_CODE, mStagedSessionErrorCode);
+ writeStringAttribute(out, ATTR_STAGED_SESSION_ERROR_MESSAGE,
+ mStagedSessionErrorMessage);
// 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);
@@ -2253,6 +2271,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final boolean isApplied = readBooleanAttribute(in, ATTR_IS_APPLIED);
final int stagedSessionErrorCode = readIntAttribute(in, ATTR_STAGED_SESSION_ERROR_CODE,
SessionInfo.NO_ERROR);
+ final String stagedSessionErrorMessage = readStringAttribute(in,
+ ATTR_STAGED_SESSION_ERROR_MESSAGE);
if (!isStagedSessionStateValid(isReady, isApplied, isFailed)) {
throw new IllegalArgumentException("Can't restore staged session with invalid state.");
@@ -2296,7 +2316,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
installerThread, stagingManager, sessionId, userId, installerPackageName,
installerUid, params, createdMillis, stageDir, stageCid, prepared, sealed,
childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
- stagedSessionErrorCode);
+ stagedSessionErrorCode, stagedSessionErrorMessage);
}
/**
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 5311c2a55931..b930d267282f 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -166,6 +166,7 @@ public class StagingManager {
if (!session.isMultiPackage()
&& isApexSession(session)) {
success = submitSessionToApexService(session, null, apexInfoList);
+
} else if (session.isMultiPackage()) {
List<PackageInstallerSession> childSessions =
Arrays.stream(session.getChildSessionIds())
@@ -179,7 +180,13 @@ public class StagingManager {
} // else this is a staged multi-package session with no APEX files.
}
- if (success && (apexInfoList.apexInfos.length > 0)) {
+ if (!success) {
+ session.setStagedSessionFailed(
+ SessionInfo.VERIFICATION_FAILED,
+ "APEX staging failed, check logcat messages from apexd for more details.");
+ }
+
+ if (apexInfoList.apexInfos.length > 0) {
// For APEXes, we validate the signature here before we mark the session as ready,
// so we fail the session early if there is a signature mismatch. For APKs, the
// signature verification will be done by the package manager at the point at which
@@ -190,17 +197,16 @@ public class StagingManager {
for (ApexInfo apexPackage : apexInfoList.apexInfos) {
if (!validateApexSignatureLocked(apexPackage.packagePath,
apexPackage.packageName)) {
- success = false;
- break;
+ session.setStagedSessionFailed(SessionInfo.VERIFICATION_FAILED,
+ "APK-container signature verification failed for package "
+ + apexPackage.packageName + ". Signature of file "
+ + apexPackage.packagePath + " does not match the signature of "
+ + " the package already installed.");
+ return;
}
}
}
-
- if (success) {
- session.setStagedSessionReady();
- } else {
- session.setStagedSessionFailed(SessionInfo.VERIFICATION_FAILED);
- }
+ session.setStagedSessionReady();
}
private void resumeSession(@NonNull PackageInstallerSession session) {
@@ -217,7 +223,9 @@ public class StagingManager {
return;
}
if (apexSessionInfo.isActivationFailed || apexSessionInfo.isUnknown) {
- session.setStagedSessionFailed(SessionInfo.ACTIVATION_FAILED);
+ session.setStagedSessionFailed(SessionInfo.ACTIVATION_FAILED,
+ "APEX activation failed. Check logcat messages from apexd for "
+ + "more information.");
}
if (apexSessionInfo.isActivated) {
session.setStagedSessionApplied();
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index 73e96134167a..742ae41ed9f0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -173,7 +173,8 @@ public class PackageInstallerSessionTest {
/* isReady */ staged ? true : false,
/* isFailed */ false,
/* isApplied */false,
- /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.VERIFICATION_FAILED);
+ /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.VERIFICATION_FAILED,
+ /* stagedSessionErrorMessage */ "some error");
}
private void dumpSession(PackageInstallerSession session) {
@@ -295,6 +296,8 @@ public class PackageInstallerSessionTest {
assertEquals(expected.isStagedSessionFailed(), actual.isStagedSessionFailed());
assertEquals(expected.isStagedSessionReady(), actual.isStagedSessionReady());
assertEquals(expected.getStagedSessionErrorCode(), actual.getStagedSessionErrorCode());
+ assertEquals(expected.getStagedSessionErrorMessage(),
+ actual.getStagedSessionErrorMessage());
assertEquals(expected.isPrepared(), actual.isPrepared());
assertEquals(expected.isSealed(), actual.isSealed());
assertEquals(expected.isMultiPackage(), actual.isMultiPackage());