Loading libs/gui/ITransactionCompletedListener.cpp +46 −42 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #define LOG_TAG "ITransactionCompletedListener" //#define LOG_NDEBUG 0 #include <gui/LayerState.h> #include <gui/ISurfaceComposer.h> #include <gui/ITransactionCompletedListener.h> namespace android { Loading Loading @@ -90,61 +92,63 @@ status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { return err; } status_t SurfaceStats::writeToParcel(Parcel* output) const { status_t err = output->writeStrongBinder(surfaceControl); if (err != NO_ERROR) { return err; JankData::JankData() : frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), jankType(JankType::None) { } err = output->writeInt64(acquireTime); if (err != NO_ERROR) { return err; status_t JankData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, frameVsyncId); SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankType)); return NO_ERROR; } if (previousReleaseFence) { err = output->writeBool(true); if (err != NO_ERROR) { return err; status_t JankData::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readInt64, &frameVsyncId); int32_t jankTypeInt; SAFE_PARCEL(input->readInt32, &jankTypeInt); jankType = static_cast<JankType>(jankTypeInt); return NO_ERROR; } err = output->write(*previousReleaseFence); status_t SurfaceStats::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeStrongBinder, surfaceControl); SAFE_PARCEL(output->writeInt64, acquireTime); if (previousReleaseFence) { SAFE_PARCEL(output->writeBool, true); SAFE_PARCEL(output->write, *previousReleaseFence); } else { err = output->writeBool(false); SAFE_PARCEL(output->writeBool, false); } err = output->writeUint32(transformHint); if (err != NO_ERROR) { return err; SAFE_PARCEL(output->writeUint32, transformHint); SAFE_PARCEL(output->writeParcelable, eventStats); SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankData.size())); for (const auto& data : jankData) { SAFE_PARCEL(output->writeParcelable, data); } err = output->writeParcelable(eventStats); return err; return NO_ERROR; } status_t SurfaceStats::readFromParcel(const Parcel* input) { status_t err = input->readStrongBinder(&surfaceControl); if (err != NO_ERROR) { return err; } err = input->readInt64(&acquireTime); if (err != NO_ERROR) { return err; } SAFE_PARCEL(input->readStrongBinder, &surfaceControl); SAFE_PARCEL(input->readInt64, &acquireTime); bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) { return err; } SAFE_PARCEL(input->readBool, &hasFence); if (hasFence) { previousReleaseFence = new Fence(); err = input->read(*previousReleaseFence); if (err != NO_ERROR) { return err; } } err = input->readUint32(&transformHint); if (err != NO_ERROR) { return err; SAFE_PARCEL(input->read, *previousReleaseFence); } SAFE_PARCEL(input->readUint32, &transformHint); SAFE_PARCEL(input->readParcelable, &eventStats); err = input->readParcelable(&eventStats); return err; int32_t jankData_size = 0; SAFE_PARCEL_READ_SIZE(input->readInt32, &jankData_size, input->dataSize()); for (int i = 0; i < jankData_size; i++) { JankData data; SAFE_PARCEL(input->readParcelable, &data); jankData.push_back(data); } return NO_ERROR; } status_t TransactionStats::writeToParcel(Parcel* output) const { Loading libs/gui/SurfaceComposerClient.cpp +29 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,9 @@ sp<SurfaceComposerClient> SurfaceComposerClient::getDefault() { return DefaultComposerClient::getComposerClient(); } JankDataListener::~JankDataListener() { } // --------------------------------------------------------------------------- // TransactionCompletedListener does not use ANDROID_SINGLETON_STATIC_INSTANCE because it needs Loading Loading @@ -174,6 +177,23 @@ CallbackId TransactionCompletedListener::addCallbackFunction( 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) { Loading @@ -189,6 +209,7 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( 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); Loading @@ -204,6 +225,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener * 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); Loading Loading @@ -236,6 +258,13 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener 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); } } } } Loading libs/gui/include/gui/ITransactionCompletedListener.h +28 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #include "JankInfo.h" #include <binder/IInterface.h> #include <binder/Parcel.h> #include <binder/Parcelable.h> Loading Loading @@ -57,6 +59,27 @@ public: nsecs_t dequeueReadyTime; }; /** * Jank information representing SurfaceFlinger's jank classification about frames for a specific * surface. */ class JankData : public Parcelable { public: status_t writeToParcel(Parcel* output) const override; status_t readFromParcel(const Parcel* input) override; JankData(); JankData(int64_t frameVsyncId, JankType jankType) : frameVsyncId(frameVsyncId), jankType(jankType) {} // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId int64_t frameVsyncId; // The type of jank occurred JankType jankType; }; class SurfaceStats : public Parcelable { public: status_t writeToParcel(Parcel* output) const override; Loading @@ -64,18 +87,21 @@ public: SurfaceStats() = default; SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence, uint32_t hint, FrameEventHistoryStats frameEventStats) uint32_t hint, FrameEventHistoryStats frameEventStats, std::vector<JankData> jankData) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence), transformHint(hint), eventStats(frameEventStats) {} eventStats(frameEventStats), jankData(std::move(jankData)) {} sp<IBinder> surfaceControl; nsecs_t acquireTime = -1; sp<Fence> previousReleaseFence; uint32_t transformHint = 0; FrameEventHistoryStats eventStats; std::vector<JankData> jankData; }; class TransactionStats : public Parcelable { Loading libs/gui/include/gui/SurfaceComposerClient.h +19 −0 Original line number Diff line number Diff line Loading @@ -619,6 +619,12 @@ public: // --------------------------------------------------------------------------- class JankDataListener : public VirtualLightRefBase { public: virtual ~JankDataListener() = 0; virtual void onJankDataAvailable(const std::vector<JankData>& jankData) = 0; }; class TransactionCompletedListener : public BnTransactionCompletedListener { TransactionCompletedListener(); Loading @@ -637,6 +643,7 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { }; std::unordered_map<CallbackId, CallbackTranslation> mCallbacks GUARDED_BY(mMutex); std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex); public: static sp<TransactionCompletedListener> getInstance(); Loading @@ -652,6 +659,18 @@ public: void addSurfaceControlToCallbacks(const sp<SurfaceControl>& surfaceControl, const std::unordered_set<CallbackId>& callbackIds); /* * Adds a jank listener to be informed about SurfaceFlinger's jank classification for a specific * surface. Jank classifications arrive as part of the transaction callbacks about previous * frames submitted to this Surface. */ void addJankListener(const sp<JankDataListener>& listener, sp<SurfaceControl> surfaceControl); /** * Removes a jank listener previously added to addJankCallback. */ void removeJankListener(const sp<JankDataListener>& listener); // Overrides BnTransactionCompletedListener's onTransactionCompleted void onTransactionCompleted(ListenerStats stats) override; }; Loading services/surfaceflinger/BufferQueueLayer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -440,7 +440,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { mName, mFrameTimelineVsyncId); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems.push_back({item, std::move(surfaceFrame)}); mQueueItems.push_back({item, surfaceFrame}); mQueuedFrames++; // Wake up any pending callbacks Loading Loading
libs/gui/ITransactionCompletedListener.cpp +46 −42 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #define LOG_TAG "ITransactionCompletedListener" //#define LOG_NDEBUG 0 #include <gui/LayerState.h> #include <gui/ISurfaceComposer.h> #include <gui/ITransactionCompletedListener.h> namespace android { Loading Loading @@ -90,61 +92,63 @@ status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { return err; } status_t SurfaceStats::writeToParcel(Parcel* output) const { status_t err = output->writeStrongBinder(surfaceControl); if (err != NO_ERROR) { return err; JankData::JankData() : frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), jankType(JankType::None) { } err = output->writeInt64(acquireTime); if (err != NO_ERROR) { return err; status_t JankData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, frameVsyncId); SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankType)); return NO_ERROR; } if (previousReleaseFence) { err = output->writeBool(true); if (err != NO_ERROR) { return err; status_t JankData::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readInt64, &frameVsyncId); int32_t jankTypeInt; SAFE_PARCEL(input->readInt32, &jankTypeInt); jankType = static_cast<JankType>(jankTypeInt); return NO_ERROR; } err = output->write(*previousReleaseFence); status_t SurfaceStats::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeStrongBinder, surfaceControl); SAFE_PARCEL(output->writeInt64, acquireTime); if (previousReleaseFence) { SAFE_PARCEL(output->writeBool, true); SAFE_PARCEL(output->write, *previousReleaseFence); } else { err = output->writeBool(false); SAFE_PARCEL(output->writeBool, false); } err = output->writeUint32(transformHint); if (err != NO_ERROR) { return err; SAFE_PARCEL(output->writeUint32, transformHint); SAFE_PARCEL(output->writeParcelable, eventStats); SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankData.size())); for (const auto& data : jankData) { SAFE_PARCEL(output->writeParcelable, data); } err = output->writeParcelable(eventStats); return err; return NO_ERROR; } status_t SurfaceStats::readFromParcel(const Parcel* input) { status_t err = input->readStrongBinder(&surfaceControl); if (err != NO_ERROR) { return err; } err = input->readInt64(&acquireTime); if (err != NO_ERROR) { return err; } SAFE_PARCEL(input->readStrongBinder, &surfaceControl); SAFE_PARCEL(input->readInt64, &acquireTime); bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) { return err; } SAFE_PARCEL(input->readBool, &hasFence); if (hasFence) { previousReleaseFence = new Fence(); err = input->read(*previousReleaseFence); if (err != NO_ERROR) { return err; } } err = input->readUint32(&transformHint); if (err != NO_ERROR) { return err; SAFE_PARCEL(input->read, *previousReleaseFence); } SAFE_PARCEL(input->readUint32, &transformHint); SAFE_PARCEL(input->readParcelable, &eventStats); err = input->readParcelable(&eventStats); return err; int32_t jankData_size = 0; SAFE_PARCEL_READ_SIZE(input->readInt32, &jankData_size, input->dataSize()); for (int i = 0; i < jankData_size; i++) { JankData data; SAFE_PARCEL(input->readParcelable, &data); jankData.push_back(data); } return NO_ERROR; } status_t TransactionStats::writeToParcel(Parcel* output) const { Loading
libs/gui/SurfaceComposerClient.cpp +29 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,9 @@ sp<SurfaceComposerClient> SurfaceComposerClient::getDefault() { return DefaultComposerClient::getComposerClient(); } JankDataListener::~JankDataListener() { } // --------------------------------------------------------------------------- // TransactionCompletedListener does not use ANDROID_SINGLETON_STATIC_INSTANCE because it needs Loading Loading @@ -174,6 +177,23 @@ CallbackId TransactionCompletedListener::addCallbackFunction( 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) { Loading @@ -189,6 +209,7 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( 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); Loading @@ -204,6 +225,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener * 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); Loading Loading @@ -236,6 +258,13 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener 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); } } } } Loading
libs/gui/include/gui/ITransactionCompletedListener.h +28 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #include "JankInfo.h" #include <binder/IInterface.h> #include <binder/Parcel.h> #include <binder/Parcelable.h> Loading Loading @@ -57,6 +59,27 @@ public: nsecs_t dequeueReadyTime; }; /** * Jank information representing SurfaceFlinger's jank classification about frames for a specific * surface. */ class JankData : public Parcelable { public: status_t writeToParcel(Parcel* output) const override; status_t readFromParcel(const Parcel* input) override; JankData(); JankData(int64_t frameVsyncId, JankType jankType) : frameVsyncId(frameVsyncId), jankType(jankType) {} // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId int64_t frameVsyncId; // The type of jank occurred JankType jankType; }; class SurfaceStats : public Parcelable { public: status_t writeToParcel(Parcel* output) const override; Loading @@ -64,18 +87,21 @@ public: SurfaceStats() = default; SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence, uint32_t hint, FrameEventHistoryStats frameEventStats) uint32_t hint, FrameEventHistoryStats frameEventStats, std::vector<JankData> jankData) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence), transformHint(hint), eventStats(frameEventStats) {} eventStats(frameEventStats), jankData(std::move(jankData)) {} sp<IBinder> surfaceControl; nsecs_t acquireTime = -1; sp<Fence> previousReleaseFence; uint32_t transformHint = 0; FrameEventHistoryStats eventStats; std::vector<JankData> jankData; }; class TransactionStats : public Parcelable { Loading
libs/gui/include/gui/SurfaceComposerClient.h +19 −0 Original line number Diff line number Diff line Loading @@ -619,6 +619,12 @@ public: // --------------------------------------------------------------------------- class JankDataListener : public VirtualLightRefBase { public: virtual ~JankDataListener() = 0; virtual void onJankDataAvailable(const std::vector<JankData>& jankData) = 0; }; class TransactionCompletedListener : public BnTransactionCompletedListener { TransactionCompletedListener(); Loading @@ -637,6 +643,7 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { }; std::unordered_map<CallbackId, CallbackTranslation> mCallbacks GUARDED_BY(mMutex); std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex); public: static sp<TransactionCompletedListener> getInstance(); Loading @@ -652,6 +659,18 @@ public: void addSurfaceControlToCallbacks(const sp<SurfaceControl>& surfaceControl, const std::unordered_set<CallbackId>& callbackIds); /* * Adds a jank listener to be informed about SurfaceFlinger's jank classification for a specific * surface. Jank classifications arrive as part of the transaction callbacks about previous * frames submitted to this Surface. */ void addJankListener(const sp<JankDataListener>& listener, sp<SurfaceControl> surfaceControl); /** * Removes a jank listener previously added to addJankCallback. */ void removeJankListener(const sp<JankDataListener>& listener); // Overrides BnTransactionCompletedListener's onTransactionCompleted void onTransactionCompleted(ListenerStats stats) override; }; Loading
services/surfaceflinger/BufferQueueLayer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -440,7 +440,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { mName, mFrameTimelineVsyncId); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems.push_back({item, std::move(surfaceFrame)}); mQueueItems.push_back({item, surfaceFrame}); mQueuedFrames++; // Wake up any pending callbacks Loading