From 35018763c0098ce802d51408f77b13633128041c Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 7 Jan 2021 17:56:08 -0800 Subject: SurfaceFlinger: handle high refresh rate deny list Add visibility to SurfaceFlinger into the high refresh rate deny list and let SurfaceFlinger handle it. Previously WM was setting the preferredDisplayModeId on the denied app's window. The old way prevented SurfaceFlinger to use the frame rate override feature as it didn't know that a specific app is causing the refresh rate spec to be limited. With this change, SurfaceFlinger will limit the display refresh rate based on the high refresh rate deny list, and if possible, will use the frame rate override feature to change the display rate to a multiple, allowing other animations to be smooth while the denied app remains in the low refresh rate. Bug: 170502573 Test: SF unit tests Change-Id: Idc8a5fe6bc12dbd949ad5e09ff50e339ffaeac36 --- libs/gui/LayerState.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'libs/gui/LayerState.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 63be3edf94..e5e10a0014 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "LayerState" +#include #include #include @@ -620,7 +621,8 @@ status_t InputWindowCommands::read(const Parcel& input) { return NO_ERROR; } -bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName) { +bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName, + bool privileged) { const char* functionName = inFunctionName != nullptr ? inFunctionName : "call"; int floatClassification = std::fpclassify(frameRate); if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) { @@ -629,8 +631,10 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunc } if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && - compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) { - ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility); + compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE && + (!privileged || compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT)) { + ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName, + compatibility, privileged ? "yes" : "no"); return false; } -- cgit v1.2.3-59-g8ed1b From 58ca29d421dbec323e7f854ee8226b2d365c00be Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 13 Jan 2021 10:28:00 -1000 Subject: Add inputEventId to SurfaceFrame SurfaceFrame will now be aware of the id of the input event that caused the current frame. The flow of input event id is inputflinger -> app -> surfaceflinger. Here, we are adding the 'inputEventId' parameter to the 'setFrameTimelineVsync' call. This call will now be responsible for setting two pieces of information: the vsync id, and the input event id. Since it will no longer be limited to the vsync id, we rename this call to "setFrameTimelineInfo". Once the inputEventId is stored in SurfaceFrame, we will add a binder call to send the frame timing information to inputflinger (separate, future CL). This will allow input to reconstruct the entire sequence of events (at what time was input event getting processed in system_server, app, and surfaceflinger) and will provide the ability to measure end-to-end touch latency. In a separate change, we will also add ATRACE calls to allow manual / script-based latency analysis for local debugging. We will now know which input event is being processed in surfaceflinger. Bug: 169866723 Bug: 129481165 Design doc: https://docs.google.com/document/d/1G3bLaZYSmbe6AKcL-6ZChvrw_B_LXEz29Z6Ed9QoYXY/edit# Test: atest WMShellUnitTests SurfaceParcelable_test libgui_test IPC_test SurfaceFlinger_test Change-Id: If7e0eee82603b38b396b53ad7ced660973efcb50 --- libs/gui/Android.bp | 3 + libs/gui/BLASTBufferQueue.cpp | 14 +- libs/gui/FrameTimelineInfo.cpp | 62 +++++ libs/gui/ISurfaceComposer.cpp | 251 ++++++++++----------- libs/gui/ITransactionCompletedListener.cpp | 6 +- libs/gui/LayerState.cpp | 18 +- libs/gui/Surface.cpp | 16 +- libs/gui/SurfaceComposerClient.cpp | 41 ++-- libs/gui/include/gui/BLASTBufferQueue.h | 4 +- libs/gui/include/gui/DisplayEventDispatcher.h | 2 +- libs/gui/include/gui/FrameTimelineInfo.h | 43 ++++ libs/gui/include/gui/ISurfaceComposer.h | 14 +- libs/gui/include/gui/LayerState.h | 4 +- libs/gui/include/gui/Surface.h | 5 +- libs/gui/include/gui/SurfaceComposerClient.h | 13 +- libs/gui/tests/Surface_test.cpp | 6 +- libs/input/android/os/IInputConstants.aidl | 6 + libs/nativewindow/include/system/window.h | 11 +- services/surfaceflinger/BufferQueueLayer.cpp | 14 +- services/surfaceflinger/BufferQueueLayer.h | 6 +- .../surfaceflinger/FrameTimeline/FrameTimeline.cpp | 97 ++++---- .../surfaceflinger/FrameTimeline/FrameTimeline.h | 28 +-- services/surfaceflinger/Layer.cpp | 18 +- services/surfaceflinger/Layer.h | 9 +- services/surfaceflinger/SurfaceFlinger.cpp | 40 ++-- services/surfaceflinger/SurfaceFlinger.h | 18 +- services/surfaceflinger/tests/LayerState_test.cpp | 29 +++ .../tests/unittests/FrameTimelineTest.cpp | 187 +++++++-------- .../tests/unittests/TestableSurfaceFlinger.h | 18 +- .../tests/unittests/TransactionApplicationTest.cpp | 72 +++--- 30 files changed, 587 insertions(+), 468 deletions(-) create mode 100644 libs/gui/FrameTimelineInfo.cpp create mode 100644 libs/gui/include/gui/FrameTimelineInfo.h (limited to 'libs/gui/LayerState.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 38ae353a68..fa5044cc16 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -49,6 +49,7 @@ cc_library_shared { srcs: [ ":framework_native_aidl", + ":inputconstants_aidl", ":libgui_aidl", ":libgui_bufferqueue_sources", @@ -62,6 +63,7 @@ cc_library_shared { "DebugEGLImageTracker.cpp", "DisplayEventDispatcher.cpp", "DisplayEventReceiver.cpp", + "FrameTimelineInfo.cpp", "GLConsumer.cpp", "IConsumerListener.cpp", "IDisplayEventConnection.cpp", @@ -154,6 +156,7 @@ cc_library_static { defaults: ["libgui_bufferqueue-defaults"], srcs: [ + ":inputconstants_aidl", ":libgui_aidl", ":libgui_bufferqueue_sources", ], diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 0a3d44d336..adc7745e06 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -353,9 +353,9 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { } t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber); - if (!mNextFrameTimelineVsyncIdQueue.empty()) { - t->setFrameTimelineVsync(mSurfaceControl, mNextFrameTimelineVsyncIdQueue.front()); - mNextFrameTimelineVsyncIdQueue.pop(); + if (!mNextFrameTimelineInfoQueue.empty()) { + t->setFrameTimelineInfo(mSurfaceControl, mNextFrameTimelineInfoQueue.front()); + mNextFrameTimelineInfoQueue.pop(); } if (mAutoRefresh != bufferItem.mAutoRefresh) { @@ -514,8 +514,8 @@ public: return mBbq->setFrameRate(frameRate, compatibility, shouldBeSeamless); } - status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId) override { - return mBbq->setFrameTimelineVsync(frameTimelineVsyncId); + status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override { + return mBbq->setFrameTimelineInfo(frameTimelineInfo); } }; @@ -529,9 +529,9 @@ status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility, return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply(); } -status_t BLASTBufferQueue::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { +status_t BLASTBufferQueue::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) { std::unique_lock _lock{mMutex}; - mNextFrameTimelineVsyncIdQueue.push(frameTimelineVsyncId); + mNextFrameTimelineInfoQueue.push(frameTimelineInfo); return OK; } diff --git a/libs/gui/FrameTimelineInfo.cpp b/libs/gui/FrameTimelineInfo.cpp new file mode 100644 index 0000000000..f40077403a --- /dev/null +++ b/libs/gui/FrameTimelineInfo.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 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 "FrameTimelineInfo" + +#include + +#include +#include +#include +#include + +#include + +using android::os::IInputConstants; + +namespace android { + +status_t FrameTimelineInfo::write(Parcel& output) const { + SAFE_PARCEL(output.writeInt64, vsyncId); + SAFE_PARCEL(output.writeInt32, inputEventId); + return NO_ERROR; +} + +status_t FrameTimelineInfo::read(const Parcel& input) { + SAFE_PARCEL(input.readInt64, &vsyncId); + SAFE_PARCEL(input.readInt32, &inputEventId); + return NO_ERROR; +} + +void FrameTimelineInfo::merge(const FrameTimelineInfo& other) { + // When merging vsync Ids we take the oldest valid one + if (vsyncId != INVALID_VSYNC_ID && other.vsyncId != INVALID_VSYNC_ID) { + if (other.vsyncId > vsyncId) { + vsyncId = other.vsyncId; + inputEventId = other.inputEventId; + } + } else if (vsyncId == INVALID_VSYNC_ID) { + vsyncId = other.vsyncId; + inputEventId = other.inputEventId; + } +} + +void FrameTimelineInfo::clear() { + vsyncId = INVALID_VSYNC_ID; + inputEventId = IInputConstants::INVALID_INPUT_EVENT_ID; +} + +}; // namespace android diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index a8d6832275..f68f3e134e 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -68,16 +68,19 @@ public: return interface_cast(reply.readStrongBinder()); } - virtual status_t setTransactionState( - int64_t frameTimelineVsyncId, const Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, - const InputWindowCommands& commands, int64_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, - const std::vector& listenerCallbacks, uint64_t transactionId) { + status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo, + const Vector& state, + const Vector& displays, uint32_t flags, + const sp& applyToken, const InputWindowCommands& commands, + int64_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + const std::vector& listenerCallbacks, + uint64_t transactionId) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(data.writeInt64, frameTimelineVsyncId); + SAFE_PARCEL(frameTimelineInfo.write, data); + SAFE_PARCEL(data.writeUint32, static_cast(state.size())); for (const auto& s : state) { SAFE_PARCEL(s.write, data); @@ -108,15 +111,14 @@ public: return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } - virtual void bootFinished() - { + void bootFinished() override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t captureDisplay(const DisplayCaptureArgs& args, - const sp& captureListener) { + status_t captureDisplay(const DisplayCaptureArgs& args, + const sp& captureListener) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); SAFE_PARCEL(args.write, data); @@ -125,8 +127,8 @@ public: return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply); } - virtual status_t captureDisplay(uint64_t displayOrLayerStack, - const sp& captureListener) { + status_t captureDisplay(uint64_t displayOrLayerStack, + const sp& captureListener) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); SAFE_PARCEL(data.writeUint64, displayOrLayerStack); @@ -135,8 +137,8 @@ public: return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply); } - virtual status_t captureLayers(const LayerCaptureArgs& args, - const sp& captureListener) { + status_t captureLayers(const LayerCaptureArgs& args, + const sp& captureListener) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); SAFE_PARCEL(args.write, data); @@ -145,9 +147,8 @@ public: return remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); } - virtual bool authenticateSurfaceTexture( - const sp& bufferProducer) const - { + bool authenticateSurfaceTexture( + const sp& bufferProducer) const override { Parcel data, reply; int err = NO_ERROR; err = data.writeInterfaceToken( @@ -180,8 +181,7 @@ public: return result != 0; } - virtual status_t getSupportedFrameTimestamps( - std::vector* outSupported) const { + status_t getSupportedFrameTimestamps(std::vector* outSupported) const override { if (!outSupported) { return UNEXPECTED_NULL; } @@ -224,8 +224,8 @@ public: return NO_ERROR; } - virtual sp createDisplayEventConnection( - VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) { + sp createDisplayEventConnection( + VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) override { Parcel data, reply; sp result; int err = data.writeInterfaceToken( @@ -247,8 +247,7 @@ public: return result; } - virtual sp createDisplay(const String8& displayName, bool secure) - { + sp createDisplay(const String8& displayName, bool secure) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t status = data.writeString8(displayName); @@ -272,15 +271,14 @@ public: return display; } - virtual void destroyDisplay(const sp& display) - { + void destroyDisplay(const sp& display) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); remote()->transact(BnSurfaceComposer::DESTROY_DISPLAY, data, &reply); } - virtual std::vector getPhysicalDisplayIds() const { + std::vector getPhysicalDisplayIds() const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS, data, &reply) == @@ -297,7 +295,7 @@ public: return {}; } - virtual sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const { + sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeUint64(displayId.value); @@ -305,8 +303,7 @@ public: return reply.readStrongBinder(); } - virtual void setPowerMode(const sp& display, int mode) - { + void setPowerMode(const sp& display, int mode) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -314,7 +311,7 @@ public: remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply); } - virtual status_t getDisplayState(const sp& display, ui::DisplayState* state) { + status_t getDisplayState(const sp& display, ui::DisplayState* state) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -326,7 +323,7 @@ public: return result; } - virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info) { + status_t getDisplayInfo(const sp& display, DisplayInfo* info) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -336,7 +333,8 @@ public: return reply.read(*info); } - virtual status_t getDisplayConfigs(const sp& display, Vector* configs) { + status_t getDisplayConfigs(const sp& display, + Vector* configs) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -354,9 +352,7 @@ public: return result; } - virtual status_t getDisplayStats(const sp& display, - DisplayStatInfo* stats) - { + status_t getDisplayStats(const sp& display, DisplayStatInfo* stats) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -370,8 +366,7 @@ public: return result; } - virtual int getActiveConfig(const sp& display) - { + int getActiveConfig(const sp& display) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -379,8 +374,8 @@ public: return reply.readInt32(); } - virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) { + status_t getDisplayColorModes(const sp& display, + Vector* outColorModes) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -409,8 +404,8 @@ public: return result; } - virtual status_t getDisplayNativePrimaries(const sp& display, - ui::DisplayPrimaries& primaries) { + status_t getDisplayNativePrimaries(const sp& display, + ui::DisplayPrimaries& primaries) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -435,7 +430,7 @@ public: return result; } - virtual ColorMode getActiveColorMode(const sp& display) { + ColorMode getActiveColorMode(const sp& display) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -455,8 +450,7 @@ public: return static_cast(reply.readInt32()); } - virtual status_t setActiveColorMode(const sp& display, - ColorMode colorMode) { + status_t setActiveColorMode(const sp& display, ColorMode colorMode) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -481,8 +475,8 @@ public: return static_cast(reply.readInt32()); } - virtual status_t getAutoLowLatencyModeSupport(const sp& display, - bool* outSupport) const { + status_t getAutoLowLatencyModeSupport(const sp& display, + bool* outSupport) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t result = data.writeStrongBinder(display); @@ -499,7 +493,7 @@ public: return reply.readBool(outSupport); } - virtual void setAutoLowLatencyMode(const sp& display, bool on) { + void setAutoLowLatencyMode(const sp& display, bool on) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -524,7 +518,8 @@ public: } } - virtual status_t getGameContentTypeSupport(const sp& display, bool* outSupport) const { + status_t getGameContentTypeSupport(const sp& display, + bool* outSupport) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t result = data.writeStrongBinder(display); @@ -540,7 +535,7 @@ public: return reply.readBool(outSupport); } - virtual void setGameContentType(const sp& display, bool on) { + void setGameContentType(const sp& display, bool on) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -563,7 +558,7 @@ public: } } - virtual status_t clearAnimationFrameStats() { + status_t clearAnimationFrameStats() override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -578,7 +573,7 @@ public: return reply.readInt32(); } - virtual status_t getAnimationFrameStats(FrameStats* outStats) const { + status_t getAnimationFrameStats(FrameStats* outStats) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::GET_ANIMATION_FRAME_STATS, data, &reply); @@ -586,8 +581,8 @@ public: return reply.readInt32(); } - virtual status_t getHdrCapabilities(const sp& display, - HdrCapabilities* outCapabilities) const { + status_t getHdrCapabilities(const sp& display, + HdrCapabilities* outCapabilities) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t result = data.writeStrongBinder(display); @@ -608,7 +603,7 @@ public: return result; } - virtual status_t enableVSyncInjections(bool enable) { + status_t enableVSyncInjections(bool enable) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -629,7 +624,7 @@ public: return result; } - virtual status_t injectVSync(nsecs_t when) { + status_t injectVSync(nsecs_t when) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -650,7 +645,7 @@ public: return result; } - virtual status_t getLayerDebugInfo(std::vector* outLayers) { + status_t getLayerDebugInfo(std::vector* outLayers) override { if (!outLayers) { return UNEXPECTED_NULL; } @@ -680,10 +675,10 @@ public: return reply.readParcelableVector(outLayers); } - virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace, - ui::PixelFormat* defaultPixelFormat, - ui::Dataspace* wideColorGamutDataspace, - ui::PixelFormat* wideColorGamutPixelFormat) const { + status_t getCompositionPreference(ui::Dataspace* defaultDataspace, + ui::PixelFormat* defaultPixelFormat, + ui::Dataspace* wideColorGamutDataspace, + ui::PixelFormat* wideColorGamutPixelFormat) const override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -703,7 +698,7 @@ public: return error; } - virtual status_t getColorManagement(bool* outGetColorManagement) const { + status_t getColorManagement(bool* outGetColorManagement) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::GET_COLOR_MANAGEMENT, data, &reply); @@ -715,10 +710,10 @@ public: return err; } - virtual status_t getDisplayedContentSamplingAttributes(const sp& display, - ui::PixelFormat* outFormat, - ui::Dataspace* outDataspace, - uint8_t* outComponentMask) const { + status_t getDisplayedContentSamplingAttributes(const sp& display, + ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask) const override { if (!outFormat || !outDataspace || !outComponentMask) return BAD_VALUE; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -752,8 +747,8 @@ public: return error; } - virtual status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, - uint8_t componentMask, uint64_t maxFrames) { + status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, + uint8_t componentMask, uint64_t maxFrames) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -766,9 +761,9 @@ public: return result; } - virtual status_t getDisplayedContentSample(const sp& display, uint64_t maxFrames, - uint64_t timestamp, - DisplayedFrameStats* outStats) const { + status_t getDisplayedContentSample(const sp& display, uint64_t maxFrames, + uint64_t timestamp, + DisplayedFrameStats* outStats) const override { if (!outStats) return BAD_VALUE; Parcel data, reply; @@ -805,7 +800,7 @@ public: return result; } - virtual status_t getProtectedContentSupport(bool* outSupported) const { + status_t getProtectedContentSupport(bool* outSupported) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t error = @@ -817,8 +812,8 @@ public: return error; } - virtual status_t isWideColorDisplay(const sp& token, - bool* outIsWideColorDisplay) const { + status_t isWideColorDisplay(const sp& token, + bool* outIsWideColorDisplay) const override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -837,9 +832,8 @@ public: return error; } - virtual status_t addRegionSamplingListener(const Rect& samplingArea, - const sp& stopLayerHandle, - const sp& listener) { + status_t addRegionSamplingListener(const Rect& samplingArea, const sp& stopLayerHandle, + const sp& listener) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -868,7 +862,7 @@ public: return error; } - virtual status_t removeRegionSamplingListener(const sp& listener) { + status_t removeRegionSamplingListener(const sp& listener) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -888,12 +882,11 @@ public: return error; } - virtual status_t setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, bool allowGroupSwitching, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { + status_t setDesiredDisplayConfigSpecs(const sp& displayToken, int32_t defaultConfig, + bool allowGroupSwitching, float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -947,13 +940,12 @@ public: return reply.readInt32(); } - virtual status_t getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, - bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) { + status_t getDesiredDisplayConfigSpecs(const sp& displayToken, + int32_t* outDefaultConfig, bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) override { if (!outDefaultConfig || !outAllowGroupSwitching || !outPrimaryRefreshRateMin || !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { @@ -1011,8 +1003,8 @@ public: return reply.readInt32(); } - virtual status_t getDisplayBrightnessSupport(const sp& displayToken, - bool* outSupport) const { + status_t getDisplayBrightnessSupport(const sp& displayToken, + bool* outSupport) const override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -1039,7 +1031,7 @@ public: return NO_ERROR; } - virtual status_t setDisplayBrightness(const sp& displayToken, float brightness) { + status_t setDisplayBrightness(const sp& displayToken, float brightness) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -1064,7 +1056,7 @@ public: return NO_ERROR; } - virtual status_t notifyPowerBoost(int32_t boostId) { + status_t notifyPowerBoost(int32_t boostId) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -1085,8 +1077,8 @@ public: return NO_ERROR; } - virtual status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, - float lightPosY, float lightPosZ, float lightRadius) { + status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, + float lightPosY, float lightPosZ, float lightRadius) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -1114,8 +1106,8 @@ public: return NO_ERROR; } - virtual status_t setFrameRate(const sp& surface, float frameRate, - int8_t compatibility, bool shouldBeSeamless) { + status_t setFrameRate(const sp& surface, float frameRate, + int8_t compatibility, bool shouldBeSeamless) override { Parcel data, reply; status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (err != NO_ERROR) { @@ -1156,7 +1148,7 @@ public: return reply.readInt32(); } - virtual status_t acquireFrameRateFlexibilityToken(sp* outToken) { + status_t acquireFrameRateFlexibilityToken(sp* outToken) override { if (!outToken) return BAD_VALUE; Parcel data, reply; @@ -1191,40 +1183,34 @@ public: return NO_ERROR; } - virtual status_t setFrameTimelineVsync(const sp& surface, - int64_t frameTimelineVsyncId) { + status_t setFrameTimelineInfo(const sp& surface, + const FrameTimelineInfo& frameTimelineInfo) override { Parcel data, reply; status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed writing interface token: %s (%d)", strerror(-err), - -err); + ALOGE("%s: failed writing interface token: %s (%d)", __func__, strerror(-err), -err); return err; } err = data.writeStrongBinder(IInterface::asBinder(surface)); if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed writing strong binder: %s (%d)", strerror(-err), - -err); + ALOGE("%s: failed writing strong binder: %s (%d)", __func__, strerror(-err), -err); return err; } - err = data.writeInt64(frameTimelineVsyncId); - if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed writing int64_t: %s (%d)", strerror(-err), -err); - return err; - } + SAFE_PARCEL(frameTimelineInfo.write, data); - err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_VSYNC, data, &reply); + err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_INFO, data, &reply); if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed to transact: %s (%d)", strerror(-err), err); + ALOGE("%s: failed to transact: %s (%d)", __func__, strerror(-err), err); return err; } return reply.readInt32(); } - virtual status_t addTransactionTraceListener( - const sp& listener) { + status_t addTransactionTraceListener( + const sp& listener) override { Parcel data, reply; SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); @@ -1235,7 +1221,7 @@ public: /** * Get priority of the RenderEngine in surface flinger. */ - virtual int getGPUContextPriority() { + int getGPUContextPriority() override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t err = @@ -1269,8 +1255,9 @@ status_t BnSurfaceComposer::onTransact( case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - int64_t frameTimelineVsyncId; - SAFE_PARCEL(data.readInt64, &frameTimelineVsyncId); + FrameTimelineInfo frameTimelineInfo; + SAFE_PARCEL(frameTimelineInfo.read, data); + uint32_t count = 0; SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); Vector state; @@ -1324,10 +1311,10 @@ status_t BnSurfaceComposer::onTransact( uint64_t transactionId = -1; SAFE_PARCEL(data.readUint64, &transactionId); - return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags, - applyToken, inputWindowCommands, desiredPresentTime, - isAutoTimestamp, uncachedBuffer, hasListenerCallbacks, - listenerCallbacks, transactionId); + return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken, + inputWindowCommands, desiredPresentTime, isAutoTimestamp, + uncachedBuffer, hasListenerCallbacks, listenerCallbacks, + transactionId); } case BOOT_FINISHED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); @@ -2078,30 +2065,26 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } - case SET_FRAME_TIMELINE_VSYNC: { + case SET_FRAME_TIMELINE_INFO: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp binder; status_t err = data.readStrongBinder(&binder); if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed to read strong binder: %s (%d)", - strerror(-err), -err); + ALOGE("setFrameTimelineInfo: failed to read strong binder: %s (%d)", strerror(-err), + -err); return err; } sp surface = interface_cast(binder); if (!surface) { - ALOGE("setFrameTimelineVsync: failed to cast to IGraphicBufferProducer: %s (%d)", + ALOGE("setFrameTimelineInfo: failed to cast to IGraphicBufferProducer: %s (%d)", strerror(-err), -err); return err; } - int64_t frameTimelineVsyncId; - err = data.readInt64(&frameTimelineVsyncId); - if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed to read int64_t: %s (%d)", strerror(-err), - -err); - return err; - } - status_t result = setFrameTimelineVsync(surface, frameTimelineVsyncId); + FrameTimelineInfo frameTimelineInfo; + SAFE_PARCEL(frameTimelineInfo.read, data); + + status_t result = setFrameTimelineInfo(surface, frameTimelineInfo); reply->writeInt32(result); return NO_ERROR; } diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 180857185c..0ded9361bf 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -92,10 +92,8 @@ status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { return err; } -JankData::JankData() : - frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), - jankType(JankType::None) { -} +JankData::JankData() + : frameVsyncId(FrameTimelineInfo::INVALID_VSYNC_ID), jankType(JankType::None) {} status_t JankData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, frameVsyncId); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e5e10a0014..2aac87c9d0 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -63,7 +63,7 @@ layer_state_t::layer_state_t() shouldBeSeamless(true), fixedTransformHint(ui::Transform::ROT_INVALID), frameNumber(0), - frameTimelineVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), + frameTimelineInfo(), autoRefresh(false) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; @@ -151,7 +151,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeBool, shouldBeSeamless); SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeUint64, frameNumber); - SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId); + SAFE_PARCEL(frameTimelineInfo.write, output); SAFE_PARCEL(output.writeBool, autoRefresh); SAFE_PARCEL(output.writeUint32, blurRegions.size()); @@ -272,7 +272,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); SAFE_PARCEL(input.readUint64, &frameNumber); - SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId); + SAFE_PARCEL(frameTimelineInfo.read, input); SAFE_PARCEL(input.readBool, &autoRefresh); uint32_t numRegions = 0; @@ -539,15 +539,9 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFrameNumberChanged; frameNumber = other.frameNumber; } - if (other.what & eFrameTimelineVsyncChanged) { - // When merging vsync Ids we take the oldest valid one - if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID && - other.frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) { - frameTimelineVsyncId = std::max(frameTimelineVsyncId, other.frameTimelineVsyncId); - } else if (frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) { - frameTimelineVsyncId = other.frameTimelineVsyncId; - } - what |= eFrameTimelineVsyncChanged; + if (other.what & eFrameTimelineInfoChanged) { + what |= eFrameTimelineInfoChanged; + frameTimelineInfo.merge(other.frameTimelineInfo); } if (other.what & eAutoRefreshChanged) { what |= eAutoRefreshChanged; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e82f0cc9e9..59ad8d28bd 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1496,8 +1496,8 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER: res = dispatchGetLastQueuedBuffer(args); break; - case NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC: - res = dispatchSetFrameTimelineVsync(args); + case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO: + res = dispatchSetFrameTimelineInfo(args); break; default: res = NAME_NOT_FOUND; @@ -1806,12 +1806,13 @@ int Surface::dispatchGetLastQueuedBuffer(va_list args) { return result; } -int Surface::dispatchSetFrameTimelineVsync(va_list args) { +int Surface::dispatchSetFrameTimelineInfo(va_list args) { ATRACE_CALL(); auto frameTimelineVsyncId = static_cast(va_arg(args, int64_t)); + auto inputEventId = static_cast(va_arg(args, int32_t)); - ALOGV("Surface::dispatchSetFrameTimelineVsync"); - return setFrameTimelineVsync(frameTimelineVsyncId); + ALOGV("Surface::%s", __func__); + return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId}); } bool Surface::transformToDisplayInverse() { @@ -2579,9 +2580,8 @@ status_t Surface::setFrameRate(float frameRate, int8_t compatibility, bool shoul shouldBeSeamless); } -status_t Surface::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { - return composerService()->setFrameTimelineVsync(mGraphicBufferProducer, - frameTimelineVsyncId); +status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) { + return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo); } }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 78f655a71b..7de256d09c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -396,7 +396,7 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mContainsBuffer(other.mContainsBuffer), mDesiredPresentTime(other.mDesiredPresentTime), mIsAutoTimestamp(other.mIsAutoTimestamp), - mFrameTimelineVsyncId(other.mFrameTimelineVsyncId), + mFrameTimelineInfo(other.mFrameTimelineInfo), mApplyToken(other.mApplyToken) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; @@ -427,7 +427,9 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel const bool containsBuffer = parcel->readBool(); const int64_t desiredPresentTime = parcel->readInt64(); const bool isAutoTimestamp = parcel->readBool(); - const int64_t frameTimelineVsyncId = parcel->readInt64(); + FrameTimelineInfo frameTimelineInfo; + SAFE_PARCEL(frameTimelineInfo.read, *parcel); + sp applyToken; parcel->readNullableStrongBinder(&applyToken); size_t count = static_cast(parcel->readUint32()); @@ -502,7 +504,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel mContainsBuffer = containsBuffer; mDesiredPresentTime = desiredPresentTime; mIsAutoTimestamp = isAutoTimestamp; - mFrameTimelineVsyncId = frameTimelineVsyncId; + mFrameTimelineInfo = frameTimelineInfo; mDisplayStates = displayStates; mListenerCallbacks = listenerCallbacks; mComposerStates = composerStates; @@ -534,7 +536,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const parcel->writeBool(mContainsBuffer); parcel->writeInt64(mDesiredPresentTime); parcel->writeBool(mIsAutoTimestamp); - parcel->writeInt64(mFrameTimelineVsyncId); + SAFE_PARCEL(mFrameTimelineInfo.write, *parcel); parcel->writeStrongBinder(mApplyToken); parcel->writeUint32(static_cast(mDisplayStates.size())); for (auto const& displayState : mDisplayStates) { @@ -613,13 +615,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mExplicitEarlyWakeupEnd = mExplicitEarlyWakeupEnd || other.mExplicitEarlyWakeupEnd; mApplyToken = other.mApplyToken; - // When merging vsync Ids we take the oldest one - if (mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID && - other.mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) { - mFrameTimelineVsyncId = std::max(mFrameTimelineVsyncId, other.mFrameTimelineVsyncId); - } else if (mFrameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) { - mFrameTimelineVsyncId = other.mFrameTimelineVsyncId; - } + mFrameTimelineInfo.merge(other.mFrameTimelineInfo); other.clear(); return *this; @@ -639,7 +635,7 @@ void SurfaceComposerClient::Transaction::clear() { mExplicitEarlyWakeupEnd = false; mDesiredPresentTime = 0; mIsAutoTimestamp = true; - mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + mFrameTimelineInfo.clear(); mApplyToken = nullptr; } @@ -651,9 +647,8 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.id = cacheId; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {}, - systemTime(), true, uncacheBuffer, false, {}, - 0 /* Undefined transactionId */); + sf->setTransactionState(FrameTimelineInfo{}, {}, {}, 0, applyToken, {}, systemTime(), true, + uncacheBuffer, false, {}, 0 /* Undefined transactionId */); } void SurfaceComposerClient::Transaction::cacheBuffers() { @@ -773,7 +768,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { ? mApplyToken : IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken, + sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken, mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp, {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/, hasListenerCallbacks, listenerCallbacks, mId); @@ -1548,22 +1543,22 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixed return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync( - int64_t frameTimelineVsyncId) { - mFrameTimelineVsyncId = frameTimelineVsyncId; +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo( + const FrameTimelineInfo& frameTimelineInfo) { + mFrameTimelineInfo = frameTimelineInfo; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync( - const sp& sc, int64_t frameTimelineVsyncId) { +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo( + const sp& sc, const FrameTimelineInfo& frameTimelineInfo) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eFrameTimelineVsyncChanged; - s->frameTimelineVsyncId = frameTimelineVsyncId; + s->what |= layer_state_t::eFrameTimelineInfoChanged; + s->frameTimelineInfo = frameTimelineInfo; return *this; } diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index 411526eeb3..59c400a79e 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -92,7 +92,7 @@ public: void flushShadowQueue() { mFlushShadowQueue = true; } status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); - status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId); + status_t setFrameTimelineInfo(const FrameTimelineInfo& info); virtual ~BLASTBufferQueue(); @@ -156,7 +156,7 @@ private: // This is only relevant for shared buffer mode. bool mAutoRefresh GUARDED_BY(mMutex) = false; - std::queue mNextFrameTimelineVsyncIdQueue GUARDED_BY(mMutex); + std::queue mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); // Last acquired buffer's scaling mode. This is used to check if we should update the blast // layer size immediately or wait until we get the next buffer. This will support scenarios diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index 5587acf08f..f446dd88ed 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -25,7 +25,7 @@ struct VsyncEventData { // The Vsync Id corresponsing to this vsync event. This will be used to // populate ISurfaceComposer::setFrameTimelineVsync and // SurfaceComposerClient::setFrameTimelineVsync - int64_t id = ISurfaceComposer::INVALID_VSYNC_ID; + int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID; // The deadline in CLOCK_MONOTONIC that the app needs to complete its // frame by (both on the CPU and the GPU) diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h new file mode 100644 index 0000000000..3b4c009609 --- /dev/null +++ b/libs/gui/include/gui/FrameTimelineInfo.h @@ -0,0 +1,43 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +namespace android { + +struct FrameTimelineInfo { + // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java + static constexpr int64_t INVALID_VSYNC_ID = -1; + + // The vsync id that was used to start the transaction + int64_t vsyncId = INVALID_VSYNC_ID; + + // The id of the input event that caused this buffer + int32_t inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID; + + status_t write(Parcel& output) const; + status_t read(const Parcel& input); + + void merge(const FrameTimelineInfo& other); + void clear(); +}; + +} // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 86f3c605ab..81ff6b0d8d 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -117,9 +118,6 @@ public: using EventRegistrationFlags = Flags; - // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java - static constexpr int64_t INVALID_VSYNC_ID = -1; - /* * Create a connection with SurfaceFlinger. */ @@ -164,7 +162,7 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t setTransactionState( - int64_t frameTimelineVsyncId, const Vector& state, + const FrameTimelineInfo& frameTimelineInfo, const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, @@ -494,11 +492,11 @@ public: virtual status_t acquireFrameRateFlexibilityToken(sp* outToken) = 0; /* - * Sets the frame timeline vsync id received from choreographer that corresponds to next + * Sets the frame timeline vsync info received from choreographer that corresponds to next * buffer submitted on that surface. */ - virtual status_t setFrameTimelineVsync(const sp& surface, - int64_t frameTimelineVsyncId) = 0; + virtual status_t setFrameTimelineInfo(const sp& surface, + const FrameTimelineInfo& frameTimelineInfo) = 0; /* * Adds a TransactionTraceListener to listen for transaction tracing state updates. @@ -569,7 +567,7 @@ public: SET_GAME_CONTENT_TYPE, SET_FRAME_RATE, ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, - SET_FRAME_TIMELINE_VSYNC, + SET_FRAME_TIMELINE_INFO, ADD_TRANSACTION_TRACE_LISTENER, GET_GPU_CONTEXT_PRIORITY, // Always append new enum to the end. diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 83a9d3356e..800f86ee92 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -128,7 +128,7 @@ struct layer_state_t { eProducerDisconnect = 0x100'00000000, eFixedTransformHintChanged = 0x200'00000000, eFrameNumberChanged = 0x400'00000000, - eFrameTimelineVsyncChanged = 0x800'00000000, + eFrameTimelineInfoChanged = 0x800'00000000, eBlurRegionsChanged = 0x1000'00000000, eAutoRefreshChanged = 0x2000'00000000, }; @@ -234,7 +234,7 @@ struct layer_state_t { // graphics producer. uint64_t frameNumber; - int64_t frameTimelineVsyncId; + FrameTimelineInfo frameTimelineInfo; // Indicates that the consumer should acquire the next frame as soon as it // can and not wait for a frame to become available. This is only relevant diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 43b5dcd60d..b6b5c7ca5e 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -18,6 +18,7 @@ #define ANDROID_GUI_SURFACE_H #include +#include #include #include #include @@ -187,7 +188,7 @@ public: status_t getConsumerUsage(uint64_t* outUsage) const; virtual status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); - virtual status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId); + virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info); protected: virtual ~Surface(); @@ -273,7 +274,7 @@ private: int dispatchAddQueueInterceptor(va_list args); int dispatchAddQueryInterceptor(va_list args); int dispatchGetLastQueuedBuffer(va_list args); - int dispatchSetFrameTimelineVsync(va_list args); + int dispatchSetFrameTimelineInfo(va_list args); bool transformToDisplayInverse(); protected: diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 11db658de2..bed5c44110 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -385,8 +385,8 @@ public: int64_t mDesiredPresentTime = 0; bool mIsAutoTimestamp = true; - // The vsync Id provided by Choreographer.getVsyncId - int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + // The vsync id provided by Choreographer.getVsyncId and the input event id + FrameTimelineInfo mFrameTimelineInfo; // If not null, transactions will be queued up using this token otherwise a common token // per process will be used. @@ -546,11 +546,12 @@ public: Transaction& setFixedTransformHint(const sp& sc, int32_t transformHint); // Sets the frame timeline vsync id received from choreographer that corresponds - // to the transaction. - Transaction& setFrameTimelineVsync(int64_t frameTimelineVsyncId); + // to the transaction, and the input event id that identifies the input event that caused + // the current frame. + Transaction& setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo); // Variant that only applies to a specific SurfaceControl. - Transaction& setFrameTimelineVsync(const sp& sc, - int64_t frameTimelineVsyncId); + Transaction& setFrameTimelineInfo(const sp& sc, + const FrameTimelineInfo& frameTimelineInfo); // Indicates that the consumer should acquire the next frame as soon as it // can and not wait for a frame to become available. This is only relevant diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 63db9a7b96..3f7a5b1785 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -695,7 +695,7 @@ public: void destroyDisplay(const sp& /*display */) override {} std::vector getPhysicalDisplayIds() const override { return {}; } sp getPhysicalDisplayToken(PhysicalDisplayId) const override { return nullptr; } - status_t setTransactionState(int64_t /*frameTimelineVsyncId*/, + status_t setTransactionState(const FrameTimelineInfo& /*frameTimelineInfo*/, const Vector& /*state*/, const Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, @@ -877,8 +877,8 @@ public: return NO_ERROR; } - status_t setFrameTimelineVsync(const sp& /*surface*/, - int64_t /*frameTimelineVsyncId*/) override { + status_t setFrameTimelineInfo(const sp& /*surface*/, + const FrameTimelineInfo& /*frameTimelineInfo*/) override { return NO_ERROR; } diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl index c69a53a784..bce0ec8367 100644 --- a/libs/input/android/os/IInputConstants.aidl +++ b/libs/input/android/os/IInputConstants.aidl @@ -31,4 +31,10 @@ interface IInputConstants // Indicate invalid battery capacity const int INVALID_BATTERY_CAPACITY = -1; + + /** + * Every input event has an id. This constant value is used when a valid input event id is not + * available. + */ + const int INVALID_INPUT_EVENT_ID = 0; } diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 82d2e661b4..ffe4412b72 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -255,7 +255,7 @@ enum { NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */ NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */ NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */ - NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC = 48, /* private */ + NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO = 48, /* private */ // clang-format on }; @@ -1023,10 +1023,11 @@ static inline int native_window_set_frame_rate(struct ANativeWindow* window, flo (int)compatibility, (int)shouldBeSeamless); } -static inline int native_window_set_frame_timeline_vsync(struct ANativeWindow* window, - int64_t frameTimelineVsyncId) { - return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC, - frameTimelineVsyncId); +static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window, + int64_t frameTimelineVsyncId, + int32_t inputEventId) { + return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO, + frameTimelineVsyncId, inputEventId); } // ------------------------------------------------------------------------------------------------ diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 32e6b1098f..52197873c5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -384,8 +384,8 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) { - mFrameTimelineVsyncId = frameTimelineVsyncId; +void BufferQueueLayer::setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) { + mFrameTimelineInfo = frameTimelineInfo; } // ----------------------------------------------------------------------- @@ -445,9 +445,8 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { } auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, - mOwnerPid, mOwnerUid, mName, - mName); + mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, + mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems.push_back({item, surfaceFrame}); @@ -485,9 +484,8 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { } auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, - mOwnerPid, mOwnerUid, mName, - mName); + mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, + mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems[mQueueItems.size() - 1].item = item; mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 0e8fdbe092..41ff01262e 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -101,7 +101,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) override; + void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) override; sp createClone() override; @@ -145,10 +145,10 @@ private: sp mContentsChangedListener; - // The last vsync id received on this layer. This will be used when we get + // The last vsync info received on this layer. This will be used when we get // a buffer to correlate the buffer with the vsync id. Can only be accessed // with the SF state lock held. - std::optional mFrameTimelineVsyncId; + FrameTimelineInfo mFrameTimelineInfo; // Keeps track of the time SF latched the last buffer from this layer. // Used in buffer stuffing analysis in FrameTimeline. diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index 17d1f3bff7..3743716876 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -275,13 +275,15 @@ int64_t TraceCookieCounter::getCookieForTracing() { return ++mTraceCookie; } -SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName, - std::string debugName, PredictionState predictionState, +SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, + uid_t ownerUid, std::string layerName, std::string debugName, + PredictionState predictionState, frametimeline::TimelineItem&& predictions, std::shared_ptr timeStats, JankClassificationThresholds thresholds, TraceCookieCounter* traceCookieCounter) - : mToken(token), + : mToken(frameTimelineInfo.vsyncId), + mInputEventId(frameTimelineInfo.inputEventId), mOwnerPid(ownerPid), mOwnerUid(ownerUid), mLayerName(std::move(layerName)), @@ -295,27 +297,27 @@ SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::s mTraceCookieCounter(*traceCookieCounter) {} void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mActuals.startTime = actualStartTime; } void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mActualQueueTime = actualQueueTime; } void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime); } void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mPresentState = presentState; mLastLatchTime = lastLatchTime; } std::optional SurfaceFrame::getJankType() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); if (mActuals.presentTime == 0) { return std::nullopt; } @@ -323,32 +325,32 @@ std::optional SurfaceFrame::getJankType() const { } nsecs_t SurfaceFrame::getBaseTime() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return getMinTime(mPredictionState, mPredictions, mActuals); } TimelineItem SurfaceFrame::getActuals() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return mActuals; } SurfaceFrame::PresentState SurfaceFrame::getPresentState() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return mPresentState; } FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return mFramePresentMetadata; } FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return mFrameReadyMetadata; } void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); StringAppendF(&result, "%s", indent.c_str()); StringAppendF(&result, "Layer - %s", mDebugName.c_str()); if (mJankType != JankType::None) { @@ -387,7 +389,7 @@ void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, nsecs_t vsyncPeriod) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); if (mPresentState != PresentState::Presented) { // No need to update dropped buffers return; @@ -479,6 +481,9 @@ void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, mTimeStats->incrementJankyFrames(mOwnerUid, mLayerName, mJankType); } +/** + * TODO(b/178637512): add inputEventId to the perfetto trace. + */ void SurfaceFrame::trace(int64_t displayFrameToken) { using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource; @@ -486,12 +491,12 @@ void SurfaceFrame::trace(int64_t displayFrameToken) { bool missingToken = false; // Expected timeline start FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { - std::lock_guard lock(mMutex); - if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) { + std::scoped_lock lock(mMutex); + if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) { ALOGD("Cannot trace SurfaceFrame - %s with invalid token", mLayerName.c_str()); missingToken = true; return; - } else if (displayFrameToken == ISurfaceComposer::INVALID_VSYNC_ID) { + } else if (displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) { ALOGD("Cannot trace SurfaceFrame - %s with invalid displayFrameToken", mLayerName.c_str()); missingToken = true; @@ -521,7 +526,7 @@ void SurfaceFrame::trace(int64_t displayFrameToken) { // Expected timeline end FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); auto packet = ctx.NewTracePacket(); packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); packet->set_timestamp(static_cast(mPredictions.endTime)); @@ -535,7 +540,7 @@ void SurfaceFrame::trace(int64_t displayFrameToken) { int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing(); // Actual timeline start FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); auto packet = ctx.NewTracePacket(); packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); // Actual start time is not yet available, so use expected start instead @@ -566,7 +571,7 @@ void SurfaceFrame::trace(int64_t displayFrameToken) { }); // Actual timeline end FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); auto packet = ctx.NewTracePacket(); packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); packet->set_timestamp(static_cast(mActuals.endTime)); @@ -582,7 +587,7 @@ namespace impl { int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) { ATRACE_CALL(); - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); const int64_t assignedToken = mCurrentToken++; mPredictions[assignedToken] = {systemTime(), predictions}; flushTokens(systemTime()); @@ -590,7 +595,7 @@ int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) { } std::optional TokenManager::getPredictionsForToken(int64_t token) const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); auto predictionsIterator = mPredictions.find(token); if (predictionsIterator != mPredictions.end()) { return predictionsIterator->second.predictions; @@ -634,26 +639,28 @@ void FrameTimeline::registerDataSource() { } std::shared_ptr FrameTimeline::createSurfaceFrameForToken( - std::optional token, pid_t ownerPid, uid_t ownerUid, std::string layerName, - std::string debugName) { + const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + std::string layerName, std::string debugName) { ATRACE_CALL(); - if (!token) { - return std::make_shared(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid, - ownerUid, std::move(layerName), std::move(debugName), + if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) { + return std::make_shared(frameTimelineInfo, ownerPid, ownerUid, + std::move(layerName), std::move(debugName), PredictionState::None, TimelineItem(), mTimeStats, mJankClassificationThresholds, &mTraceCookieCounter); } - std::optional predictions = mTokenManager.getPredictionsForToken(*token); + std::optional predictions = + mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId); if (predictions) { - return std::make_shared(*token, ownerPid, ownerUid, std::move(layerName), - std::move(debugName), PredictionState::Valid, - std::move(*predictions), mTimeStats, - mJankClassificationThresholds, &mTraceCookieCounter); - } - return std::make_shared(*token, ownerPid, ownerUid, std::move(layerName), - std::move(debugName), PredictionState::Expired, - TimelineItem(), mTimeStats, mJankClassificationThresholds, - &mTraceCookieCounter); + return std::make_shared(frameTimelineInfo, ownerPid, ownerUid, + std::move(layerName), std::move(debugName), + PredictionState::Valid, std::move(*predictions), + mTimeStats, mJankClassificationThresholds, + &mTraceCookieCounter); + } + return std::make_shared(frameTimelineInfo, ownerPid, ownerUid, + std::move(layerName), std::move(debugName), + PredictionState::Expired, TimelineItem(), mTimeStats, + mJankClassificationThresholds, &mTraceCookieCounter); } FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr timeStats, @@ -669,13 +676,13 @@ FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr timeStats, void FrameTimeline::addSurfaceFrame(std::shared_ptr surfaceFrame) { ATRACE_CALL(); - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame); } void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsyncPeriod) { ATRACE_CALL(); - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mCurrentDisplayFrame->onSfWakeUp(token, vsyncPeriod, mTokenManager.getPredictionsForToken(token), wakeUpTime); } @@ -683,7 +690,7 @@ void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsync void FrameTimeline::setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr& presentFence) { ATRACE_CALL(); - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mCurrentDisplayFrame->setActualEndTime(sfPresentTime); mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame)); flushPendingPresentFences(); @@ -826,7 +833,7 @@ void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const { // Expected timeline start FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { auto packet = ctx.NewTracePacket(); - if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) { + if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) { ALOGD("Cannot trace DisplayFrame with invalid token"); missingToken = true; return; @@ -999,7 +1006,7 @@ void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) co } void FrameTimeline::dumpAll(std::string& result) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size()); nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime(); for (size_t i = 0; i < mDisplayFrames.size(); i++) { @@ -1009,7 +1016,7 @@ void FrameTimeline::dumpAll(std::string& result) { } void FrameTimeline::dumpJank(std::string& result) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime(); for (size_t i = 0; i < mDisplayFrames.size(); i++) { mDisplayFrames[i]->dumpJank(result, baseTime, static_cast(i)); @@ -1031,7 +1038,7 @@ void FrameTimeline::parseArgs(const Vector& args, std::string& result) } void FrameTimeline::setMaxDisplayFrames(uint32_t size) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); // The size can either increase or decrease, clear everything, to be consistent mDisplayFrames.clear(); diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h index ed38cc6375..54e8efbc92 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h @@ -154,10 +154,10 @@ public: // Only FrameTimeline can construct a SurfaceFrame as it provides Predictions(through // TokenManager), Thresholds and TimeStats pointer. - SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName, - std::string debugName, PredictionState predictionState, TimelineItem&& predictions, - std::shared_ptr timeStats, JankClassificationThresholds thresholds, - TraceCookieCounter* traceCookieCounter); + SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + std::string layerName, std::string debugName, PredictionState predictionState, + TimelineItem&& predictions, std::shared_ptr timeStats, + JankClassificationThresholds thresholds, TraceCookieCounter* traceCookieCounter); ~SurfaceFrame() = default; // Returns std::nullopt if the frame hasn't been classified yet. @@ -166,6 +166,7 @@ public: // Functions called by SF int64_t getToken() const { return mToken; }; + int32_t getInputEventId() const { return mInputEventId; }; TimelineItem getPredictions() const { return mPredictions; }; // Actual timestamps of the app are set individually at different functions. // Start time (if the app provides) and Queue time are accessible after queueing the frame, @@ -198,6 +199,7 @@ public: private: const int64_t mToken; + const int32_t mInputEventId; const pid_t mOwnerPid; const uid_t mOwnerUid; const std::string mLayerName; @@ -243,10 +245,9 @@ public: // Create a new surface frame, set the predictions based on a token and return it to the caller. // Debug name is the human-readable debugging string for dumpsys. - virtual std::shared_ptr createSurfaceFrameForToken(std::optional token, - pid_t ownerPid, uid_t ownerUid, - std::string layerName, - std::string debugName) = 0; + virtual std::shared_ptr createSurfaceFrameForToken( + const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + std::string layerName, std::string debugName) = 0; // Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be // composited into one display frame. @@ -279,7 +280,7 @@ namespace impl { class TokenManager : public android::frametimeline::TokenManager { public: - TokenManager() : mCurrentToken(ISurfaceComposer::INVALID_VSYNC_ID + 1) {} + TokenManager() : mCurrentToken(FrameTimelineInfo::INVALID_VSYNC_ID + 1) {} ~TokenManager() = default; int64_t generateTokenForPredictions(TimelineItem&& predictions) override; @@ -353,7 +354,7 @@ public: private: void dump(std::string& result, nsecs_t baseTime) const; - int64_t mToken = ISurfaceComposer::INVALID_VSYNC_ID; + int64_t mToken = FrameTimelineInfo::INVALID_VSYNC_ID; /* Usage of TimelineItem w.r.t SurfaceFlinger * startTime Time when SurfaceFlinger wakes up to handle transactions and buffer updates @@ -393,10 +394,9 @@ public: ~FrameTimeline() = default; frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; } - std::shared_ptr createSurfaceFrameForToken(std::optional token, - pid_t ownerPid, uid_t ownerUid, - std::string layerName, - std::string debugName) override; + std::shared_ptr createSurfaceFrameForToken( + const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + std::string layerName, std::string debugName) override; void addSurfaceFrame(std::shared_ptr surfaceFrame) override; void setSfWakeUp(int64_t token, nsecs_t wakeupTime, nsecs_t vsyncPeriod) override; void setSfPresent(nsecs_t sfPresentTime, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 66ce3f1a44..aeaa7e2d67 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -129,7 +129,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.shadowRadius = 0.f; mCurrentState.treeHasFrameRateVote = false; mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID; - mCurrentState.frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + mCurrentState.frameTimelineInfo = {}; mCurrentState.postTime = -1; if (args.flags & ISurfaceComposerClient::eNoColorFill) { @@ -907,14 +907,10 @@ bool Layer::applyPendingStates(State* stateToCommit) { } if (stateUpdateAvailable) { - const auto vsyncId = - stateToCommit->frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID - ? std::nullopt - : std::make_optional(stateToCommit->frameTimelineVsyncId); - mSurfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(vsyncId, mOwnerPid, mOwnerUid, - mName, mTransactionName); + mFlinger->mFrameTimeline + ->createSurfaceFrameForToken(stateToCommit->frameTimelineInfo, mOwnerPid, + mOwnerUid, mName, mTransactionName); mSurfaceFrame->setActualQueueTime(stateToCommit->postTime); // For transactions we set the acquire fence time to the post time as we // don't have a buffer. For BufferStateLayer it is overridden in @@ -1313,7 +1309,7 @@ bool Layer::setBlurRegions(const std::vector& blurRegions) { } bool Layer::setFlags(uint8_t flags, uint8_t mask) { - const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); + const uint8_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); if (mCurrentState.flags == newFlags) return false; mCurrentState.sequence++; mCurrentState.flags = newFlags; @@ -1491,8 +1487,8 @@ bool Layer::setFrameRate(FrameRate frameRate) { return true; } -void Layer::setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime) { - mCurrentState.frameTimelineVsyncId = frameTimelineVsyncId; +void Layer::setFrameTimelineInfoForTransaction(const FrameTimelineInfo& info, nsecs_t postTime) { + mCurrentState.frameTimelineInfo = info; mCurrentState.postTime = postTime; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 359340eb64..9b33beb620 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -304,8 +304,8 @@ public: // a fixed transform hint is not set. ui::Transform::RotationFlags fixedTransformHint; - // The vsync id that was used to start the transaction - int64_t frameTimelineVsyncId; + // The vsync info that was used to start the transaction + FrameTimelineInfo frameTimelineInfo; // When the transaction was posted nsecs_t postTime; @@ -869,8 +869,9 @@ public: bool setFrameRate(FrameRate); - virtual void setFrameTimelineVsyncForBuffer(int64_t /*frameTimelineVsyncId*/) {} - void setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime); + virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {} + void setFrameTimelineInfoForTransaction(const FrameTimelineInfo& frameTimelineInfo, + nsecs_t postTime); // Creates a new handle each time, so we only expect // this to be called once. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c1fabf8322..2a1a4aa5b2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3264,7 +3264,7 @@ bool SurfaceFlinger::flushTransactionQueues() { break; } transactions.push_back(transaction); - applyTransactionState(transaction.frameTimelineVsyncId, transaction.states, + applyTransactionState(transaction.frameTimelineInfo, transaction.states, transaction.displays, transaction.flags, mPendingInputWindowCommands, transaction.desiredPresentTime, transaction.isAutoTimestamp, transaction.buffer, @@ -3334,7 +3334,7 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, } status_t SurfaceFlinger::setTransactionState( - int64_t frameTimelineVsyncId, const Vector& states, + const FrameTimelineInfo& frameTimelineInfo, const Vector& states, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, @@ -3387,7 +3387,7 @@ status_t SurfaceFlinger::setTransactionState( // if the transaction contains a buffer. if (!transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true) || pendingTransactions) { - mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags, + mTransactionQueues[applyToken].emplace(frameTimelineInfo, states, displays, flags, desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged, hasListenerCallbacks, listenerCallbacks, originPid, originUid, @@ -3396,7 +3396,7 @@ status_t SurfaceFlinger::setTransactionState( return NO_ERROR; } - applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands, + applyTransactionState(frameTimelineInfo, states, displays, flags, inputWindowCommands, desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged, hasListenerCallbacks, listenerCallbacks, originPid, originUid, transactionId, /*isMainThread*/ false); @@ -3404,7 +3404,7 @@ status_t SurfaceFlinger::setTransactionState( } void SurfaceFlinger::applyTransactionState( - int64_t frameTimelineVsyncId, const Vector& states, + const FrameTimelineInfo& frameTimelineInfo, const Vector& states, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime, @@ -3445,9 +3445,9 @@ void SurfaceFlinger::applyTransactionState( uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { clientStateFlags |= - setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime, - isAutoTimestamp, postTime, privileged, - listenerCallbacksWithSurfaces, originPid, originUid); + setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp, + postTime, privileged, listenerCallbacksWithSurfaces, originPid, + originUid); if ((flags & eAnimation) && state.state.surface) { if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) { mScheduler->recordLayerHistory(layer.get(), @@ -3625,7 +3625,7 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis } uint32_t SurfaceFlinger::setClientStateLocked( - int64_t frameTimelineVsyncId, const ComposerState& composerState, + const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks, int originPid, int originUid) { @@ -3883,10 +3883,10 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } - if (what & layer_state_t::eFrameTimelineVsyncChanged) { - layer->setFrameTimelineVsyncForTransaction(s.frameTimelineVsyncId, postTime); - } else if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) { - layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime); + if (what & layer_state_t::eFrameTimelineInfoChanged) { + layer->setFrameTimelineInfoForTransaction(s.frameTimelineInfo, postTime); + } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { + layer->setFrameTimelineInfoForTransaction(frameTimelineInfo, postTime); } if (what & layer_state_t::eFixedTransformHintChanged) { if (layer->setFixedTransformHint(s.fixedTransformHint)) { @@ -4222,7 +4222,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr, + setTransactionState(FrameTimelineInfo{}, state, displays, 0, nullptr, mPendingInputWindowCommands, systemTime(), true, {}, false, {}, 0 /* Undefined transactionId */); @@ -4973,7 +4973,7 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case CAPTURE_LAYERS: case CAPTURE_DISPLAY: case SET_DISPLAY_BRIGHTNESS: - case SET_FRAME_TIMELINE_VSYNC: + case SET_FRAME_TIMELINE_INFO: // This is not sensitive information, so should not require permission control. case GET_GPU_CONTEXT_PRIORITY: { return OK; @@ -6350,21 +6350,21 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { })); } -status_t SurfaceFlinger::setFrameTimelineVsync(const sp& surface, - int64_t frameTimelineVsyncId) { +status_t SurfaceFlinger::setFrameTimelineInfo(const sp& surface, + const FrameTimelineInfo& frameTimelineInfo) { Mutex::Autolock lock(mStateLock); if (!authenticateSurfaceTextureLocked(surface)) { - ALOGE("Attempt to set frame timeline vsync on an unrecognized IGraphicBufferProducer"); + ALOGE("Attempt to set frame timeline info on an unrecognized IGraphicBufferProducer"); return BAD_VALUE; } sp layer = (static_cast(surface.get()))->getLayer(); if (layer == nullptr) { - ALOGE("Attempt to set frame timeline vsync on a layer that no longer exists"); + ALOGE("Attempt to set frame timeline info on a layer that no longer exists"); return BAD_VALUE; } - layer->setFrameTimelineVsyncForBuffer(frameTimelineVsyncId); + layer->setFrameTimelineInfoForBuffer(frameTimelineInfo); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c90fb4aca3..c54c1fb892 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -342,7 +342,7 @@ protected: virtual ~SurfaceFlinger(); virtual uint32_t setClientStateLocked( - int64_t frameTimelineVsyncId, const ComposerState& composerState, + const FrameTimelineInfo& info, const ComposerState& composerState, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks, int originPid, int originUid) REQUIRES(mStateLock); @@ -434,14 +434,15 @@ private: }; struct TransactionState { - TransactionState(int64_t frameTimelineVsyncId, const Vector& composerStates, + TransactionState(const FrameTimelineInfo& frameTimelineInfo, + const Vector& composerStates, const Vector& displayStates, uint32_t transactionFlags, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged, bool hasListenerCallbacks, std::vector listenerCallbacks, int originPid, int originUid, uint64_t transactionId) - : frameTimelineVsyncId(frameTimelineVsyncId), + : frameTimelineInfo(frameTimelineInfo), states(composerStates), displays(displayStates), flags(transactionFlags), @@ -456,7 +457,7 @@ private: originUid(originUid), id(transactionId) {} - int64_t frameTimelineVsyncId; + FrameTimelineInfo frameTimelineInfo; Vector states; Vector displays; uint32_t flags; @@ -521,7 +522,8 @@ private: void destroyDisplay(const sp& displayToken) override; std::vector getPhysicalDisplayIds() const override; sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const override; - status_t setTransactionState(int64_t frameTimelineVsyncId, const Vector& state, + status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo, + const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, @@ -607,8 +609,8 @@ private: int8_t compatibility, bool shouldBeSeamless) override; status_t acquireFrameRateFlexibilityToken(sp* outToken) override; - status_t setFrameTimelineVsync(const sp& surface, - int64_t frameTimelineVsyncId) override; + status_t setFrameTimelineInfo(const sp& surface, + const FrameTimelineInfo& frameTimelineInfo) override; status_t addTransactionTraceListener( const sp& listener) override; @@ -725,7 +727,7 @@ private: /* * Transactions */ - void applyTransactionState(int64_t frameTimelineVsyncId, const Vector& state, + void applyTransactionState(const FrameTimelineInfo& info, const Vector& state, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp index ecfed13adb..913f133a96 100644 --- a/services/surfaceflinger/tests/LayerState_test.cpp +++ b/services/surfaceflinger/tests/LayerState_test.cpp @@ -104,5 +104,34 @@ TEST(LayerStateTest, ParcellingScreenCaptureResults) { ASSERT_EQ(results.result, results2.result); } +/** + * Parcel a layer_state_t struct, and then unparcel. Ensure that the object that was parceled + * matches the object that's unparceled. + */ +TEST(LayerStateTest, ParcelUnparcelLayerStateT) { + layer_state_t input; + input.frameTimelineInfo.vsyncId = 1; + input.frameTimelineInfo.inputEventId = 2; + Parcel p; + input.write(p); + layer_state_t output; + p.setDataPosition(0); + output.read(p); + ASSERT_EQ(input.frameTimelineInfo.vsyncId, output.frameTimelineInfo.vsyncId); + ASSERT_EQ(input.frameTimelineInfo.inputEventId, output.frameTimelineInfo.inputEventId); +} + +TEST(LayerStateTest, LayerStateMerge_SelectsValidInputEvent) { + layer_state_t layer1; + layer1.frameTimelineInfo.inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID; + layer_state_t layer2; + layer2.frameTimelineInfo.inputEventId = 1; + layer2.what |= layer_state_t::eFrameTimelineInfoChanged; + + layer1.merge(layer2); + + ASSERT_EQ(1, layer1.frameTimelineInfo.inputEventId); +} + } // namespace test } // namespace android diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index e2584e266d..6e9f09bdaa 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -14,9 +14,6 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wextra" #include "gmock/gmock-spec-builders.h" #include "mock/MockTimeStats.h" @@ -177,16 +174,17 @@ static const std::string sLayerNameTwo = "layer2"; static constexpr const uid_t sUidOne = 0; static constexpr pid_t sPidOne = 10; static constexpr pid_t sPidTwo = 20; +static constexpr int32_t sInputEventId = 5; TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) { int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0}); - EXPECT_EQ(getPredictions().size(), 1); + EXPECT_EQ(getPredictions().size(), 1u); flushTokens(systemTime() + maxTokenRetentionTime); int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30}); std::optional predictions = mTokenManager->getPredictionsForToken(token1); // token1 should have expired - EXPECT_EQ(getPredictions().size(), 1); + EXPECT_EQ(getPredictions().size(), 1u); EXPECT_EQ(predictions.has_value(), false); predictions = mTokenManager->getPredictionsForToken(token2); @@ -194,16 +192,16 @@ TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) { } TEST_F(FrameTimelineTest, createSurfaceFrameForToken_getOwnerPidReturnsCorrectPid) { - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, + auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, sLayerNameOne); - auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidTwo, sUidOne, + auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({}, sPidTwo, sUidOne, sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame1->getOwnerPid(), sPidOne); EXPECT_EQ(surfaceFrame2->getOwnerPid(), sPidTwo); } TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) { - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, + auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::None); } @@ -211,21 +209,33 @@ TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) { TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) { int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0}); flushTokens(systemTime() + maxTokenRetentionTime); - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired); } TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid); EXPECT_EQ(compareTimelineItems(surfaceFrame->getPredictions(), TimelineItem(10, 20, 30)), true); } +TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validInputEventId) { + int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); + constexpr int32_t inputEventId = 1; + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({token1, inputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); + + EXPECT_EQ(inputEventId, surfaceFrame->getInputEventId()); +} + TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) { // Global increment EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)); @@ -234,8 +244,9 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20, 11); @@ -264,11 +275,11 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30}); int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 60}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameTwo, sLayerNameTwo); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameTwo, sLayerNameTwo); mFrameTimeline->setSfWakeUp(sfToken1, 22, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -288,8 +299,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame3 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken2, 52, 11); surfaceFrame3->setPresentState(SurfaceFrame::PresentState::Dropped); mFrameTimeline->addSurfaceFrame(surfaceFrame3); @@ -320,8 +331,9 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { int64_t sfToken = mTokenManager->generateTokenForPredictions( {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor}); auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, + sPidOne, sUidOne, sLayerNameOne, + sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -341,8 +353,8 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { int64_t sfToken = mTokenManager->generateTokenForPredictions( {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor}); auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -356,18 +368,18 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { } TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) { - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0, - "acquireFenceAfterQueue", - "acquireFenceAfterQueue"); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue", + "acquireFenceAfterQueue"); surfaceFrame->setActualQueueTime(123); surfaceFrame->setAcquireFenceTime(456); EXPECT_EQ(surfaceFrame->getActuals().endTime, 456); } TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) { - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0, - "acquireFenceAfterQueue", - "acquireFenceAfterQueue"); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue", + "acquireFenceAfterQueue"); surfaceFrame->setActualQueueTime(456); surfaceFrame->setAcquireFenceTime(123); EXPECT_EQ(surfaceFrame->getActuals().endTime, 456); @@ -383,8 +395,8 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { // Size shouldn't exceed maxDisplayFrames - 64 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, + sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -395,15 +407,15 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { // Increase the size to 256 mFrameTimeline->setMaxDisplayFrames(256); - EXPECT_EQ(*maxDisplayFrames, 256); + EXPECT_EQ(*maxDisplayFrames, 256u); // Global increment EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)) .Times(static_cast(*maxDisplayFrames + 10)); for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, + sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -414,15 +426,15 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { // Shrink the size to 128 mFrameTimeline->setMaxDisplayFrames(128); - EXPECT_EQ(*maxDisplayFrames, 128); + EXPECT_EQ(*maxDisplayFrames, 128u); // Global increment EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)) .Times(static_cast(*maxDisplayFrames + 10)); for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, + sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -449,8 +461,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { std::chrono::duration_cast(56ms).count(), std::chrono::duration_cast(60ms).count()}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast(52ms).count(), 11); @@ -478,8 +490,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { std::chrono::duration_cast(56ms).count(), std::chrono::duration_cast(60ms).count()}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast(52ms).count(), 30); @@ -507,8 +519,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { std::chrono::duration_cast(86ms).count(), std::chrono::duration_cast(90ms).count()}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime( std::chrono::duration_cast(45ms).count()); mFrameTimeline->setSfWakeUp(sfToken1, @@ -542,8 +554,9 @@ TEST_F(FrameTimelineTest, tracing_noPacketsSentWithoutTraceStart) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20, 11); @@ -558,7 +571,7 @@ TEST_F(FrameTimelineTest, tracing_noPacketsSentWithoutTraceStart) { mFrameTimeline->setSfPresent(55, presentFence2); auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); - EXPECT_EQ(packets.size(), 0); + EXPECT_EQ(packets.size(), 0u); } TEST_F(FrameTimelineTest, tracing_sanityTest) { @@ -573,8 +586,9 @@ TEST_F(FrameTimelineTest, tracing_sanityTest) { tracingSession->StartBlocking(); int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token2, 20, 11); @@ -594,7 +608,7 @@ TEST_F(FrameTimelineTest, tracing_sanityTest) { auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); // Display Frame 1 has 8 packets - 4 from DisplayFrame and 4 from SurfaceFrame. - EXPECT_EQ(packets.size(), 8); + EXPECT_EQ(packets.size(), 8u); } TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) { @@ -622,7 +636,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) tracingSession->StopBlocking(); auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); - EXPECT_EQ(packets.size(), 0); + EXPECT_EQ(packets.size(), 0u); } TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) { @@ -635,7 +649,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) tracingSession->StartBlocking(); int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, + auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, sLayerNameOne); // Set up the display frame @@ -657,7 +671,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); // Display Frame 1 has 4 packets (SurfaceFrame shouldn't be traced since it has an invalid // token). - EXPECT_EQ(packets.size(), 4); + EXPECT_EQ(packets.size(), 4u); } void validateTraceEvent(const ProtoExpectedDisplayFrameStart& received, @@ -791,12 +805,12 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { tracingSession->StopBlocking(); auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); - EXPECT_EQ(packets.size(), 4); + EXPECT_EQ(packets.size(), 4u); // Packet - 0 : ExpectedDisplayFrameStart const auto& packet0 = packets[0]; ASSERT_TRUE(packet0.has_timestamp()); - EXPECT_EQ(packet0.timestamp(), 10); + EXPECT_EQ(packet0.timestamp(), 10u); ASSERT_TRUE(packet0.has_frame_timeline_event()); const auto& event0 = packet0.frame_timeline_event(); @@ -807,7 +821,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { // Packet - 1 : FrameEnd (ExpectedDisplayFrame) const auto& packet1 = packets[1]; ASSERT_TRUE(packet1.has_timestamp()); - EXPECT_EQ(packet1.timestamp(), 25); + EXPECT_EQ(packet1.timestamp(), 25u); ASSERT_TRUE(packet1.has_frame_timeline_event()); const auto& event1 = packet1.frame_timeline_event(); @@ -818,7 +832,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { // Packet - 2 : ActualDisplayFrameStart const auto& packet2 = packets[2]; ASSERT_TRUE(packet2.has_timestamp()); - EXPECT_EQ(packet2.timestamp(), 20); + EXPECT_EQ(packet2.timestamp(), 20u); ASSERT_TRUE(packet2.has_frame_timeline_event()); const auto& event2 = packet2.frame_timeline_event(); @@ -829,7 +843,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { // Packet - 3 : FrameEnd (ActualDisplayFrame) const auto& packet3 = packets[3]; ASSERT_TRUE(packet3.has_timestamp()); - EXPECT_EQ(packet3.timestamp(), 26); + EXPECT_EQ(packet3.timestamp(), 26u); ASSERT_TRUE(packet3.has_frame_timeline_event()); const auto& event3 = packet3.frame_timeline_event(); @@ -853,8 +867,8 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { int64_t displayFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setActualStartTime(0); surfaceFrame1->setActualQueueTime(15); surfaceFrame1->setAcquireFenceTime(20); @@ -904,12 +918,12 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { tracingSession->StopBlocking(); auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); - EXPECT_EQ(packets.size(), 8); + EXPECT_EQ(packets.size(), 8u); // Packet - 4 : ExpectedSurfaceFrameStart const auto& packet4 = packets[4]; ASSERT_TRUE(packet4.has_timestamp()); - EXPECT_EQ(packet4.timestamp(), 10); + EXPECT_EQ(packet4.timestamp(), 10u); ASSERT_TRUE(packet4.has_frame_timeline_event()); const auto& event4 = packet4.frame_timeline_event(); @@ -920,7 +934,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { // Packet - 5 : FrameEnd (ExpectedSurfaceFrame) const auto& packet5 = packets[5]; ASSERT_TRUE(packet5.has_timestamp()); - EXPECT_EQ(packet5.timestamp(), 25); + EXPECT_EQ(packet5.timestamp(), 25u); ASSERT_TRUE(packet5.has_frame_timeline_event()); const auto& event5 = packet5.frame_timeline_event(); @@ -931,7 +945,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { // Packet - 6 : ActualSurfaceFrameStart const auto& packet6 = packets[6]; ASSERT_TRUE(packet6.has_timestamp()); - EXPECT_EQ(packet6.timestamp(), 10); + EXPECT_EQ(packet6.timestamp(), 10u); ASSERT_TRUE(packet6.has_frame_timeline_event()); const auto& event6 = packet6.frame_timeline_event(); @@ -942,7 +956,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { // Packet - 7 : FrameEnd (ActualSurfaceFrame) const auto& packet7 = packets[7]; ASSERT_TRUE(packet7.has_timestamp()); - EXPECT_EQ(packet7.timestamp(), 20); + EXPECT_EQ(packet7.timestamp(), 20u); ASSERT_TRUE(packet7.has_frame_timeline_event()); const auto& event7 = packet7.frame_timeline_event(); @@ -961,8 +975,8 @@ TEST_F(FrameTimelineTest, jankClassification_presentOnTimeDoesNotClassify) { int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30}); auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, 22, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -1126,8 +1140,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40}); int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(16); mFrameTimeline->setSfWakeUp(sfToken1, 22, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1145,8 +1159,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame2->setAcquireFenceTime(36); mFrameTimeline->setSfWakeUp(sfToken2, 52, 11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1199,8 +1213,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40}); int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(16); mFrameTimeline->setSfWakeUp(sfToken1, 22, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1218,8 +1232,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame2->setAcquireFenceTime(36); mFrameTimeline->setSfWakeUp(sfToken2, 52, 11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1270,8 +1284,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishEarlyPresent) int64_t sfToken1 = mTokenManager->generateTokenForPredictions({42, 46, 50}); int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 26, 60}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(40); mFrameTimeline->setSfWakeUp(sfToken1, 42, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1316,8 +1330,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 30}); int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 50}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(26); mFrameTimeline->setSfWakeUp(sfToken1, 32, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1335,8 +1349,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame2->setAcquireFenceTime(40); mFrameTimeline->setSfWakeUp(sfToken2, 43, 11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1390,8 +1404,8 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 56, 60}); int64_t sfToken2 = mTokenManager->generateTokenForPredictions({112, 116, 120}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(50); mFrameTimeline->setSfWakeUp(sfToken1, 52, 30); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1409,8 +1423,8 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame2->setAcquireFenceTime(84); mFrameTimeline->setSfWakeUp(sfToken2, 112, 30); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54); @@ -1456,6 +1470,3 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli JankType::AppDeadlineMissed | JankType::BufferStuffing); } } // namespace android::frametimeline - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 9a9eeab96c..a46affd4a3 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -368,16 +368,14 @@ public: auto& getTransactionQueue() { return mFlinger->mTransactionQueues; } - auto setTransactionState(int64_t frameTimelineVsyncId, const Vector& states, - const Vector& displays, uint32_t flags, - const sp& applyToken, - const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, - std::vector& listenerCallbacks, - uint64_t transactionId) { - return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags, - applyToken, inputWindowCommands, desiredPresentTime, + auto setTransactionState( + const FrameTimelineInfo& frameTimelineInfo, const Vector& states, + const Vector& displays, uint32_t flags, const sp& applyToken, + const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, + bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + std::vector& listenerCallbacks, uint64_t transactionId) { + return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken, + inputWindowCommands, desiredPresentTime, isAutoTimestamp, uncacheBuffer, hasListenerCallbacks, listenerCallbacks, transactionId); } diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 06275c6b5b..6d2f672bce 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -14,10 +14,6 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "CompositionTest" @@ -100,43 +96,44 @@ public: InputWindowCommands inputWindowCommands; int64_t desiredPresentTime = 0; bool isAutoTimestamp = true; - int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + FrameTimelineInfo frameTimelineInfo; client_cache_t uncacheBuffer; - int64_t id = -1; + uint64_t id = static_cast(-1); + static_assert(0xffffffffffffffff == static_cast(-1)); }; void checkEqual(TransactionInfo info, SurfaceFlinger::TransactionState state) { - EXPECT_EQ(0, info.states.size()); - EXPECT_EQ(0, state.states.size()); + EXPECT_EQ(0u, info.states.size()); + EXPECT_EQ(0u, state.states.size()); - EXPECT_EQ(0, info.displays.size()); - EXPECT_EQ(0, state.displays.size()); + EXPECT_EQ(0u, info.displays.size()); + EXPECT_EQ(0u, state.displays.size()); EXPECT_EQ(info.flags, state.flags); EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime); } void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows, int64_t desiredPresentTime, bool isAutoTimestamp, - int64_t frameTimelineVsyncId) { + const FrameTimelineInfo& frameTimelineInfo) { mTransactionNumber++; transaction.flags |= flags; // ISurfaceComposer::eSynchronous; transaction.inputWindowCommands.syncInputWindows = syncInputWindows; transaction.desiredPresentTime = desiredPresentTime; transaction.isAutoTimestamp = isAutoTimestamp; - transaction.frameTimelineVsyncId = frameTimelineVsyncId; + transaction.frameTimelineInfo = frameTimelineInfo; } void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) { - ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); // called in SurfaceFlinger::signalTransaction EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime())); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, - ISurfaceComposer::INVALID_VSYNC_ID); + FrameTimelineInfo{}); nsecs_t applicationTime = systemTime(); - mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, + mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.isAutoTimestamp, @@ -155,11 +152,11 @@ public: EXPECT_LE(returnedTime, applicationTime + s2ns(5)); } auto transactionQueue = mFlinger.getTransactionQueue(); - EXPECT_EQ(0, transactionQueue.size()); + EXPECT_EQ(0u, transactionQueue.size()); } void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) { - ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); // called in SurfaceFlinger::signalTransaction EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); @@ -170,10 +167,9 @@ public: .WillOnce(Return(time + nsecs_t(5 * 1e8))); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, - /*desiredPresentTime*/ time + s2ns(1), false, - ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{}); nsecs_t applicationSentTime = systemTime(); - mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, + mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.isAutoTimestamp, @@ -184,11 +180,11 @@ public: EXPECT_LE(returnedTime, applicationSentTime + s2ns(5)); // This transaction should have been placed on the transaction queue auto transactionQueue = mFlinger.getTransactionQueue(); - EXPECT_EQ(1, transactionQueue.size()); + EXPECT_EQ(1u, transactionQueue.size()); } void BlockedByPriorTransaction(uint32_t flags, bool syncInputWindows) { - ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); // called in SurfaceFlinger::signalTransaction nsecs_t time = systemTime(); EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); @@ -197,18 +193,17 @@ public: // transaction that should go on the pending thread TransactionInfo transactionA; setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ time + s2ns(1), false, - ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{}); // transaction that would not have gone on the pending thread if not // blocked TransactionInfo transactionB; setupSingle(transactionB, flags, syncInputWindows, /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, - ISurfaceComposer::INVALID_VSYNC_ID); + FrameTimelineInfo{}); nsecs_t applicationSentTime = systemTime(); - mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, + mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, transactionA.isAutoTimestamp, @@ -221,7 +216,7 @@ public: EXPECT_LE(systemTime(), applicationSentTime + s2ns(5)); applicationSentTime = systemTime(); - mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states, + mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states, transactionB.displays, transactionB.flags, transactionB.applyToken, transactionB.inputWindowCommands, transactionB.desiredPresentTime, transactionB.isAutoTimestamp, @@ -240,10 +235,10 @@ public: // check that there is one binder on the pending queue. auto transactionQueue = mFlinger.getTransactionQueue(); - EXPECT_EQ(1, transactionQueue.size()); + EXPECT_EQ(1u, transactionQueue.size()); auto& [applyToken, transactionStates] = *(transactionQueue.begin()); - EXPECT_EQ(2, transactionStates.size()); + EXPECT_EQ(2u, transactionStates.size()); auto& transactionStateA = transactionStates.front(); transactionStates.pop(); @@ -258,7 +253,7 @@ public: }; TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { - ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); // called in SurfaceFlinger::signalTransaction EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); @@ -268,18 +263,18 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { .WillOnce(Return(s2ns(2))); TransactionInfo transactionA; // transaction to go on pending queue setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ s2ns(1), false, ISurfaceComposer::INVALID_VSYNC_ID); - mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, + /*desiredPresentTime*/ s2ns(1), false, FrameTimelineInfo{}); + mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, transactionA.isAutoTimestamp, transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, transactionA.id); auto& transactionQueue = mFlinger.getTransactionQueue(); - ASSERT_EQ(1, transactionQueue.size()); + ASSERT_EQ(1u, transactionQueue.size()); auto& [applyToken, transactionStates] = *(transactionQueue.begin()); - ASSERT_EQ(1, transactionStates.size()); + ASSERT_EQ(1u, transactionStates.size()); auto& transactionState = transactionStates.front(); checkEqual(transactionA, transactionState); @@ -289,8 +284,8 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { // different process) to re-query and reset the cached expected present time TransactionInfo empty; empty.applyToken = sp(); - mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays, - empty.flags, empty.applyToken, empty.inputWindowCommands, + mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags, + empty.applyToken, empty.inputWindowCommands, empty.desiredPresentTime, empty.isAutoTimestamp, empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id); @@ -298,7 +293,7 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { // passed mFlinger.flushTransactionQueues(); - EXPECT_EQ(0, transactionQueue.size()); + EXPECT_EQ(0u, transactionQueue.size()); } TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Synchronous) { @@ -343,6 +338,3 @@ TEST_F(TransactionApplicationTest, FromHandle) { EXPECT_EQ(nullptr, ret.promote().get()); } } // namespace android - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" -- cgit v1.2.3-59-g8ed1b From 98318de954ba00293cfd179266f09f266dc1c82b Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 19 May 2021 16:45:23 -0500 Subject: Renamed and moved InputWindow and related files In preparation for the hierarchy listener interface, moved the InputWindow structs into libgui and have libinput dependant on libgui. Also renamed InputWindow to exclude Input since it will be used for more generic purposes. Test: Builds and flashes Bug: 188792659 Change-Id: I24262cbc14d409c00273de0024a672394a959e5f --- include/ftl/Flags.h | 280 ++++++++++++++++++++ include/ftl/NamedEnum.h | 125 +++++++++ include/input/DisplayViewport.h | 3 +- include/input/Flags.h | 283 --------------------- include/input/Input.h | 15 -- include/input/InputApplication.h | 85 ------- include/input/InputWindow.h | 279 -------------------- include/input/NamedEnum.h | 128 ---------- libs/ftl/Android.bp | 10 + libs/ftl/Flags_test.cpp | 227 +++++++++++++++++ libs/ftl/NamedEnum_test.cpp | 101 ++++++++ libs/gui/Android.bp | 56 +++- libs/gui/BLASTBufferQueue.cpp | 6 +- libs/gui/LayerState.cpp | 27 +- libs/gui/SurfaceComposerClient.cpp | 16 +- libs/gui/WindowInfo.cpp | 223 ++++++++++++++++ libs/gui/android/gui/FocusRequest.aidl | 45 ++++ libs/gui/android/gui/InputApplicationInfo.aidl | 23 ++ libs/gui/android/gui/TouchOcclusionMode.aidl | 47 ++++ libs/gui/android/gui/WindowInfo.aidl | 19 ++ libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/include/gui/InputApplication.h | 79 ++++++ libs/gui/include/gui/LayerState.h | 14 +- libs/gui/include/gui/SurfaceComposerClient.h | 6 +- libs/gui/include/gui/WindowInfo.h | 273 ++++++++++++++++++++ libs/gui/include/gui/constants.h | 37 +++ libs/gui/tests/Android.bp | 1 + libs/gui/tests/EndToEndNativeInputTest.cpp | 27 +- libs/gui/tests/WindowInfo_test.cpp | 133 ++++++++++ libs/input/Android.bp | 14 +- libs/input/Input.cpp | 1 + libs/input/InputDevice.cpp | 2 +- libs/input/InputTransport.cpp | 2 +- libs/input/InputWindow.cpp | 224 ---------------- libs/input/KeyCharacterMap.cpp | 5 +- libs/input/KeyLayoutMap.cpp | 2 +- libs/input/android/FocusRequest.aidl | 45 ---- libs/input/android/InputApplicationInfo.aidl | 23 -- libs/input/android/InputWindowInfo.aidl | 20 -- libs/input/android/os/IInputFlinger.aidl | 6 +- libs/input/android/os/TouchOcclusionMode.aidl | 47 ---- libs/input/tests/Android.bp | 10 +- libs/input/tests/Flags_test.cpp | 227 ----------------- libs/input/tests/InputEvent_test.cpp | 24 +- .../input/tests/InputPublisherAndConsumer_test.cpp | 1 + libs/input/tests/InputWindow_test.cpp | 129 ---------- libs/input/tests/NamedEnum_test.cpp | 101 -------- libs/input/tests/VelocityTracker_test.cpp | 7 +- libs/input/tests/VerifiedInputEvent_test.cpp | 8 +- libs/nativedisplay/AChoreographer.cpp | 1 - services/inputflinger/InputManager.cpp | 16 +- services/inputflinger/InputManager.h | 4 +- services/inputflinger/InputReaderBase.cpp | 2 +- .../benchmarks/InputDispatcher_benchmarks.cpp | 11 +- services/inputflinger/dispatcher/DragState.cpp | 2 - services/inputflinger/dispatcher/DragState.h | 10 +- services/inputflinger/dispatcher/Entry.h | 2 +- services/inputflinger/dispatcher/FocusResolver.cpp | 15 +- services/inputflinger/dispatcher/FocusResolver.h | 18 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 233 ++++++++--------- services/inputflinger/dispatcher/InputDispatcher.h | 90 ++++--- services/inputflinger/dispatcher/InputTarget.h | 3 +- services/inputflinger/dispatcher/TouchState.cpp | 11 +- services/inputflinger/dispatcher/TouchState.h | 12 +- services/inputflinger/dispatcher/TouchedWindow.h | 6 +- .../dispatcher/include/InputDispatcherInterface.h | 11 +- .../include/InputDispatcherPolicyInterface.h | 2 +- services/inputflinger/host/InputFlinger.h | 4 +- services/inputflinger/reader/InputDevice.cpp | 2 +- .../reader/controller/PeripheralController.cpp | 2 +- services/inputflinger/reader/include/EventHub.h | 2 +- services/inputflinger/reader/include/InputDevice.h | 2 +- .../reader/mapper/TouchInputMapper.cpp | 2 +- services/inputflinger/tests/Android.bp | 1 + services/inputflinger/tests/FocusResolver_test.cpp | 19 +- .../inputflinger/tests/IInputFlingerQuery.aidl | 6 +- .../tests/InputClassifierConverter_test.cpp | 2 +- .../inputflinger/tests/InputClassifier_test.cpp | 1 + .../inputflinger/tests/InputDispatcher_test.cpp | 149 +++++------ .../tests/InputFlingerService_test.cpp | 52 ++-- services/inputflinger/tests/InputReader_test.cpp | 1 + services/surfaceflinger/Android.bp | 1 - services/surfaceflinger/BufferLayer.cpp | 4 +- .../compositionengine/impl/planner/LayerState.h | 2 +- services/surfaceflinger/Layer.cpp | 24 +- services/surfaceflinger/Layer.h | 18 +- services/surfaceflinger/LayerProtoHelper.cpp | 7 +- services/surfaceflinger/LayerProtoHelper.h | 4 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 9 +- services/surfaceflinger/SurfaceFlinger.cpp | 7 +- .../tests/RefreshRateOverlay_test.cpp | 4 + .../surfaceflinger/tests/utils/CallbackUtils.h | 4 + 92 files changed, 2158 insertions(+), 2088 deletions(-) create mode 100644 include/ftl/Flags.h create mode 100644 include/ftl/NamedEnum.h delete mode 100644 include/input/Flags.h delete mode 100644 include/input/InputApplication.h delete mode 100644 include/input/InputWindow.h delete mode 100644 include/input/NamedEnum.h create mode 100644 libs/ftl/Flags_test.cpp create mode 100644 libs/ftl/NamedEnum_test.cpp create mode 100644 libs/gui/WindowInfo.cpp create mode 100644 libs/gui/android/gui/FocusRequest.aidl create mode 100644 libs/gui/android/gui/InputApplicationInfo.aidl create mode 100644 libs/gui/android/gui/TouchOcclusionMode.aidl create mode 100644 libs/gui/android/gui/WindowInfo.aidl create mode 100644 libs/gui/include/gui/InputApplication.h create mode 100644 libs/gui/include/gui/WindowInfo.h create mode 100644 libs/gui/include/gui/constants.h create mode 100644 libs/gui/tests/WindowInfo_test.cpp delete mode 100644 libs/input/InputWindow.cpp delete mode 100644 libs/input/android/FocusRequest.aidl delete mode 100644 libs/input/android/InputApplicationInfo.aidl delete mode 100644 libs/input/android/InputWindowInfo.aidl delete mode 100644 libs/input/android/os/TouchOcclusionMode.aidl delete mode 100644 libs/input/tests/Flags_test.cpp delete mode 100644 libs/input/tests/InputWindow_test.cpp delete mode 100644 libs/input/tests/NamedEnum_test.cpp (limited to 'libs/gui/LayerState.cpp') diff --git a/include/ftl/Flags.h b/include/ftl/Flags.h new file mode 100644 index 0000000000..27c84769cb --- /dev/null +++ b/include/ftl/Flags.h @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include "utils/BitSet.h" + +#pragma once + +namespace android { + +namespace details { + +template +inline constexpr auto flag_count = sizeof(F) * __CHAR_BIT__; + +template +constexpr auto generate_flag_values(std::integer_sequence seq) { + constexpr size_t count = seq.size(); + + std::array values{}; + for (size_t i = 0, v = 0; v < count; ++i) { + values[v++] = static_cast(T{1} << i); + } + + return values; +} + +template +inline constexpr auto flag_values = generate_flag_values( + std::make_integer_sequence, flag_count>{}); + +template +constexpr auto generate_flag_names(std::index_sequence) noexcept { + return std::array, sizeof...(I)>{ + {enum_value_name[I]>()...}}; +} + +template +inline constexpr auto flag_names = + generate_flag_names(std::make_index_sequence>{}); + +// A trait for determining whether a type is specifically an enum class or not. +template > +struct is_enum_class : std::false_type {}; + +// By definition, an enum class is an enum that is not implicitly convertible to its underlying +// type. +template +struct is_enum_class + : std::bool_constant>> {}; + +template +inline constexpr bool is_enum_class_v = is_enum_class::value; +} // namespace details + +template +constexpr auto flag_name() { + using F = decltype(V); + return details::enum_value_name(); +} + +template +constexpr std::optional flag_name(F flag) { + using U = std::underlying_type_t; + auto idx = static_cast(__builtin_ctzl(static_cast(flag))); + return details::flag_names[idx]; +} + +/* A class for handling flags defined by an enum or enum class in a type-safe way. */ +template +class Flags { + // F must be an enum or its underlying type is undefined. Theoretically we could specialize this + // further to avoid this restriction but in general we want to encourage the use of enums + // anyways. + static_assert(std::is_enum_v, "Flags type must be an enum"); + using U = typename std::underlying_type_t; + +public: + constexpr Flags(F f) : mFlags(static_cast(f)) {} + constexpr Flags() : mFlags(0) {} + constexpr Flags(const Flags& f) : mFlags(f.mFlags) {} + + // Provide a non-explicit construct for non-enum classes since they easily convert to their + // underlying types (e.g. when used with bitwise operators). For enum classes, however, we + // should force them to be explicitly constructed from their underlying types to make full use + // of the type checker. + template + constexpr Flags(T t, typename std::enable_if_t, T>* = nullptr) + : mFlags(t) {} + template + explicit constexpr Flags(T t, + typename std::enable_if_t, T>* = nullptr) + : mFlags(t) {} + + class Iterator { + // The type can't be larger than 64-bits otherwise it won't fit in BitSet64. + static_assert(sizeof(U) <= sizeof(uint64_t)); + + public: + Iterator(Flags flags) : mRemainingFlags(flags.mFlags) { (*this)++; } + Iterator() : mRemainingFlags(0), mCurrFlag(static_cast(0)) {} + + // Pre-fix ++ + Iterator& operator++() { + if (mRemainingFlags.isEmpty()) { + mCurrFlag = static_cast(0); + } else { + uint64_t bit = mRemainingFlags.clearLastMarkedBit(); // counts from left + const U flag = 1 << (64 - bit - 1); + mCurrFlag = static_cast(flag); + } + return *this; + } + + // Post-fix ++ + Iterator operator++(int) { + Iterator iter = *this; + ++*this; + return iter; + } + + bool operator==(Iterator other) const { + return mCurrFlag == other.mCurrFlag && mRemainingFlags == other.mRemainingFlags; + } + + bool operator!=(Iterator other) const { return !(*this == other); } + + F operator*() { return mCurrFlag; } + + // iterator traits + + // In the future we could make this a bidirectional const iterator instead of a forward + // iterator but it doesn't seem worth the added complexity at this point. This could not, + // however, be made a non-const iterator as assigning one flag to another is a non-sensical + // operation. + using iterator_category = std::input_iterator_tag; + using value_type = F; + // Per the C++ spec, because input iterators are not assignable the iterator's reference + // type does not actually need to be a reference. In fact, making it a reference would imply + // that modifying it would change the underlying Flags object, which is obviously wrong for + // the same reason this can't be a non-const iterator. + using reference = F; + using difference_type = void; + using pointer = void; + + private: + BitSet64 mRemainingFlags; + F mCurrFlag; + }; + + /* + * Tests whether the given flag is set. + */ + bool test(F flag) const { + U f = static_cast(flag); + return (f & mFlags) == f; + } + + /* Tests whether any of the given flags are set */ + bool any(Flags f) { return (mFlags & f.mFlags) != 0; } + + /* Tests whether all of the given flags are set */ + bool all(Flags f) { return (mFlags & f.mFlags) == f.mFlags; } + + Flags operator|(Flags rhs) const { return static_cast(mFlags | rhs.mFlags); } + Flags& operator|=(Flags rhs) { + mFlags = mFlags | rhs.mFlags; + return *this; + } + + Flags operator&(Flags rhs) const { return static_cast(mFlags & rhs.mFlags); } + Flags& operator&=(Flags rhs) { + mFlags = mFlags & rhs.mFlags; + return *this; + } + + Flags operator^(Flags rhs) const { return static_cast(mFlags ^ rhs.mFlags); } + Flags& operator^=(Flags rhs) { + mFlags = mFlags ^ rhs.mFlags; + return *this; + } + + Flags operator~() { return static_cast(~mFlags); } + + bool operator==(Flags rhs) const { return mFlags == rhs.mFlags; } + bool operator!=(Flags rhs) const { return !operator==(rhs); } + + Flags& operator=(const Flags& rhs) { + mFlags = rhs.mFlags; + return *this; + } + + Iterator begin() const { return Iterator(*this); } + + Iterator end() const { return Iterator(); } + + /* + * Returns the stored set of flags. + * + * Note that this returns the underlying type rather than the base enum class. This is because + * the value is no longer necessarily a strict member of the enum since the returned value could + * be multiple enum variants OR'd together. + */ + U get() const { return mFlags; } + + std::string string() const { + std::string result; + bool first = true; + U unstringified = 0; + for (const F f : *this) { + std::optional flagString = flag_name(f); + if (flagString) { + appendFlag(result, flagString.value(), first); + } else { + unstringified |= static_cast(f); + } + } + + if (unstringified != 0) { + appendFlag(result, base::StringPrintf("0x%08x", unstringified), first); + } + + if (first) { + result += "0x0"; + } + + return result; + } + +private: + U mFlags; + + static void appendFlag(std::string& str, const std::string_view& flag, bool& first) { + if (first) { + first = false; + } else { + str += " | "; + } + str += flag; + } +}; + +// This namespace provides operator overloads for enum classes to make it easier to work with them +// as flags. In order to use these, add them via a `using namespace` declaration. +namespace flag_operators { + +template >> +inline Flags operator~(F f) { + using U = typename std::underlying_type_t; + return static_cast(~static_cast(f)); +} +template >> +Flags operator|(F lhs, F rhs) { + using U = typename std::underlying_type_t; + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +} // namespace flag_operators +} // namespace android diff --git a/include/ftl/NamedEnum.h b/include/ftl/NamedEnum.h new file mode 100644 index 0000000000..f50ff46fe2 --- /dev/null +++ b/include/ftl/NamedEnum.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#pragma once + +namespace android { + +namespace details { +template +constexpr std::optional enum_value_name() { + // Should look something like (but all on one line): + // std::optional + // android::details::enum_value_name() + // [E = android::test::TestEnums, V = android::test::TestEnums::ONE] + std::string_view view = __PRETTY_FUNCTION__; + size_t templateStart = view.rfind("["); + size_t templateEnd = view.rfind("]"); + if (templateStart == std::string::npos || templateEnd == std::string::npos) { + return std::nullopt; + } + + // Extract the template parameters without the enclosing braces. + // Example (cont'd): E = android::test::TestEnums, V = android::test::TestEnums::ONE + view = view.substr(templateStart + 1, templateEnd - templateStart - 1); + size_t valStart = view.rfind("V = "); + if (valStart == std::string::npos) { + return std::nullopt; + } + + // Example (cont'd): V = android::test::TestEnums::ONE + view = view.substr(valStart); + size_t nameStart = view.rfind("::"); + if (nameStart == std::string::npos) { + return std::nullopt; + } + + // Chop off the initial "::" + nameStart += 2; + return view.substr(nameStart); +} + +template +constexpr auto generate_enum_values(std::integer_sequence seq) { + constexpr size_t count = seq.size(); + + std::array values{}; + for (size_t i = 0, v = 0; v < count; ++i) { + values[v++] = static_cast(T{0} + i); + } + + return values; +} + +template +inline constexpr auto enum_values = + generate_enum_values(std::make_integer_sequence, N>{}); + +template +constexpr auto generate_enum_names(std::index_sequence) noexcept { + return std::array, sizeof...(I)>{ + {enum_value_name[I]>()...}}; +} + +template +inline constexpr auto enum_names = generate_enum_names(std::make_index_sequence{}); + +} // namespace details + +class NamedEnum { +public: + // By default allowed enum value range is 0 ~ 7. + template + static constexpr size_t max = 8; + + template + static constexpr auto enum_name() { + using E = decltype(V); + return details::enum_value_name(); + } + + template + static constexpr std::optional enum_name(E val) { + auto idx = static_cast(val); + return idx < max ? details::enum_names>[idx] : std::nullopt; + } + + // Helper function for parsing enum value to string. + // Example : enum class TestEnums { ZERO = 0x0 }; + // NamedEnum::string(TestEnums::ZERO) returns string of "ZERO". + // Note the default maximum enum is 8, if the enum ID to be parsed if greater than 8 like 16, + // it should be declared to specialized the maximum enum by below: + // template <> constexpr size_t NamedEnum::max = 16; + // If the enum class definition is sparse and contains enum values starting from a large value, + // Do not specialize it to a large number to avoid performance issues. + // The recommended maximum enum number to specialize is 64. + template + static const std::string string(E val, const char* fallbackFormat = "%02d") { + std::string result; + std::optional enumString = enum_name(val); + result += enumString ? enumString.value() : base::StringPrintf(fallbackFormat, val); + return result; + } +}; + +} // namespace android diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h index 5e40ca7ece..a6213f3ddd 100644 --- a/include/input/DisplayViewport.h +++ b/include/input/DisplayViewport.h @@ -18,8 +18,9 @@ #define _LIBINPUT_DISPLAY_VIEWPORT_H #include +#include +#include #include -#include #include #include diff --git a/include/input/Flags.h b/include/input/Flags.h deleted file mode 100644 index b12a9ed2c5..0000000000 --- a/include/input/Flags.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include -#include - -#include "NamedEnum.h" -#include "utils/BitSet.h" - -#ifndef __UI_INPUT_FLAGS_H -#define __UI_INPUT_FLAGS_H - -namespace android { - -namespace details { - -template -inline constexpr auto flag_count = sizeof(F) * __CHAR_BIT__; - -template -constexpr auto generate_flag_values(std::integer_sequence seq) { - constexpr size_t count = seq.size(); - - std::array values{}; - for (size_t i = 0, v = 0; v < count; ++i) { - values[v++] = static_cast(T{1} << i); - } - - return values; -} - -template -inline constexpr auto flag_values = generate_flag_values( - std::make_integer_sequence, flag_count>{}); - -template -constexpr auto generate_flag_names(std::index_sequence) noexcept { - return std::array, sizeof...(I)>{ - {enum_value_name[I]>()...}}; -} - -template -inline constexpr auto flag_names = - generate_flag_names(std::make_index_sequence>{}); - -// A trait for determining whether a type is specifically an enum class or not. -template > -struct is_enum_class : std::false_type {}; - -// By definition, an enum class is an enum that is not implicitly convertible to its underlying -// type. -template -struct is_enum_class - : std::bool_constant>> {}; - -template -inline constexpr bool is_enum_class_v = is_enum_class::value; -} // namespace details - -template -constexpr auto flag_name() { - using F = decltype(V); - return details::enum_value_name(); -} - -template -constexpr std::optional flag_name(F flag) { - using U = std::underlying_type_t; - auto idx = static_cast(__builtin_ctzl(static_cast(flag))); - return details::flag_names[idx]; -} - -/* A class for handling flags defined by an enum or enum class in a type-safe way. */ -template -class Flags { - // F must be an enum or its underlying type is undefined. Theoretically we could specialize this - // further to avoid this restriction but in general we want to encourage the use of enums - // anyways. - static_assert(std::is_enum_v, "Flags type must be an enum"); - using U = typename std::underlying_type_t; - -public: - constexpr Flags(F f) : mFlags(static_cast(f)) {} - constexpr Flags() : mFlags(0) {} - constexpr Flags(const Flags& f) : mFlags(f.mFlags) {} - - // Provide a non-explicit construct for non-enum classes since they easily convert to their - // underlying types (e.g. when used with bitwise operators). For enum classes, however, we - // should force them to be explicitly constructed from their underlying types to make full use - // of the type checker. - template - constexpr Flags(T t, typename std::enable_if_t, T>* = nullptr) - : mFlags(t) {} - template - explicit constexpr Flags(T t, - typename std::enable_if_t, T>* = nullptr) - : mFlags(t) {} - - class Iterator { - // The type can't be larger than 64-bits otherwise it won't fit in BitSet64. - static_assert(sizeof(U) <= sizeof(uint64_t)); - - public: - Iterator(Flags flags) : mRemainingFlags(flags.mFlags) { (*this)++; } - Iterator() : mRemainingFlags(0), mCurrFlag(static_cast(0)) {} - - // Pre-fix ++ - Iterator& operator++() { - if (mRemainingFlags.isEmpty()) { - mCurrFlag = static_cast(0); - } else { - uint64_t bit = mRemainingFlags.clearLastMarkedBit(); // counts from left - const U flag = 1 << (64 - bit - 1); - mCurrFlag = static_cast(flag); - } - return *this; - } - - // Post-fix ++ - Iterator operator++(int) { - Iterator iter = *this; - ++*this; - return iter; - } - - bool operator==(Iterator other) const { - return mCurrFlag == other.mCurrFlag && mRemainingFlags == other.mRemainingFlags; - } - - bool operator!=(Iterator other) const { return !(*this == other); } - - F operator*() { return mCurrFlag; } - - // iterator traits - - // In the future we could make this a bidirectional const iterator instead of a forward - // iterator but it doesn't seem worth the added complexity at this point. This could not, - // however, be made a non-const iterator as assigning one flag to another is a non-sensical - // operation. - using iterator_category = std::input_iterator_tag; - using value_type = F; - // Per the C++ spec, because input iterators are not assignable the iterator's reference - // type does not actually need to be a reference. In fact, making it a reference would imply - // that modifying it would change the underlying Flags object, which is obviously wrong for - // the same reason this can't be a non-const iterator. - using reference = F; - using difference_type = void; - using pointer = void; - - private: - BitSet64 mRemainingFlags; - F mCurrFlag; - }; - - /* - * Tests whether the given flag is set. - */ - bool test(F flag) const { - U f = static_cast(flag); - return (f & mFlags) == f; - } - - /* Tests whether any of the given flags are set */ - bool any(Flags f) { return (mFlags & f.mFlags) != 0; } - - /* Tests whether all of the given flags are set */ - bool all(Flags f) { return (mFlags & f.mFlags) == f.mFlags; } - - Flags operator|(Flags rhs) const { return static_cast(mFlags | rhs.mFlags); } - Flags& operator|=(Flags rhs) { - mFlags = mFlags | rhs.mFlags; - return *this; - } - - Flags operator&(Flags rhs) const { return static_cast(mFlags & rhs.mFlags); } - Flags& operator&=(Flags rhs) { - mFlags = mFlags & rhs.mFlags; - return *this; - } - - Flags operator^(Flags rhs) const { return static_cast(mFlags ^ rhs.mFlags); } - Flags& operator^=(Flags rhs) { - mFlags = mFlags ^ rhs.mFlags; - return *this; - } - - Flags operator~() { return static_cast(~mFlags); } - - bool operator==(Flags rhs) const { return mFlags == rhs.mFlags; } - bool operator!=(Flags rhs) const { return !operator==(rhs); } - - Flags& operator=(const Flags& rhs) { - mFlags = rhs.mFlags; - return *this; - } - - Iterator begin() const { return Iterator(*this); } - - Iterator end() const { return Iterator(); } - - /* - * Returns the stored set of flags. - * - * Note that this returns the underlying type rather than the base enum class. This is because - * the value is no longer necessarily a strict member of the enum since the returned value could - * be multiple enum variants OR'd together. - */ - U get() const { return mFlags; } - - std::string string() const { - std::string result; - bool first = true; - U unstringified = 0; - for (const F f : *this) { - std::optional flagString = flag_name(f); - if (flagString) { - appendFlag(result, flagString.value(), first); - } else { - unstringified |= static_cast(f); - } - } - - if (unstringified != 0) { - appendFlag(result, base::StringPrintf("0x%08x", unstringified), first); - } - - if (first) { - result += "0x0"; - } - - return result; - } - -private: - U mFlags; - - static void appendFlag(std::string& str, const std::string_view& flag, bool& first) { - if (first) { - first = false; - } else { - str += " | "; - } - str += flag; - } -}; - -// This namespace provides operator overloads for enum classes to make it easier to work with them -// as flags. In order to use these, add them via a `using namespace` declaration. -namespace flag_operators { - -template >> -inline Flags operator~(F f) { - using U = typename std::underlying_type_t; - return static_cast(~static_cast(f)); -} -template >> -Flags operator|(F lhs, F rhs) { - using U = typename std::underlying_type_t; - return static_cast(static_cast(lhs) | static_cast(rhs)); -} - -} // namespace flag_operators -} // namespace android - -#endif // __UI_INPUT_FLAGS_H diff --git a/include/input/Input.h b/include/input/Input.h index 438121b30e..3bac7636e7 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -105,15 +105,6 @@ constexpr int32_t VERIFIED_MOTION_EVENT_FLAGS = */ constexpr int32_t AMOTION_EVENT_FLAG_CANCELED = 0x20; -enum { - /* Used when a motion 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, -}; - enum { /* * Indicates that an input device has switches. @@ -338,12 +329,6 @@ private: */ constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits::quiet_NaN(); -/** - * Invalid value for display size. Used when display size isn't available for an event or doesn't - * matter. This is just a constant 0 so that it has no effect if unused. - */ -constexpr int32_t AMOTION_EVENT_INVALID_DISPLAY_SIZE = 0; - /* * Pointer coordinate data. */ diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h deleted file mode 100644 index 8e4fe796a5..0000000000 --- a/include/input/InputApplication.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#ifndef _UI_INPUT_APPLICATION_H -#define _UI_INPUT_APPLICATION_H - -#include - -#include - -#include -#include -#include - -#include -#include -#include - -namespace android { -/* - * Handle for an application that can receive input. - * - * Used by the native input dispatcher as a handle for the window manager objects - * that describe an application. - */ -class InputApplicationHandle { -public: - inline const InputApplicationInfo* getInfo() const { - return &mInfo; - } - - inline std::string getName() const { - return !mInfo.name.empty() ? mInfo.name : ""; - } - - inline std::chrono::nanoseconds getDispatchingTimeout( - std::chrono::nanoseconds defaultValue) const { - return mInfo.token ? std::chrono::milliseconds(mInfo.dispatchingTimeoutMillis) - : defaultValue; - } - - inline sp getApplicationToken() const { - return mInfo.token; - } - - bool operator==(const InputApplicationHandle& other) const { - return getName() == other.getName() && getApplicationToken() == other.getApplicationToken(); - } - - bool operator!=(const InputApplicationHandle& other) const { return !(*this == other); } - - /** - * Requests that the state of this object be updated to reflect - * the most current available information about the application. - * - * This method should only be called from within the input dispatcher's - * critical section. - * - * Returns true on success, or false if the handle is no longer valid. - */ - virtual bool updateInfo() = 0; - -protected: - InputApplicationHandle() = default; - virtual ~InputApplicationHandle() = default; - - InputApplicationInfo mInfo; -}; - -} // namespace android - -#endif // _UI_INPUT_APPLICATION_H diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h deleted file mode 100644 index 121be6d963..0000000000 --- a/include/input/InputWindow.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#ifndef _UI_INPUT_WINDOW_H -#define _UI_INPUT_WINDOW_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "InputApplication.h" - -using android::os::TouchOcclusionMode; - -namespace android { - -/* - * Describes the properties of a window that can receive input. - */ -struct InputWindowInfo : public Parcelable { - InputWindowInfo() = default; - - // Window flags from WindowManager.LayoutParams - enum class Flag : uint32_t { - ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, - DIM_BEHIND = 0x00000002, - BLUR_BEHIND = 0x00000004, - NOT_FOCUSABLE = 0x00000008, - NOT_TOUCHABLE = 0x00000010, - NOT_TOUCH_MODAL = 0x00000020, - TOUCHABLE_WHEN_WAKING = 0x00000040, - KEEP_SCREEN_ON = 0x00000080, - LAYOUT_IN_SCREEN = 0x00000100, - LAYOUT_NO_LIMITS = 0x00000200, - FULLSCREEN = 0x00000400, - FORCE_NOT_FULLSCREEN = 0x00000800, - DITHER = 0x00001000, - SECURE = 0x00002000, - SCALED = 0x00004000, - IGNORE_CHEEK_PRESSES = 0x00008000, - LAYOUT_INSET_DECOR = 0x00010000, - ALT_FOCUSABLE_IM = 0x00020000, - WATCH_OUTSIDE_TOUCH = 0x00040000, - SHOW_WHEN_LOCKED = 0x00080000, - SHOW_WALLPAPER = 0x00100000, - TURN_SCREEN_ON = 0x00200000, - DISMISS_KEYGUARD = 0x00400000, - SPLIT_TOUCH = 0x00800000, - HARDWARE_ACCELERATED = 0x01000000, - LAYOUT_IN_OVERSCAN = 0x02000000, - TRANSLUCENT_STATUS = 0x04000000, - TRANSLUCENT_NAVIGATION = 0x08000000, - LOCAL_FOCUS_MODE = 0x10000000, - SLIPPERY = 0x20000000, - LAYOUT_ATTACHED_IN_DECOR = 0x40000000, - DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000, - }; // Window types from WindowManager.LayoutParams - - enum class Type : int32_t { - UNKNOWN = 0, - FIRST_APPLICATION_WINDOW = 1, - BASE_APPLICATION = 1, - APPLICATION = 2, - APPLICATION_STARTING = 3, - LAST_APPLICATION_WINDOW = 99, - FIRST_SUB_WINDOW = 1000, - APPLICATION_PANEL = FIRST_SUB_WINDOW, - APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1, - APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2, - APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3, - APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4, - LAST_SUB_WINDOW = 1999, - FIRST_SYSTEM_WINDOW = 2000, - STATUS_BAR = FIRST_SYSTEM_WINDOW, - SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1, - PHONE = FIRST_SYSTEM_WINDOW + 2, - SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3, - KEYGUARD = FIRST_SYSTEM_WINDOW + 4, - TOAST = FIRST_SYSTEM_WINDOW + 5, - SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6, - PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7, - SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8, - KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9, - SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10, - INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11, - INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12, - WALLPAPER = FIRST_SYSTEM_WINDOW + 13, - STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14, - SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15, - DRAG = FIRST_SYSTEM_WINDOW + 16, - STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17, - POINTER = FIRST_SYSTEM_WINDOW + 18, - NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19, - VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20, - BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21, - INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22, - NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24, - MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27, - ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32, - DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, - ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39, - NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, - LAST_SYSTEM_WINDOW = 2999, - }; - - enum class Feature { - DISABLE_TOUCH_PAD_GESTURES = 0x00000001, - NO_INPUT_CHANNEL = 0x00000002, - DISABLE_USER_ACTIVITY = 0x00000004, - }; - - /* These values are filled in by the WM and passed through SurfaceFlinger - * unless specified otherwise. - */ - // This value should NOT be used to uniquely identify the window. There may be different - // input windows that have the same token. - sp token; - // This uniquely identifies the input window. - int32_t id = -1; - std::string name; - Flags flags; - Type type = Type::UNKNOWN; - std::chrono::nanoseconds dispatchingTimeout = std::chrono::seconds(5); - - /* These values are filled in by SurfaceFlinger. */ - int32_t frameLeft = -1; - int32_t frameTop = -1; - int32_t frameRight = -1; - int32_t frameBottom = -1; - - /* - * SurfaceFlinger consumes this value to shrink the computed frame. This is - * different from shrinking the touchable region in that it DOES shift the coordinate - * space where-as the touchable region does not and is more like "cropping". This - * is used for window shadows. - */ - int32_t surfaceInset = 0; - - // A global scaling factor for all windows. Unlike windowScaleX/Y this results - // in scaling of the TOUCH_MAJOR/TOUCH_MINOR axis. - float globalScaleFactor = 1.0f; - - // The opacity of this window, from 0.0 to 1.0 (inclusive). - // An alpha of 1.0 means fully opaque and 0.0 means fully transparent. - float alpha; - - // Transform applied to individual windows. - ui::Transform transform; - - // Display size in its natural rotation. Used to rotate raw coordinates for compatibility. - int32_t displayWidth = AMOTION_EVENT_INVALID_DISPLAY_SIZE; - int32_t displayHeight = AMOTION_EVENT_INVALID_DISPLAY_SIZE; - - /* - * This is filled in by the WM relative to the frame and then translated - * to absolute coordinates by SurfaceFlinger once the frame is computed. - */ - Region touchableRegion; - bool visible = false; - bool focusable = false; - bool hasWallpaper = false; - bool paused = false; - /* This flag is set when the window is of a trusted type that is allowed to silently - * overlay other windows for the purpose of implementing the secure views feature. - * Trusted overlays, such as IME windows, can partly obscure other windows without causing - * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. - */ - bool trustedOverlay = false; - TouchOcclusionMode touchOcclusionMode = TouchOcclusionMode::BLOCK_UNTRUSTED; - int32_t ownerPid = -1; - int32_t ownerUid = -1; - std::string packageName; - Flags inputFeatures; - int32_t displayId = ADISPLAY_ID_NONE; - int32_t portalToDisplayId = ADISPLAY_ID_NONE; - InputApplicationInfo applicationInfo; - bool replaceTouchableRegionWithCrop = false; - wp touchableRegionCropHandle; - - 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 overlaps(const InputWindowInfo* other) const; - - bool operator==(const InputWindowInfo& inputChannel) const; - - status_t writeToParcel(android::Parcel* parcel) const override; - - status_t readFromParcel(const android::Parcel* parcel) override; -}; - -/* - * Handle for a window that can receive input. - * - * Used by the native input dispatcher to indirectly refer to the window manager objects - * that describe a window. - */ -class InputWindowHandle : public RefBase { -public: - explicit InputWindowHandle(); - InputWindowHandle(const InputWindowHandle& other); - InputWindowHandle(const InputWindowInfo& other); - - inline const InputWindowInfo* getInfo() const { return &mInfo; } - - sp getToken() const; - - int32_t getId() const { return mInfo.id; } - - sp getApplicationToken() { return mInfo.applicationInfo.token; } - - inline std::string getName() const { return !mInfo.name.empty() ? mInfo.name : ""; } - - inline std::chrono::nanoseconds getDispatchingTimeout( - std::chrono::nanoseconds defaultValue) const { - return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeout) : defaultValue; - } - - /** - * Requests that the state of this object be updated to reflect - * the most current available information about the application. - * As this class is created as RefBase object, no pure virtual function is allowed. - * - * This method should only be called from within the input dispatcher's - * critical section. - * - * Returns true on success, or false if the handle is no longer valid. - */ - virtual bool updateInfo() { return false; } - - /** - * Updates from another input window handle. - */ - void updateFrom(const sp handle); - - /** - * Releases the channel used by the associated information when it is - * no longer needed. - */ - void releaseChannel(); - - // Not override since this class is not derrived from Parcelable. - status_t readFromParcel(const android::Parcel* parcel); - status_t writeToParcel(android::Parcel* parcel) const; - -protected: - virtual ~InputWindowHandle(); - - InputWindowInfo mInfo; -}; -} // namespace android - -#endif // _UI_INPUT_WINDOW_H diff --git a/include/input/NamedEnum.h b/include/input/NamedEnum.h deleted file mode 100644 index 6562348701..0000000000 --- a/include/input/NamedEnum.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#ifndef __UI_INPUT_NAMEDENUM_H -#define __UI_INPUT_NAMEDENUM_H - -namespace android { - -namespace details { -template -constexpr std::optional enum_value_name() { - // Should look something like (but all on one line): - // std::optional - // android::details::enum_value_name() - // [E = android::test::TestEnums, V = android::test::TestEnums::ONE] - std::string_view view = __PRETTY_FUNCTION__; - size_t templateStart = view.rfind("["); - size_t templateEnd = view.rfind("]"); - if (templateStart == std::string::npos || templateEnd == std::string::npos) { - return std::nullopt; - } - - // Extract the template parameters without the enclosing braces. - // Example (cont'd): E = android::test::TestEnums, V = android::test::TestEnums::ONE - view = view.substr(templateStart + 1, templateEnd - templateStart - 1); - size_t valStart = view.rfind("V = "); - if (valStart == std::string::npos) { - return std::nullopt; - } - - // Example (cont'd): V = android::test::TestEnums::ONE - view = view.substr(valStart); - size_t nameStart = view.rfind("::"); - if (nameStart == std::string::npos) { - return std::nullopt; - } - - // Chop off the initial "::" - nameStart += 2; - return view.substr(nameStart); -} - -template -constexpr auto generate_enum_values(std::integer_sequence seq) { - constexpr size_t count = seq.size(); - - std::array values{}; - for (size_t i = 0, v = 0; v < count; ++i) { - values[v++] = static_cast(T{0} + i); - } - - return values; -} - -template -inline constexpr auto enum_values = - generate_enum_values(std::make_integer_sequence, N>{}); - -template -constexpr auto generate_enum_names(std::index_sequence) noexcept { - return std::array, sizeof...(I)>{ - {enum_value_name[I]>()...}}; -} - -template -inline constexpr auto enum_names = generate_enum_names(std::make_index_sequence{}); - -} // namespace details - -class NamedEnum { -public: - // By default allowed enum value range is 0 ~ 7. - template - static constexpr size_t max = 8; - - template - static constexpr auto enum_name() { - using E = decltype(V); - return details::enum_value_name(); - } - - template - static constexpr std::optional enum_name(E val) { - auto idx = static_cast(val); - return idx < max ? details::enum_names>[idx] : std::nullopt; - } - - // Helper function for parsing enum value to string. - // Example : enum class TestEnums { ZERO = 0x0 }; - // NamedEnum::string(TestEnums::ZERO) returns string of "ZERO". - // Note the default maximum enum is 8, if the enum ID to be parsed if greater than 8 like 16, - // it should be declared to specialized the maximum enum by below: - // template <> constexpr size_t NamedEnum::max = 16; - // If the enum class definition is sparse and contains enum values starting from a large value, - // Do not specialize it to a large number to avoid performance issues. - // The recommended maximum enum number to specialize is 64. - template - static const std::string string(E val, const char* fallbackFormat = "%02d") { - std::string result; - std::optional enumString = enum_name(val); - result += enumString ? enumString.value() : base::StringPrintf(fallbackFormat, val); - return result; - } -}; - -} // namespace android - -#endif // __UI_INPUT_NAMEDENUM_H \ No newline at end of file diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp index 436620350a..3026921044 100644 --- a/libs/ftl/Android.bp +++ b/libs/ftl/Android.bp @@ -15,7 +15,9 @@ cc_test { }, srcs: [ "cast_test.cpp", + "Flags_test.cpp", "future_test.cpp", + "NamedEnum_test.cpp", "small_map_test.cpp", "small_vector_test.cpp", "static_vector_test.cpp", @@ -27,4 +29,12 @@ cc_test { "-Wextra", "-Wpedantic", ], + + header_libs: [ + "libbase_headers", + ], + + shared_libs: [ + "libbase", + ], } diff --git a/libs/ftl/Flags_test.cpp b/libs/ftl/Flags_test.cpp new file mode 100644 index 0000000000..8c00b5299b --- /dev/null +++ b/libs/ftl/Flags_test.cpp @@ -0,0 +1,227 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +namespace android::test { + +using namespace android::flag_operators; + +enum class TestFlags { ONE = 0x1, TWO = 0x2, THREE = 0x4 }; + +TEST(Flags, Test) { + Flags flags = TestFlags::ONE; + ASSERT_TRUE(flags.test(TestFlags::ONE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); + ASSERT_FALSE(flags.test(TestFlags::THREE)); +} + +TEST(Flags, Any) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_TRUE(flags.any(TestFlags::ONE)); + ASSERT_TRUE(flags.any(TestFlags::TWO)); + ASSERT_FALSE(flags.any(TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO)); + ASSERT_TRUE(flags.any(TestFlags::TWO | TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, All) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_TRUE(flags.all(TestFlags::ONE)); + ASSERT_TRUE(flags.all(TestFlags::TWO)); + ASSERT_FALSE(flags.all(TestFlags::THREE)); + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO)); + ASSERT_FALSE(flags.all(TestFlags::TWO | TestFlags::THREE)); + ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, DefaultConstructor_hasNoFlagsSet) { + Flags flags; + ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, NotOperator_onEmptyFlagsSetsAllFlags) { + Flags flags; + flags = ~flags; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, NotOperator_onNonEmptyFlagsInvertsFlags) { + Flags flags = TestFlags::TWO; + flags = ~flags; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); +} + +TEST(Flags, OrOperator_withNewFlag) { + Flags flags = TestFlags::ONE; + Flags flags2 = flags | TestFlags::TWO; + ASSERT_FALSE(flags2.test(TestFlags::THREE)); + ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, OrOperator_withExistingFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags flags2 = flags | TestFlags::THREE; + ASSERT_FALSE(flags2.test(TestFlags::TWO)); + ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::THREE)); +} + +TEST(Flags, OrEqualsOperator_withNewFlag) { + Flags flags; + flags |= TestFlags::THREE; + ASSERT_TRUE(flags.test(TestFlags::THREE)); + ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, OrEqualsOperator_withExistingFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + flags |= TestFlags::THREE; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withOneSetFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & TestFlags::THREE; + ASSERT_TRUE(andFlags.test(TestFlags::THREE)); + ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withMultipleSetFlags) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & (TestFlags::ONE | TestFlags::THREE); + ASSERT_TRUE(andFlags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(andFlags.test(TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withNoSetFlags) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & TestFlags::TWO; + ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, Equality) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags1, flags2); +} + +TEST(Flags, Inequality) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = TestFlags::ONE | TestFlags::THREE; + ASSERT_NE(flags1, flags2); +} + +TEST(Flags, EqualsOperator) { + Flags flags; + flags = TestFlags::ONE; + ASSERT_TRUE(flags.test(TestFlags::ONE)); + ASSERT_FALSE(flags.any(TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, EqualsOperator_DontShareState) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = flags1; + ASSERT_EQ(flags1, flags2); + + flags1 &= TestFlags::TWO; + ASSERT_NE(flags1, flags2); +} + +TEST(Flags, GetValue) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags.get(), 0x3); +} + +TEST(Flags, String_NoFlags) { + Flags flags; + ASSERT_EQ(flags.string(), "0x0"); +} + +TEST(Flags, String_KnownValues) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags.string(), "ONE | TWO"); +} + +TEST(Flags, String_UnknownValues) { + auto flags = Flags(0b1011); + ASSERT_EQ(flags.string(), "ONE | TWO | 0x00000008"); +} + +TEST(FlagsIterator, IteratesOverAllFlags) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2; + for (TestFlags f : flags1) { + flags2 |= f; + } + ASSERT_EQ(flags2, flags1); +} + +TEST(FlagsIterator, IteratesInExpectedOrder) { + const std::vector flagOrder = {TestFlags::ONE, TestFlags::TWO}; + Flags flags; + for (TestFlags f : flagOrder) { + flags |= f; + } + + size_t idx = 0; + auto iter = flags.begin(); + while (iter != flags.end() && idx < flagOrder.size()) { + // Make sure the order is what we expect + ASSERT_EQ(*iter, flagOrder[idx]); + iter++; + idx++; + } + ASSERT_EQ(iter, flags.end()); +} +TEST(FlagsIterator, PostFixIncrement) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + auto iter = flags.begin(); + ASSERT_EQ(*(iter++), TestFlags::ONE); + ASSERT_EQ(*iter, TestFlags::TWO); + ASSERT_EQ(*(iter++), TestFlags::TWO); + ASSERT_EQ(iter, flags.end()); +} + +TEST(FlagsIterator, PreFixIncrement) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + auto iter = flags.begin(); + ASSERT_EQ(*++iter, TestFlags::TWO); + ASSERT_EQ(++iter, flags.end()); +} + +TEST(FlagNames, RuntimeFlagName) { + TestFlags f = TestFlags::ONE; + ASSERT_EQ(flag_name(f), "ONE"); +} + +TEST(FlagNames, RuntimeUnknownFlagName) { + TestFlags f = static_cast(0x8); + ASSERT_EQ(flag_name(f), std::nullopt); +} + +TEST(FlagNames, CompileTimeFlagName) { + static_assert(flag_name() == "TWO"); +} + +} // namespace android::test \ No newline at end of file diff --git a/libs/ftl/NamedEnum_test.cpp b/libs/ftl/NamedEnum_test.cpp new file mode 100644 index 0000000000..dff2b8aaa1 --- /dev/null +++ b/libs/ftl/NamedEnum_test.cpp @@ -0,0 +1,101 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace android { + +// Test enum class maximum enum value smaller than default maximum of 8. +enum class TestEnums { ZERO = 0x0, ONE = 0x1, TWO = 0x2, THREE = 0x3, SEVEN = 0x7 }; +// Big enum contains enum values greater than default maximum of 8. +enum class TestBigEnums { ZERO = 0x0, FIFTEEN = 0xF }; + +// Declared to specialize the maximum enum since the enum size exceeds 8 by default. +template <> +constexpr size_t NamedEnum::max = 16; + +namespace test { +using android::TestBigEnums; +using android::TestEnums; + +TEST(NamedEnum, RuntimeNamedEnum) { + TestEnums e = TestEnums::ZERO; + ASSERT_EQ(NamedEnum::enum_name(e), "ZERO"); + + e = TestEnums::ONE; + ASSERT_EQ(NamedEnum::enum_name(e), "ONE"); + + e = TestEnums::THREE; + ASSERT_EQ(NamedEnum::enum_name(e), "THREE"); + + e = TestEnums::SEVEN; + ASSERT_EQ(NamedEnum::enum_name(e), "SEVEN"); +} + +// Test big enum +TEST(NamedEnum, RuntimeBigNamedEnum) { + TestBigEnums e = TestBigEnums::ZERO; + ASSERT_EQ(NamedEnum::enum_name(e), "ZERO"); + + e = TestBigEnums::FIFTEEN; + ASSERT_EQ(NamedEnum::enum_name(e), "FIFTEEN"); +} + +TEST(NamedEnum, RuntimeNamedEnumAsString) { + TestEnums e = TestEnums::ZERO; + ASSERT_EQ(NamedEnum::string(e), "ZERO"); + + e = TestEnums::ONE; + ASSERT_EQ(NamedEnum::string(e), "ONE"); + + e = TestEnums::THREE; + ASSERT_EQ(NamedEnum::string(e), "THREE"); + + e = TestEnums::SEVEN; + ASSERT_EQ(NamedEnum::string(e), "SEVEN"); +} + +TEST(NamedEnum, RuntimeBigNamedEnumAsString) { + TestBigEnums e = TestBigEnums::ZERO; + ASSERT_EQ(NamedEnum::string(e), "ZERO"); + + e = TestBigEnums::FIFTEEN; + ASSERT_EQ(NamedEnum::string(e), "FIFTEEN"); +} + +TEST(NamedEnum, RuntimeUnknownNamedEnum) { + TestEnums e = static_cast(0x5); + ASSERT_EQ(NamedEnum::enum_name(e), std::nullopt); + e = static_cast(0x9); + ASSERT_EQ(NamedEnum::enum_name(e), std::nullopt); +} + +TEST(NamedEnum, RuntimeUnknownNamedEnumAsString) { + TestEnums e = static_cast(0x5); + ASSERT_EQ(NamedEnum::string(e), "05"); + e = static_cast(0x9); + ASSERT_EQ(NamedEnum::string(e, "0x%08x"), "0x00000009"); +} + +TEST(NamedEnum, CompileTimeFlagName) { + static_assert(NamedEnum::enum_name() == "TWO"); + static_assert(NamedEnum::enum_name() == "THREE"); +} + +} // namespace test + +} // namespace android diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 64203f78a8..2d8fff91da 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -51,6 +51,51 @@ cc_library_headers { ], } +// AIDL files that should be exposed to java +filegroup { + name: "guiconstants_aidl", + srcs: [ + "android/**/TouchOcclusionMode.aidl", + ], +} + +cc_library_static { + name: "libgui_window_info_static", + vendor_available: true, + host_supported: true, + srcs: [ + ":guiconstants_aidl", + "android/gui/FocusRequest.aidl", + "android/gui/InputApplicationInfo.aidl", + "android/gui/WindowInfo.aidl", + "WindowInfo.cpp", + ], + + shared_libs: [ + "libbinder", + ], + + local_include_dirs: [ + "include", + ], + + export_shared_lib_headers: [ + "libbinder", + ], + + static_libs: [ + "libui-types", + ], + + aidl: { + export_aidl_headers: true + }, + + include_dirs: [ + "frameworks/native/include", + ], +} + filegroup { name: "libgui_aidl", srcs: ["aidl/**/*.aidl"], @@ -77,12 +122,15 @@ cc_library_static { "libbinder", ], + static_libs: [ + "libui-types", + ], + aidl: { export_aidl_headers: true } } - cc_library_shared { name: "libgui", vendor_available: true, @@ -96,9 +144,11 @@ cc_library_shared { static_libs: [ "libgui_aidl_static", + "libgui_window_info_static", ], export_static_lib_headers: [ "libgui_aidl_static", + "libgui_window_info_static", ], srcs: [ @@ -150,13 +200,11 @@ cc_library_shared { "libbinder", "libbufferhub", "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui. - "libinput", "libpdx_default_transport", ], export_shared_lib_headers: [ "libbinder", - "libinput", ], export_header_lib_headers: [ @@ -168,7 +216,6 @@ cc_library_shared { vendor: { cflags: [ "-DNO_BUFFERHUB", - "-DNO_INPUT", ], exclude_srcs: [ "BufferHubConsumer.cpp", @@ -178,7 +225,6 @@ cc_library_shared { "android.frameworks.bufferhub@1.0", "libbufferhub", "libbufferhubqueue", - "libinput", "libpdx_default_transport", ], }, diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 29701168e7..dbb1cb0c17 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -38,7 +38,7 @@ using namespace std::chrono_literals; namespace { -inline const char* toString(bool b) { +inline const char* boolToString(bool b) { return b ? "true" : "false"; } } // namespace @@ -513,7 +513,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d" " graphicBufferId=%" PRIu64 "%s", - mSize.width, mSize.height, bufferItem.mFrameNumber, toString(applyTransaction), + mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction), bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "", static_cast(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(), bufferItem.mAutoRefresh ? " mAutoRefresh" : ""); @@ -543,7 +543,7 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { mNumFrameAvailable + mNumAcquired - mPendingRelease.size()); BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, - toString(nextTransactionSet)); + boolToString(nextTransactionSet)); processNextBufferLocked(nextTransactionSet /* useNextTransaction */); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index d102e07623..001570c391 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -31,6 +31,9 @@ namespace android { +using gui::FocusRequest; +using gui::WindowInfoHandle; + layer_state_t::layer_state_t() : what(0), x(0), @@ -94,9 +97,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeFloat, color.r); SAFE_PARCEL(output.writeFloat, color.g); SAFE_PARCEL(output.writeFloat, color.b); -#ifndef NO_INPUT - SAFE_PARCEL(inputHandle->writeToParcel, &output); -#endif + SAFE_PARCEL(windowInfoHandle->writeToParcel, &output); SAFE_PARCEL(output.write, transparentRegion); SAFE_PARCEL(output.writeUint32, transform); SAFE_PARCEL(output.writeBool, transformToDisplayInverse); @@ -205,9 +206,7 @@ status_t layer_state_t::read(const Parcel& input) color.g = tmpFloat; SAFE_PARCEL(input.readFloat, &tmpFloat); color.b = tmpFloat; -#ifndef NO_INPUT - SAFE_PARCEL(inputHandle->readFromParcel, &input); -#endif + SAFE_PARCEL(windowInfoHandle->readFromParcel, &input); SAFE_PARCEL(input.read, transparentRegion); SAFE_PARCEL(input.readUint32, &transform); @@ -491,14 +490,10 @@ void layer_state_t::merge(const layer_state_t& other) { if (other.what & eHasListenerCallbacksChanged) { what |= eHasListenerCallbacksChanged; } - -#ifndef NO_INPUT if (other.what & eInputInfoChanged) { what |= eInputInfoChanged; - inputHandle = new InputWindowHandle(*other.inputHandle); + windowInfoHandle = new WindowInfoHandle(*other.windowInfoHandle); } -#endif - if (other.what & eCachedBufferChanged) { what |= eCachedBufferChanged; cachedBuffer = other.cachedBuffer; @@ -589,11 +584,9 @@ status_t layer_state_t::matrix22_t::read(const Parcel& input) { bool InputWindowCommands::merge(const InputWindowCommands& other) { bool changes = false; -#ifndef NO_INPUT changes |= !other.focusRequests.empty(); focusRequests.insert(focusRequests.end(), std::make_move_iterator(other.focusRequests.begin()), std::make_move_iterator(other.focusRequests.end())); -#endif changes |= other.syncInputWindows && !syncInputWindows; syncInputWindows |= other.syncInputWindows; return changes; @@ -601,31 +594,23 @@ bool InputWindowCommands::merge(const InputWindowCommands& other) { bool InputWindowCommands::empty() const { bool empty = true; -#ifndef NO_INPUT empty = focusRequests.empty() && !syncInputWindows; -#endif return empty; } void InputWindowCommands::clear() { -#ifndef NO_INPUT focusRequests.clear(); -#endif syncInputWindows = false; } status_t InputWindowCommands::write(Parcel& output) const { -#ifndef NO_INPUT SAFE_PARCEL(output.writeParcelableVector, focusRequests); -#endif SAFE_PARCEL(output.writeBool, syncInputWindows); return NO_ERROR; } status_t InputWindowCommands::read(const Parcel& input) { -#ifndef NO_INPUT SAFE_PARCEL(input.readParcelableVector, &focusRequests); -#endif SAFE_PARCEL(input.readBool, &syncInputWindows); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3118c72276..ec03c2105b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -39,14 +39,11 @@ #include #include #include +#include #include #include #include -#ifndef NO_INPUT -#include -#endif - #include // This server size should always be smaller than the server cache size @@ -54,6 +51,9 @@ namespace android { +using gui::FocusRequest; +using gui::WindowInfo; +using gui::WindowInfoHandle; using ui::ColorMode; // --------------------------------------------------------------------------- @@ -1491,16 +1491,14 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame return *this; } -#ifndef NO_INPUT SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo( - const sp& sc, - const InputWindowInfo& info) { + const sp& sc, const WindowInfo& info) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->inputHandle = new InputWindowHandle(info); + s->windowInfoHandle = new WindowInfoHandle(info); s->what |= layer_state_t::eInputInfoChanged; return *this; } @@ -1516,8 +1514,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInpu return *this; } -#endif - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform( const sp& sc, const mat3& matrix, const vec3& translation) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp new file mode 100644 index 0000000000..ff0bb8aa55 --- /dev/null +++ b/libs/gui/WindowInfo.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2011 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 +#define LOG_TAG "WindowInfo" +#define LOG_NDEBUG 0 + +#include +#include +#include + +#include + +namespace android::gui { + +// --- WindowInfo --- +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 >= frameLeft && x < frameRight && y >= frameTop && y < frameBottom; +} + +bool WindowInfo::supportsSplitTouch() const { + return flags.test(Flag::SPLIT_TOUCH); +} + +bool WindowInfo::overlaps(const WindowInfo* other) const { + return frameLeft < other->frameRight && frameRight > other->frameLeft && + frameTop < other->frameBottom && frameBottom > other->frameTop; +} + +bool WindowInfo::operator==(const WindowInfo& info) const { + return info.token == token && info.id == id && info.name == name && info.flags == flags && + info.type == type && info.dispatchingTimeout == dispatchingTimeout && + info.frameLeft == frameLeft && info.frameTop == frameTop && + info.frameRight == frameRight && info.frameBottom == frameBottom && + info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor && + info.transform == transform && info.displayWidth == displayWidth && + info.displayHeight == displayHeight && + info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible && + info.trustedOverlay == trustedOverlay && info.focusable == focusable && + info.touchOcclusionMode == touchOcclusionMode && info.hasWallpaper == hasWallpaper && + info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid && + info.packageName == packageName && info.inputFeatures == inputFeatures && + info.displayId == displayId && info.portalToDisplayId == portalToDisplayId && + info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && + info.applicationInfo == applicationInfo; +} + +status_t WindowInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + if (name.empty()) { + parcel->writeInt32(0); + return OK; + } + parcel->writeInt32(1); + + // clang-format off + status_t status = parcel->writeStrongBinder(token) ?: + parcel->writeInt64(dispatchingTimeout.count()) ?: + parcel->writeInt32(id) ?: + parcel->writeUtf8AsUtf16(name) ?: + parcel->writeInt32(flags.get()) ?: + parcel->writeInt32(static_cast>(type)) ?: + parcel->writeInt32(frameLeft) ?: + parcel->writeInt32(frameTop) ?: + parcel->writeInt32(frameRight) ?: + parcel->writeInt32(frameBottom) ?: + parcel->writeInt32(surfaceInset) ?: + parcel->writeFloat(globalScaleFactor) ?: + parcel->writeFloat(alpha) ?: + parcel->writeFloat(transform.dsdx()) ?: + parcel->writeFloat(transform.dtdx()) ?: + parcel->writeFloat(transform.tx()) ?: + parcel->writeFloat(transform.dtdy()) ?: + parcel->writeFloat(transform.dsdy()) ?: + parcel->writeFloat(transform.ty()) ?: + parcel->writeInt32(displayWidth) ?: + parcel->writeInt32(displayHeight) ?: + parcel->writeBool(visible) ?: + parcel->writeBool(focusable) ?: + parcel->writeBool(hasWallpaper) ?: + parcel->writeBool(paused) ?: + parcel->writeBool(trustedOverlay) ?: + parcel->writeInt32(static_cast(touchOcclusionMode)) ?: + parcel->writeInt32(ownerPid) ?: + parcel->writeInt32(ownerUid) ?: + parcel->writeUtf8AsUtf16(packageName) ?: + parcel->writeInt32(inputFeatures.get()) ?: + parcel->writeInt32(displayId) ?: + parcel->writeInt32(portalToDisplayId) ?: + applicationInfo.writeToParcel(parcel) ?: + parcel->write(touchableRegion) ?: + parcel->writeBool(replaceTouchableRegionWithCrop) ?: + parcel->writeStrongBinder(touchableRegionCropHandle.promote()); + // clang-format on + return status; +} + +status_t WindowInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + if (parcel->readInt32() == 0) { + return OK; + } + + token = parcel->readStrongBinder(); + dispatchingTimeout = static_cast(parcel->readInt64()); + status_t status = parcel->readInt32(&id) ?: parcel->readUtf8FromUtf16(&name); + if (status != OK) { + return status; + } + + flags = Flags(parcel->readInt32()); + type = static_cast(parcel->readInt32()); + float dsdx, dtdx, tx, dtdy, dsdy, ty; + int32_t touchOcclusionModeInt; + // clang-format off + status = parcel->readInt32(&frameLeft) ?: + parcel->readInt32(&frameTop) ?: + parcel->readInt32(&frameRight) ?: + parcel->readInt32(&frameBottom) ?: + parcel->readInt32(&surfaceInset) ?: + parcel->readFloat(&globalScaleFactor) ?: + parcel->readFloat(&alpha) ?: + parcel->readFloat(&dsdx) ?: + parcel->readFloat(&dtdx) ?: + parcel->readFloat(&tx) ?: + parcel->readFloat(&dtdy) ?: + parcel->readFloat(&dsdy) ?: + parcel->readFloat(&ty) ?: + parcel->readInt32(&displayWidth) ?: + parcel->readInt32(&displayHeight) ?: + parcel->readBool(&visible) ?: + parcel->readBool(&focusable) ?: + parcel->readBool(&hasWallpaper) ?: + parcel->readBool(&paused) ?: + parcel->readBool(&trustedOverlay) ?: + parcel->readInt32(&touchOcclusionModeInt) ?: + parcel->readInt32(&ownerPid) ?: + parcel->readInt32(&ownerUid) ?: + parcel->readUtf8FromUtf16(&packageName); + // clang-format on + + if (status != OK) { + return status; + } + + touchOcclusionMode = static_cast(touchOcclusionModeInt); + + inputFeatures = Flags(parcel->readInt32()); + // clang-format off + status = parcel->readInt32(&displayId) ?: + parcel->readInt32(&portalToDisplayId) ?: + applicationInfo.readFromParcel(parcel) ?: + parcel->read(touchableRegion) ?: + parcel->readBool(&replaceTouchableRegionWithCrop); + // clang-format on + + if (status != OK) { + return status; + } + + touchableRegionCropHandle = parcel->readStrongBinder(); + transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1}); + + return OK; +} + +// --- WindowInfoHandle --- + +WindowInfoHandle::WindowInfoHandle() {} + +WindowInfoHandle::~WindowInfoHandle() {} + +WindowInfoHandle::WindowInfoHandle(const WindowInfoHandle& other) : mInfo(other.mInfo) {} + +WindowInfoHandle::WindowInfoHandle(const WindowInfo& other) : mInfo(other) {} + +status_t WindowInfoHandle::writeToParcel(android::Parcel* parcel) const { + return mInfo.writeToParcel(parcel); +} + +status_t WindowInfoHandle::readFromParcel(const android::Parcel* parcel) { + return mInfo.readFromParcel(parcel); +} + +void WindowInfoHandle::releaseChannel() { + mInfo.token.clear(); +} + +sp WindowInfoHandle::getToken() const { + return mInfo.token; +} + +void WindowInfoHandle::updateFrom(sp handle) { + mInfo = handle->mInfo; +} +} // namespace android::gui diff --git a/libs/gui/android/gui/FocusRequest.aidl b/libs/gui/android/gui/FocusRequest.aidl new file mode 100644 index 0000000000..90186351c5 --- /dev/null +++ b/libs/gui/android/gui/FocusRequest.aidl @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + +/** @hide */ +parcelable FocusRequest { + /** + * Input channel token used to identify the window that should gain focus. + */ + IBinder token; + @utf8InCpp String windowName; + /** + * The token that the caller expects currently to be focused. If the + * specified token does not match the currently focused window, this request will be dropped. + * If the specified focused token matches the currently focused window, the call will succeed. + * Set this to "null" if this call should succeed no matter what the currently focused token + * is. + */ + @nullable IBinder focusedToken; + @utf8InCpp String focusedWindowName; + /** + * SYSTEM_TIME_MONOTONIC timestamp in nanos set by the client (wm) when requesting the focus + * change. This determines which request gets precedence if there is a focus change request + * from another source such as pointer down. + */ + long timestamp; + /** + * Display id associated with this request. + */ + int displayId; +} diff --git a/libs/gui/android/gui/InputApplicationInfo.aidl b/libs/gui/android/gui/InputApplicationInfo.aidl new file mode 100644 index 0000000000..c0fd666543 --- /dev/null +++ b/libs/gui/android/gui/InputApplicationInfo.aidl @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + +parcelable InputApplicationInfo { + @nullable IBinder token; + @utf8InCpp String name; + long dispatchingTimeoutMillis; +} diff --git a/libs/gui/android/gui/TouchOcclusionMode.aidl b/libs/gui/android/gui/TouchOcclusionMode.aidl new file mode 100644 index 0000000000..d91d052135 --- /dev/null +++ b/libs/gui/android/gui/TouchOcclusionMode.aidl @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + + +/** + * Touch occlusion modes: These modes represent how windows are taken into + * consideration in order to decide whether to block obscured touches or + * not. + * + * @hide + */ +@Backing(type="int") +enum TouchOcclusionMode { + /** + * Touches that pass through this window will be blocked if they are + * consumed by a different UID and this window is not trusted. + */ + BLOCK_UNTRUSTED, + + /** + * The window's opacity will be taken into consideration for touch + * occlusion rules if the touch passes through it and the window is not + * trusted. + */ + USE_OPACITY, + + /** + * The window won't count for touch occlusion rules if the touch passes + * through it. + */ + ALLOW +} diff --git a/libs/gui/android/gui/WindowInfo.aidl b/libs/gui/android/gui/WindowInfo.aidl new file mode 100644 index 0000000000..2c85d155a8 --- /dev/null +++ b/libs/gui/android/gui/WindowInfo.aidl @@ -0,0 +1,19 @@ +/* +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.gui; + +parcelable WindowInfo cpp_header "gui/WindowInfo.h"; diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 8ec7e6d630..c0a2335885 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -24,9 +24,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/libs/gui/include/gui/InputApplication.h b/libs/gui/include/gui/InputApplication.h new file mode 100644 index 0000000000..679c2a1754 --- /dev/null +++ b/libs/gui/include/gui/InputApplication.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef _UI_INPUT_APPLICATION_H +#define _UI_INPUT_APPLICATION_H + +#include + +#include + +#include +#include +#include + +#include +#include + +namespace android { + +/* + * Handle for an application that can receive input. + * + * Used by the native input dispatcher as a handle for the window manager objects + * that describe an application. + */ +class InputApplicationHandle { +public: + inline const gui::InputApplicationInfo* getInfo() const { return &mInfo; } + + inline std::string getName() const { return !mInfo.name.empty() ? mInfo.name : ""; } + + inline std::chrono::nanoseconds getDispatchingTimeout( + std::chrono::nanoseconds defaultValue) const { + return mInfo.token ? std::chrono::milliseconds(mInfo.dispatchingTimeoutMillis) + : defaultValue; + } + + inline sp getApplicationToken() const { return mInfo.token; } + + bool operator==(const InputApplicationHandle& other) const { + return getName() == other.getName() && getApplicationToken() == other.getApplicationToken(); + } + + bool operator!=(const InputApplicationHandle& other) const { return !(*this == other); } + + /** + * Requests that the state of this object be updated to reflect + * the most current available information about the application. + * + * This method should only be called from within the input dispatcher's + * critical section. + * + * Returns true on success, or false if the handle is no longer valid. + */ + virtual bool updateInfo() = 0; + +protected: + InputApplicationHandle() = default; + virtual ~InputApplicationHandle() = default; + + gui::InputApplicationInfo mInfo; +}; + +} // namespace android + +#endif // _UI_INPUT_APPLICATION_H diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 7961f4bd07..92de74a414 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -26,14 +26,12 @@ #include #include -#ifndef NO_INPUT -#include -#include (f)) {} - constexpr Flags() : mFlags(0) {} - constexpr Flags(const Flags& f) : mFlags(f.mFlags) {} - - // Provide a non-explicit construct for non-enum classes since they easily convert to their - // underlying types (e.g. when used with bitwise operators). For enum classes, however, we - // should force them to be explicitly constructed from their underlying types to make full use - // of the type checker. - template - constexpr Flags(T t, std::enable_if_t, T>* = nullptr) : mFlags(t) {} - - template - explicit constexpr Flags(T t, std::enable_if_t, T>* = nullptr) - : mFlags(t) {} - - class Iterator { - using Bits = std::uint64_t; - static_assert(sizeof(U) <= sizeof(Bits)); - - public: - constexpr Iterator() = default; - Iterator(Flags flags) : mRemainingFlags(flags.mFlags) { (*this)++; } - - // Pre-fix ++ - Iterator& operator++() { - if (mRemainingFlags.none()) { - mCurrFlag = 0; - } else { - // TODO: Replace with std::countr_zero in C++20. - const Bits bit = static_cast(__builtin_ctzll(mRemainingFlags.to_ullong())); - mRemainingFlags.reset(static_cast(bit)); - mCurrFlag = static_cast(static_cast(1) << bit); - } - return *this; - } - - // Post-fix ++ - Iterator operator++(int) { - Iterator iter = *this; - ++*this; - return iter; - } - - bool operator==(Iterator other) const { - return mCurrFlag == other.mCurrFlag && mRemainingFlags == other.mRemainingFlags; - } - - bool operator!=(Iterator other) const { return !(*this == other); } - - F operator*() const { return F{mCurrFlag}; } - - // iterator traits - - // In the future we could make this a bidirectional const iterator instead of a forward - // iterator but it doesn't seem worth the added complexity at this point. This could not, - // however, be made a non-const iterator as assigning one flag to another is a non-sensical - // operation. - using iterator_category = std::input_iterator_tag; - using value_type = F; - // Per the C++ spec, because input iterators are not assignable the iterator's reference - // type does not actually need to be a reference. In fact, making it a reference would imply - // that modifying it would change the underlying Flags object, which is obviously wrong for - // the same reason this can't be a non-const iterator. - using reference = F; - using difference_type = void; - using pointer = void; - - private: - std::bitset mRemainingFlags; - U mCurrFlag = 0; - }; - - /* - * Tests whether the given flag is set. - */ - bool test(F flag) const { - U f = static_cast(flag); - return (f & mFlags) == f; - } - - /* Tests whether any of the given flags are set */ - bool any(Flags f) const { return (mFlags & f.mFlags) != 0; } - - /* Tests whether all of the given flags are set */ - bool all(Flags f) const { return (mFlags & f.mFlags) == f.mFlags; } - - Flags operator|(Flags rhs) const { return static_cast(mFlags | rhs.mFlags); } - Flags& operator|=(Flags rhs) { - mFlags = mFlags | rhs.mFlags; - return *this; - } - - Flags operator&(Flags rhs) const { return static_cast(mFlags & rhs.mFlags); } - Flags& operator&=(Flags rhs) { - mFlags = mFlags & rhs.mFlags; - return *this; - } - - Flags operator^(Flags rhs) const { return static_cast(mFlags ^ rhs.mFlags); } - Flags& operator^=(Flags rhs) { - mFlags = mFlags ^ rhs.mFlags; - return *this; - } - - Flags operator~() { return static_cast(~mFlags); } - - bool operator==(Flags rhs) const { return mFlags == rhs.mFlags; } - bool operator!=(Flags rhs) const { return !operator==(rhs); } - - Flags& operator=(const Flags& rhs) { - mFlags = rhs.mFlags; - return *this; - } - - inline Flags& clear(Flags f = static_cast(~static_cast(0))) { - return *this &= ~f; - } - - Iterator begin() const { return Iterator(*this); } - - Iterator end() const { return Iterator(); } - - /* - * Returns the stored set of flags. - * - * Note that this returns the underlying type rather than the base enum class. This is because - * the value is no longer necessarily a strict member of the enum since the returned value could - * be multiple enum variants OR'd together. - */ - U get() const { return mFlags; } - - std::string string() const { - std::string result; - bool first = true; - U unstringified = 0; - for (const F f : *this) { - if (const auto flagName = ftl::flag_name(f)) { - appendFlag(result, flagName.value(), first); - } else { - unstringified |= static_cast(f); - } - } - - if (unstringified != 0) { - constexpr auto radix = sizeof(U) == 1 ? ftl::Radix::kBin : ftl::Radix::kHex; - appendFlag(result, ftl::to_string(unstringified, radix), first); - } - - if (first) { - result += "0x0"; - } - - return result; - } - -private: - U mFlags; - - static void appendFlag(std::string& str, const std::string_view& flag, bool& first) { - if (first) { - first = false; - } else { - str += " | "; - } - str += flag; - } -}; - -// This namespace provides operator overloads for enum classes to make it easier to work with them -// as flags. In order to use these, add them via a `using namespace` declaration. -namespace flag_operators { - -template >> -inline Flags operator~(F f) { - return static_cast(~ftl::to_underlying(f)); -} - -template >> -Flags operator|(F lhs, F rhs) { - return static_cast(ftl::to_underlying(lhs) | ftl::to_underlying(rhs)); -} - -} // namespace flag_operators -} // namespace android diff --git a/include/ftl/flags.h b/include/ftl/flags.h new file mode 100644 index 0000000000..70aaa0e6dd --- /dev/null +++ b/include/ftl/flags.h @@ -0,0 +1,225 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +// TODO(b/185536303): Align with FTL style. + +namespace android::ftl { + +/* A class for handling flags defined by an enum or enum class in a type-safe way. */ +template +class Flags { + // F must be an enum or its underlying type is undefined. Theoretically we could specialize this + // further to avoid this restriction but in general we want to encourage the use of enums + // anyways. + static_assert(std::is_enum_v, "Flags type must be an enum"); + using U = std::underlying_type_t; + +public: + constexpr Flags(F f) : mFlags(static_cast(f)) {} + constexpr Flags() : mFlags(0) {} + constexpr Flags(const Flags& f) : mFlags(f.mFlags) {} + + // Provide a non-explicit construct for non-enum classes since they easily convert to their + // underlying types (e.g. when used with bitwise operators). For enum classes, however, we + // should force them to be explicitly constructed from their underlying types to make full use + // of the type checker. + template + constexpr Flags(T t, std::enable_if_t, T>* = nullptr) : mFlags(t) {} + + template + explicit constexpr Flags(T t, std::enable_if_t, T>* = nullptr) + : mFlags(t) {} + + class Iterator { + using Bits = std::uint64_t; + static_assert(sizeof(U) <= sizeof(Bits)); + + public: + constexpr Iterator() = default; + Iterator(Flags flags) : mRemainingFlags(flags.mFlags) { (*this)++; } + + // Pre-fix ++ + Iterator& operator++() { + if (mRemainingFlags.none()) { + mCurrFlag = 0; + } else { + // TODO: Replace with std::countr_zero in C++20. + const Bits bit = static_cast(__builtin_ctzll(mRemainingFlags.to_ullong())); + mRemainingFlags.reset(static_cast(bit)); + mCurrFlag = static_cast(static_cast(1) << bit); + } + return *this; + } + + // Post-fix ++ + Iterator operator++(int) { + Iterator iter = *this; + ++*this; + return iter; + } + + bool operator==(Iterator other) const { + return mCurrFlag == other.mCurrFlag && mRemainingFlags == other.mRemainingFlags; + } + + bool operator!=(Iterator other) const { return !(*this == other); } + + F operator*() const { return F{mCurrFlag}; } + + // iterator traits + + // In the future we could make this a bidirectional const iterator instead of a forward + // iterator but it doesn't seem worth the added complexity at this point. This could not, + // however, be made a non-const iterator as assigning one flag to another is a non-sensical + // operation. + using iterator_category = std::input_iterator_tag; + using value_type = F; + // Per the C++ spec, because input iterators are not assignable the iterator's reference + // type does not actually need to be a reference. In fact, making it a reference would imply + // that modifying it would change the underlying Flags object, which is obviously wrong for + // the same reason this can't be a non-const iterator. + using reference = F; + using difference_type = void; + using pointer = void; + + private: + std::bitset mRemainingFlags; + U mCurrFlag = 0; + }; + + /* + * Tests whether the given flag is set. + */ + bool test(F flag) const { + U f = static_cast(flag); + return (f & mFlags) == f; + } + + /* Tests whether any of the given flags are set */ + bool any(Flags f) const { return (mFlags & f.mFlags) != 0; } + + /* Tests whether all of the given flags are set */ + bool all(Flags f) const { return (mFlags & f.mFlags) == f.mFlags; } + + Flags operator|(Flags rhs) const { return static_cast(mFlags | rhs.mFlags); } + Flags& operator|=(Flags rhs) { + mFlags = mFlags | rhs.mFlags; + return *this; + } + + Flags operator&(Flags rhs) const { return static_cast(mFlags & rhs.mFlags); } + Flags& operator&=(Flags rhs) { + mFlags = mFlags & rhs.mFlags; + return *this; + } + + Flags operator^(Flags rhs) const { return static_cast(mFlags ^ rhs.mFlags); } + Flags& operator^=(Flags rhs) { + mFlags = mFlags ^ rhs.mFlags; + return *this; + } + + Flags operator~() { return static_cast(~mFlags); } + + bool operator==(Flags rhs) const { return mFlags == rhs.mFlags; } + bool operator!=(Flags rhs) const { return !operator==(rhs); } + + Flags& operator=(const Flags& rhs) { + mFlags = rhs.mFlags; + return *this; + } + + inline Flags& clear(Flags f = static_cast(~static_cast(0))) { + return *this &= ~f; + } + + Iterator begin() const { return Iterator(*this); } + + Iterator end() const { return Iterator(); } + + /* + * Returns the stored set of flags. + * + * Note that this returns the underlying type rather than the base enum class. This is because + * the value is no longer necessarily a strict member of the enum since the returned value could + * be multiple enum variants OR'd together. + */ + U get() const { return mFlags; } + + std::string string() const { + std::string result; + bool first = true; + U unstringified = 0; + for (const F f : *this) { + if (const auto flagName = flag_name(f)) { + appendFlag(result, flagName.value(), first); + } else { + unstringified |= static_cast(f); + } + } + + if (unstringified != 0) { + constexpr auto radix = sizeof(U) == 1 ? Radix::kBin : Radix::kHex; + appendFlag(result, to_string(unstringified, radix), first); + } + + if (first) { + result += "0x0"; + } + + return result; + } + +private: + U mFlags; + + static void appendFlag(std::string& str, const std::string_view& flag, bool& first) { + if (first) { + first = false; + } else { + str += " | "; + } + str += flag; + } +}; + +// This namespace provides operator overloads for enum classes to make it easier to work with them +// as flags. In order to use these, add them via a `using namespace` declaration. +namespace flag_operators { + +template >> +inline Flags operator~(F f) { + return static_cast(~to_underlying(f)); +} + +template >> +Flags operator|(F lhs, F rhs) { + return static_cast(to_underlying(lhs) | to_underlying(rhs)); +} + +} // namespace flag_operators +} // namespace android::ftl diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp index ef201965ad..c010a2e58a 100644 --- a/libs/ftl/Android.bp +++ b/libs/ftl/Android.bp @@ -14,11 +14,11 @@ cc_test { address: true, }, srcs: [ - "Flags_test.cpp", "cast_test.cpp", "concat_test.cpp", "enum_test.cpp", "fake_guard_test.cpp", + "flags_test.cpp", "future_test.cpp", "small_map_test.cpp", "small_vector_test.cpp", diff --git a/libs/ftl/Flags_test.cpp b/libs/ftl/Flags_test.cpp deleted file mode 100644 index d241fa272a..0000000000 --- a/libs/ftl/Flags_test.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include - -namespace android::test { - -using namespace android::flag_operators; - -enum class TestFlags : uint8_t { ONE = 0x1, TWO = 0x2, THREE = 0x4 }; - -TEST(Flags, Test) { - Flags flags = TestFlags::ONE; - ASSERT_TRUE(flags.test(TestFlags::ONE)); - ASSERT_FALSE(flags.test(TestFlags::TWO)); - ASSERT_FALSE(flags.test(TestFlags::THREE)); -} - -TEST(Flags, Any) { - Flags flags = TestFlags::ONE | TestFlags::TWO; - ASSERT_TRUE(flags.any(TestFlags::ONE)); - ASSERT_TRUE(flags.any(TestFlags::TWO)); - ASSERT_FALSE(flags.any(TestFlags::THREE)); - ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO)); - ASSERT_TRUE(flags.any(TestFlags::TWO | TestFlags::THREE)); - ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::THREE)); - ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); -} - -TEST(Flags, All) { - Flags flags = TestFlags::ONE | TestFlags::TWO; - ASSERT_TRUE(flags.all(TestFlags::ONE)); - ASSERT_TRUE(flags.all(TestFlags::TWO)); - ASSERT_FALSE(flags.all(TestFlags::THREE)); - ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO)); - ASSERT_FALSE(flags.all(TestFlags::TWO | TestFlags::THREE)); - ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::THREE)); - ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); -} - -TEST(Flags, DefaultConstructor_hasNoFlagsSet) { - Flags flags; - ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); -} - -TEST(Flags, NotOperator_onEmptyFlagsSetsAllFlags) { - Flags flags; - flags = ~flags; - ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); -} - -TEST(Flags, NotOperator_onNonEmptyFlagsInvertsFlags) { - Flags flags = TestFlags::TWO; - flags = ~flags; - ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE)); - ASSERT_FALSE(flags.test(TestFlags::TWO)); -} - -TEST(Flags, OrOperator_withNewFlag) { - Flags flags = TestFlags::ONE; - Flags flags2 = flags | TestFlags::TWO; - ASSERT_FALSE(flags2.test(TestFlags::THREE)); - ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::TWO)); -} - -TEST(Flags, OrOperator_withExistingFlag) { - Flags flags = TestFlags::ONE | TestFlags::THREE; - Flags flags2 = flags | TestFlags::THREE; - ASSERT_FALSE(flags2.test(TestFlags::TWO)); - ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::THREE)); -} - -TEST(Flags, OrEqualsOperator_withNewFlag) { - Flags flags; - flags |= TestFlags::THREE; - ASSERT_TRUE(flags.test(TestFlags::THREE)); - ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO)); -} - -TEST(Flags, OrEqualsOperator_withExistingFlag) { - Flags flags = TestFlags::ONE | TestFlags::THREE; - flags |= TestFlags::THREE; - ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE)); - ASSERT_FALSE(flags.test(TestFlags::TWO)); -} - -TEST(Flags, AndOperator_withOneSetFlag) { - Flags flags = TestFlags::ONE | TestFlags::THREE; - Flags andFlags = flags & TestFlags::THREE; - ASSERT_TRUE(andFlags.test(TestFlags::THREE)); - ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO)); -} - -TEST(Flags, AndOperator_withMultipleSetFlags) { - Flags flags = TestFlags::ONE | TestFlags::THREE; - Flags andFlags = flags & (TestFlags::ONE | TestFlags::THREE); - ASSERT_TRUE(andFlags.all(TestFlags::ONE | TestFlags::THREE)); - ASSERT_FALSE(andFlags.test(TestFlags::TWO)); -} - -TEST(Flags, AndOperator_withNoSetFlags) { - Flags flags = TestFlags::ONE | TestFlags::THREE; - Flags andFlags = flags & TestFlags::TWO; - ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); -} - -TEST(Flags, Equality) { - Flags flags1 = TestFlags::ONE | TestFlags::TWO; - Flags flags2 = TestFlags::ONE | TestFlags::TWO; - ASSERT_EQ(flags1, flags2); -} - -TEST(Flags, Inequality) { - Flags flags1 = TestFlags::ONE | TestFlags::TWO; - Flags flags2 = TestFlags::ONE | TestFlags::THREE; - ASSERT_NE(flags1, flags2); -} - -TEST(Flags, EqualsOperator) { - Flags flags; - flags = TestFlags::ONE; - ASSERT_TRUE(flags.test(TestFlags::ONE)); - ASSERT_FALSE(flags.any(TestFlags::TWO | TestFlags::THREE)); -} - -TEST(Flags, EqualsOperator_DontShareState) { - Flags flags1 = TestFlags::ONE | TestFlags::TWO; - Flags flags2 = flags1; - ASSERT_EQ(flags1, flags2); - - flags1 &= TestFlags::TWO; - ASSERT_NE(flags1, flags2); -} - -TEST(Flags, GetValue) { - Flags flags = TestFlags::ONE | TestFlags::TWO; - ASSERT_EQ(flags.get(), 0x3); -} - -TEST(Flags, String_NoFlags) { - Flags flags; - ASSERT_EQ(flags.string(), "0x0"); -} - -TEST(Flags, String_KnownValues) { - Flags flags = TestFlags::ONE | TestFlags::TWO; - ASSERT_EQ(flags.string(), "ONE | TWO"); -} - -TEST(Flags, String_UnknownValues) { - auto flags = Flags(0b1011); - ASSERT_EQ(flags.string(), "ONE | TWO | 0b1000"); -} - -TEST(FlagsIterator, IteratesOverAllFlags) { - Flags flags1 = TestFlags::ONE | TestFlags::TWO; - Flags flags2; - for (TestFlags f : flags1) { - flags2 |= f; - } - ASSERT_EQ(flags2, flags1); -} - -TEST(FlagsIterator, IteratesInExpectedOrder) { - const std::vector flagOrder = {TestFlags::ONE, TestFlags::TWO}; - Flags flags; - for (TestFlags f : flagOrder) { - flags |= f; - } - - size_t idx = 0; - auto iter = flags.begin(); - while (iter != flags.end() && idx < flagOrder.size()) { - // Make sure the order is what we expect - ASSERT_EQ(*iter, flagOrder[idx]); - iter++; - idx++; - } - ASSERT_EQ(iter, flags.end()); -} -TEST(FlagsIterator, PostFixIncrement) { - Flags flags = TestFlags::ONE | TestFlags::TWO; - auto iter = flags.begin(); - ASSERT_EQ(*(iter++), TestFlags::ONE); - ASSERT_EQ(*iter, TestFlags::TWO); - ASSERT_EQ(*(iter++), TestFlags::TWO); - ASSERT_EQ(iter, flags.end()); -} - -TEST(FlagsIterator, PreFixIncrement) { - Flags flags = TestFlags::ONE | TestFlags::TWO; - auto iter = flags.begin(); - ASSERT_EQ(*++iter, TestFlags::TWO); - ASSERT_EQ(++iter, flags.end()); -} - -} // namespace android::test diff --git a/libs/ftl/flags_test.cpp b/libs/ftl/flags_test.cpp new file mode 100644 index 0000000000..eea052ba33 --- /dev/null +++ b/libs/ftl/flags_test.cpp @@ -0,0 +1,214 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +namespace android::test { + +using ftl::Flags; +using namespace ftl::flag_operators; + +enum class TestFlags : uint8_t { ONE = 0x1, TWO = 0x2, THREE = 0x4 }; + +TEST(Flags, Test) { + Flags flags = TestFlags::ONE; + ASSERT_TRUE(flags.test(TestFlags::ONE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); + ASSERT_FALSE(flags.test(TestFlags::THREE)); +} + +TEST(Flags, Any) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_TRUE(flags.any(TestFlags::ONE)); + ASSERT_TRUE(flags.any(TestFlags::TWO)); + ASSERT_FALSE(flags.any(TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO)); + ASSERT_TRUE(flags.any(TestFlags::TWO | TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, All) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_TRUE(flags.all(TestFlags::ONE)); + ASSERT_TRUE(flags.all(TestFlags::TWO)); + ASSERT_FALSE(flags.all(TestFlags::THREE)); + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO)); + ASSERT_FALSE(flags.all(TestFlags::TWO | TestFlags::THREE)); + ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, DefaultConstructor_hasNoFlagsSet) { + Flags flags; + ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, NotOperator_onEmptyFlagsSetsAllFlags) { + Flags flags; + flags = ~flags; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, NotOperator_onNonEmptyFlagsInvertsFlags) { + Flags flags = TestFlags::TWO; + flags = ~flags; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); +} + +TEST(Flags, OrOperator_withNewFlag) { + Flags flags = TestFlags::ONE; + Flags flags2 = flags | TestFlags::TWO; + ASSERT_FALSE(flags2.test(TestFlags::THREE)); + ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, OrOperator_withExistingFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags flags2 = flags | TestFlags::THREE; + ASSERT_FALSE(flags2.test(TestFlags::TWO)); + ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::THREE)); +} + +TEST(Flags, OrEqualsOperator_withNewFlag) { + Flags flags; + flags |= TestFlags::THREE; + ASSERT_TRUE(flags.test(TestFlags::THREE)); + ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, OrEqualsOperator_withExistingFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + flags |= TestFlags::THREE; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withOneSetFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & TestFlags::THREE; + ASSERT_TRUE(andFlags.test(TestFlags::THREE)); + ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withMultipleSetFlags) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & (TestFlags::ONE | TestFlags::THREE); + ASSERT_TRUE(andFlags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(andFlags.test(TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withNoSetFlags) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & TestFlags::TWO; + ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, Equality) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags1, flags2); +} + +TEST(Flags, Inequality) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = TestFlags::ONE | TestFlags::THREE; + ASSERT_NE(flags1, flags2); +} + +TEST(Flags, EqualsOperator) { + Flags flags; + flags = TestFlags::ONE; + ASSERT_TRUE(flags.test(TestFlags::ONE)); + ASSERT_FALSE(flags.any(TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, EqualsOperator_DontShareState) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = flags1; + ASSERT_EQ(flags1, flags2); + + flags1 &= TestFlags::TWO; + ASSERT_NE(flags1, flags2); +} + +TEST(Flags, GetValue) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags.get(), 0x3); +} + +TEST(Flags, String_NoFlags) { + Flags flags; + ASSERT_EQ(flags.string(), "0x0"); +} + +TEST(Flags, String_KnownValues) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags.string(), "ONE | TWO"); +} + +TEST(Flags, String_UnknownValues) { + auto flags = Flags(0b1011); + ASSERT_EQ(flags.string(), "ONE | TWO | 0b1000"); +} + +TEST(FlagsIterator, IteratesOverAllFlags) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2; + for (TestFlags f : flags1) { + flags2 |= f; + } + ASSERT_EQ(flags2, flags1); +} + +TEST(FlagsIterator, IteratesInExpectedOrder) { + const std::vector flagOrder = {TestFlags::ONE, TestFlags::TWO}; + Flags flags; + for (TestFlags f : flagOrder) { + flags |= f; + } + + size_t idx = 0; + auto iter = flags.begin(); + while (iter != flags.end() && idx < flagOrder.size()) { + // Make sure the order is what we expect + ASSERT_EQ(*iter, flagOrder[idx]); + iter++; + idx++; + } + ASSERT_EQ(iter, flags.end()); +} +TEST(FlagsIterator, PostFixIncrement) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + auto iter = flags.begin(); + ASSERT_EQ(*(iter++), TestFlags::ONE); + ASSERT_EQ(*iter, TestFlags::TWO); + ASSERT_EQ(*(iter++), TestFlags::TWO); + ASSERT_EQ(iter, flags.end()); +} + +TEST(FlagsIterator, PreFixIncrement) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + auto iter = flags.begin(); + ASSERT_EQ(*++iter, TestFlags::TWO); + ASSERT_EQ(++iter, flags.end()); +} + +} // namespace android::test diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 34db5b1626..53c7f5ac14 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -815,7 +815,7 @@ status_t BufferData::writeToParcel(Parcel* output) const { status_t BufferData::readFromParcel(const Parcel* input) { int32_t tmpInt32; SAFE_PARCEL(input->readInt32, &tmpInt32); - flags = Flags(tmpInt32); + flags = ftl::Flags(tmpInt32); bool tmpBool = false; SAFE_PARCEL(input->readBool, &tmpBool); diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp index 2312a8cf0d..804ce4fac0 100644 --- a/libs/gui/WindowInfo.cpp +++ b/libs/gui/WindowInfo.cpp @@ -14,10 +14,11 @@ * limitations under the License. */ -#include #define LOG_TAG "WindowInfo" #define LOG_NDEBUG 0 +#include + #include #include @@ -25,8 +26,7 @@ namespace android::gui { -// --- WindowInfo --- -void WindowInfo::setInputConfig(Flags config, bool value) { +void WindowInfo::setInputConfig(ftl::Flags config, bool value) { if (value) { inputConfig |= config; return; @@ -182,18 +182,16 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) { return status; } - layoutParamsFlags = Flags(lpFlags); + layoutParamsFlags = ftl::Flags(lpFlags); layoutParamsType = static_cast(lpType); transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1}); touchOcclusionMode = static_cast(touchOcclusionModeInt); - inputConfig = Flags(inputConfigInt); + inputConfig = ftl::Flags(inputConfigInt); touchableRegionCropHandle = touchableRegionCropHandleSp; return OK; } -// --- WindowInfoHandle --- - WindowInfoHandle::WindowInfoHandle() {} WindowInfoHandle::~WindowInfoHandle() {} diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 0a3cc19a13..b11e6748f0 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -126,7 +126,7 @@ public: frameRateOverride = 1 << 1, }; - using EventRegistrationFlags = Flags; + using EventRegistrationFlags = ftl::Flags; /* * Create a connection with SurfaceFlinger. diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 0f37dab53c..b33d4c0cc3 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -102,7 +103,7 @@ public: // was called with. sp releaseBufferEndpoint; - Flags flags; + ftl::Flags flags; client_cache_t cachedBuffer; diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h index ef0b98b5cb..0e1d25812e 100644 --- a/libs/gui/include/gui/WindowInfo.h +++ b/libs/gui/include/gui/WindowInfo.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -224,7 +224,7 @@ struct WindowInfo : public Parcelable { int32_t ownerPid = -1; int32_t ownerUid = -1; std::string packageName; - Flags inputConfig; + ftl::Flags inputConfig; int32_t displayId = ADISPLAY_ID_NONE; InputApplicationInfo applicationInfo; bool replaceTouchableRegionWithCrop = false; @@ -232,9 +232,9 @@ struct WindowInfo : public Parcelable { // The window's layout params flags and type set by WM. Type layoutParamsType = Type::UNKNOWN; - Flags layoutParamsFlags; + ftl::Flags layoutParamsFlags; - void setInputConfig(Flags config, bool value); + void setInputConfig(ftl::Flags config, bool value); void addTouchableRegion(const Rect& region); diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 8bd3899469..d6a6bd214e 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -60,10 +60,11 @@ #define INDENT3 " " using android::base::StringPrintf; -using namespace android::flag_operators; namespace android { +using namespace ftl::flag_operators; + static const char* DEVICE_INPUT_PATH = "/dev/input"; // v4l2 devices go directly into /dev static const char* DEVICE_PATH = "/dev"; @@ -302,7 +303,8 @@ static std::optional> getColorIndexArray( // --- Global Functions --- -Flags getAbsAxisUsage(int32_t axis, Flags deviceClasses) { +ftl::Flags getAbsAxisUsage(int32_t axis, + ftl::Flags deviceClasses) { // Touch devices get dibs on touch-related axes. if (deviceClasses.test(InputDeviceClass::TOUCH)) { switch (axis) { @@ -765,10 +767,10 @@ InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const { return device != nullptr ? device->identifier : InputDeviceIdentifier(); } -Flags EventHub::getDeviceClasses(int32_t deviceId) const { +ftl::Flags EventHub::getDeviceClasses(int32_t deviceId) const { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); - return device != nullptr ? device->classes : Flags(0); + return device != nullptr ? device->classes : ftl::Flags(0); } int32_t EventHub::getDeviceControllerNumber(int32_t deviceId) const { @@ -1909,7 +1911,7 @@ void EventHub::unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& vide } void EventHub::reportDeviceAddedForStatisticsLocked(const InputDeviceIdentifier& identifier, - Flags classes) { + ftl::Flags classes) { SHA256_CTX ctx; SHA256_Init(&ctx); SHA256_Update(&ctx, reinterpret_cast(identifier.uniqueId.c_str()), @@ -2191,7 +2193,7 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { } // If the device isn't recognized as something we handle, don't monitor it. - if (device->classes == Flags(0)) { + if (device->classes == ftl::Flags(0)) { ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(), device->identifier.name.c_str()); return; diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index a050963fef..ba5083bec3 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -18,9 +18,10 @@ #include "InputDevice.h" -#include #include +#include + #include "CursorInputMapper.h" #include "ExternalStylusInputMapper.h" #include "InputReaderContext.h" @@ -145,7 +146,7 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { return; } std::unique_ptr contextPtr(new InputDeviceContext(*this, eventHubId)); - Flags classes = contextPtr->getDeviceClasses(); + ftl::Flags classes = contextPtr->getDeviceClasses(); std::vector> mappers; // Check if we should skip population @@ -236,7 +237,7 @@ void InputDevice::removeEventHubDevice(int32_t eventHubId) { void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) { mSources = 0; - mClasses = Flags(0); + mClasses = ftl::Flags(0); mControllerNumber = 0; for_each_subdevice([this](InputDeviceContext& context) { diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 18e912db75..130c55639b 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -19,13 +19,12 @@ #include #include +#include #include #include -#include -#include - #include +#include #include #include #include @@ -189,7 +188,7 @@ struct RawLightInfo { int32_t id; std::string name; std::optional maxBrightness; - Flags flags; + ftl::Flags flags; std::array rgbIndex; std::filesystem::path path; }; @@ -198,7 +197,7 @@ struct RawLightInfo { struct RawBatteryInfo { int32_t id; std::string name; - Flags flags; + ftl::Flags flags; std::filesystem::path path; }; @@ -206,7 +205,8 @@ struct RawBatteryInfo { * Gets the class that owns an axis, in cases where multiple classes might claim * the same axis for different purposes. */ -extern Flags getAbsAxisUsage(int32_t axis, Flags deviceClasses); +extern ftl::Flags getAbsAxisUsage(int32_t axis, + ftl::Flags deviceClasses); /* * Grand Central Station for events. @@ -239,7 +239,7 @@ public: FIRST_SYNTHETIC_EVENT = DEVICE_ADDED, }; - virtual Flags getDeviceClasses(int32_t deviceId) const = 0; + virtual ftl::Flags getDeviceClasses(int32_t deviceId) const = 0; virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0; @@ -436,7 +436,7 @@ class EventHub : public EventHubInterface { public: EventHub(); - Flags getDeviceClasses(int32_t deviceId) const override final; + ftl::Flags getDeviceClasses(int32_t deviceId) const override final; InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override final; @@ -559,7 +559,7 @@ private: std::unique_ptr videoDevice; - Flags classes; + ftl::Flags classes; BitArray keyBitmask; BitArray keyState; @@ -662,7 +662,7 @@ private: int32_t getNextControllerNumberLocked(const std::string& name) REQUIRES(mLock); void releaseControllerNumberLocked(int32_t num) REQUIRES(mLock); void reportDeviceAddedForStatisticsLocked(const InputDeviceIdentifier& identifier, - Flags classes) REQUIRES(mLock); + ftl::Flags classes) REQUIRES(mLock); const std::unordered_map& getBatteryInfoLocked(int32_t deviceId) const REQUIRES(mLock); @@ -725,6 +725,6 @@ private: bool mPendingINotify; }; -}; // namespace android +} // namespace android #endif // _RUNTIME_EVENT_HUB_H diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 694daa99ce..728020eadc 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -17,12 +17,12 @@ #ifndef _UI_INPUTREADER_INPUT_DEVICE_H #define _UI_INPUTREADER_INPUT_DEVICE_H -#include +#include #include #include #include -#include +#include #include #include #include @@ -53,7 +53,7 @@ public: inline int32_t getGeneration() const { return mGeneration; } inline const std::string getName() const { return mIdentifier.name; } inline const std::string getDescriptor() { return mIdentifier.descriptor; } - inline Flags getClasses() const { return mClasses; } + inline ftl::Flags getClasses() const { return mClasses; } inline uint32_t getSources() const { return mSources; } inline bool hasEventHubDevices() const { return !mDevices.empty(); } @@ -160,7 +160,7 @@ private: int32_t mControllerNumber; InputDeviceIdentifier mIdentifier; std::string mAlias; - Flags mClasses; + ftl::Flags mClasses; // map from eventHubId to device context and mappers using MapperVector = std::vector>; @@ -250,7 +250,7 @@ public: inline int32_t getId() { return mDeviceId; } inline int32_t getEventHubId() { return mId; } - inline Flags getDeviceClasses() const { + inline ftl::Flags getDeviceClasses() const { return mEventHub->getDeviceClasses(mId); } inline InputDeviceIdentifier getDeviceIdentifier() const { diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index bf587050c6..864128734b 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -39,10 +39,11 @@ using android::gui::WindowInfo; using android::gui::WindowInfoHandle; using android::os::InputEventInjectionResult; using android::os::InputEventInjectionSync; -using namespace android::flag_operators; namespace android::inputdispatcher { +using namespace ftl::flag_operators; + // An arbitrary time value. static const nsecs_t ARBITRARY_TIME = 1234; diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 9f33d23af5..8ba501c275 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -14,6 +14,9 @@ * limitations under the License. */ +#include +#include + #include #include #include @@ -34,18 +37,15 @@ #include #include #include -#include -#include -#include -#include #include "input/DisplayViewport.h" #include "input/Input.h" namespace android { +using namespace ftl::flag_operators; + using std::chrono_literals::operator""ms; -using namespace android::flag_operators; // Timeout for waiting for an expected event static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms; @@ -429,7 +429,7 @@ class FakeEventHub : public EventHubInterface { struct Device { InputDeviceIdentifier identifier; - Flags classes; + ftl::Flags classes; PropertyMap configuration; KeyedVector absoluteAxes; KeyedVector relativeAxes; @@ -457,7 +457,7 @@ class FakeEventHub : public EventHubInterface { return OK; } - explicit Device(Flags classes) : classes(classes), enabled(true) {} + explicit Device(ftl::Flags classes) : classes(classes), enabled(true) {} }; std::mutex mLock; @@ -484,7 +484,8 @@ public: FakeEventHub() { } - void addDevice(int32_t deviceId, const std::string& name, Flags classes) { + void addDevice(int32_t deviceId, const std::string& name, + ftl::Flags classes) { Device* device = new Device(classes); device->identifier.name = name; mDevices.add(deviceId, device); @@ -695,9 +696,9 @@ private: return index >= 0 ? mDevices.valueAt(index) : nullptr; } - Flags getDeviceClasses(int32_t deviceId) const override { + ftl::Flags getDeviceClasses(int32_t deviceId) const override { Device* device = getDevice(deviceId); - return device ? device->classes : Flags(0); + return device ? device->classes : ftl::Flags(0); } InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override { @@ -1572,8 +1573,8 @@ protected: mFakePolicy.clear(); } - void addDevice(int32_t eventHubId, const std::string& name, Flags classes, - const PropertyMap* configuration) { + void addDevice(int32_t eventHubId, const std::string& name, + ftl::Flags classes, const PropertyMap* configuration) { mFakeEventHub->addDevice(eventHubId, name, classes); if (configuration) { @@ -1598,7 +1599,8 @@ protected: FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId, const std::string& name, - Flags classes, uint32_t sources, + ftl::Flags classes, + uint32_t sources, const PropertyMap* configuration) { std::shared_ptr device = mReader->newDevice(deviceId, name); FakeInputMapper& mapper = device->addMapper(eventHubId, sources); @@ -1610,7 +1612,7 @@ protected: TEST_F(InputReaderTest, PolicyGetInputDevices) { ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr)); - ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", Flags(0), + ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", ftl::Flags(0), nullptr)); // no classes so device will be ignored // Should also have received a notification describing the new input devices. @@ -1672,7 +1674,7 @@ TEST_F(InputReaderTest, GetMergedInputDevicesEnabled) { TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass(InputDeviceClass::KEYBOARD); + constexpr ftl::Flags deviceClass(InputDeviceClass::KEYBOARD); constexpr int32_t eventHubId = 1; std::shared_ptr device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! @@ -1709,7 +1711,7 @@ TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubId = 1; FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass, @@ -1773,7 +1775,7 @@ TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_NoKeyboardMapper) { TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubId = 1; FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass, @@ -1806,7 +1808,7 @@ TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) { TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubId = 1; FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass, @@ -1839,7 +1841,7 @@ TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) { TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubId = 1; FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass, @@ -1891,7 +1893,7 @@ TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChange TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr nsecs_t when = 0; constexpr int32_t eventHubId = 1; constexpr nsecs_t readTime = 2; @@ -1915,7 +1917,7 @@ TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { TEST_F(InputReaderTest, DeviceReset_RandomId) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubId = 1; std::shared_ptr device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! @@ -1948,7 +1950,7 @@ TEST_F(InputReaderTest, DeviceReset_RandomId) { TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) { constexpr int32_t deviceId = 1; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubId = 1; std::shared_ptr device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! @@ -1963,7 +1965,7 @@ TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) { TEST_F(InputReaderTest, Device_CanDispatchToDisplay) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubId = 1; const char* DEVICE_LOCATION = "USB1"; std::shared_ptr device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); @@ -2008,7 +2010,7 @@ TEST_F(InputReaderTest, Device_CanDispatchToDisplay) { TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1}; std::shared_ptr device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! @@ -2049,7 +2051,7 @@ TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) { TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - constexpr Flags deviceClass = InputDeviceClass::KEYBOARD; + constexpr ftl::Flags deviceClass = InputDeviceClass::KEYBOARD; constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1}; // Add two subdevices to device std::shared_ptr device = mReader->newDevice(deviceId, "fake"); @@ -2106,7 +2108,8 @@ public: TEST_F(InputReaderTest, VibratorGetVibratorIds) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - Flags deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR; + ftl::Flags deviceClass = + InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR; constexpr int32_t eventHubId = 1; const char* DEVICE_LOCATION = "BLUETOOTH"; std::shared_ptr device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); @@ -2166,7 +2169,8 @@ private: TEST_F(InputReaderTest, BatteryGetCapacity) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - Flags deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY; + ftl::Flags deviceClass = + InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY; constexpr int32_t eventHubId = 1; const char* DEVICE_LOCATION = "BLUETOOTH"; std::shared_ptr device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); @@ -2182,7 +2186,8 @@ TEST_F(InputReaderTest, BatteryGetCapacity) { TEST_F(InputReaderTest, BatteryGetStatus) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - Flags deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY; + ftl::Flags deviceClass = + InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY; constexpr int32_t eventHubId = 1; const char* DEVICE_LOCATION = "BLUETOOTH"; std::shared_ptr device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); @@ -2198,7 +2203,7 @@ TEST_F(InputReaderTest, BatteryGetStatus) { TEST_F(InputReaderTest, LightGetColor) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; - Flags deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT; + ftl::Flags deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT; constexpr int32_t eventHubId = 1; const char* DEVICE_LOCATION = "BLUETOOTH"; std::shared_ptr device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); @@ -2625,7 +2630,7 @@ protected: static const int32_t DEVICE_ID; static const int32_t DEVICE_GENERATION; static const int32_t DEVICE_CONTROLLER_NUMBER; - static const Flags DEVICE_CLASSES; + static const ftl::Flags DEVICE_CLASSES; static const int32_t EVENTHUB_ID; std::shared_ptr mFakeEventHub; @@ -2646,7 +2651,7 @@ protected: mDevice = std::make_shared(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION, identifier); mReader->pushNextDevice(mDevice); - mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, Flags(0)); + mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags(0)); mReader->loopOnce(); } @@ -2661,14 +2666,14 @@ const char* InputDeviceTest::DEVICE_LOCATION = "USB1"; const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000; const int32_t InputDeviceTest::DEVICE_GENERATION = 2; const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0; -const Flags InputDeviceTest::DEVICE_CLASSES = +const ftl::Flags InputDeviceTest::DEVICE_CLASSES = InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK; const int32_t InputDeviceTest::EVENTHUB_ID = 1; TEST_F(InputDeviceTest, ImmutableProperties) { ASSERT_EQ(DEVICE_ID, mDevice->getId()); ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str()); - ASSERT_EQ(Flags(0), mDevice->getClasses()); + ASSERT_EQ(ftl::Flags(0), mDevice->getClasses()); } TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) { @@ -2912,7 +2917,7 @@ protected: static const int32_t DEVICE_ID; static const int32_t DEVICE_GENERATION; static const int32_t DEVICE_CONTROLLER_NUMBER; - static const Flags DEVICE_CLASSES; + static const ftl::Flags DEVICE_CLASSES; static const int32_t EVENTHUB_ID; std::shared_ptr mFakeEventHub; @@ -2921,7 +2926,7 @@ protected: std::unique_ptr mReader; std::shared_ptr mDevice; - virtual void SetUp(Flags classes) { + virtual void SetUp(ftl::Flags classes) { mFakeEventHub = std::make_unique(); mFakePolicy = new FakeInputReaderPolicy(); mFakeListener = std::make_unique(); @@ -2953,7 +2958,7 @@ protected: std::shared_ptr newDevice(int32_t deviceId, const std::string& name, const std::string& location, int32_t eventHubId, - Flags classes) { + ftl::Flags classes) { InputDeviceIdentifier identifier; identifier.name = name; identifier.location = location; @@ -3045,8 +3050,8 @@ const char* InputMapperTest::DEVICE_LOCATION = "USB1"; const int32_t InputMapperTest::DEVICE_ID = END_RESERVED_ID + 1000; const int32_t InputMapperTest::DEVICE_GENERATION = 2; const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0; -const Flags InputMapperTest::DEVICE_CLASSES = - Flags(0); // not needed for current tests +const ftl::Flags InputMapperTest::DEVICE_CLASSES = + ftl::Flags(0); // not needed for current tests const int32_t InputMapperTest::EVENTHUB_ID = 1; // --- SwitchInputMapperTest --- @@ -3842,7 +3847,7 @@ TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) { constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1; std::shared_ptr device2 = newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID, - Flags(0)); + ftl::Flags(0)); mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0); mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0); @@ -3954,7 +3959,7 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) { constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1; std::shared_ptr device2 = newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID, - Flags(0)); + ftl::Flags(0)); mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/); mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/); mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/); @@ -8409,7 +8414,7 @@ TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) { constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1; std::shared_ptr device2 = newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID, - Flags(0)); + ftl::Flags(0)); mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0 /*flat*/, 0 /*fuzz*/); @@ -9350,7 +9355,7 @@ protected: static const int32_t DEVICE_ID; static const int32_t DEVICE_GENERATION; static const int32_t DEVICE_CONTROLLER_NUMBER; - static const Flags DEVICE_CLASSES; + static const ftl::Flags DEVICE_CLASSES; static const int32_t EVENTHUB_ID; std::shared_ptr mFakeEventHub; @@ -9359,7 +9364,7 @@ protected: std::unique_ptr mReader; std::shared_ptr mDevice; - virtual void SetUp(Flags classes) { + virtual void SetUp(ftl::Flags classes) { mFakeEventHub = std::make_unique(); mFakePolicy = new FakeInputReaderPolicy(); mFakeListener = std::make_unique(); @@ -9385,7 +9390,7 @@ protected: std::shared_ptr newDevice(int32_t deviceId, const std::string& name, const std::string& location, int32_t eventHubId, - Flags classes) { + ftl::Flags classes) { InputDeviceIdentifier identifier; identifier.name = name; identifier.location = location; @@ -9411,8 +9416,8 @@ const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH"; const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000; const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2; const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0; -const Flags PeripheralControllerTest::DEVICE_CLASSES = - Flags(0); // not needed for current tests +const ftl::Flags PeripheralControllerTest::DEVICE_CLASSES = + ftl::Flags(0); // not needed for current tests const int32_t PeripheralControllerTest::EVENTHUB_ID = 1; // --- BatteryControllerTest --- diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h index cb00e719f8..29d33662ab 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h @@ -16,20 +16,20 @@ #pragma once +#include + +#include +#include #include +#include +#include + #include #include #include #include -#include - -#include #include "DisplayHardware/Hal.h" -#include "math/HashCombine.h" - -#include -#include namespace std { template @@ -84,13 +84,13 @@ class StateInterface { public: virtual ~StateInterface() = default; - virtual Flags update(const compositionengine::OutputLayer* layer) = 0; + virtual ftl::Flags update(const compositionengine::OutputLayer* layer) = 0; virtual size_t getHash() const = 0; virtual LayerStateField getField() const = 0; - virtual Flags getFieldIfDifferent(const StateInterface* other) const = 0; + virtual ftl::Flags getFieldIfDifferent(const StateInterface* other) const = 0; virtual bool equals(const StateInterface* other) const = 0; @@ -152,12 +152,12 @@ public: ~OutputLayerState() override = default; // Returns this member's field flag if it was changed - Flags update(const compositionengine::OutputLayer* layer) override { + ftl::Flags update(const compositionengine::OutputLayer* layer) override { T newValue = mReader(layer); return update(newValue); } - Flags update(const T& newValue) { + ftl::Flags update(const T& newValue) { if (!mEquals(mValue, newValue)) { mValue = newValue; mHash = {}; @@ -176,14 +176,14 @@ public: return *mHash; } - Flags getFieldIfDifferent(const StateInterface* other) const override { + ftl::Flags getFieldIfDifferent(const StateInterface* other) const override { if (other->getField() != FIELD) { return {}; } // The early return ensures that this downcast is sound const OutputLayerState* otherState = static_cast(other); - return *this != *otherState ? FIELD : Flags{}; + return *this != *otherState ? FIELD : ftl::Flags{}; } bool equals(const StateInterface* other) const override { @@ -215,7 +215,7 @@ public: LayerState(compositionengine::OutputLayer* layer); // Returns which fields were updated - Flags update(compositionengine::OutputLayer*); + ftl::Flags update(compositionengine::OutputLayer*); // Computes a hash for this LayerState. // The hash is only computed from NonUniqueFields, and excludes GraphicBuffers since they are @@ -224,7 +224,7 @@ public: // Returns the bit-set of differing fields between this LayerState and another LayerState. // This bit-set is based on NonUniqueFields only, and excludes GraphicBuffers. - Flags getDifferingFields(const LayerState& other) const; + ftl::Flags getDifferingFields(const LayerState& other) const; compositionengine::OutputLayer* getOutputLayer() const { return mOutputLayer; } int32_t getId() const { return mId.get(); } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h index ef1560e23d..6be673597e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h @@ -16,6 +16,8 @@ #pragma once +#include + #include namespace android::compositionengine::impl::planner { @@ -35,7 +37,7 @@ public: // This implies that only one layer is allowed to differ in an approximate match. size_t differingIndex; // Set of fields that differ for the differing layer in the approximate match. - Flags differingFields; + ftl::Flags differingFields; }; // Returns an approximate match when comparing this layer stack with the provided list of diff --git a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp index c79ca0d959..f439caf9e1 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp @@ -41,7 +41,7 @@ LayerState::LayerState(compositionengine::OutputLayer* layer) update(layer); } -Flags LayerState::update(compositionengine::OutputLayer* layer) { +ftl::Flags LayerState::update(compositionengine::OutputLayer* layer) { ALOGE_IF(mOutputLayer != layer && layer->getLayerFE().getSequence() != mId.get(), "[%s] Expected mOutputLayer ID to never change: %d, %d", __func__, layer->getLayerFE().getSequence(), mId.get()); @@ -50,7 +50,7 @@ Flags LayerState::update(compositionengine::OutputLayer* layer) // same, i.e., the LayerFE is the same. An example use-case is screen rotation. mOutputLayer = layer; - Flags differences; + ftl::Flags differences; // Update the unique fields as well, since we have to set them at least // once from the OutputLayer @@ -76,8 +76,8 @@ size_t LayerState::getHash() const { return hash; } -Flags LayerState::getDifferingFields(const LayerState& other) const { - Flags differences; +ftl::Flags LayerState::getDifferingFields(const LayerState& other) const { + ftl::Flags differences; auto myFields = getNonUniqueFields(); auto otherFields = other.getNonUniqueFields(); for (size_t i = 0; i < myFields.size(); ++i) { diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp index 74d27015d7..c8413eb8bc 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp @@ -97,7 +97,7 @@ void Planner::plan( if (const auto layerEntry = mPreviousLayers.find(id); layerEntry != mPreviousLayers.end()) { // Track changes from previous info LayerState& state = layerEntry->second; - Flags differences = state.update(layer); + ftl::Flags differences = state.update(layer); if (differences.get() == 0) { state.incrementFramesSinceBufferUpdate(); } else { diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp index 2d53583ed8..2fc029fdc6 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp @@ -57,7 +57,7 @@ std::optional LayerStack::getApproximateMatch( return std::nullopt; } - Flags differingFields = mLayers[i].getDifferingFields(*other[i]); + ftl::Flags differingFields = mLayers[i].getDifferingFields(*other[i]); // If we don't find an approximate match on this layer, then the LayerStacks differ // by too much, so return nothing diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp index bd4ff13236..5c6e8da58c 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp @@ -97,12 +97,12 @@ struct LayerStateTest : public testing::Test { void verifyUniqueDifferingFields(const LayerState& lhs, const LayerState& rhs) { EXPECT_EQ(lhs.getHash(), rhs.getHash()); - EXPECT_EQ(Flags(LayerStateField::None), lhs.getDifferingFields(rhs)); - EXPECT_EQ(Flags(LayerStateField::None), rhs.getDifferingFields(lhs)); + EXPECT_EQ(ftl::Flags(LayerStateField::None), lhs.getDifferingFields(rhs)); + EXPECT_EQ(ftl::Flags(LayerStateField::None), rhs.getDifferingFields(lhs)); } void verifyNonUniqueDifferingFields(const LayerState& lhs, const LayerState& rhs, - Flags fields) { + ftl::Flags fields) { EXPECT_NE(lhs.getHash(), rhs.getHash()); EXPECT_EQ(fields, lhs.getDifferingFields(rhs)); @@ -159,9 +159,9 @@ TEST_F(LayerStateTest, updateId) { sp newLayerFE = sp::make(); setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionState, sSequenceIdTwo); - Flags updates = mLayerState->update(&newOutputLayer); + ftl::Flags updates = mLayerState->update(&newOutputLayer); EXPECT_EQ(sSequenceIdTwo, mLayerState->getId()); - EXPECT_EQ(Flags(LayerStateField::Id), updates); + EXPECT_EQ(ftl::Flags(LayerStateField::Id), updates); } TEST_F(LayerStateTest, compareId) { @@ -204,9 +204,9 @@ TEST_F(LayerStateTest, updateName) { sp newLayerFE = sp::make(); setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionState, sSequenceId, sDebugNameTwo); - Flags updates = mLayerState->update(&newOutputLayer); + ftl::Flags updates = mLayerState->update(&newOutputLayer); EXPECT_EQ(sDebugNameTwo, mLayerState->getName()); - EXPECT_EQ(Flags(LayerStateField::Name), updates); + EXPECT_EQ(ftl::Flags(LayerStateField::Name), updates); } TEST_F(LayerStateTest, compareName) { @@ -253,9 +253,9 @@ TEST_F(LayerStateTest, updateDisplayFrame) { outputLayerCompositionStateTwo.displayFrame = sRectTwo; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo, layerFECompositionState); - Flags updates = mLayerState->update(&newOutputLayer); + ftl::Flags updates = mLayerState->update(&newOutputLayer); EXPECT_EQ(sRectTwo, mLayerState->getDisplayFrame()); - EXPECT_EQ(Flags(LayerStateField::DisplayFrame), updates); + EXPECT_EQ(ftl::Flags(LayerStateField::DisplayFrame), updates); } TEST_F(LayerStateTest, compareDisplayFrame) { @@ -315,9 +315,9 @@ TEST_F(LayerStateTest, updateCompositionType) { layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); + ftl::Flags updates = mLayerState->update(&newOutputLayer); EXPECT_EQ(Composition::SOLID_COLOR, mLayerState->getCompositionType()); - EXPECT_EQ(Flags(LayerStateField::CompositionType), updates); + EXPECT_EQ(ftl::Flags(LayerStateField::CompositionType), updates); } TEST_F(LayerStateTest, compareCompositionType) { @@ -357,8 +357,8 @@ TEST_F(LayerStateTest, updateBuffer) { layerFECompositionStateTwo.buffer = new GraphicBuffer(); setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::Buffer), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::Buffer), updates); } TEST_F(LayerStateTest, updateBufferSingleBufferedLegacy) { @@ -380,8 +380,8 @@ TEST_F(LayerStateTest, updateBufferSingleBufferedLegacy) { layerFECompositionStateTwo.frameNumber = i; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::Buffer), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::Buffer), updates); } } @@ -404,8 +404,8 @@ TEST_F(LayerStateTest, updateBufferSingleBufferedUsage) { for (uint64_t i = 0; i < 10; i++) { setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::Buffer), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::Buffer), updates); } } @@ -446,8 +446,8 @@ TEST_F(LayerStateTest, updateSourceCrop) { outputLayerCompositionStateTwo.sourceCrop = sFloatRectTwo; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo, layerFECompositionState); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::SourceCrop), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::SourceCrop), updates); } TEST_F(LayerStateTest, compareSourceCrop) { @@ -485,8 +485,8 @@ TEST_F(LayerStateTest, updateBufferTransform) { outputLayerCompositionStateTwo.bufferTransform = Hwc2::Transform::FLIP_V; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo, layerFECompositionState); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::BufferTransform), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::BufferTransform), updates); } TEST_F(LayerStateTest, compareBufferTransform) { @@ -525,8 +525,8 @@ TEST_F(LayerStateTest, updateBlendMode) { layerFECompositionStateTwo.blendMode = hal::BlendMode::PREMULTIPLIED; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::BlendMode), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::BlendMode), updates); } TEST_F(LayerStateTest, compareBlendMode) { @@ -564,8 +564,8 @@ TEST_F(LayerStateTest, updateAlpha) { layerFECompositionStateTwo.alpha = sAlphaTwo; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::Alpha), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::Alpha), updates); } TEST_F(LayerStateTest, compareAlpha) { @@ -603,8 +603,8 @@ TEST_F(LayerStateTest, updateLayerMetadata) { layerFECompositionStateTwo.metadata[sMetadataKeyTwo] = sMetadataValueTwo; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::LayerMetadata), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::LayerMetadata), updates); } TEST_F(LayerStateTest, compareLayerMetadata) { @@ -652,8 +652,8 @@ TEST_F(LayerStateTest, updateVisibleRegion) { outputLayerCompositionStateTwo.visibleRegion = sRegionTwo; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo, layerFECompositionState); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::VisibleRegion), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::VisibleRegion), updates); } TEST_F(LayerStateTest, compareVisibleRegion) { @@ -691,8 +691,8 @@ TEST_F(LayerStateTest, updateDataspace) { outputLayerCompositionStateTwo.dataspace = ui::Dataspace::DISPLAY_P3; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo, layerFECompositionState); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::Dataspace), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::Dataspace), updates); } TEST_F(LayerStateTest, compareDataspace) { @@ -738,9 +738,9 @@ TEST_F(LayerStateTest, updatePixelFormat) { "buffer2"); setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::Buffer) | - Flags(LayerStateField::PixelFormat), + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::Buffer) | + ftl::Flags(LayerStateField::PixelFormat), updates); } @@ -768,7 +768,7 @@ TEST_F(LayerStateTest, comparePixelFormat) { auto otherLayerState = std::make_unique(&newOutputLayer); verifyNonUniqueDifferingFields(*mLayerState, *otherLayerState, - Flags(LayerStateField::PixelFormat)); + ftl::Flags(LayerStateField::PixelFormat)); EXPECT_TRUE(mLayerState->compare(*otherLayerState)); EXPECT_TRUE(otherLayerState->compare(*mLayerState)); @@ -790,8 +790,8 @@ TEST_F(LayerStateTest, updateColorTransform) { layerFECompositionStateTwo.colorTransform = sMat4One; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::ColorTransform), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::ColorTransform), updates); } TEST_F(LayerStateTest, compareColorTransform) { @@ -831,8 +831,8 @@ TEST_F(LayerStateTest, updateSidebandStream) { layerFECompositionStateTwo.sidebandStream = NativeHandle::create(sFakeSidebandStreamTwo, false); setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::SidebandStream), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::SidebandStream), updates); } TEST_F(LayerStateTest, compareSidebandStream) { @@ -870,8 +870,8 @@ TEST_F(LayerStateTest, updateSolidColor) { layerFECompositionStateTwo.color = sHalf4Two; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::SolidColor), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::SolidColor), updates); } TEST_F(LayerStateTest, compareSolidColor) { @@ -909,8 +909,8 @@ TEST_F(LayerStateTest, updateBackgroundBlur) { layerFECompositionStateTwo.backgroundBlurRadius = sBgBlurRadiusTwo; setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::BackgroundBlurRadius), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::BackgroundBlurRadius), updates); } TEST_F(LayerStateTest, compareBackgroundBlur) { @@ -949,8 +949,8 @@ TEST_F(LayerStateTest, updateBlurRegions) { layerFECompositionStateTwo.blurRegions.push_back(sBlurRegionTwo); setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState, layerFECompositionStateTwo); - Flags updates = mLayerState->update(&newOutputLayer); - EXPECT_EQ(Flags(LayerStateField::BlurRegions), updates); + ftl::Flags updates = mLayerState->update(&newOutputLayer); + EXPECT_EQ(ftl::Flags(LayerStateField::BlurRegions), updates); } TEST_F(LayerStateTest, compareBlurRegions) { diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index b4fb51f9d5..3803a78670 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -19,20 +19,20 @@ #pragma clang diagnostic ignored "-Wconversion" // #define LOG_NDEBUG 0 -#include "VirtualDisplaySurface.h" #include -#include "HWComposer.h" -#include "SurfaceFlinger.h" - -#include #include +#include #include #include #include #include +#include "HWComposer.h" +#include "SurfaceFlinger.h" +#include "VirtualDisplaySurface.h" + #define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \ mDisplayName.c_str(), ##__VA_ARGS__) #define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \ @@ -657,7 +657,7 @@ auto VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) -> std::string VirtualDisplaySurface::toString(CompositionType type) { using namespace std::literals; - return type == CompositionType::Unknown ? "Unknown"s : Flags(type).string(); + return type == CompositionType::Unknown ? "Unknown"s : ftl::Flags(type).string(); } } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 894fb8d47b..41e048715c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -82,11 +82,13 @@ namespace { constexpr int kDumpTableRowLength = 159; } // namespace +using namespace ftl::flag_operators; + using base::StringAppendF; -using namespace android::flag_operators; -using PresentState = frametimeline::SurfaceFrame::PresentState; using gui::WindowInfo; +using PresentState = frametimeline::SurfaceFrame::PresentState; + std::atomic Layer::sSequence{1}; Layer::Layer(const LayerCreationArgs& args) diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Features.h b/services/surfaceflinger/Scheduler/include/scheduler/Features.h index 0e96678420..b3a6a606c3 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/Features.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/Features.h @@ -16,10 +16,10 @@ #pragma once -#include - #include +#include + namespace android::scheduler { enum class Feature : std::uint8_t { @@ -29,6 +29,6 @@ enum class Feature : std::uint8_t { kTracePredictedVsync = 0b1000, }; -using FeatureFlags = Flags; +using FeatureFlags = ftl::Flags; } // namespace android::scheduler diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index d249b60f2a..a73eccf0e5 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -429,7 +429,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer_sta bufferProto.height(), bufferProto.pixel_format(), bufferProto.usage())); layer.bufferData->frameNumber = bufferProto.frame_number(); - layer.bufferData->flags = Flags(bufferProto.flags()); + layer.bufferData->flags = ftl::Flags(bufferProto.flags()); layer.bufferData->cachedBuffer.id = bufferProto.cached_buffer_id(); layer.bufferData->acquireFence = Fence::NO_FENCE; } diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 14d8f987b0..fa36d9c16b 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -34,12 +34,13 @@ using namespace std::chrono_literals; using namespace std::placeholders; -using namespace android::flag_operators; using testing::_; using testing::Invoke; namespace android { +using namespace ftl::flag_operators; + namespace { constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = PhysicalDisplayId::fromPort(111u); -- cgit v1.2.3-59-g8ed1b From 1f6fc70ab0c6efdaa1c60dd2ced32fb6833c92e2 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 21 Mar 2022 08:34:50 -0700 Subject: SF: Fix feedback loop with refresh rate overlay RefreshRateOverlay was refactored to use transactions instead of APIs internal to SF. A side effect is that the overlay layer feeds back into the frame rate detection and idle heuristics, which causes oscillation that trends to the high refresh rate. The transaction to setFrameRate failed to apply, as the NoVote argument was invalid. Make it valid, such that LayerHistory::summarize skips the overlay layer. Do not reset the idle timer for solely NO_VOTE transactions. Bug: 221081400 Test: flame is not stuck at 90 Hz when overlay is enabled. Test: Same with sf.debug.show_refresh_rate_overlay_spinner Test: SetFrameRateTest Change-Id: I6322c1c487672b602a0f974e8ecf445633dcc3a1 --- libs/gui/LayerState.cpp | 11 +++--- libs/nativewindow/include/apex/window.h | 13 ------- libs/nativewindow/include/system/window.h | 18 ++++++++++ services/surfaceflinger/Layer.cpp | 2 ++ services/surfaceflinger/RefreshRateOverlay.cpp | 42 ++++++++++------------ services/surfaceflinger/SurfaceFlinger.cpp | 19 ++++------ services/surfaceflinger/SurfaceFlinger.h | 3 +- services/surfaceflinger/TransactionState.h | 36 +++++++++++++++++-- .../tests/unittests/SetFrameRateTest.cpp | 21 +++++++---- 9 files changed, 101 insertions(+), 64 deletions(-) (limited to 'libs/gui/LayerState.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index f7cd5c4f71..502031c8d8 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -16,8 +16,8 @@ #define LOG_TAG "LayerState" -#include -#include +#include +#include #include #include @@ -25,10 +25,9 @@ #include #include #include +#include #include -#include - namespace android { using gui::FocusRequest; @@ -679,7 +678,9 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, int8_t changeFrame if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE && - (!privileged || compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT)) { + (!privileged || + (compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT && + compatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE))) { ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName, compatibility, privileged ? "yes" : "no"); return false; diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h index 0923438eec..2d1354cdf1 100644 --- a/libs/nativewindow/include/apex/window.h +++ b/libs/nativewindow/include/apex/window.h @@ -39,19 +39,6 @@ enum ANativeWindowPerform { // clang-format on }; -/* - * Internal extension of compatibility value for ANativeWindow_setFrameRate. */ -enum ANativeWindow_FrameRateCompatibilityInternal { - /** - * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display - * to operate at the exact frame rate. - * - * This is used internally by the platform and should not be used by apps. - * @hide - */ - ANATIVEWINDOW_FRAME_RATE_EXACT = 100, -}; - /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_cancelBuffer is called. diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index a319769148..a54af1fa62 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -1018,6 +1018,24 @@ static inline int native_window_set_auto_prerotation(struct ANativeWindow* windo return window->perform(window, NATIVE_WINDOW_SET_AUTO_PREROTATION, autoPrerotation); } +/* + * Internal extension of ANativeWindow_FrameRateCompatibility. + */ +enum { + /** + * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display + * to operate at the exact frame rate. + * + * Keep in sync with Surface.java constant. + */ + ANATIVEWINDOW_FRAME_RATE_EXACT = 100, + + /** + * This surface is ignored while choosing the refresh rate. + */ + ANATIVEWINDOW_FRAME_RATE_NO_VOTE, +}; + static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy) { return window->perform(window, NATIVE_WINDOW_SET_FRAME_RATE, (double)frameRate, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 997b1a1b1a..f7e1d1ee95 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2596,6 +2596,8 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp return FrameRateCompatibility::ExactOrMultiple; case ANATIVEWINDOW_FRAME_RATE_EXACT: return FrameRateCompatibility::Exact; + case ANATIVEWINDOW_FRAME_RATE_NO_VOTE: + return FrameRateCompatibility::NoVote; default: LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); return FrameRateCompatibility::Default; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 80aa07231f..d4435c2818 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -45,6 +45,15 @@ constexpr int kDigitSpace = 16; constexpr int kBufferWidth = 4 * kDigitWidth + 3 * kDigitSpace; constexpr int kBufferHeight = kDigitHeight; +SurfaceComposerClient::Transaction createTransaction(const sp& surface) { + constexpr float kFrameRate = 0.f; + constexpr int8_t kCompatibility = ANATIVEWINDOW_FRAME_RATE_NO_VOTE; + constexpr int8_t kSeamlessness = ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS; + + return SurfaceComposerClient::Transaction().setFrameRate(surface, kFrameRate, kCompatibility, + kSeamlessness); +} + } // namespace void RefreshRateOverlay::SevenSegmentDrawer::drawSegment(Segment segment, int left, SkColor color, @@ -213,12 +222,7 @@ RefreshRateOverlay::RefreshRateOverlay(FpsRange fpsRange, bool showSpinner) return; } - constexpr float kFrameRate = 0.f; - constexpr int8_t kCompatibility = static_cast(Layer::FrameRateCompatibility::NoVote); - constexpr int8_t kSeamlessness = ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS; - - SurfaceComposerClient::Transaction() - .setFrameRate(mSurfaceControl, kFrameRate, kCompatibility, kSeamlessness) + createTransaction(mSurfaceControl) .setLayer(mSurfaceControl, INT32_MAX - 2) .setTrustedOverlay(mSurfaceControl, true) .apply(); @@ -243,9 +247,7 @@ auto RefreshRateOverlay::getOrCreateBuffers(Fps fps) -> const Buffers& { } }(); - SurfaceComposerClient::Transaction t; - t.setTransform(mSurfaceControl, transform); - t.apply(); + createTransaction(mSurfaceControl).setTransform(mSurfaceControl, transform).apply(); BufferCache::const_iterator it = mBufferCache.find({fps.getIntValue(), transformHint}); if (it == mBufferCache.end()) { @@ -287,25 +289,21 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame((3 * width) >> 4, height >> 5); frame.offsetBy(width >> 5, height >> 4); - SurfaceComposerClient::Transaction t; - t.setMatrix(mSurfaceControl, frame.getWidth() / static_cast(kBufferWidth), 0, 0, - frame.getHeight() / static_cast(kBufferHeight)); - t.setPosition(mSurfaceControl, frame.left, frame.top); - t.apply(); + createTransaction(mSurfaceControl) + .setMatrix(mSurfaceControl, frame.getWidth() / static_cast(kBufferWidth), 0, 0, + frame.getHeight() / static_cast(kBufferHeight)) + .setPosition(mSurfaceControl, frame.left, frame.top) + .apply(); } void RefreshRateOverlay::setLayerStack(ui::LayerStack stack) { - SurfaceComposerClient::Transaction t; - t.setLayerStack(mSurfaceControl, stack); - t.apply(); + createTransaction(mSurfaceControl).setLayerStack(mSurfaceControl, stack).apply(); } void RefreshRateOverlay::changeRefreshRate(Fps fps) { mCurrentFps = fps; const auto buffer = getOrCreateBuffers(fps)[mFrame]; - SurfaceComposerClient::Transaction t; - t.setBuffer(mSurfaceControl, buffer); - t.apply(); + createTransaction(mSurfaceControl).setBuffer(mSurfaceControl, buffer).apply(); } void RefreshRateOverlay::animate() { @@ -314,9 +312,7 @@ void RefreshRateOverlay::animate() { const auto& buffers = getOrCreateBuffers(*mCurrentFps); mFrame = (mFrame + 1) % buffers.size(); const auto buffer = buffers[mFrame]; - SurfaceComposerClient::Transaction t; - t.setBuffer(mSurfaceControl, buffer); - t.apply(); + createTransaction(mSurfaceControl).setBuffer(mSurfaceControl, buffer).apply(); } } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4c830307e8..64ba280f9c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3629,11 +3629,11 @@ uint32_t SurfaceFlinger::clearTransactionFlags(uint32_t mask) { } void SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule schedule, - const sp& applyToken) { + const sp& applyToken, FrameHint frameHint) { modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, applyToken); if (const bool scheduled = mTransactionFlags.fetch_or(mask) & mask; !scheduled) { - scheduleCommit(FrameHint::kActive); + scheduleCommit(frameHint); } } @@ -4005,7 +4005,7 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied( } void SurfaceFlinger::queueTransaction(TransactionState& state) { - Mutex::Autolock _l(mQueueLock); + Mutex::Autolock lock(mQueueLock); // Generate a CountDownLatch pending state if this is a synchronous transaction. if ((state.flags & eSynchronous) || state.inputWindowCommands.syncInputWindows) { @@ -4024,7 +4024,9 @@ void SurfaceFlinger::queueTransaction(TransactionState& state) { return TransactionSchedule::Late; }(state.flags); - setTransactionFlags(eTransactionFlushNeeded, schedule, state.applyToken); + const auto frameHint = state.isFrameActive() ? FrameHint::kActive : FrameHint::kNone; + + setTransactionFlags(eTransactionFlushNeeded, schedule, state.applyToken, frameHint); } void SurfaceFlinger::waitForSynchronousTransaction( @@ -7172,15 +7174,6 @@ int SurfaceFlinger::getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) con return calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } -void TransactionState::traverseStatesWithBuffers( - std::function visitor) { - for (const auto& state : states) { - if (state.state.hasBufferChanges() && state.state.hasValidBuffer() && state.state.surface) { - visitor(state.state); - } - } -} - void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state) { sp layer = state.layer.promote(); if (!layer) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 97b0e8db5c..3c7facfc12 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -784,7 +784,8 @@ private: // Sets the masked bits, and schedules a commit if needed. void setTransactionFlags(uint32_t mask, TransactionSchedule = TransactionSchedule::Late, - const sp& applyToken = nullptr); + const sp& applyToken = nullptr, + FrameHint = FrameHint::kActive); // Clears and returns the masked bits. uint32_t clearTransactionFlags(uint32_t mask); diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h index 04ca347b2f..bab5326093 100644 --- a/services/surfaceflinger/TransactionState.h +++ b/services/surfaceflinger/TransactionState.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright 2021 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,12 +16,21 @@ #pragma once +#include +#include +#include +#include + #include +#include namespace android { + class CountDownLatch; struct TransactionState { + TransactionState() = default; + TransactionState(const FrameTimelineInfo& frameTimelineInfo, const Vector& composerStates, const Vector& displayStates, uint32_t transactionFlags, @@ -47,9 +56,30 @@ struct TransactionState { originUid(originUid), id(transactionId) {} - TransactionState() {} + // Invokes `void(const layer_state_t&)` visitor for matching layers. + template + void traverseStatesWithBuffers(Visitor&& visitor) const { + for (const auto& [state] : states) { + if (state.hasBufferChanges() && state.hasValidBuffer() && state.surface) { + visitor(state); + } + } + } + + // TODO(b/185535769): Remove FrameHint. Instead, reset the idle timer (of the relevant physical + // display) on the main thread if commit leads to composite. Then, RefreshRateOverlay should be + // able to setFrameRate once, rather than for each transaction. + bool isFrameActive() const { + if (!displays.empty()) return true; + + for (const auto& [state] : states) { + if (state.frameRateCompatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE) { + return true; + } + } - void traverseStatesWithBuffers(std::function visitor); + return false; + } FrameTimelineInfo frameTimelineInfo; Vector states; diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index 825f145ecd..b9a5f36794 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -337,10 +337,22 @@ TEST_F(SetFrameRateTest, ValidateFrameRate) { ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS, "")); EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); + + // Privileged APIs. + EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); + EXPECT_FALSE(ValidateFrameRate(0.0f, ANATIVEWINDOW_FRAME_RATE_NO_VOTE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); + + constexpr bool kPrivileged = true; EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "", - /*privileged=*/true)); + kPrivileged)); + EXPECT_TRUE(ValidateFrameRate(0.0f, ANATIVEWINDOW_FRAME_RATE_NO_VOTE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "", + kPrivileged)); + // Invalid frame rate. EXPECT_FALSE(ValidateFrameRate(-1, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); EXPECT_FALSE(ValidateFrameRate(1.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, @@ -348,15 +360,12 @@ TEST_F(SetFrameRateTest, ValidateFrameRate) { EXPECT_FALSE(ValidateFrameRate(0.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); - EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, - ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); - - // Invalid compatibility + // Invalid compatibility. EXPECT_FALSE( ValidateFrameRate(60.0f, -1, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); EXPECT_FALSE(ValidateFrameRate(60.0f, 2, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, "")); - // Invalid change frame rate strategy + // Invalid change frame rate strategy. EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, -1, "")); EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, 2, "")); } -- cgit v1.2.3-59-g8ed1b