event_manager: Change compiled trace search strategy and
disable trace when isReadAhead.

(1) Get compiled trace file path from sqlite.
(2) If not exists, try the prebuilt path.

Measured the overhead of looking up compiled trace path in db.
It's less than 1 ms.

Bug: 140429498
Test: Make
Test: Run an app with a compiled trace and path stored in db.
Prefetching is preformed and tracing is not.
Test: atest --host -v iorapd-host-tests
Change-Id: I965bc34ba7ed578031c696967e4386495e3ef21a
diff --git a/src/db/app_component_name.h b/src/db/app_component_name.h
index 19ab4b2..e364163 100644
--- a/src/db/app_component_name.h
+++ b/src/db/app_component_name.h
@@ -21,6 +21,16 @@
   std::string package;
   std::string activity_name;
 
+  // Turns the activity name to the fully qualified name.
+  // For example, if the activity name is ".MainActivity" and the package is
+  // foo.bar. Then the fully qualified name is foo.bar.MainActivity.
+  AppComponentName Canonicalize() const {
+    if (!activity_name.empty() && activity_name[0] == '.') {
+      return {package, package + activity_name};
+    }
+    return {package, activity_name};
+  }
+
   static bool HasAppComponentName(const std::string& s) {
     return s.find('/') != std::string::npos;
   }
diff --git a/src/db/models.h b/src/db/models.h
index 94f82da..90acfc1 100644
--- a/src/db/models.h
+++ b/src/db/models.h
@@ -766,8 +766,8 @@
     std::string query = "SELECT * FROM app_launch_histories "
                         "WHERE activity_id = ?1 AND"
                         "  temperature = 1 AND"
-                        "  trace_enabled = TRUE"
-                        "  intent_started_ns != NULL;";
+                        "  trace_enabled = TRUE AND"
+                        "  intent_started_ns IS NOT NULL;";
     DbStatement stmt = DbStatement::Prepare(db, query, activity_id);
     std::vector<AppLaunchHistoryModel> result;
 
@@ -778,6 +778,7 @@
                                       p.temperature,
                                       p.trace_enabled,
                                       p.readahead_enabled,
+                                      p.intent_started_ns,
                                       p.total_time_ns,
                                       p.report_fully_drawn_ns)) {
       result.push_back(p);
@@ -978,6 +979,28 @@
   }
 
  public:
