Fix compiler filter / reason reporting and add the ISA to the metrics

The compiler filter / reason reporting was not accurate for a variety
of reasons. (e.g. reporting was only done at startup, it was relying
on imprecise APIs and had errors in the logic).

In order to keep track of the precise optimization status, this CL
introduces the concept of AppInfo, which encapsulates the data about
the application / system server code paths, their optimization status
and possible other metadata (e.g. profiles).

To populate it, we rely on 2 distinct events:
1) The framework calling VMRuntime#registerAppInfo to inform the
runtime about the applications code paths and their types (e.g. primary,
split, secondary).
2) Class loading, when we can determine the actual optimization status
like filters, reasons, and whether or not we can load the odex files.

These events may happen in any order so we could deal with a partial
state at some point in time, but in the majority of cases they always
happen at Class Loading, followed by RegisterAppInfo.

This CL also deletes the OatFileManager#getPrimaryOatFile which was
a misleading API as it didn't work in most cases. It also adds more
tests to the metrics/reporting infra for previous missing or
unimplemented cases.

Test: gtest
Bug: 170149255
Change-Id: If0a7a25d06ff6fb89fe4861139b7dee61c05814d
diff --git a/libartbase/base/metrics/metrics.h b/libartbase/base/metrics/metrics.h
index c9110ee..2a71c2c 100644
--- a/libartbase/base/metrics/metrics.h
+++ b/libartbase/base/metrics/metrics.h
@@ -29,7 +29,6 @@
 
 #include "android-base/logging.h"
 #include "base/bit_utils.h"
-#include "base/compiler_filter.h"
 #include "base/time_utils.h"
 
 #pragma clang diagnostic push
@@ -82,127 +81,96 @@
 #undef METRIC
 };
 
+// Names come from PackageManagerServiceCompilerMapping.java
+#define REASON_NAME_LIST(V) \
+  V(kError, "error") \
+  V(kUnknown, "unknown") \
+  V(kFirstBoot, "first-boot") \
+  V(kBootAfterOTA, "boot-after-ota") \
+  V(kPostBoot, "post-boot") \
+  V(kInstall, "install") \
+  V(kInstallFast, "install-fast") \
+  V(kInstallBulk, "install-bulk") \
+  V(kInstallBulkSecondary, "install-bulk-secondary") \
+  V(kInstallBulkDowngraded, "install-bulk-downgraded") \
+  V(kInstallBulkSecondaryDowngraded, "install-bulk-secondary-downgraded") \
+  V(kBgDexopt, "bg-dexopt") \
+  V(kABOTA, "ab-ota") \
+  V(kInactive, "inactive") \
+  V(kShared, "shared") \
+  V(kInstallWithDexMetadata, "install-with-dex-metadata") \
+  V(kPrebuilt, "prebuilt") \
+  V(kCmdLine, "cmdline")
+
 // We log compilation reasons as part of the metadata we report. Since elsewhere compilation reasons
 // are specified as a string, we define them as an enum here which indicates the reasons that we
 // support.
 enum class CompilationReason {
-  kError,
-  kUnknown,
-  kFirstBoot,
-  kBootAfterOTA,
-  kPostBoot,
-  kInstall,
-  kInstallFast,
-  kInstallBulk,
-  kInstallBulkSecondary,
-  kInstallBulkDowngraded,
-  kInstallBulkSecondaryDowngraded,
-  kBgDexopt,
-  kABOTA,
-  kInactive,
-  kShared,
-  kInstallWithDexMetadata,
-  kPrebuilt,
-  kCmdLine
+#define REASON(kind, name) kind,
+  REASON_NAME_LIST(REASON)
+#undef REASON
 };
 
