summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libartservice/service/java/com/android/server/art/Dexopter.java13
-rw-r--r--libartservice/service/java/com/android/server/art/PrimaryDexopter.java11
-rw-r--r--libartservice/service/java/com/android/server/art/SecondaryDexopter.java6
-rw-r--r--libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java9
-rw-r--r--libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java37
5 files changed, 76 insertions, 0 deletions
diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java
index b8aa912723..5185f59b20 100644
--- a/libartservice/service/java/com/android/server/art/Dexopter.java
+++ b/libartservice/service/java/com/android/server/art/Dexopter.java
@@ -118,6 +118,14 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
continue;
}
+ if (mInjector.isPreReboot() && !isDexFileFound(dexInfo)) {
+ // In the pre-reboot case, it's possible that a dex file doesn't exist in the
+ // new system image. Although code below can gracefully handle failures, those
+ // failures can be red herrings in metrics and bug reports, so we skip
+ // non-existing dex files to avoid them.
+ continue;
+ }
+
DexMetadataInfo dmInfo =
mInjector.getDexMetadataHelper().getDexMetadataInfo(buildDmPath(dexInfo));
@@ -639,6 +647,11 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
protected abstract boolean isDexFilePublic(@NonNull DexInfoType dexInfo);
/**
+ * Returns true if the dex file is found.
+ */
+ protected abstract boolean isDexFileFound(@NonNull DexInfoType dexInfo);
+
+ /**
* Returns a list of external profiles (e.g., a DM profile) that the reference profile can be
* initialized from, in the order of preference.
*/
diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
index e4475d8503..f8234c4df9 100644
--- a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
+++ b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
@@ -118,6 +118,17 @@ public class PrimaryDexopter extends Dexopter<DetailedPrimaryDexInfo> {
}
@Override
+ protected boolean isDexFileFound(@NonNull DetailedPrimaryDexInfo dexInfo) {
+ try {
+ return mInjector.getArtd().getDexFileVisibility(dexInfo.dexPath())
+ != FileVisibility.NOT_FOUND;
+ } catch (ServiceSpecificException | RemoteException e) {
+ AsLog.e("Failed to get visibility of " + dexInfo.dexPath(), e);
+ return false;
+ }
+ }
+
+ @Override
@NonNull
protected List<ProfilePath> getExternalProfiles(@NonNull DetailedPrimaryDexInfo dexInfo) {
return PrimaryDexUtils.getExternalProfiles(dexInfo);
diff --git a/libartservice/service/java/com/android/server/art/SecondaryDexopter.java b/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
index 07c6c0d654..57fe174d6a 100644
--- a/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
+++ b/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
@@ -87,6 +87,12 @@ public class SecondaryDexopter extends Dexopter<CheckedSecondaryDexInfo> {
}
@Override
+ protected boolean isDexFileFound(@NonNull CheckedSecondaryDexInfo dexInfo) {
+ // `getDexInfoList` has already excluded non-existing dex files.
+ return true;
+ }
+
+ @Override
@NonNull
protected List<ProfilePath> getExternalProfiles(@NonNull CheckedSecondaryDexInfo dexInfo) {
// A secondary dex file doesn't have any external profile to use.
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index 864390c217..2304d5c180 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -311,6 +311,15 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase {
.when(mDexMetadataHelperInjector.openZipFile(any()))
.thenThrow(NoSuchFileException.class);
+ if (mParams.mIsPreReboot) {
+ doReturn(FileVisibility.OTHER_READABLE)
+ .when(mArtd)
+ .getDexFileVisibility("/somewhere/app/foo/base.apk");
+ doReturn(FileVisibility.OTHER_READABLE)
+ .when(mArtd)
+ .getDexFileVisibility("/somewhere/app/foo/split_0.apk");
+ }
+
// The first one is normal.
doReturn(dexoptIsNeeded())
.when(mArtd)
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
index beb8c1eaf4..eb90b49e4a 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
@@ -140,6 +140,13 @@ public class PrimaryDexopterTest extends PrimaryDexopterTestBase {
.when(mArtd.createCancellationSignal())
.thenReturn(mock(IArtdCancellationSignal.class));
+ lenient()
+ .when(mArtd.getDexFileVisibility(mDexPath))
+ .thenReturn(FileVisibility.OTHER_READABLE);
+ lenient()
+ .when(mArtd.getDexFileVisibility(mSplit0DexPath))
+ .thenReturn(FileVisibility.OTHER_READABLE);
+
mPrimaryDexopter =
new PrimaryDexopter(mInjector, mPkgState, mPkg, mDexoptParams, mCancellationSignal);
@@ -850,6 +857,36 @@ public class PrimaryDexopterTest extends PrimaryDexopterTestBase {
.isEqualTo(0);
}
+ @Test
+ public void testDexoptPreRebootDexNotFound() throws Exception {
+ when(mInjector.isPreReboot()).thenReturn(true);
+ doReturn(FileVisibility.NOT_FOUND).when(mArtd).getDexFileVisibility(mDexPath);
+ doReturn(FileVisibility.NOT_FOUND).when(mArtd).getDexFileVisibility(mSplit0DexPath);
+
+ mPrimaryDexopter =
+ new PrimaryDexopter(mInjector, mPkgState, mPkg, mDexoptParams, mCancellationSignal);
+
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ assertThat(results).hasSize(0);
+ }
+
+ @Test
+ public void testDexoptPreRebootSomeDexNotFound() throws Exception {
+ when(mInjector.isPreReboot()).thenReturn(true);
+ doReturn(FileVisibility.OTHER_READABLE).when(mArtd).getDexFileVisibility(mDexPath);
+ doReturn(FileVisibility.NOT_FOUND).when(mArtd).getDexFileVisibility(mSplit0DexPath);
+
+ mPrimaryDexopter =
+ new PrimaryDexopter(mInjector, mPkgState, mPkg, mDexoptParams, mCancellationSignal);
+
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ assertThat(results).hasSize(2);
+ assertThat(results.get(0).getDexContainerFile()).isEqualTo(mDexPath);
+ assertThat(results.get(0).getAbi()).isEqualTo("arm64-v8a");
+ assertThat(results.get(1).getDexContainerFile()).isEqualTo(mDexPath);
+ assertThat(results.get(1).getAbi()).isEqualTo("armeabi-v7a");
+ }
+
private void checkDexoptWithProfile(IArtd artd, String dexPath, String isa, ProfilePath profile,
boolean isOtherReadable) throws Exception {
artd.dexopt(argThat(artifacts