From c50b4988e93872bfe023a4e099548f84bdfd998d Mon Sep 17 00:00:00 2001 From: Huihong Luo Date: Wed, 24 Nov 2021 12:34:52 -0800 Subject: Migrate ITransactionCompletedListener to AIDL This migrates the c++ interface to aidl. Bug: 225250470 Test: atest libsurfaceflinger_unittest libgui_test SurfaceFlinger_test Change-Id: I997e302ac8c6a23bedefaa5b8272677f3dce54df --- libs/gui/ISurfaceComposer.cpp | 1 + libs/gui/ITransactionCompletedListener.cpp | 71 +----- libs/gui/LayerState.cpp | 1 + libs/gui/SurfaceComposerClient.cpp | 33 ++- .../android/gui/ITransactionCompletedListener.aidl | 31 +++ libs/gui/aidl/android/gui/ListenerStats.aidl | 19 ++ libs/gui/aidl/android/gui/ReleaseCallbackId.aidl | 19 ++ libs/gui/include/gui/ISurfaceComposer.h | 3 +- .../include/gui/ITransactionCompletedListener.h | 271 --------------------- libs/gui/include/gui/LayerState.h | 6 +- libs/gui/include/gui/ListenerStats.h | 225 +++++++++++++++++ libs/gui/include/gui/ReleaseCallbackId.h | 50 ++++ libs/gui/include/gui/SurfaceComposerClient.h | 25 +- 13 files changed, 399 insertions(+), 356 deletions(-) create mode 100644 libs/gui/aidl/android/gui/ITransactionCompletedListener.aidl create mode 100644 libs/gui/aidl/android/gui/ListenerStats.aidl create mode 100644 libs/gui/aidl/android/gui/ReleaseCallbackId.aidl delete mode 100644 libs/gui/include/gui/ITransactionCompletedListener.h create mode 100644 libs/gui/include/gui/ListenerStats.h create mode 100644 libs/gui/include/gui/ReleaseCallbackId.h (limited to 'libs/gui') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index a77ca04943..a0e75ffe49 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -42,6 +42,7 @@ using namespace aidl::android::hardware::graphics; namespace android { +using gui::CallbackId; using gui::DisplayCaptureArgs; using gui::IDisplayEventConnection; using gui::IRegionSamplingListener; diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 2b25b614e9..23d7d500c8 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -21,22 +21,11 @@ #include #include -#include #include +#include #include -namespace android { - -namespace { // Anonymous - -enum class Tag : uint32_t { - ON_TRANSACTION_COMPLETED = IBinder::FIRST_CALL_TRANSACTION, - ON_RELEASE_BUFFER, - ON_TRANSACTION_QUEUE_STALLED, - LAST = ON_TRANSACTION_QUEUE_STALLED, -}; - -} // Anonymous namespace +namespace android::gui { status_t FrameEventHistoryStats::writeToParcel(Parcel* output) const { status_t err = output->writeUint64(frameNumber); @@ -274,60 +263,6 @@ ListenerStats ListenerStats::createEmpty( return listenerStats; } -class BpTransactionCompletedListener : public SafeBpInterface { -public: - explicit BpTransactionCompletedListener(const sp& impl) - : SafeBpInterface(impl, "BpTransactionCompletedListener") { - } - - ~BpTransactionCompletedListener() override; - - void onTransactionCompleted(ListenerStats stats) override { - callRemoteAsync(Tag::ON_TRANSACTION_COMPLETED, - stats); - } - - void onReleaseBuffer(ReleaseCallbackId callbackId, sp releaseFence, - uint32_t currentMaxAcquiredBufferCount) override { - callRemoteAsync(Tag::ON_RELEASE_BUFFER, callbackId, - releaseFence, - currentMaxAcquiredBufferCount); - } - - void onTransactionQueueStalled(const String8& reason) override { - callRemoteAsync< - decltype(&ITransactionCompletedListener:: - onTransactionQueueStalled)>(Tag::ON_TRANSACTION_QUEUE_STALLED, - reason); - } -}; - -// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see -// clang warning -Wweak-vtables) -BpTransactionCompletedListener::~BpTransactionCompletedListener() = default; - -IMPLEMENT_META_INTERFACE(TransactionCompletedListener, "android.gui.ITransactionComposerListener"); - -status_t BnTransactionCompletedListener::onTransact(uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags) { - if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast(Tag::LAST)) { - return BBinder::onTransact(code, data, reply, flags); - } - auto tag = static_cast(code); - switch (tag) { - case Tag::ON_TRANSACTION_COMPLETED: - return callLocalAsync(data, reply, - &ITransactionCompletedListener::onTransactionCompleted); - case Tag::ON_RELEASE_BUFFER: - return callLocalAsync(data, reply, &ITransactionCompletedListener::onReleaseBuffer); - case Tag::ON_TRANSACTION_QUEUE_STALLED: - return callLocalAsync(data, reply, - &ITransactionCompletedListener::onTransactionQueueStalled); - } -} - ListenerCallbacks ListenerCallbacks::filter(CallbackId::Type type) const { std::vector filteredCallbackIds; for (const auto& callbackId : callbackIds) { @@ -366,4 +301,4 @@ status_t ReleaseCallbackId::readFromParcel(const Parcel* input) { const ReleaseCallbackId ReleaseCallbackId::INVALID_ID = ReleaseCallbackId(0, 0); -}; // namespace android +}; // namespace android::gui diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 59b62fe58c..0d1a69b898 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -51,6 +51,7 @@ namespace android { +using gui::CallbackId; using gui::FocusRequest; using gui::WindowInfoHandle; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7085e8a349..d741c99d01 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -314,7 +314,8 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( } } -void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { +binder::Status TransactionCompletedListener::onTransactionCompleted( + const ListenerStats& listenerStats) { std::unordered_map callbacksMap; std::multimap> jankListenersMap; { @@ -454,9 +455,10 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener } } } + return binder::Status::ok(); } -void TransactionCompletedListener::onTransactionQueueStalled(const String8& reason) { +binder::Status TransactionCompletedListener::onTransactionQueueStalled(const std::string& reason) { std::unordered_map> callbackCopy; { std::scoped_lock lock(mMutex); @@ -465,6 +467,7 @@ void TransactionCompletedListener::onTransactionQueueStalled(const String8& reas for (auto const& it : callbackCopy) { it.second(reason.c_str()); } + return binder::Status::ok(); } void TransactionCompletedListener::addQueueStallListener( @@ -478,9 +481,12 @@ void TransactionCompletedListener::removeQueueStallListener(void* id) { mQueueStallListeners.erase(id); } -void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId, - sp releaseFence, - uint32_t currentMaxAcquiredBufferCount) { +binder::Status TransactionCompletedListener::onReleaseBuffer( + const ReleaseCallbackId& callbackId, + const std::optional& releaseFenceFd, + int32_t currentMaxAcquiredBufferCount) { + sp releaseFence(releaseFenceFd ? new Fence(::dup(releaseFenceFd->get())) + : Fence::NO_FENCE); ReleaseBufferCallback callback; { std::scoped_lock lock(mMutex); @@ -489,13 +495,14 @@ void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId, if (!callback) { ALOGE("Could not call release buffer callback, buffer not found %s", callbackId.to_string().c_str()); - return; + return binder::Status::fromExceptionCode(binder::Status::EX_ILLEGAL_ARGUMENT); } std::optional optionalMaxAcquiredBufferCount = - currentMaxAcquiredBufferCount == UINT_MAX + static_cast(currentMaxAcquiredBufferCount) == UINT_MAX ? std::nullopt : std::make_optional(currentMaxAcquiredBufferCount); callback(callbackId, releaseFence, optionalMaxAcquiredBufferCount); + return binder::Status::ok(); } ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLocked( @@ -825,7 +832,11 @@ void SurfaceComposerClient::Transaction::releaseBufferIfOverwriting(const layer_ ->mReleaseCallbackThread .addReleaseCallback(state.bufferData->generateReleaseCallbackId(), fence); } else { - listener->onReleaseBuffer(state.bufferData->generateReleaseCallbackId(), fence, UINT_MAX); + std::optional fenceFd; + if (fence != Fence::NO_FENCE) { + fenceFd = os::ParcelFileDescriptor(base::unique_fd(::dup(fence->get()))); + } + listener->onReleaseBuffer(state.bufferData->generateReleaseCallbackId(), fenceFd, UINT_MAX); } } @@ -2846,7 +2857,11 @@ void ReleaseCallbackThread::threadMain() { while (!callbackInfos.empty()) { auto [callbackId, releaseFence] = callbackInfos.front(); - listener->onReleaseBuffer(callbackId, std::move(releaseFence), UINT_MAX); + std::optional fenceFd; + if (releaseFence != Fence::NO_FENCE) { + fenceFd = os::ParcelFileDescriptor(base::unique_fd(::dup(releaseFence->get()))); + } + listener->onReleaseBuffer(callbackId, fenceFd, UINT_MAX); callbackInfos.pop(); } diff --git a/libs/gui/aidl/android/gui/ITransactionCompletedListener.aidl b/libs/gui/aidl/android/gui/ITransactionCompletedListener.aidl new file mode 100644 index 0000000000..dde4d38cba --- /dev/null +++ b/libs/gui/aidl/android/gui/ITransactionCompletedListener.aidl @@ -0,0 +1,31 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + +import android.gui.ListenerStats; +import android.gui.ReleaseCallbackId; + +/** @hide */ +oneway interface ITransactionCompletedListener { + void onTransactionCompleted(in ListenerStats stats); + + void onReleaseBuffer(in ReleaseCallbackId callbackId, + in @nullable ParcelFileDescriptor releaseFenceFd, + int currentMaxAcquiredBufferCount); + + void onTransactionQueueStalled(@utf8InCpp String name); +} diff --git a/libs/gui/aidl/android/gui/ListenerStats.aidl b/libs/gui/aidl/android/gui/ListenerStats.aidl new file mode 100644 index 0000000000..63248b2bf3 --- /dev/null +++ b/libs/gui/aidl/android/gui/ListenerStats.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + +parcelable ListenerStats cpp_header "gui/ListenerStats.h"; diff --git a/libs/gui/aidl/android/gui/ReleaseCallbackId.aidl b/libs/gui/aidl/android/gui/ReleaseCallbackId.aidl new file mode 100644 index 0000000000..c86de34de9 --- /dev/null +++ b/libs/gui/aidl/android/gui/ReleaseCallbackId.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + +parcelable ReleaseCallbackId cpp_header "gui/ReleaseCallbackId.h"; diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index d517e99fda..d70a7f0f1b 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -23,11 +23,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -66,6 +66,7 @@ using gui::FrameTimelineInfo; using gui::IDisplayEventConnection; using gui::IRegionSamplingListener; using gui::IScreenCaptureListener; +using gui::ListenerCallbacks; using gui::SpHash; namespace gui { diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h deleted file mode 100644 index 453e8f3ef5..0000000000 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "JankInfo.h" - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -namespace android { - -class ITransactionCompletedListener; -class ListenerCallbacks; - -class CallbackId : public Parcelable { -public: - int64_t id; - enum class Type : int32_t { ON_COMPLETE, ON_COMMIT } type; - - CallbackId() {} - CallbackId(int64_t id, Type type) : id(id), type(type) {} - status_t writeToParcel(Parcel* output) const override; - status_t readFromParcel(const Parcel* input) override; - - bool operator==(const CallbackId& rhs) const { return id == rhs.id && type == rhs.type; } -}; - -struct CallbackIdHash { - std::size_t operator()(const CallbackId& key) const { return std::hash()(key.id); } -}; - -class ReleaseCallbackId : public Parcelable { -public: - static const ReleaseCallbackId INVALID_ID; - - uint64_t bufferId; - uint64_t framenumber; - ReleaseCallbackId() {} - ReleaseCallbackId(uint64_t bufferId, uint64_t framenumber) - : bufferId(bufferId), framenumber(framenumber) {} - status_t writeToParcel(Parcel* output) const override; - status_t readFromParcel(const Parcel* input) override; - - bool operator==(const ReleaseCallbackId& rhs) const { - return bufferId == rhs.bufferId && framenumber == rhs.framenumber; - } - bool operator!=(const ReleaseCallbackId& rhs) const { return !operator==(rhs); } - std::string to_string() const { - if (*this == INVALID_ID) return "INVALID_ID"; - - return "bufferId:" + std::to_string(bufferId) + - " framenumber:" + std::to_string(framenumber); - } -}; - -struct ReleaseBufferCallbackIdHash { - std::size_t operator()(const ReleaseCallbackId& key) const { - return std::hash()(key.bufferId); - } -}; - -class FrameEventHistoryStats : public Parcelable { -public: - status_t writeToParcel(Parcel* output) const override; - status_t readFromParcel(const Parcel* input) override; - - FrameEventHistoryStats() = default; - FrameEventHistoryStats(uint64_t fn, const sp& gpuCompFence, CompositorTiming compTiming, - nsecs_t refreshTime, nsecs_t dequeueReadyTime) - : frameNumber(fn), - gpuCompositionDoneFence(gpuCompFence), - compositorTiming(compTiming), - refreshStartTime(refreshTime), - dequeueReadyTime(dequeueReadyTime) {} - - uint64_t frameNumber; - sp gpuCompositionDoneFence; - CompositorTiming compositorTiming; - nsecs_t refreshStartTime; - 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, int32_t jankType) - : frameVsyncId(frameVsyncId), jankType(jankType) {} - - // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId - int64_t frameVsyncId; - - // Bitmask of janks that occurred - int32_t jankType; -}; - -class SurfaceStats : public Parcelable { -public: - status_t writeToParcel(Parcel* output) const override; - status_t readFromParcel(const Parcel* input) override; - - SurfaceStats() = default; - SurfaceStats(const sp& sc, std::variant> acquireTimeOrFence, - const sp& prevReleaseFence, std::optional hint, - uint32_t currentMaxAcquiredBuffersCount, FrameEventHistoryStats frameEventStats, - std::vector jankData, ReleaseCallbackId previousReleaseCallbackId) - : surfaceControl(sc), - acquireTimeOrFence(std::move(acquireTimeOrFence)), - previousReleaseFence(prevReleaseFence), - transformHint(hint), - currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount), - eventStats(frameEventStats), - jankData(std::move(jankData)), - previousReleaseCallbackId(previousReleaseCallbackId) {} - - sp surfaceControl; - std::variant> acquireTimeOrFence = -1; - sp previousReleaseFence; - std::optional transformHint = 0; - uint32_t currentMaxAcquiredBufferCount = 0; - FrameEventHistoryStats eventStats; - std::vector jankData; - ReleaseCallbackId previousReleaseCallbackId; -}; - -class TransactionStats : public Parcelable { -public: - status_t writeToParcel(Parcel* output) const override; - status_t readFromParcel(const Parcel* input) override; - - TransactionStats() = default; - TransactionStats(const std::vector& ids) : callbackIds(ids) {} - TransactionStats(const std::unordered_set& ids) - : callbackIds(ids.begin(), ids.end()) {} - TransactionStats(const std::vector& ids, nsecs_t latch, const sp& present, - const std::vector& surfaces) - : callbackIds(ids), latchTime(latch), presentFence(present), surfaceStats(surfaces) {} - - std::vector callbackIds; - nsecs_t latchTime = -1; - sp presentFence = nullptr; - std::vector surfaceStats; -}; - -class ListenerStats : public Parcelable { -public: - status_t writeToParcel(Parcel* output) const override; - status_t readFromParcel(const Parcel* input) override; - - static ListenerStats createEmpty( - const sp& listener, - const std::unordered_set& callbackIds); - - sp listener; - std::vector transactionStats; -}; - -class ITransactionCompletedListener : public IInterface { -public: - DECLARE_META_INTERFACE(TransactionCompletedListener) - - virtual void onTransactionCompleted(ListenerStats stats) = 0; - - virtual void onReleaseBuffer(ReleaseCallbackId callbackId, sp releaseFence, - uint32_t currentMaxAcquiredBufferCount) = 0; - - virtual void onTransactionQueueStalled(const String8& name) = 0; -}; - -class BnTransactionCompletedListener : public SafeBnInterface { -public: - BnTransactionCompletedListener() - : SafeBnInterface("BnTransactionCompletedListener") {} - - status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags = 0) override; -}; - -class ListenerCallbacks { -public: - ListenerCallbacks(const sp& listener, - const std::unordered_set& callbacks) - : transactionCompletedListener(listener), - callbackIds(callbacks.begin(), callbacks.end()) {} - - ListenerCallbacks(const sp& listener, const std::vector& ids) - : transactionCompletedListener(listener), callbackIds(ids) {} - - bool operator==(const ListenerCallbacks& rhs) const { - if (transactionCompletedListener != rhs.transactionCompletedListener) { - return false; - } - if (callbackIds.empty()) { - return rhs.callbackIds.empty(); - } - return callbackIds.front().id == rhs.callbackIds.front().id; - } - - // Returns a new ListenerCallbacks filtered by type - ListenerCallbacks filter(CallbackId::Type type) const; - - sp transactionCompletedListener; - std::vector callbackIds; -}; - -struct IListenerHash { - std::size_t operator()(const sp& strongPointer) const { - return std::hash{}(strongPointer.get()); - } -}; - -struct CallbackIdsHash { - // CallbackId vectors have several properties that let us get away with this simple hash. - // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is - // empty we can still hash 0. - // 2) CallbackId vectors for the same listener either are identical or contain none of the - // same members. It is sufficient to just check the first CallbackId in the vectors. If - // they match, they are the same. If they do not match, they are not the same. - std::size_t operator()(const std::vector& callbackIds) const { - return std::hash{}((callbackIds.empty()) ? 0 : callbackIds.front().id); - } -}; - -struct ListenerCallbacksHash { - std::size_t HashCombine(size_t value1, size_t value2) const { - return value1 ^ (value2 + 0x9e3779b9 + (value1 << 6) + (value1 >> 2)); - } - - std::size_t operator()(const ListenerCallbacks& listenerCallbacks) const { - struct IListenerHash listenerHasher; - struct CallbackIdsHash callbackIdsHasher; - - std::size_t listenerHash = listenerHasher(listenerCallbacks.transactionCompletedListener); - std::size_t callbackIdsHash = callbackIdsHasher(listenerCallbacks.callbackIds); - - return HashCombine(listenerHash, callbackIdsHash); - } -}; - -} // namespace android diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 45a84f6c66..c5fdf82d4f 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -21,10 +21,10 @@ #include #include +#include #include #include #include -#include #include #include @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,9 @@ class Parcel; using gui::ISurfaceComposerClient; using gui::LayerMetadata; +using gui::ITransactionCompletedListener; +using gui::ReleaseCallbackId; + struct client_cache_t { wp token = nullptr; uint64_t id; diff --git a/libs/gui/include/gui/ListenerStats.h b/libs/gui/include/gui/ListenerStats.h new file mode 100644 index 0000000000..3a12802146 --- /dev/null +++ b/libs/gui/include/gui/ListenerStats.h @@ -0,0 +1,225 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "JankInfo.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace android::gui { + +class CallbackId : public Parcelable { +public: + int64_t id; + enum class Type : int32_t { ON_COMPLETE, ON_COMMIT } type; + + CallbackId() {} + CallbackId(int64_t id, Type type) : id(id), type(type) {} + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + bool operator==(const CallbackId& rhs) const { return id == rhs.id && type == rhs.type; } +}; + +struct CallbackIdHash { + std::size_t operator()(const CallbackId& key) const { return std::hash()(key.id); } +}; + +struct ReleaseBufferCallbackIdHash { + std::size_t operator()(const ReleaseCallbackId& key) const { + return std::hash()(key.bufferId); + } +}; + +class FrameEventHistoryStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + FrameEventHistoryStats() = default; + FrameEventHistoryStats(uint64_t fn, const sp& gpuCompFence, CompositorTiming compTiming, + nsecs_t refreshTime, nsecs_t dequeueReadyTime) + : frameNumber(fn), + gpuCompositionDoneFence(gpuCompFence), + compositorTiming(compTiming), + refreshStartTime(refreshTime), + dequeueReadyTime(dequeueReadyTime) {} + + uint64_t frameNumber; + sp gpuCompositionDoneFence; + CompositorTiming compositorTiming; + nsecs_t refreshStartTime; + 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, int32_t jankType) + : frameVsyncId(frameVsyncId), jankType(jankType) {} + + // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId + int64_t frameVsyncId; + + // Bitmask of janks that occurred + int32_t jankType; +}; + +class SurfaceStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + SurfaceStats() = default; + SurfaceStats(const sp& sc, std::variant> acquireTimeOrFence, + const sp& prevReleaseFence, std::optional hint, + uint32_t currentMaxAcquiredBuffersCount, FrameEventHistoryStats frameEventStats, + std::vector jankData, ReleaseCallbackId previousReleaseCallbackId) + : surfaceControl(sc), + acquireTimeOrFence(std::move(acquireTimeOrFence)), + previousReleaseFence(prevReleaseFence), + transformHint(hint), + currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount), + eventStats(frameEventStats), + jankData(std::move(jankData)), + previousReleaseCallbackId(previousReleaseCallbackId) {} + + sp surfaceControl; + std::variant> acquireTimeOrFence = -1; + sp previousReleaseFence; + std::optional transformHint = 0; + uint32_t currentMaxAcquiredBufferCount = 0; + FrameEventHistoryStats eventStats; + std::vector jankData; + ReleaseCallbackId previousReleaseCallbackId; +}; + +class TransactionStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + TransactionStats() = default; + TransactionStats(const std::vector& ids) : callbackIds(ids) {} + TransactionStats(const std::unordered_set& ids) + : callbackIds(ids.begin(), ids.end()) {} + TransactionStats(const std::vector& ids, nsecs_t latch, const sp& present, + const std::vector& surfaces) + : callbackIds(ids), latchTime(latch), presentFence(present), surfaceStats(surfaces) {} + + std::vector callbackIds; + nsecs_t latchTime = -1; + sp presentFence = nullptr; + std::vector surfaceStats; +}; + +class ListenerStats : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + static ListenerStats createEmpty( + const sp& listener, + const std::unordered_set& callbackIds); + + sp listener; + std::vector transactionStats; +}; + +class ListenerCallbacks { +public: + ListenerCallbacks(const sp& listener, + const std::unordered_set& callbacks) + : transactionCompletedListener(listener), + callbackIds(callbacks.begin(), callbacks.end()) {} + + ListenerCallbacks(const sp& listener, const std::vector& ids) + : transactionCompletedListener(listener), callbackIds(ids) {} + + bool operator==(const ListenerCallbacks& rhs) const { + if (transactionCompletedListener != rhs.transactionCompletedListener) { + return false; + } + if (callbackIds.empty()) { + return rhs.callbackIds.empty(); + } + return callbackIds.front().id == rhs.callbackIds.front().id; + } + + // Returns a new ListenerCallbacks filtered by type + ListenerCallbacks filter(CallbackId::Type type) const; + + sp transactionCompletedListener; + std::vector callbackIds; +}; + +struct IListenerHash { + std::size_t operator()(const sp& strongPointer) const { + return std::hash{}(strongPointer.get()); + } +}; + +struct CallbackIdsHash { + // CallbackId vectors have several properties that let us get away with this simple hash. + // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is + // empty we can still hash 0. + // 2) CallbackId vectors for the same listener either are identical or contain none of the + // same members. It is sufficient to just check the first CallbackId in the vectors. If + // they match, they are the same. If they do not match, they are not the same. + std::size_t operator()(const std::vector& callbackIds) const { + return std::hash{}((callbackIds.empty()) ? 0 : callbackIds.front().id); + } +}; + +struct ListenerCallbacksHash { + std::size_t HashCombine(size_t value1, size_t value2) const { + return value1 ^ (value2 + 0x9e3779b9 + (value1 << 6) + (value1 >> 2)); + } + + std::size_t operator()(const ListenerCallbacks& listenerCallbacks) const { + struct IListenerHash listenerHasher; + struct CallbackIdsHash callbackIdsHasher; + + std::size_t listenerHash = listenerHasher(listenerCallbacks.transactionCompletedListener); + std::size_t callbackIdsHash = callbackIdsHasher(listenerCallbacks.callbackIds); + + return HashCombine(listenerHash, callbackIdsHash); + } +}; + +} // namespace android::gui diff --git a/libs/gui/include/gui/ReleaseCallbackId.h b/libs/gui/include/gui/ReleaseCallbackId.h new file mode 100644 index 0000000000..142ee5a727 --- /dev/null +++ b/libs/gui/include/gui/ReleaseCallbackId.h @@ -0,0 +1,50 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +namespace android::gui { + +class ReleaseCallbackId : public Parcelable { +public: + static const ReleaseCallbackId INVALID_ID; + + uint64_t bufferId; + uint64_t framenumber; + ReleaseCallbackId() {} + ReleaseCallbackId(uint64_t bufferId, uint64_t framenumber) + : bufferId(bufferId), framenumber(framenumber) {} + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + bool operator==(const ReleaseCallbackId& rhs) const { + return bufferId == rhs.bufferId && framenumber == rhs.framenumber; + } + bool operator!=(const ReleaseCallbackId& rhs) const { return !operator==(rhs); } + std::string to_string() const { + if (*this == INVALID_ID) return "INVALID_ID"; + + return "bufferId:" + std::to_string(bufferId) + + " framenumber:" + std::to_string(framenumber); + } +}; + +} // namespace android::gui diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index df47002b3b..96d3a23bec 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -42,10 +42,13 @@ #include +#include + #include #include -#include #include +#include +#include #include #include #include @@ -59,11 +62,21 @@ class IGraphicBufferProducer; class ITunnelModeEnabledListener; class Region; +using gui::BnTransactionCompletedListener; +using gui::CallbackId; +using gui::CallbackIdHash; using gui::DisplayCaptureArgs; +using gui::FrameEventHistoryStats; using gui::IRegionSamplingListener; using gui::ISurfaceComposerClient; +using gui::ITransactionCompletedListener; +using gui::JankData; using gui::LayerCaptureArgs; using gui::LayerMetadata; +using gui::ListenerStats; +using gui::ReleaseBufferCallbackIdHash; +using gui::ReleaseCallbackId; +using gui::SurfaceStats; struct SurfaceControlStats { SurfaceControlStats(const sp& sc, nsecs_t latchTime, @@ -825,17 +838,17 @@ public: void setReleaseBufferCallback(const ReleaseCallbackId&, ReleaseBufferCallback); // BnTransactionCompletedListener overrides - void onTransactionCompleted(ListenerStats stats) override; - void onReleaseBuffer(ReleaseCallbackId, sp releaseFence, - uint32_t currentMaxAcquiredBufferCount) override; + binder::Status onTransactionCompleted(const ListenerStats& stats) override; + binder::Status onReleaseBuffer(const ReleaseCallbackId& callbackId, + const std::optional& releaseFenceFd, + int32_t currentMaxAcquiredBufferCount) override; + binder::Status onTransactionQueueStalled(const std::string& reason) override; void removeReleaseBufferCallback(const ReleaseCallbackId& callbackId); // For Testing Only static void setInstance(const sp&); - void onTransactionQueueStalled(const String8& reason) override; - private: ReleaseBufferCallback popReleaseBufferCallbackLocked(const ReleaseCallbackId&); static sp sInstance; -- cgit v1.2.3-59-g8ed1b