Loading services/surfaceflinger/SurfaceFlinger.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -494,6 +494,7 @@ void SurfaceFlinger::bootFinished() ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); mFrameTracer->initialize(); mTimeStats->onBootFinished(); // wait patiently for the window manager death const String16 name("window"); Loading services/surfaceflinger/TimeStats/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -8,12 +8,18 @@ cc_library_shared { "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: [ Loading services/surfaceflinger/TimeStats/TimeStats.cpp +63 −9 Original line number Diff line number Diff line Loading @@ -36,11 +36,50 @@ namespace android { 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(); } Loading Loading @@ -69,7 +108,7 @@ void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, std::strin } if (argsMap.count("-clear")) { clear(); clearAll(); } if (argsMap.count("-enable")) { Loading Loading @@ -594,6 +633,8 @@ void TimeStats::enable() { 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"); } Loading @@ -606,15 +647,20 @@ void TimeStats::disable() { 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; Loading @@ -628,7 +674,15 @@ void TimeStats::clear() { 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() { Loading services/surfaceflinger/TimeStats/TimeStats.h +47 −1 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -37,6 +40,10 @@ class TimeStats { 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; Loading Loading @@ -131,6 +138,39 @@ class TimeStats : public android::TimeStats { 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; Loading Loading @@ -167,6 +207,9 @@ public: 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(); Loading @@ -174,7 +217,9 @@ private: 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; Loading @@ -187,6 +232,7 @@ private: 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 Loading services/surfaceflinger/tests/unittests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ cc_test { "perfetto_trace_protos", ], shared_libs: [ "libstatssocket", "libsurfaceflinger", "libtimestats", "libtimestats_proto", Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -494,6 +494,7 @@ void SurfaceFlinger::bootFinished() ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); mFrameTracer->initialize(); mTimeStats->onBootFinished(); // wait patiently for the window manager death const String16 name("window"); Loading
services/surfaceflinger/TimeStats/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -8,12 +8,18 @@ cc_library_shared { "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: [ Loading
services/surfaceflinger/TimeStats/TimeStats.cpp +63 −9 Original line number Diff line number Diff line Loading @@ -36,11 +36,50 @@ namespace android { 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(); } Loading Loading @@ -69,7 +108,7 @@ void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, std::strin } if (argsMap.count("-clear")) { clear(); clearAll(); } if (argsMap.count("-enable")) { Loading Loading @@ -594,6 +633,8 @@ void TimeStats::enable() { 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"); } Loading @@ -606,15 +647,20 @@ void TimeStats::disable() { 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; Loading @@ -628,7 +674,15 @@ void TimeStats::clear() { 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() { Loading
services/surfaceflinger/TimeStats/TimeStats.h +47 −1 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -37,6 +40,10 @@ class TimeStats { 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; Loading Loading @@ -131,6 +138,39 @@ class TimeStats : public android::TimeStats { 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; Loading Loading @@ -167,6 +207,9 @@ public: 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(); Loading @@ -174,7 +217,9 @@ private: 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; Loading @@ -187,6 +232,7 @@ private: 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 Loading
services/surfaceflinger/tests/unittests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ cc_test { "perfetto_trace_protos", ], shared_libs: [ "libstatssocket", "libsurfaceflinger", "libtimestats", "libtimestats_proto", Loading