summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/TransactionCompletedThread.cpp
diff options
context:
space:
mode:
author Xin Li <delphij@google.com> 2020-09-09 20:21:16 -0700
committer Xin Li <delphij@google.com> 2020-09-09 20:21:16 -0700
commitac07d0f5ab16bb9e8bbbabb589d1c7d36817baa9 (patch)
treef7110d50445c67a337105034b1f2db3946a88fef /services/surfaceflinger/TransactionCompletedThread.cpp
parent171cac1b603e4bb83412eb596d05a500af5d7a76 (diff)
parentc83049d93712f12279dbeabfa1857c1921804979 (diff)
Merge Android R
Bug: 168057903 Merged-In: I1428ead11c6c2d6fd107a014df0082fdbfa9ba8a Change-Id: I7e084a4c5a3fd06152ea6f1bfe17c53f95faba79
Diffstat (limited to 'services/surfaceflinger/TransactionCompletedThread.cpp')
-rw-r--r--services/surfaceflinger/TransactionCompletedThread.cpp115
1 files changed, 91 insertions, 24 deletions
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index fd466dedff..ca244934e4 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
//#define LOG_NDEBUG 0
#undef LOG_TAG
#define LOG_TAG "TransactionCompletedThread"
@@ -24,7 +28,6 @@
#include <cinttypes>
#include <binder/IInterface.h>
-#include <gui/ITransactionCompletedListener.h>
#include <utils/RefBase.h>
namespace android {
@@ -58,7 +61,7 @@ TransactionCompletedThread::~TransactionCompletedThread() {
{
std::lock_guard lock(mMutex);
for (const auto& [listener, transactionStats] : mCompletedTransactions) {
- IInterface::asBinder(listener)->unlinkToDeath(mDeathRecipient);
+ listener->unlinkToDeath(mDeathRecipient);
}
}
}
@@ -75,27 +78,59 @@ void TransactionCompletedThread::run() {
mThread = std::thread(&TransactionCompletedThread::threadMain, this);
}
-status_t TransactionCompletedThread::addCallback(const sp<ITransactionCompletedListener>& listener,
- const std::vector<CallbackId>& callbackIds) {
+status_t TransactionCompletedThread::startRegistration(const ListenerCallbacks& listenerCallbacks) {
+ // begin running if not already running
+ run();
std::lock_guard lock(mMutex);
if (!mRunning) {
ALOGE("cannot add callback because the callback thread isn't running");
return BAD_VALUE;
}
- if (mCompletedTransactions.count(listener) == 0) {
- status_t err = IInterface::asBinder(listener)->linkToDeath(mDeathRecipient);
- if (err != NO_ERROR) {
- ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
- return err;
+ auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks);
+ auto& [listener, callbackIds] = listenerCallbacks;
+
+ if (inserted) {
+ if (mCompletedTransactions.count(listener) == 0) {
+ status_t err = listener->linkToDeath(mDeathRecipient);
+ if (err != NO_ERROR) {
+ ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
+ return err;
+ }
}
+ auto& transactionStatsDeque = mCompletedTransactions[listener];
+ transactionStatsDeque.emplace_back(callbackIds);
}
- auto& transactionStatsDeque = mCompletedTransactions[listener];
- transactionStatsDeque.emplace_back(callbackIds);
return NO_ERROR;
}
+status_t TransactionCompletedThread::endRegistration(const ListenerCallbacks& listenerCallbacks) {
+ std::lock_guard lock(mMutex);
+ if (!mRunning) {
+ ALOGE("cannot add callback because the callback thread isn't running");
+ return BAD_VALUE;
+ }
+
+ auto itr = mRegisteringTransactions.find(listenerCallbacks);
+ if (itr == mRegisteringTransactions.end()) {
+ ALOGE("cannot end a registration that does not exist");
+ return BAD_VALUE;
+ }
+
+ mRegisteringTransactions.erase(itr);
+
+ return NO_ERROR;
+}
+
+bool TransactionCompletedThread::isRegisteringTransaction(
+ const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
+ ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
+
+ auto itr = mRegisteringTransactions.find(listenerCallbacks);
+ return itr != mRegisteringTransactions.end();
+}
+
status_t TransactionCompletedThread::registerPendingCallbackHandle(
const sp<CallbackHandle>& handle) {
std::lock_guard lock(mMutex);
@@ -105,7 +140,7 @@ status_t TransactionCompletedThread::registerPendingCallbackHandle(
}
// If we can't find the transaction stats something has gone wrong. The client should call
- // addCallback before trying to register a pending callback handle.
+ // startRegistration before trying to register a pending callback handle.
TransactionStats* transactionStats;
status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
if (err != NO_ERROR) {
@@ -117,8 +152,11 @@ status_t TransactionCompletedThread::registerPendingCallbackHandle(
return NO_ERROR;
}
-status_t TransactionCompletedThread::addPresentedCallbackHandles(
+status_t TransactionCompletedThread::finalizePendingCallbackHandles(
const std::deque<sp<CallbackHandle>>& handles) {
+ if (handles.empty()) {
+ return NO_ERROR;
+ }
std::lock_guard lock(mMutex);
if (!mRunning) {
ALOGE("cannot add presented callback handle because the callback thread isn't running");
@@ -158,7 +196,7 @@ status_t TransactionCompletedThread::addPresentedCallbackHandles(
return NO_ERROR;
}
-status_t TransactionCompletedThread::addUnpresentedCallbackHandle(
+status_t TransactionCompletedThread::registerUnpresentedCallbackHandle(
const sp<CallbackHandle>& handle) {
std::lock_guard lock(mMutex);
if (!mRunning) {
@@ -170,8 +208,8 @@ status_t TransactionCompletedThread::addUnpresentedCallbackHandle(
}
status_t TransactionCompletedThread::findTransactionStats(
- const sp<ITransactionCompletedListener>& listener,
- const std::vector<CallbackId>& callbackIds, TransactionStats** outTransactionStats) {
+ const sp<IBinder>& listener, const std::vector<CallbackId>& callbackIds,
+ TransactionStats** outTransactionStats) {
auto& transactionStatsDeque = mCompletedTransactions[listener];
// Search back to front because the most recent transactions are at the back of the deque
@@ -189,7 +227,7 @@ status_t TransactionCompletedThread::findTransactionStats(
status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
// If we can't find the transaction stats something has gone wrong. The client should call
- // addCallback before trying to add a presnted callback handle.
+ // startRegistration before trying to add a callback handle.
TransactionStats* transactionStats;
status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
if (err != NO_ERROR) {
@@ -202,8 +240,13 @@ status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>&
// destroyed the client side is dead and there won't be anyone to send the callback to.
sp<IBinder> surfaceControl = handle->surfaceControl.promote();
if (surfaceControl) {
+ FrameEventHistoryStats eventStats(handle->frameNumber,
+ handle->gpuCompositionDoneFence->getSnapshot().fence,
+ handle->compositorTiming, handle->refreshStartTime,
+ handle->dequeueReadyTime);
transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
- handle->previousReleaseFence);
+ handle->previousReleaseFence,
+ handle->transformHint, eventStats);
}
return NO_ERROR;
}
@@ -239,6 +282,13 @@ void TransactionCompletedThread::threadMain() {
while (transactionStatsItr != transactionStatsDeque.end()) {
auto& transactionStats = *transactionStatsItr;
+ // If this transaction is still registering, it is not safe to send a callback
+ // because there could be surface controls that haven't been added to
+ // transaction stats or mPendingTransactions.
+ if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
+ break;
+ }
+
// If we are still waiting on the callback handles for this transaction, stop
// here because all transaction callbacks for the same listener must come in order
auto pendingTransactions = mPendingTransactions.find(listener);
@@ -262,12 +312,26 @@ void TransactionCompletedThread::threadMain() {
// If the listener has completed transactions
if (!listenerStats.transactionStats.empty()) {
// If the listener is still alive
- if (IInterface::asBinder(listener)->isBinderAlive()) {
- // Send callback
- listenerStats.listener->onTransactionCompleted(listenerStats);
- IInterface::asBinder(listener)->unlinkToDeath(mDeathRecipient);
+ if (listener->isBinderAlive()) {
+ // Send callback. The listener stored in listenerStats
+ // comes from the cross-process setTransactionState call to
+ // SF. This MUST be an ITransactionCompletedListener. We
+ // keep it as an IBinder due to consistency reasons: if we
+ // interface_cast at the IPC boundary when reading a Parcel,
+ // we get pointers that compare unequal in the SF process.
+ interface_cast<ITransactionCompletedListener>(listenerStats.listener)
+ ->onTransactionCompleted(listenerStats);
+ if (transactionStatsDeque.empty()) {
+ listener->unlinkToDeath(mDeathRecipient);
+ completedTransactionsItr =
+ mCompletedTransactions.erase(completedTransactionsItr);
+ } else {
+ completedTransactionsItr++;
+ }
+ } else {
+ completedTransactionsItr =
+ mCompletedTransactions.erase(completedTransactionsItr);
}
- completedTransactionsItr = mCompletedTransactions.erase(completedTransactionsItr);
} else {
completedTransactionsItr++;
}
@@ -297,8 +361,11 @@ void TransactionCompletedThread::threadMain() {
// -----------------------------------------------------------------------
-CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
+CallbackHandle::CallbackHandle(const sp<IBinder>& transactionListener,
const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
: listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
} // namespace android
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"