Loading services/core/java/com/android/server/pm/ApexManager.java +19 −14 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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; Loading Loading @@ -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); } } } } Loading Loading @@ -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 Loading services/core/java/com/android/server/pm/PackageManagerService.java +6 −3 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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 services/core/java/com/android/server/pm/StagingManager.java +11 −5 Original line number Original line Diff line number Diff line Loading @@ -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); } } } } } } Loading Loading @@ -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) { Loading services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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); Loading services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +5 −3 Original line number Original line Diff line number Diff line Loading @@ -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"); } } /** /** Loading Loading
services/core/java/com/android/server/pm/ApexManager.java +19 −14 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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; Loading Loading @@ -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); } } } } Loading Loading @@ -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 Loading
services/core/java/com/android/server/pm/PackageManagerService.java +6 −3 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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
services/core/java/com/android/server/pm/StagingManager.java +11 −5 Original line number Original line Diff line number Diff line Loading @@ -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); } } } } } } Loading Loading @@ -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) { Loading
services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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); Loading
services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +5 −3 Original line number Original line Diff line number Diff line Loading @@ -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"); } } /** /** Loading