Loading cmds/dumpstate/dumpstate.cpp +19 −14 Original line number Diff line number Diff line Loading @@ -1545,11 +1545,7 @@ static Dumpstate::RunStatus dumpstate() { * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport * with the caller. */ static Dumpstate::RunStatus DumpstateDefault() { // Invoking the following dumpsys calls before DumpTraces() to try and // keep the system stats as close to its initial state as possible. RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical); Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() { // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the // buffer. DoLogcat(); Loading Loading @@ -1634,6 +1630,7 @@ static void DumpstateRadioCommon() { // This method collects dumpsys for telephony debugging only static void DumpstateTelephonyOnly() { DurationReporter duration_reporter("DUMPSTATE"); const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build(); DumpstateRadioCommon(); Loading Loading @@ -2353,11 +2350,6 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n", calling_uid, calling_package.c_str()); if (CalledByApi()) { // If the output needs to be copied over to the caller's fd, get user consent. android::String16 package(calling_package.c_str()); CheckUserConsent(calling_uid, package); } // Redirect output if needed bool is_redirecting = options_->OutputToFile(); Loading Loading @@ -2500,13 +2492,23 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, PrintHeader(); if (options_->telephony_only) { MaybeCheckUserConsent(calling_uid, calling_package); DumpstateTelephonyOnly(); DumpstateBoard(); } else if (options_->wifi_only) { MaybeCheckUserConsent(calling_uid, calling_package); DumpstateWifiOnly(); } else { // Invoking the critical dumpsys calls before DumpTraces() to try and // keep the system stats as close to its initial state as possible. RunDumpsysCritical(); // Run consent check only after critical dumpsys has finished -- so the consent // isn't going to pollute the system state / logs. MaybeCheckUserConsent(calling_uid, calling_package); // Dump state for the default case. This also drops root. RunStatus s = DumpstateDefault(); RunStatus s = DumpstateDefaultAfterCritical(); if (s != RunStatus::OK) { if (s == RunStatus::USER_CONSENT_DENIED) { HandleUserConsentDenied(); Loading Loading @@ -2591,17 +2593,20 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, : RunStatus::OK; } void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) { if (calling_uid == AID_SHELL) { void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) { if (calling_uid == AID_SHELL || !CalledByApi()) { // No need to get consent for shell triggered dumpstates, or not through // bugreporting API (i.e. no fd to copy back). return; } consent_callback_ = new ConsentCallback(); const String16 incidentcompanion("incidentcompanion"); sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion)); android::String16 package(calling_package.c_str()); if (ics != nullptr) { MYLOGD("Checking user consent via incidentcompanion service\n"); android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport( calling_uid, calling_package, String16(), String16(), calling_uid, package, String16(), String16(), 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get()); } else { MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n"); Loading cmds/dumpstate/dumpstate.h +3 −1 Original line number Diff line number Diff line Loading @@ -486,7 +486,9 @@ class Dumpstate { private: RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package); void CheckUserConsent(int32_t calling_uid, const android::String16& calling_package); RunStatus DumpstateDefaultAfterCritical(); void MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package); // Removes the in progress files output files (tmp file, zip/txt file, screenshot), // but leaves the log file alone. Loading include/input/InputTransport.h +8 −3 Original line number Diff line number Diff line Loading @@ -121,11 +121,16 @@ struct InputMessage { float yCursorPosition; uint32_t pointerCount; uint32_t empty3; // Note that PointerCoords requires 8 byte alignment. /** * The "pointers" field must be the last field of the struct InputMessage. * When we send the struct InputMessage across the socket, we are not * writing the entire "pointers" array, but only the pointerCount portion * of it as an optimization. Adding a field after "pointers" would break this. */ struct Pointer { PointerProperties properties; PointerCoords coords; } pointers[MAX_POINTERS]; } pointers[MAX_POINTERS] __attribute__((aligned(8))); int32_t getActionId() const { uint32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) Loading @@ -141,7 +146,7 @@ struct InputMessage { struct Finished { uint32_t seq; bool handled; uint32_t handled; // actually a bool, but we must maintain 8-byte alignment inline size_t size() const { return sizeof(Finished); Loading libs/gui/BLASTBufferQueue.cpp +41 −15 Original line number Diff line number Diff line Loading @@ -14,6 +14,9 @@ * limitations under the License. */ #undef LOG_TAG #define LOG_TAG "BLASTBufferQueue" #include <gui/BLASTBufferQueue.h> #include <gui/BufferItemConsumer.h> Loading @@ -24,8 +27,14 @@ using namespace std::chrono_literals; namespace android { BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height) : mSurfaceControl(surface), mWidth(width), mHeight(height) { : mSurfaceControl(surface), mPendingCallbacks(0), mWidth(width), mHeight(height), mNextTransaction(nullptr) { BufferQueue::createBufferQueue(&mProducer, &mConsumer); mConsumer->setMaxBufferCount(MAX_BUFFERS); mProducer->setMaxDequeuedBufferCount(MAX_BUFFERS - 1); mBufferItemConsumer = new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true); mBufferItemConsumer->setName(String8("BLAST Consumer")); Loading @@ -34,6 +43,8 @@ BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight); mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888); mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint()); mAcquired = false; } void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) { Loading @@ -59,20 +70,32 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence const std::vector<SurfaceControlStats>& stats) { std::unique_lock _lock{mMutex}; if (stats.size() > 0 && mNextCallbackBufferItem.mGraphicBuffer != nullptr) { if (stats.size() > 0 && !mShadowQueue.empty()) { mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem, stats[0].previousReleaseFence ? stats[0].previousReleaseFence : Fence::NO_FENCE); mAcquired = false; mNextCallbackBufferItem = BufferItem(); mBufferItemConsumer->setTransformHint(stats[0].transformHint); } mDequeueWaitCV.notify_all(); mPendingCallbacks--; processNextBufferLocked(); mCallbackCV.notify_all(); decStrong((void*)transactionCallbackThunk); } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { std::unique_lock _lock{mMutex}; void BLASTBufferQueue::processNextBufferLocked() { if (mShadowQueue.empty()) { return; } if (mAcquired) { return; } BufferItem item = std::move(mShadowQueue.front()); mShadowQueue.pop(); SurfaceComposerClient::Transaction localTransaction; bool applyTransaction = true; Loading @@ -83,11 +106,11 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { applyTransaction = false; } int status = OK; mNextCallbackBufferItem = mLastSubmittedBufferItem; mLastSubmittedBufferItem = BufferItem(); status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false); status_t status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false); mAcquired = true; if (status != OK) { ALOGE("Failed to acquire?"); } Loading @@ -99,7 +122,6 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { return; } // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); Loading @@ -112,17 +134,21 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { t->setCrop(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()}); if (applyTransaction) { ALOGE("Apply transaction"); t->apply(); if (mNextCallbackBufferItem.mGraphicBuffer != nullptr) { mDequeueWaitCV.wait_for(_lock, 5000ms); } } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { std::lock_guard _lock{mMutex}; // add to shadow queue mShadowQueue.push(item); processNextBufferLocked(); mPendingCallbacks++; } void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) { std::unique_lock _lock{mMutex}; std::lock_guard _lock{mMutex}; mNextTransaction = t; } Loading libs/gui/SurfaceComposerClient.cpp +28 −27 Original line number Diff line number Diff line Loading @@ -189,48 +189,49 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( } void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { std::unordered_map<CallbackId, CallbackTranslation> callbacksMap; { 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. * 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. * 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. */ std::unordered_map<sp<IBinder>, sp<SurfaceControl>, SurfaceComposerClient::IBinderHash> surfaceControls; callbacksMap = mCallbacks; for (const auto& transactionStats : listenerStats.transactionStats) { for (auto callbackId : transactionStats.callbackIds) { auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId]; surfaceControls.insert(callbackSurfaceControls.begin(), callbackSurfaceControls.end()); for (auto& callbackId : transactionStats.callbackIds) { mCallbacks.erase(callbackId); } } } for (const auto& transactionStats : listenerStats.transactionStats) { for (auto callbackId : transactionStats.callbackIds) { auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId]; 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(surfaceControls[surfaceStats.surfaceControl], surfaceStats.acquireTime, surfaceStats.previousReleaseFence, surfaceStats.transformHint); surfaceControls[surfaceStats.surfaceControl]->setTransformHint( surfaceControlStats .emplace_back(callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl], surfaceStats.acquireTime, surfaceStats.previousReleaseFence, surfaceStats.transformHint); callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl] ->setTransformHint(surfaceStats.transformHint); } callbackFunction(transactionStats.latchTime, transactionStats.presentFence, surfaceControlStats); mCallbacks.erase(callbackId); } } } Loading Loading
cmds/dumpstate/dumpstate.cpp +19 −14 Original line number Diff line number Diff line Loading @@ -1545,11 +1545,7 @@ static Dumpstate::RunStatus dumpstate() { * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport * with the caller. */ static Dumpstate::RunStatus DumpstateDefault() { // Invoking the following dumpsys calls before DumpTraces() to try and // keep the system stats as close to its initial state as possible. RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical); Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() { // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the // buffer. DoLogcat(); Loading Loading @@ -1634,6 +1630,7 @@ static void DumpstateRadioCommon() { // This method collects dumpsys for telephony debugging only static void DumpstateTelephonyOnly() { DurationReporter duration_reporter("DUMPSTATE"); const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build(); DumpstateRadioCommon(); Loading Loading @@ -2353,11 +2350,6 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n", calling_uid, calling_package.c_str()); if (CalledByApi()) { // If the output needs to be copied over to the caller's fd, get user consent. android::String16 package(calling_package.c_str()); CheckUserConsent(calling_uid, package); } // Redirect output if needed bool is_redirecting = options_->OutputToFile(); Loading Loading @@ -2500,13 +2492,23 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, PrintHeader(); if (options_->telephony_only) { MaybeCheckUserConsent(calling_uid, calling_package); DumpstateTelephonyOnly(); DumpstateBoard(); } else if (options_->wifi_only) { MaybeCheckUserConsent(calling_uid, calling_package); DumpstateWifiOnly(); } else { // Invoking the critical dumpsys calls before DumpTraces() to try and // keep the system stats as close to its initial state as possible. RunDumpsysCritical(); // Run consent check only after critical dumpsys has finished -- so the consent // isn't going to pollute the system state / logs. MaybeCheckUserConsent(calling_uid, calling_package); // Dump state for the default case. This also drops root. RunStatus s = DumpstateDefault(); RunStatus s = DumpstateDefaultAfterCritical(); if (s != RunStatus::OK) { if (s == RunStatus::USER_CONSENT_DENIED) { HandleUserConsentDenied(); Loading Loading @@ -2591,17 +2593,20 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, : RunStatus::OK; } void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) { if (calling_uid == AID_SHELL) { void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) { if (calling_uid == AID_SHELL || !CalledByApi()) { // No need to get consent for shell triggered dumpstates, or not through // bugreporting API (i.e. no fd to copy back). return; } consent_callback_ = new ConsentCallback(); const String16 incidentcompanion("incidentcompanion"); sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion)); android::String16 package(calling_package.c_str()); if (ics != nullptr) { MYLOGD("Checking user consent via incidentcompanion service\n"); android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport( calling_uid, calling_package, String16(), String16(), calling_uid, package, String16(), String16(), 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get()); } else { MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n"); Loading
cmds/dumpstate/dumpstate.h +3 −1 Original line number Diff line number Diff line Loading @@ -486,7 +486,9 @@ class Dumpstate { private: RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package); void CheckUserConsent(int32_t calling_uid, const android::String16& calling_package); RunStatus DumpstateDefaultAfterCritical(); void MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package); // Removes the in progress files output files (tmp file, zip/txt file, screenshot), // but leaves the log file alone. Loading
include/input/InputTransport.h +8 −3 Original line number Diff line number Diff line Loading @@ -121,11 +121,16 @@ struct InputMessage { float yCursorPosition; uint32_t pointerCount; uint32_t empty3; // Note that PointerCoords requires 8 byte alignment. /** * The "pointers" field must be the last field of the struct InputMessage. * When we send the struct InputMessage across the socket, we are not * writing the entire "pointers" array, but only the pointerCount portion * of it as an optimization. Adding a field after "pointers" would break this. */ struct Pointer { PointerProperties properties; PointerCoords coords; } pointers[MAX_POINTERS]; } pointers[MAX_POINTERS] __attribute__((aligned(8))); int32_t getActionId() const { uint32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) Loading @@ -141,7 +146,7 @@ struct InputMessage { struct Finished { uint32_t seq; bool handled; uint32_t handled; // actually a bool, but we must maintain 8-byte alignment inline size_t size() const { return sizeof(Finished); Loading
libs/gui/BLASTBufferQueue.cpp +41 −15 Original line number Diff line number Diff line Loading @@ -14,6 +14,9 @@ * limitations under the License. */ #undef LOG_TAG #define LOG_TAG "BLASTBufferQueue" #include <gui/BLASTBufferQueue.h> #include <gui/BufferItemConsumer.h> Loading @@ -24,8 +27,14 @@ using namespace std::chrono_literals; namespace android { BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height) : mSurfaceControl(surface), mWidth(width), mHeight(height) { : mSurfaceControl(surface), mPendingCallbacks(0), mWidth(width), mHeight(height), mNextTransaction(nullptr) { BufferQueue::createBufferQueue(&mProducer, &mConsumer); mConsumer->setMaxBufferCount(MAX_BUFFERS); mProducer->setMaxDequeuedBufferCount(MAX_BUFFERS - 1); mBufferItemConsumer = new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true); mBufferItemConsumer->setName(String8("BLAST Consumer")); Loading @@ -34,6 +43,8 @@ BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight); mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888); mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint()); mAcquired = false; } void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) { Loading @@ -59,20 +70,32 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence const std::vector<SurfaceControlStats>& stats) { std::unique_lock _lock{mMutex}; if (stats.size() > 0 && mNextCallbackBufferItem.mGraphicBuffer != nullptr) { if (stats.size() > 0 && !mShadowQueue.empty()) { mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem, stats[0].previousReleaseFence ? stats[0].previousReleaseFence : Fence::NO_FENCE); mAcquired = false; mNextCallbackBufferItem = BufferItem(); mBufferItemConsumer->setTransformHint(stats[0].transformHint); } mDequeueWaitCV.notify_all(); mPendingCallbacks--; processNextBufferLocked(); mCallbackCV.notify_all(); decStrong((void*)transactionCallbackThunk); } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { std::unique_lock _lock{mMutex}; void BLASTBufferQueue::processNextBufferLocked() { if (mShadowQueue.empty()) { return; } if (mAcquired) { return; } BufferItem item = std::move(mShadowQueue.front()); mShadowQueue.pop(); SurfaceComposerClient::Transaction localTransaction; bool applyTransaction = true; Loading @@ -83,11 +106,11 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { applyTransaction = false; } int status = OK; mNextCallbackBufferItem = mLastSubmittedBufferItem; mLastSubmittedBufferItem = BufferItem(); status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false); status_t status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false); mAcquired = true; if (status != OK) { ALOGE("Failed to acquire?"); } Loading @@ -99,7 +122,6 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { return; } // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); Loading @@ -112,17 +134,21 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { t->setCrop(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()}); if (applyTransaction) { ALOGE("Apply transaction"); t->apply(); if (mNextCallbackBufferItem.mGraphicBuffer != nullptr) { mDequeueWaitCV.wait_for(_lock, 5000ms); } } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { std::lock_guard _lock{mMutex}; // add to shadow queue mShadowQueue.push(item); processNextBufferLocked(); mPendingCallbacks++; } void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) { std::unique_lock _lock{mMutex}; std::lock_guard _lock{mMutex}; mNextTransaction = t; } Loading
libs/gui/SurfaceComposerClient.cpp +28 −27 Original line number Diff line number Diff line Loading @@ -189,48 +189,49 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( } void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { std::unordered_map<CallbackId, CallbackTranslation> callbacksMap; { 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. * 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. * 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. */ std::unordered_map<sp<IBinder>, sp<SurfaceControl>, SurfaceComposerClient::IBinderHash> surfaceControls; callbacksMap = mCallbacks; for (const auto& transactionStats : listenerStats.transactionStats) { for (auto callbackId : transactionStats.callbackIds) { auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId]; surfaceControls.insert(callbackSurfaceControls.begin(), callbackSurfaceControls.end()); for (auto& callbackId : transactionStats.callbackIds) { mCallbacks.erase(callbackId); } } } for (const auto& transactionStats : listenerStats.transactionStats) { for (auto callbackId : transactionStats.callbackIds) { auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId]; 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(surfaceControls[surfaceStats.surfaceControl], surfaceStats.acquireTime, surfaceStats.previousReleaseFence, surfaceStats.transformHint); surfaceControls[surfaceStats.surfaceControl]->setTransformHint( surfaceControlStats .emplace_back(callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl], surfaceStats.acquireTime, surfaceStats.previousReleaseFence, surfaceStats.transformHint); callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl] ->setTransformHint(surfaceStats.transformHint); } callbackFunction(transactionStats.latchTime, transactionStats.presentFence, surfaceControlStats); mCallbacks.erase(callbackId); } } } Loading