summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Stefano Cianciulli <scianciulli@google.com> 2024-09-09 11:11:30 +0000
committer Stefano Cianciulli <scianciulli@google.com> 2024-09-20 10:20:01 +0000
commit8a5ecf2f6734241f511a088a2a474674373924e7 (patch)
tree6241326480afab7db515b8af79f44adb8dbd9918
parenta303efff1731e5b7e9574a4e54701515a4c16d41 (diff)
Report dex2oat metrics to StatsD when dexopting
Bug: 327134025 Test: atest art_standalone_artd_tests && atest ArtServicesTest Change-Id: I4212899e78c23d8ff8c0307f9699f6b772c50000
-rw-r--r--artd/artd.cc25
-rw-r--r--artd/artd_test.cc22
-rw-r--r--artd/binder/com/android/server/art/IArtd.aidl14
-rw-r--r--libartservice/service/java/com/android/server/art/ArtManagerLocal.java17
-rw-r--r--libartservice/service/java/com/android/server/art/Dex2OatStatsReporter.java182
-rw-r--r--libartservice/service/java/com/android/server/art/DexMetadataHelper.java39
-rw-r--r--libartservice/service/java/com/android/server/art/DexoptHelper.java20
-rw-r--r--libartservice/service/java/com/android/server/art/Dexopter.java42
-rw-r--r--libartservice/service/java/com/android/server/art/PrimaryDexopter.java14
-rw-r--r--libartservice/service/java/com/android/server/art/SecondaryDexopter.java6
-rw-r--r--libartservice/service/java/com/android/server/art/model/DexMetadata.java49
-rw-r--r--libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java1
-rw-r--r--libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java2
-rw-r--r--libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java4
-rw-r--r--libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java2
-rw-r--r--libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java3
-rw-r--r--libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java3
-rw-r--r--odrefresh/odr_metrics_record.h3
-rw-r--r--runtime/exec_utils.h2
19 files changed, 394 insertions, 56 deletions
diff --git a/artd/artd.cc b/artd/artd.cc
index 44f11f366d..493cc10926 100644
--- a/artd/artd.cc
+++ b/artd/artd.cc
@@ -1171,22 +1171,33 @@ ndk::ScopedAStatus Artd::dexopt(
<< "\nOpened FDs: " << fd_logger;
ProcessStat stat;
- Result<int> result = ExecAndReturnCode(
- art_exec_args.Get(), kLongTimeoutSec, cancellation_signal->CreateExecCallbacks(), &stat);
+ std::string error_msg;
+ ExecResult result = exec_utils_->ExecAndReturnResult(art_exec_args.Get(),
+ kLongTimeoutSec,
+ cancellation_signal->CreateExecCallbacks(),
+ /*new_process_group=*/true,
+ &stat,
+ &error_msg);
_aidl_return->wallTimeMs = stat.wall_time_ms;
_aidl_return->cpuTimeMs = stat.cpu_time_ms;
- if (!result.ok()) {
+
+ auto result_info = ART_FORMAT("[status={},exit_code={},signal={}]",
+ static_cast<int>(result.status),
+ result.exit_code,
+ result.signal);
+ if (result.status != ExecResult::kExited) {
if (cancellation_signal->IsCancelled()) {
_aidl_return->cancelled = true;
return ScopedAStatus::ok();
}
- return NonFatal("Failed to run dex2oat: " + result.error().message());
+ return NonFatal(ART_FORMAT("Failed to run dex2oat: {} {}", error_msg, result_info));
}
- LOG(INFO) << ART_FORMAT("dex2oat returned code {}", result.value());
+ LOG(INFO) << ART_FORMAT("dex2oat returned code {}", result.exit_code);
- if (result.value() != 0) {
- return NonFatal(ART_FORMAT("dex2oat returned an unexpected code: {}", result.value()));
+ if (result.exit_code != 0) {
+ return NonFatal(
+ ART_FORMAT("dex2oat returned an unexpected code: {} {}", result.exit_code, result_info));
}
int64_t size_bytes = 0;
diff --git a/artd/artd_test.cc b/artd/artd_test.cc
index 1a53df714f..34950eee74 100644
--- a/artd/artd_test.cc
+++ b/artd/artd_test.cc
@@ -313,8 +313,9 @@ class MockExecUtils : public ExecUtils {
Result<int> code = DoExecAndReturnCode(arg_vector, callbacks, stat);
if (code.ok()) {
return {.status = ExecResult::kExited, .exit_code = code.value()};
+ } else {
+ return {.status = ExecResult::kSignaled, .signal = SIGKILL};
}
- return {.status = ExecResult::kUnknown};
}
MOCK_METHOD(Result<int>,
@@ -1113,14 +1114,29 @@ TEST_F(ArtdTest, dexoptAllResourceControlBackground) {
RunDexopt();
}
+TEST_F(ArtdTest, dexoptTerminatedBySignal) {
+ EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
+ .WillOnce(Return(Result<int>(Error())));
+ RunDexopt(AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
+ Property(&ndk::ScopedAStatus::getMessage,
+ HasSubstr(ART_FORMAT("[status={},exit_code=-1,signal={}]",
+ static_cast<int>(ExecResult::kSignaled),
+ SIGKILL)))));
+}
+
TEST_F(ArtdTest, dexoptFailed) {
dexopt_options_.generateAppImage = true;
+ constexpr int kExitCode = 135;
EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
.WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "new_oat")),
WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "new_vdex")),
WithArg<0>(WriteToFdFlag("--app-image-fd=", "new_art")),
- Return(1)));
- RunDexopt(EX_SERVICE_SPECIFIC);
+ Return(kExitCode)));
+ RunDexopt(AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
+ Property(&ndk::ScopedAStatus::getMessage,
+ HasSubstr(ART_FORMAT("[status={},exit_code={},signal=0]",
+ static_cast<int>(ExecResult::kExited),
+ kExitCode)))));
CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "old_oat");
CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "old_vdex");
diff --git a/artd/binder/com/android/server/art/IArtd.aidl b/artd/binder/com/android/server/art/IArtd.aidl
index 47fc89966b..75b634dffa 100644
--- a/artd/binder/com/android/server/art/IArtd.aidl
+++ b/artd/binder/com/android/server/art/IArtd.aidl
@@ -155,7 +155,19 @@ interface IArtd {
/**
* Dexopts a dex file for the given instruction set.
*
- * Throws fatal and non-fatal errors.
+ * Throws fatal and non-fatal errors. When dexopt fails, the non-fatal status includes an error
+ * message containing a substring formatted as:
+ * [status=%STATUS%,exit_code=%EXIT_CODE%,signal=%SIGNAL%]
+ * where %STATUS% is the integer value of the corresponding ExecResultStatus enumeration defined
+ * in frameworks/proto_logging/stats/enums/art/common_enums.proto,
+ * %EXIT_CODE% is the exit code for the dex2oat process and set only when %STATUS% is set to
+ * EXEC_RESULT_STATUS_EXITED (-1 otherwsie),
+ * and %SIGNAL% is the signal that interrupted the dex2oat
+ * process and set only when %STATUS% is EXEC_RESULT_STATUS_SIGNALED (0 otherwise).
+ *
+ * The purpose of this format is to share information about the dex2oat run result with the
+ * ArtService code in Java that orchestrates the dexopt process, so that it can be reported to
+ * StatsD.
*/
com.android.server.art.ArtdDexoptResult dexopt(
in com.android.server.art.OutputArtifacts outputArtifacts,
diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
index 61d3b159c7..8436fd1095 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -20,7 +20,6 @@ import static com.android.server.art.ArtFileManager.ProfileLists;
import static com.android.server.art.ArtFileManager.UsableArtifactLists;
import static com.android.server.art.ArtFileManager.WritableArtifactLists;
import static com.android.server.art.DexMetadataHelper.DexMetadataInfo;
-import static com.android.server.art.DexUseManagerLocal.SecondaryDexInfo;
import static com.android.server.art.PrimaryDexUtils.DetailedPrimaryDexInfo;
import static com.android.server.art.PrimaryDexUtils.PrimaryDexInfo;
import static com.android.server.art.ProfilePath.WritableProfilePath;
@@ -102,6 +101,8 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;
@@ -1521,6 +1522,7 @@ public final class ArtManagerLocal {
@Nullable private final Context mContext;
@Nullable private final PackageManagerLocal mPackageManagerLocal;
@Nullable private final Config mConfig;
+ @Nullable private final ThreadPoolExecutor mReporterExecutor;
@Nullable private BackgroundDexoptJob mBgDexoptJob = null;
@Nullable private PreRebootDexoptJob mPrDexoptJob = null;
@@ -1531,6 +1533,7 @@ public final class ArtManagerLocal {
mContext = null;
mPackageManagerLocal = null;
mConfig = null;
+ mReporterExecutor = null;
}
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@@ -1541,6 +1544,10 @@ public final class ArtManagerLocal {
mPackageManagerLocal = Objects.requireNonNull(
LocalManagerRegistry.getManager(PackageManagerLocal.class));
mConfig = new Config();
+ mReporterExecutor =
+ new ThreadPoolExecutor(1 /* corePoolSize */, 1 /* maximumPoolSize */,
+ 60 /* keepTimeAlive */, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
+ mReporterExecutor.allowsCoreThreadTimeOut();
// Call the getters for the dependencies that aren't optional, to ensure correct
// initialization order.
@@ -1587,7 +1594,7 @@ public final class ArtManagerLocal {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@NonNull
public DexoptHelper getDexoptHelper() {
- return new DexoptHelper(getContext(), getConfig());
+ return new DexoptHelper(getContext(), getConfig(), getReporterExecutor());
}
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@@ -1596,6 +1603,12 @@ public final class ArtManagerLocal {
return mConfig;
}
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @NonNull
+ public Executor getReporterExecutor() {
+ return mReporterExecutor;
+ }
+
/** Returns the registered {@link AppHibernationManager} instance. */
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@NonNull
diff --git a/libartservice/service/java/com/android/server/art/Dex2OatStatsReporter.java b/libartservice/service/java/com/android/server/art/Dex2OatStatsReporter.java
new file mode 100644
index 0000000000..d553113301
--- /dev/null
+++ b/libartservice/service/java/com/android/server/art/Dex2OatStatsReporter.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.art;
+
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.server.art.model.DetailedDexInfo;
+import com.android.server.art.model.DexMetadata;
+
+/**
+ * A class to report dex2oat metrics to StatsD.
+ *
+ * @hide
+ */
+@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class Dex2OatStatsReporter {
+ public static void report(int appId, @NonNull String compilerFilter,
+ @NonNull String compilationReason, @DexMetadata.Type int dexMetadataType,
+ @NonNull DetailedDexInfo dexInfo, @NonNull String isa, @NonNull Dex2OatResult result,
+ long artifactsSize, long compilationTime) {
+ ArtStatsLog.write(ArtStatsLog.ART_DEX2OAT_REPORTED, appId,
+ translateCompilerFilter(compilerFilter),
+ translateCompilationReason(compilationReason),
+ translateDexMetadataType(dexMetadataType), getApkType(dexInfo), translateIsa(isa),
+ result.status, result.exitCode, result.signal, (int) (artifactsSize / 1024),
+ (int) compilationTime);
+ }
+
+ private static int translateCompilerFilter(String compilerFilter) {
+ return switch (compilerFilter) {
+ case "assume-verified" ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_ASSUMED_VERIFIED;
+ case "verify" ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_VERIFY;
+ case "space-profile" ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_SPACE_PROFILE;
+ case "space" ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_SPACE;
+ case "speed-profile" ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_SPEED_PROFILE;
+ case "speed" ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_SPEED;
+ case "everything-profile" ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_EVERYTHING_PROFILE;
+ case "everything" ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_EVERYTHING;
+ default ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__COMPILER_FILTER__ART_COMPILATION_FILTER_UNKNOWN;
+ };
+ }
+
+ private static int translateCompilationReason(String compilationReason) {
+ return switch (compilationReason) {
+ case ReasonMapping.REASON_FIRST_BOOT ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT;
+ case ReasonMapping.REASON_BOOT_AFTER_OTA ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BOOT_AFTER_OTA;
+ case ReasonMapping.REASON_BOOT_AFTER_MAINLINE_UPDATE ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BOOT_AFTER_MAINLINE_UPDATE;
+ case ReasonMapping.REASON_INSTALL ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL;
+ case ReasonMapping.REASON_BG_DEXOPT ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BG_DEXOPT;
+ case ReasonMapping.REASON_CMDLINE ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_CMDLINE;
+ case ReasonMapping.REASON_INACTIVE ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INACTIVE;
+ case ReasonMapping.REASON_PRE_REBOOT_DEXOPT ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_AB_OTA;
+ case ReasonMapping.REASON_INSTALL_FAST ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_FAST;
+ case ReasonMapping.REASON_INSTALL_BULK ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK;
+ case ReasonMapping.REASON_INSTALL_BULK_SECONDARY ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY;
+ case ReasonMapping.REASON_INSTALL_BULK_DOWNGRADED ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED;
+ case ReasonMapping.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
+ default ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN;
+ };
+ }
+
+ private static int translateIsa(String isa) {
+ return switch (isa) {
+ case "arm" -> ArtStatsLog.ART_DEX2_OAT_REPORTED__ISA__ART_ISA_ARM;
+ case "arm64" -> ArtStatsLog.ART_DEX2_OAT_REPORTED__ISA__ART_ISA_ARM64;
+ case "riscv64" -> ArtStatsLog.ART_DEX2_OAT_REPORTED__ISA__ART_ISA_RISCV64;
+ case "x86" -> ArtStatsLog.ART_DEX2_OAT_REPORTED__ISA__ART_ISA_X86;
+ case "x86_64" -> ArtStatsLog.ART_DATUM_DELTA_REPORTED__ISA__ART_ISA_X86_64;
+ default -> ArtStatsLog.ART_DEX2_OAT_REPORTED__ISA__ART_ISA_UNKNOWN;
+ };
+ }
+
+ private static int translateDexMetadataType(@DexMetadata.Type int dexMetadataType) {
+ return switch (dexMetadataType) {
+ case DexMetadata.TYPE_PROFILE ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE;
+ case DexMetadata.TYPE_VDEX ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX;
+ case DexMetadata.TYPE_PROFILE_AND_VDEX ->
+ ArtStatsLog
+ .ART_DEX2_OAT_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX;
+ case DexMetadata.TYPE_NONE ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE;
+ case DexMetadata.TYPE_ERROR ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_ERROR;
+ case DexMetadata.TYPE_UNKNOWN ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN;
+ default ->
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN;
+ };
+ }
+
+ private static int getApkType(DetailedDexInfo dexInfo) {
+ if (dexInfo instanceof PrimaryDexUtils.PrimaryDexInfo primaryDexInfo) {
+ return primaryDexInfo.splitName() == null
+ ? ArtStatsLog.ART_DEX2_OAT_REPORTED__APK_TYPE__ART_APK_TYPE_BASE
+ : ArtStatsLog.ART_DEX2_OAT_REPORTED__APK_TYPE__ART_APK_TYPE_SPLIT;
+ } else if (dexInfo instanceof DexUseManagerLocal.CheckedSecondaryDexInfo) {
+ return ArtStatsLog.ART_DEX2_OAT_REPORTED__APK_TYPE__ART_APK_TYPE_SECONDARY;
+ }
+ return ArtStatsLog.ART_DEX2_OAT_REPORTED__APK_TYPE__ART_APK_TYPE_UNKNOWN;
+ }
+
+ public record Dex2OatResult(int status, int exitCode, int signal) {
+ public static Dex2OatResult notRun() {
+ return new Dex2OatResult(
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__RESULT_STATUS__EXEC_RESULT_STATUS_NOT_RUN,
+ -1 /* exitCode */, 0 /* signal */);
+ }
+
+ public static Dex2OatResult exited(int exitCode) {
+ return new Dex2OatResult(
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__RESULT_STATUS__EXEC_RESULT_STATUS_EXITED,
+ exitCode, 0 /* signal */);
+ }
+
+ public static Dex2OatResult cancelled() {
+ return new Dex2OatResult(
+ ArtStatsLog.ART_DEX2_OAT_REPORTED__RESULT_STATUS__EXEC_RESULT_STATUS_CANCELLED,
+ -1 /* exitCode */, 0 /* signal */);
+ }
+ }
+}
diff --git a/libartservice/service/java/com/android/server/art/DexMetadataHelper.java b/libartservice/service/java/com/android/server/art/DexMetadataHelper.java
index 99d92083d3..237bb1878e 100644
--- a/libartservice/service/java/com/android/server/art/DexMetadataHelper.java
+++ b/libartservice/service/java/com/android/server/art/DexMetadataHelper.java
@@ -23,6 +23,7 @@ import android.os.Build;
import androidx.annotation.RequiresApi;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.art.model.DexMetadata;
import com.android.server.art.proto.DexMetadataConfig;
import java.io.FileNotFoundException;
@@ -44,6 +45,9 @@ import java.util.zip.ZipFile;
public class DexMetadataHelper {
@NonNull private final Injector mInjector;
+ private static final String PROFILE_DEX_METADATA = "primary.prof";
+ private static final String VDEX_DEX_METADATA = "primary.vdex";
+
public DexMetadataHelper() {
this(new Injector());
}
@@ -56,29 +60,31 @@ public class DexMetadataHelper {
@NonNull
public DexMetadataInfo getDexMetadataInfo(@Nullable DexMetadataPath dmPath) {
if (dmPath == null) {
- return getDefaultDexMetadataInfo();
+ return getDefaultDexMetadataInfo(DexMetadata.TYPE_NONE);
}
String realDmPath = getDmPath(dmPath);
try (var zipFile = mInjector.openZipFile(realDmPath)) {
ZipEntry entry = zipFile.getEntry("config.pb");
if (entry == null) {
- return new DexMetadataInfo(dmPath, DexMetadataConfig.getDefaultInstance());
+ return new DexMetadataInfo(
+ dmPath, DexMetadataConfig.getDefaultInstance(), getType(zipFile));
}
try (InputStream stream = zipFile.getInputStream(entry)) {
- return new DexMetadataInfo(dmPath, DexMetadataConfig.parseFrom(stream));
+ return new DexMetadataInfo(
+ dmPath, DexMetadataConfig.parseFrom(stream), getType(zipFile));
}
} catch (IOException e) {
if (!(e instanceof FileNotFoundException || e instanceof NoSuchFileException)) {
AsLog.e(String.format("Failed to read dm file '%s'", realDmPath), e);
}
- return getDefaultDexMetadataInfo();
+ return getDefaultDexMetadataInfo(DexMetadata.TYPE_ERROR);
}
}
@NonNull
- private DexMetadataInfo getDefaultDexMetadataInfo() {
- return new DexMetadataInfo(null /* dmPath */, DexMetadataConfig.getDefaultInstance());
+ private DexMetadataInfo getDefaultDexMetadataInfo(@DexMetadata.Type int type) {
+ return new DexMetadataInfo(null /* dmPath */, DexMetadataConfig.getDefaultInstance(), type);
}
@NonNull
@@ -88,14 +94,31 @@ public class DexMetadataHelper {
return (pos != -1 ? dexPath.substring(0, pos) : dexPath) + ".dm";
}
+ private static @DexMetadata.Type int getType(@NonNull ZipFile zipFile) {
+ var profile = zipFile.getEntry(PROFILE_DEX_METADATA);
+ var vdex = zipFile.getEntry(VDEX_DEX_METADATA);
+
+ if (profile != null && vdex != null) {
+ return DexMetadata.TYPE_PROFILE_AND_VDEX;
+ } else if (profile != null) {
+ return DexMetadata.TYPE_PROFILE;
+ } else if (vdex != null) {
+ return DexMetadata.TYPE_VDEX;
+ } else {
+ return DexMetadata.TYPE_NONE;
+ }
+ }
+
/**
* @param dmPath Represents the path to the dm file, if it exists. Or null if the file doesn't
* exist or an error occurred.
* @param config The config deserialized from `config.pb`, if it exists. Or the default instance
* if the file doesn't exist or an error occurred.
+ * @param type An enum value representing whether the dm file contains a profile, a VDEX file,
+ * none, or both.
*/
- public record DexMetadataInfo(
- @Nullable DexMetadataPath dmPath, @NonNull DexMetadataConfig config) {}
+ public record DexMetadataInfo(@Nullable DexMetadataPath dmPath,
+ @NonNull DexMetadataConfig config, @DexMetadata.Type int type) {}
/**
* Injector pattern for testing purpose.
diff --git a/libartservice/service/java/com/android/server/art/DexoptHelper.java b/libartservice/service/java/com/android/server/art/DexoptHelper.java
index 2369ad4eba..828a05c656 100644
--- a/libartservice/service/java/com/android/server/art/DexoptHelper.java
+++ b/libartservice/service/java/com/android/server/art/DexoptHelper.java
@@ -29,7 +29,6 @@ import android.os.Binder;
import android.os.Build;
import android.os.CancellationSignal;
import android.os.RemoteException;
-import android.os.WorkSource;
import androidx.annotation.RequiresApi;
@@ -54,7 +53,6 @@ import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -71,8 +69,9 @@ import java.util.stream.Collectors;
public class DexoptHelper {
@NonNull private final Injector mInjector;
- public DexoptHelper(@NonNull Context context, @NonNull Config config) {
- this(new Injector(context, config));
+ public DexoptHelper(
+ @NonNull Context context, @NonNull Config config, @NonNull Executor reporterExecutor) {
+ this(new Injector(context, config, reporterExecutor));
}
@VisibleForTesting
@@ -324,10 +323,13 @@ public class DexoptHelper {
public static class Injector {
@NonNull private final Context mContext;
@NonNull private final Config mConfig;
+ @NonNull private final Executor mReporterExecutor;
- Injector(@NonNull Context context, @NonNull Config config) {
+ Injector(@NonNull Context context, @NonNull Config config,
+ @NonNull Executor reporterExecutor) {
mContext = context;
mConfig = config;
+ mReporterExecutor = reporterExecutor;
// Call the getters for the dependencies that aren't optional, to ensure correct
// initialization order.
@@ -338,16 +340,16 @@ public class DexoptHelper {
PrimaryDexopter getPrimaryDexopter(@NonNull PackageState pkgState,
@NonNull AndroidPackage pkg, @NonNull DexoptParams params,
@NonNull CancellationSignal cancellationSignal) {
- return new PrimaryDexopter(
- mContext, mConfig, pkgState, pkg, params, cancellationSignal);
+ return new PrimaryDexopter(mContext, mConfig, mReporterExecutor, pkgState, pkg, params,
+ cancellationSignal);
}
@NonNull
SecondaryDexopter getSecondaryDexopter(@NonNull PackageState pkgState,
@NonNull AndroidPackage pkg, @NonNull DexoptParams params,
@NonNull CancellationSignal cancellationSignal) {
- return new SecondaryDexopter(
- mContext, mConfig, pkgState, pkg, params, cancellationSignal);
+ return new SecondaryDexopter(mContext, mConfig, mReporterExecutor, pkgState, pkg,
+ params, cancellationSignal);
}
@NonNull
diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java
index 271dc6144f..b13ec66831 100644
--- a/libartservice/service/java/com/android/server/art/Dexopter.java
+++ b/libartservice/service/java/com/android/server/art/Dexopter.java
@@ -26,10 +26,8 @@ import static com.android.server.art.model.ArtFlags.DexoptFlags;
import static com.android.server.art.model.Config.Callback;
import static com.android.server.art.model.DexoptResult.DexContainerFileDexoptResult;
-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.Build;
@@ -39,13 +37,12 @@ import android.os.ServiceSpecificException;
import android.os.SystemProperties;
import android.os.UserManager;
import android.os.storage.StorageManager;
-import android.text.TextUtils;
-import android.util.Pair;
import androidx.annotation.RequiresApi;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalManagerRegistry;
+import com.android.server.art.Dex2OatStatsReporter.Dex2OatResult;
import com.android.server.art.model.ArtFlags;
import com.android.server.art.model.Config;
import com.android.server.art.model.DetailedDexInfo;
@@ -64,6 +61,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/** @hide */
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@@ -193,6 +193,7 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
long cpuTimeMs = 0;
long sizeBytes = 0;
long sizeBeforeBytes = 0;
+ Dex2OatResult dex2OatResult = Dex2OatResult.notRun();
@DexoptResult.DexoptResultExtendedStatusFlags int extendedStatusFlags = 0;
try {
var target = DexoptTarget.<DexInfoType>builder()
@@ -276,6 +277,8 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
cpuTimeMs = dexoptResult.cpuTimeMs;
sizeBytes = dexoptResult.sizeBytes;
sizeBeforeBytes = dexoptResult.sizeBeforeBytes;
+ dex2OatResult = dexoptResult.cancelled ? Dex2OatResult.cancelled()
+ : Dex2OatResult.exited(0);
if (status == DexoptResult.DEXOPT_CANCELLED) {
return results;
@@ -288,6 +291,16 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
dexInfo.classLoaderContext()),
e);
status = DexoptResult.DEXOPT_FAILED;
+
+ // Parse status, exit code and signal from the dex2oat error message
+ Pattern pattern = Pattern.compile(
+ "\\[status=(-?\\d+),exit_code=(-?\\d+),signal=(-?\\d+)]");
+ Matcher matcher = pattern.matcher(Objects.requireNonNull(e.getMessage()));
+ if (matcher.matches()) {
+ dex2OatResult = new Dex2OatResult(Integer.parseInt(matcher.group(1)),
+ Integer.parseInt(matcher.group(2)),
+ Integer.parseInt(matcher.group(3)));
+ }
} finally {
if (!externalProfileErrors.isEmpty()) {
extendedStatusFlags |= DexoptResult.EXTENDED_BAD_EXTERNAL_PROFILE;
@@ -306,6 +319,17 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
// Make sure artd does not leak even if the caller holds
// `mCancellationSignal` forever.
mCancellationSignal.setOnCancelListener(null);
+
+ // Variables used in lambda needs to be effectively final.
+ Dex2OatResult finalDex2OatResult = dex2OatResult;
+ mInjector.getReporterExecutor().execute(
+ ()
+ -> Dex2OatStatsReporter.report(mPkgState.getAppId(),
+ result.getActualCompilerFilter(),
+ mParams.getReason(), dmInfo.type(), dexInfo,
+ abi.isa(), finalDex2OatResult,
+ result.getSizeBytes(),
+ result.getDex2oatWallTimeMillis()));
}
}
@@ -757,10 +781,13 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
public static class Injector {
@NonNull private final Context mContext;
@NonNull private final Config mConfig;
+ @NonNull private final Executor mReporterExecutor;
- public Injector(@NonNull Context context, @NonNull Config config) {
+ public Injector(@NonNull Context context, @NonNull Config config,
+ @NonNull Executor reporterExecutor) {
mContext = context;
mConfig = config;
+ mReporterExecutor = reporterExecutor;
// Call the getters for various dependencies, to ensure correct initialization order.
getUserManager();
@@ -823,6 +850,11 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
}
@NonNull
+ public Executor getReporterExecutor() {
+ return mReporterExecutor;
+ }
+
+ @NonNull
public DexMetadataHelper getDexMetadataHelper() {
return new DexMetadataHelper();
}
diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
index f8234c4df9..eb200592aa 100644
--- a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
+++ b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
@@ -30,7 +30,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
-import android.text.TextUtils;
import androidx.annotation.RequiresApi;
@@ -39,18 +38,12 @@ import com.android.modules.utils.pm.PackageStateModulesUtils;
import com.android.server.art.model.ArtFlags;
import com.android.server.art.model.Config;
import com.android.server.art.model.DexoptParams;
-import com.android.server.art.model.DexoptResult;
-import com.android.server.pm.PackageManagerLocal;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
-import dalvik.system.DexFile;
-
-import com.google.auto.value.AutoValue;
-
-import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.Executor;
/** @hide */
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@@ -58,9 +51,10 @@ public class PrimaryDexopter extends Dexopter<DetailedPrimaryDexInfo> {
private final int mSharedGid;
public PrimaryDexopter(@NonNull Context context, @NonNull Config config,
- @NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
+ Executor reporterExecutor, @NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
@NonNull DexoptParams params, @NonNull CancellationSignal cancellationSignal) {
- this(new Injector(context, config), pkgState, pkg, params, cancellationSignal);
+ this(new Injector(context, config, reporterExecutor), pkgState, pkg, params,
+ cancellationSignal);
}
@VisibleForTesting
diff --git a/libartservice/service/java/com/android/server/art/SecondaryDexopter.java b/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
index 57fe174d6a..b8ee9d079d 100644
--- a/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
+++ b/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
@@ -36,14 +36,16 @@ import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import java.util.List;
+import java.util.concurrent.Executor;
/** @hide */
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public class SecondaryDexopter extends Dexopter<CheckedSecondaryDexInfo> {
public SecondaryDexopter(@NonNull Context context, @NonNull Config config,
- @NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
+ Executor reporterExecutor, @NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
@NonNull DexoptParams params, @NonNull CancellationSignal cancellationSignal) {
- this(new Injector(context, config), pkgState, pkg, params, cancellationSignal);
+ this(new Injector(context, config, reporterExecutor), pkgState, pkg, params,
+ cancellationSignal);
}
@VisibleForTesting
diff --git a/libartservice/service/java/com/android/server/art/model/DexMetadata.java b/libartservice/service/java/com/android/server/art/model/DexMetadata.java
new file mode 100644
index 0000000000..5895b7be30
--- /dev/null
+++ b/libartservice/service/java/com/android/server/art/model/DexMetadata.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.art.model;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** @hide */
+public class DexMetadata {
+ /** An explicit private class to avoid exposing constructor.*/
+ private DexMetadata() {}
+
+ public static final int TYPE_UNKNOWN = 0;
+ public static final int TYPE_PROFILE = 1;
+ public static final int TYPE_VDEX = 2;
+ public static final int TYPE_PROFILE_AND_VDEX = 3;
+ public static final int TYPE_NONE = 4;
+ public static final int TYPE_ERROR = 5;
+
+ /** @hide */
+ // clang-format off
+ @IntDef(prefix = "TYPE_", value = {
+ TYPE_UNKNOWN,
+ TYPE_PROFILE,
+ TYPE_VDEX,
+ TYPE_PROFILE_AND_VDEX,
+ TYPE_NONE,
+ TYPE_ERROR,
+ })
+ // clang-format on
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+}
diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
index 739c2daaa9..9deb3f1055 100644
--- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
@@ -35,7 +35,6 @@ import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.isNull;
diff --git a/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java b/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
index ac5947930b..f6ed721157 100644
--- a/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
+++ b/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
@@ -25,7 +25,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.lenient;
@@ -34,7 +33,6 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.apphibernation.AppHibernationManager;
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index 49d7c6cb41..10f9f59e91 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -51,8 +51,6 @@ import com.android.server.art.model.DexoptParams;
import com.android.server.art.model.DexoptResult;
import com.android.server.art.testing.TestingUtils;
-import dalvik.system.DexFile;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -344,7 +342,7 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase {
.when(mArtd)
.getDexoptNeeded("/somewhere/app/foo/base.apk", "arm", "PCL[]",
mParams.mExpectedCompilerFilter, mParams.mExpectedDexoptTrigger);
- doThrow(ServiceSpecificException.class)
+ doThrow(new ServiceSpecificException(31, "This is an error message."))
.when(mArtd)
.dexopt(deepEq(buildOutputArtifacts("/somewhere/app/foo/base.apk", "arm",
mParams.mIsInDalvikCache, permissionSettings,
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
index 0030085497..5cc201cd37 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
@@ -577,7 +577,7 @@ public class PrimaryDexopterTest extends PrimaryDexopterTestBase {
when(mArtd.dexopt(any(), eq(mDexPath), any(), any(), any(), any(), any(), any(), anyInt(),
any(), any()))
- .thenThrow(ServiceSpecificException.class);
+ .thenThrow(new ServiceSpecificException(42, "This is an error message"));
mPrimaryDexopter.dexopt();
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
index 3105e4e51b..d94190ded5 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
@@ -46,6 +46,7 @@ import org.mockito.Mock;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ThreadPoolExecutor;
public class PrimaryDexopterTestBase {
protected static final String PKG_NAME = "com.example.foo";
@@ -65,6 +66,7 @@ public class PrimaryDexopterTestBase {
@Mock protected DexUseManagerLocal mDexUseManager;
@Mock protected StorageManager mStorageManager;
@Mock protected DexMetadataHelper.Injector mDexMetadataHelperInjector;
+ @Mock protected ThreadPoolExecutor mReporterExecutor;
protected PackageState mPkgState;
protected AndroidPackage mPkg;
protected PackageUserState mPkgUserStateNotInstalled;
@@ -91,6 +93,7 @@ public class PrimaryDexopterTestBase {
lenient().when(mInjector.getStorageManager()).thenReturn(mStorageManager);
lenient().when(mInjector.getArtVersion()).thenReturn(ART_VERSION);
lenient().when(mInjector.getConfig()).thenReturn(mConfig);
+ lenient().when(mInjector.getReporterExecutor()).thenReturn(mReporterExecutor);
lenient().when(mInjector.getDexMetadataHelper()).thenReturn(mDexMetadataHelper);
lenient().when(mInjector.isPreReboot()).thenReturn(false);
diff --git a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
index 07dd07dae7..074edc0629 100644
--- a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
@@ -61,6 +61,7 @@ import org.mockito.Mock;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
@SmallTest
@@ -108,6 +109,7 @@ public class SecondaryDexopterTest {
@Mock private IArtd mArtd;
@Mock private DexUseManagerLocal mDexUseManager;
@Mock private DexMetadataHelper.Injector mDexMetadataHelperInjector;
+ @Mock private ThreadPoolExecutor mReporterExecutor;
private PackageState mPkgState;
private AndroidPackage mPkg;
private CancellationSignal mCancellationSignal;
@@ -144,6 +146,7 @@ public class SecondaryDexopterTest {
lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false);
lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
lenient().when(mInjector.getConfig()).thenReturn(mConfig);
+ lenient().when(mInjector.getReporterExecutor()).thenReturn(mReporterExecutor);
lenient().when(mInjector.getDexMetadataHelper()).thenReturn(mDexMetadataHelper);
List<CheckedSecondaryDexInfo> secondaryDexInfo = createSecondaryDexInfo();
diff --git a/odrefresh/odr_metrics_record.h b/odrefresh/odr_metrics_record.h
index 4b18edb6d6..47db41978a 100644
--- a/odrefresh/odr_metrics_record.h
+++ b/odrefresh/odr_metrics_record.h
@@ -34,7 +34,8 @@ constexpr const char* kOdrefreshMetricsFile = "/data/misc/odrefresh/odrefresh-me
static constexpr int32_t kOdrefreshMetricsVersion = 4;
// Constant value used in ExecResult when the process was not run at all.
-// Mirrors EXEC_RESULT_STATUS_NOT_RUN contained in frameworks/proto_logging/atoms.proto.
+// Mirrors EXEC_RESULT_STATUS_NOT_RUN contained in
+// frameworks/proto_logging/stats/enums/art/common_enums.proto.
static constexpr int32_t kExecResultNotRun = 5;
static_assert(kExecResultNotRun > ExecResult::Status::kLast,
"`art::odrefresh::kExecResultNotRun` value should not overlap with"
diff --git a/runtime/exec_utils.h b/runtime/exec_utils.h
index 61e9beae32..6a97cc7e5b 100644
--- a/runtime/exec_utils.h
+++ b/runtime/exec_utils.h
@@ -48,7 +48,7 @@ struct ExecCallbacks {
struct ExecResult {
// This struct needs to be in sync with the ExecResultStatus enum contained within the
- // OdrefreshReported atom in frameworks/proto_logging/atoms/art/odrefresh_extension_atoms.proto.
+ // OdrefreshReported atom in frameworks/proto_logging/stats/enums/art/common_enums.proto.
enum Status {
// Unable to get the status.
kUnknown = 0,