Dexopt launcher on boot after mainline update.
Bug: 269140736
Test: atest ArtServiceTests
Ignore-AOSP-First: ART Services.
Change-Id: I46b8f0a9bc1f94f7926aa616440d1efebcf7d7a7
(cherry picked from commit 296bff69ead68553800eff41fa30d49654b32d78)
Merged-In: I46b8f0a9bc1f94f7926aa616440d1efebcf7d7a7
diff --git a/libartservice/service/Android.bp b/libartservice/service/Android.bp
index a34e9e8..ad2033a 100644
--- a/libartservice/service/Android.bp
+++ b/libartservice/service/Android.bp
@@ -73,6 +73,7 @@
libs: [
"androidx.annotation_annotation",
"auto_value_annotations",
+ "sdk_module-lib_current_framework-permission-s",
// TODO(b/256866172): Transitive dependency, for r8 only.
"framework-statsd.stubs.module_lib",
// TODO(b/256866172): Transitive dependency, for r8 only. This module
diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
index bba7b9e..2f4fe7c 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -28,7 +28,6 @@
import static com.android.server.art.model.Config.Callback;
import static com.android.server.art.model.DexoptStatus.DexContainerFileDexoptStatus;
-import android.R;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -997,8 +996,9 @@
switch (reason) {
case ReasonMapping.REASON_BOOT_AFTER_MAINLINE_UPDATE:
- packages = packages.filter(
- pkgState -> mInjector.isSystemUiPackage(pkgState.getPackageName()));
+ packages = packages.filter(pkgState
+ -> mInjector.isSystemUiPackage(pkgState.getPackageName())
+ || mInjector.isLauncherPackage(pkgState.getPackageName()));
break;
case ReasonMapping.REASON_INACTIVE:
packages = filterAndSortByLastActiveTime(
@@ -1249,9 +1249,12 @@
LocalManagerRegistry.getManager(DexUseManagerLocal.class));
}
- @NonNull
public boolean isSystemUiPackage(@NonNull String packageName) {
- return packageName.equals(mContext.getString(R.string.config_systemUi));
+ return Utils.isSystemUiPackage(mContext, packageName);
+ }
+
+ public boolean isLauncherPackage(@NonNull String packageName) {
+ return Utils.isLauncherPackage(mContext, packageName);
}
public long getCurrentTimeMillis() {
diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java
index acc797b..24ba783 100644
--- a/libartservice/service/java/com/android/server/art/Dexopter.java
+++ b/libartservice/service/java/com/android/server/art/Dexopter.java
@@ -26,6 +26,7 @@
import android.R;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.role.RoleManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.CancellationSignal;
@@ -279,6 +280,10 @@
}
}
+ if (mInjector.isLauncherPackage(mPkgState.getPackageName())) {
+ return "speed-profile";
+ }
+
// We force vmSafeMode on debuggable apps as well:
// - the runtime ignores their compiled code
// - they generally have lots of methods that could make the compiler used run out of
@@ -656,7 +661,11 @@
}
public boolean isSystemUiPackage(@NonNull String packageName) {
- return packageName.equals(mContext.getString(R.string.config_systemUi));
+ return Utils.isSystemUiPackage(mContext, packageName);
+ }
+
+ public boolean isLauncherPackage(@NonNull String packageName) {
+ return Utils.isLauncherPackage(mContext, packageName);
}
@NonNull
diff --git a/libartservice/service/java/com/android/server/art/Utils.java b/libartservice/service/java/com/android/server/art/Utils.java
index a8ed9f7..fd377c1 100644
--- a/libartservice/service/java/com/android/server/art/Utils.java
+++ b/libartservice/service/java/com/android/server/art/Utils.java
@@ -16,10 +16,13 @@
package com.android.server.art;
+import android.R;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
+import android.app.role.RoleManager;
import android.apphibernation.AppHibernationManager;
+import android.content.Context;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserManager;
@@ -302,6 +305,15 @@
}
}
+ public static boolean isSystemUiPackage(@NonNull Context context, @NonNull String packageName) {
+ return packageName.equals(context.getString(R.string.config_systemUi));
+ }
+
+ public static boolean isLauncherPackage(@NonNull Context context, @NonNull String packageName) {
+ RoleManager roleManager = context.getSystemService(RoleManager.class);
+ return roleManager.getRoleHolders(RoleManager.ROLE_HOME).contains(packageName);
+ }
+
@AutoValue
public abstract static class Abi {
static @NonNull Abi create(
diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
index 239006f..eff8505 100644
--- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
@@ -95,8 +95,8 @@
@SmallTest
@RunWith(Parameterized.class)
public class ArtManagerLocalTest {
- private static final String PKG_NAME = "com.example.foo";
- private static final String PKG_NAME_SYS_UI = "com.android.systemui";
+ private static final String PKG_NAME_1 = "com.example.foo";
+ private static final String PKG_NAME_2 = "com.android.bar";
private static final String PKG_NAME_HIBERNATING = "com.example.hibernating";
private static final int INACTIVE_DAYS = 1;
private static final long CURRENT_TIME_MS = 10000000000l;
@@ -118,8 +118,8 @@
@Mock private UserManager mUserManager;
@Mock private DexUseManagerLocal mDexUseManager;
@Mock private StorageManager mStorageManager;
- private PackageState mPkgState;
- private AndroidPackage mPkg;
+ private PackageState mPkgState1;
+ private AndroidPackage mPkg1;
private Config mConfig;
// True if the primary dex'es are in a readonly partition.
@@ -146,7 +146,7 @@
lenient().when(mInjector.getAppHibernationManager()).thenReturn(mAppHibernationManager);
lenient().when(mInjector.getUserManager()).thenReturn(mUserManager);
lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false);
- lenient().when(mInjector.isSystemUiPackage(PKG_NAME_SYS_UI)).thenReturn(true);
+ lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false);
lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
lenient().when(mInjector.getCurrentTimeMillis()).thenReturn(CURRENT_TIME_MS);
lenient().when(mInjector.getStorageManager()).thenReturn(mStorageManager);
@@ -193,11 +193,14 @@
// All packages are by default recently used.
lenient().when(mDexUseManager.getPackageLastUsedAtMs(any())).thenReturn(RECENT_TIME_MS);
List<DetailedSecondaryDexInfo> secondaryDexInfo = createSecondaryDexInfo();
- lenient().doReturn(secondaryDexInfo).when(mDexUseManager).getSecondaryDexInfo(eq(PKG_NAME));
lenient()
.doReturn(secondaryDexInfo)
.when(mDexUseManager)
- .getFilteredDetailedSecondaryDexInfo(eq(PKG_NAME));
+ .getSecondaryDexInfo(eq(PKG_NAME_1));
+ lenient()
+ .doReturn(secondaryDexInfo)
+ .when(mDexUseManager)
+ .getFilteredDetailedSecondaryDexInfo(eq(PKG_NAME_1));
simulateStorageNotLow();
@@ -211,8 +214,8 @@
var packageStateMap = pkgStates.stream().collect(
Collectors.toMap(PackageState::getPackageName, it -> it));
lenient().when(mSnapshot.getPackageStates()).thenReturn(packageStateMap);
- mPkgState = mSnapshot.getPackageState(PKG_NAME);
- mPkg = mPkgState.getAndroidPackage();
+ mPkgState1 = mSnapshot.getPackageState(PKG_NAME_1);
+ mPkg1 = mPkgState1.getAndroidPackage();
mArtManagerLocal = new ArtManagerLocal(mInjector);
}
@@ -221,7 +224,7 @@
public void testdeleteDexoptArtifacts() throws Exception {
when(mArtd.deleteArtifacts(any())).thenReturn(1l);
- DeleteResult result = mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME);
+ DeleteResult result = mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME_1);
assertThat(result.getFreedBytes()).isEqualTo(5);
verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
@@ -247,7 +250,7 @@
when(mArtd.deleteArtifacts(any())).thenReturn(1l);
- DeleteResult result = mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME);
+ DeleteResult result = mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME_1);
assertThat(result.getFreedBytes()).isEqualTo(5);
verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
@@ -268,14 +271,14 @@
public void testdeleteDexoptArtifactsPackageNotFound() throws Exception {
when(mSnapshot.getPackageState(anyString())).thenReturn(null);
- mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME);
+ mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME_1);
}
@Test(expected = IllegalArgumentException.class)
public void testdeleteDexoptArtifactsNoPackage() throws Exception {
- when(mPkgState.getAndroidPackage()).thenReturn(null);
+ when(mPkgState1.getAndroidPackage()).thenReturn(null);
- mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME);
+ mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME_1);
}
@Test
@@ -300,7 +303,7 @@
.when(mArtd)
.getDexoptStatus("/data/user/0/foo/1.apk", "arm64", "CLC");
- DexoptStatus result = mArtManagerLocal.getDexoptStatus(mSnapshot, PKG_NAME);
+ DexoptStatus result = mArtManagerLocal.getDexoptStatus(mSnapshot, PKG_NAME_1);
assertThat(result.getDexContainerFileDexoptStatuses())
.comparingElementsUsing(TestingUtils.<DexContainerFileDexoptStatus>deepEquality())
@@ -326,14 +329,14 @@
public void testGetDexoptStatusPackageNotFound() throws Exception {
when(mSnapshot.getPackageState(anyString())).thenReturn(null);
- mArtManagerLocal.getDexoptStatus(mSnapshot, PKG_NAME);
+ mArtManagerLocal.getDexoptStatus(mSnapshot, PKG_NAME_1);
}
@Test(expected = IllegalArgumentException.class)
public void testGetDexoptStatusNoPackage() throws Exception {
- when(mPkgState.getAndroidPackage()).thenReturn(null);
+ when(mPkgState1.getAndroidPackage()).thenReturn(null);
- mArtManagerLocal.getDexoptStatus(mSnapshot, PKG_NAME);
+ mArtManagerLocal.getDexoptStatus(mSnapshot, PKG_NAME_1);
}
@Test
@@ -341,7 +344,7 @@
when(mArtd.getDexoptStatus(any(), any(), any()))
.thenThrow(new ServiceSpecificException(1 /* errorCode */, "some error message"));
- DexoptStatus result = mArtManagerLocal.getDexoptStatus(mSnapshot, PKG_NAME);
+ DexoptStatus result = mArtManagerLocal.getDexoptStatus(mSnapshot, PKG_NAME_1);
List<DexContainerFileDexoptStatus> statuses = result.getDexContainerFileDexoptStatuses();
assertThat(statuses.size()).isEqualTo(5);
@@ -355,14 +358,14 @@
@Test
public void testClearAppProfiles() throws Exception {
- mArtManagerLocal.clearAppProfiles(mSnapshot, PKG_NAME);
+ mArtManagerLocal.clearAppProfiles(mSnapshot, PKG_NAME_1);
verify(mArtd).deleteProfile(
- deepEq(AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "primary")));
+ deepEq(AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_1, "primary")));
verify(mArtd).deleteProfile(deepEq(
- AidlUtils.buildProfilePathForPrimaryCur(0 /* userId */, PKG_NAME, "primary")));
+ AidlUtils.buildProfilePathForPrimaryCur(0 /* userId */, PKG_NAME_1, "primary")));
verify(mArtd).deleteProfile(deepEq(
- AidlUtils.buildProfilePathForPrimaryCur(1 /* userId */, PKG_NAME, "primary")));
+ AidlUtils.buildProfilePathForPrimaryCur(1 /* userId */, PKG_NAME_1, "primary")));
verify(mArtd).deleteProfile(
deepEq(AidlUtils.buildProfilePathForSecondaryRef("/data/user/0/foo/1.apk")));
@@ -374,14 +377,14 @@
public void testClearAppProfilesPackageNotFound() throws Exception {
when(mSnapshot.getPackageState(anyString())).thenReturn(null);
- mArtManagerLocal.clearAppProfiles(mSnapshot, PKG_NAME);
+ mArtManagerLocal.clearAppProfiles(mSnapshot, PKG_NAME_1);
}
@Test(expected = IllegalArgumentException.class)
public void testClearAppProfilesNoPackage() throws Exception {
- when(mPkgState.getAndroidPackage()).thenReturn(null);
+ when(mPkgState1.getAndroidPackage()).thenReturn(null);
- mArtManagerLocal.clearAppProfiles(mSnapshot, PKG_NAME);
+ mArtManagerLocal.clearAppProfiles(mSnapshot, PKG_NAME_1);
}
@Test
@@ -390,11 +393,12 @@
var result = mock(DexoptResult.class);
var cancellationSignal = new CancellationSignal();
- when(mDexoptHelper.dexopt(any(), deepEq(List.of(PKG_NAME)), same(params),
+ when(mDexoptHelper.dexopt(any(), deepEq(List.of(PKG_NAME_1)), same(params),
same(cancellationSignal), any()))
.thenReturn(result);
- assertThat(mArtManagerLocal.dexoptPackage(mSnapshot, PKG_NAME, params, cancellationSignal))
+ assertThat(
+ mArtManagerLocal.dexoptPackage(mSnapshot, PKG_NAME_1, params, cancellationSignal))
.isSameInstanceAs(result);
}
@@ -404,18 +408,18 @@
var cancellationSignal = new CancellationSignal();
when(mDexoptHelper.dexopt(
- any(), deepEq(List.of(PKG_NAME)), any(), same(cancellationSignal), any()))
+ any(), deepEq(List.of(PKG_NAME_1)), any(), same(cancellationSignal), any()))
.thenReturn(result);
- assertThat(mArtManagerLocal.resetDexoptStatus(mSnapshot, PKG_NAME, cancellationSignal))
+ assertThat(mArtManagerLocal.resetDexoptStatus(mSnapshot, PKG_NAME_1, cancellationSignal))
.isSameInstanceAs(result);
verify(mArtd).deleteProfile(
- deepEq(AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "primary")));
+ deepEq(AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_1, "primary")));
verify(mArtd).deleteProfile(deepEq(
- AidlUtils.buildProfilePathForPrimaryCur(0 /* userId */, PKG_NAME, "primary")));
+ AidlUtils.buildProfilePathForPrimaryCur(0 /* userId */, PKG_NAME_1, "primary")));
verify(mArtd).deleteProfile(deepEq(
- AidlUtils.buildProfilePathForPrimaryCur(1 /* userId */, PKG_NAME, "primary")));
+ AidlUtils.buildProfilePathForPrimaryCur(1 /* userId */, PKG_NAME_1, "primary")));
verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
"/data/app/foo/base.apk", "arm64", mIsInReadonlyPartition)));
@@ -439,14 +443,14 @@
public void testDexoptPackages() throws Exception {
var dexoptResult = mock(DexoptResult.class);
var cancellationSignal = new CancellationSignal();
- when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME_SYS_UI)).thenReturn(CURRENT_TIME_MS);
+ when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME_2)).thenReturn(CURRENT_TIME_MS);
simulateStorageLow();
// It should use the default package list and params. The list is sorted by last active
// time in descending order.
doReturn(dexoptResult)
.when(mDexoptHelper)
- .dexopt(any(), deepEq(List.of(PKG_NAME_SYS_UI, PKG_NAME)),
+ .dexopt(any(), deepEq(List.of(PKG_NAME_2, PKG_NAME_1)),
argThat(params -> params.getReason().equals("bg-dexopt")),
same(cancellationSignal), any(), any(), any());
@@ -463,25 +467,25 @@
@Test
public void testDexoptPackagesRecentlyInstalled() throws Exception {
// The package is recently installed but hasn't been used.
- PackageUserState userState = mPkgState.getStateForUser(UserHandle.of(1));
+ PackageUserState userState = mPkgState1.getStateForUser(UserHandle.of(1));
when(userState.getFirstInstallTimeMillis()).thenReturn(RECENT_TIME_MS);
- when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME)).thenReturn(0l);
+ when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME_1)).thenReturn(0l);
simulateStorageLow();
var result = mock(DexoptResult.class);
var cancellationSignal = new CancellationSignal();
- // PKG_NAME should be dexopted.
+ // PKG_NAME_1 should be dexopted.
doReturn(result)
.when(mDexoptHelper)
- .dexopt(any(), inAnyOrder(PKG_NAME, PKG_NAME_SYS_UI),
+ .dexopt(any(), inAnyOrder(PKG_NAME_1, PKG_NAME_2),
argThat(params -> params.getReason().equals("bg-dexopt")), any(), any(),
any(), any());
mArtManagerLocal.dexoptPackages(mSnapshot, "bg-dexopt", cancellationSignal,
null /* processCallbackExecutor */, null /* processCallback */);
- // PKG_NAME should not be downgraded.
+ // PKG_NAME_1 should not be downgraded.
verify(mDexoptHelper, never())
.dexopt(any(), any(), argThat(params -> params.getReason().equals("inactive")),
any(), any(), any(), any());
@@ -489,26 +493,26 @@
@Test
public void testDexoptPackagesInactive() throws Exception {
- // PKG_NAME is neither recently installed nor recently used.
- PackageUserState userState = mPkgState.getStateForUser(UserHandle.of(1));
+ // PKG_NAME_1 is neither recently installed nor recently used.
+ PackageUserState userState = mPkgState1.getStateForUser(UserHandle.of(1));
when(userState.getFirstInstallTimeMillis()).thenReturn(NOT_RECENT_TIME_MS);
- when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME)).thenReturn(NOT_RECENT_TIME_MS);
+ when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME_1)).thenReturn(NOT_RECENT_TIME_MS);
simulateStorageLow();
var result = mock(DexoptResult.class);
var cancellationSignal = new CancellationSignal();
- // PKG_NAME should not be dexopted.
+ // PKG_NAME_1 should not be dexopted.
doReturn(result)
.when(mDexoptHelper)
- .dexopt(any(), deepEq(List.of(PKG_NAME_SYS_UI)),
+ .dexopt(any(), deepEq(List.of(PKG_NAME_2)),
argThat(params -> params.getReason().equals("bg-dexopt")), any(), any(),
any(), any());
- // PKG_NAME should be downgraded.
+ // PKG_NAME_1 should be downgraded.
doReturn(result)
.when(mDexoptHelper)
- .dexopt(any(), deepEq(List.of(PKG_NAME)),
+ .dexopt(any(), deepEq(List.of(PKG_NAME_1)),
argThat(params -> params.getReason().equals("inactive")), any(), any(),
any(), any());
@@ -518,25 +522,25 @@
@Test
public void testDexoptPackagesInactiveStorageNotLow() throws Exception {
- // PKG_NAME is neither recently installed nor recently used.
- PackageUserState userState = mPkgState.getStateForUser(UserHandle.of(1));
+ // PKG_NAME_1 is neither recently installed nor recently used.
+ PackageUserState userState = mPkgState1.getStateForUser(UserHandle.of(1));
when(userState.getFirstInstallTimeMillis()).thenReturn(NOT_RECENT_TIME_MS);
- when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME)).thenReturn(NOT_RECENT_TIME_MS);
+ when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME_1)).thenReturn(NOT_RECENT_TIME_MS);
var result = mock(DexoptResult.class);
var cancellationSignal = new CancellationSignal();
- // PKG_NAME should not be dexopted.
+ // PKG_NAME_1 should not be dexopted.
doReturn(result)
.when(mDexoptHelper)
- .dexopt(any(), deepEq(List.of(PKG_NAME_SYS_UI)),
+ .dexopt(any(), deepEq(List.of(PKG_NAME_2)),
argThat(params -> params.getReason().equals("bg-dexopt")), any(), any(),
any(), any());
mArtManagerLocal.dexoptPackages(mSnapshot, "bg-dexopt", cancellationSignal,
null /* processCallbackExecutor */, null /* processCallback */);
- // PKG_NAME should not be downgraded because the storage is not low.
+ // PKG_NAME_1 should not be downgraded because the storage is not low.
verify(mDexoptHelper, never())
.dexopt(any(), any(), argThat(params -> params.getReason().equals("inactive")),
any(), any(), any(), any());
@@ -546,17 +550,37 @@
public void testDexoptPackagesBootAfterMainlineUpdate() throws Exception {
var result = mock(DexoptResult.class);
var cancellationSignal = new CancellationSignal();
- simulateStorageLow();
- // It should only dexopt system UI.
+ lenient().when(mInjector.isSystemUiPackage(PKG_NAME_1)).thenReturn(true);
+ lenient().when(mInjector.isLauncherPackage(PKG_NAME_2)).thenReturn(true);
+
+ // It should dexopt the system UI and the launcher.
when(mDexoptHelper.dexopt(
- any(), deepEq(List.of(PKG_NAME_SYS_UI)), any(), any(), any(), any(), any()))
+ any(), inAnyOrder(PKG_NAME_1, PKG_NAME_2), any(), any(), any(), any(), any()))
.thenReturn(result);
- assertThat(mArtManagerLocal.dexoptPackages(mSnapshot, "boot-after-mainline-update",
- cancellationSignal, null /* processCallbackExecutor */,
- null /* processCallback */))
- .isSameInstanceAs(result);
+ mArtManagerLocal.dexoptPackages(mSnapshot, "boot-after-mainline-update", cancellationSignal,
+ null /* processCallbackExecutor */, null /* processCallback */);
+ }
+
+ @Test
+ public void testDexoptPackagesBootAfterMainlineUpdatePackagesNotFound() throws Exception {
+ var result = mock(DexoptResult.class);
+ var cancellationSignal = new CancellationSignal();
+ // PKG_NAME_1 is neither recently installed nor recently used.
+ PackageUserState userState = mPkgState1.getStateForUser(UserHandle.of(1));
+ lenient().when(userState.getFirstInstallTimeMillis()).thenReturn(NOT_RECENT_TIME_MS);
+ lenient()
+ .when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME_1))
+ .thenReturn(NOT_RECENT_TIME_MS);
+ simulateStorageLow();
+
+ // It should dexopt the system UI and the launcher, but they are not found.
+ when(mDexoptHelper.dexopt(any(), deepEq(List.of()), any(), any(), any(), any(), any()))
+ .thenReturn(result);
+
+ mArtManagerLocal.dexoptPackages(mSnapshot, "boot-after-mainline-update", cancellationSignal,
+ null /* processCallbackExecutor */, null /* processCallback */);
// It should never downgrade apps, even if the storage is low.
verify(mDexoptHelper, never())
@@ -566,10 +590,10 @@
@Test
public void testDexoptPackagesOverride() throws Exception {
- // PKG_NAME is neither recently installed nor recently used.
- PackageUserState userState = mPkgState.getStateForUser(UserHandle.of(1));
+ // PKG_NAME_1 is neither recently installed nor recently used.
+ PackageUserState userState = mPkgState1.getStateForUser(UserHandle.of(1));
when(userState.getFirstInstallTimeMillis()).thenReturn(NOT_RECENT_TIME_MS);
- when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME)).thenReturn(NOT_RECENT_TIME_MS);
+ when(mDexUseManager.getPackageLastUsedAtMs(PKG_NAME_1)).thenReturn(NOT_RECENT_TIME_MS);
simulateStorageLow();
var params = new DexoptParams.Builder("bg-dexopt").build();
@@ -579,21 +603,22 @@
mArtManagerLocal.setBatchDexoptStartCallback(ForkJoinPool.commonPool(),
(snapshot, reason, defaultPackages, builder, passedSignal) -> {
assertThat(reason).isEqualTo("bg-dexopt");
- assertThat(defaultPackages).containsExactly(PKG_NAME_SYS_UI);
+ assertThat(defaultPackages).containsExactly(PKG_NAME_2);
assertThat(passedSignal).isSameInstanceAs(cancellationSignal);
- builder.setPackages(List.of(PKG_NAME)).setDexoptParams(params);
+ builder.setPackages(List.of(PKG_NAME_1)).setDexoptParams(params);
});
// It should use the overridden package list and params.
doReturn(result)
.when(mDexoptHelper)
- .dexopt(any(), deepEq(List.of(PKG_NAME)), same(params), any(), any(), any(), any());
+ .dexopt(any(), deepEq(List.of(PKG_NAME_1)), same(params), any(), any(), any(),
+ any());
mArtManagerLocal.dexoptPackages(mSnapshot, "bg-dexopt", cancellationSignal,
null /* processCallbackExecutor */, null /* processCallback */);
- // It should not downgrade PKG_NAME because it's in the overridden package list. It should
- // not downgrade PKG_NAME_SYS_UI either because it's not an inactive package.
+ // It should not downgrade PKG_NAME_1 because it's in the overridden package list. It should
+ // not downgrade PKG_NAME_2 either because it's not an inactive package.
verify(mDexoptHelper, never())
.dexopt(any(), any(), argThat(params2 -> params2.getReason().equals("inactive")),
any(), any(), any(), any());
@@ -607,12 +632,12 @@
mArtManagerLocal.setBatchDexoptStartCallback(ForkJoinPool.commonPool(),
(snapshot, reason, defaultPackages, builder, passedSignal) -> {
- builder.setPackages(List.of(PKG_NAME)).setDexoptParams(params);
+ builder.setPackages(List.of(PKG_NAME_1)).setDexoptParams(params);
});
mArtManagerLocal.clearBatchDexoptStartCallback();
// It should use the default package list and params.
- when(mDexoptHelper.dexopt(any(), inAnyOrder(PKG_NAME, PKG_NAME_SYS_UI), not(same(params)),
+ when(mDexoptHelper.dexopt(any(), inAnyOrder(PKG_NAME_1, PKG_NAME_2), not(same(params)),
same(cancellationSignal), any(), any(), any()))
.thenReturn(result);
@@ -645,13 +670,13 @@
tempFile.deleteOnExit();
when(mArtd.mergeProfiles(
- deepEq(List.of(AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "primary"),
+ deepEq(List.of(AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_1, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
- 0 /* userId */, PKG_NAME, "primary"),
+ 0 /* userId */, PKG_NAME_1, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
- 1 /* userId */, PKG_NAME, "primary"))),
+ 1 /* userId */, PKG_NAME_1, "primary"))),
isNull(),
- deepEq(AidlUtils.buildOutputProfileForPrimary(PKG_NAME, "primary",
+ deepEq(AidlUtils.buildOutputProfileForPrimary(PKG_NAME_1, "primary",
Process.SYSTEM_UID, Process.SYSTEM_UID, false /* isPublic */)),
deepEq(List.of("/data/app/foo/base.apk")), deepEq(options)))
.thenAnswer(invocation -> {
@@ -666,7 +691,7 @@
});
ParcelFileDescriptor fd =
- mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME, null /* splitName */);
+ mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME_1, null /* splitName */);
verify(mArtd).deleteProfile(
argThat(profile -> profile.getTmpProfilePath().tmpPath.equals(tempFile.getPath())));
@@ -680,18 +705,18 @@
@Test
public void testSnapshotAppProfileSplit() throws Exception {
when(mArtd.mergeProfiles(deepEq(List.of(AidlUtils.buildProfilePathForPrimaryRef(
- PKG_NAME, "split_0.split"),
+ PKG_NAME_1, "split_0.split"),
AidlUtils.buildProfilePathForPrimaryCur(
- 0 /* userId */, PKG_NAME, "split_0.split"),
+ 0 /* userId */, PKG_NAME_1, "split_0.split"),
AidlUtils.buildProfilePathForPrimaryCur(
- 1 /* userId */, PKG_NAME, "split_0.split"))),
+ 1 /* userId */, PKG_NAME_1, "split_0.split"))),
isNull(),
- deepEq(AidlUtils.buildOutputProfileForPrimary(PKG_NAME, "split_0.split",
+ deepEq(AidlUtils.buildOutputProfileForPrimary(PKG_NAME_1, "split_0.split",
Process.SYSTEM_UID, Process.SYSTEM_UID, false /* isPublic */)),
deepEq(List.of("/data/app/foo/split_0.apk")), any()))
.thenReturn(false);
- mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME, "split_0");
+ mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME_1, "split_0");
}
@Test
@@ -699,7 +724,7 @@
when(mArtd.mergeProfiles(any(), any(), any(), any(), any())).thenReturn(false);
ParcelFileDescriptor fd =
- mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME, null /* splitName */);
+ mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME_1, null /* splitName */);
verify(mArtd, never()).deleteProfile(any());
@@ -712,19 +737,19 @@
public void testSnapshotAppProfilePackageNotFound() throws Exception {
when(mSnapshot.getPackageState(anyString())).thenReturn(null);
- mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME, null /* splitName */);
+ mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME_1, null /* splitName */);
}
@Test(expected = IllegalArgumentException.class)
public void testSnapshotAppProfileNoPackage() throws Exception {
- when(mPkgState.getAndroidPackage()).thenReturn(null);
+ when(mPkgState1.getAndroidPackage()).thenReturn(null);
- mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME, null /* splitName */);
+ mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME_1, null /* splitName */);
}
@Test(expected = IllegalArgumentException.class)
public void testSnapshotAppProfileSplitNotFound() throws Exception {
- mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME, "non-existent-split");
+ mArtManagerLocal.snapshotAppProfile(mSnapshot, PKG_NAME_1, "non-existent-split");
}
@Test
@@ -736,7 +761,7 @@
.thenReturn(false); // A non-empty merge is tested in `testSnapshotAppProfile`.
ParcelFileDescriptor fd = mArtManagerLocal.dumpAppProfile(
- mSnapshot, PKG_NAME, null /* splitName */, false /* dumpClassesAndMethods */);
+ mSnapshot, PKG_NAME_1, null /* splitName */, false /* dumpClassesAndMethods */);
}
@Test
@@ -748,7 +773,7 @@
.thenReturn(false); // A non-empty merge is tested in `testSnapshotAppProfile`.
ParcelFileDescriptor fd = mArtManagerLocal.dumpAppProfile(
- mSnapshot, PKG_NAME, null /* splitName */, true /* dumpClassesAndMethods */);
+ mSnapshot, PKG_NAME_1, null /* splitName */, true /* dumpClassesAndMethods */);
}
@Test
@@ -769,21 +794,21 @@
0 /* userId */, "android", "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
1 /* userId */, "android", "primary"),
- AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "primary"),
+ AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_1, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
- 0 /* userId */, PKG_NAME, "primary"),
+ 0 /* userId */, PKG_NAME_1, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
- 1 /* userId */, PKG_NAME, "primary"),
- AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "split_0.split"),
+ 1 /* userId */, PKG_NAME_1, "primary"),
+ AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_1, "split_0.split"),
AidlUtils.buildProfilePathForPrimaryCur(
- 0 /* userId */, PKG_NAME, "split_0.split"),
+ 0 /* userId */, PKG_NAME_1, "split_0.split"),
AidlUtils.buildProfilePathForPrimaryCur(
- 1 /* userId */, PKG_NAME, "split_0.split"),
- AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_SYS_UI, "primary"),
+ 1 /* userId */, PKG_NAME_1, "split_0.split"),
+ AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_2, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
- 0 /* userId */, PKG_NAME_SYS_UI, "primary"),
+ 0 /* userId */, PKG_NAME_2, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
- 1 /* userId */, PKG_NAME_SYS_UI, "primary"),
+ 1 /* userId */, PKG_NAME_2, "primary"),
AidlUtils.buildProfilePathForPrimaryRef(
PKG_NAME_HIBERNATING, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
@@ -823,20 +848,20 @@
.when(mArtd)
.getDexoptStatus(eq("/data/app/foo/base.apk"), eq("arm"), any());
- when(mSnapshot.getPackageStates()).thenReturn(Map.of(PKG_NAME, mPkgState));
+ when(mSnapshot.getPackageStates()).thenReturn(Map.of(PKG_NAME_1, mPkgState1));
mArtManagerLocal.cleanup(mSnapshot);
verify(mArtd).cleanup(
- inAnyOrderDeepEquals(AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "primary"),
+ inAnyOrderDeepEquals(AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_1, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
- 0 /* userId */, PKG_NAME, "primary"),
+ 0 /* userId */, PKG_NAME_1, "primary"),
AidlUtils.buildProfilePathForPrimaryCur(
- 1 /* userId */, PKG_NAME, "primary"),
- AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "split_0.split"),
+ 1 /* userId */, PKG_NAME_1, "primary"),
+ AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME_1, "split_0.split"),
AidlUtils.buildProfilePathForPrimaryCur(
- 0 /* userId */, PKG_NAME, "split_0.split"),
+ 0 /* userId */, PKG_NAME_1, "split_0.split"),
AidlUtils.buildProfilePathForPrimaryCur(
- 1 /* userId */, PKG_NAME, "split_0.split"),
+ 1 /* userId */, PKG_NAME_1, "split_0.split"),
AidlUtils.buildProfilePathForSecondaryRef("/data/user/0/foo/1.apk"),
AidlUtils.buildProfilePathForSecondaryCur("/data/user/0/foo/1.apk")),
inAnyOrderDeepEquals(AidlUtils.buildArtifactsPath("/data/app/foo/base.apk", "arm64",
@@ -908,11 +933,11 @@
}
private List<PackageState> createPackageStates() {
- PackageState pkgState =
- createPackageState(PKG_NAME, true /* isDexoptable */, true /* multiSplit */);
+ PackageState pkgState1 =
+ createPackageState(PKG_NAME_1, true /* isDexoptable */, true /* multiSplit */);
- PackageState sysUiPkgState = createPackageState(
- PKG_NAME_SYS_UI, true /* isDexoptable */, false /* multiSplit */);
+ PackageState pkgState2 =
+ createPackageState(PKG_NAME_2, true /* isDexoptable */, false /* multiSplit */);
// This should not be dexopted because it's hibernating. However, it should be included
// when snapshotting boot image profile.
@@ -926,7 +951,7 @@
PackageState nonDexoptablePkgState = createPackageState(
"com.example.non-dexoptable", false /* isDexoptable */, false /* multiSplit */);
- return List.of(pkgState, sysUiPkgState, pkgHibernatingState, nonDexoptablePkgState);
+ return List.of(pkgState1, pkgState2, pkgHibernatingState, nonDexoptablePkgState);
}
private GetDexoptStatusResult createGetDexoptStatusResult(
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index 6340efc..f0ef8f5 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
@@ -49,6 +50,8 @@
import com.android.server.art.testing.OnSuccessRule;
import com.android.server.art.testing.TestingUtils;
+import dalvik.system.DexFile;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -56,6 +59,7 @@
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
+import org.mockito.ArgumentMatcher;
import java.util.ArrayList;
import java.util.List;
@@ -136,6 +140,11 @@
list.add(params);
params = new Params();
+ params.mIsLauncher = true;
+ params.mExpectedCompilerFilter = "speed-profile";
+ list.add(params);
+
+ params = new Params();
params.mForce = true;
params.mShouldDowngrade = false;
params.mExpectedDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_BETTER
@@ -169,6 +178,7 @@
super.setUp();
lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(mParams.mIsSystemUi);
+ lenient().when(mInjector.isLauncherPackage(any())).thenReturn(mParams.mIsLauncher);
lenient()
.when(SystemProperties.getBoolean(eq("dalvik.vm.always_debuggable"), anyBoolean()))
@@ -184,6 +194,14 @@
lenient().when(mPkgState.isSystem()).thenReturn(mParams.mIsSystem);
lenient().when(mPkgState.isUpdatedSystemApp()).thenReturn(mParams.mIsUpdatedSystemApp);
+ if (DexFile.isProfileGuidedCompilerFilter(mParams.mExpectedCompilerFilter)) {
+ // Make all profile-related operations succeed so that "speed-profile" doesn't fall back
+ // to "verify".
+ when(mArtd.isProfileUsable(any(), any())).thenReturn(true);
+ when(mArtd.getProfileVisibility(any())).thenReturn(FileVisibility.OTHER_READABLE);
+ when(mArtd.mergeProfiles(any(), any(), any(), any(), any())).thenReturn(false);
+ }
+
mDexoptParams =
new DexoptParams.Builder("install")
.setCompilerFilter(mParams.mRequestedCompilerFilter)
@@ -207,12 +225,12 @@
buildFsPermission(Process.SYSTEM_UID /* uid */, SHARED_GID /* gid */,
true /* isOtherReadable */),
null /* seContext */);
- DexoptOptions dexoptOptions = new DexoptOptions();
- dexoptOptions.compilationReason = "install";
- dexoptOptions.targetSdkVersion = 123;
- dexoptOptions.debuggable = mParams.mExpectedIsDebuggable;
- dexoptOptions.generateAppImage = false;
- dexoptOptions.hiddenApiPolicyEnabled = mParams.mExpectedIsHiddenApiPolicyEnabled;
+
+ // No need to check `generateAppImage`. It is checked in `PrimaryDexopterTest`.
+ ArgumentMatcher<DexoptOptions> dexoptOptionsMatcher = options
+ -> options.compilationReason.equals("install") && options.targetSdkVersion == 123
+ && options.debuggable == mParams.mExpectedIsDebuggable
+ && options.hiddenApiPolicyEnabled == mParams.mExpectedIsHiddenApiPolicyEnabled;
when(mArtd.createCancellationSignal()).thenReturn(mock(IArtdCancellationSignal.class));
when(mArtd.getDmFileVisibility(any())).thenReturn(FileVisibility.NOT_FOUND);
@@ -228,9 +246,9 @@
.dexopt(deepEq(buildOutputArtifacts("/data/app/foo/base.apk", "arm64",
mParams.mExpectedIsInDalvikCache, permissionSettings)),
eq("/data/app/foo/base.apk"), eq("arm64"), eq("PCL[]"),
- eq(mParams.mExpectedCompilerFilter), isNull() /* profile */,
+ eq(mParams.mExpectedCompilerFilter), any() /* profile */,
isNull() /* inputVdex */, isNull() /* dmFile */,
- eq(PriorityClass.INTERACTIVE), deepEq(dexoptOptions), any());
+ eq(PriorityClass.INTERACTIVE), argThat(dexoptOptionsMatcher), any());
// The second one fails on `dexopt`.
doReturn(dexoptIsNeeded())
@@ -242,9 +260,9 @@
.dexopt(deepEq(buildOutputArtifacts("/data/app/foo/base.apk", "arm",
mParams.mExpectedIsInDalvikCache, permissionSettings)),
eq("/data/app/foo/base.apk"), eq("arm"), eq("PCL[]"),
- eq(mParams.mExpectedCompilerFilter), isNull() /* profile */,
+ eq(mParams.mExpectedCompilerFilter), any() /* profile */,
isNull() /* inputVdex */, isNull() /* dmFile */,
- eq(PriorityClass.INTERACTIVE), deepEq(dexoptOptions), any());
+ eq(PriorityClass.INTERACTIVE), argThat(dexoptOptionsMatcher), any());
// The third one doesn't need dexopt.
doReturn(dexoptIsNotNeeded())
@@ -263,9 +281,9 @@
.dexopt(deepEq(buildOutputArtifacts("/data/app/foo/split_0.apk", "arm",
mParams.mExpectedIsInDalvikCache, permissionSettings)),
eq("/data/app/foo/split_0.apk"), eq("arm"), eq("PCL[base.apk]"),
- eq(mParams.mExpectedCompilerFilter), isNull() /* profile */,
+ eq(mParams.mExpectedCompilerFilter), any() /* profile */,
isNull() /* inputVdex */, isNull() /* dmFile */,
- eq(PriorityClass.INTERACTIVE), deepEq(dexoptOptions), any());
+ eq(PriorityClass.INTERACTIVE), argThat(dexoptOptionsMatcher), any());
assertThat(mPrimaryDexopter.dexopt())
.comparingElementsUsing(TestingUtils.<DexContainerFileDexoptResult>deepEquality())
@@ -304,6 +322,7 @@
public boolean mIsVmSafeMode = false;
public boolean mIsDebuggable = false;
public boolean mIsSystemUi = false;
+ public boolean mIsLauncher = false;
public boolean mIsUseEmbeddedDex = false;
// Options.
@@ -324,16 +343,30 @@
public boolean mExpectedIsHiddenApiPolicyEnabled = true;
public String toString() {
- return String.format("isSystem=%b,isUpdatedSystemApp=%b,mHiddenApiEnforcementPolicy=%d"
- + ",isVmSafeMode=%b,isDebuggable=%b,isSystemUi=%b,isUseEmbeddedDex=%b,"
- + "requestedCompilerFilter=%s,force=%b,shouldDowngrade=%b,"
- + "mSkipIfStorageLow=%b,alwaysDebuggable=%b => targetCompilerFilter=%s,"
- + "expectedDexoptTrigger=%d,expectedIsInDalvikCache=%b,"
- + "expectedIsDebuggable=%b,expectedIsHiddenApiPolicyEnabled=%b",
+ return String.format("isSystem=%b,"
+ + "isUpdatedSystemApp=%b,"
+ + "mHiddenApiEnforcementPolicy=%d,"
+ + "isVmSafeMode=%b,"
+ + "isDebuggable=%b,"
+ + "isSystemUi=%b,"
+ + "isLauncher=%b,"
+ + "isUseEmbeddedDex=%b,"
+ + "requestedCompilerFilter=%s,"
+ + "force=%b,"
+ + "shouldDowngrade=%b,"
+ + "mSkipIfStorageLow=%b,"
+ + "alwaysDebuggable=%b"
+ + " => "
+ + "targetCompilerFilter=%s,"
+ + "expectedDexoptTrigger=%d,"
+ + "expectedIsInDalvikCache=%b,"
+ + "expectedIsDebuggable=%b,"
+ + "expectedIsHiddenApiPolicyEnabled=%b",
mIsSystem, mIsUpdatedSystemApp, mHiddenApiEnforcementPolicy, mIsVmSafeMode,
- mIsDebuggable, mIsSystemUi, mIsUseEmbeddedDex, mRequestedCompilerFilter, mForce,
- mShouldDowngrade, mSkipIfStorageLow, mAlwaysDebuggable, mExpectedCompilerFilter,
- mExpectedDexoptTrigger, mExpectedIsInDalvikCache, mExpectedIsDebuggable,
+ mIsDebuggable, mIsSystemUi, mIsLauncher, mIsUseEmbeddedDex,
+ mRequestedCompilerFilter, mForce, mShouldDowngrade, mSkipIfStorageLow,
+ mAlwaysDebuggable, mExpectedCompilerFilter, mExpectedDexoptTrigger,
+ mExpectedIsInDalvikCache, mExpectedIsDebuggable,
mExpectedIsHiddenApiPolicyEnabled);
}
}
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
index 27babfa..3b94961 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
@@ -72,6 +72,7 @@
public void setUp() throws Exception {
lenient().when(mInjector.getArtd()).thenReturn(mArtd);
lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false);
+ lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false);
lenient().when(mInjector.getUserManager()).thenReturn(mUserManager);
lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
lenient().when(mInjector.getStorageManager()).thenReturn(mStorageManager);
diff --git a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
index 0f118a9..5d8661f 100644
--- a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
@@ -128,6 +128,7 @@
lenient().when(mInjector.getArtd()).thenReturn(mArtd);
lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false);
+ lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false);
lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
List<DetailedSecondaryDexInfo> secondaryDexInfo = createSecondaryDexInfo();