Add Shared timeline jank classification listener (1/2)
Adds the ability to register a listener that gets informed about
SF' jank classifications via the TransactionCompleted interface
Bug: 17475548
Test: FrameTimelineTest
Test: Register listener, ensure data flows back
Change-Id: Ie42c508da605c03569eadab6ab18b7315b35d247
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 47a08ab..9ed7d1c 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -125,6 +125,9 @@
return DefaultComposerClient::getComposerClient();
}
+JankDataListener::~JankDataListener() {
+}
+
// ---------------------------------------------------------------------------
// TransactionCompletedListener does not use ANDROID_SINGLETON_STATIC_INSTANCE because it needs
@@ -174,6 +177,23 @@
return callbackId;
}
+void TransactionCompletedListener::addJankListener(const sp<JankDataListener>& listener,
+ sp<SurfaceControl> surfaceControl) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mJankListeners.insert({surfaceControl->getHandle(), listener});
+}
+
+void TransactionCompletedListener::removeJankListener(const sp<JankDataListener>& listener) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ for (auto it = mJankListeners.begin(); it != mJankListeners.end();) {
+ if (it->second == listener) {
+ it = mJankListeners.erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+
void TransactionCompletedListener::addSurfaceControlToCallbacks(
const sp<SurfaceControl>& surfaceControl,
const std::unordered_set<CallbackId>& callbackIds) {
@@ -189,6 +209,7 @@
void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) {
std::unordered_map<CallbackId, CallbackTranslation> callbacksMap;
+ std::multimap<sp<IBinder>, sp<JankDataListener>> jankListenersMap;
{
std::lock_guard<std::mutex> lock(mMutex);
@@ -204,6 +225,7 @@
* sp<SurfaceControl> that could possibly exist for the callbacks.
*/
callbacksMap = mCallbacks;
+ jankListenersMap = mJankListeners;
for (const auto& transactionStats : listenerStats.transactionStats) {
for (auto& callbackId : transactionStats.callbackIds) {
mCallbacks.erase(callbackId);
@@ -236,6 +258,13 @@
callbackFunction(transactionStats.latchTime, transactionStats.presentFence,
surfaceControlStats);
}
+ for (const auto& surfaceStats : transactionStats.surfaceStats) {
+ if (surfaceStats.jankData.empty()) continue;
+ for (auto it = jankListenersMap.find(surfaceStats.surfaceControl);
+ it != jankListenersMap.end(); it++) {
+ it->second->onJankDataAvailable(surfaceStats.jankData);
+ }
+ }
}
}