+#define REASON_NAME(kind, kind_name) \
+    case CompilationReason::kind: return kind_name;
+#define REASON_FROM_NAME(kind, kind_name) \
+    if (name == kind_name) { return CompilationReason::kind; }
+
 constexpr const char* CompilationReasonName(CompilationReason reason) {
   switch (reason) {
-    case CompilationReason::kError:
-      return "error";
-    case CompilationReason::kUnknown:
-      return "unknown";
-    case CompilationReason::kFirstBoot:
-      return "first-boot";
-    case CompilationReason::kBootAfterOTA:
-      return "boot-after-ota";
-    case CompilationReason::kPostBoot:
-      return "post-boot";
-    case CompilationReason::kInstall:
-      return "install";
-    case CompilationReason::kInstallFast:
-      return "install-fast";
-    case CompilationReason::kInstallBulk:
-      return "install-bulk";
-    case CompilationReason::kInstallBulkSecondary:
-      return "install-bulk-secondary";
-    case CompilationReason::kInstallBulkDowngraded:
-      return "install-bulk-downgraded";
-    case CompilationReason::kInstallBulkSecondaryDowngraded:
-      return "install-bulk-secondary-downgraded";
-    case CompilationReason::kBgDexopt:
-      return "bg-dexopt";
-    case CompilationReason::kABOTA:
-      return "ab-ota";
-    case CompilationReason::kInactive:
-      return "inactive";
-    case CompilationReason::kShared:
-      return "shared";
-    case CompilationReason::kInstallWithDexMetadata:
-      return "install-with-dex-metadata";
-    case CompilationReason::kPrebuilt:
-      return "prebuilt";
-    case CompilationReason::kCmdLine:
-      return "cmdline";
+    REASON_NAME_LIST(REASON_NAME)
   }
 }
 
 constexpr CompilationReason CompilationReasonFromName(std::string_view name) {
-  // Names come from PackageManagerServiceCompilerMapping.java
-  if (name == "unknown") {
-    return CompilationReason::kUnknown;
-  }
-  if (name == "first-boot") {
-    return CompilationReason::kFirstBoot;
-  }
-  if (name == "boot-after-ota") {
-    return CompilationReason::kBootAfterOTA;
-  }
-  if (name == "post-boot") {
-    return CompilationReason::kPostBoot;
-  }
-  if (name == "install") {
-    return CompilationReason::kInstall;
-  }
-  if (name == "install-fast") {
-    return CompilationReason::kInstallFast;
-  }
-  if (name == "install-bulk") {
-    return CompilationReason::kInstallBulk;
-  }
-  if (name == "install-bulk-secondary") {
-    return CompilationReason::kInstallBulkSecondary;
-  }
-  if (name == "install-bulk-downgraded") {
-    return CompilationReason::kInstallBulkDowngraded;
-  }
-  if (name == "install-bulk-secondary-downgraded") {
-    return CompilationReason::kInstallBulkSecondaryDowngraded;
-  }
-  if (name == "bg-dexopt") {
-    return CompilationReason::kBgDexopt;
-  }
-  if (name == "ab-ota") {
-    return CompilationReason::kABOTA;
-  }
-  if (name == "inactive") {
-    return CompilationReason::kInactive;
-  }
-  if (name == "shared") {
-    return CompilationReason::kShared;
-  }
-  if (name == "install-with-dex-metadata") {
-    return CompilationReason::kInstallWithDexMetadata;
-  }
-  if (name == "prebuilt") {
-    return CompilationReason::kPrebuilt;
-  }
-  if (name == "cmdline") {
-    return CompilationReason::kCmdLine;
-  }
+  REASON_NAME_LIST(REASON_FROM_NAME)
   return CompilationReason::kError;
 }
 
+#undef REASON_NAME
+#undef ReasonFromName
+
+#define COMPILER_FILTER_REPORTING_LIST(V) \
+  V(kError, "error") /* Error (invalid value) condition */ \
+  V(kUnknown, "unknown") /* Unknown (not set) condition */ \
+  V(kAssumeVerified, "assume-verified") /* Standard compiler filters */ \
+  V(kExtract, "extract") \
+  V(kVerify, "verify") \
+  V(kSpaceProfile, "space-profile") \
+  V(kSpace, "space") \
+  V(kSpeedProfile, "speed-profile") \
+  V(kSpeed, "speed") \
+  V(kEverythingProfile, "everything-profile") \
+  V(kEverything, "everything") \
+  V(kRunFromApk, "run-from-apk") /* Augmented compiler filters as produces by OatFileAssistant#GetOptimizationStatus */ \
+  V(kRunFromApkFallback, "run-from-apk-fallback")
+
+// Augmented compiler filter enum, used in the reporting infra.
+enum class CompilerFilterReporting {
+#define FILTER(kind, name) kind,
+  COMPILER_FILTER_REPORTING_LIST(FILTER)
+#undef FILTER
+};
+
+#define FILTER_NAME(kind, kind_name) \
+    case CompilerFilterReporting::kind: return kind_name;
+#define FILTER_FROM_NAME(kind, kind_name) \
+    if (name == kind_name) { return CompilerFilterReporting::kind; }
+
+constexpr const char* CompilerFilterReportingName(CompilerFilterReporting filter) {
+  switch (filter) {
+    COMPILER_FILTER_REPORTING_LIST(FILTER_NAME)
+  }
+}
+
+constexpr CompilerFilterReporting CompilerFilterReportingFromName(std::string_view name) {
+  COMPILER_FILTER_REPORTING_LIST(FILTER_FROM_NAME)
+  return CompilerFilterReporting::kError;
+}
+
+#undef FILTER_NAME
+#undef FILTER_FROM_NAME
+
 // SessionData contains metadata about a metrics session (basically the lifetime of an ART process).
 // This information should not change for the lifetime of the session.
 struct SessionData {
@@ -214,7 +182,7 @@
   int64_t session_id;
   int32_t uid;
   CompilationReason compilation_reason;
-  std::optional<CompilerFilter::Filter> compiler_filter;
+  CompilerFilterReporting compiler_filter;
 };
 
 // MetricsBackends are used by a metrics reporter to write metrics to some external location. For
