Revert "Revert "[TimeStats] Add callback for global stats""
This reverts commit de64c56f39b03f4908200d1ed2fdc9561f86fe2a.
Reason for revert: Rolling forward with fix
Test: adb shell cmd stats pull-source 10062
Change-Id: I981b12a1c5e69aad0c0d3a409d8b90b3399401f4
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index 20c2218..7ff2594 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -8,12 +8,18 @@
"libcutils",
"liblog",
"libprotobuf-cpp-lite",
+ "libstatslog",
+ "libstatspull",
+ "libstatssocket",
"libtimestats_proto",
"libui",
"libutils",
],
export_include_dirs: ["."],
export_shared_lib_headers: [
+ "libstatslog",
+ "libstatspull",
+ "libstatssocket",
"libtimestats_proto",
],
cppflags: [
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 0939fa4..44a59fd 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -36,11 +36,50 @@
namespace impl {
-TimeStats::TimeStats() {
+status_pull_atom_return_t TimeStats::pullGlobalAtomCallback(int32_t atom_tag,
+ pulled_stats_event_list* data,
+ void* cookie) {
+ impl::TimeStats* timeStats = reinterpret_cast<impl::TimeStats*>(cookie);
+ if (atom_tag != android::util::SURFACEFLINGER_STATS_GLOBAL_INFO) {
+ return STATS_PULL_SKIP;
+ }
+
+ std::lock_guard<std::mutex> lock(timeStats->mMutex);
+
+ const auto& stats = timeStats->mTimeStats;
+ if (stats.statsStart == 0) {
+ return STATS_PULL_SKIP;
+ }
+ timeStats->flushPowerTimeLocked();
+
+ struct stats_event* event = timeStats->mStatsDelegate->addStatsEventToPullData(data);
+ timeStats->mStatsDelegate->statsEventSetAtomId(event,
+ android::util::SURFACEFLINGER_STATS_GLOBAL_INFO);
+ timeStats->mStatsDelegate->statsEventWriteInt64(event, stats.totalFrames);
+ timeStats->mStatsDelegate->statsEventWriteInt64(event, stats.missedFrames);
+ timeStats->mStatsDelegate->statsEventWriteInt64(event, stats.clientCompositionFrames);
+ timeStats->mStatsDelegate->statsEventWriteInt64(event, stats.displayOnTime);
+ timeStats->mStatsDelegate->statsEventWriteInt64(event, stats.presentToPresent.totalTime());
+ timeStats->mStatsDelegate->statsEventBuild(event);
+ timeStats->clearGlobalLocked();
+
+ return STATS_PULL_SUCCESS;
+}
+
+TimeStats::TimeStats() : TimeStats(nullptr) {}
+
+TimeStats::TimeStats(std::unique_ptr<StatsEventDelegate> statsDelegate) {
+ if (statsDelegate != nullptr) {
+ mStatsDelegate = std::move(statsDelegate);
+ }
+}
+
+void TimeStats::onBootFinished() {
// Temporarily enable TimeStats by default. Telemetry is disabled while
// we move onto statsd, so TimeStats is currently not exercised at all
- // during testing.
- // TODO: remove this.
+ // during testing without enabling by default.
+ // TODO: remove this, as we should only be paying this overhead on devices
+ // where statsd exists.
enable();
}
@@ -69,7 +108,7 @@
}
if (argsMap.count("-clear")) {
- clear();
+ clearAll();
}
if (argsMap.count("-enable")) {
@@ -594,6 +633,8 @@
mEnabled.store(true);
mTimeStats.statsStart = static_cast<int64_t>(std::time(0));
mPowerTime.prevTime = systemTime();
+ mStatsDelegate->registerStatsPullAtomCallback(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
+ TimeStats::pullGlobalAtomCallback, nullptr, this);
ALOGD("Enabled");
}
@@ -606,15 +647,20 @@
flushPowerTimeLocked();
mEnabled.store(false);
mTimeStats.statsEnd = static_cast<int64_t>(std::time(0));
+ mStatsDelegate->unregisterStatsPullAtomCallback(
+ android::util::SURFACEFLINGER_STATS_GLOBAL_INFO);
ALOGD("Disabled");
}
-void TimeStats::clear() {
+void TimeStats::clearAll() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ clearGlobalLocked();
+ clearLayersLocked();
+}
+
+void TimeStats::clearGlobalLocked() {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
- mTimeStatsTracker.clear();
- mTimeStats.stats.clear();
mTimeStats.statsStart = (mEnabled.load() ? static_cast<int64_t>(std::time(0)) : 0);
mTimeStats.statsEnd = 0;
mTimeStats.totalFrames = 0;
@@ -628,7 +674,15 @@
mPowerTime.prevTime = systemTime();
mGlobalRecord.prevPresentTime = 0;
mGlobalRecord.presentFences.clear();
- ALOGD("Cleared");
+ ALOGD("Cleared global stats");
+}
+
+void TimeStats::clearLayersLocked() {
+ ATRACE_CALL();
+
+ mTimeStatsTracker.clear();
+ mTimeStats.stats.clear();
+ ALOGD("Cleared layer stats");
}
bool TimeStats::isEnabled() {
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 65e5cf4..5cd421c 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -17,6 +17,9 @@
#pragma once
#include <hardware/hwcomposer_defs.h>
+#include <stats_event.h>
+#include <stats_pull_atom_callback.h>
+#include <statslog.h>
#include <timestatsproto/TimeStatsHelper.h>
#include <timestatsproto/TimeStatsProtoHeader.h>
#include <ui/FenceTime.h>
@@ -37,6 +40,10 @@
public:
virtual ~TimeStats() = default;
+ // Called once boot has been finished to perform additional capabilities,
+ // e.g. registration to statsd.
+ virtual void onBootFinished() = 0;
+
virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
virtual bool isEnabled() = 0;
virtual std::string miniDump() = 0;
@@ -131,6 +138,39 @@
public:
TimeStats();
+ // Delegate to the statsd service and associated APIs.
+ // Production code may use this class directly, whereas unit test may define
+ // a subclass for ease of testing.
+ class StatsEventDelegate {
+ public:
+ virtual ~StatsEventDelegate() = default;
+ virtual struct stats_event* addStatsEventToPullData(pulled_stats_event_list* data) {
+ return add_stats_event_to_pull_data(data);
+ }
+ virtual void registerStatsPullAtomCallback(int32_t atom_tag,
+ stats_pull_atom_callback_t callback,
+ pull_atom_metadata* metadata, void* cookie) {
+ return register_stats_pull_atom_callback(atom_tag, callback, metadata, cookie);
+ }
+
+ virtual void unregisterStatsPullAtomCallback(int32_t atom_tag) {
+ return unregister_stats_pull_atom_callback(atom_tag);
+ }
+
+ virtual void statsEventSetAtomId(struct stats_event* event, uint32_t atom_id) {
+ return stats_event_set_atom_id(event, atom_id);
+ }
+
+ virtual void statsEventWriteInt64(struct stats_event* event, int64_t field) {
+ return stats_event_write_int64(event, field);
+ }
+
+ virtual void statsEventBuild(struct stats_event* event) { return stats_event_build(event); }
+ };
+ // For testing only for injecting custom dependencies.
+ TimeStats(std::unique_ptr<StatsEventDelegate> statsDelegate);
+
+ void onBootFinished() override;
void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
bool isEnabled() override;
std::string miniDump() override;
@@ -167,6 +207,9 @@
static const size_t MAX_NUM_TIME_RECORDS = 64;
private:
+ static status_pull_atom_return_t pullGlobalAtomCallback(int32_t atom_tag,
+ pulled_stats_event_list* data,
+ void* cookie);
bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord);
void flushAvailableRecordsToStatsLocked(int32_t layerId);
void flushPowerTimeLocked();
@@ -174,7 +217,9 @@
void enable();
void disable();
- void clear();
+ void clearAll();
+ void clearGlobalLocked();
+ void clearLayersLocked();
void dump(bool asProto, std::optional<uint32_t> maxLayers, std::string& result);
std::atomic<bool> mEnabled = false;
@@ -187,6 +232,7 @@
static const size_t MAX_NUM_LAYER_RECORDS = 200;
static const size_t MAX_NUM_LAYER_STATS = 200;
+ std::unique_ptr<StatsEventDelegate> mStatsDelegate = std::make_unique<StatsEventDelegate>();
};
} // namespace impl