+  static std::optional<PrefetchFileModel> SelectByPackageNameActivityName(
+      DbHandle db, const std::string& package_name, const std::string& activity_name) {
+    ScopedLockDb lock{db};
+
+    const char* sql =
+      "SELECT prefetch_files.id, prefetch_files.activity_id, prefetch_files.file_path "
+      "FROM prefetch_files "
+      "INNER JOIN activities ON activities.id = prefetch_files.activity_id "
+      "INNER JOIN packages ON packages.id = activities.package_id "
+      "WHERE packages.name = ? AND activities.name = ? ";
+
+    DbStatement stmt = DbStatement::Prepare(db, sql, package_name, activity_name);
+
+    PrefetchFileModel p{db};
+
+    if (!DbQueryBuilder::SelectOnce(stmt, p.id, p.activity_id, p.file_path)) {
+      return std::nullopt;
+    }
+
+    return p;
+  }
+
   static std::optional<PrefetchFileModel> Insert(DbHandle db,
                                                  int activity_id,
                                                  std::string file_path) {
diff --git a/src/manager/event_manager.cc b/src/manager/event_manager.cc
index f6655a6..4f700e5 100644
--- a/src/manager/event_manager.cc
+++ b/src/manager/event_manager.cc
@@ -25,10 +25,12 @@
 #include "prefetcher/read_ahead.h"
 #include "prefetcher/task_id.h"
 
+#include <android-base/chrono_utils.h>
 #include <android-base/properties.h>
 #include <rxcpp/rx.hpp>
 
 #include <atomic>
+#include <filesystem>
 #include <functional>
 #include <utils/Trace.h>
 
@@ -159,13 +161,12 @@
         const std::string& package_name = event.intent_proto->component().package_name();
         const std::string& class_name = event.intent_proto->component().class_name();
         AppComponentName component_name{package_name, class_name};
-
-        component_name_ = component_name;
+        component_name_ = component_name.Canonicalize();
 
         if (allowed_readahead_) {
           StartReadAhead(sequence_id_, component_name);
         }
-        if (allowed_tracing_) {
+        if (allowed_tracing_ && !IsReadAhead()) {
           rx_lifetime_ = StartTracing(std::move(component_name));
         }
 
@@ -212,13 +213,12 @@
           }
 
           AppComponentName component_name = AppComponentName::FromString(title);
-
-          component_name_ = component_name;
+          component_name_ = component_name.Canonicalize();
 
           if (allowed_readahead_ && !IsReadAhead()) {
             StartReadAhead(sequence_id_, component_name);
           }
-          if (allowed_tracing_ && !IsTracing()) {
+          if (allowed_tracing_ && !IsTracing() && !IsReadAhead()) {
             rx_lifetime_ = StartTracing(std::move(component_name));
           }
         } else {
@@ -271,17 +271,63 @@
     return read_ahead_task_.has_value();
   }
 
-  void StartReadAhead(size_t id, const AppComponentName& component_name) {
-    DCHECK(allowed_readahead_);
-    DCHECK(!IsReadAhead());
+  // Gets the compiled trace.
+  // If a compiled trace exists in sqlite, use that one. Otherwise, try
+  // to find a prebuilt one.
+  std::optional<std::string> GetCompiledTrace(const AppComponentName& component_name) {
+    // Firstly, try to find the compiled trace from sqlite.
+    android::base::Timer timer{};
+    db::DbHandle db{db::SchemaModel::GetSingleton()};
+    std::optional<db::PrefetchFileModel> compiled_trace =
+        db::PrefetchFileModel::SelectByPackageNameActivityName(db,
+                                                               component_name.package,
+                                                               component_name.activity_name);
 
-    // This is changed from "/data/misc/iorapd/" for testing purpose.
-    // TODO: b/139831359.
+    std::chrono::milliseconds duration_ms = timer.duration();
+    LOG(DEBUG) << "EventManager: Looking up compiled trace done in "
+               << duration_ms.count() // the count of ticks.
+               << "ms.";
+
+    if (compiled_trace) {
+      if (std::filesystem::exists(compiled_trace->file_path)) {
+        return compiled_trace->file_path;
+      } else {
+        LOG(ERROR) << "Compiled trace in sqlite doesn't exists. file_path: "
+                   << compiled_trace->file_path;
+      }
+    }
+
+    LOG(DEBUG) << "Cannot find compiled trace in sqlite for package_name: "
+               << component_name.package
+               << " activity_name: "
+               << component_name.activity_name;
+
+    // If sqlite doesn't have the compiled trace, try the prebuilt path.
     std::string file_path = "/product/iorap-trace/";
     file_path += component_name.ToMakeFileSafeEncodedPkgString();
     file_path += ".compiled_trace.pb";
 
-    prefetcher::TaskId task{id, std::move(file_path)};
+    if (std::filesystem::exists(file_path)) {
+      return file_path;
+    }
+
+    LOG(ERROR) << "Prebuilt compiled trace doesn't exists. file_path: "
+               << file_path;
+
+    return std::nullopt;
+  }
+
+  void StartReadAhead(size_t id, const AppComponentName& component_name) {
+    DCHECK(allowed_readahead_);
+    DCHECK(!IsReadAhead());
+
+    std::optional<std::string> file_path = GetCompiledTrace(component_name);
+    if (!file_path) {
+      LOG(VERBOSE) << "Cannot find a compiled trace.";
+      return;
+    }
+
+    prefetcher::TaskId task{id, *file_path};
     read_ahead_->BeginTask(task);
     // TODO: non-void return signature?