@@ -229,7 +197,10 @@
   // includes a session id which is used to correlate any metric reports with the same instance of
   // the ART runtime. Additionally, session_data includes useful metadata such as the package name
   // for this process.
-  virtual void BeginSession(const SessionData& session_data) = 0;
+  //
+  // It may also be called whenever there is an update to the session metadata (e.g. optimization
+  // state).
+  virtual void BeginOrUpdateSession(const SessionData& session_data) = 0;
 
  protected:
   // Called by the metrics reporter to indicate that a new metrics report is starting.
@@ -468,7 +439,7 @@
  public:
   StringBackend();
 
-  void BeginSession(const SessionData& session_data) override;
+  void BeginOrUpdateSession(const SessionData& session_data) override;
 
   void BeginReport(uint64_t timestamp_millis) override;
 
diff --git a/libartbase/base/metrics/metrics_common.cc b/libartbase/base/metrics/metrics_common.cc
index c8c8701..f09987b 100644
--- a/libartbase/base/metrics/metrics_common.cc
+++ b/libartbase/base/metrics/metrics_common.cc
@@ -51,7 +51,7 @@
 
   return SessionData{
     .compilation_reason = CompilationReason::kUnknown,
-    .compiler_filter = std::nullopt,
+    .compiler_filter = CompilerFilterReporting::kUnknown,
     .session_id = kInvalidSessionId,
     .uid = uid,
   };
@@ -97,7 +97,7 @@
   return result;
 }
 
-void StringBackend::BeginSession(const SessionData& session_data) {
+void StringBackend::BeginOrUpdateSession(const SessionData& session_data) {
   session_data_ = session_data;
 }
 
@@ -110,10 +110,7 @@
     os_ << "    uid: " << session_data_->uid << "\n";
     os_ << "    compilation_reason: " << CompilationReasonName(session_data_->compilation_reason)
         << "\n";
-    os_ << "    compiler_filter: "
-        << (session_data_->compiler_filter.has_value()
-                ? CompilerFilter::NameOfFilter(session_data_->compiler_filter.value())
-                : "(unspecified)")
+    os_ << "    compiler_filter: " << CompilerFilterReportingName(session_data_->compiler_filter)
         << "\n";
   }
   os_ << "  Metrics:\n";
diff --git a/libartbase/base/metrics/metrics_test.cc b/libartbase/base/metrics/metrics_test.cc
index 77f1b97..e7882ec 100644
--- a/libartbase/base/metrics/metrics_test.cc
+++ b/libartbase/base/metrics/metrics_test.cc
@@ -305,6 +305,141 @@
   metrics.ReportAllMetrics(&zero_backend);
 }
 
