summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/binder/Android.bp9
-rw-r--r--libs/binder/rust/rpcbinder/src/lib.rs2
-rw-r--r--libs/binder/rust/rpcbinder/src/server/trusty.rs4
-rw-r--r--libs/binder/rust/src/binder.rs6
-rw-r--r--libs/gui/BLASTBufferQueue.cpp6
-rw-r--r--libs/gui/BufferQueueProducer.cpp6
-rw-r--r--libs/gui/ISurfaceComposer.cpp121
-rw-r--r--libs/gui/SurfaceComposerClient.cpp336
-rw-r--r--libs/gui/aidl/android/gui/StaticDisplayInfo.aidl1
-rw-r--r--libs/gui/include/gui/BLASTBufferQueue.h2
-rw-r--r--libs/gui/include/gui/ISurfaceComposer.h9
-rw-r--r--libs/gui/include/gui/InputTransferToken.h10
-rw-r--r--libs/gui/include/gui/SurfaceComposerClient.h66
-rw-r--r--libs/gui/include/gui/TransactionState.h6
-rw-r--r--libs/gui/libgui_flags.aconfig14
-rw-r--r--libs/gui/tests/EndToEndNativeInputTest.cpp8
-rw-r--r--libs/gui/tests/Surface_test.cpp57
-rw-r--r--libs/renderengine/Android.bp6
-rw-r--r--libs/renderengine/benchmark/Android.bp2
-rw-r--r--libs/renderengine/skia/SkiaRenderEngine.cpp10
-rw-r--r--libs/renderengine/skia/filters/LutShader.cpp7
-rw-r--r--libs/ui/Android.bp1
-rw-r--r--libs/ui/DependencyMonitor.cpp144
-rw-r--r--libs/ui/FenceTime.cpp13
-rw-r--r--libs/ui/GraphicBuffer.cpp14
-rw-r--r--libs/ui/include/ui/DependencyMonitor.h104
-rw-r--r--libs/ui/include/ui/DisplayId.h81
-rw-r--r--libs/ui/include/ui/FenceTime.h11
-rw-r--r--libs/ui/include/ui/GraphicBuffer.h5
-rw-r--r--libs/ui/include/ui/StaticDisplayInfo.h1
-rw-r--r--libs/ui/tests/Android.bp10
-rw-r--r--libs/ui/tests/DisplayId_test.cpp101
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