Merge "Propagate error while scanning apk-in-apex to session object" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
929235fb71
@@ -67,6 +67,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@@ -306,17 +307,19 @@ public abstract class ApexManager {
|
|||||||
/**
|
/**
|
||||||
* Reports error raised during installation of apk-in-apex.
|
* 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
|
* Returns null if there were no errors when installing apk-in-apex inside
|
||||||
* {@param apexPackageName}, otherwise false.
|
* {@param apexPackageName}, otherwise returns the error as string
|
||||||
*
|
*
|
||||||
* @param apexPackageName Package name of the apk container of apex
|
* @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.
|
* Returns list of {@code packageName} of apks inside the given apex.
|
||||||
@@ -438,7 +441,7 @@ public abstract class ApexManager {
|
|||||||
* inside {@code apexModuleName}.
|
* inside {@code apexModuleName}.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private Set<String> mErrorWithApkInApex = new ArraySet<>();
|
private Map<String, String> mErrorWithApkInApex = new ArrayMap<>();
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private List<PackageInfo> mAllPackagesCache;
|
private List<PackageInfo> mAllPackagesCache;
|
||||||
@@ -841,26 +844,27 @@ public abstract class ApexManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void reportErrorWithApkInApex(String scanDirPath) {
|
void reportErrorWithApkInApex(String scanDirPath, String errorMsg) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
for (ActiveApexInfo aai : mActiveApexInfosCache) {
|
for (ActiveApexInfo aai : mActiveApexInfosCache) {
|
||||||
if (scanDirPath.startsWith(aai.apexDirectory.getAbsolutePath())) {
|
if (scanDirPath.startsWith(aai.apexDirectory.getAbsolutePath())) {
|
||||||
mErrorWithApkInApex.add(aai.apexModuleName);
|
mErrorWithApkInApex.put(aai.apexModuleName, errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isApkInApexInstallSuccess(String apexPackageName) {
|
@Nullable
|
||||||
|
String getApkInApexInstallError(String apexPackageName) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
Preconditions.checkState(mPackageNameToApexModuleName != null,
|
Preconditions.checkState(mPackageNameToApexModuleName != null,
|
||||||
"APEX packages have not been scanned");
|
"APEX packages have not been scanned");
|
||||||
String moduleName = mPackageNameToApexModuleName.get(apexPackageName);
|
String moduleName = mPackageNameToApexModuleName.get(apexPackageName);
|
||||||
if (moduleName == null) {
|
if (moduleName == null) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
return !mErrorWithApkInApex.contains(moduleName);
|
return mErrorWithApkInApex.get(moduleName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1273,13 +1277,14 @@ public abstract class ApexManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void reportErrorWithApkInApex(String scanDirPath) {
|
void reportErrorWithApkInApex(String scanDirPath, String errorMsg) {
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isApkInApexInstallSuccess(String apexPackageName) {
|
@Nullable
|
||||||
return true;
|
String getApkInApexInstallError(String apexPackageName) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -11824,6 +11824,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
|
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
|
||||||
Throwable throwable = parseResult.throwable;
|
Throwable throwable = parseResult.throwable;
|
||||||
int errorCode = PackageManager.INSTALL_SUCCEEDED;
|
int errorCode = PackageManager.INSTALL_SUCCEEDED;
|
||||||
|
String errorMsg = null;
|
||||||
|
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
// TODO(toddke): move lower in the scan chain
|
// TODO(toddke): move lower in the scan chain
|
||||||
@@ -11836,20 +11837,22 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
currentTime, null);
|
currentTime, null);
|
||||||
} catch (PackageManagerException e) {
|
} catch (PackageManagerException e) {
|
||||||
errorCode = e.error;
|
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) {
|
} else if (throwable instanceof PackageParserException) {
|
||||||
PackageParserException e = (PackageParserException)
|
PackageParserException e = (PackageParserException)
|
||||||
throwable;
|
throwable;
|
||||||
errorCode = e.error;
|
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 {
|
} else {
|
||||||
throw new IllegalStateException("Unexpected exception occurred while parsing "
|
throw new IllegalStateException("Unexpected exception occurred while parsing "
|
||||||
+ parseResult.scanFile, throwable);
|
+ parseResult.scanFile, throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0 && errorCode != INSTALL_SUCCEEDED) {
|
if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0 && errorCode != INSTALL_SUCCEEDED) {
|
||||||
mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath());
|
mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath(), errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete invalid userdata apps
|
// Delete invalid userdata apps
|
||||||
|
|||||||
@@ -425,9 +425,10 @@ public class StagingManager {
|
|||||||
|
|
||||||
for (StagedSession apexSession : apexSessions) {
|
for (StagedSession apexSession : apexSessions) {
|
||||||
String packageName = apexSession.getPackageName();
|
String packageName = apexSession.getPackageName();
|
||||||
if (!mApexManager.isApkInApexInstallSuccess(packageName)) {
|
String errorMsg = mApexManager.getApkInApexInstallError(packageName);
|
||||||
|
if (errorMsg != null) {
|
||||||
throw new PackageManagerException(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
|
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;
|
continue;
|
||||||
} else if (isApexSessionFailed(apexSession)) {
|
} else if (isApexSessionFailed(apexSession)) {
|
||||||
hasFailedApexSession = true;
|
hasFailedApexSession = true;
|
||||||
String errorMsg = "APEX activation failed. " + apexSession.errorMessage;
|
|
||||||
if (!TextUtils.isEmpty(apexSession.crashingNativeProcess)) {
|
if (!TextUtils.isEmpty(apexSession.crashingNativeProcess)) {
|
||||||
prepareForLoggingApexdRevert(session, 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);
|
session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
|
||||||
continue;
|
continue;
|
||||||
} else if (apexSession.isActivated || apexSession.isSuccess) {
|
} else if (apexSession.isActivated || apexSession.isSuccess) {
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ public class StagingManagerTest {
|
|||||||
assertThat(apexSession1.getErrorCode())
|
assertThat(apexSession1.getErrorCode())
|
||||||
.isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
|
.isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
|
||||||
assertThat(apexSession1.getErrorMessage()).isEqualTo("APEX activation failed. "
|
assertThat(apexSession1.getErrorMessage()).isEqualTo("APEX activation failed. "
|
||||||
+ "Failed for test");
|
+ "Error: Failed for test");
|
||||||
|
|
||||||
assertThat(apexSession2.getErrorCode())
|
assertThat(apexSession2.getErrorCode())
|
||||||
.isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
|
.isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
|
||||||
|
|||||||
@@ -286,9 +286,11 @@ public class ApexManagerTest {
|
|||||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||||
ParallelPackageParser.makeExecutorService());
|
ParallelPackageParser.makeExecutorService());
|
||||||
|
|
||||||
assertThat(mApexManager.isApkInApexInstallSuccess(activeApex.apexModuleName)).isTrue();
|
assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName)).isNull();
|
||||||
mApexManager.reportErrorWithApkInApex(activeApex.apexDirectory.getAbsolutePath());
|
mApexManager.reportErrorWithApkInApex(activeApex.apexDirectory.getAbsolutePath(),
|
||||||
assertThat(mApexManager.isApkInApexInstallSuccess(activeApex.apexModuleName)).isFalse();
|
"Some random error");
|
||||||
|
assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName))
|
||||||
|
.isEqualTo("Some random error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user