diff options
| author | 2024-09-05 17:02:51 -0700 | |
|---|---|---|
| committer | 2024-09-05 17:02:51 -0700 | |
| commit | 60d226fc1fff9274bbb33d9c7c8a3f1b3724e832 (patch) | |
| tree | 4226e3be80e148cc9f00816bb3bd35d87929dfad /libs/gui | |
| parent | 69ec43c8a4007d96acf6d44a5484432b69ca884c (diff) | |
| parent | 98858ea367d1acc939b970cbce5528aa98213a9d (diff) | |
Merge 24Q3 to AOSP main
Bug: 357762254
Merged-In: Ibe9b06e590ed420f29c790188dee11674fca5a2e
Change-Id: Ib27f6f1e35c80ef5ac6adec6353609004ed6ed5d
Diffstat (limited to 'libs/gui')
58 files changed, 1193 insertions, 685 deletions
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 7dcbbc04bf..51d2e5305a 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -41,6 +41,11 @@ cc_aconfig_library { aconfig_declarations: "libgui_flags", } +cc_aconfig_library { + name: "libguiflags_no_apex", + aconfig_declarations: "libgui_flags", +} + cc_library_headers { name: "libgui_headers", vendor_available: true, @@ -87,6 +92,7 @@ filegroup { "android/gui/DropInputMode.aidl", "android/gui/StalledTransactionInfo.aidl", "android/**/TouchOcclusionMode.aidl", + "android/gui/TrustedOverlay.aidl", ], } @@ -155,9 +161,9 @@ cc_library_static { }, } -aidl_library { - name: "libgui_aidl_hdrs", - hdrs: [ +filegroup { + name: "libgui_extra_aidl_files", + srcs: [ "android/gui/DisplayInfo.aidl", "android/gui/FocusRequest.aidl", "android/gui/InputApplicationInfo.aidl", @@ -170,11 +176,34 @@ aidl_library { ], } +filegroup { + name: "libgui_extra_unstructured_aidl_files", + srcs: [ + "android/gui/DisplayInfo.aidl", + "android/gui/InputApplicationInfo.aidl", + "android/gui/WindowInfo.aidl", + "android/gui/WindowInfosUpdate.aidl", + ], +} + +aidl_library { + name: "libgui_aidl_hdrs", + hdrs: [":libgui_extra_aidl_files"], +} + +aidl_library { + name: "libgui_extra_unstructured_aidl_hdrs", + hdrs: [":libgui_extra_unstructured_aidl_files"], +} + aidl_library { name: "libgui_aidl", srcs: ["aidl/**/*.aidl"], strip_import_prefix: "aidl", - deps: ["libgui_aidl_hdrs"], + deps: [ + "libgui_aidl_hdrs", + "libgui_extra_unstructured_aidl_hdrs", + ], } filegroup { @@ -241,7 +270,6 @@ filegroup { "IProducerListener.cpp", "ISurfaceComposer.cpp", "ITransactionCompletedListener.cpp", - "LayerDebugInfo.cpp", "LayerMetadata.cpp", "LayerStatePermissions.cpp", "LayerState.cpp", diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index f317a2eea0..739c3c2a41 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -613,8 +613,19 @@ status_t BLASTBufferQueue::acquireNextBufferLocked( std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE; + + nsecs_t dequeueTime = -1; + { + std::lock_guard _lock{mTimestampMutex}; + auto dequeueTimeIt = mDequeueTimestamps.find(buffer->getId()); + if (dequeueTimeIt != mDequeueTimestamps.end()) { + dequeueTime = dequeueTimeIt->second; + mDequeueTimestamps.erase(dequeueTimeIt); + } + } + t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, mProducerId, - releaseBufferCallback); + releaseBufferCallback, dequeueTime); t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace)); t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage); @@ -658,17 +669,6 @@ status_t BLASTBufferQueue::acquireNextBufferLocked( mPendingFrameTimelines.pop(); } - { - std::lock_guard _lock{mTimestampMutex}; - auto dequeueTime = mDequeueTimestamps.find(buffer->getId()); - if (dequeueTime != mDequeueTimestamps.end()) { - Parcel p; - p.writeInt64(dequeueTime->second); - t->setMetadata(mSurfaceControl, gui::METADATA_DEQUEUE_TIME, p); - mDequeueTimestamps.erase(dequeueTime); - } - } - mergePendingTransactions(t, bufferItem.mFrameNumber); if (applyTransaction) { // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 88d456bf2c..a4d105d320 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -423,6 +423,11 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou sp<IConsumerListener> listener; bool callOnFrameDequeued = false; uint64_t bufferId = 0; // Only used if callOnFrameDequeued == true +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + std::vector<gui::AdditionalOptions> allocOptions; + uint32_t allocOptionsGenId = 0; +#endif + { // Autolock scope std::unique_lock<std::mutex> lock(mCore->mMutex); @@ -486,11 +491,17 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou } const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer); - if (mCore->mSharedBufferSlot == found && - buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) { - BQ_LOGE("dequeueBuffer: cannot re-allocate a shared" - "buffer"); + bool needsReallocation = buffer == nullptr || + buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage); + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + needsReallocation |= mSlots[found].mAdditionalOptionsGenerationId != + mCore->mAdditionalOptionsGenerationId; +#endif + + if (mCore->mSharedBufferSlot == found && needsReallocation) { + BQ_LOGE("dequeueBuffer: cannot re-allocate a shared buffer"); return BAD_VALUE; } @@ -505,9 +516,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou mSlots[found].mBufferState.dequeue(); - if ((buffer == nullptr) || - buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) - { + if (needsReallocation) { if (CC_UNLIKELY(ATRACE_ENABLED())) { if (buffer == nullptr) { ATRACE_FORMAT_INSTANT("%s buffer reallocation: null", mConsumerName.c_str()); @@ -530,6 +539,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou mSlots[found].mFence = Fence::NO_FENCE; mCore->mBufferAge = 0; mCore->mIsAllocating = true; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + allocOptions = mCore->mAdditionalOptions; + allocOptionsGenId = mCore->mAdditionalOptionsGenerationId; +#endif returnFlags |= BUFFER_NEEDS_REALLOCATION; } else { @@ -575,9 +588,29 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou if (returnFlags & BUFFER_NEEDS_REALLOCATION) { BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot); + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + std::vector<GraphicBufferAllocator::AdditionalOptions> tempOptions; + tempOptions.reserve(allocOptions.size()); + for (const auto& it : allocOptions) { + tempOptions.emplace_back(it.name.c_str(), it.value); + } + const GraphicBufferAllocator::AllocationRequest allocRequest = { + .importBuffer = true, + .width = width, + .height = height, + .format = format, + .layerCount = BQ_LAYER_COUNT, + .usage = usage, + .requestorName = {mConsumerName.c_str(), mConsumerName.size()}, + .extras = std::move(tempOptions), + }; + sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest); +#else sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(width, height, format, BQ_LAYER_COUNT, usage, {mConsumerName.c_str(), mConsumerName.size()}); +#endif status_t error = graphicBuffer->initCheck(); @@ -587,6 +620,9 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou if (error == NO_ERROR && !mCore->mIsAbandoned) { graphicBuffer->setGenerationNumber(mCore->mGenerationNumber); mSlots[*outSlot].mGraphicBuffer = graphicBuffer; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + mSlots[*outSlot].mAdditionalOptionsGenerationId = allocOptionsGenId; +#endif callOnFrameDequeued = true; bufferId = mSlots[*outSlot].mGraphicBuffer->getId(); } @@ -1345,6 +1381,9 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, } mCore->mAllowAllocation = true; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + mCore->mAdditionalOptions.clear(); +#endif VALIDATE_CONSISTENCY(); return status; } @@ -1413,6 +1452,9 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { mCore->mSidebandStream.clear(); mCore->mDequeueCondition.notify_all(); mCore->mAutoPrerotation = false; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + mCore->mAdditionalOptions.clear(); +#endif listener = mCore->mConsumerListener; } else if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { BQ_LOGE("disconnect: not connected (req=%d)", api); @@ -1465,6 +1507,10 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN; uint64_t allocUsage = 0; std::string allocName; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + std::vector<gui::AdditionalOptions> allocOptions; + uint32_t allocOptionsGenId = 0; +#endif { // Autolock scope std::unique_lock<std::mutex> lock(mCore->mMutex); mCore->waitWhileAllocatingLocked(lock); @@ -1493,14 +1539,42 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, allocUsage = usage | mCore->mConsumerUsageBits; allocName.assign(mCore->mConsumerName.c_str(), mCore->mConsumerName.size()); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + allocOptions = mCore->mAdditionalOptions; + allocOptionsGenId = mCore->mAdditionalOptionsGenerationId; +#endif + mCore->mIsAllocating = true; + } // Autolock scope +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + std::vector<GraphicBufferAllocator::AdditionalOptions> tempOptions; + tempOptions.reserve(allocOptions.size()); + for (const auto& it : allocOptions) { + tempOptions.emplace_back(it.name.c_str(), it.value); + } + const GraphicBufferAllocator::AllocationRequest allocRequest = { + .importBuffer = true, + .width = allocWidth, + .height = allocHeight, + .format = allocFormat, + .layerCount = BQ_LAYER_COUNT, + .usage = allocUsage, + .requestorName = allocName, + .extras = std::move(tempOptions), + }; +#endif + Vector<sp<GraphicBuffer>> buffers; for (size_t i = 0; i < newBufferCount; ++i) { +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest); +#else sp<GraphicBuffer> graphicBuffer = new GraphicBuffer( allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT, allocUsage, allocName); +#endif status_t result = graphicBuffer->initCheck(); @@ -1527,8 +1601,12 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, PixelFormat checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat; uint64_t checkUsage = usage | mCore->mConsumerUsageBits; + bool allocOptionsChanged = false; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + allocOptionsChanged = allocOptionsGenId != mCore->mAdditionalOptionsGenerationId; +#endif if (checkWidth != allocWidth || checkHeight != allocHeight || - checkFormat != allocFormat || checkUsage != allocUsage) { + checkFormat != allocFormat || checkUsage != allocUsage || allocOptionsChanged) { // Something changed while we released the lock. Retry. BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying."); mCore->mIsAllocating = false; @@ -1546,6 +1624,9 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, mCore->clearBufferSlotLocked(*slot); // Clean up the slot first mSlots[*slot].mGraphicBuffer = buffers[i]; mSlots[*slot].mFence = Fence::NO_FENCE; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + mSlots[*slot].mAdditionalOptionsGenerationId = allocOptionsGenId; +#endif // freeBufferLocked puts this slot on the free slots list. Since // we then attached a buffer, move the slot to free buffer list. @@ -1781,4 +1862,29 @@ status_t BufferQueueProducer::setFrameRate(float frameRate, int8_t compatibility } #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) +status_t BufferQueueProducer::setAdditionalOptions( + const std::vector<gui::AdditionalOptions>& options) { + ATRACE_CALL(); + BQ_LOGV("setAdditionalOptions, size = %zu", options.size()); + + if (!GraphicBufferAllocator::get().supportsAdditionalOptions()) { + return INVALID_OPERATION; + } + + std::lock_guard<std::mutex> lock(mCore->mMutex); + + if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) { + BQ_LOGE("setAdditionalOptions: BufferQueue not connected, cannot set additional options"); + return NO_INIT; + } + + if (mCore->mAdditionalOptions != options) { + mCore->mAdditionalOptions = options; + mCore->mAdditionalOptionsGenerationId++; + } + return NO_ERROR; +} +#endif + } // namespace android diff --git a/libs/gui/Choreographer.cpp b/libs/gui/Choreographer.cpp index 4518b67d4c..0c8f3fa096 100644 --- a/libs/gui/Choreographer.cpp +++ b/libs/gui/Choreographer.cpp @@ -143,9 +143,9 @@ Choreographer::~Choreographer() { void Choreographer::postFrameCallbackDelayed(AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, AChoreographer_vsyncCallback vsyncCallback, void* data, - nsecs_t delay) { + nsecs_t delay, CallbackType callbackType) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - FrameCallback callback{cb, cb64, vsyncCallback, data, now + delay}; + FrameCallback callback{cb, cb64, vsyncCallback, data, now + delay, callbackType}; { std::lock_guard<std::mutex> _l{mLock}; mFrameCallbacks.push(callback); @@ -285,18 +285,8 @@ void Choreographer::handleRefreshRateUpdates() { } } -void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, - VsyncEventData vsyncEventData) { - std::vector<FrameCallback> callbacks{}; - { - std::lock_guard<std::mutex> _l{mLock}; - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - while (!mFrameCallbacks.empty() && mFrameCallbacks.top().dueTime < now) { - callbacks.push_back(mFrameCallbacks.top()); - mFrameCallbacks.pop(); - } - } - mLastVsyncEventData = vsyncEventData; +void Choreographer::dispatchCallbacks(const std::vector<FrameCallback>& callbacks, + VsyncEventData vsyncEventData, nsecs_t timestamp) { for (const auto& cb : callbacks) { if (cb.vsyncCallback != nullptr) { ATRACE_FORMAT("AChoreographer_vsyncCallback %" PRId64, @@ -319,6 +309,34 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t } } +void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, + VsyncEventData vsyncEventData) { + std::vector<FrameCallback> animationCallbacks{}; + std::vector<FrameCallback> inputCallbacks{}; + { + std::lock_guard<std::mutex> _l{mLock}; + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + while (!mFrameCallbacks.empty() && mFrameCallbacks.top().dueTime < now) { + if (mFrameCallbacks.top().callbackType == CALLBACK_INPUT) { + inputCallbacks.push_back(mFrameCallbacks.top()); + } else { + animationCallbacks.push_back(mFrameCallbacks.top()); + } + mFrameCallbacks.pop(); + } + } + mLastVsyncEventData = vsyncEventData; + // Callbacks with type CALLBACK_INPUT should always run first + { + ATRACE_FORMAT("CALLBACK_INPUT"); + dispatchCallbacks(inputCallbacks, vsyncEventData, timestamp); + } + { + ATRACE_FORMAT("CALLBACK_ANIMATION"); + dispatchCallbacks(animationCallbacks, vsyncEventData, timestamp); + } +} + void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool connected) { ALOGV("choreographer %p ~ received hotplug event (displayId=%s, connected=%s), ignoring.", this, to_string(displayId).c_str(), toString(connected)); @@ -407,4 +425,8 @@ int64_t Choreographer::getStartTimeNanosForVsyncId(AVsyncId vsyncId) { return iter->second; } +const sp<Looper> Choreographer::getLooper() { + return mLooper; +} + } // namespace android diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index f3de96d2cd..c46f9c50ef 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -15,6 +15,7 @@ */ #define LOG_TAG "DisplayEventDispatcher" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <cinttypes> #include <cstdint> @@ -23,10 +24,13 @@ #include <gui/DisplayEventReceiver.h> #include <utils/Log.h> #include <utils/Looper.h> - #include <utils/Timers.h> +#include <utils/Trace.h> + +#include <com_android_graphics_libgui_flags.h> namespace android { +using namespace com::android::graphics::libgui; // Number of events to read at a time from the DisplayEventDispatcher pipe. // The value should be large enough that we can quickly drain the pipe @@ -171,6 +175,13 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, *outDisplayId = ev.header.displayId; *outCount = ev.vsync.count; *outVsyncEventData = ev.vsync.vsyncData; + + // Trace the RenderRate for this app + if (ATRACE_ENABLED() && flags::trace_frame_rate_override()) { + const auto frameInterval = ev.vsync.vsyncData.frameInterval; + int fps = frameInterval > 0 ? 1e9f / frameInterval : 0; + ATRACE_INT("RenderRate", fps); + } break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: if (ev.hotplug.connectionError == 0) { diff --git a/libs/gui/DisplayInfo.cpp b/libs/gui/DisplayInfo.cpp index bd640df81e..47cec0778e 100644 --- a/libs/gui/DisplayInfo.cpp +++ b/libs/gui/DisplayInfo.cpp @@ -37,8 +37,9 @@ status_t DisplayInfo::readFromParcel(const android::Parcel* parcel) { return BAD_VALUE; } + int32_t displayIdInt; float dsdx, dtdx, tx, dtdy, dsdy, ty; - SAFE_PARCEL(parcel->readInt32, &displayId); + SAFE_PARCEL(parcel->readInt32, &displayIdInt); SAFE_PARCEL(parcel->readInt32, &logicalWidth); SAFE_PARCEL(parcel->readInt32, &logicalHeight); SAFE_PARCEL(parcel->readFloat, &dsdx); @@ -48,6 +49,7 @@ status_t DisplayInfo::readFromParcel(const android::Parcel* parcel) { SAFE_PARCEL(parcel->readFloat, &dsdy); SAFE_PARCEL(parcel->readFloat, &ty); + displayId = ui::LogicalDisplayId{displayIdInt}; transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1}); return OK; @@ -59,7 +61,7 @@ status_t DisplayInfo::writeToParcel(android::Parcel* parcel) const { return BAD_VALUE; } - SAFE_PARCEL(parcel->writeInt32, displayId); + SAFE_PARCEL(parcel->writeInt32, displayId.val()); SAFE_PARCEL(parcel->writeInt32, logicalWidth); SAFE_PARCEL(parcel->writeInt32, logicalHeight); SAFE_PARCEL(parcel->writeFloat, transform.dsdx()); @@ -76,7 +78,7 @@ void DisplayInfo::dump(std::string& out, const char* prefix) const { using android::base::StringAppendF; out += prefix; - StringAppendF(&out, "DisplayViewport[id=%" PRId32 "]\n", displayId); + StringAppendF(&out, "DisplayViewport[id=%s]\n", displayId.toString().c_str()); out += prefix; StringAppendF(&out, INDENT "Width=%" PRId32 ", Height=%" PRId32 "\n", logicalWidth, logicalHeight); diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index e81c098b85..09144806ee 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -80,6 +80,7 @@ enum { QUERY_MULTIPLE, GET_LAST_QUEUED_BUFFER2, SET_FRAME_RATE, + SET_ADDITIONAL_OPTIONS, }; class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> @@ -778,6 +779,25 @@ public: return result; } #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + virtual status_t setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options) { + Parcel data, reply; + data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + if (options.size() > 100) { + return BAD_VALUE; + } + data.writeInt32(options.size()); + for (const auto& it : options) { + data.writeCString(it.name.c_str()); + data.writeInt64(it.value); + } + status_t result = remote()->transact(SET_ADDITIONAL_OPTIONS, data, &reply); + if (result == NO_ERROR) { + result = reply.readInt32(); + } + return result; + } +#endif }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -981,6 +1001,13 @@ status_t IGraphicBufferProducer::setFrameRate(float /*frameRate*/, int8_t /*comp } #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) +status_t IGraphicBufferProducer::setAdditionalOptions(const std::vector<gui::AdditionalOptions>&) { + // No-op for IGBP other than BufferQueue. + return INVALID_OPERATION; +} +#endif + status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) { status_t res = OK; res = parcel->writeUint32(USE_BUFFER_QUEUE); @@ -1533,6 +1560,28 @@ status_t BnGraphicBufferProducer::onTransact( return NO_ERROR; } #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + case SET_ADDITIONAL_OPTIONS: { + CHECK_INTERFACE(IGraphicBuffer, data, reply); + int optionCount = data.readInt32(); + if (optionCount < 0 || optionCount > 100) { + return BAD_VALUE; + } + std::vector<gui::AdditionalOptions> opts; + opts.reserve(optionCount); + for (int i = 0; i < optionCount; i++) { + const char* name = data.readCString(); + int64_t value = 0; + if (name == nullptr || data.readInt64(&value) != NO_ERROR) { + return BAD_VALUE; + } + opts.emplace_back(name, value); + } + status_t result = setAdditionalOptions(opts); + reply->writeInt32(result); + return NO_ERROR; + } +#endif } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp deleted file mode 100644 index 15b2221464..0000000000 --- a/libs/gui/LayerDebugInfo.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2017 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 <gui/LayerDebugInfo.h> - -#include <android-base/stringprintf.h> - -#include <ui/DebugUtils.h> - -#include <binder/Parcel.h> - -using namespace android; -using android::base::StringAppendF; - -#define RETURN_ON_ERROR(X) do {status_t res = (X); if (res != NO_ERROR) return res;} while(false) - -namespace android::gui { - -status_t LayerDebugInfo::writeToParcel(Parcel* parcel) const { - RETURN_ON_ERROR(parcel->writeCString(mName.c_str())); - RETURN_ON_ERROR(parcel->writeCString(mParentName.c_str())); - RETURN_ON_ERROR(parcel->writeCString(mType.c_str())); - RETURN_ON_ERROR(parcel->write(mTransparentRegion)); - RETURN_ON_ERROR(parcel->write(mVisibleRegion)); - RETURN_ON_ERROR(parcel->write(mSurfaceDamageRegion)); - RETURN_ON_ERROR(parcel->writeUint32(mLayerStack)); - RETURN_ON_ERROR(parcel->writeFloat(mX)); - RETURN_ON_ERROR(parcel->writeFloat(mY)); - RETURN_ON_ERROR(parcel->writeUint32(mZ)); - RETURN_ON_ERROR(parcel->writeInt32(mWidth)); - RETURN_ON_ERROR(parcel->writeInt32(mHeight)); - RETURN_ON_ERROR(parcel->write(mCrop)); - RETURN_ON_ERROR(parcel->writeFloat(mColor.r)); - RETURN_ON_ERROR(parcel->writeFloat(mColor.g)); - RETURN_ON_ERROR(parcel->writeFloat(mColor.b)); - RETURN_ON_ERROR(parcel->writeFloat(mColor.a)); - RETURN_ON_ERROR(parcel->writeUint32(mFlags)); - RETURN_ON_ERROR(parcel->writeInt32(mPixelFormat)); - RETURN_ON_ERROR(parcel->writeUint32(static_cast<uint32_t>(mDataSpace))); - for (size_t index = 0; index < 4; index++) { - RETURN_ON_ERROR(parcel->writeFloat(mMatrix[index / 2][index % 2])); - } - RETURN_ON_ERROR(parcel->writeInt32(mActiveBufferWidth)); - RETURN_ON_ERROR(parcel->writeInt32(mActiveBufferHeight)); - RETURN_ON_ERROR(parcel->writeInt32(mActiveBufferStride)); - RETURN_ON_ERROR(parcel->writeInt32(mActiveBufferFormat)); - RETURN_ON_ERROR(parcel->writeInt32(mNumQueuedFrames)); - RETURN_ON_ERROR(parcel->writeBool(mIsOpaque)); - RETURN_ON_ERROR(parcel->writeBool(mContentDirty)); - RETURN_ON_ERROR(parcel->write(mStretchEffect)); - return NO_ERROR; -} - -status_t LayerDebugInfo::readFromParcel(const Parcel* parcel) { - mName = parcel->readCString(); - RETURN_ON_ERROR(parcel->errorCheck()); - mParentName = parcel->readCString(); - RETURN_ON_ERROR(parcel->errorCheck()); - mType = parcel->readCString(); - RETURN_ON_ERROR(parcel->errorCheck()); - RETURN_ON_ERROR(parcel->read(mTransparentRegion)); - RETURN_ON_ERROR(parcel->read(mVisibleRegion)); - RETURN_ON_ERROR(parcel->read(mSurfaceDamageRegion)); - RETURN_ON_ERROR(parcel->readUint32(&mLayerStack)); - RETURN_ON_ERROR(parcel->readFloat(&mX)); - RETURN_ON_ERROR(parcel->readFloat(&mY)); - RETURN_ON_ERROR(parcel->readUint32(&mZ)); - RETURN_ON_ERROR(parcel->readInt32(&mWidth)); - RETURN_ON_ERROR(parcel->readInt32(&mHeight)); - RETURN_ON_ERROR(parcel->read(mCrop)); - mColor.r = parcel->readFloat(); - RETURN_ON_ERROR(parcel->errorCheck()); - mColor.g = parcel->readFloat(); - RETURN_ON_ERROR(parcel->errorCheck()); - mColor.b = parcel->readFloat(); - RETURN_ON_ERROR(parcel->errorCheck()); - mColor.a = parcel->readFloat(); - RETURN_ON_ERROR(parcel->errorCheck()); - RETURN_ON_ERROR(parcel->readUint32(&mFlags)); - RETURN_ON_ERROR(parcel->readInt32(&mPixelFormat)); - // \todo [2017-07-25 kraita]: Static casting mDataSpace pointer to an uint32 does work. Better ways? - mDataSpace = static_cast<android_dataspace>(parcel->readUint32()); - RETURN_ON_ERROR(parcel->errorCheck()); - for (size_t index = 0; index < 4; index++) { - RETURN_ON_ERROR(parcel->readFloat(&mMatrix[index / 2][index % 2])); - } - RETURN_ON_ERROR(parcel->readInt32(&mActiveBufferWidth)); - RETURN_ON_ERROR(parcel->readInt32(&mActiveBufferHeight)); - RETURN_ON_ERROR(parcel->readInt32(&mActiveBufferStride)); - RETURN_ON_ERROR(parcel->readInt32(&mActiveBufferFormat)); - RETURN_ON_ERROR(parcel->readInt32(&mNumQueuedFrames)); - RETURN_ON_ERROR(parcel->readBool(&mIsOpaque)); - RETURN_ON_ERROR(parcel->readBool(&mContentDirty)); - RETURN_ON_ERROR(parcel->read(mStretchEffect)); - return NO_ERROR; -} - -std::string to_string(const LayerDebugInfo& info) { - std::string result; - - StringAppendF(&result, "+ %s (%s)\n", info.mType.c_str(), info.mName.c_str()); - info.mTransparentRegion.dump(result, "TransparentRegion"); - info.mVisibleRegion.dump(result, "VisibleRegion"); - info.mSurfaceDamageRegion.dump(result, "SurfaceDamageRegion"); - if (info.mStretchEffect.hasEffect()) { - const auto& se = info.mStretchEffect; - StringAppendF(&result, - " StretchEffect width = %f, height = %f vec=(%f, %f) " - "maxAmount=(%f, %f)\n", - se.width, se.height, - se.vectorX, se.vectorY, se.maxAmountX, se.maxAmountY); - } - - StringAppendF(&result, " layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ", - info.mLayerStack, info.mZ, static_cast<double>(info.mX), - static_cast<double>(info.mY), info.mWidth, info.mHeight); - - StringAppendF(&result, "crop=%s, ", to_string(info.mCrop).c_str()); - StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty); - StringAppendF(&result, "dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str()); - StringAppendF(&result, "pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str()); - StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ", - static_cast<double>(info.mColor.r), static_cast<double>(info.mColor.g), - static_cast<double>(info.mColor.b), static_cast<double>(info.mColor.a), - info.mFlags); - StringAppendF(&result, "tr=[%.2f, %.2f][%.2f, %.2f]", static_cast<double>(info.mMatrix[0][0]), - static_cast<double>(info.mMatrix[0][1]), static_cast<double>(info.mMatrix[1][0]), - static_cast<double>(info.mMatrix[1][1])); - result.append("\n"); - StringAppendF(&result, " parent=%s\n", info.mParentName.c_str()); - StringAppendF(&result, " activeBuffer=[%4ux%4u:%4u,%s],", info.mActiveBufferWidth, - info.mActiveBufferHeight, info.mActiveBufferStride, - decodePixelFormat(info.mActiveBufferFormat).c_str()); - StringAppendF(&result, " queued-frames=%d", info.mNumQueuedFrames); - result.append("\n"); - return result; -} - -} // namespace android::gui diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp index 4e12fd330c..535a0218b6 100644 --- a/libs/gui/LayerMetadata.cpp +++ b/libs/gui/LayerMetadata.cpp @@ -100,27 +100,31 @@ bool LayerMetadata::has(uint32_t key) const { int32_t LayerMetadata::getInt32(uint32_t key, int32_t fallback) const { if (!has(key)) return fallback; const std::vector<uint8_t>& data = mMap.at(key); - if (data.size() < sizeof(uint32_t)) return fallback; - Parcel p; - p.setData(data.data(), data.size()); - return p.readInt32(); + + // TODO: should handle when not equal? + if (data.size() < sizeof(int32_t)) return fallback; + + int32_t result; + memcpy(&result, data.data(), sizeof(result)); + return result; } void LayerMetadata::setInt32(uint32_t key, int32_t value) { std::vector<uint8_t>& data = mMap[key]; - Parcel p; - p.writeInt32(value); - data.resize(p.dataSize()); - memcpy(data.data(), p.data(), p.dataSize()); + data.resize(sizeof(value)); + memcpy(data.data(), &value, sizeof(value)); } std::optional<int64_t> LayerMetadata::getInt64(uint32_t key) const { if (!has(key)) return std::nullopt; const std::vector<uint8_t>& data = mMap.at(key); + + // TODO: should handle when not equal? if (data.size() < sizeof(int64_t)) return std::nullopt; - Parcel p; - p.setData(data.data(), data.size()); - return p.readInt64(); + + int64_t result; + memcpy(&result, data.data(), sizeof(result)); + return result; } std::string LayerMetadata::itemToString(uint32_t key, const char* separator) const { diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 1e0aacddab..3745805aa3 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -89,8 +89,7 @@ layer_state_t::layer_state_t() frameRateSelectionStrategy(ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_PROPAGATE), fixedTransformHint(ui::Transform::ROT_INVALID), autoRefresh(false), - isTrustedOverlay(false), - borderEnabled(false), + trustedOverlay(gui::TrustedOverlay::UNSET), bufferCrop(Rect::INVALID_RECT), destinationFrame(Rect::INVALID_RECT), dropInputMode(gui::DropInputMode::NONE) { @@ -122,12 +121,6 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.write, transparentRegion); SAFE_PARCEL(output.writeUint32, bufferTransform); SAFE_PARCEL(output.writeBool, transformToDisplayInverse); - SAFE_PARCEL(output.writeBool, borderEnabled); - SAFE_PARCEL(output.writeFloat, borderWidth); - SAFE_PARCEL(output.writeFloat, borderColor.r); - SAFE_PARCEL(output.writeFloat, borderColor.g); - SAFE_PARCEL(output.writeFloat, borderColor.b); - SAFE_PARCEL(output.writeFloat, borderColor.a); SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dataspace)); SAFE_PARCEL(output.write, hdrMetadata); SAFE_PARCEL(output.write, surfaceDamageRegion); @@ -186,7 +179,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.write, stretchEffect); SAFE_PARCEL(output.write, bufferCrop); SAFE_PARCEL(output.write, destinationFrame); - SAFE_PARCEL(output.writeBool, isTrustedOverlay); + SAFE_PARCEL(output.writeInt32, static_cast<uint32_t>(trustedOverlay)); SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode)); @@ -238,17 +231,6 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, transparentRegion); SAFE_PARCEL(input.readUint32, &bufferTransform); SAFE_PARCEL(input.readBool, &transformToDisplayInverse); - SAFE_PARCEL(input.readBool, &borderEnabled); - SAFE_PARCEL(input.readFloat, &tmpFloat); - borderWidth = tmpFloat; - SAFE_PARCEL(input.readFloat, &tmpFloat); - borderColor.r = tmpFloat; - SAFE_PARCEL(input.readFloat, &tmpFloat); - borderColor.g = tmpFloat; - SAFE_PARCEL(input.readFloat, &tmpFloat); - borderColor.b = tmpFloat; - SAFE_PARCEL(input.readFloat, &tmpFloat); - borderColor.a = tmpFloat; uint32_t tmpUint32 = 0; SAFE_PARCEL(input.readUint32, &tmpUint32); @@ -326,7 +308,9 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, stretchEffect); SAFE_PARCEL(input.read, bufferCrop); SAFE_PARCEL(input.read, destinationFrame); - SAFE_PARCEL(input.readBool, &isTrustedOverlay); + uint32_t trustedOverlayInt; + SAFE_PARCEL(input.readUint32, &trustedOverlayInt); + trustedOverlay = static_cast<gui::TrustedOverlay>(trustedOverlayInt); uint32_t mode; SAFE_PARCEL(input.readUint32, &mode); @@ -659,12 +643,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eShadowRadiusChanged; shadowRadius = other.shadowRadius; } - if (other.what & eRenderBorderChanged) { - what |= eRenderBorderChanged; - borderEnabled = other.borderEnabled; - borderWidth = other.borderWidth; - borderColor = other.borderColor; - } if (other.what & eDefaultFrameRateCompatibilityChanged) { what |= eDefaultFrameRateCompatibilityChanged; defaultFrameRateCompatibility = other.defaultFrameRateCompatibility; @@ -698,7 +676,7 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eTrustedOverlayChanged) { what |= eTrustedOverlayChanged; - isTrustedOverlay = other.isTrustedOverlay; + trustedOverlay = other.trustedOverlay; } if (other.what & eStretchChanged) { what |= eStretchChanged; @@ -794,7 +772,6 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF2(diff, eBackgroundColorChanged, other, bgColor, bgColorDataspace); if (other.what & eMetadataChanged) diff |= eMetadataChanged; CHECK_DIFF(diff, eShadowRadiusChanged, other, shadowRadius); - CHECK_DIFF3(diff, eRenderBorderChanged, other, borderEnabled, borderWidth, borderColor); CHECK_DIFF(diff, eDefaultFrameRateCompatibilityChanged, other, defaultFrameRateCompatibility); CHECK_DIFF(diff, eFrameRateSelectionPriority, other, frameRateSelectionPriority); CHECK_DIFF3(diff, eFrameRateChanged, other, frameRate, frameRateCompatibility, @@ -804,7 +781,7 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF(diff, eFrameRateSelectionStrategyChanged, other, frameRateSelectionStrategy); CHECK_DIFF(diff, eFixedTransformHintChanged, other, fixedTransformHint); CHECK_DIFF(diff, eAutoRefreshChanged, other, autoRefresh); - CHECK_DIFF(diff, eTrustedOverlayChanged, other, isTrustedOverlay); + CHECK_DIFF(diff, eTrustedOverlayChanged, other, trustedOverlay); CHECK_DIFF(diff, eStretchChanged, other, stretchEffect); CHECK_DIFF(diff, eBufferCropChanged, other, bufferCrop); CHECK_DIFF(diff, eDestinationFrameChanged, other, destinationFrame); @@ -1008,6 +985,7 @@ status_t BufferData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeBool, hasBarrier); SAFE_PARCEL(output->writeUint64, barrierFrameNumber); SAFE_PARCEL(output->writeUint32, producerId); + SAFE_PARCEL(output->writeInt64, dequeueTime); return NO_ERROR; } @@ -1047,6 +1025,7 @@ status_t BufferData::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readBool, &hasBarrier); SAFE_PARCEL(input->readUint64, &barrierFrameNumber); SAFE_PARCEL(input->readUint32, &producerId); + SAFE_PARCEL(input->readInt64, &dequeueTime); return NO_ERROR; } diff --git a/libs/gui/LayerStatePermissions.cpp b/libs/gui/LayerStatePermissions.cpp index 28697ca953..c467cfdc68 100644 --- a/libs/gui/LayerStatePermissions.cpp +++ b/libs/gui/LayerStatePermissions.cpp @@ -23,31 +23,31 @@ #include <gui/LayerState.h> namespace android { -std::unordered_map<std::string, int> LayerStatePermissions::mPermissionMap = { +std::vector<std::pair<String16, int>> LayerStatePermissions::mPermissionMap = { // If caller has ACCESS_SURFACE_FLINGER, they automatically get ROTATE_SURFACE_FLINGER // permission, as well - {"android.permission.ACCESS_SURFACE_FLINGER", + {String16("android.permission.ACCESS_SURFACE_FLINGER"), layer_state_t::Permission::ACCESS_SURFACE_FLINGER | layer_state_t::Permission::ROTATE_SURFACE_FLINGER}, - {"android.permission.ROTATE_SURFACE_FLINGER", + {String16("android.permission.ROTATE_SURFACE_FLINGER"), layer_state_t::Permission::ROTATE_SURFACE_FLINGER}, - {"android.permission.INTERNAL_SYSTEM_WINDOW", + {String16("android.permission.INTERNAL_SYSTEM_WINDOW"), layer_state_t::Permission::INTERNAL_SYSTEM_WINDOW}, }; -static bool callingThreadHasPermission(const std::string& permission __attribute__((unused)), +static bool callingThreadHasPermission(const String16& permission __attribute__((unused)), int pid __attribute__((unused)), int uid __attribute__((unused))) { #ifndef __ANDROID_VNDK__ return uid == AID_GRAPHICS || uid == AID_SYSTEM || - PermissionCache::checkPermission(String16(permission.c_str()), pid, uid); + PermissionCache::checkPermission(permission, pid, uid); #endif // __ANDROID_VNDK__ return false; } uint32_t LayerStatePermissions::getTransactionPermissions(int pid, int uid) { uint32_t permissions = 0; - for (auto [permissionName, permissionVal] : mPermissionMap) { + for (const auto& [permissionName, permissionVal] : mPermissionMap) { if (callingThreadHasPermission(permissionName, pid, uid)) { permissions |= permissionVal; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 086544e48a..87fd448f0c 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1475,6 +1475,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO: res = dispatchSetFrameTimelineInfo(args); break; + case NATIVE_WINDOW_SET_BUFFERS_ADDITIONAL_OPTIONS: + res = dispatchSetAdditionalOptions(args); + break; default: res = NAME_NOT_FOUND; break; @@ -1833,6 +1836,24 @@ int Surface::dispatchSetFrameTimelineInfo(va_list args) { return setFrameTimelineInfo(nativeWindowFtlInfo.frameNumber, ftlInfo); } +int Surface::dispatchSetAdditionalOptions(va_list args) { + ATRACE_CALL(); + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + const AHardwareBufferLongOptions* opts = va_arg(args, const AHardwareBufferLongOptions*); + const size_t optsSize = va_arg(args, size_t); + std::vector<gui::AdditionalOptions> convertedOpts; + convertedOpts.reserve(optsSize); + for (size_t i = 0; i < optsSize; i++) { + convertedOpts.emplace_back(opts[i].name, opts[i].value); + } + return setAdditionalOptions(convertedOpts); +#else + (void)args; + return INVALID_OPERATION; +#endif +} + bool Surface::transformToDisplayInverse() const { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; @@ -2619,6 +2640,17 @@ status_t Surface::setFrameTimelineInfo(uint64_t /*frameNumber*/, return BAD_VALUE; } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) +status_t Surface::setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options) { + if (!GraphicBufferAllocator::get().supportsAdditionalOptions()) { + return INVALID_OPERATION; + } + + Mutex::Autolock lock(mMutex); + return mGraphicBufferProducer->setAdditionalOptions(options); +} +#endif + sp<IBinder> Surface::getSurfaceControlHandle() const { Mutex::Autolock lock(mMutex); return mSurfaceControlHandle; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7f64a04347..af91bb3ae2 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -89,6 +89,8 @@ int64_t generateId() { void emptyCallback(nsecs_t, const sp<Fence>&, const std::vector<SurfaceControlStats>&) {} } // namespace +const std::string SurfaceComposerClient::kEmpty{}; + ComposerService::ComposerService() : Singleton<ComposerService>() { Mutex::Autolock _l(mLock); @@ -706,6 +708,7 @@ void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId) { SurfaceComposerClient::Transaction::Transaction() { mId = generateId(); + mTransactionCompletedListener = TransactionCompletedListener::getInstance(); } SurfaceComposerClient::Transaction::Transaction(const Transaction& other) @@ -723,6 +726,7 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mComposerStates = other.mComposerStates; mInputWindowCommands = other.mInputWindowCommands; mListenerCallbacks = other.mListenerCallbacks; + mTransactionCompletedListener = TransactionCompletedListener::getInstance(); } void SurfaceComposerClient::Transaction::sanitize(int pid, int uid) { @@ -1000,8 +1004,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr // register all surface controls for all callbackIds for this listener that is merging for (const auto& surfaceControl : currentProcessCallbackInfo.surfaceControls) { - TransactionCompletedListener::getInstance() - ->addSurfaceControlToCallbacks(currentProcessCallbackInfo, surfaceControl); + mTransactionCompletedListener->addSurfaceControlToCallbacks(currentProcessCallbackInfo, + surfaceControl); } } @@ -1276,19 +1280,22 @@ status_t SurfaceComposerClient::Transaction::sendSurfaceFlushJankDataTransaction } // --------------------------------------------------------------------------- -sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool secure, - float requestedRefereshRate) { +sp<IBinder> SurfaceComposerClient::createVirtualDisplay(const std::string& displayName, + bool isSecure, const std::string& uniqueId, + float requestedRefreshRate) { sp<IBinder> display = nullptr; binder::Status status = - ComposerServiceAIDL::getComposerService()->createDisplay(std::string( - displayName.c_str()), - secure, requestedRefereshRate, - &display); + ComposerServiceAIDL::getComposerService()->createVirtualDisplay(displayName, isSecure, + uniqueId, + requestedRefreshRate, + &display); return status.isOk() ? display : nullptr; } -void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) { - ComposerServiceAIDL::getComposerService()->destroyDisplay(display); +status_t SurfaceComposerClient::destroyVirtualDisplay(const sp<IBinder>& displayToken) { + return ComposerServiceAIDL::getComposerService() + ->destroyVirtualDisplay(displayToken) + .transactionError(); } std::vector<PhysicalDisplayId> SurfaceComposerClient::getPhysicalDisplayIds() { @@ -1354,7 +1361,7 @@ void SurfaceComposerClient::Transaction::registerSurfaceControlForCallback( auto& callbackInfo = mListenerCallbacks[TransactionCompletedListener::getIInstance()]; callbackInfo.surfaceControls.insert(sc); - TransactionCompletedListener::getInstance()->addSurfaceControlToCallbacks(callbackInfo, sc); + mTransactionCompletedListener->addSurfaceControlToCallbacks(callbackInfo, sc); } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition( @@ -1672,7 +1679,7 @@ std::shared_ptr<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffe std::shared_ptr<BufferData> bufferData = std::move(s->bufferData); - TransactionCompletedListener::getInstance()->removeReleaseBufferCallback( + mTransactionCompletedListener->removeReleaseBufferCallback( bufferData->generateReleaseCallbackId()); s->what &= ~layer_state_t::eBufferChanged; s->bufferData = nullptr; @@ -1695,7 +1702,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& optFrameNumber, - uint32_t producerId, ReleaseBufferCallback callback) { + uint32_t producerId, ReleaseBufferCallback callback, nsecs_t dequeueTime) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; @@ -1711,12 +1718,12 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe bufferData->frameNumber = frameNumber; bufferData->producerId = producerId; bufferData->flags |= BufferData::BufferDataChange::frameNumberChanged; + bufferData->dequeueTime = dequeueTime; if (fence) { bufferData->acquireFence = *fence; bufferData->flags |= BufferData::BufferDataChange::fenceChanged; } - bufferData->releaseBufferEndpoint = - IInterface::asBinder(TransactionCompletedListener::getIInstance()); + bufferData->releaseBufferEndpoint = IInterface::asBinder(mTransactionCompletedListener); setReleaseBufferCallback(bufferData.get(), callback); } @@ -1774,9 +1781,10 @@ void SurfaceComposerClient::Transaction::setReleaseBufferCallback(BufferData* bu return; } - bufferData->releaseBufferListener = TransactionCompletedListener::getIInstance(); - auto listener = TransactionCompletedListener::getInstance(); - listener->setReleaseBufferCallback(bufferData->generateReleaseCallbackId(), callback); + bufferData->releaseBufferListener = + static_cast<sp<ITransactionCompletedListener>>(mTransactionCompletedListener); + mTransactionCompletedListener->setReleaseBufferCallback(bufferData->generateReleaseCallbackId(), + callback); } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDataspace( @@ -1932,18 +1940,15 @@ SurfaceComposerClient::Transaction::setFrameRateSelectionPriority(const sp<Surfa SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addTransactionCallback( TransactionCompletedCallbackTakesContext callback, void* callbackContext, CallbackId::Type callbackType) { - auto listener = TransactionCompletedListener::getInstance(); - auto callbackWithContext = std::bind(callback, callbackContext, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); - const auto& surfaceControls = - mListenerCallbacks[TransactionCompletedListener::getIInstance()].surfaceControls; + const auto& surfaceControls = mListenerCallbacks[mTransactionCompletedListener].surfaceControls; CallbackId callbackId = - listener->addCallbackFunction(callbackWithContext, surfaceControls, callbackType); + mTransactionCompletedListener->addCallbackFunction(callbackWithContext, surfaceControls, + callbackType); - mListenerCallbacks[TransactionCompletedListener::getIInstance()].callbackIds.emplace( - callbackId); + mListenerCallbacks[mTransactionCompletedListener].callbackIds.emplace(callbackId); return *this; } @@ -2175,6 +2180,13 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAutoR SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedOverlay( const sp<SurfaceControl>& sc, bool isTrustedOverlay) { + return setTrustedOverlay(sc, + isTrustedOverlay ? gui::TrustedOverlay::ENABLED + : gui::TrustedOverlay::UNSET); +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedOverlay( + const sp<SurfaceControl>& sc, gui::TrustedOverlay trustedOverlay) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; @@ -2182,7 +2194,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrust } s->what |= layer_state_t::eTrustedOverlayChanged; - s->isTrustedOverlay = isTrustedOverlay; + s->trustedOverlay = trustedOverlay; return *this; } @@ -2250,23 +2262,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDropI return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::enableBorder( - const sp<SurfaceControl>& sc, bool shouldEnable, float width, const half4& color) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - - s->what |= layer_state_t::eRenderBorderChanged; - s->borderEnabled = shouldEnable; - s->borderWidth = width; - s->borderColor = color; - - registerSurfaceControlForCallback(sc); - return *this; -} - // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) { @@ -2350,8 +2345,9 @@ SurfaceComposerClient::Transaction::setTrustedPresentationCallback( const sp<SurfaceControl>& sc, TrustedPresentationCallback cb, const TrustedPresentationThresholds& thresholds, void* context, sp<SurfaceComposerClient::PresentationCallbackRAII>& outCallbackRef) { - auto listener = TransactionCompletedListener::getInstance(); - outCallbackRef = listener->addTrustedPresentationCallback(cb, sc->getLayerId(), context); + outCallbackRef = + mTransactionCompletedListener->addTrustedPresentationCallback(cb, sc->getLayerId(), + context); layer_state_t* s = getLayerState(sc); if (!s) { @@ -2368,8 +2364,7 @@ SurfaceComposerClient::Transaction::setTrustedPresentationCallback( SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::clearTrustedPresentationCallback(const sp<SurfaceControl>& sc) { - auto listener = TransactionCompletedListener::getInstance(); - listener->clearTrustedPresentationCallback(sc->getLayerId()); + mTransactionCompletedListener->clearTrustedPresentationCallback(sc->getLayerId()); layer_state_t* s = getLayerState(sc); if (!s) { @@ -3131,6 +3126,10 @@ status_t SurfaceComposerClient::removeWindowInfosListener( ->removeWindowInfosListener(windowInfosListener, ComposerServiceAIDL::getComposerService()); } + +void SurfaceComposerClient::notifyShutdown() { + ComposerServiceAIDL::getComposerService()->notifyShutdown(); +} // ---------------------------------------------------------------------------- status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs, diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp index 86bf0ee745..82d2554340 100644 --- a/libs/gui/WindowInfo.cpp +++ b/libs/gui/WindowInfo.cpp @@ -73,14 +73,6 @@ void WindowInfo::addTouchableRegion(const Rect& region) { touchableRegion.orSelf(region); } -bool WindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const { - return touchableRegion.contains(x, y); -} - -bool WindowInfo::frameContainsPoint(int32_t x, int32_t y) const { - return x >= frame.left && x < frame.right && y >= frame.top && y < frame.bottom; -} - bool WindowInfo::supportsSplitTouch() const { return !inputConfig.test(InputConfig::PREVENT_SPLITTING); } @@ -154,7 +146,7 @@ status_t WindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeInt32(ownerUid.val()) ?: parcel->writeUtf8AsUtf16(packageName) ?: parcel->writeInt32(inputConfig.get()) ?: - parcel->writeInt32(displayId) ?: + parcel->writeInt32(displayId.val()) ?: applicationInfo.writeToParcel(parcel) ?: parcel->write(touchableRegion) ?: parcel->writeBool(replaceTouchableRegionWithCrop) ?: @@ -183,7 +175,8 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) { } float dsdx, dtdx, tx, dtdy, dsdy, ty; - int32_t lpFlags, lpType, touchOcclusionModeInt, inputConfigInt, ownerPidInt, ownerUidInt; + int32_t lpFlags, lpType, touchOcclusionModeInt, inputConfigInt, ownerPidInt, ownerUidInt, + displayIdInt; sp<IBinder> touchableRegionCropHandleSp; // clang-format off @@ -206,7 +199,7 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->readInt32(&ownerUidInt) ?: parcel->readUtf8FromUtf16(&packageName) ?: parcel->readInt32(&inputConfigInt) ?: - parcel->readInt32(&displayId) ?: + parcel->readInt32(&displayIdInt) ?: applicationInfo.readFromParcel(parcel) ?: parcel->read(touchableRegion) ?: parcel->readBool(&replaceTouchableRegionWithCrop) ?: @@ -229,6 +222,7 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) { ownerPid = Pid{ownerPidInt}; ownerUid = Uid{static_cast<uid_t>(ownerUidInt)}; touchableRegionCropHandle = touchableRegionCropHandleSp; + displayId = ui::LogicalDisplayId{displayIdInt}; return OK; } diff --git a/libs/gui/aidl/Android.bp b/libs/gui/aidl/Android.bp new file mode 100644 index 0000000000..8ed08c2644 --- /dev/null +++ b/libs/gui/aidl/Android.bp @@ -0,0 +1,85 @@ +// Copyright 2024 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], + default_team: "trendy_team_android_core_graphics_stack", +} + +filegroup { + name: "libgui_unstructured_aidl_files", + srcs: [ + ":libgui_extra_unstructured_aidl_files", + + "android/gui/BitTube.aidl", + "android/gui/CaptureArgs.aidl", + "android/gui/DisplayCaptureArgs.aidl", + "android/gui/LayerCaptureArgs.aidl", + "android/gui/LayerMetadata.aidl", + "android/gui/ParcelableVsyncEventData.aidl", + "android/gui/ScreenCaptureResults.aidl", + ], +} + +aidl_library { + name: "libgui_unstructured_aidl", + hdrs: [":libgui_unstructured_aidl_files"], +} + +filegroup { + name: "libgui_interface_aidl_files", + srcs: [ + ":libgui_extra_aidl_files", + "**/*.aidl", + ], + exclude_srcs: [":libgui_unstructured_aidl_files"], +} + +aidl_interface { + name: "android.gui", + unstable: true, + srcs: [ + ":libgui_interface_aidl_files", + ], + include_dirs: [ + "frameworks/native/libs/gui", + "frameworks/native/libs/gui/aidl", + ], + headers: [ + "libgui_aidl_hdrs", + "libgui_extra_unstructured_aidl_hdrs", + ], + backend: { + rust: { + enabled: true, + additional_rustlibs: [ + "libgui_aidl_types_rs", + ], + }, + java: { + enabled: false, + }, + cpp: { + enabled: false, + }, + ndk: { + enabled: false, + }, + }, +} diff --git a/libs/gui/aidl/android/gui/BitTube.aidl b/libs/gui/aidl/android/gui/BitTube.aidl index 6b0595ec66..eb231c1c9f 100644 --- a/libs/gui/aidl/android/gui/BitTube.aidl +++ b/libs/gui/aidl/android/gui/BitTube.aidl @@ -16,4 +16,4 @@ package android.gui; -parcelable BitTube cpp_header "private/gui/BitTube.h"; +parcelable BitTube cpp_header "private/gui/BitTube.h" rust_type "gui_aidl_types_rs::BitTube"; diff --git a/libs/gui/aidl/android/gui/CaptureArgs.aidl b/libs/gui/aidl/android/gui/CaptureArgs.aidl index 920d94980a..9f198cae10 100644 --- a/libs/gui/aidl/android/gui/CaptureArgs.aidl +++ b/libs/gui/aidl/android/gui/CaptureArgs.aidl @@ -16,4 +16,4 @@ package android.gui; -parcelable CaptureArgs cpp_header "gui/DisplayCaptureArgs.h"; +parcelable CaptureArgs cpp_header "gui/DisplayCaptureArgs.h" rust_type "gui_aidl_types_rs::CaptureArgs"; diff --git a/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl b/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl index 2caa2b9f61..fc97dbf03d 100644 --- a/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl +++ b/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl @@ -16,4 +16,5 @@ package android.gui; -parcelable DisplayCaptureArgs cpp_header "gui/DisplayCaptureArgs.h"; +parcelable DisplayCaptureArgs cpp_header "gui/DisplayCaptureArgs.h" rust_type "gui_aidl_types_rs::DisplayCaptureArgs"; + diff --git a/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl b/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl index af138c7539..13962fee5d 100644 --- a/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl +++ b/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl @@ -42,6 +42,17 @@ parcelable DisplayModeSpecs { } /** + * Refers to the time after which the idle screen's refresh rate is to be reduced + */ + parcelable IdleScreenRefreshRateConfig { + + /** + * The timeout value in milli seconds + */ + int timeoutMillis; + } + + /** * Base mode ID. This is what system defaults to for all other settings, or * if the refresh rate range is not available. */ @@ -72,4 +83,13 @@ parcelable DisplayModeSpecs { * never smaller. */ RefreshRateRanges appRequestRanges; + + /** + * The config to represent the maximum time (in ms) for which the display can remain in an idle + * state before reducing the refresh rate to conserve power. + * Null value refers that the device is not configured to dynamically reduce the refresh rate + * based on external conditions. + * -1 refers to the current conditions requires no timeout + */ + @nullable IdleScreenRefreshRateConfig idleScreenRefreshRateConfig; } diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl index 51e01930d3..6d018ea7ef 100644 --- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -43,7 +43,6 @@ import android.gui.ITunnelModeEnabledListener; import android.gui.IWindowInfosListener; import android.gui.IWindowInfosPublisher; import android.gui.LayerCaptureArgs; -import android.gui.LayerDebugInfo; import android.gui.OverlayProperties; import android.gui.PullAtomData; import android.gui.ScreenCaptureResults; @@ -73,7 +72,7 @@ interface ISurfaceComposer { void bootFinished(); /** - * Create a display event connection + * Create a display event connection. * * layerHandle * Optional binder handle representing a Layer in SF to associate the new @@ -90,12 +89,14 @@ interface ISurfaceComposer { @nullable ISurfaceComposerClient createConnection(); /** - * Create a virtual display + * Create a virtual display. * * displayName - * The name of the virtual display - * secure - * Whether this virtual display is secure + * The name of the virtual display. + * isSecure + * Whether this virtual display is secure. + * uniqueId + * The unique ID for the display. * requestedRefreshRate * The refresh rate, frames per second, to request on the virtual display. * This is just a request, the actual rate may be adjusted to align well @@ -104,14 +105,14 @@ interface ISurfaceComposer { * * requires ACCESS_SURFACE_FLINGER permission. */ - @nullable IBinder createDisplay(@utf8InCpp String displayName, boolean secure, - float requestedRefreshRate); + @nullable IBinder createVirtualDisplay(@utf8InCpp String displayName, boolean isSecure, + @utf8InCpp String uniqueId, float requestedRefreshRate); /** - * Destroy a virtual display + * Destroy a virtual display. * requires ACCESS_SURFACE_FLINGER permission. */ - void destroyDisplay(IBinder display); + void destroyVirtualDisplay(IBinder displayToken); /** * Get stable IDs for connected physical displays. @@ -289,13 +290,6 @@ interface ISurfaceComposer { PullAtomData onPullAtom(int atomId); /** - * Gets the list of active layers in Z order for debugging purposes - * - * Requires the ACCESS_SURFACE_FLINGER permission. - */ - List<LayerDebugInfo> getLayerDebugInfo(); - - /** * Gets the composition preference of the default data space and default pixel format, * as well as the wide color gamut data space and wide color gamut pixel format. * If the wide color gamut data space is V0_SRGB, then it implies that the platform @@ -579,4 +573,11 @@ interface ISurfaceComposer { @nullable StalledTransactionInfo getStalledTransactionInfo(int pid); SchedulingPolicy getSchedulingPolicy(); + + /** + * Notifies the SurfaceFlinger that the ShutdownThread is running. When it is called, + * transaction traces will be captured and writted into a file. + * This method should not block the ShutdownThread therefore it's handled asynchronously. + */ + oneway void notifyShutdown(); } diff --git a/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl b/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl index f0def5019a..18d293f211 100644 --- a/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl +++ b/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl @@ -16,4 +16,4 @@ package android.gui; -parcelable LayerCaptureArgs cpp_header "gui/LayerCaptureArgs.h"; +parcelable LayerCaptureArgs cpp_header "gui/LayerCaptureArgs.h" rust_type "gui_aidl_types_rs::LayerCaptureArgs"; diff --git a/libs/gui/aidl/android/gui/LayerDebugInfo.aidl b/libs/gui/aidl/android/gui/LayerDebugInfo.aidl deleted file mode 100644 index faca980f3c..0000000000 --- a/libs/gui/aidl/android/gui/LayerDebugInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.gui; - -parcelable LayerDebugInfo cpp_header "gui/LayerDebugInfo.h"; diff --git a/libs/gui/aidl/android/gui/LayerMetadata.aidl b/libs/gui/aidl/android/gui/LayerMetadata.aidl index 1368ac512f..d8121bedb0 100644 --- a/libs/gui/aidl/android/gui/LayerMetadata.aidl +++ b/libs/gui/aidl/android/gui/LayerMetadata.aidl @@ -16,4 +16,4 @@ package android.gui; -parcelable LayerMetadata cpp_header "gui/LayerMetadata.h"; +parcelable LayerMetadata cpp_header "gui/LayerMetadata.h" rust_type "gui_aidl_types_rs::LayerMetadata"; diff --git a/libs/gui/aidl/android/gui/ParcelableVsyncEventData.aidl b/libs/gui/aidl/android/gui/ParcelableVsyncEventData.aidl index ba76671f8f..53f443aa59 100644 --- a/libs/gui/aidl/android/gui/ParcelableVsyncEventData.aidl +++ b/libs/gui/aidl/android/gui/ParcelableVsyncEventData.aidl @@ -16,4 +16,4 @@ package android.gui; -parcelable ParcelableVsyncEventData cpp_header "gui/VsyncEventData.h"; +parcelable ParcelableVsyncEventData cpp_header "gui/VsyncEventData.h" rust_type "gui_aidl_types_rs::VsyncEventData"; diff --git a/libs/gui/aidl/android/gui/ScreenCaptureResults.aidl b/libs/gui/aidl/android/gui/ScreenCaptureResults.aidl index 9908edd2ef..97a903515b 100644 --- a/libs/gui/aidl/android/gui/ScreenCaptureResults.aidl +++ b/libs/gui/aidl/android/gui/ScreenCaptureResults.aidl @@ -16,4 +16,4 @@ package android.gui; -parcelable ScreenCaptureResults cpp_header "gui/ScreenCaptureResults.h";
\ No newline at end of file +parcelable ScreenCaptureResults cpp_header "gui/ScreenCaptureResults.h" rust_type "gui_aidl_types_rs::ScreenCaptureResults";
\ No newline at end of file diff --git a/libs/gui/android/gui/DisplayInfo.aidl b/libs/gui/android/gui/DisplayInfo.aidl index 30c088525d..3b16724e7f 100644 --- a/libs/gui/android/gui/DisplayInfo.aidl +++ b/libs/gui/android/gui/DisplayInfo.aidl @@ -16,4 +16,4 @@ package android.gui; -parcelable DisplayInfo cpp_header "gui/DisplayInfo.h"; +parcelable DisplayInfo cpp_header "gui/DisplayInfo.h" rust_type "gui_aidl_types_rs::DisplayInfo"; diff --git a/libs/gui/android/gui/TrustedOverlay.aidl b/libs/gui/android/gui/TrustedOverlay.aidl new file mode 100644 index 0000000000..06fb5f0bd5 --- /dev/null +++ b/libs/gui/android/gui/TrustedOverlay.aidl @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2024, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + + +/** + * Trusted overlay state prevents layers from being considered as obscuring for + * input occlusion detection purposes. + * + * @hide + */ +@Backing(type="int") +enum TrustedOverlay { + /** + * The default, layer will inherit the state from its parents. If the parent state is also + * unset, the layer will be considered as untrusted. + */ + UNSET, + + /** + * Treats this layer and all its children as an untrusted overlay. This will override any + * state set by its parent layers. + */ + DISABLED, + + /** + * Treats this layer and all its children as a trusted overlay unless the child layer + * explicitly disables its trusted state. + */ + ENABLED +} diff --git a/libs/gui/android/gui/WindowInfo.aidl b/libs/gui/android/gui/WindowInfo.aidl index 2c85d155a8..b9d5ccf753 100644 --- a/libs/gui/android/gui/WindowInfo.aidl +++ b/libs/gui/android/gui/WindowInfo.aidl @@ -16,4 +16,4 @@ package android.gui; -parcelable WindowInfo cpp_header "gui/WindowInfo.h"; +parcelable WindowInfo cpp_header "gui/WindowInfo.h" rust_type "gui_aidl_types_rs::WindowInfo"; diff --git a/libs/gui/android/gui/WindowInfosUpdate.aidl b/libs/gui/android/gui/WindowInfosUpdate.aidl index 0c6109da8f..5c23e088ba 100644 --- a/libs/gui/android/gui/WindowInfosUpdate.aidl +++ b/libs/gui/android/gui/WindowInfosUpdate.aidl @@ -19,4 +19,4 @@ package android.gui; import android.gui.DisplayInfo; import android.gui.WindowInfo; -parcelable WindowInfosUpdate cpp_header "gui/WindowInfosUpdate.h"; +parcelable WindowInfosUpdate cpp_header "gui/WindowInfosUpdate.h" rust_type "gui_aidl_types_rs::WindowInfosUpdate"; diff --git a/libs/gui/include/gui/constants.h b/libs/gui/include/gui/AdditionalOptions.h index 8eab3783e9..87cb913675 100644 --- a/libs/gui/include/gui/constants.h +++ b/libs/gui/include/gui/AdditionalOptions.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright 2024 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. @@ -16,22 +16,17 @@ #pragma once -#include <stdint.h> +#include <string> -namespace android { +namespace android::gui { +// Additional options to pass to AHardwareBuffer_allocateWithOptions. +// See also allocator-v2's BufferDescriptorInfo.aidl +struct AdditionalOptions { + std::string name; + int64_t value; -/** - * Invalid value for display size. Used when display size isn't available. - */ -constexpr int32_t INVALID_DISPLAY_SIZE = 0; - -enum { - /* Used when an event is not associated with any display. - * Typically used for non-pointer events. */ - ADISPLAY_ID_NONE = -1, - - /* The default display id. */ - ADISPLAY_ID_DEFAULT = 0, + bool operator==(const AdditionalOptions& other) const { + return value == other.value && name == other.name; + } }; - -} // namespace android
\ No newline at end of file +} // namespace android::gui diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h index c16e370efc..d5dd7c897c 100644 --- a/libs/gui/include/gui/BufferQueueCore.h +++ b/libs/gui/include/gui/BufferQueueCore.h @@ -17,6 +17,9 @@ #ifndef ANDROID_GUI_BUFFERQUEUECORE_H #define ANDROID_GUI_BUFFERQUEUECORE_H +#include <com_android_graphics_libgui_flags.h> + +#include <gui/AdditionalOptions.h> #include <gui/BufferItem.h> #include <gui/BufferQueueDefs.h> #include <gui/BufferSlot.h> @@ -361,6 +364,14 @@ private: // This allows the consumer to acquire an additional buffer if that buffer is not droppable and // will eventually be released or acquired by the consumer. bool mAllowExtraAcquire = false; + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + // Additional options to pass when allocating GraphicBuffers. + // GenerationID changes when the options change, indicating reallocation is required + uint32_t mAdditionalOptionsGenerationId = 0; + std::vector<gui::AdditionalOptions> mAdditionalOptions; +#endif + }; // class BufferQueueCore } // namespace android diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h index de47483dca..37a960708c 100644 --- a/libs/gui/include/gui/BufferQueueProducer.h +++ b/libs/gui/include/gui/BufferQueueProducer.h @@ -17,6 +17,7 @@ #ifndef ANDROID_GUI_BUFFERQUEUEPRODUCER_H #define ANDROID_GUI_BUFFERQUEUEPRODUCER_H +#include <gui/AdditionalOptions.h> #include <gui/BufferQueueDefs.h> #include <gui/IGraphicBufferProducer.h> @@ -208,6 +209,10 @@ public: int8_t changeFrameRateStrategy) override; #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + status_t setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options) override; +#endif + protected: // see IGraphicsBufferProducer::setMaxDequeuedBufferCount, but with the ability to retrieve the // total maximum buffer count for the buffer queue (dequeued AND acquired) diff --git a/libs/gui/include/gui/BufferSlot.h b/libs/gui/include/gui/BufferSlot.h index 57704b1d09..5b32710135 100644 --- a/libs/gui/include/gui/BufferSlot.h +++ b/libs/gui/include/gui/BufferSlot.h @@ -17,6 +17,8 @@ #ifndef ANDROID_GUI_BUFFERSLOT_H #define ANDROID_GUI_BUFFERSLOT_H +#include <com_android_graphics_libgui_flags.h> + #include <ui/Fence.h> #include <ui/GraphicBuffer.h> @@ -230,6 +232,11 @@ struct BufferSlot { // producer. If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when // dequeued to prevent the producer from using a stale cached buffer. bool mNeedsReallocation; + +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + // The generation id of the additional options that mGraphicBuffer was allocated with + uint32_t mAdditionalOptionsGenerationId = 0; +#endif }; } // namespace android diff --git a/libs/gui/include/gui/Choreographer.h b/libs/gui/include/gui/Choreographer.h index 55a7aa7ddc..2e5aa4a893 100644 --- a/libs/gui/include/gui/Choreographer.h +++ b/libs/gui/include/gui/Choreographer.h @@ -28,12 +28,18 @@ namespace android { using gui::VsyncEventData; +enum CallbackType : int8_t { + CALLBACK_INPUT, + CALLBACK_ANIMATION, +}; + struct FrameCallback { AChoreographer_frameCallback callback; AChoreographer_frameCallback64 callback64; AChoreographer_vsyncCallback vsyncCallback; void* data; nsecs_t dueTime; + CallbackType callbackType; inline bool operator<(const FrameCallback& rhs) const { // Note that this is intentionally flipped because we want callbacks due sooner to be at @@ -78,7 +84,7 @@ public: void postFrameCallbackDelayed(AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, AChoreographer_vsyncCallback vsyncCallback, void* data, - nsecs_t delay); + nsecs_t delay, CallbackType callbackType); void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data) EXCLUDES(gChoreographers.lock); void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data); @@ -103,12 +109,15 @@ public: virtual ~Choreographer() override EXCLUDES(gChoreographers.lock); int64_t getFrameInterval() const; bool inCallback() const; + const sp<Looper> getLooper(); private: Choreographer(const Choreographer&) = delete; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, VsyncEventData vsyncEventData) override; + void dispatchCallbacks(const std::vector<FrameCallback>&, VsyncEventData vsyncEventData, + nsecs_t timestamp); void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; void dispatchHotplugConnectionError(nsecs_t timestamp, int32_t connectionError) override; void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index 8c1103bfc2..4dbf9e1929 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -119,6 +119,7 @@ public: HdcpLevelsChange hdcpLevelsChange; }; }; + static_assert(sizeof(Event) == 216); public: /* diff --git a/libs/gui/include/gui/DisplayInfo.h b/libs/gui/include/gui/DisplayInfo.h index 42b62c755c..7094658379 100644 --- a/libs/gui/include/gui/DisplayInfo.h +++ b/libs/gui/include/gui/DisplayInfo.h @@ -18,7 +18,7 @@ #include <binder/Parcel.h> #include <binder/Parcelable.h> -#include <gui/constants.h> +#include <ui/LogicalDisplayId.h> #include <ui/Transform.h> namespace android::gui { @@ -29,7 +29,7 @@ namespace android::gui { * This should only be used by InputFlinger to support raw coordinates in logical display space. */ struct DisplayInfo : public Parcelable { - int32_t displayId = ADISPLAY_ID_NONE; + ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID; // Logical display dimensions. int32_t logicalWidth = 0; diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 7639e709ca..8fca9460aa 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -31,6 +31,7 @@ #include <ui/Rect.h> #include <ui/Region.h> +#include <gui/AdditionalOptions.h> #include <gui/FrameTimestamps.h> #include <gui/HdrMetadata.h> @@ -684,6 +685,10 @@ public: int8_t changeFrameRateStrategy); #endif +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + virtual status_t setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options); +#endif + struct RequestBufferOutput : public Flattenable<RequestBufferOutput> { RequestBufferOutput() = default; diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index a836f4642a..eb4a802c17 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -74,7 +74,6 @@ namespace gui { struct DisplayCaptureArgs; struct LayerCaptureArgs; -class LayerDebugInfo; } // namespace gui @@ -131,8 +130,8 @@ public: CREATE_CONNECTION, // Deprecated. Autogenerated by .aidl now. GET_STATIC_DISPLAY_INFO, // Deprecated. Autogenerated by .aidl now. CREATE_DISPLAY_EVENT_CONNECTION, // Deprecated. Autogenerated by .aidl now. - CREATE_DISPLAY, // Deprecated. Autogenerated by .aidl now. - DESTROY_DISPLAY, // Deprecated. Autogenerated by .aidl now. + CREATE_VIRTUAL_DISPLAY, // Deprecated. Autogenerated by .aidl now. + DESTROY_VIRTUAL_DISPLAY, // Deprecated. Autogenerated by .aidl now. GET_PHYSICAL_DISPLAY_TOKEN, // Deprecated. Autogenerated by .aidl now. SET_TRANSACTION_STATE, AUTHENTICATE_SURFACE, // Deprecated. Autogenerated by .aidl now. diff --git a/libs/gui/include/gui/InputTransferToken.h b/libs/gui/include/gui/InputTransferToken.h new file mode 100644 index 0000000000..6530b5069a --- /dev/null +++ b/libs/gui/include/gui/InputTransferToken.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 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 <binder/Binder.h> +#include <binder/IBinder.h> +#include <binder/Parcel.h> +#include <private/gui/ParcelUtils.h> +#include <utils/Errors.h> + +namespace android { +struct InputTransferToken : public RefBase, Parcelable { +public: + InputTransferToken() { mToken = new BBinder(); } + + InputTransferToken(const sp<IBinder>& token) { mToken = token; } + + status_t writeToParcel(Parcel* parcel) const override { + SAFE_PARCEL(parcel->writeStrongBinder, mToken); + return NO_ERROR; + } + + status_t readFromParcel(const Parcel* parcel) { + SAFE_PARCEL(parcel->readStrongBinder, &mToken); + return NO_ERROR; + }; + + 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
\ No newline at end of file diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h deleted file mode 100644 index dbb80e583c..0000000000 --- a/libs/gui/include/gui/LayerDebugInfo.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2017 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 <binder/Parcelable.h> - -#include <ui/PixelFormat.h> -#include <ui/Region.h> -#include <ui/StretchEffect.h> - -#include <string> -#include <math/vec4.h> - -namespace android::gui { - -/* Class for transporting debug info from SurfaceFlinger to authorized - * recipients. The class is intended to be a data container. There are - * no getters or setters. - */ -class LayerDebugInfo : public Parcelable { -public: - LayerDebugInfo() = default; - LayerDebugInfo(const LayerDebugInfo&) = default; - virtual ~LayerDebugInfo() = default; - - virtual status_t writeToParcel(Parcel* parcel) const; - virtual status_t readFromParcel(const Parcel* parcel); - - std::string mName = std::string("NOT FILLED"); - std::string mParentName = std::string("NOT FILLED"); - std::string mType = std::string("NOT FILLED"); - Region mTransparentRegion = Region::INVALID_REGION; - Region mVisibleRegion = Region::INVALID_REGION; - Region mSurfaceDamageRegion = Region::INVALID_REGION; - uint32_t mLayerStack = 0; - float mX = 0.f; - float mY = 0.f; - uint32_t mZ = 0 ; - int32_t mWidth = -1; - int32_t mHeight = -1; - android::Rect mCrop = android::Rect::INVALID_RECT; - half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf); - uint32_t mFlags = 0; - PixelFormat mPixelFormat = PIXEL_FORMAT_NONE; - android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN; - // Row-major transform matrix (SurfaceControl::setMatrix()) - float mMatrix[2][2] = {{0.f, 0.f}, {0.f, 0.f}}; - int32_t mActiveBufferWidth = -1; - int32_t mActiveBufferHeight = -1; - int32_t mActiveBufferStride = 0; - PixelFormat mActiveBufferFormat = PIXEL_FORMAT_NONE; - int32_t mNumQueuedFrames = -1; - bool mIsOpaque = false; - bool mContentDirty = false; - StretchEffect mStretchEffect = {}; -}; - -std::string to_string(const LayerDebugInfo& info); - -} // namespace android::gui diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 0fedea7b9e..5f2f8dc013 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -30,6 +30,7 @@ #include <android/gui/DropInputMode.h> #include <android/gui/FocusRequest.h> +#include <android/gui/TrustedOverlay.h> #include <ftl/flags.h> #include <gui/DisplayCaptureArgs.h> @@ -127,6 +128,8 @@ public: client_cache_t cachedBuffer; + nsecs_t dequeueTime; + // Generates the release callback id based on the buffer id and frame number. // This is used as an identifier when release callbacks are invoked. ReleaseCallbackId generateReleaseCallbackId() const; @@ -179,7 +182,6 @@ struct layer_state_t { eCachingHintChanged = 0x00000200, eDimmingEnabledChanged = 0x00000400, eShadowRadiusChanged = 0x00000800, - eRenderBorderChanged = 0x00001000, eBufferCropChanged = 0x00002000, eRelativeLayerChanged = 0x00004000, eReparent = 0x00008000, @@ -258,8 +260,8 @@ struct layer_state_t { layer_state_t::eBlurRegionsChanged | layer_state_t::eColorChanged | layer_state_t::eColorSpaceAgnosticChanged | layer_state_t::eColorTransformChanged | layer_state_t::eCornerRadiusChanged | layer_state_t::eDimmingEnabledChanged | - layer_state_t::eHdrMetadataChanged | layer_state_t::eRenderBorderChanged | - layer_state_t::eShadowRadiusChanged | layer_state_t::eStretchChanged; + layer_state_t::eHdrMetadataChanged | layer_state_t::eShadowRadiusChanged | + layer_state_t::eStretchChanged; // Changes which invalidates the layer's visible region in CE. static constexpr uint64_t CONTENT_DIRTY = layer_state_t::CONTENT_CHANGES | @@ -276,9 +278,9 @@ struct layer_state_t { layer_state_t::eFrameRateSelectionPriority | layer_state_t::eFixedTransformHintChanged; // Changes affecting data sent to input. - static constexpr uint64_t INPUT_CHANGES = layer_state_t::eInputInfoChanged | - layer_state_t::eDropInputModeChanged | layer_state_t::eTrustedOverlayChanged | - layer_state_t::eLayerStackChanged; + static constexpr uint64_t INPUT_CHANGES = layer_state_t::eAlphaChanged | + layer_state_t::eInputInfoChanged | layer_state_t::eDropInputModeChanged | + layer_state_t::eTrustedOverlayChanged | layer_state_t::eLayerStackChanged; // Changes that affect the visible region on a display. static constexpr uint64_t VISIBLE_REGION_CHANGES = layer_state_t::GEOMETRY_CHANGES | @@ -386,12 +388,7 @@ struct layer_state_t { // An inherited state that indicates that this surface control and its children // should be trusted for input occlusion detection purposes - bool isTrustedOverlay; - - // Flag to indicate if border needs to be enabled on the layer - bool borderEnabled; - float borderWidth; - half4 borderColor; + gui::TrustedOverlay trustedOverlay; // Stretch effect to be applied to this layer StretchEffect stretchEffect; diff --git a/libs/gui/include/gui/LayerStatePermissions.h b/libs/gui/include/gui/LayerStatePermissions.h index a90f30c621..b6588a2a82 100644 --- a/libs/gui/include/gui/LayerStatePermissions.h +++ b/libs/gui/include/gui/LayerStatePermissions.h @@ -15,15 +15,14 @@ */ #include <stdint.h> -#include <string> -#include <unordered_map> - +#include <utils/String16.h> +#include <vector> namespace android { class LayerStatePermissions { public: static uint32_t getTransactionPermissions(int pid, int uid); private: - static std::unordered_map<std::string, int> mPermissionMap; + static std::vector<std::pair<String16, int>> mPermissionMap; }; } // namespace android
\ No newline at end of file diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 39a59e42aa..bdcaaf2866 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -215,6 +215,16 @@ public: int8_t changeFrameRateStrategy); virtual status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& info); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE) + /** + * Set additional options to be passed when allocating a buffer. Only valid if IAllocator-V2 + * or newer is available, otherwise will return INVALID_OPERATION. Only allowed to be called + * after connect and options are cleared when disconnect happens. Returns NO_INIT if not + * connected + */ + status_t setAdditionalOptions(const std::vector<gui::AdditionalOptions>& options); +#endif + protected: virtual ~Surface(); @@ -302,6 +312,7 @@ private: int dispatchGetLastQueuedBuffer(va_list args); int dispatchGetLastQueuedBuffer2(va_list args); int dispatchSetFrameTimelineInfo(va_list args); + int dispatchSetAdditionalOptions(va_list args); std::mutex mNameMutex; std::string mName; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 288882695a..0862e03c44 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -18,6 +18,7 @@ #include <stdint.h> #include <sys/types.h> + #include <set> #include <thread> #include <unordered_map> @@ -374,17 +375,15 @@ public: sp<SurfaceControl> mirrorDisplay(DisplayId displayId); - //! Create a virtual display - static sp<IBinder> createDisplay(const String8& displayName, bool secure, - float requestedRefereshRate = 0); + static const std::string kEmpty; + static sp<IBinder> createVirtualDisplay(const std::string& displayName, bool isSecure, + const std::string& uniqueId = kEmpty, + float requestedRefreshRate = 0); - //! Destroy a virtual display - static void destroyDisplay(const sp<IBinder>& display); + static status_t destroyVirtualDisplay(const sp<IBinder>& displayToken); - //! Get stable IDs for connected physical displays static std::vector<PhysicalDisplayId> getPhysicalDisplayIds(); - //! Get token for a physical display given its stable ID static sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId); // Returns StalledTransactionInfo if a transaction from the provided pid has not been applied @@ -431,6 +430,8 @@ public: 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; protected: std::unordered_map<sp<IBinder>, ComposerState, IBinderHash> mComposerStates; @@ -567,7 +568,8 @@ public: Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const std::optional<sp<Fence>>& fence = std::nullopt, const std::optional<uint64_t>& frameNumber = std::nullopt, - uint32_t producerId = 0, ReleaseBufferCallback callback = nullptr); + uint32_t producerId = 0, ReleaseBufferCallback callback = nullptr, + nsecs_t dequeueTime = -1); Transaction& unsetBuffer(const sp<SurfaceControl>& sc); std::shared_ptr<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc); @@ -718,6 +720,8 @@ public: // Sets that this surface control and its children are trusted overlays for input Transaction& setTrustedOverlay(const sp<SurfaceControl>& sc, bool isTrustedOverlay); + Transaction& setTrustedOverlay(const sp<SurfaceControl>& sc, + gui::TrustedOverlay trustedOverlay); // Queues up transactions using this token in SurfaceFlinger. By default, all transactions // from a client are placed on the same queue. This can be used to prevent multiple @@ -744,9 +748,6 @@ public: const Rect& destinationFrame); Transaction& setDropInputMode(const sp<SurfaceControl>& sc, gui::DropInputMode mode); - Transaction& enableBorder(const sp<SurfaceControl>& sc, bool shouldEnable, float width, - const half4& color); - status_t setDisplaySurface(const sp<IBinder>& token, const sp<IGraphicBufferProducer>& bufferProducer); @@ -826,6 +827,8 @@ public: nullptr); status_t removeWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener); + static void notifyShutdown(); + protected: ReleaseCallbackThread mReleaseCallbackThread; diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h index 32d60be612..eb3be5588a 100644 --- a/libs/gui/include/gui/WindowInfo.h +++ b/libs/gui/include/gui/WindowInfo.h @@ -23,7 +23,7 @@ #include <ftl/flags.h> #include <ftl/mixins.h> #include <gui/PidUid.h> -#include <gui/constants.h> +#include <ui/LogicalDisplayId.h> #include <ui/Rect.h> #include <ui/Region.h> #include <ui/Size.h> @@ -178,6 +178,8 @@ struct WindowInfo : public Parcelable { static_cast<uint32_t>(os::InputConfig::CLONE), GLOBAL_STYLUS_BLOCKS_TOUCH = static_cast<uint32_t>(os::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH), + SENSITIVE_FOR_PRIVACY = + static_cast<uint32_t>(os::InputConfig::SENSITIVE_FOR_PRIVACY), // clang-format on }; @@ -232,7 +234,7 @@ struct WindowInfo : public Parcelable { Uid ownerUid = Uid::INVALID; std::string packageName; ftl::Flags<InputConfig> inputConfig; - int32_t displayId = ADISPLAY_ID_NONE; + ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID; InputApplicationInfo applicationInfo; bool replaceTouchableRegionWithCrop = false; wp<IBinder> touchableRegionCropHandle; @@ -254,10 +256,6 @@ struct WindowInfo : public Parcelable { void addTouchableRegion(const Rect& region); - bool touchableRegionContainsPoint(int32_t x, int32_t y) const; - - bool frameContainsPoint(int32_t x, int32_t y) const; - bool supportsSplitTouch() const; bool isSpy() const; diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig index 78fc59072e..87cef087db 100644 --- a/libs/gui/libgui_flags.aconfig +++ b/libs/gui/libgui_flags.aconfig @@ -7,7 +7,7 @@ flag { description: "This flag controls plumbing setFrameRate thru BufferQueue" bug: "281695725" is_fixed_read_only: true -} +} # bq_setframerate flag { name: "bq_consumer_attach_callback" @@ -23,4 +23,23 @@ flag { description: "Controls a fence fixup for timestamp apis" bug: "310927247" is_fixed_read_only: true -} +} # frametimestamps_previousrelease + +flag { + name: "bq_extendedallocate" + namespace: "core_graphics" + description: "Add BQ support for allocate with extended options" + bug: "268382490" + is_fixed_read_only: true +} # bq_extendedallocate + +flag { + name: "trace_frame_rate_override" + namespace: "core_graphics" + description: "Trace FrameRateOverride fps" + bug: "347314033" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} # trace_frame_rate_override diff --git a/libs/gui/rust/aidl_types/Android.bp b/libs/gui/rust/aidl_types/Android.bp new file mode 100644 index 0000000000..794f69e1e6 --- /dev/null +++ b/libs/gui/rust/aidl_types/Android.bp @@ -0,0 +1,23 @@ +rust_defaults { + name: "libgui_aidl_types_defaults", + srcs: ["src/lib.rs"], + rustlibs: [ + "libbinder_rs", + ], +} + +rust_library { + name: "libgui_aidl_types_rs", + crate_name: "gui_aidl_types_rs", + defaults: ["libgui_aidl_types_defaults"], + + // Currently necessary for host builds + // TODO(b/31559095): bionic on host should define this + target: { + darwin: { + enabled: false, + }, + }, + min_sdk_version: "VanillaIceCream", + vendor_available: true, +} diff --git a/libs/gui/rust/aidl_types/src/lib.rs b/libs/gui/rust/aidl_types/src/lib.rs new file mode 100644 index 0000000000..fead018bbf --- /dev/null +++ b/libs/gui/rust/aidl_types/src/lib.rs @@ -0,0 +1,55 @@ +// Copyright (C) 2024 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. + +//! Rust wrapper for libgui AIDL types. + +use binder::{ + binder_impl::{BorrowedParcel, UnstructuredParcelable}, + impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable, + StatusCode, +}; + +macro_rules! stub_unstructured_parcelable { + ($name:ident) => { + /// Unimplemented stub parcelable. + #[derive(Debug, Default)] + pub struct $name(()); + + impl UnstructuredParcelable for $name { + fn write_to_parcel(&self, _parcel: &mut BorrowedParcel) -> Result<(), StatusCode> { + todo!() + } + + fn from_parcel(_parcel: &BorrowedParcel) -> Result<Self, StatusCode> { + todo!() + } + } + + impl_deserialize_for_unstructured_parcelable!($name); + impl_serialize_for_unstructured_parcelable!($name); + }; +} + +stub_unstructured_parcelable!(BitTube); +stub_unstructured_parcelable!(CaptureArgs); +stub_unstructured_parcelable!(DisplayCaptureArgs); +stub_unstructured_parcelable!(DisplayInfo); +stub_unstructured_parcelable!(LayerCaptureArgs); +stub_unstructured_parcelable!(LayerDebugInfo); +stub_unstructured_parcelable!(LayerMetadata); +stub_unstructured_parcelable!(ParcelableVsyncEventData); +stub_unstructured_parcelable!(ScreenCaptureResults); +stub_unstructured_parcelable!(VsyncEventData); +stub_unstructured_parcelable!(WindowInfo); +stub_unstructured_parcelable!(WindowInfosUpdate); diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index e606b9941e..ea8acbbb72 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -21,8 +21,10 @@ cc_test { cppflags: [ "-Wall", "-Werror", - "-Wno-extra", + "-Wextra", + "-Wthread-safety", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_SETFRAMERATE=true", + "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_EXTENDEDALLOCATE=true", ], srcs: [ @@ -30,6 +32,7 @@ cc_test { "BLASTBufferQueue_test.cpp", "BufferItemConsumer_test.cpp", "BufferQueue_test.cpp", + "Choreographer_test.cpp", "CompositorTiming_test.cpp", "CpuConsumer_test.cpp", "EndToEndNativeInputTest.cpp", @@ -61,6 +64,7 @@ cc_test { "libSurfaceFlingerProp", "libGLESv1_CM", "libinput", + "libnativedisplay", ], static_libs: [ diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index ea7078dd05..946ff058cf 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -18,6 +18,7 @@ #include <gui/BLASTBufferQueue.h> +#include <android-base/thread_annotations.h> #include <android/hardware/graphics/common/1.2/types.h> #include <gui/AidlStatusUtil.h> #include <gui/BufferQueueCore.h> @@ -61,7 +62,8 @@ public: } void waitOnNumberReleased(int32_t expectedNumReleased) { - std::unique_lock<std::mutex> lock(mMutex); + std::unique_lock lock{mMutex}; + base::ScopedLockAssertion assumeLocked(mMutex); while (mNumReleased < expectedNumReleased) { ASSERT_NE(mReleaseCallback.wait_for(lock, std::chrono::seconds(3)), std::cv_status::timeout) @@ -134,11 +136,18 @@ public: void clearSyncTransaction() { mBlastBufferQueueAdapter->clearSyncTransaction(); } - int getWidth() { return mBlastBufferQueueAdapter->mSize.width; } + int getWidth() { + std::scoped_lock lock(mBlastBufferQueueAdapter->mMutex); + return mBlastBufferQueueAdapter->mSize.width; + } - int getHeight() { return mBlastBufferQueueAdapter->mSize.height; } + int getHeight() { + std::scoped_lock lock(mBlastBufferQueueAdapter->mMutex); + return mBlastBufferQueueAdapter->mSize.height; + } std::function<void(Transaction*)> getTransactionReadyCallback() { + std::scoped_lock lock(mBlastBufferQueueAdapter->mMutex); return mBlastBufferQueueAdapter->mTransactionReadyCallback; } @@ -147,6 +156,7 @@ public: } const sp<SurfaceControl> getSurfaceControl() { + std::scoped_lock lock(mBlastBufferQueueAdapter->mMutex); return mBlastBufferQueueAdapter->mSurfaceControl; } @@ -156,6 +166,7 @@ public: void waitForCallbacks() { std::unique_lock lock{mBlastBufferQueueAdapter->mMutex}; + base::ScopedLockAssertion assumeLocked(mBlastBufferQueueAdapter->mMutex); // Wait until all but one of the submitted buffers have been released. while (mBlastBufferQueueAdapter->mSubmitted.size() > 1) { mBlastBufferQueueAdapter->mCallbackCV.wait(lock); @@ -166,8 +177,8 @@ public: mBlastBufferQueueAdapter->waitForCallback(frameNumber); } - void validateNumFramesSubmitted(int64_t numFramesSubmitted) { - std::unique_lock lock{mBlastBufferQueueAdapter->mMutex}; + void validateNumFramesSubmitted(size_t numFramesSubmitted) { + std::scoped_lock lock{mBlastBufferQueueAdapter->mMutex}; ASSERT_EQ(numFramesSubmitted, mBlastBufferQueueAdapter->mSubmitted.size()); } @@ -201,7 +212,7 @@ protected: mDisplayWidth = resolution.getWidth(); mDisplayHeight = resolution.getHeight(); ALOGD("Display: %dx%d orientation:%d", mDisplayWidth, mDisplayHeight, - displayState.orientation); + static_cast<int32_t>(displayState.orientation)); mRootSurfaceControl = mClient->createSurface(String8("RootTestSurface"), mDisplayWidth, mDisplayHeight, PIXEL_FORMAT_RGBA_8888, @@ -240,8 +251,8 @@ protected: void fillBuffer(uint32_t* bufData, Rect rect, uint32_t stride, uint8_t r, uint8_t g, uint8_t b) { - for (uint32_t row = rect.top; row < rect.bottom; row++) { - for (uint32_t col = rect.left; col < rect.right; col++) { + for (int32_t row = rect.top; row < rect.bottom; row++) { + for (int32_t col = rect.left; col < rect.right; col++) { uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col); *pixel = r; *(pixel + 1) = g; @@ -271,16 +282,16 @@ protected: bool outsideRegion = false) { sp<GraphicBuffer>& captureBuf = mCaptureResults.buffer; const auto epsilon = 3; - const auto width = captureBuf->getWidth(); - const auto height = captureBuf->getHeight(); + const int32_t width = static_cast<int32_t>(captureBuf->getWidth()); + const int32_t height = static_cast<int32_t>(captureBuf->getHeight()); const auto stride = captureBuf->getStride(); uint32_t* bufData; captureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN), reinterpret_cast<void**>(&bufData)); - for (uint32_t row = 0; row < height; row++) { - for (uint32_t col = 0; col < width; col++) { + for (int32_t row = 0; row < height; row++) { + for (int32_t col = 0; col < width; col++) { uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col); ASSERT_NE(nullptr, pixel); bool inRegion; @@ -352,8 +363,8 @@ TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) { // create BLASTBufferQueue adapter associated with this surface BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl()); - ASSERT_EQ(mDisplayWidth, adapter.getWidth()); - ASSERT_EQ(mDisplayHeight, adapter.getHeight()); + ASSERT_EQ(static_cast<int32_t>(mDisplayWidth), adapter.getWidth()); + ASSERT_EQ(static_cast<int32_t>(mDisplayHeight), adapter.getHeight()); ASSERT_EQ(nullptr, adapter.getTransactionReadyCallback()); } @@ -371,10 +382,10 @@ TEST_F(BLASTBufferQueueTest, Update) { int32_t width; igbProducer->query(NATIVE_WINDOW_WIDTH, &width); - ASSERT_EQ(mDisplayWidth / 2, width); + ASSERT_EQ(static_cast<int32_t>(mDisplayWidth) / 2, width); int32_t height; igbProducer->query(NATIVE_WINDOW_HEIGHT, &height); - ASSERT_EQ(mDisplayHeight / 2, height); + ASSERT_EQ(static_cast<int32_t>(mDisplayHeight) / 2, height); } TEST_F(BLASTBufferQueueTest, SyncNextTransaction) { @@ -476,7 +487,7 @@ TEST_F(BLASTBufferQueueTest, TripleBuffering) { ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf)); allocated.push_back({slot, fence}); } - for (int i = 0; i < allocated.size(); i++) { + for (size_t i = 0; i < allocated.size(); i++) { igbProducer->cancelBuffer(allocated[i].first, allocated[i].second); } @@ -1313,14 +1324,14 @@ TEST_F(BLASTBufferQueueTest, TransformHint) { // Before connecting to the surface, we do not get a valid transform hint int transformHint; surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint); - ASSERT_EQ(ui::Transform::ROT_0, transformHint); + ASSERT_EQ(ui::Transform::ROT_0, static_cast<ui::Transform::RotationFlags>(transformHint)); ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, new TestProducerListener(igbProducer))); // After connecting to the surface, we should get the correct hint. surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint); - ASSERT_EQ(ui::Transform::ROT_90, transformHint); + ASSERT_EQ(ui::Transform::ROT_90, static_cast<ui::Transform::RotationFlags>(transformHint)); ANativeWindow_Buffer buffer; surface->lock(&buffer, nullptr /* inOutDirtyBounds */); @@ -1331,13 +1342,13 @@ TEST_F(BLASTBufferQueueTest, TransformHint) { // The hint does not change and matches the value used when dequeueing the buffer. surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint); - ASSERT_EQ(ui::Transform::ROT_90, transformHint); + ASSERT_EQ(ui::Transform::ROT_90, static_cast<ui::Transform::RotationFlags>(transformHint)); surface->unlockAndPost(); // After queuing the buffer, we get the updated transform hint surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint); - ASSERT_EQ(ui::Transform::ROT_0, transformHint); + ASSERT_EQ(ui::Transform::ROT_0, static_cast<ui::Transform::RotationFlags>(transformHint)); adapter.waitForCallbacks(); } @@ -1573,7 +1584,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { FrameEvents* events = nullptr; events = history.getFrame(1); ASSERT_NE(nullptr, events); - ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(1u, events->frameNumber); ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeA); @@ -1591,7 +1602,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { ASSERT_NE(nullptr, events); // frame number, requestedPresentTime, and postTime should not have changed - ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(1u, events->frameNumber); ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeA); @@ -1606,7 +1617,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { // we should also have gotten the initial values for the next frame events = history.getFrame(2); ASSERT_NE(nullptr, events); - ASSERT_EQ(2, events->frameNumber); + ASSERT_EQ(2u, events->frameNumber); ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeB); @@ -1622,7 +1633,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { // Check the first frame... events = history.getFrame(1); ASSERT_NE(nullptr, events); - ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(1u, events->frameNumber); ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeA); ASSERT_GE(events->latchTime, postedTimeA); @@ -1636,7 +1647,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { // ...and the second events = history.getFrame(2); ASSERT_NE(nullptr, events); - ASSERT_EQ(2, events->frameNumber); + ASSERT_EQ(2u, events->frameNumber); ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeB); ASSERT_GE(events->latchTime, postedTimeB); @@ -1650,7 +1661,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { // ...and finally the third! events = history.getFrame(3); ASSERT_NE(nullptr, events); - ASSERT_EQ(3, events->frameNumber); + ASSERT_EQ(3u, events->frameNumber); ASSERT_EQ(requestedPresentTimeC, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeC); @@ -1677,7 +1688,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) { FrameEvents* events = nullptr; events = history.getFrame(1); ASSERT_NE(nullptr, events); - ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(1u, events->frameNumber); ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeA); @@ -1692,7 +1703,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) { ASSERT_NE(nullptr, events); // frame number, requestedPresentTime, and postTime should not have changed - ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(1u, events->frameNumber); ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeA); @@ -1715,7 +1726,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) { adapter.waitForCallback(3); // frame number, requestedPresentTime, and postTime should not have changed - ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(1u, events->frameNumber); ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeA); @@ -1729,7 +1740,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) { // we should also have gotten values for the presented frame events = history.getFrame(2); ASSERT_NE(nullptr, events); - ASSERT_EQ(2, events->frameNumber); + ASSERT_EQ(2u, events->frameNumber); ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeB); ASSERT_GE(events->latchTime, postedTimeB); @@ -1751,7 +1762,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) { // frame number, requestedPresentTime, and postTime should not have changed events = history.getFrame(1); - ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(1u, events->frameNumber); ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeA); @@ -1765,7 +1776,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) { // we should also have gotten values for the presented frame events = history.getFrame(2); ASSERT_NE(nullptr, events); - ASSERT_EQ(2, events->frameNumber); + ASSERT_EQ(2u, events->frameNumber); ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeB); ASSERT_GE(events->latchTime, postedTimeB); diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index be6c7d6a5b..590e2c87c9 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -28,6 +28,8 @@ #include <ui/GraphicBuffer.h> +#include <android-base/properties.h> + #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/ProcessState.h> @@ -47,6 +49,10 @@ using namespace std::chrono_literals; +static bool IsCuttlefish() { + return ::android::base::GetProperty("ro.product.board", "") == "cutf"; +} + namespace android { using namespace com::android::graphics::libgui; @@ -119,8 +125,7 @@ TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) { } sp<IServiceManager> serviceManager = defaultServiceManager(); - sp<IBinder> binderProducer = - serviceManager->getService(PRODUCER_NAME); + sp<IBinder> binderProducer = serviceManager->waitForService(PRODUCER_NAME); mProducer = interface_cast<IGraphicBufferProducer>(binderProducer); EXPECT_TRUE(mProducer != nullptr); sp<IBinder> binderConsumer = @@ -1114,7 +1119,7 @@ TEST_F(BufferQueueTest, TestDiscardFreeBuffers) { // Check onBuffersDiscarded is called with correct slots auto buffersDiscarded = pl->getDiscardedSlots(); - ASSERT_EQ(buffersDiscarded.size(), 1); + ASSERT_EQ(buffersDiscarded.size(), 1u); ASSERT_EQ(buffersDiscarded[0], releasedSlot); // Check no free buffers in dump @@ -1239,7 +1244,7 @@ TEST_F(BufferQueueTest, TestConsumerDetachProducerListener) { ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot)); // Check whether the slot from IProducerListener is same to the detached slot. - ASSERT_EQ(pl->getDetachedSlots().size(), 1); + ASSERT_EQ(pl->getDetachedSlots().size(), 1u); ASSERT_EQ(pl->getDetachedSlots()[0], slots[1]); // Dequeue another buffer. @@ -1525,4 +1530,55 @@ TEST(BufferQueueThreading, TestProducerDequeueConsumerDestroy) { EXPECT_EQ(nullptr, bufferConsumer.get()); } +TEST_F(BufferQueueTest, TestAdditionalOptions) { + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + sp<BufferItemConsumer> bufferConsumer = + sp<BufferItemConsumer>::make(consumer, GRALLOC_USAGE_SW_READ_OFTEN, 2); + ASSERT_NE(nullptr, bufferConsumer.get()); + sp<Surface> surface = sp<Surface>::make(producer); + native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888); + native_window_set_buffers_dimensions(surface.get(), 100, 100); + + std::array<AHardwareBufferLongOptions, 1> extras = {{ + {.name = "android.hardware.graphics.common.Dataspace", ADATASPACE_DISPLAY_P3}, + }}; + + ASSERT_EQ(NO_INIT, + native_window_set_buffers_additional_options(surface.get(), extras.data(), + extras.size())); + + if (!IsCuttlefish()) { + GTEST_SKIP() << "Not cuttlefish"; + } + + ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU)); + ASSERT_EQ(OK, + native_window_set_buffers_additional_options(surface.get(), extras.data(), + extras.size())); + + ANativeWindowBuffer* windowBuffer = nullptr; + int fence = -1; + ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence)); + + AHardwareBuffer* buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer); + ASSERT_TRUE(buffer); + ADataSpace dataSpace = AHardwareBuffer_getDataSpace(buffer); + EXPECT_EQ(ADATASPACE_DISPLAY_P3, dataSpace); + + ANativeWindow_cancelBuffer(surface.get(), windowBuffer, -1); + + // Check that reconnecting properly clears the options + ASSERT_EQ(OK, native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_CPU)); + ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU)); + + ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence)); + buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer); + ASSERT_TRUE(buffer); + dataSpace = AHardwareBuffer_getDataSpace(buffer); + EXPECT_EQ(ADATASPACE_UNKNOWN, dataSpace); +} + } // namespace android diff --git a/libs/gui/tests/Choreographer_test.cpp b/libs/gui/tests/Choreographer_test.cpp new file mode 100644 index 0000000000..2ac2550f07 --- /dev/null +++ b/libs/gui/tests/Choreographer_test.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2024 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_TAG "Choreographer_test" + +#include <android-base/stringprintf.h> +#include <android/choreographer.h> +#include <gtest/gtest.h> +#include <gui/Choreographer.h> +#include <utils/Looper.h> +#include <chrono> +#include <future> +#include <string> + +namespace android { +class ChoreographerTest : public ::testing::Test {}; + +struct VsyncCallback { + std::atomic<bool> completePromise{false}; + std::chrono::nanoseconds frameTime{0LL}; + std::chrono::nanoseconds receivedCallbackTime{0LL}; + + void onVsyncCallback(const AChoreographerFrameCallbackData* callbackData) { + frameTime = std::chrono::nanoseconds{ + AChoreographerFrameCallbackData_getFrameTimeNanos(callbackData)}; + receivedCallbackTime = std::chrono::nanoseconds{systemTime(SYSTEM_TIME_MONOTONIC)}; + completePromise.store(true); + } + + bool callbackReceived() { return completePromise.load(); } +}; + +static void vsyncCallback(const AChoreographerFrameCallbackData* callbackData, void* data) { + VsyncCallback* cb = static_cast<VsyncCallback*>(data); + cb->onVsyncCallback(callbackData); +} + +TEST_F(ChoreographerTest, InputCallbackBeforeAnimation) { + sp<Looper> looper = Looper::prepare(0); + Choreographer* choreographer = Choreographer::getForThread(); + VsyncCallback animationCb; + VsyncCallback inputCb; + + choreographer->postFrameCallbackDelayed(nullptr, nullptr, vsyncCallback, &animationCb, 0, + CALLBACK_ANIMATION); + choreographer->postFrameCallbackDelayed(nullptr, nullptr, vsyncCallback, &inputCb, 0, + CALLBACK_INPUT); + + nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); + nsecs_t currTime; + int pollResult; + do { + pollResult = looper->pollOnce(16); + currTime = systemTime(SYSTEM_TIME_MONOTONIC); + } while (!(inputCb.callbackReceived() && animationCb.callbackReceived()) && + (pollResult != Looper::POLL_TIMEOUT && pollResult != Looper::POLL_ERROR) && + (currTime - startTime < 3000)); + + ASSERT_TRUE(inputCb.callbackReceived()) << "did not receive input callback"; + ASSERT_TRUE(animationCb.callbackReceived()) << "did not receive animation callback"; + + ASSERT_EQ(inputCb.frameTime, animationCb.frameTime) + << android::base::StringPrintf("input and animation callback frame times don't match. " + "inputFrameTime=%lld animationFrameTime=%lld", + inputCb.frameTime.count(), + animationCb.frameTime.count()); + + ASSERT_LT(inputCb.receivedCallbackTime, animationCb.receivedCallbackTime) + << android::base::StringPrintf("input callback was not called first. " + "inputCallbackTime=%lld animationCallbackTime=%lld", + inputCb.frameTime.count(), + animationCb.frameTime.count()); +} + +} // namespace android
\ No newline at end of file diff --git a/libs/gui/tests/DisplayInfo_test.cpp b/libs/gui/tests/DisplayInfo_test.cpp index df3329cd52..4df76b1591 100644 --- a/libs/gui/tests/DisplayInfo_test.cpp +++ b/libs/gui/tests/DisplayInfo_test.cpp @@ -28,7 +28,7 @@ namespace test { TEST(DisplayInfo, Parcelling) { DisplayInfo info; - info.displayId = 42; + info.displayId = ui::LogicalDisplayId{42}; info.logicalWidth = 99; info.logicalHeight = 78; info.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1}); diff --git a/libs/gui/tests/DisplayedContentSampling_test.cpp b/libs/gui/tests/DisplayedContentSampling_test.cpp index 0a2750a4dd..bffb3f0430 100644 --- a/libs/gui/tests/DisplayedContentSampling_test.cpp +++ b/libs/gui/tests/DisplayedContentSampling_test.cpp @@ -116,10 +116,10 @@ TEST_F(DisplayedContentSamplingTest, SampleCollectionCoherentWithSupportMask) { EXPECT_EQ(OK, status); if (stats.numFrames <= 0) return; - if (componentMask & (0x1 << 0)) EXPECT_NE(0, stats.component_0_sample.size()); - if (componentMask & (0x1 << 1)) EXPECT_NE(0, stats.component_1_sample.size()); - if (componentMask & (0x1 << 2)) EXPECT_NE(0, stats.component_2_sample.size()); - if (componentMask & (0x1 << 3)) EXPECT_NE(0, stats.component_3_sample.size()); + if (componentMask & (0x1 << 0)) EXPECT_NE(0u, stats.component_0_sample.size()); + if (componentMask & (0x1 << 1)) EXPECT_NE(0u, stats.component_1_sample.size()); + if (componentMask & (0x1 << 2)) EXPECT_NE(0u, stats.component_2_sample.size()); + if (componentMask & (0x1 << 3)) EXPECT_NE(0u, stats.component_3_sample.size()); } } // namespace android diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index a9d6e8d3bf..7d0b512cb4 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -24,6 +24,7 @@ #include <memory> +#include <android-base/thread_annotations.h> #include <android/gui/BnWindowInfosReportedListener.h> #include <android/keycodes.h> #include <android/native_window.h> @@ -41,6 +42,7 @@ #include <android/os/IInputFlinger.h> #include <gui/WindowInfo.h> #include <input/Input.h> +#include <input/InputConsumer.h> #include <input/InputTransport.h> #include <ui/DisplayMode.h> @@ -58,7 +60,13 @@ using android::gui::InputApplicationInfo; using android::gui::TouchOcclusionMode; using android::gui::WindowInfo; -namespace android::test { +namespace android { +namespace { +ui::LogicalDisplayId toDisplayId(ui::LayerStack layerStack) { + return ui::LogicalDisplayId{static_cast<int32_t>(layerStack.id)}; +} +} // namespace +namespace test { using Transaction = SurfaceComposerClient::Transaction; @@ -66,7 +74,9 @@ sp<IInputFlinger> getInputFlinger() { sp<IBinder> input(defaultServiceManager()->waitForService(String16("inputflinger"))); if (input == nullptr) { ALOGE("Failed to link to input service"); - } else { ALOGE("Linked to input"); } + } else { + ALOGE("Linked to input"); + } return interface_cast<IInputFlinger>(input); } @@ -77,26 +87,27 @@ static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s; class SynchronousWindowInfosReportedListener : public gui::BnWindowInfosReportedListener { public: binder::Status onWindowInfosReported() override { - std::lock_guard<std::mutex> lock{mMutex}; + std::scoped_lock lock{mLock}; mWindowInfosReported = true; mConditionVariable.notify_one(); return binder::Status::ok(); } void wait() { - std::unique_lock<std::mutex> lock{mMutex}; - mConditionVariable.wait(lock, [&] { return mWindowInfosReported; }); + std::unique_lock lock{mLock}; + android::base::ScopedLockAssertion assumeLocked(mLock); + mConditionVariable.wait(lock, [&]() REQUIRES(mLock) { return mWindowInfosReported; }); } private: - std::mutex mMutex; + std::mutex mLock; std::condition_variable mConditionVariable; - bool mWindowInfosReported{false}; + bool mWindowInfosReported GUARDED_BY(mLock){false}; }; class InputSurface { public: - InputSurface(const sp<SurfaceControl> &sc, int width, int height, bool noInputChannel = false) { + InputSurface(const sp<SurfaceControl>& sc, int width, int height, bool noInputChannel = false) { mSurfaceControl = sc; mInputFlinger = getInputFlinger(); @@ -127,7 +138,7 @@ public: mInputInfo.applicationInfo = aInfo; } - static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc, + static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient>& scc, int width, int height) { sp<SurfaceControl> surfaceControl = scc->createSurface(String8("Test Surface"), 0 /* bufHeight */, 0 /* bufWidth */, @@ -137,7 +148,7 @@ public: } static std::unique_ptr<InputSurface> makeBufferInputSurface( - const sp<SurfaceComposerClient> &scc, int width, int height) { + const sp<SurfaceComposerClient>& scc, int width, int height) { sp<SurfaceControl> surfaceControl = scc->createSurface(String8("Test Buffer Surface"), width, height, PIXEL_FORMAT_RGBA_8888, 0 /* flags */); @@ -145,7 +156,7 @@ public: } static std::unique_ptr<InputSurface> makeContainerInputSurface( - const sp<SurfaceComposerClient> &scc, int width, int height) { + const sp<SurfaceComposerClient>& scc, int width, int height) { sp<SurfaceControl> surfaceControl = scc->createSurface(String8("Test Container Surface"), 0 /* bufHeight */, 0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888, @@ -154,7 +165,7 @@ public: } static std::unique_ptr<InputSurface> makeContainerInputSurfaceNoInputChannel( - const sp<SurfaceComposerClient> &scc, int width, int height) { + const sp<SurfaceComposerClient>& scc, int width, int height) { sp<SurfaceControl> surfaceControl = scc->createSurface(String8("Test Container Surface"), 100 /* height */, 100 /* width */, PIXEL_FORMAT_RGBA_8888, @@ -164,7 +175,7 @@ public: } static std::unique_ptr<InputSurface> makeCursorInputSurface( - const sp<SurfaceComposerClient> &scc, int width, int height) { + const sp<SurfaceComposerClient>& scc, int width, int height) { sp<SurfaceControl> surfaceControl = scc->createSurface(String8("Test Cursor Surface"), 0 /* bufHeight */, 0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888, @@ -175,7 +186,7 @@ public: InputEvent* consumeEvent(std::chrono::milliseconds timeout = 3000ms) { mClientChannel->waitForMessage(timeout); - InputEvent *ev; + InputEvent* ev; uint32_t seqId; status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev); if (consumed != OK) { @@ -187,14 +198,14 @@ public: } void assertFocusChange(bool hasFocus) { - InputEvent *ev = consumeEvent(); + InputEvent* ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(InputEventType::FOCUS, ev->getType()); - FocusEvent *focusEvent = static_cast<FocusEvent *>(ev); + FocusEvent* focusEvent = static_cast<FocusEvent*>(ev); EXPECT_EQ(hasFocus, focusEvent->getHasFocus()); } - void expectTap(int x, int y) { + void expectTap(float x, float y) { InputEvent* ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(InputEventType::MOTION, ev->getType()); @@ -213,10 +224,10 @@ public: } void expectTapWithFlag(int x, int y, int32_t flags) { - InputEvent *ev = consumeEvent(); + InputEvent* ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(InputEventType::MOTION, ev->getType()); - MotionEvent *mev = static_cast<MotionEvent *>(ev); + 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)); @@ -225,18 +236,18 @@ public: ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(InputEventType::MOTION, ev->getType()); - mev = static_cast<MotionEvent *>(ev); + mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); EXPECT_EQ(flags, mev->getFlags() & flags); } void expectTapInDisplayCoordinates(int displayX, int displayY) { - InputEvent *ev = consumeEvent(); + InputEvent* ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(InputEventType::MOTION, ev->getType()); - MotionEvent *mev = static_cast<MotionEvent *>(ev); + MotionEvent* mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); - const PointerCoords &coords = *mev->getRawPointerCoords(0 /*pointerIndex*/); + const PointerCoords& coords = *mev->getRawPointerCoords(0 /*pointerIndex*/); EXPECT_EQ(displayX, coords.getX()); EXPECT_EQ(displayY, coords.getY()); EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); @@ -244,16 +255,16 @@ public: ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(InputEventType::MOTION, ev->getType()); - mev = static_cast<MotionEvent *>(ev); + mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); } - void expectKey(uint32_t keycode) { - InputEvent *ev = consumeEvent(); + void expectKey(int32_t keycode) { + InputEvent* ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(InputEventType::KEY, ev->getType()); - KeyEvent *keyEvent = static_cast<KeyEvent *>(ev); + KeyEvent* keyEvent = static_cast<KeyEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, keyEvent->getAction()); EXPECT_EQ(keycode, keyEvent->getKeyCode()); EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS); @@ -261,12 +272,17 @@ public: ev = consumeEvent(); ASSERT_NE(ev, nullptr); ASSERT_EQ(InputEventType::KEY, ev->getType()); - keyEvent = static_cast<KeyEvent *>(ev); + keyEvent = static_cast<KeyEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, keyEvent->getAction()); EXPECT_EQ(keycode, keyEvent->getKeyCode()); EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS); } + void assertNoEvent() { + InputEvent* event = consumeEvent(/*timeout=*/100ms); + ASSERT_EQ(event, nullptr) << "Expected no event, but got " << *event; + } + virtual ~InputSurface() { if (mClientChannel) { mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); @@ -274,7 +290,7 @@ public: } virtual void doTransaction( - std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)> + std::function<void(SurfaceComposerClient::Transaction&, const sp<SurfaceControl>&)> transactionBody) { SurfaceComposerClient::Transaction t; transactionBody(t, mSurfaceControl); @@ -295,13 +311,13 @@ public: reportedListener->wait(); } - void requestFocus(int displayId = ADISPLAY_ID_DEFAULT) { + void requestFocus(ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT) { SurfaceComposerClient::Transaction t; FocusRequest request; request.token = mInputInfo.token; request.windowName = mInputInfo.name; request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); - request.displayId = displayId; + request.displayId = displayId.val(); t.setFocusedWindow(request); t.apply(true); } @@ -319,7 +335,7 @@ public: class BlastInputSurface : public InputSurface { public: - BlastInputSurface(const sp<SurfaceControl> &sc, const sp<SurfaceControl> &parentSc, int width, + BlastInputSurface(const sp<SurfaceControl>& sc, const sp<SurfaceControl>& parentSc, int width, int height) : InputSurface(sc, width, height) { mParentSurfaceControl = parentSc; @@ -328,7 +344,7 @@ public: ~BlastInputSurface() = default; static std::unique_ptr<BlastInputSurface> makeBlastInputSurface( - const sp<SurfaceComposerClient> &scc, int width, int height) { + const sp<SurfaceComposerClient>& scc, int width, int height) { sp<SurfaceControl> parentSc = scc->createSurface(String8("Test Parent Surface"), 0 /* bufHeight */, 0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888, @@ -343,7 +359,7 @@ public: } void doTransaction( - std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)> + std::function<void(SurfaceComposerClient::Transaction&, const sp<SurfaceControl>&)> transactionBody) override { SurfaceComposerClient::Transaction t; transactionBody(t, mParentSurfaceControl); @@ -370,9 +386,7 @@ private: class InputSurfacesTest : public ::testing::Test { public: - InputSurfacesTest() { - ProcessState::self()->startThreadPool(); - } + InputSurfacesTest() { ProcessState::self()->startThreadPool(); } void SetUp() { mComposerClient = new SurfaceComposerClient; @@ -392,15 +406,13 @@ public: mBufferPostDelay = static_cast<int32_t>(1e6 / mode.peakRefreshRate) * 3; } - void TearDown() { - mComposerClient->dispose(); - } + void TearDown() { mComposerClient->dispose(); } std::unique_ptr<InputSurface> makeSurface(int width, int height) { return InputSurface::makeColorInputSurface(mComposerClient, width, height); } - void postBuffer(const sp<SurfaceControl> &layer, int32_t w, int32_t h) { + void postBuffer(const sp<SurfaceControl>& layer, int32_t w, int32_t h) { int64_t usageFlags = BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE; sp<GraphicBuffer> buffer = @@ -413,31 +425,31 @@ public: int32_t mBufferPostDelay; }; -void injectTapOnDisplay(int x, int y, int displayId) { +void injectTapOnDisplay(int x, int y, ui::LogicalDisplayId displayId) { char *buf1, *buf2, *bufDisplayId; asprintf(&buf1, "%d", x); asprintf(&buf2, "%d", y); - asprintf(&bufDisplayId, "%d", displayId); + asprintf(&bufDisplayId, "%d", displayId.val()); if (fork() == 0) { execlp("input", "input", "-d", bufDisplayId, "tap", buf1, buf2, NULL); } } void injectTap(int x, int y) { - injectTapOnDisplay(x, y, ADISPLAY_ID_DEFAULT); + injectTapOnDisplay(x, y, ui::LogicalDisplayId::DEFAULT); } -void injectKeyOnDisplay(uint32_t keycode, int displayId) { +void injectKeyOnDisplay(uint32_t keycode, ui::LogicalDisplayId displayId) { char *buf1, *bufDisplayId; asprintf(&buf1, "%d", keycode); - asprintf(&bufDisplayId, "%d", displayId); + asprintf(&bufDisplayId, "%d", displayId.val()); if (fork() == 0) { execlp("input", "input", "-d", bufDisplayId, "keyevent", buf1, NULL); } } void injectKey(uint32_t keycode) { - injectKeyOnDisplay(keycode, ADISPLAY_ID_NONE); + injectKeyOnDisplay(keycode, ui::LogicalDisplayId::INVALID); } TEST_F(InputSurfacesTest, can_receive_input) { @@ -468,12 +480,8 @@ TEST_F(InputSurfacesTest, input_respects_positioning) { injectTap(101, 101); surface->expectTap(1, 1); - surface2->doTransaction([](auto &t, auto &sc) { - t.setPosition(sc, 100, 100); - }); - surface->doTransaction([](auto &t, auto &sc) { - t.setPosition(sc, 200, 200); - }); + surface2->doTransaction([](auto& t, auto& sc) { t.setPosition(sc, 100, 100); }); + surface->doTransaction([](auto& t, auto& sc) { t.setPosition(sc, 200, 200); }); injectTap(101, 101); surface2->expectTap(1, 1); @@ -489,23 +497,17 @@ TEST_F(InputSurfacesTest, input_respects_layering) { surface->showAt(10, 10); surface2->showAt(10, 10); - surface->doTransaction([](auto &t, auto &sc) { - t.setLayer(sc, LAYER_BASE + 1); - }); + surface->doTransaction([](auto& t, auto& sc) { t.setLayer(sc, LAYER_BASE + 1); }); injectTap(11, 11); surface->expectTap(1, 1); - surface2->doTransaction([](auto &t, auto &sc) { - t.setLayer(sc, LAYER_BASE + 1); - }); + surface2->doTransaction([](auto& t, auto& sc) { t.setLayer(sc, LAYER_BASE + 1); }); injectTap(11, 11); surface2->expectTap(1, 1); - surface2->doTransaction([](auto &t, auto &sc) { - t.hide(sc); - }); + surface2->doTransaction([](auto& t, auto& sc) { t.hide(sc); }); injectTap(11, 11); surface->expectTap(1, 1); @@ -554,7 +556,7 @@ TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) { childSurface->mInputInfo.surfaceInset = 10; childSurface->showAt(100, 100); - childSurface->doTransaction([&](auto &t, auto &sc) { + childSurface->doTransaction([&](auto& t, auto& sc) { t.setPosition(sc, -5, -5); t.reparent(sc, parentSurface->mSurfaceControl); }); @@ -575,7 +577,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) { fgSurface->mInputInfo.surfaceInset = 5; fgSurface->showAt(100, 100); - fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); }); + fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); }); // expect = touch / scale - inset injectTap(112, 124); @@ -594,7 +596,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) { fgSurface->mInputInfo.surfaceInset = INT32_MAX; fgSurface->showAt(100, 100); - fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); + fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); // expect no crash for overflow, and inset size to be clamped to surface size injectTap(112, 124); @@ -643,7 +645,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_touchable_region_overflow) { fgSurface->mInputInfo.touchableRegion.orSelf(Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX}); fgSurface->showAt(0, 0); - fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); + fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); // Expect no crash for overflow. injectTap(12, 24); @@ -653,7 +655,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_touchable_region_overflow) { // Ensure we ignore transparent region when getting screen bounds when positioning input frame. TEST_F(InputSurfacesTest, input_ignores_transparent_region) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { Region transparentRegion(Rect(0, 0, 10, 10)); t.setTransparentRegionHint(sc, transparentRegion); }); @@ -694,7 +696,7 @@ TEST_F(InputSurfacesTest, input_respects_buffer_layer_alpha) { injectTap(11, 11); bufferSurface->expectTap(1, 1); - bufferSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); }); + bufferSurface->doTransaction([](auto& t, auto& sc) { t.setAlpha(sc, 0.0); }); injectTap(11, 11); bgSurface->expectTap(1, 1); @@ -710,7 +712,7 @@ TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) { injectTap(11, 11); fgSurface->expectTap(1, 1); - fgSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); }); + fgSurface->doTransaction([](auto& t, auto& sc) { t.setAlpha(sc, 0.0); }); injectTap(11, 11); fgSurface->expectTap(1, 1); @@ -727,7 +729,7 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { injectTap(11, 11); containerSurface->expectTap(1, 1); - containerSurface->doTransaction([](auto &t, auto &sc) { t.hide(sc); }); + containerSurface->doTransaction([](auto& t, auto& sc) { t.hide(sc); }); injectTap(11, 11); bgSurface->expectTap(1, 1); @@ -767,19 +769,19 @@ TEST_F(InputSurfacesTest, can_be_focused) { TEST_F(InputSurfacesTest, rotate_surface) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(10, 10); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, 0, 1, -1, 0); // 90 degrees }); injectTap(8, 11); surface->expectTap(1, 2); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, -1, 0, 0, -1); // 180 degrees }); injectTap(9, 8); surface->expectTap(1, 2); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, 0, -1, 1, 0); // 270 degrees }); injectTap(12, 9); @@ -789,19 +791,19 @@ TEST_F(InputSurfacesTest, rotate_surface) { TEST_F(InputSurfacesTest, rotate_surface_with_scale) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(10, 10); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, 0, 2, -4, 0); // 90 degrees }); injectTap(2, 12); surface->expectTap(1, 2); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, -2, 0, 0, -4); // 180 degrees }); injectTap(8, 2); surface->expectTap(1, 2); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, 0, -2, 4, 0); // 270 degrees }); injectTap(18, 8); @@ -813,19 +815,19 @@ TEST_F(InputSurfacesTest, rotate_surface_with_scale_and_insets) { surface->mInputInfo.surfaceInset = 5; surface->showAt(100, 100); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, 0, 2, -4, 0); // 90 degrees }); injectTap(40, 120); surface->expectTap(5, 10); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, -2, 0, 0, -4); // 180 degrees }); injectTap(80, 40); surface->expectTap(5, 10); - surface->doTransaction([](auto &t, auto &sc) { + surface->doTransaction([](auto& t, auto& sc) { t.setMatrix(sc, 0, -2, 4, 0); // 270 degrees }); injectTap(160, 80); @@ -866,7 +868,7 @@ TEST_F(InputSurfacesTest, touch_flag_partially_obscured_with_crop) { nonTouchableSurface->showAt(0, 0); parentSurface->showAt(100, 100); - nonTouchableSurface->doTransaction([&](auto &t, auto &sc) { + nonTouchableSurface->doTransaction([&](auto& t, auto& sc) { t.setCrop(parentSurface->mSurfaceControl, Rect(0, 0, 50, 50)); t.reparent(sc, parentSurface->mSurfaceControl); }); @@ -890,7 +892,7 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_crop) { nonTouchableSurface->showAt(0, 0); parentSurface->showAt(50, 50); - nonTouchableSurface->doTransaction([&](auto &t, auto &sc) { + nonTouchableSurface->doTransaction([&](auto& t, auto& sc) { t.setCrop(parentSurface->mSurfaceControl, Rect(0, 0, 50, 50)); t.reparent(sc, parentSurface->mSurfaceControl); }); @@ -932,13 +934,11 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) { TEST_F(InputSurfacesTest, strict_unobscured_input_unobscured_window) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->doTransaction( - [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); + [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); surface->showAt(100, 100); injectTap(101, 101); - - EXPECT_NE(surface->consumeEvent(), nullptr); - EXPECT_NE(surface->consumeEvent(), nullptr); + surface->expectTap(1, 1); surface->requestFocus(); surface->assertFocusChange(true); @@ -948,16 +948,14 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_unobscured_window) { TEST_F(InputSurfacesTest, strict_unobscured_input_scaled_without_crop_window) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->doTransaction([&](auto &t, auto &sc) { + surface->doTransaction([&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); t.setMatrix(sc, 2.0, 0, 0, 2.0); }); surface->showAt(100, 100); injectTap(101, 101); - - EXPECT_NE(surface->consumeEvent(), nullptr); - EXPECT_NE(surface->consumeEvent(), nullptr); + surface->expectTap(.5, .5); surface->requestFocus(); surface->assertFocusChange(true); @@ -969,26 +967,26 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_obscured_window) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->mInputInfo.ownerUid = gui::Uid{11111}; surface->doTransaction( - [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); + [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); surface->showAt(100, 100); std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100); obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); obscuringSurface->mInputInfo.ownerUid = gui::Uid{22222}; obscuringSurface->showAt(100, 100); injectTap(101, 101); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); surface->requestFocus(); surface->assertFocusChange(true); injectKey(AKEYCODE_V); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); } TEST_F(InputSurfacesTest, strict_unobscured_input_partially_obscured_window) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->mInputInfo.ownerUid = gui::Uid{11111}; surface->doTransaction( - [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); + [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); surface->showAt(100, 100); std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100); obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); @@ -997,12 +995,12 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_partially_obscured_window) { injectTap(101, 101); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); surface->requestFocus(); surface->assertFocusChange(true); injectKey(AKEYCODE_V); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); } TEST_F(InputSurfacesTest, strict_unobscured_input_alpha_window) { @@ -1011,7 +1009,7 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_alpha_window) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); - surface->doTransaction([&](auto &t, auto &sc) { + surface->doTransaction([&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); t.reparent(sc, parentSurface->mSurfaceControl); t.setAlpha(parentSurface->mSurfaceControl, 0.9f); @@ -1019,12 +1017,12 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_alpha_window) { injectTap(101, 101); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); surface->requestFocus(); surface->assertFocusChange(true); injectKey(AKEYCODE_V); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); } TEST_F(InputSurfacesTest, strict_unobscured_input_cropped_window) { @@ -1032,7 +1030,7 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_cropped_window) { parentSurface->showAt(0, 0, Rect(0, 0, 300, 300)); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->doTransaction([&](auto &t, auto &sc) { + surface->doTransaction([&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); t.reparent(sc, parentSurface->mSurfaceControl); t.setCrop(parentSurface->mSurfaceControl, Rect(10, 10, 100, 100)); @@ -1041,12 +1039,12 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_cropped_window) { injectTap(111, 111); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); surface->requestFocus(); surface->assertFocusChange(true); injectKey(AKEYCODE_V); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); } TEST_F(InputSurfacesTest, ignore_touch_region_with_zero_sized_blast) { @@ -1066,17 +1064,16 @@ TEST_F(InputSurfacesTest, ignore_touch_region_with_zero_sized_blast) { TEST_F(InputSurfacesTest, drop_input_policy) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->doTransaction( - [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::ALL); }); + [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::ALL); }); surface->showAt(100, 100); injectTap(101, 101); - - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); surface->requestFocus(); surface->assertFocusChange(true); injectKey(AKEYCODE_V); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); } TEST_F(InputSurfacesTest, layer_with_valid_crop_can_be_focused) { @@ -1099,7 +1096,7 @@ TEST_F(InputSurfacesTest, cropped_container_replaces_touchable_region_with_null_ std::unique_ptr<InputSurface> containerSurface = InputSurface::makeContainerInputSurface(mComposerClient, 100, 100); containerSurface->doTransaction( - [&](auto &t, auto &sc) { t.reparent(sc, parentContainer->mSurfaceControl); }); + [&](auto& t, auto& sc) { t.reparent(sc, parentContainer->mSurfaceControl); }); containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true; containerSurface->mInputInfo.touchableRegionCropHandle = nullptr; parentContainer->showAt(10, 10, Rect(0, 0, 20, 20)); @@ -1111,7 +1108,7 @@ TEST_F(InputSurfacesTest, cropped_container_replaces_touchable_region_with_null_ // Does not receive events outside its crop injectTap(26, 26); - EXPECT_EQ(containerSurface->consumeEvent(/*timeout=*/100ms), nullptr); + containerSurface->assertNoEvent(); } /** @@ -1124,7 +1121,7 @@ TEST_F(InputSurfacesTest, uncropped_container_replaces_touchable_region_with_nul std::unique_ptr<InputSurface> containerSurface = InputSurface::makeContainerInputSurface(mComposerClient, 100, 100); containerSurface->doTransaction( - [&](auto &t, auto &sc) { t.reparent(sc, parentContainer->mSurfaceControl); }); + [&](auto& t, auto& sc) { t.reparent(sc, parentContainer->mSurfaceControl); }); containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true; containerSurface->mInputInfo.touchableRegionCropHandle = nullptr; parentContainer->showAt(10, 10, Rect(0, 0, 20, 20)); @@ -1136,7 +1133,7 @@ TEST_F(InputSurfacesTest, uncropped_container_replaces_touchable_region_with_nul // Does not receive events outside parent bounds injectTap(31, 31); - EXPECT_EQ(containerSurface->consumeEvent(/*timeout=*/100ms), nullptr); + containerSurface->assertNoEvent(); } /** @@ -1162,7 +1159,7 @@ TEST_F(InputSurfacesTest, replace_touchable_region_with_crop) { // Does not receive events outside crop layer bounds injectTap(21, 21); injectTap(71, 71); - EXPECT_EQ(containerSurface->consumeEvent(/*timeout=*/100ms), nullptr); + containerSurface->assertNoEvent(); } TEST_F(InputSurfacesTest, child_container_with_no_input_channel_blocks_parent) { @@ -1176,19 +1173,19 @@ TEST_F(InputSurfacesTest, child_container_with_no_input_channel_blocks_parent) { InputSurface::makeContainerInputSurfaceNoInputChannel(mComposerClient, 100, 100); childContainerSurface->showAt(0, 0); childContainerSurface->doTransaction( - [&](auto &t, auto &sc) { t.reparent(sc, parent->mSurfaceControl); }); + [&](auto& t, auto& sc) { t.reparent(sc, parent->mSurfaceControl); }); injectTap(101, 101); - EXPECT_EQ(parent->consumeEvent(/*timeout=*/100ms), nullptr); + parent->assertNoEvent(); } class MultiDisplayTests : public InputSurfacesTest { public: MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); } + void TearDown() override { - for (auto &token : mVirtualDisplays) { - SurfaceComposerClient::destroyDisplay(token); - } + std::for_each(mVirtualDisplays.begin(), mVirtualDisplays.end(), + SurfaceComposerClient::destroyVirtualDisplay); InputSurfacesTest::TearDown(); } @@ -1203,7 +1200,7 @@ public: std::string name = "VirtualDisplay"; name += std::to_string(mVirtualDisplays.size()); - sp<IBinder> token = SurfaceComposerClient::createDisplay(String8(name.c_str()), isSecure); + sp<IBinder> token = SurfaceComposerClient::createVirtualDisplay(name, isSecure); SurfaceComposerClient::Transaction t; t.setDisplaySurface(token, producer); t.setDisplayFlags(token, receivesInput ? 0x01 /* DisplayDevice::eReceivesInput */ : 0); @@ -1223,18 +1220,18 @@ TEST_F(MultiDisplayTests, drop_touch_if_layer_on_invalid_display) { ui::LayerStack layerStack = ui::LayerStack::fromValue(42); // Do not create a display associated with the LayerStack. std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->doTransaction([&](auto &t, auto &sc) { t.setLayerStack(sc, layerStack); }); + surface->doTransaction([&](auto& t, auto& sc) { t.setLayerStack(sc, layerStack); }); surface->showAt(100, 100); // Touches should be dropped if the layer is on an invalid display. - injectTapOnDisplay(101, 101, layerStack.id); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + injectTapOnDisplay(101, 101, toDisplayId(layerStack)); + surface->assertNoEvent(); // However, we still let the window be focused and receive keys. - surface->requestFocus(layerStack.id); + surface->requestFocus(toDisplayId(layerStack)); surface->assertFocusChange(true); - injectKeyOnDisplay(AKEYCODE_V, layerStack.id); + injectKeyOnDisplay(AKEYCODE_V, toDisplayId(layerStack)); surface->expectKey(AKEYCODE_V); } @@ -1242,15 +1239,15 @@ TEST_F(MultiDisplayTests, virtual_display_receives_input) { ui::LayerStack layerStack = ui::LayerStack::fromValue(42); createDisplay(1000, 1000, false /*isSecure*/, layerStack); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->doTransaction([&](auto &t, auto &sc) { t.setLayerStack(sc, layerStack); }); + surface->doTransaction([&](auto& t, auto& sc) { t.setLayerStack(sc, layerStack); }); surface->showAt(100, 100); - injectTapOnDisplay(101, 101, layerStack.id); + injectTapOnDisplay(101, 101, toDisplayId(layerStack)); surface->expectTap(1, 1); - surface->requestFocus(layerStack.id); + surface->requestFocus(toDisplayId(layerStack)); surface->assertFocusChange(true); - injectKeyOnDisplay(AKEYCODE_V, layerStack.id); + injectKeyOnDisplay(AKEYCODE_V, toDisplayId(layerStack)); surface->expectKey(AKEYCODE_V); } @@ -1258,20 +1255,20 @@ TEST_F(MultiDisplayTests, drop_input_for_secure_layer_on_nonsecure_display) { ui::LayerStack layerStack = ui::LayerStack::fromValue(42); createDisplay(1000, 1000, false /*isSecure*/, layerStack); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->doTransaction([&](auto &t, auto &sc) { + surface->doTransaction([&](auto& t, auto& sc) { t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); t.setLayerStack(sc, layerStack); }); surface->showAt(100, 100); - injectTapOnDisplay(101, 101, layerStack.id); + injectTapOnDisplay(101, 101, toDisplayId(layerStack)); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + surface->assertNoEvent(); - surface->requestFocus(layerStack.id); + surface->requestFocus(toDisplayId(layerStack)); surface->assertFocusChange(true); - injectKeyOnDisplay(AKEYCODE_V, layerStack.id); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/100ms), nullptr); + injectKeyOnDisplay(AKEYCODE_V, toDisplayId(layerStack)); + surface->assertNoEvent(); } TEST_F(MultiDisplayTests, dont_drop_input_for_secure_layer_on_secure_display) { @@ -1284,21 +1281,21 @@ TEST_F(MultiDisplayTests, dont_drop_input_for_secure_layer_on_secure_display) { seteuid(AID_ROOT); std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->doTransaction([&](auto &t, auto &sc) { + surface->doTransaction([&](auto& t, auto& sc) { t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); t.setLayerStack(sc, layerStack); }); surface->showAt(100, 100); - injectTapOnDisplay(101, 101, layerStack.id); - EXPECT_NE(surface->consumeEvent(), nullptr); - EXPECT_NE(surface->consumeEvent(), nullptr); + injectTapOnDisplay(101, 101, toDisplayId(layerStack)); + surface->expectTap(1, 1); - surface->requestFocus(layerStack.id); + surface->requestFocus(toDisplayId(layerStack)); surface->assertFocusChange(true); - injectKeyOnDisplay(AKEYCODE_V, layerStack.id); + injectKeyOnDisplay(AKEYCODE_V, toDisplayId(layerStack)); surface->expectKey(AKEYCODE_V); } -} // namespace android::test +} // namespace test +} // namespace android diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp index b18b544257..223e4b6cbd 100644 --- a/libs/gui/tests/RegionSampling_test.cpp +++ b/libs/gui/tests/RegionSampling_test.cpp @@ -239,8 +239,9 @@ protected: float const luma_green = 0.7152; uint32_t const rgba_blue = 0xFFFF0000; float const luma_blue = 0.0722; - float const error_margin = 0.01; + float const error_margin = 0.1; float const luma_gray = 0.50; + static constexpr std::chrono::milliseconds EVENT_WAIT_TIME_MS = 5000ms; }; TEST_F(RegionSamplingTest, invalidLayerHandle_doesNotCrash) { @@ -261,7 +262,7 @@ TEST_F(RegionSamplingTest, invalidLayerHandle_doesNotCrash) { composer->removeRegionSamplingListener(listener); } -TEST_F(RegionSamplingTest, DISABLED_CollectsLuma) { +TEST_F(RegionSamplingTest, CollectsLuma) { fill_render(rgba_green); sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService(); @@ -273,7 +274,30 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLuma) { sampleArea.bottom = 200; composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; + EXPECT_NEAR(listener->luma(), luma_green, error_margin); + + composer->removeRegionSamplingListener(listener); +} + +TEST_F(RegionSamplingTest, CollectsLumaForSecureLayer) { + fill_render(rgba_green); + SurfaceComposerClient::Transaction() + .setFlags(mContentLayer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) + .apply(/*synchronous=*/true); + + sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService(); + sp<Listener> listener = new Listener(); + gui::ARect sampleArea; + sampleArea.left = 100; + sampleArea.top = 100; + sampleArea.right = 200; + sampleArea.bottom = 200; + composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); + + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_green, error_margin); composer->removeRegionSamplingListener(listener); @@ -291,13 +315,14 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsChangingLuma) { sampleArea.bottom = 200; composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_green, error_margin); listener->reset(); fill_render(rgba_blue); - EXPECT_TRUE(listener->wait_event(300ms)) + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) << "timed out waiting for 2nd luma event to be received"; EXPECT_NEAR(listener->luma(), luma_blue, error_margin); @@ -323,10 +348,10 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromTwoRegions) { graySampleArea.bottom = 200; composer->addRegionSamplingListener(graySampleArea, mTopLayer->getHandle(), grayListener); - EXPECT_TRUE(grayListener->wait_event(300ms)) + EXPECT_TRUE(grayListener->wait_event(EVENT_WAIT_TIME_MS)) << "timed out waiting for luma event to be received"; EXPECT_NEAR(grayListener->luma(), luma_gray, error_margin); - EXPECT_TRUE(greenListener->wait_event(300ms)) + EXPECT_TRUE(greenListener->wait_event(EVENT_WAIT_TIME_MS)) << "timed out waiting for luma event to be received"; EXPECT_NEAR(greenListener->luma(), luma_green, error_margin); @@ -334,7 +359,7 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromTwoRegions) { composer->removeRegionSamplingListener(grayListener); } -TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) { +TEST_F(RegionSamplingTest, TestIfInvalidInputParameters) { sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService(); sp<Listener> listener = new Listener(); @@ -369,7 +394,7 @@ TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) { composer->removeRegionSamplingListener(listener); } -TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) { +TEST_F(RegionSamplingTest, TestCallbackAfterRemoveListener) { fill_render(rgba_green); sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService(); sp<Listener> listener = new Listener(); @@ -381,7 +406,8 @@ TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) { composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); fill_render(rgba_green); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_green, error_margin); listener->reset(); @@ -404,11 +430,13 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) { // Test: listener in (100, 100). See layer before move, no layer after move. fill_render(rgba_blue); composer->addRegionSamplingListener(sampleAreaA, mTopLayer->getHandle(), listener); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_blue, error_margin); listener->reset(); SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply(); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_gray, error_margin); composer->removeRegionSamplingListener(listener); @@ -420,11 +448,13 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) { sampleAreaA.right = sampleArea.right; sampleAreaA.bottom = sampleArea.bottom; composer->addRegionSamplingListener(sampleAreaA, mTopLayer->getHandle(), listener); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_gray, error_margin); listener->reset(); SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply(); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_green, error_margin); composer->removeRegionSamplingListener(listener); } diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 577d2394c6..43cd0f8a7f 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -173,7 +173,7 @@ protected: // Acquire and free 1+extraDiscardedBuffers buffer, check onBufferReleased is called. std::vector<BufferItem> releasedItems; releasedItems.resize(1+extraDiscardedBuffers); - for (int i = 0; i < releasedItems.size(); i++) { + for (size_t i = 0; i < releasedItems.size(); i++) { ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&releasedItems[i], 0)); ASSERT_EQ(NO_ERROR, consumer->releaseBuffer(releasedItems[i].mSlot, releasedItems[i].mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, @@ -197,7 +197,7 @@ protected: // Check onBufferDiscarded is called with correct buffer auto discardedBuffers = listener->getDiscardedBuffers(); ASSERT_EQ(discardedBuffers.size(), releasedItems.size()); - for (int i = 0; i < releasedItems.size(); i++) { + for (size_t i = 0; i < releasedItems.size(); i++) { ASSERT_EQ(discardedBuffers[i], releasedItems[i].mGraphicBuffer); } @@ -673,13 +673,14 @@ public: return binder::Status::ok(); } - binder::Status createDisplay(const std::string& /*displayName*/, bool /*secure*/, - float /*requestedRefreshRate*/, - sp<IBinder>* /*outDisplay*/) override { + binder::Status createVirtualDisplay(const std::string& /*displayName*/, bool /*isSecure*/, + const std::string& /*uniqueId*/, + float /*requestedRefreshRate*/, + sp<IBinder>* /*outDisplay*/) override { return binder::Status::ok(); } - binder::Status destroyDisplay(const sp<IBinder>& /*display*/) override { + binder::Status destroyVirtualDisplay(const sp<IBinder>& /*displayToken*/) override { return binder::Status::ok(); } @@ -815,10 +816,6 @@ public: return binder::Status::ok(); } - binder::Status getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* /*outLayers*/) override { - return binder::Status::ok(); - } - binder::Status getCompositionPreference(gui::CompositionPreference* /*outPref*/) override { return binder::Status::ok(); } @@ -988,6 +985,8 @@ public: return binder::Status::ok(); } + binder::Status notifyShutdown() override { return binder::Status::ok(); } + protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp index 5eb5d3bff0..ce22082a9f 100644 --- a/libs/gui/tests/WindowInfo_test.cpp +++ b/libs/gui/tests/WindowInfo_test.cpp @@ -64,7 +64,7 @@ TEST(WindowInfo, Parcelling) { i.ownerUid = gui::Uid{24}; i.packageName = "com.example.package"; i.inputConfig = WindowInfo::InputConfig::NOT_FOCUSABLE; - i.displayId = 34; + i.displayId = ui::LogicalDisplayId{34}; i.replaceTouchableRegionWithCrop = true; i.touchableRegionCropHandle = touchableRegionCropHandle; i.applicationInfo.name = "ApplicationFooBar"; |