Loading services/core/java/com/android/server/pm/BackgroundDexOptService.java +23 −9 Original line number Diff line number Diff line Loading @@ -92,6 +92,8 @@ public final class BackgroundDexOptService { new ComponentName("android", BackgroundDexOptJobService.class.getName()); // Possible return codes of individual optimization steps. /** Initial value. */ public static final int STATUS_UNSPECIFIED = -1; /** Ok status: Optimizations finished, All packages were processed, can continue */ public static final int STATUS_OK = 0; /** Optimizations should be aborted. Job scheduler requested it. */ Loading @@ -108,16 +110,20 @@ public final class BackgroundDexOptService { * job will exclude those failed packages. */ public static final int STATUS_DEX_OPT_FAILED = 5; /** Encountered fatal error, such as a runtime exception. */ public static final int STATUS_FATAL_ERROR = 6; @IntDef(prefix = {"STATUS_"}, value = { STATUS_UNSPECIFIED, STATUS_OK, STATUS_ABORT_BY_CANCELLATION, STATUS_ABORT_NO_SPACE_LEFT, STATUS_ABORT_THERMAL, STATUS_ABORT_BATTERY, STATUS_DEX_OPT_FAILED, STATUS_FATAL_ERROR, }) @Retention(RetentionPolicy.SOURCE) public @interface Status {} Loading Loading @@ -153,7 +159,7 @@ public final class BackgroundDexOptService { // True if JobScheduler invocations of dexopt have been disabled. @GuardedBy("mLock") private boolean mDisableJobSchedulerJobs; @GuardedBy("mLock") @Status private int mLastExecutionStatus = STATUS_OK; @GuardedBy("mLock") @Status private int mLastExecutionStatus = STATUS_UNSPECIFIED; @GuardedBy("mLock") private long mLastExecutionStartUptimeMs; @GuardedBy("mLock") private long mLastExecutionDurationMs; Loading Loading @@ -561,18 +567,26 @@ public final class BackgroundDexOptService { private boolean runIdleOptimization( PackageManagerService pm, List<String> pkgs, boolean isPostBootUpdate) { synchronized (mLock) { mLastExecutionStatus = STATUS_UNSPECIFIED; mLastExecutionStartUptimeMs = SystemClock.uptimeMillis(); mLastExecutionDurationMs = -1; } int status = STATUS_UNSPECIFIED; try { long lowStorageThreshold = getLowStorageThreshold(); int status = idleOptimizePackages(pm, pkgs, lowStorageThreshold, isPostBootUpdate); status = idleOptimizePackages(pm, pkgs, lowStorageThreshold, isPostBootUpdate); logStatus(status); return status == STATUS_OK || status == STATUS_DEX_OPT_FAILED; } catch (RuntimeException e) { status = STATUS_FATAL_ERROR; throw e; } finally { synchronized (mLock) { mLastExecutionStatus = status; mLastExecutionDurationMs = SystemClock.uptimeMillis() - mLastExecutionStartUptimeMs; } return status == STATUS_OK || status == STATUS_DEX_OPT_FAILED; } } /** Gets the size of the directory. It uses recursion to go over all files. */ Loading services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java +6 −2 Original line number Diff line number Diff line Loading @@ -303,7 +303,9 @@ public class ArtStatsLogUtils { } private static final Map<Integer, Integer> STATUS_MAP = Map.of(BackgroundDexOptService.STATUS_OK, Map.of(BackgroundDexOptService.STATUS_UNSPECIFIED, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_UNKNOWN, BackgroundDexOptService.STATUS_OK, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_JOB_FINISHED, BackgroundDexOptService.STATUS_ABORT_BY_CANCELLATION, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_BY_CANCELLATION, Loading @@ -314,7 +316,9 @@ public class ArtStatsLogUtils { BackgroundDexOptService.STATUS_ABORT_BATTERY, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_BATTERY, BackgroundDexOptService.STATUS_DEX_OPT_FAILED, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_JOB_FINISHED); ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_JOB_FINISHED, BackgroundDexOptService.STATUS_FATAL_ERROR, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_FATAL_ERROR); /** Helper class to write background dexopt job stats to statsd. */ public static class BackgroundDexoptJobStatsLogger { Loading services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java +26 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.pm; import static com.android.server.pm.BackgroundDexOptService.STATUS_DEX_OPT_FAILED; import static com.android.server.pm.BackgroundDexOptService.STATUS_FATAL_ERROR; import static com.android.server.pm.BackgroundDexOptService.STATUS_OK; import static com.google.common.truth.Truth.assertThat; Loading @@ -24,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; Loading Loading @@ -263,6 +265,20 @@ public final class BackgroundDexOptServiceUnitTest { assertThat(getFailedPackageNamesSecondary()).isEmpty(); } @Test public void testIdleJobFullRunWithFatalError() { initUntilBootCompleted(); runFullJob(mJobServiceForPostBoot, mJobParametersForPostBoot, /* expectedReschedule= */ false, /* expectedStatus= */ STATUS_OK, /* totalJobFinishedWithParams= */ 1, /* expectedSkippedPackage= */ null); doThrow(RuntimeException.class).when(mDexOptHelper).performDexOptWithStatus(any()); runFullJob(mJobServiceForIdle, mJobParametersForIdle, /* expectedReschedule= */ false, /* expectedStatus= */ STATUS_FATAL_ERROR, /* totalJobFinishedWithParams= */ 1, /* expectedSkippedPackage= */ null); } @Test public void testSystemReadyWhenDisabled() { when(mInjector.isBackgroundDexOptDisabled()).thenReturn(true); Loading Loading @@ -510,13 +526,21 @@ public final class BackgroundDexOptServiceUnitTest { ArgumentCaptor<Runnable> argThreadRunnable = ArgumentCaptor.forClass(Runnable.class); verify(mInjector, atLeastOnce()).createAndStartThread(any(), argThreadRunnable.capture()); try { argThreadRunnable.getValue().run(); } catch (RuntimeException e) { if (expectedStatus != STATUS_FATAL_ERROR) { throw e; } } verify(jobService, times(totalJobFinishedWithParams)).jobFinished(params, expectedReschedule); // Never block verify(mDexOptHelper, never()).controlDexOptBlocking(true); if (expectedStatus != STATUS_FATAL_ERROR) { verifyPerformDexOpt(); } assertThat(getLastExecutionStatus()).isEqualTo(expectedStatus); } Loading Loading
services/core/java/com/android/server/pm/BackgroundDexOptService.java +23 −9 Original line number Diff line number Diff line Loading @@ -92,6 +92,8 @@ public final class BackgroundDexOptService { new ComponentName("android", BackgroundDexOptJobService.class.getName()); // Possible return codes of individual optimization steps. /** Initial value. */ public static final int STATUS_UNSPECIFIED = -1; /** Ok status: Optimizations finished, All packages were processed, can continue */ public static final int STATUS_OK = 0; /** Optimizations should be aborted. Job scheduler requested it. */ Loading @@ -108,16 +110,20 @@ public final class BackgroundDexOptService { * job will exclude those failed packages. */ public static final int STATUS_DEX_OPT_FAILED = 5; /** Encountered fatal error, such as a runtime exception. */ public static final int STATUS_FATAL_ERROR = 6; @IntDef(prefix = {"STATUS_"}, value = { STATUS_UNSPECIFIED, STATUS_OK, STATUS_ABORT_BY_CANCELLATION, STATUS_ABORT_NO_SPACE_LEFT, STATUS_ABORT_THERMAL, STATUS_ABORT_BATTERY, STATUS_DEX_OPT_FAILED, STATUS_FATAL_ERROR, }) @Retention(RetentionPolicy.SOURCE) public @interface Status {} Loading Loading @@ -153,7 +159,7 @@ public final class BackgroundDexOptService { // True if JobScheduler invocations of dexopt have been disabled. @GuardedBy("mLock") private boolean mDisableJobSchedulerJobs; @GuardedBy("mLock") @Status private int mLastExecutionStatus = STATUS_OK; @GuardedBy("mLock") @Status private int mLastExecutionStatus = STATUS_UNSPECIFIED; @GuardedBy("mLock") private long mLastExecutionStartUptimeMs; @GuardedBy("mLock") private long mLastExecutionDurationMs; Loading Loading @@ -561,18 +567,26 @@ public final class BackgroundDexOptService { private boolean runIdleOptimization( PackageManagerService pm, List<String> pkgs, boolean isPostBootUpdate) { synchronized (mLock) { mLastExecutionStatus = STATUS_UNSPECIFIED; mLastExecutionStartUptimeMs = SystemClock.uptimeMillis(); mLastExecutionDurationMs = -1; } int status = STATUS_UNSPECIFIED; try { long lowStorageThreshold = getLowStorageThreshold(); int status = idleOptimizePackages(pm, pkgs, lowStorageThreshold, isPostBootUpdate); status = idleOptimizePackages(pm, pkgs, lowStorageThreshold, isPostBootUpdate); logStatus(status); return status == STATUS_OK || status == STATUS_DEX_OPT_FAILED; } catch (RuntimeException e) { status = STATUS_FATAL_ERROR; throw e; } finally { synchronized (mLock) { mLastExecutionStatus = status; mLastExecutionDurationMs = SystemClock.uptimeMillis() - mLastExecutionStartUptimeMs; } return status == STATUS_OK || status == STATUS_DEX_OPT_FAILED; } } /** Gets the size of the directory. It uses recursion to go over all files. */ Loading
services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java +6 −2 Original line number Diff line number Diff line Loading @@ -303,7 +303,9 @@ public class ArtStatsLogUtils { } private static final Map<Integer, Integer> STATUS_MAP = Map.of(BackgroundDexOptService.STATUS_OK, Map.of(BackgroundDexOptService.STATUS_UNSPECIFIED, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_UNKNOWN, BackgroundDexOptService.STATUS_OK, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_JOB_FINISHED, BackgroundDexOptService.STATUS_ABORT_BY_CANCELLATION, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_BY_CANCELLATION, Loading @@ -314,7 +316,9 @@ public class ArtStatsLogUtils { BackgroundDexOptService.STATUS_ABORT_BATTERY, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_BATTERY, BackgroundDexOptService.STATUS_DEX_OPT_FAILED, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_JOB_FINISHED); ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_JOB_FINISHED, BackgroundDexOptService.STATUS_FATAL_ERROR, ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_FATAL_ERROR); /** Helper class to write background dexopt job stats to statsd. */ public static class BackgroundDexoptJobStatsLogger { Loading
services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java +26 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.pm; import static com.android.server.pm.BackgroundDexOptService.STATUS_DEX_OPT_FAILED; import static com.android.server.pm.BackgroundDexOptService.STATUS_FATAL_ERROR; import static com.android.server.pm.BackgroundDexOptService.STATUS_OK; import static com.google.common.truth.Truth.assertThat; Loading @@ -24,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; Loading Loading @@ -263,6 +265,20 @@ public final class BackgroundDexOptServiceUnitTest { assertThat(getFailedPackageNamesSecondary()).isEmpty(); } @Test public void testIdleJobFullRunWithFatalError() { initUntilBootCompleted(); runFullJob(mJobServiceForPostBoot, mJobParametersForPostBoot, /* expectedReschedule= */ false, /* expectedStatus= */ STATUS_OK, /* totalJobFinishedWithParams= */ 1, /* expectedSkippedPackage= */ null); doThrow(RuntimeException.class).when(mDexOptHelper).performDexOptWithStatus(any()); runFullJob(mJobServiceForIdle, mJobParametersForIdle, /* expectedReschedule= */ false, /* expectedStatus= */ STATUS_FATAL_ERROR, /* totalJobFinishedWithParams= */ 1, /* expectedSkippedPackage= */ null); } @Test public void testSystemReadyWhenDisabled() { when(mInjector.isBackgroundDexOptDisabled()).thenReturn(true); Loading Loading @@ -510,13 +526,21 @@ public final class BackgroundDexOptServiceUnitTest { ArgumentCaptor<Runnable> argThreadRunnable = ArgumentCaptor.forClass(Runnable.class); verify(mInjector, atLeastOnce()).createAndStartThread(any(), argThreadRunnable.capture()); try { argThreadRunnable.getValue().run(); } catch (RuntimeException e) { if (expectedStatus != STATUS_FATAL_ERROR) { throw e; } } verify(jobService, times(totalJobFinishedWithParams)).jobFinished(params, expectedReschedule); // Never block verify(mDexOptHelper, never()).controlDexOptBlocking(true); if (expectedStatus != STATUS_FATAL_ERROR) { verifyPerformDexOpt(); } assertThat(getLastExecutionStatus()).isEqualTo(expectedStatus); } Loading