diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 9ff4aab83cffd..032b41f4bfcb1 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -253,7 +253,8 @@ public final class BackgroundDexOptService {
*
*
This is only for shell command and only root or shell user can use this.
*
- * @param packageNames dex optimize the passed packages or all packages if null
+ * @param packageNames dex optimize the passed packages in the given order, or all packages in
+ * the default order if null
*
* @return true if dex optimization is complete. false if the task is cancelled or if there was
* an error.
@@ -268,11 +269,11 @@ public final class BackgroundDexOptService {
resetStatesForNewDexOptRunLocked(Thread.currentThread());
}
PackageManagerService pm = mInjector.getPackageManagerService();
- ArraySet packagesToOptimize;
+ List packagesToOptimize;
if (packageNames == null) {
packagesToOptimize = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer());
} else {
- packagesToOptimize = new ArraySet<>(packageNames);
+ packagesToOptimize = packageNames;
}
return runIdleOptimization(pm, packagesToOptimize, /* isPostBootUpdate= */ false);
} finally {
@@ -335,7 +336,7 @@ public final class BackgroundDexOptService {
return false;
}
- ArraySet pkgs = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer());
+ List pkgs = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer());
if (pkgs.isEmpty()) {
Slog.i(TAG, "No packages to optimize");
markPostBootUpdateCompleted(params);
@@ -525,7 +526,7 @@ public final class BackgroundDexOptService {
}
/** Returns true if completed */
- private boolean runIdleOptimization(PackageManagerService pm, ArraySet pkgs,
+ private boolean runIdleOptimization(PackageManagerService pm, List pkgs,
boolean isPostBootUpdate) {
synchronized (mLock) {
mLastExecutionStartTimeMs = SystemClock.elapsedRealtime();
@@ -581,7 +582,7 @@ public final class BackgroundDexOptService {
}
@Status
- private int idleOptimizePackages(PackageManagerService pm, ArraySet pkgs,
+ private int idleOptimizePackages(PackageManagerService pm, List pkgs,
long lowStorageThreshold, boolean isPostBootUpdate) {
ArraySet updatedPackages = new ArraySet<>();
ArraySet updatedPackagesDueToSecondaryDex = new ArraySet<>();
@@ -640,7 +641,7 @@ public final class BackgroundDexOptService {
}
}
- pkgs = new ArraySet<>(pkgs);
+ pkgs = new ArrayList<>(pkgs);
pkgs.removeAll(unusedPackages);
}
}
@@ -670,7 +671,7 @@ public final class BackgroundDexOptService {
}
@Status
- private int optimizePackages(ArraySet pkgs, long lowStorageThreshold,
+ private int optimizePackages(List pkgs, long lowStorageThreshold,
boolean isForPrimaryDex, ArraySet updatedPackages, boolean isPostBootUpdate) {
for (String pkg : pkgs) {
int abortCode = abortIdleOptimizations(lowStorageThreshold);
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 50b2e23218864..bb2ba5cc498d1 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -293,8 +293,8 @@ final class DexOptHelper {
MetricsLogger.histogram(mPm.mContext, "opt_dialog_time_s", elapsedTimeSeconds);
}
- public ArraySet getOptimizablePackages(@NonNull Computer snapshot) {
- ArraySet pkgs = new ArraySet<>();
+ public List getOptimizablePackages(@NonNull Computer snapshot) {
+ ArrayList pkgs = new ArrayList<>();
mPm.forEachPackageState(snapshot, packageState -> {
final AndroidPackage pkg = packageState.getPkg();
if (pkg != null && mPm.mPackageDexOptimizer.canOptimizePackage(pkg)) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
index 6f503c7dd9418..b335749b7c174 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
@@ -19,7 +19,9 @@ package com.android.server.pm;
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.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
@@ -36,23 +38,21 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.HandlerThread;
import android.os.PowerManager;
-import android.util.ArraySet;
import com.android.server.LocalServices;
import com.android.server.PinnerService;
import com.android.server.pm.dex.DexManager;
-import com.android.server.pm.dex.DexoptOptions;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
@@ -66,9 +66,8 @@ public final class BackgroundDexOptServiceUnitTest {
private static final long TEST_WAIT_TIMEOUT_MS = 10_000;
- private static final ArraySet DEFAULT_PACKAGE_LIST = new ArraySet<>(
- Arrays.asList("aaa", "bbb"));
- private static final ArraySet EMPTY_PACKAGE_LIST = new ArraySet<>();
+ private static final List DEFAULT_PACKAGE_LIST = List.of("aaa", "bbb");
+ private static final List EMPTY_PACKAGE_LIST = List.of();
@Mock
private Context mContext;
@@ -418,26 +417,14 @@ public final class BackgroundDexOptServiceUnitTest {
verifyPerformDexOpt(DEFAULT_PACKAGE_LIST, totalJobRuns);
}
- private void verifyPerformDexOpt(ArraySet pkgs, int expectedRuns) {
- ArgumentCaptor dexOptOptions = ArgumentCaptor.forClass(DexoptOptions.class);
- verify(mDexOptHelper, atLeastOnce()).performDexOptWithStatus(dexOptOptions.capture());
- HashMap primaryPkgs = new HashMap<>(); // K: pkg, V: dexopt runs left
- for (String pkg : pkgs) {
- primaryPkgs.put(pkg, expectedRuns);
- }
-
- for (DexoptOptions opt : dexOptOptions.getAllValues()) {
- assertThat(pkgs).contains(opt.getPackageName());
- assertThat(opt.isDexoptOnlySecondaryDex()).isFalse();
- Integer count = primaryPkgs.get(opt.getPackageName());
- assertThat(count).isNotNull();
- if (count == 1) {
- primaryPkgs.remove(opt.getPackageName());
- } else {
- primaryPkgs.put(opt.getPackageName(), count - 1);
+ private void verifyPerformDexOpt(List pkgs, int expectedRuns) {
+ InOrder inOrder = inOrder(mDexOptHelper);
+ for (int i = 0; i < expectedRuns; i++) {
+ for (String pkg : pkgs) {
+ inOrder.verify(mDexOptHelper, times(1)).performDexOptWithStatus(argThat((option) ->
+ option.getPackageName().equals(pkg) && !option.isDexoptOnlySecondaryDex()));
}
}
- assertThat(primaryPkgs).isEmpty();
}
private static class StartAndWaitThread extends Thread {