Use an ordered list for optimizable packages.
This allows us to order optimizable packages in the future. Bug: 218666049 Test: atest FrameworksMockingServicesTests:BackgroundDexOptServiceUnitTest Change-Id: Iee87cf41d269024132fd4c35a05e3bf40532c2a0
This commit is contained in:
@@ -253,7 +253,8 @@ public final class BackgroundDexOptService {
|
||||
*
|
||||
* <p>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<String> packagesToOptimize;
|
||||
List<String> 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<String> pkgs = mDexOptHelper.getOptimizablePackages(pm.snapshotComputer());
|
||||
List<String> 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<String> pkgs,
|
||||
private boolean runIdleOptimization(PackageManagerService pm, List<String> pkgs,
|
||||
boolean isPostBootUpdate) {
|
||||
synchronized (mLock) {
|
||||
mLastExecutionStartTimeMs = SystemClock.elapsedRealtime();
|
||||
@@ -581,7 +582,7 @@ public final class BackgroundDexOptService {
|
||||
}
|
||||
|
||||
@Status
|
||||
private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
|
||||
private int idleOptimizePackages(PackageManagerService pm, List<String> pkgs,
|
||||
long lowStorageThreshold, boolean isPostBootUpdate) {
|
||||
ArraySet<String> updatedPackages = new ArraySet<>();
|
||||
ArraySet<String> 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<String> pkgs, long lowStorageThreshold,
|
||||
private int optimizePackages(List<String> pkgs, long lowStorageThreshold,
|
||||
boolean isForPrimaryDex, ArraySet<String> updatedPackages, boolean isPostBootUpdate) {
|
||||
for (String pkg : pkgs) {
|
||||
int abortCode = abortIdleOptimizations(lowStorageThreshold);
|
||||
|
||||
@@ -293,8 +293,8 @@ final class DexOptHelper {
|
||||
MetricsLogger.histogram(mPm.mContext, "opt_dialog_time_s", elapsedTimeSeconds);
|
||||
}
|
||||
|
||||
public ArraySet<String> getOptimizablePackages(@NonNull Computer snapshot) {
|
||||
ArraySet<String> pkgs = new ArraySet<>();
|
||||
public List<String> getOptimizablePackages(@NonNull Computer snapshot) {
|
||||
ArrayList<String> pkgs = new ArrayList<>();
|
||||
mPm.forEachPackageState(snapshot, packageState -> {
|
||||
final AndroidPackage pkg = packageState.getPkg();
|
||||
if (pkg != null && mPm.mPackageDexOptimizer.canOptimizePackage(pkg)) {
|
||||
|
||||
@@ -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<String> DEFAULT_PACKAGE_LIST = new ArraySet<>(
|
||||
Arrays.asList("aaa", "bbb"));
|
||||
private static final ArraySet<String> EMPTY_PACKAGE_LIST = new ArraySet<>();
|
||||
private static final List<String> DEFAULT_PACKAGE_LIST = List.of("aaa", "bbb");
|
||||
private static final List<String> 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<String> pkgs, int expectedRuns) {
|
||||
ArgumentCaptor<DexoptOptions> dexOptOptions = ArgumentCaptor.forClass(DexoptOptions.class);
|
||||
verify(mDexOptHelper, atLeastOnce()).performDexOptWithStatus(dexOptOptions.capture());
|
||||
HashMap<String, Integer> 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<String> 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 {
|
||||
|
||||
Reference in New Issue
Block a user