diff options
Diffstat (limited to 'libs')
32 files changed, 518 insertions, 655 deletions
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index ea5343a2a0..a3499c1963 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -277,15 +277,6 @@ cc_defaults { "-fvisibility=hidden", "-DBUILDING_LIBBINDER", ], - - target: { - vendor: { - // Trimming the exported symbols reveals a bug in vendor code, so - // disable it for the vendor variant for now. http://b/349657329 - // TODO: Fix the issue and remove this override. - cflags: ["-fvisibility=default"], - }, - }, } cc_defaults { diff --git a/libs/binder/rust/rpcbinder/src/lib.rs b/libs/binder/rust/rpcbinder/src/lib.rs index 7e5c9ddc35..774bb21efe 100644 --- a/libs/binder/rust/rpcbinder/src/lib.rs +++ b/libs/binder/rust/rpcbinder/src/lib.rs @@ -20,6 +20,8 @@ mod server; mod session; pub use server::RpcServer; +#[cfg(target_os = "trusty")] +pub use server::RpcServerConnection; #[cfg(not(target_os = "trusty"))] pub use server::RpcServerRef; pub use session::{FileDescriptorTransportMode, RpcSession, RpcSessionRef}; diff --git a/libs/binder/rust/rpcbinder/src/server/trusty.rs b/libs/binder/rust/rpcbinder/src/server/trusty.rs index fe45decf25..54d82d5bd0 100644 --- a/libs/binder/rust/rpcbinder/src/server/trusty.rs +++ b/libs/binder/rust/rpcbinder/src/server/trusty.rs @@ -106,6 +106,10 @@ pub struct RpcServerConnection { ctx: *mut c_void, } +// SAFETY: The opaque handle: `ctx` points into a dynamic allocation, +// and not tied to anything specific to the current thread. +unsafe impl Send for RpcServerConnection {} + impl Drop for RpcServerConnection { fn drop(&mut self) { // We do not need to close handle_fd since we do not own it. diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs index 6a8a69843a..771c65bf92 100644 --- a/libs/binder/rust/src/binder.rs +++ b/libs/binder/rust/src/binder.rs @@ -1160,6 +1160,12 @@ macro_rules! declare_binder_enum { pub const fn enum_values() -> [Self; $size] { [$(Self::$name),*] } + + #[inline(always)] + #[allow(missing_docs)] + pub const fn get(&self) -> $backing { + self.0 + } } impl std::fmt::Debug for $enum { diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 1aae13c1f4..5b0f21de91 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -1032,7 +1032,7 @@ void BLASTBufferQueue::mergeWithNextTransaction(SurfaceComposerClient::Transacti // Apply the transaction since we have already acquired the desired frame. t->setApplyToken(mApplyToken).apply(); } else { - mPendingTransactions.emplace_back(frameNumber, *t); + mPendingTransactions.emplace_back(frameNumber, std::move(*t)); // Clear the transaction so it can't be applied elsewhere. t->clear(); } @@ -1050,8 +1050,8 @@ void BLASTBufferQueue::applyPendingTransactions(uint64_t frameNumber) { void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber) { auto mergeTransaction = - [&t, currentFrameNumber = frameNumber]( - std::tuple<uint64_t, SurfaceComposerClient::Transaction> pendingTransaction) { + [t, currentFrameNumber = frameNumber]( + std::pair<uint64_t, SurfaceComposerClient::Transaction>& pendingTransaction) { auto& [targetFrameNumber, transaction] = pendingTransaction; if (currentFrameNumber < targetFrameNumber) { return false; diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 5961b41478..bcf61e45de 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -364,8 +364,10 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller, // Producers are not allowed to dequeue more than // mMaxDequeuedBufferCount buffers. // This check is only done if a buffer has already been queued - if (mCore->mBufferHasBeenQueued && - dequeuedCount >= mCore->mMaxDequeuedBufferCount) { + using namespace com::android::graphics::libgui::flags; + bool flagGatedBufferHasBeenQueued = + bq_always_use_max_dequeued_buffer_count() || mCore->mBufferHasBeenQueued; + if (flagGatedBufferHasBeenQueued && dequeuedCount >= mCore->mMaxDequeuedBufferCount) { // Supress error logs when timeout is non-negative. if (mDequeueTimeout < 0) { BQ_LOGE("%s: attempting to exceed the max dequeued buffer " diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 269936858a..ae4b74e03b 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -26,6 +26,7 @@ #include <gui/ISurfaceComposer.h> #include <gui/LayerState.h> #include <gui/SchedulingPolicy.h> +#include <gui/TransactionState.h> #include <private/gui/ParcelUtils.h> #include <stdint.h> #include <sys/types.h> @@ -60,54 +61,12 @@ public: virtual ~BpSurfaceComposer(); - status_t setTransactionState( - const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, - Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp, - const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, - const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId, - const std::vector<uint64_t>& mergedTransactionIds) override { + status_t setTransactionState(TransactionState&& state) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(state.writeToParcel, &data); - frameTimelineInfo.writeToParcel(&data); - - SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(state.size())); - for (const auto& s : state) { - SAFE_PARCEL(s.write, data); - } - - SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(displays.size())); - for (const auto& d : displays) { - SAFE_PARCEL(d.write, data); - } - - SAFE_PARCEL(data.writeUint32, flags); - SAFE_PARCEL(data.writeStrongBinder, applyToken); - SAFE_PARCEL(commands.write, data); - SAFE_PARCEL(data.writeInt64, desiredPresentTime); - SAFE_PARCEL(data.writeBool, isAutoTimestamp); - SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(uncacheBuffers.size())); - for (const client_cache_t& uncacheBuffer : uncacheBuffers) { - SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote()); - SAFE_PARCEL(data.writeUint64, uncacheBuffer.id); - } - SAFE_PARCEL(data.writeBool, hasListenerCallbacks); - - SAFE_PARCEL(data.writeVectorSize, listenerCallbacks); - for (const auto& [listener, callbackIds] : listenerCallbacks) { - SAFE_PARCEL(data.writeStrongBinder, listener); - SAFE_PARCEL(data.writeParcelableVector, callbackIds); - } - - SAFE_PARCEL(data.writeUint64, transactionId); - - SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(mergedTransactionIds.size())); - for (auto mergedTransactionId : mergedTransactionIds) { - SAFE_PARCEL(data.writeUint64, mergedTransactionId); - } - - if (flags & ISurfaceComposer::eOneWay) { + if (state.mFlags & ISurfaceComposer::eOneWay) { return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply, IBinder::FLAG_ONEWAY); } else { @@ -132,75 +91,9 @@ status_t BnSurfaceComposer::onTransact( case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - FrameTimelineInfo frameTimelineInfo; - frameTimelineInfo.readFromParcel(&data); - - uint32_t count = 0; - SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); - Vector<ComposerState> state; - state.setCapacity(count); - for (size_t i = 0; i < count; i++) { - ComposerState s; - SAFE_PARCEL(s.read, data); - state.add(s); - } - - SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); - DisplayState d; - Vector<DisplayState> displays; - displays.setCapacity(count); - for (size_t i = 0; i < count; i++) { - SAFE_PARCEL(d.read, data); - displays.add(d); - } - - uint32_t stateFlags = 0; - SAFE_PARCEL(data.readUint32, &stateFlags); - sp<IBinder> applyToken; - SAFE_PARCEL(data.readStrongBinder, &applyToken); - InputWindowCommands inputWindowCommands; - SAFE_PARCEL(inputWindowCommands.read, data); - - int64_t desiredPresentTime = 0; - bool isAutoTimestamp = true; - SAFE_PARCEL(data.readInt64, &desiredPresentTime); - SAFE_PARCEL(data.readBool, &isAutoTimestamp); - - SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); - std::vector<client_cache_t> uncacheBuffers(count); - sp<IBinder> tmpBinder; - for (size_t i = 0; i < count; i++) { - SAFE_PARCEL(data.readNullableStrongBinder, &tmpBinder); - uncacheBuffers[i].token = tmpBinder; - SAFE_PARCEL(data.readUint64, &uncacheBuffers[i].id); - } - - bool hasListenerCallbacks = false; - SAFE_PARCEL(data.readBool, &hasListenerCallbacks); - - std::vector<ListenerCallbacks> listenerCallbacks; - int32_t listenersSize = 0; - SAFE_PARCEL_READ_SIZE(data.readInt32, &listenersSize, data.dataSize()); - for (int32_t i = 0; i < listenersSize; i++) { - SAFE_PARCEL(data.readStrongBinder, &tmpBinder); - std::vector<CallbackId> callbackIds; - SAFE_PARCEL(data.readParcelableVector, &callbackIds); - listenerCallbacks.emplace_back(tmpBinder, callbackIds); - } - - uint64_t transactionId = -1; - SAFE_PARCEL(data.readUint64, &transactionId); - - SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); - std::vector<uint64_t> mergedTransactions(count); - for (size_t i = 0; i < count; i++) { - SAFE_PARCEL(data.readUint64, &mergedTransactions[i]); - } - - return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken, - std::move(inputWindowCommands), desiredPresentTime, - isAutoTimestamp, uncacheBuffers, hasListenerCallbacks, - listenerCallbacks, transactionId, mergedTransactions); + TransactionState state; + SAFE_PARCEL(state.readFromParcel, &data); + return setTransactionState(std::move(state)); } case GET_SCHEDULING_POLICY: { gui::SchedulingPolicy policy; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e407a63d10..69ba1d731d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -824,34 +824,24 @@ void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId) { // --------------------------------------------------------------------------- SurfaceComposerClient::Transaction::Transaction() { - mId = generateId(); + mState.mId = generateId(); mTransactionCompletedListener = TransactionCompletedListener::getInstance(); } -SurfaceComposerClient::Transaction::Transaction(const Transaction& other) - : mId(other.mId), - mFlags(other.mFlags), - mMayContainBuffer(other.mMayContainBuffer), - mDesiredPresentTime(other.mDesiredPresentTime), - mIsAutoTimestamp(other.mIsAutoTimestamp), - mFrameTimelineInfo(other.mFrameTimelineInfo), - mApplyToken(other.mApplyToken) { - mDisplayStates = other.mDisplayStates; - mComposerStates = other.mComposerStates; - mInputWindowCommands = other.mInputWindowCommands; - mListenerCallbacks = other.mListenerCallbacks; - mTransactionCompletedListener = TransactionCompletedListener::getInstance(); -} +SurfaceComposerClient::Transaction::Transaction(Transaction&& other) + : mTransactionCompletedListener(TransactionCompletedListener::getInstance()), + mState(std::move(other.mState)), + mListenerCallbacks(std::move(other.mListenerCallbacks)) {} void SurfaceComposerClient::Transaction::sanitize(int pid, int uid) { uint32_t permissions = LayerStatePermissions::getTransactionPermissions(pid, uid); - for (auto& composerState : mComposerStates) { + for (auto& composerState : mState.mComposerStates) { composerState.state.sanitize(permissions); } - if (!mInputWindowCommands.empty() && + if (!mState.mInputWindowCommands.empty() && (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) == 0) { ALOGE("Only privileged callers are allowed to send input commands."); - mInputWindowCommands.clear(); + mState.mInputWindowCommands.clear(); } } @@ -866,31 +856,10 @@ SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) { status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) { - const uint64_t transactionId = parcel->readUint64(); - const uint32_t flags = parcel->readUint32(); - const int64_t desiredPresentTime = parcel->readInt64(); - const bool isAutoTimestamp = parcel->readBool(); - const bool logCallPoints = parcel->readBool(); - FrameTimelineInfo frameTimelineInfo; - frameTimelineInfo.readFromParcel(parcel); - - sp<IBinder> applyToken; - parcel->readNullableStrongBinder(&applyToken); - size_t count = static_cast<size_t>(parcel->readUint32()); - if (count > parcel->dataSize()) { - return BAD_VALUE; - } - Vector<DisplayState> displayStates; - displayStates.setCapacity(count); - for (size_t i = 0; i < count; i++) { - DisplayState displayState; - if (displayState.read(*parcel) == BAD_VALUE) { - return BAD_VALUE; - } - displayStates.add(displayState); - } + TransactionState tmpState; + SAFE_PARCEL(tmpState.readFromParcel, parcel); - count = static_cast<size_t>(parcel->readUint32()); + size_t count = static_cast<size_t>(parcel->readUint32()); if (count > parcel->dataSize()) { return BAD_VALUE; } @@ -919,57 +888,8 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel } } - count = static_cast<size_t>(parcel->readUint32()); - if (count > parcel->dataSize()) { - return BAD_VALUE; - } - Vector<ComposerState> composerStates; - composerStates.setCapacity(count); - for (size_t i = 0; i < count; i++) { - ComposerState composerState; - if (composerState.read(*parcel) == BAD_VALUE) { - return BAD_VALUE; - } - composerStates.add(composerState); - } - - InputWindowCommands inputWindowCommands; - inputWindowCommands.read(*parcel); - - count = static_cast<size_t>(parcel->readUint32()); - if (count > parcel->dataSize()) { - return BAD_VALUE; - } - std::vector<client_cache_t> uncacheBuffers(count); - for (size_t i = 0; i < count; i++) { - sp<IBinder> tmpBinder; - SAFE_PARCEL(parcel->readStrongBinder, &tmpBinder); - uncacheBuffers[i].token = tmpBinder; - SAFE_PARCEL(parcel->readUint64, &uncacheBuffers[i].id); - } - - count = static_cast<size_t>(parcel->readUint32()); - if (count > parcel->dataSize()) { - return BAD_VALUE; - } - std::vector<uint64_t> mergedTransactionIds(count); - for (size_t i = 0; i < count; i++) { - SAFE_PARCEL(parcel->readUint64, &mergedTransactionIds[i]); - } - - // Parsing was successful. Update the object. - mId = transactionId; - mFlags = flags; - mDesiredPresentTime = desiredPresentTime; - mIsAutoTimestamp = isAutoTimestamp; - mFrameTimelineInfo = frameTimelineInfo; - mDisplayStates = std::move(displayStates); - mListenerCallbacks = listenerCallbacks; - mComposerStates = std::move(composerStates); - mInputWindowCommands = inputWindowCommands; - mApplyToken = applyToken; - mUncacheBuffers = std::move(uncacheBuffers); - mMergedTransactionIds = std::move(mergedTransactionIds); + mState = std::move(tmpState); + mListenerCallbacks = std::move(listenerCallbacks); return NO_ERROR; } @@ -987,17 +907,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const const_cast<SurfaceComposerClient::Transaction*>(this)->cacheBuffers(); - parcel->writeUint64(mId); - parcel->writeUint32(mFlags); - parcel->writeInt64(mDesiredPresentTime); - parcel->writeBool(mIsAutoTimestamp); - parcel->writeBool(mLogCallPoints); - mFrameTimelineInfo.writeToParcel(parcel); - parcel->writeStrongBinder(mApplyToken); - parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size())); - for (auto const& displayState : mDisplayStates) { - displayState.write(*parcel); - } + SAFE_PARCEL(mState.writeToParcel, parcel); parcel->writeUint32(static_cast<uint32_t>(mListenerCallbacks.size())); for (auto const& [listener, callbackInfo] : mListenerCallbacks) { @@ -1012,24 +922,6 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const } } - parcel->writeUint32(static_cast<uint32_t>(mComposerStates.size())); - for (auto const& composerState : mComposerStates) { - composerState.write(*parcel); - } - - mInputWindowCommands.write(*parcel); - - SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mUncacheBuffers.size())); - for (const client_cache_t& uncacheBuffer : mUncacheBuffers) { - SAFE_PARCEL(parcel->writeStrongBinder, uncacheBuffer.token.promote()); - SAFE_PARCEL(parcel->writeUint64, uncacheBuffer.id); - } - - SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mMergedTransactionIds.size())); - for (auto mergedTransactionId : mMergedTransactionIds) { - SAFE_PARCEL(parcel->writeUint64, mergedTransactionId); - } - return NO_ERROR; } @@ -1054,50 +946,8 @@ void SurfaceComposerClient::Transaction::releaseBufferIfOverwriting(const layer_ } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) { - while (mMergedTransactionIds.size() + other.mMergedTransactionIds.size() > - MAX_MERGE_HISTORY_LENGTH - 1 && - mMergedTransactionIds.size() > 0) { - mMergedTransactionIds.pop_back(); - } - if (other.mMergedTransactionIds.size() == MAX_MERGE_HISTORY_LENGTH) { - mMergedTransactionIds.insert(mMergedTransactionIds.begin(), - other.mMergedTransactionIds.begin(), - other.mMergedTransactionIds.end() - 1); - } else if (other.mMergedTransactionIds.size() > 0u) { - mMergedTransactionIds.insert(mMergedTransactionIds.begin(), - other.mMergedTransactionIds.begin(), - other.mMergedTransactionIds.end()); - } - mMergedTransactionIds.insert(mMergedTransactionIds.begin(), other.mId); - - for (auto const& otherState : other.mComposerStates) { - if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(), - [&otherState](const auto& composerState) { - return composerState.state.surface == - otherState.state.surface; - }); - it != mComposerStates.end()) { - if (otherState.state.what & layer_state_t::eBufferChanged) { - releaseBufferIfOverwriting(it->state); - } - it->state.merge(otherState.state); - } else { - mComposerStates.add(otherState); - } - } - - for (auto const& state : other.mDisplayStates) { - if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(), - [&state](const auto& displayState) { - return displayState.token == state.token; - }); - it != mDisplayStates.end()) { - it->merge(state); - } else { - mDisplayStates.add(state); - } - } - + mState.merge(std::move(other.mState), + std::bind(&Transaction::releaseBufferIfOverwriting, this, std::placeholders::_1)); for (const auto& [listener, callbackInfo] : other.mListenerCallbacks) { auto& [callbackIds, surfaceControls] = callbackInfo; mListenerCallbacks[listener].callbackIds.insert(std::make_move_iterator( @@ -1121,50 +971,21 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr } } - for (const auto& cacheId : other.mUncacheBuffers) { - mUncacheBuffers.push_back(cacheId); - } - - mInputWindowCommands.merge(other.mInputWindowCommands); - - mMayContainBuffer |= other.mMayContainBuffer; - mFlags |= other.mFlags; - mApplyToken = other.mApplyToken; - - mergeFrameTimelineInfo(mFrameTimelineInfo, other.mFrameTimelineInfo); - - mLogCallPoints |= other.mLogCallPoints; - if (mLogCallPoints) { - ALOG(LOG_DEBUG, LOG_SURFACE_CONTROL_REGISTRY, - "Transaction %" PRIu64 " merged with transaction %" PRIu64, other.getId(), mId); - } - other.clear(); return *this; } void SurfaceComposerClient::Transaction::clear() { - mComposerStates.clear(); - mDisplayStates.clear(); + mState.clear(); mListenerCallbacks.clear(); - mInputWindowCommands.clear(); - mUncacheBuffers.clear(); - mMayContainBuffer = false; - mDesiredPresentTime = 0; - mIsAutoTimestamp = true; - mFrameTimelineInfo = {}; - mApplyToken = nullptr; - mMergedTransactionIds.clear(); - mLogCallPoints = false; - mFlags = 0; } -uint64_t SurfaceComposerClient::Transaction::getId() { - return mId; +uint64_t SurfaceComposerClient::Transaction::getId() const { + return mState.mId; } std::vector<uint64_t> SurfaceComposerClient::Transaction::getMergedTransactionIds() { - return mMergedTransactionIds; + return mState.mMergedTransactionIds; } void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { @@ -1173,12 +994,13 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { client_cache_t uncacheBuffer; uncacheBuffer.token = BufferCache::getInstance().getToken(); uncacheBuffer.id = cacheId; - Vector<ComposerState> composerStates; - Vector<DisplayState> displayStates; - status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, displayStates, - ISurfaceComposer::eOneWay, - Transaction::getDefaultApplyToken(), {}, systemTime(), - true, {uncacheBuffer}, false, {}, generateId(), {}); + TransactionState state; + state.mId = generateId(); + state.mApplyToken = Transaction::getDefaultApplyToken(); + state.mUncacheBuffers.emplace_back(std::move(uncacheBuffer)); + state.mFlags = ISurfaceComposer::eOneWay; + state.mDesiredPresentTime = systemTime(); + status_t status = sf->setTransactionState(std::move(state)); if (status != NO_ERROR) { ALOGE_AND_TRACE("SurfaceComposerClient::doUncacheBufferTransaction - %s", strerror(-status)); @@ -1186,12 +1008,12 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { } void SurfaceComposerClient::Transaction::cacheBuffers() { - if (!mMayContainBuffer) { + if (!mState.mMayContainBuffer) { return; } size_t count = 0; - for (auto& cs : mComposerStates) { + for (auto& cs : mState.mComposerStates) { layer_state_t* s = &cs.state; if (!(s->what & layer_state_t::eBufferChanged)) { continue; @@ -1219,7 +1041,7 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { std::optional<client_cache_t> uncacheBuffer; cacheId = BufferCache::getInstance().cache(s->bufferData->buffer, uncacheBuffer); if (uncacheBuffer) { - mUncacheBuffers.push_back(*uncacheBuffer); + mState.mUncacheBuffers.emplace_back(*uncacheBuffer); } } s->bufferData->flags |= BufferData::BufferDataChange::cachedBufferChanged; @@ -1288,8 +1110,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay /*callbackContext=*/nullptr); } - bool hasListenerCallbacks = !mListenerCallbacks.empty(); - std::vector<ListenerCallbacks> listenerCallbacks; + mState.mHasListenerCallbacks = !mListenerCallbacks.empty(); // For every listener with registered callbacks for (const auto& [listener, callbackInfo] : mListenerCallbacks) { auto& [callbackIds, surfaceControls] = callbackInfo; @@ -1298,7 +1119,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay } if (surfaceControls.empty()) { - listenerCallbacks.emplace_back(IInterface::asBinder(listener), std::move(callbackIds)); + mState.mListenerCallbacks.emplace_back(IInterface::asBinder(listener), + std::move(callbackIds)); } else { // If the listener has any SurfaceControls set on this Transaction update the surface // state @@ -1310,7 +1132,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay } std::vector<CallbackId> callbacks(callbackIds.begin(), callbackIds.end()); s->what |= layer_state_t::eHasListenerCallbacksChanged; - s->listeners.emplace_back(IInterface::asBinder(listener), callbacks); + s->listeners.emplace_back(IInterface::asBinder(listener), std::move(callbacks)); } } } @@ -1322,25 +1144,21 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay ALOGE("Transaction attempted to set synchronous and one way at the same time" " this is an invalid request. Synchronous will win for safety"); } else { - mFlags |= ISurfaceComposer::eOneWay; + mState.mFlags |= ISurfaceComposer::eOneWay; } } // If both ISurfaceComposer::eEarlyWakeupStart and ISurfaceComposer::eEarlyWakeupEnd are set // it is equivalent for none uint32_t wakeupFlags = ISurfaceComposer::eEarlyWakeupStart | ISurfaceComposer::eEarlyWakeupEnd; - if ((mFlags & wakeupFlags) == wakeupFlags) { - mFlags &= ~(wakeupFlags); + if ((mState.mFlags & wakeupFlags) == wakeupFlags) { + mState.mFlags &= ~(wakeupFlags); } - sp<IBinder> applyToken = mApplyToken ? mApplyToken : getDefaultApplyToken(); + if (!mState.mApplyToken) mState.mApplyToken = getDefaultApplyToken(); sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - status_t binderStatus = - sf->setTransactionState(mFrameTimelineInfo, mComposerStates, mDisplayStates, mFlags, - applyToken, mInputWindowCommands, mDesiredPresentTime, - mIsAutoTimestamp, mUncacheBuffers, hasListenerCallbacks, - listenerCallbacks, mId, mMergedTransactionIds); - mId = generateId(); + status_t binderStatus = sf->setTransactionState(std::move(mState)); + mState.mId = generateId(); // Clear the current states and flags clear(); @@ -1349,8 +1167,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay syncCallback->wait(); } - if (mLogCallPoints) { - ALOG(LOG_DEBUG, LOG_SURFACE_CONTROL_REGISTRY, "Transaction %" PRIu64 " applied", mId); + if (mState.mLogCallPoints) { + ALOG(LOG_DEBUG, LOG_SURFACE_CONTROL_REGISTRY, "Transaction %" PRIu64 " applied", getId()); } mStatus = NO_ERROR; @@ -1385,7 +1203,7 @@ status_t SurfaceComposerClient::Transaction::sendSurfaceFlushJankDataTransaction } void SurfaceComposerClient::Transaction::enableDebugLogCallPoints() { - mLogCallPoints = true; + mState.mLogCallPoints = true; } // --------------------------------------------------------------------------- @@ -1443,34 +1261,19 @@ std::optional<gui::StalledTransactionInfo> SurfaceComposerClient::getStalledTran } void SurfaceComposerClient::Transaction::setAnimationTransaction() { - mFlags |= ISurfaceComposer::eAnimation; + mState.mFlags |= ISurfaceComposer::eAnimation; } void SurfaceComposerClient::Transaction::setEarlyWakeupStart() { - mFlags |= ISurfaceComposer::eEarlyWakeupStart; + mState.mFlags |= ISurfaceComposer::eEarlyWakeupStart; } void SurfaceComposerClient::Transaction::setEarlyWakeupEnd() { - mFlags |= ISurfaceComposer::eEarlyWakeupEnd; + mState.mFlags |= ISurfaceComposer::eEarlyWakeupEnd; } layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp<SurfaceControl>& sc) { - auto handle = sc->getLayerStateHandle(); - if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(), - [&handle](const auto& composerState) { - return composerState.state.surface == handle; - }); - it != mComposerStates.end()) { - return &it->state; - } - - // we don't have it, add an initialized layer_state to our list - ComposerState s; - s.state.surface = handle; - s.state.layerId = sc->getLayerId(); - mComposerStates.add(s); - - return &mComposerStates.editItemAt(mComposerStates.size() - 1).state; + return mState.getLayerState(sc); } void SurfaceComposerClient::Transaction::registerSurfaceControlForCallback( @@ -1846,8 +1649,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe setReleaseBufferCallback(bufferData.get(), callback); } - if (mIsAutoTimestamp) { - mDesiredPresentTime = systemTime(); + if (mState.mIsAutoTimestamp) { + mState.mDesiredPresentTime = systemTime(); } s->what |= layer_state_t::eBufferChanged; s->bufferData = std::move(bufferData); @@ -1865,7 +1668,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe const std::vector<SurfaceControlStats>&) {}, nullptr); - mMayContainBuffer = true; + mState.mMayContainBuffer = true; return *this; } @@ -2041,8 +1844,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSideb SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesiredPresentTime( nsecs_t desiredPresentTime) { - mDesiredPresentTime = desiredPresentTime; - mIsAutoTimestamp = false; + mState.mDesiredPresentTime = desiredPresentTime; + mState.mIsAutoTimestamp = false; return *this; } @@ -2131,14 +1934,14 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( const FocusRequest& request) { - mInputWindowCommands.addFocusRequest(request); + mState.mInputWindowCommands.addFocusRequest(request); return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addWindowInfosReportedListener( sp<gui::IWindowInfosReportedListener> windowInfosReportedListener) { - mInputWindowCommands.addWindowInfosReportedListener(windowInfosReportedListener); + mState.mInputWindowCommands.addWindowInfosReportedListener(windowInfosReportedListener); return *this; } @@ -2302,7 +2105,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixed SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo( const FrameTimelineInfo& frameTimelineInfo) { - mergeFrameTimelineInfo(mFrameTimelineInfo, frameTimelineInfo); + mState.mergeFrameTimelineInfo(frameTimelineInfo); return *this; } @@ -2341,7 +2144,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrust SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApplyToken( const sp<IBinder>& applyToken) { - mApplyToken = applyToken; + mState.mApplyToken = applyToken; return *this; } @@ -2469,17 +2272,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setConte // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) { - if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(), - [token](const auto& display) { return display.token == token; }); - it != mDisplayStates.end()) { - return *it; - } - - // If display state doesn't exist, add a new one. - DisplayState s; - s.token = token; - mDisplayStates.add(s); - return mDisplayStates.editItemAt(mDisplayStates.size() - 1); + return mState.getDisplayState(token); } status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp<IBinder>& token, @@ -2532,20 +2325,6 @@ void SurfaceComposerClient::Transaction::setDisplaySize(const sp<IBinder>& token s.what |= DisplayState::eDisplaySizeChanged; } -// copied from FrameTimelineInfo::merge() -void SurfaceComposerClient::Transaction::mergeFrameTimelineInfo(FrameTimelineInfo& t, - const FrameTimelineInfo& other) { - // When merging vsync Ids we take the oldest valid one - if (t.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID && - other.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { - if (other.vsyncId > t.vsyncId) { - t = other; - } - } else if (t.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) { - t = other; - } -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedPresentationCallback( const sp<SurfaceControl>& sc, TrustedPresentationCallback cb, @@ -2766,6 +2545,7 @@ status_t SurfaceComposerClient::getStaticDisplayInfo(int64_t displayId, if (status.isOk()) { // convert gui::StaticDisplayInfo to ui::StaticDisplayInfo outInfo->connectionType = static_cast<ui::DisplayConnectionType>(ginfo.connectionType); + outInfo->port = ginfo.port; outInfo->density = ginfo.density; outInfo->secure = ginfo.secure; outInfo->installOrientation = static_cast<ui::Rotation>(ginfo.installOrientation); diff --git a/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl b/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl index 0ccda56ef5..7ff332c29e 100644 --- a/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl +++ b/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl @@ -23,6 +23,7 @@ import android.gui.Rotation; /** @hide */ parcelable StaticDisplayInfo { DisplayConnectionType connectionType = DisplayConnectionType.Internal; + int port = -1; float density; boolean secure; @nullable DeviceProductInfo deviceProductInfo; diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index db1b9fb8eb..c69b0a79ad 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -284,7 +284,7 @@ private: std::function<void(SurfaceComposerClient::Transaction*)> mTransactionReadyCallback GUARDED_BY(mMutex); SurfaceComposerClient::Transaction* mSyncTransaction GUARDED_BY(mMutex); - std::vector<std::tuple<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>> + std::vector<std::pair<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>> mPendingTransactions GUARDED_BY(mMutex); std::queue<std::pair<uint64_t, FrameTimelineInfo>> mPendingFrameTimelines GUARDED_BY(mMutex); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 9a422fd808..de553aef72 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -65,6 +65,7 @@ struct DisplayState; struct InputWindowCommands; class HdrCapabilities; class Rect; +class TransactionState; using gui::FrameTimelineInfo; using gui::IDisplayEventConnection; @@ -105,13 +106,7 @@ public: }; /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ - virtual status_t setTransactionState( - const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, - Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, - bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer, - bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, - uint64_t transactionId, const std::vector<uint64_t>& mergedTransactionIds) = 0; + virtual status_t setTransactionState(TransactionState&& state) = 0; }; // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/InputTransferToken.h b/libs/gui/include/gui/InputTransferToken.h index fb4aaa73ae..b83f24562b 100644 --- a/libs/gui/include/gui/InputTransferToken.h +++ b/libs/gui/include/gui/InputTransferToken.h @@ -39,15 +39,9 @@ public: return NO_ERROR; }; + bool operator==(const InputTransferToken& other) const { return mToken == other.mToken; } + sp<IBinder> mToken; }; -static inline bool operator==(const sp<InputTransferToken>& token1, - const sp<InputTransferToken>& token2) { - if (token1.get() == token2.get()) { - return true; - } - return token1->mToken == token2->mToken; -} - } // namespace android diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 4fda8deb9c..668bd6fbb8 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -52,6 +52,7 @@ #include <gui/ITransactionCompletedListener.h> #include <gui/LayerState.h> #include <gui/SurfaceControl.h> +#include <gui/TransactionState.h> #include <gui/WindowInfosListenerReporter.h> #include <math/vec3.h> @@ -442,61 +443,16 @@ public: virtual ~PresentationCallbackRAII(); }; - class Transaction : public Parcelable { + class Transaction { private: static sp<IBinder> sApplyToken; static std::mutex sApplyTokenMutex; void releaseBufferIfOverwriting(const layer_state_t& state); - static void mergeFrameTimelineInfo(FrameTimelineInfo& t, const FrameTimelineInfo& other); // Tracks registered callbacks sp<TransactionCompletedListener> mTransactionCompletedListener = nullptr; - // Prints debug logs when enabled. - bool mLogCallPoints = false; - protected: - Vector<ComposerState> mComposerStates; - Vector<DisplayState> mDisplayStates; - std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash> - mListenerCallbacks; - std::vector<client_cache_t> mUncacheBuffers; - - // We keep track of the last MAX_MERGE_HISTORY_LENGTH merged transaction ids. - // Ordered most recently merged to least recently merged. - static const size_t MAX_MERGE_HISTORY_LENGTH = 10u; - std::vector<uint64_t> mMergedTransactionIds; - - uint64_t mId; - uint32_t mFlags = 0; - - // Indicates that the Transaction may contain buffers that should be cached. The reason this - // is only a guess is that buffers can be removed before cache is called. This is only a - // hint that at some point a buffer was added to this transaction before apply was called. - bool mMayContainBuffer = false; - - // mDesiredPresentTime is the time in nanoseconds that the client would like the transaction - // to be presented. When it is not possible to present at exactly that time, it will be - // presented after the time has passed. - // - // If the client didn't pass a desired presentation time, mDesiredPresentTime will be - // populated to the time setBuffer was called, and mIsAutoTimestamp will be set to true. - // - // Desired present times that are more than 1 second in the future may be ignored. - // When a desired present time has already passed, the transaction will be presented as soon - // as possible. - // - // Transactions from the same process are presented in the same order that they are applied. - // The desired present time does not affect this ordering. - int64_t mDesiredPresentTime = 0; - bool mIsAutoTimestamp = true; - - // The vsync id provided by Choreographer.getVsyncId and the input event id - FrameTimelineInfo mFrameTimelineInfo; - - // If not null, transactions will be queued up using this token otherwise a common token - // per process will be used. - sp<IBinder> mApplyToken = nullptr; + TransactionState mState; - InputWindowCommands mInputWindowCommands; int mStatus = NO_ERROR; layer_state_t* getLayerState(const sp<SurfaceControl>& sc); @@ -506,23 +462,29 @@ public: void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc); void setReleaseBufferCallback(BufferData*, ReleaseBufferCallback); + protected: + // Accessed in tests. + explicit Transaction(Transaction const& other) = default; + std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash> + mListenerCallbacks; + public: Transaction(); - virtual ~Transaction() = default; - Transaction(Transaction const& other); + Transaction(Transaction&& other); + Transaction& operator=(Transaction&& other) = default; // Factory method that creates a new Transaction instance from the parcel. static std::unique_ptr<Transaction> createFromParcel(const Parcel* parcel); - status_t writeToParcel(Parcel* parcel) const override; - status_t readFromParcel(const Parcel* parcel) override; + status_t writeToParcel(Parcel* parcel) const; + status_t readFromParcel(const Parcel* parcel); // Clears the contents of the transaction without applying it. void clear(); // Returns the current id of the transaction. // The id is updated every time the transaction is applied. - uint64_t getId(); + uint64_t getId() const; std::vector<uint64_t> getMergedTransactionIds(); diff --git a/libs/gui/include/gui/TransactionState.h b/libs/gui/include/gui/TransactionState.h index 4358227dae..79124f3ed7 100644 --- a/libs/gui/include/gui/TransactionState.h +++ b/libs/gui/include/gui/TransactionState.h @@ -26,7 +26,8 @@ namespace android { class TransactionState { public: explicit TransactionState() = default; - TransactionState(TransactionState const& other) = default; + TransactionState(TransactionState&& other) = default; + TransactionState& operator=(TransactionState&& other) = default; status_t writeToParcel(Parcel* parcel) const; status_t readFromParcel(const Parcel* parcel); layer_state_t* getLayerState(const sp<SurfaceControl>& sc); @@ -86,6 +87,9 @@ public: std::vector<ListenerCallbacks> mListenerCallbacks; private: + explicit TransactionState(TransactionState const& other) = default; + friend class TransactionApplicationTest; + friend class SurfaceComposerClient; // We keep track of the last MAX_MERGE_HISTORY_LENGTH merged transaction ids. // Ordered most recently merged to least recently merged. static constexpr size_t MAX_MERGE_HISTORY_LENGTH = 10u; diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig index 2c3222dd82..ce1bc9512c 100644 --- a/libs/gui/libgui_flags.aconfig +++ b/libs/gui/libgui_flags.aconfig @@ -130,9 +130,6 @@ flag { description: "Remove BufferQueueProducer::dequeue's wait on this fence (or the fence entirely) to prevent deadlocks" bug: "339705065" is_fixed_read_only: true - metadata { - purpose: PURPOSE_BUGFIX - } } # bq_gl_fence_cleanup flag { @@ -153,3 +150,14 @@ flag { } is_fixed_read_only: true } # allocate_buffer_priority + +flag { + name: "bq_always_use_max_dequeued_buffer_count" + namespace: "core_graphics" + description: "BufferQueueProducer::dequeue's respects setMaxDequeuedBufferCount even before a buffer is dequeued." + bug: "399328309" + metadata { + purpose: PURPOSE_BUGFIX + } + is_fixed_read_only: true +} # bq_always_use_max_dequeued_buffer_count diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index cf05fd4ba5..adf8fce472 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -222,8 +222,8 @@ public: ASSERT_EQ(InputEventType::MOTION, ev->getType()); MotionEvent* mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); - EXPECT_EQ(x, mev->getX(0)); - EXPECT_EQ(y, mev->getY(0)); + EXPECT_NEAR(x, mev->getX(0), EPSILON); + EXPECT_NEAR(y, mev->getY(0), EPSILON); EXPECT_EQ(flags, mev->getFlags() & flags); ev = consumeEvent(); @@ -241,8 +241,8 @@ public: MotionEvent* mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); const PointerCoords& coords = *mev->getRawPointerCoords(0 /*pointerIndex*/); - EXPECT_EQ(displayX, coords.getX()); - EXPECT_EQ(displayY, coords.getY()); + EXPECT_NEAR(displayX, coords.getX(), EPSILON); + EXPECT_NEAR(displayY, coords.getY(), EPSILON); EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); ev = consumeEvent(); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index e7690e2530..c4dcba856a 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -648,16 +648,7 @@ public: mSupportsPresent = supportsPresent; } - status_t setTransactionState( - const FrameTimelineInfo& /*frameTimelineInfo*/, Vector<ComposerState>& /*state*/, - Vector<DisplayState>& /*displays*/, uint32_t /*flags*/, - const sp<IBinder>& /*applyToken*/, InputWindowCommands /*inputWindowCommands*/, - int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, - const std::vector<client_cache_t>& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, - const std::vector<ListenerCallbacks>& /*listenerCallbacks*/, uint64_t /*transactionId*/, - const std::vector<uint64_t>& /*mergedTransactionIds*/) override { - return NO_ERROR; - } + status_t setTransactionState(TransactionState&&) override { return NO_ERROR; } protected: IBinder* onAsBinder() override { return nullptr; } @@ -2246,6 +2237,52 @@ TEST_F(SurfaceTest, BatchIllegalOperations) { ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU)); } +TEST_F(SurfaceTest, setMaxDequeuedBufferCount_setMaxAcquiredBufferCount_allocations) { + // + // Set up the consumer and producer--nothing fancy. + // + auto [consumer, surface] = + BufferItemConsumer::create(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER); + sp<SurfaceListener> surfaceListener = sp<StubSurfaceListener>::make(); + surface->connect(NATIVE_WINDOW_API_CPU, surfaceListener); + sp<GraphicBuffer> buffer; + sp<Fence> fence; + + // + // These values are independent. The consumer can dequeue 3 and the consumer can acquire 3 at + // the same time. + // + ASSERT_EQ(OK, consumer->setMaxAcquiredBufferCount(3)); + ASSERT_EQ(OK, surface->setMaxDequeuedBufferCount(3)); + + // + // Take all three buffers out of the queue--a fourth can't be retrieved. Then queue them. + // + std::vector<Surface::BatchBuffer> dequeuedBuffers(3); + EXPECT_EQ(OK, surface->dequeueBuffers(&dequeuedBuffers)); + if (::com::android::graphics::libgui::flags::bq_always_use_max_dequeued_buffer_count()) { + EXPECT_EQ(INVALID_OPERATION, surface->dequeueBuffer(&buffer, &fence)); + } + + for (auto& batchBuffer : dequeuedBuffers) { + EXPECT_EQ(OK, + surface->queueBuffer(GraphicBuffer::from(batchBuffer.buffer), + sp<Fence>::make(batchBuffer.fenceFd))); + } + dequeuedBuffers.assign(3, {}); + + // + // Acquire all three, then we should be able to dequeue 3 more. + // + std::vector<BufferItem> acquiredBuffers(3); + for (auto& bufferItem : acquiredBuffers) { + EXPECT_EQ(OK, consumer->acquireBuffer(&bufferItem, 0)); + } + + EXPECT_EQ(OK, surface->dequeueBuffers(&dequeuedBuffers)); + EXPECT_EQ(INVALID_OPERATION, surface->dequeueBuffer(&buffer, &fence)); +} + #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) TEST_F(SurfaceTest, PlatformBufferMethods) { diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index 7f207f0670..f9b84fa948 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -25,6 +25,7 @@ cc_defaults { defaults: [ "android.hardware.graphics.composer3-ndk_shared", "renderengine_defaults", + "libsurfaceflinger_common_deps", ], cflags: [ "-DGL_GLEXT_PROTOTYPES", @@ -117,7 +118,10 @@ filegroup { // possible if libskia_renderengine is just pulled into librenderengine via whole_static_libs. cc_defaults { name: "librenderengine_deps", - defaults: ["skia_renderengine_deps"], + defaults: [ + "skia_renderengine_deps", + "libsurfaceflinger_common_deps", + ], static_libs: ["libskia_renderengine"], } diff --git a/libs/renderengine/benchmark/Android.bp b/libs/renderengine/benchmark/Android.bp index f84db0b04c..2d18ddb0aa 100644 --- a/libs/renderengine/benchmark/Android.bp +++ b/libs/renderengine/benchmark/Android.bp @@ -28,6 +28,7 @@ cc_benchmark { "android.hardware.graphics.composer3-ndk_shared", "librenderengine_deps", "surfaceflinger_defaults", + "libsurfaceflinger_common_deps", ], srcs: [ "main.cpp", @@ -38,7 +39,6 @@ cc_benchmark { static_libs: [ "librenderengine", "libshaders", - "libsurfaceflinger_common", "libtonemap", ], cflags: [ diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index 25afc7b465..9e1c226371 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -1236,6 +1236,16 @@ void SkiaRenderEngine::drawLayersInternal( LOG_ALWAYS_FATAL_IF(activeSurface != dstSurface); auto drawFence = sp<Fence>::make(flushAndSubmit(context, dstSurface)); trace(drawFence); + FenceTimePtr fenceTime = FenceTime::makeValid(drawFence); + for (const auto& layer : layers) { + if (FlagManager::getInstance().monitor_buffer_fences()) { + if (layer.source.buffer.buffer) { + layer.source.buffer.buffer->getBuffer() + ->getDependencyMonitor() + .addAccessCompletion(fenceTime, "RE"); + } + } + } resultPromise->set_value(std::move(drawFence)); } diff --git a/libs/renderengine/skia/filters/LutShader.cpp b/libs/renderengine/skia/filters/LutShader.cpp index f262158f2c..6a577ff41f 100644 --- a/libs/renderengine/skia/filters/LutShader.cpp +++ b/libs/renderengine/skia/filters/LutShader.cpp @@ -24,7 +24,6 @@ #include <ui/ColorSpace.h> #include "include/core/SkColorSpace.h" -#include "src/core/SkColorFilterPriv.h" using aidl::android::hardware::graphics::composer3::LutProperties; @@ -116,7 +115,7 @@ static const SkString kShader = SkString(R"( linear = mix(c0, c1, linear.b); } } - return float4(linear, rgba.a); + return float4(fromLinearSrgb(linear), rgba.a); })"); // same as shader::toColorSpace function @@ -289,9 +288,7 @@ sk_sp<SkShader> LutShader::lutShader(sk_sp<SkShader>& input, lutProperties[i].samplingKey, srcDataspace); } - auto colorXformLutToDst = - SkColorFilterPriv::MakeColorSpaceXform(lutMathColorSpace, outColorSpace); - input = input->makeWithColorFilter(colorXformLutToDst); + input = input->makeWithWorkingColorSpace(outColorSpace); } return input; } diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index 87e213e394..10cb992835 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -122,6 +122,7 @@ cc_library_shared { srcs: [ "DebugUtils.cpp", + "DependencyMonitor.cpp", "DeviceProductInfo.cpp", "DisplayIdentification.cpp", "DynamicDisplayInfo.cpp", diff --git a/libs/ui/DependencyMonitor.cpp b/libs/ui/DependencyMonitor.cpp new file mode 100644 index 0000000000..b7e490eba4 --- /dev/null +++ b/libs/ui/DependencyMonitor.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2025 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. + */ + +// #define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "DependencyMonitor" + +#include <ui/DependencyMonitor.h> +#include <ui/Fence.h> +#include <utils/Timers.h> + +#include <inttypes.h> + +namespace android { + +void DependencyMonitor::addIngress(FenceTimePtr fence, std::string annotation) { + std::lock_guard lock(mMutex); + resolveLocked(); + if (mDependencies.isFull() && !mDependencies.front().updateSignalTimes(true)) { + ALOGD("%s: Clobbering unresolved dependencies -- make me bigger!", mToken.c_str()); + } + + auto& entry = mDependencies.next(); + entry.reset(mToken.c_str()); + ALOGV("%" PRId64 "/%s: addIngress at CPU time %" PRId64 " (%s)", mDependencies.back().id, + mToken.c_str(), systemTime(), annotation.c_str()); + + mDependencies.back().ingress = {std::move(fence), std::move(annotation)}; +} + +void DependencyMonitor::addAccessCompletion(FenceTimePtr fence, std::string annotation) { + std::lock_guard lock(mMutex); + if (mDependencies.size() == 0) { + return; + } + ALOGV("%" PRId64 "/%s: addAccessCompletion at CPU time %" PRId64 " (%s)", + mDependencies.back().id, mToken.c_str(), systemTime(), annotation.c_str()); + mDependencies.back().accessCompletions.emplace_back(std::move(fence), std::move(annotation)); +} + +void DependencyMonitor::addEgress(FenceTimePtr fence, std::string annotation) { + std::lock_guard lock(mMutex); + if (mDependencies.size() == 0) { + return; + } + ALOGV("%" PRId64 "/%s: addEgress at CPU time %" PRId64 " (%s)", mDependencies.back().id, + mToken.c_str(), systemTime(), annotation.c_str()); + mDependencies.back().egress = {std::move(fence), std::move(annotation)}; +} + +void DependencyMonitor::resolveLocked() { + if (mDependencies.size() == 0) { + return; + } + + for (size_t i = mDependencies.size(); i > 0; i--) { + auto& dependencyBlock = mDependencies[i - 1]; + + if (dependencyBlock.validated) { + continue; + } + + if (!dependencyBlock.updateSignalTimes(false)) { + break; + } + + dependencyBlock.validated = true; + dependencyBlock.checkUnsafeAccess(); + } +} + +bool DependencyMonitor::DependencyBlock::updateSignalTimes(bool excludeIngress) { + if (egress.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + + if (!excludeIngress && ingress.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + + for (auto& accessCompletion : accessCompletions) { + if (accessCompletion.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + } + + return true; +} + +void DependencyMonitor::DependencyBlock::checkUnsafeAccess() const { + const nsecs_t egressTime = egress.fence->getCachedSignalTime(); + const nsecs_t ingressTime = ingress.fence->getCachedSignalTime(); + + ALOGV_IF(egressTime != Fence::SIGNAL_TIME_INVALID, + "%" PRId64 "/%s: Egress time: %" PRId64 " (%s)", token, id, egressTime, + egress.annotation.c_str()); + ALOGV_IF(Fence::isValidTimestamp(egressTime) && Fence::isValidTimestamp(ingressTime) && + egressTime < ingressTime, + "%" PRId64 "/%s: Detected egress before ingress!: %" PRId64 " (%s) < %" PRId64 " (%s)", + id, token, egressTime, egress.annotation, ingressTime, ingress.annotation.c_str()); + + for (auto& accessCompletion : accessCompletions) { + const nsecs_t accessCompletionTime = accessCompletion.fence->getCachedSignalTime(); + if (!Fence::isValidTimestamp(accessCompletionTime)) { + ALOGI("%" PRId64 "/%s: Detected invalid access completion! <%s>", id, token, + accessCompletion.annotation.c_str()); + continue; + } else { + ALOGV("%" PRId64 "/%s: Access completion time: %" PRId64 " <%s>", id, token, + accessCompletionTime, accessCompletion.annotation.c_str()); + } + + ALOGI_IF(Fence::isValidTimestamp(egressTime) && accessCompletionTime > egressTime, + "%" PRId64 "/%s: Detected access completion after egress!: %" PRId64 + " (%s) > %" PRId64 " (%s)", + id, token, accessCompletionTime, accessCompletion.annotation.c_str(), egressTime, + egress.annotation.c_str()); + + ALOGI_IF(Fence::isValidTimestamp(ingressTime) && accessCompletionTime < ingressTime, + "%" PRId64 "/%s: Detected access completion prior to ingress!: %" PRId64 + " (%s) < %" PRId64 " (%s)", + id, token, accessCompletionTime, accessCompletion.annotation.c_str(), ingressTime, + ingress.annotation.c_str()); + } + + ALOGV_IF(ingressTime != Fence::SIGNAL_TIME_INVALID, + "%" PRId64 "/%s: Ingress time: %" PRId64 " (%s)", id, token, ingressTime, + ingress.annotation.c_str()); +} + +} // namespace android
\ No newline at end of file diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp index 4246c40f64..81afe9ef0e 100644 --- a/libs/ui/FenceTime.cpp +++ b/libs/ui/FenceTime.cpp @@ -59,6 +59,14 @@ FenceTime::FenceTime(nsecs_t signalTime) } } +FenceTimePtr FenceTime::makeValid(const sp<Fence>& fence) { + if (fence && fence->isValid()) { + return std::make_shared<FenceTime>(fence); + } else { + return std::make_shared<FenceTime>(systemTime()); + } +} + void FenceTime::applyTrustedSnapshot(const Snapshot& src) { if (CC_UNLIKELY(src.state != Snapshot::State::SIGNAL_TIME)) { // Applying Snapshot::State::FENCE, could change the valid state of the @@ -289,9 +297,10 @@ status_t FenceTime::Snapshot::unflatten( // ============================================================================ void FenceTimeline::push(const std::shared_ptr<FenceTime>& fence) { std::lock_guard<std::mutex> lock(mMutex); - while (mQueue.size() >= MAX_ENTRIES) { + static constexpr size_t MAX_QUEUE_SIZE = 64; + while (mQueue.size() >= MAX_QUEUE_SIZE) { // This is a sanity check to make sure the queue doesn't grow unbounded. - // MAX_ENTRIES should be big enough not to trigger this path. + // MAX_QUEUE_SIZE should be big enough not to trigger this path. // In case this path is taken though, users of FenceTime must make sure // not to rely solely on FenceTimeline to get the final timestamp and // should eventually call Fence::getSignalTime on their own. diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 18c9a6bc48..f7c94005f1 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -27,6 +27,8 @@ #include <ui/GraphicBufferMapper.h> #include <utils/Trace.h> +#include <string> + namespace android { // =========================================================================== @@ -104,6 +106,7 @@ GraphicBuffer::GraphicBuffer() usage = 0; layerCount = 0; handle = nullptr; + mDependencyMonitor.setToken(std::to_string(mId)); } // deprecated @@ -155,6 +158,8 @@ GraphicBuffer::GraphicBuffer(const GraphicBufferAllocator::AllocationRequest& re layerCount = request.layerCount; usage = request.usage; usage_deprecated = int(usage); + std::string name = request.requestorName; + mDependencyMonitor.setToken(name.append(":").append(std::to_string(mId))); } } @@ -252,6 +257,7 @@ status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight, usage = inUsage; usage_deprecated = int(usage); stride = static_cast<int>(outStride); + mDependencyMonitor.setToken(requestorName.append(":").append(std::to_string(mId))); } return err; } @@ -609,6 +615,14 @@ status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts); } + std::string name; + status_t err = mBufferMapper.getName(handle, &name); + if (err != NO_ERROR) { + name = "<Unknown>"; + } + + mDependencyMonitor.setToken(name.append(":").append(std::to_string(mId))); + buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); size -= sizeNeeded; fds += numFds; diff --git a/libs/ui/include/ui/DependencyMonitor.h b/libs/ui/include/ui/DependencyMonitor.h new file mode 100644 index 0000000000..5ad1fd9528 --- /dev/null +++ b/libs/ui/include/ui/DependencyMonitor.h @@ -0,0 +1,104 @@ +/* + * Copyright 2025 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 <ui/FatVector.h> +#include <ui/FenceTime.h> +#include <ui/RingBuffer.h> + +namespace android { + +// Debugging class for that tries to add userspace logging for fence depencencies. +// The model that a DependencyMonitor tries to follow is, for each access of some resource: +// 1. There is a single ingress fence, that guards whether a resource is now safe to read from +// another system. +// 2. There are multiple access fences, that are fired when a resource is read. +// 3. There is a single egress fence, that is fired when a resource is released and sent to another +// system. +// +// Note that there can be repeated ingress and egress of a resource, but the assumption is that +// there is exactly one egress for every ingress, unless the resource is destroyed rather than +// released. +// +// The DependencyMonitor will log if there is an anomaly in the fences tracked for some resource. +// This includes: +// * If (2) happens before (1) +// * If (2) happens after (3) +// +// Note that this class has no knowledge of the "other system". I.e., if the other system ignores +// the fence reported in (3), but still takes a long time to write to the resource and produce (1), +// then nothing will be logged. That other system must have its own DependencyMonitor. Conversely, +// this class has imperfect knowledge of the system it is monitoring. For example, this class does +// not know the precise start times of reading from a resource, the exact time that a read might +// occur from a hardware unit is not known to userspace. +// +// In other words, this class logs specific classes of fence violations, but is not sensitive to +// *all* violations. One property of this is that unless the system tracked by a DependencyMonitor +// is feeding in literally incorrect fences, then there is no chance of a false positive. +// +// This class is thread safe. +class DependencyMonitor { +public: + // Sets a debug token identifying the resource this monitor is tracking. + void setToken(std::string token) { mToken = std::move(token); } + + // Adds a fence that is fired when the resource ready to be ingested by the system using the + // DependencyMonitor. + void addIngress(FenceTimePtr fence, std::string annotation); + // Adds a fence that is fired when the resource is accessed. + void addAccessCompletion(FenceTimePtr fence, std::string annotation); + // Adds a fence that is fired when the resource is released to another system. + void addEgress(FenceTimePtr fence, std::string annotation); + +private: + struct AnnotatedFenceTime { + FenceTimePtr fence; + std::string annotation; + }; + + struct DependencyBlock { + int64_t id = -1; + AnnotatedFenceTime ingress = {FenceTime::NO_FENCE, ""}; + FatVector<AnnotatedFenceTime> accessCompletions; + AnnotatedFenceTime egress = {FenceTime::NO_FENCE, ""}; + bool validated = false; + const char* token = nullptr; + + void reset(const char* newToken) { + static std::atomic<int64_t> counter = 0; + id = counter++; + ingress = {FenceTime::NO_FENCE, ""}; + accessCompletions.clear(); + egress = {FenceTime::NO_FENCE, ""}; + validated = false; + token = newToken; + } + + // Returns true if all fences in this block have valid signal times. + bool updateSignalTimes(bool excludeIngress); + + void checkUnsafeAccess() const; + }; + + void resolveLocked() REQUIRES(mMutex); + + std::string mToken; + std::mutex mMutex; + ui::RingBuffer<DependencyBlock, 10> mDependencies GUARDED_BY(mMutex); +}; + +} // namespace android
\ No newline at end of file diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h index 937e3f1486..1e1c77b9fc 100644 --- a/libs/ui/include/ui/DisplayId.h +++ b/libs/ui/include/ui/DisplayId.h @@ -20,6 +20,7 @@ #include <ostream> #include <string> +#include <ftl/match.h> #include <ftl/optional.h> namespace android { @@ -36,7 +37,6 @@ struct DisplayId { DisplayId& operator=(const DisplayId&) = default; static constexpr DisplayId fromValue(uint64_t value) { return DisplayId(value); } - constexpr bool isVirtual() const { return value & FLAG_VIRTUAL; } uint64_t value; @@ -66,13 +66,6 @@ struct PhysicalDisplayId : DisplayId { // TODO: b/162612135 - Remove default constructor. PhysicalDisplayId() = default; - static constexpr ftl::Optional<PhysicalDisplayId> tryCast(DisplayId id) { - if (id.isVirtual()) { - return std::nullopt; - } - return PhysicalDisplayId(id); - } - // Returns a stable ID based on EDID and port information. static constexpr PhysicalDisplayId fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t modelHash) { @@ -90,8 +83,6 @@ struct PhysicalDisplayId : DisplayId { return PhysicalDisplayId(value); } - constexpr uint8_t getPort() const { return static_cast<uint8_t>(value); } - private: // Flag indicating that the ID is stable across reboots. static constexpr uint64_t FLAG_STABLE = 1ULL << 62; @@ -112,13 +103,6 @@ struct VirtualDisplayId : DisplayId { // Flag indicating that this virtual display is backed by the GPU. static constexpr uint64_t FLAG_GPU = 1ULL << 61; - static constexpr std::optional<VirtualDisplayId> tryCast(DisplayId id) { - if (id.isVirtual()) { - return VirtualDisplayId(id); - } - return std::nullopt; - } - static constexpr VirtualDisplayId fromValue(uint64_t value) { return VirtualDisplayId(SkipVirtualFlag{}, value); } @@ -134,13 +118,6 @@ protected: struct HalVirtualDisplayId : VirtualDisplayId { explicit constexpr HalVirtualDisplayId(BaseId baseId) : VirtualDisplayId(baseId) {} - static constexpr std::optional<HalVirtualDisplayId> tryCast(DisplayId id) { - if (id.isVirtual() && !(id.value & FLAG_GPU)) { - return HalVirtualDisplayId(id); - } - return std::nullopt; - } - static constexpr HalVirtualDisplayId fromValue(uint64_t value) { return HalVirtualDisplayId(SkipVirtualFlag{}, value); } @@ -152,13 +129,6 @@ private: struct GpuVirtualDisplayId : VirtualDisplayId { explicit constexpr GpuVirtualDisplayId(BaseId baseId) : VirtualDisplayId(FLAG_GPU | baseId) {} - static constexpr std::optional<GpuVirtualDisplayId> tryCast(DisplayId id) { - if (id.isVirtual() && (id.value & FLAG_GPU)) { - return GpuVirtualDisplayId(id); - } - return std::nullopt; - } - static constexpr GpuVirtualDisplayId fromValue(uint64_t value) { return GpuVirtualDisplayId(SkipVirtualFlag{}, value); } @@ -172,14 +142,6 @@ private: struct HalDisplayId : DisplayId { constexpr HalDisplayId(HalVirtualDisplayId other) : DisplayId(other) {} constexpr HalDisplayId(PhysicalDisplayId other) : DisplayId(other) {} - - static constexpr std::optional<HalDisplayId> tryCast(DisplayId id) { - if (GpuVirtualDisplayId::tryCast(id)) { - return std::nullopt; - } - return HalDisplayId(id); - } - static constexpr HalDisplayId fromValue(uint64_t value) { return HalDisplayId(value); } private: @@ -187,6 +149,47 @@ private: explicit constexpr HalDisplayId(DisplayId other) : DisplayId(other) {} }; +using DisplayIdVariant = std::variant<PhysicalDisplayId, GpuVirtualDisplayId, HalVirtualDisplayId>; +using VirtualDisplayIdVariant = std::variant<GpuVirtualDisplayId, HalVirtualDisplayId>; + +template <typename DisplayIdType> +inline auto asDisplayIdOfType(DisplayIdVariant variant) -> ftl::Optional<DisplayIdType> { + return ftl::match( + variant, + [](DisplayIdType id) -> ftl::Optional<DisplayIdType> { return ftl::Optional(id); }, + [](auto) -> ftl::Optional<DisplayIdType> { return std::nullopt; }); +} + +template <typename Variant> +inline auto asHalDisplayId(Variant variant) -> ftl::Optional<HalDisplayId> { + return ftl::match( + variant, + [](GpuVirtualDisplayId) -> ftl::Optional<HalDisplayId> { return std::nullopt; }, + [](auto id) -> ftl::Optional<HalDisplayId> { + return ftl::Optional(static_cast<HalDisplayId>(id)); + }); +} + +inline auto asPhysicalDisplayId(DisplayIdVariant variant) -> ftl::Optional<PhysicalDisplayId> { + return asDisplayIdOfType<PhysicalDisplayId>(variant); +} + +inline auto asVirtualDisplayId(DisplayIdVariant variant) -> ftl::Optional<VirtualDisplayId> { + return ftl::match( + variant, + [](GpuVirtualDisplayId id) -> ftl::Optional<VirtualDisplayId> { + return ftl::Optional(static_cast<VirtualDisplayId>(id)); + }, + [](HalVirtualDisplayId id) -> ftl::Optional<VirtualDisplayId> { + return ftl::Optional(static_cast<VirtualDisplayId>(id)); + }, + [](auto) -> ftl::Optional<VirtualDisplayId> { return std::nullopt; }); +} + +inline auto asDisplayId(DisplayIdVariant variant) -> DisplayId { + return ftl::match(variant, [](auto id) -> DisplayId { return static_cast<DisplayId>(id); }); +} + static_assert(sizeof(DisplayId) == sizeof(uint64_t)); static_assert(sizeof(HalDisplayId) == sizeof(uint64_t)); static_assert(sizeof(VirtualDisplayId) == sizeof(uint64_t)); diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h index 334106f0cf..3560d57cff 100644 --- a/libs/ui/include/ui/FenceTime.h +++ b/libs/ui/include/ui/FenceTime.h @@ -17,6 +17,7 @@ #ifndef ANDROID_FENCE_TIME_H #define ANDROID_FENCE_TIME_H +#include <stddef.h> #include <ui/Fence.h> #include <utils/Flattenable.h> #include <utils/Mutex.h> @@ -30,6 +31,8 @@ namespace android { class FenceToFenceTimeMap; +class FenceTime; +using FenceTimePtr = std::shared_ptr<FenceTime>; // A wrapper around fence that only implements isValid and getSignalTime. // It automatically closes the fence in a thread-safe manner once the signal @@ -95,6 +98,10 @@ public: FenceTime& operator=(const FenceTime&) = delete; FenceTime& operator=(FenceTime&&) = delete; + // Constructs a FenceTime, falling back to a timestamp if the fence is + // invalid. + static FenceTimePtr makeValid(const sp<Fence>& fence); + // This method should only be called when replacing the fence with // a signalTime. Since this is an indirect way of setting the signal time // of a fence, the snapshot should come from a trusted source. @@ -142,8 +149,6 @@ private: std::atomic<nsecs_t> mSignalTime{Fence::SIGNAL_TIME_INVALID}; }; -using FenceTimePtr = std::shared_ptr<FenceTime>; - // A queue of FenceTimes that are expected to signal in FIFO order. // Only maintains a queue of weak pointers so it doesn't keep references // to Fences on its own. @@ -162,8 +167,6 @@ using FenceTimePtr = std::shared_ptr<FenceTime>; // different threads. class FenceTimeline { public: - static constexpr size_t MAX_ENTRIES = 64; - void push(const std::shared_ptr<FenceTime>& fence); void updateSignalTimes(); diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 936bf8f862..9305180ecb 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -23,6 +23,7 @@ #include <string> #include <utility> #include <vector> +#include "ui/DependencyMonitor.h" #include <android/hardware_buffer.h> #include <ui/ANativeObjectBase.h> @@ -229,6 +230,8 @@ public: void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context); + DependencyMonitor& getDependencyMonitor() { return mDependencyMonitor; } + private: ~GraphicBuffer(); @@ -295,6 +298,8 @@ private: // and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer. std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>> mDeathCallbacks; + + DependencyMonitor mDependencyMonitor; }; } // namespace android diff --git a/libs/ui/include/ui/StaticDisplayInfo.h b/libs/ui/include/ui/StaticDisplayInfo.h index 83da821f37..53164487f3 100644 --- a/libs/ui/include/ui/StaticDisplayInfo.h +++ b/libs/ui/include/ui/StaticDisplayInfo.h @@ -28,6 +28,7 @@ enum class DisplayConnectionType { Internal, External, ftl_last = External }; // Immutable information about physical display. struct StaticDisplayInfo { DisplayConnectionType connectionType = DisplayConnectionType::Internal; + uint8_t port; float density = 0.f; bool secure = false; std::optional<DeviceProductInfo> deviceProductInfo; diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 2b11786df3..d950f2a23f 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -45,16 +45,6 @@ cc_test { } cc_test { - name: "DisplayId_test", - shared_libs: ["libui"], - srcs: ["DisplayId_test.cpp"], - cflags: [ - "-Wall", - "-Werror", - ], -} - -cc_test { name: "DisplayIdentification_test", shared_libs: ["libui"], static_libs: ["libgmock"], diff --git a/libs/ui/tests/DisplayId_test.cpp b/libs/ui/tests/DisplayId_test.cpp deleted file mode 100644 index 209acba672..0000000000 --- a/libs/ui/tests/DisplayId_test.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020 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. - */ - -#include <ui/DisplayId.h> - -#include <gtest/gtest.h> - -namespace android::ui { - -TEST(DisplayIdTest, createPhysicalIdFromEdid) { - constexpr uint8_t port = 1; - constexpr uint16_t manufacturerId = 13; - constexpr uint32_t modelHash = 42; - const PhysicalDisplayId id = PhysicalDisplayId::fromEdid(port, manufacturerId, modelHash); - EXPECT_EQ(port, id.getPort()); - EXPECT_FALSE(VirtualDisplayId::tryCast(id)); - EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_TRUE(PhysicalDisplayId::tryCast(id)); - EXPECT_TRUE(HalDisplayId::tryCast(id)); - - EXPECT_EQ(id, DisplayId::fromValue(id.value)); - EXPECT_EQ(id, PhysicalDisplayId::fromValue(id.value)); -} - -TEST(DisplayIdTest, createPhysicalIdFromPort) { - constexpr uint8_t port = 3; - const PhysicalDisplayId id = PhysicalDisplayId::fromPort(port); - EXPECT_EQ(port, id.getPort()); - EXPECT_FALSE(VirtualDisplayId::tryCast(id)); - EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_TRUE(PhysicalDisplayId::tryCast(id)); - EXPECT_TRUE(HalDisplayId::tryCast(id)); - - EXPECT_EQ(id, DisplayId::fromValue(id.value)); - EXPECT_EQ(id, PhysicalDisplayId::fromValue(id.value)); -} - -TEST(DisplayIdTest, createGpuVirtualId) { - const GpuVirtualDisplayId id(42); - EXPECT_TRUE(VirtualDisplayId::tryCast(id)); - EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); - EXPECT_FALSE(HalDisplayId::tryCast(id)); - - EXPECT_EQ(id, DisplayId::fromValue(id.value)); - EXPECT_EQ(id, GpuVirtualDisplayId::fromValue(id.value)); -} - -TEST(DisplayIdTest, createVirtualIdFromGpuVirtualId) { - const VirtualDisplayId id(GpuVirtualDisplayId(42)); - EXPECT_TRUE(VirtualDisplayId::tryCast(id)); - EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); - EXPECT_FALSE(HalDisplayId::tryCast(id)); - - const bool isGpuVirtualId = (id.value & VirtualDisplayId::FLAG_GPU); - EXPECT_EQ((id.isVirtual() && isGpuVirtualId), GpuVirtualDisplayId::tryCast(id).has_value()); -} - -TEST(DisplayIdTest, createHalVirtualId) { - const HalVirtualDisplayId id(42); - EXPECT_TRUE(VirtualDisplayId::tryCast(id)); - EXPECT_TRUE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); - EXPECT_TRUE(HalDisplayId::tryCast(id)); - - EXPECT_EQ(id, DisplayId::fromValue(id.value)); - EXPECT_EQ(id, HalVirtualDisplayId::fromValue(id.value)); -} - -TEST(DisplayIdTest, createVirtualIdFromHalVirtualId) { - const VirtualDisplayId id(HalVirtualDisplayId(42)); - EXPECT_TRUE(VirtualDisplayId::tryCast(id)); - EXPECT_TRUE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); - EXPECT_TRUE(HalDisplayId::tryCast(id)); - - const bool isGpuVirtualId = (id.value & VirtualDisplayId::FLAG_GPU); - EXPECT_EQ((id.isVirtual() && !isGpuVirtualId), HalVirtualDisplayId::tryCast(id).has_value()); -} - -} // namespace android::ui |