+TEST(CompilerFilterReportingTest, FromName) {
+  ASSERT_EQ(CompilerFilterReportingFromName("error"),
+            CompilerFilterReporting::kError);
+  ASSERT_EQ(CompilerFilterReportingFromName("unknown"),
+            CompilerFilterReporting::kUnknown);
+  ASSERT_EQ(CompilerFilterReportingFromName("assume-verified"),
+            CompilerFilterReporting::kAssumeVerified);
+  ASSERT_EQ(CompilerFilterReportingFromName("extract"),
+            CompilerFilterReporting::kExtract);
+  ASSERT_EQ(CompilerFilterReportingFromName("verify"),
+            CompilerFilterReporting::kVerify);
+  ASSERT_EQ(CompilerFilterReportingFromName("space-profile"),
+            CompilerFilterReporting::kSpaceProfile);
+  ASSERT_EQ(CompilerFilterReportingFromName("space"),
+            CompilerFilterReporting::kSpace);
+  ASSERT_EQ(CompilerFilterReportingFromName("speed-profile"),
+            CompilerFilterReporting::kSpeedProfile);
+  ASSERT_EQ(CompilerFilterReportingFromName("speed"),
+            CompilerFilterReporting::kSpeed);
+  ASSERT_EQ(CompilerFilterReportingFromName("everything-profile"),
+            CompilerFilterReporting::kEverythingProfile);
+  ASSERT_EQ(CompilerFilterReportingFromName("everything"),
+            CompilerFilterReporting::kEverything);
+  ASSERT_EQ(CompilerFilterReportingFromName("run-from-apk"),
+            CompilerFilterReporting::kRunFromApk);
+  ASSERT_EQ(CompilerFilterReportingFromName("run-from-apk-fallback"),
+            CompilerFilterReporting::kRunFromApkFallback);
+}
+
+TEST(CompilerFilterReportingTest, Name) {
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kError),
+            "error");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kUnknown),
+            "unknown");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kAssumeVerified),
+            "assume-verified");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kExtract),
+            "extract");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kVerify),
+            "verify");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpaceProfile),
+            "space-profile");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpace),
+            "space");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpeedProfile),
+            "speed-profile");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpeed),
+            "speed");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kEverythingProfile),
+            "everything-profile");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kEverything),
+            "everything");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kRunFromApk),
+            "run-from-apk");
+  ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kRunFromApkFallback),
+            "run-from-apk-fallback");
+}
+
+TEST(CompilerReason, FromName) {
+  ASSERT_EQ(CompilationReasonFromName("unknown"),
+            CompilationReason::kUnknown);
+  ASSERT_EQ(CompilationReasonFromName("first-boot"),
+            CompilationReason::kFirstBoot);
+  ASSERT_EQ(CompilationReasonFromName("boot-after-ota"),
+            CompilationReason::kBootAfterOTA);
+  ASSERT_EQ(CompilationReasonFromName("post-boot"),
+            CompilationReason::kPostBoot);
+  ASSERT_EQ(CompilationReasonFromName("install"),
+            CompilationReason::kInstall);
+  ASSERT_EQ(CompilationReasonFromName("install-fast"),
+            CompilationReason::kInstallFast);
+  ASSERT_EQ(CompilationReasonFromName("install-bulk"),
+            CompilationReason::kInstallBulk);
+  ASSERT_EQ(CompilationReasonFromName("install-bulk-secondary"),
+            CompilationReason::kInstallBulkSecondary);
+  ASSERT_EQ(CompilationReasonFromName("install-bulk-downgraded"),
+            CompilationReason::kInstallBulkDowngraded);
+  ASSERT_EQ(CompilationReasonFromName("install-bulk-secondary-downgraded"),
+            CompilationReason::kInstallBulkSecondaryDowngraded);
+  ASSERT_EQ(CompilationReasonFromName("bg-dexopt"),
+            CompilationReason::kBgDexopt);
+  ASSERT_EQ(CompilationReasonFromName("ab-ota"),
+            CompilationReason::kABOTA);
+  ASSERT_EQ(CompilationReasonFromName("inactive"),
+            CompilationReason::kInactive);
+  ASSERT_EQ(CompilationReasonFromName("shared"),
+            CompilationReason::kShared);
+  ASSERT_EQ(CompilationReasonFromName("install-with-dex-metadata"),
+            CompilationReason::kInstallWithDexMetadata);
+  ASSERT_EQ(CompilationReasonFromName("prebuilt"),
+            CompilationReason::kPrebuilt);
+  ASSERT_EQ(CompilationReasonFromName("cmdline"),
+            CompilationReason::kCmdLine);
+  ASSERT_EQ(CompilationReasonFromName("error"),
+            CompilationReason::kError);
+}
+
+TEST(CompilerReason, Name) {
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kUnknown),
+            "unknown");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kFirstBoot),
+            "first-boot");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kBootAfterOTA),
+            "boot-after-ota");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kPostBoot),
+            "post-boot");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstall),
+            "install");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallFast),
+            "install-fast");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulk),
+            "install-bulk");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkSecondary),
+            "install-bulk-secondary");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkDowngraded),
+            "install-bulk-downgraded");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkSecondaryDowngraded),
+            "install-bulk-secondary-downgraded");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kBgDexopt),
+            "bg-dexopt");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kABOTA),
+            "ab-ota");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInactive),
+            "inactive");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kShared),
+            "shared");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallWithDexMetadata),
+            "install-with-dex-metadata");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kPrebuilt),
+            "prebuilt");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kCmdLine),
+            "cmdline");
+  ASSERT_EQ(CompilationReasonName(CompilationReason::kError),
+            "error");
+}
 }  // namespace metrics
 }  // namespace art
 
diff --git a/libartbase/base/metrics/metrics_test.h b/libartbase/base/metrics/metrics_test.h
index 48fd517..3e8b42a 100644
--- a/libartbase/base/metrics/metrics_test.h
+++ b/libartbase/base/metrics/metrics_test.h
@@ -33,7 +33,7 @@
 // test cases to test specific behaviors.
 class TestBackendBase : public MetricsBackend {
  public:
-  void BeginSession([[maybe_unused]] const SessionData& session_data) override {}
+  void BeginOrUpdateSession([[maybe_unused]] const SessionData& session_data) override {}
 
   void BeginReport([[maybe_unused]] uint64_t timestamp_since_start_ms) override {}