Propagate error while scanning apk-in-apex to session object
By storing the error message on session object, we avoid searching the logcat (which is not always available) for information on why apk-in-apex scanning failed. Bug: 178192690 Test: atest ApexManagerTest Test: atest StagedInstallTest#testApexFailsToInstallIfApkInApexFailsToScan Change-Id: I1be52da133ea534ba103f5fbdea5b8138ef67ef6
This commit is contained in:
@@ -67,6 +67,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -306,17 +307,19 @@ public abstract class ApexManager {
|
||||
/**
|
||||
* Reports error raised during installation of apk-in-apex.
|
||||
*
|
||||
* @param scanDir the directory of the apex inside which apk-in-apex resides.
|
||||
* @param scanDirPath the directory of the apex inside which apk-in-apex resides.
|
||||
* @param errorMsg the actual error that occurred when scanning the path
|
||||
*/
|
||||
abstract void reportErrorWithApkInApex(String scanDirPath);
|
||||
abstract void reportErrorWithApkInApex(String scanDirPath, String errorMsg);
|
||||
|
||||
/**
|
||||
* Returns true if there were no errors when installing apk-in-apex inside
|
||||
* {@param apexPackageName}, otherwise false.
|
||||
* Returns null if there were no errors when installing apk-in-apex inside
|
||||
* {@param apexPackageName}, otherwise returns the error as string
|
||||
*
|
||||
* @param apexPackageName Package name of the apk container of apex
|
||||
*/
|
||||
abstract boolean isApkInApexInstallSuccess(String apexPackageName);
|
||||
@Nullable
|
||||
abstract String getApkInApexInstallError(String apexPackageName);
|
||||
|
||||
/**
|
||||
* Returns list of {@code packageName} of apks inside the given apex.
|
||||
@@ -438,7 +441,7 @@ public abstract class ApexManager {
|
||||
* inside {@code apexModuleName}.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private Set<String> mErrorWithApkInApex = new ArraySet<>();
|
||||
private Map<String, String> mErrorWithApkInApex = new ArrayMap<>();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private List<PackageInfo> mAllPackagesCache;
|
||||
@@ -841,26 +844,27 @@ public abstract class ApexManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
void reportErrorWithApkInApex(String scanDirPath) {
|
||||
void reportErrorWithApkInApex(String scanDirPath, String errorMsg) {
|
||||
synchronized (mLock) {
|
||||
for (ActiveApexInfo aai : mActiveApexInfosCache) {
|
||||
if (scanDirPath.startsWith(aai.apexDirectory.getAbsolutePath())) {
|
||||
mErrorWithApkInApex.add(aai.apexModuleName);
|
||||
mErrorWithApkInApex.put(aai.apexModuleName, errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isApkInApexInstallSuccess(String apexPackageName) {
|
||||
@Nullable
|
||||
String getApkInApexInstallError(String apexPackageName) {
|
||||
synchronized (mLock) {
|
||||
Preconditions.checkState(mPackageNameToApexModuleName != null,
|
||||
"APEX packages have not been scanned");
|
||||
String moduleName = mPackageNameToApexModuleName.get(apexPackageName);
|
||||
if (moduleName == null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return !mErrorWithApkInApex.contains(moduleName);
|
||||
return mErrorWithApkInApex.get(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1273,13 +1277,14 @@ public abstract class ApexManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
void reportErrorWithApkInApex(String scanDirPath) {
|
||||
void reportErrorWithApkInApex(String scanDirPath, String errorMsg) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isApkInApexInstallSuccess(String apexPackageName) {
|
||||
return true;
|
||||
@Nullable
|
||||
String getApkInApexInstallError(String apexPackageName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11824,6 +11824,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
|
||||
Throwable throwable = parseResult.throwable;
|
||||
int errorCode = PackageManager.INSTALL_SUCCEEDED;
|
||||
String errorMsg = null;
|
||||
|
||||
if (throwable == null) {
|
||||
// TODO(toddke): move lower in the scan chain
|
||||
@@ -11836,20 +11837,22 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
currentTime, null);
|
||||
} catch (PackageManagerException e) {
|
||||
errorCode = e.error;
|
||||
Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
|
||||
errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage();
|
||||
Slog.w(TAG, errorMsg);
|
||||
}
|
||||
} else if (throwable instanceof PackageParserException) {
|
||||
PackageParserException e = (PackageParserException)
|
||||
throwable;
|
||||
errorCode = e.error;
|
||||
Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage());
|
||||
errorMsg = "Failed to parse " + parseResult.scanFile + ": " + e.getMessage();
|
||||
Slog.w(TAG, errorMsg);
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected exception occurred while parsing "
|
||||
+ parseResult.scanFile, throwable);
|
||||
}
|
||||
|
||||
if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0 && errorCode != INSTALL_SUCCEEDED) {
|
||||
mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath());
|
||||
mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath(), errorMsg);
|
||||
}
|
||||
|
||||
// Delete invalid userdata apps
|
||||
|
||||
@@ -425,9 +425,10 @@ public class StagingManager {
|
||||
|
||||
for (StagedSession apexSession : apexSessions) {
|
||||
String packageName = apexSession.getPackageName();
|
||||
if (!mApexManager.isApkInApexInstallSuccess(packageName)) {
|
||||
String errorMsg = mApexManager.getApkInApexInstallError(packageName);
|
||||
if (errorMsg != null) {
|
||||
throw new PackageManagerException(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
|
||||
"Failed to install apk-in-apex of " + packageName);
|
||||
"Failed to install apk-in-apex of " + packageName + " : " + errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -955,12 +956,17 @@ public class StagingManager {
|
||||
continue;
|
||||
} else if (isApexSessionFailed(apexSession)) {
|
||||
hasFailedApexSession = true;
|
||||
String errorMsg = "APEX activation failed. " + apexSession.errorMessage;
|
||||
if (!TextUtils.isEmpty(apexSession.crashingNativeProcess)) {
|
||||
prepareForLoggingApexdRevert(session, apexSession.crashingNativeProcess);
|
||||
errorMsg = "Session reverted due to crashing native process: "
|
||||
+ apexSession.crashingNativeProcess;
|
||||
}
|
||||
String errorMsg = "APEX activation failed.";
|
||||
final String reasonForRevert = getReasonForRevert();
|
||||
if (!TextUtils.isEmpty(reasonForRevert)) {
|
||||
errorMsg += " Reason: " + reasonForRevert;
|
||||
} else if (!TextUtils.isEmpty(apexSession.errorMessage)) {
|
||||
errorMsg += " Error: " + apexSession.errorMessage;
|
||||
}
|
||||
Slog.d(TAG, errorMsg);
|
||||
session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
|
||||
continue;
|
||||
} else if (apexSession.isActivated || apexSession.isSuccess) {
|
||||
|
||||
@@ -311,7 +311,7 @@ public class StagingManagerTest {
|
||||
assertThat(apexSession1.getErrorCode())
|
||||
.isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
|
||||
assertThat(apexSession1.getErrorMessage()).isEqualTo("APEX activation failed. "
|
||||
+ "Failed for test");
|
||||
+ "Error: Failed for test");
|
||||
|
||||
assertThat(apexSession2.getErrorCode())
|
||||
.isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
|
||||
|
||||
@@ -286,9 +286,11 @@ public class ApexManagerTest {
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
assertThat(mApexManager.isApkInApexInstallSuccess(activeApex.apexModuleName)).isTrue();
|
||||
mApexManager.reportErrorWithApkInApex(activeApex.apexDirectory.getAbsolutePath());
|
||||
assertThat(mApexManager.isApkInApexInstallSuccess(activeApex.apexModuleName)).isFalse();
|
||||
assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName)).isNull();
|
||||
mApexManager.reportErrorWithApkInApex(activeApex.apexDirectory.getAbsolutePath(),
|
||||
"Some random error");
|
||||
assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName))
|
||||
.isEqualTo("Some random error");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user