db: Store timestamps to the sqlite db.
Test: make
Bug: 137786053
Change-Id: I401e80e6168c717258644a37e9d8753c61248acd
diff --git a/src/db/models.h b/src/db/models.h
index f2ff651..0eac13f 100644
--- a/src/db/models.h
+++ b/src/db/models.h
@@ -306,9 +306,18 @@
return static_cast<int>(last_rowid);
}
- // Returns the row ID that was inserted last.
template <typename... Args>
static bool Delete(DbHandle db, const std::string& sql, Args&&... args) {
+ return ExecuteOnce(db, sql, std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ static bool Update(DbHandle db, const std::string& sql, Args&&... args) {
+ return ExecuteOnce(db, sql, std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ static bool ExecuteOnce(DbHandle db, const std::string& sql, Args&&... args) {
ScopedLockDb lock{db};
DbStatement stmt = DbStatement::Prepare(db, sql, std::forward<Args>(args)...);
@@ -705,6 +714,7 @@
p.temperature,
p.trace_enabled,
p.readahead_enabled,
+ p.intent_started_ns,
p.total_time_ns,
p.report_fully_drawn_ns)) {
return std::nullopt;
@@ -718,13 +728,14 @@
AppLaunchHistoryModel::Temperature temperature,
bool trace_enabled,
bool readahead_enabled,
+ std::optional<uint64_t> intent_started_ns,
std::optional<uint64_t> total_time_ns,
std::optional<uint64_t> report_fully_drawn_ns)
{
const char* sql = "INSERT INTO app_launch_histories (activity_id, temperature, trace_enabled, "
- "readahead_enabled, total_time_ns, "
- "report_fully_drawn_ns) "
- "VALUES (?1, ?2, ?3, ?4, ?5, ?6);";
+ "readahead_enabled, intent_started_ns, "
+ "total_time_ns, report_fully_drawn_ns) "
+ "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);";
std::optional<int> inserted_row_id =
DbQueryBuilder::Insert(db,
@@ -733,6 +744,7 @@
temperature,
trace_enabled,
readahead_enabled,
+ intent_started_ns,
total_time_ns,
report_fully_drawn_ns);
if (!inserted_row_id) {
@@ -745,17 +757,36 @@
p.temperature = temperature;
p.trace_enabled = trace_enabled;
p.readahead_enabled = readahead_enabled;
+ p.intent_started_ns = intent_started_ns;
p.total_time_ns = total_time_ns;
p.report_fully_drawn_ns = report_fully_drawn_ns;
return p;
}
+ static bool UpdateReportFullyDrawn(DbHandle db,
+ int history_id,
+ std::optional<uint64_t> report_fully_drawn_ns)
+ {
+ const char* sql = "UPDATE app_launch_histories "
+ "SET report_fully_drawn_ns = ?1 "
+ "WHERE id = ?2;";
+
+ bool result = DbQueryBuilder::Update(db, sql, history_id, report_fully_drawn_ns);
+
+ if (!result) {
+ LOG(ERROR)<< "Failed to update history_id:"<< history_id
+ << ", report_fully_drawn_ns: " << report_fully_drawn_ns.value();
+ }
+ return result;
+ }
+
int id;
int activity_id; // ActivityModel::id
Temperature temperature = Temperature::kUninitialized;
bool trace_enabled;
bool readahead_enabled;
+ std::optional<uint64_t> intent_started_ns;
std::optional<uint64_t> total_time_ns;
std::optional<uint64_t> report_fully_drawn_ns;
};
@@ -766,7 +797,14 @@
<< "temperature=" << static_cast<int>(p.temperature) << ","
<< "trace_enabled=" << p.trace_enabled << ","
<< "readahead_enabled=" << p.readahead_enabled << ","
- << "total_time_ns=";
+ << "intent_started_ns=";
+ if (p.intent_started_ns) {
+ os << *p.intent_started_ns;
+ } else {
+ os << "(nullopt)";
+ }
+ os << ",";
+ os << "total_time_ns=";
if (p.total_time_ns) {
os << *p.total_time_ns;
} else {
diff --git a/src/manager/event_manager.cc b/src/manager/event_manager.cc
index 434568a..3909bef 100644
--- a/src/manager/event_manager.cc
+++ b/src/manager/event_manager.cc
@@ -68,6 +68,14 @@
std::optional<rxcpp::subscriber<int>> history_id_subscriber_;
rxcpp::observable<int> history_id_observable_;
+ std::optional<uint64_t> intent_started_ns_;
+ std::optional<uint64_t> total_time_ns_;
+
+ // Used by kReportFullyDrawn to find the right history_id.
+ // We assume no interleaving between different sequences.
+ // This assumption is checked in the Java service code.
+ std::optional<uint64_t> recent_history_id_;
+
// labeled as 'shared' due to rx not being able to handle move-only objects.
// lifetime: in practice equivalent to unique_ptr.
std::shared_ptr<prefetcher::ReadAhead> read_ahead_;
@@ -161,6 +169,12 @@
rx_lifetime_ = StartTracing(std::move(component_name));
}
+ if (event.timestamp_nanos >= 0) {
+ intent_started_ns_ = event.timestamp_nanos;
+ } else {
+ LOG(WARNING) << "Negative event timestamp: " << event.timestamp_nanos;
+ }
+
break;
}
case Type::kIntentFailed:
@@ -219,6 +233,9 @@
break;
}
case Type::kActivityLaunchFinished:
+ if (event.timestamp_nanos >= 0) {
+ total_time_ns_ = event.timestamp_nanos;
+ }
RecordDbLaunchHistory();
// Finish tracing and collect trace buffer.
//
@@ -234,9 +251,14 @@
AbortTrace();
AbortReadAhead();
break;
- case Type::kReportFullyDrawn:
- // TODO(yawanng) add handling of this event.
+ case Type::kReportFullyDrawn: {
+ if (!recent_history_id_) {
+ LOG(WARNING) << "Dangling kReportFullyDrawn event";
+ return;
+ }
+ UpdateReportFullyDrawn(event.timestamp_nanos, *recent_history_id_);
break;
+ }
default:
DCHECK(false) << "invalid type: " << event; // binder layer should've rejected this.
LOG(ERROR) << "invalid type: " << event; // binder layer should've rejected this.
@@ -426,11 +448,14 @@
if (!history) {
history_id_subscriber_->on_error(rxcpp::util::make_error_ptr(
std::ios_base::failure("Failed to insert history id")));
+ recent_history_id_ = std::nullopt;
} else {
// Note: we must have already subscribed, or this value will disappear.
LOG(VERBOSE) << "history_id_subscriber on_next history_id=" << history->id;
history_id_subscriber_->on_next(history->id);
history_id_subscriber_->on_completed();
+
+ recent_history_id_ = history->id;
}
history_id_subscriber_ = std::nullopt;
}
@@ -468,8 +493,11 @@
temp,
IsTracing(),
IsReadAhead(),
- /*total_time_ns*/std::nullopt,
- /*report_fully_drawn_ns*/std::nullopt);
+ intent_started_ns_,
+ total_time_ns_,
+ // ReportFullyDrawn event normally occurs after this. Need update later.
+ /* report_fully_drawn_ns= */ std::nullopt);
+ //Repo
if (!alh) {
LOG(WARNING) << "Failed to insert app_launch_histories row";
return std::nullopt;
@@ -478,6 +506,26 @@
LOG(VERBOSE) << "RecordDbLaunchHistory: " << *alh;
return alh;
}
+
+ void UpdateReportFullyDrawn(int history_id, uint64_t timestamp_ns) {
+ if (timestamp_ns < 0) {
+ LOG(WARNING) << "Invalid timestamp_ns: " << timestamp_ns;
+ return;
+ }
+
+ android::ScopedTrace trace{ATRACE_TAG_PACKAGE_MANAGER,
+ "IorapNativeService::UpdateReportFullyDrawn"};
+ db::DbHandle db{db::SchemaModel::GetSingleton()};
+
+ bool result =
+ db::AppLaunchHistoryModel::UpdateReportFullyDrawn(db,
+ history_id,
+ timestamp_ns);
+
+ if (!result) {
+ LOG(WARNING) << "Failed to update app_launch_histories row";
+ }
+ }
};
// Convert callback pattern into reactive pattern.