void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) {
std::unordered_map<CallbackId, CallbackTranslation, CallbackIdHash> callbacksMap;
std::multimap<int32_t, sp<JankDataListener>> jankListenersMap;
{
std::lock_guard<std::mutex> lock(mMutex);
/* This listener knows all the sp<IBinder> to sp<SurfaceControl> for all its registered
* callbackIds, except for when Transactions are merged together. This probably cannot be
* solved before this point because the Transactions could be merged together and applied in
* a different process.
*
* Fortunately, we get all the callbacks for this listener for the same frame together at
* the same time. This means if any Transactions were merged together, we will get their
* callbacks at the same time. We can combine all the sp<IBinder> to sp<SurfaceControl> maps
* for all the callbackIds to generate one super map that contains all the sp<IBinder> to
* 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);
}
}
}
mCallbacks
拷贝到 callbacksMap
。
- 遍历
listenerStats
中的 cllbackId
,从 mCallbacks
中移除,因为下面就会处理这些 callbackId
。
for (const auto& transactionStats : listenerStats.transactionStats) {
// handle on commit callbacks
for (auto callbackId : transactionStats.callbackIds) {
if (callbackId.type != CallbackId::Type::ON_COMMIT) {
continue;
}
auto& [callbackFunction, callbackSurfaceControls] = callbacksMap[callbackId];
if (!callbackFunction) {
ALOGE("cannot call null callback function, skipping");
continue;
}
std::vector<SurfaceControlStats> surfaceControlStats;
for (const auto& surfaceStats : transactionStats.surfaceStats) {
surfaceControlStats
.emplace_back(callbacksMap[callbackId]
.surfaceControls[surfaceStats.surfaceControl],
transactionStats.latchTime, surfaceStats.acquireTime,
transactionStats.presentFence,
surfaceStats.previousReleaseFence, surfaceStats.transformHint,
surfaceStats.eventStats, surfaceStats.currentMaxAcquiredBufferCount);
}
callbackFunction(transactionStats.latchTime, transactionStats.presentFence,
surfaceControlStats);
}
// handle on complete callbacks
for (auto callbackId : transactionStats.callbackIds) {
if (callbackId.type != CallbackId::Type::ON_COMPLETE) {
continue;
}
auto& [callbackFunction, callbackSurfaceControls] = callbacksMap[callbackId];
if (!callbackFunction) {
ALOGE("cannot call null callback function, skipping");
continue;
}
std::vector<SurfaceControlStats> surfaceControlStats;
for (const auto& surfaceStats : transactionStats.surfaceStats) {
surfaceControlStats
.emplace_back(callbacksMap[callbackId]
.surfaceControls[surfaceStats.surfaceControl],
transactionStats.latchTime, surfaceStats.acquireTime,
transactionStats.presentFence,
surfaceStats.previousReleaseFence, surfaceStats.transformHint,
surfaceStats.eventStats, surfaceStats.currentMaxAcquiredBufferCount);
if (callbacksMap[callbackId].surfaceControls[surfaceStats.surfaceControl]) {
callbacksMap[callbackId]
.surfaceControls[surfaceStats.surfaceControl]
->setTransformHint(surfaceStats.transformHint);
}
// If there is buffer id set, we look up any pending client release buffer callbacks
// and call them. This is a performance optimization when we have a transaction
// callback and a release buffer callback happening at the same time to avoid an
// additional ipc call from the server.
if (surfaceStats.previousReleaseCallbackId != ReleaseCallbackId::INVALID_ID) {
ReleaseBufferCallback callback;
{
std::scoped_lock<std::mutex> lock(mMutex);
callback = popReleaseBufferCallbackLocked(
surfaceStats.previousReleaseCallbackId);
}
if (callback) {
callback(surfaceStats.previousReleaseCallbackId,
surfaceStats.previousReleaseFence
? surfaceStats.previousReleaseFence
: Fence::NO_FENCE,
surfaceStats.transformHint,
surfaceStats.currentMaxAcquiredBufferCount);
}
}
}
callbackFunction(transactionStats.latchTime, transactionStats.presentFence,
surfaceControlStats);
}