From 4bc7cdf68bdd9d3248e802e3f2f430d05879744f Mon Sep 17 00:00:00 2001 From: Kriti Dang Date: Fri, 8 Jan 2021 11:49:56 +0100 Subject: Hdr format settings [Backend] Added new API to SurfaceControl to override the HDR formats supported by device in SurfaceFlinger. This API is used in the CTS Tests to verify HDR capabilities and enabling/disabling of HDR formats. Bug: 172905874 Test: atest CtsDisplayTestCases Change-Id: Icb13cdd638d315c0e23ece8aa61242470404a428 --- libs/gui/SurfaceComposerClient.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index c16a98f42f..229ed7b5c5 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1925,6 +1925,11 @@ status_t SurfaceComposerClient::getAnimationFrameStats(FrameStats* outStats) { return ComposerService::getComposerService()->getAnimationFrameStats(outStats); } +status_t SurfaceComposerClient::overrideHdrTypes(const sp& display, + const std::vector& hdrTypes) { + return ComposerService::getComposerService()->overrideHdrTypes(display, hdrTypes); +} + status_t SurfaceComposerClient::getDisplayedContentSamplingAttributes(const sp& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, -- cgit v1.2.3-59-g8ed1b From f1833853ccc1a54dcc7056a9f87eefa1baccc945 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Tue, 23 Mar 2021 15:06:50 -0700 Subject: SF: Remove layer stack lookup for screencap GPU virtual displays now have IDs, so the (ambiguous) fallback is no longer necessary. Remove PhysicalDisplayId constructor from uint64_t to enforce error checking at compile time when upcasting or deserializing. Bug: 162612135 Bug: 182939859 Test: screencap -d Test: DisplayId_test Change-Id: I68fa0835cbc915975c7fa40c7d544d9491db9fa2 --- libs/gui/ISurfaceComposer.cpp | 30 +++++++---- libs/gui/SurfaceComposerClient.cpp | 4 +- libs/gui/include/gui/ISurfaceComposer.h | 20 ++++---- libs/gui/include/gui/SurfaceComposerClient.h | 9 ++-- libs/gui/tests/Surface_test.cpp | 16 +++--- libs/nativedisplay/AChoreographer.cpp | 5 +- libs/ui/include/ui/DisplayId.h | 35 ++++++++++--- libs/ui/tests/DisplayId_test.cpp | 12 +++++ .../display/AutomotiveDisplayProxyService.cpp | 11 +++- .../CompositionEngine/tests/DisplayTest.cpp | 7 +-- .../CompositionEngine/tests/RenderSurfaceTest.cpp | 4 +- services/surfaceflinger/DisplayDevice.h | 12 ----- services/surfaceflinger/SurfaceFlinger.cpp | 58 ++++++++-------------- services/surfaceflinger/SurfaceFlinger.h | 18 ++----- .../tests/fakehwc/SFFakeHwc_test.cpp | 4 +- .../tests/unittests/CompositionTest.cpp | 2 +- .../tests/unittests/DisplayTransactionTest.cpp | 2 +- .../tests/unittests/EventThreadTest.cpp | 9 ++-- .../tests/unittests/SchedulerTest.cpp | 2 +- 19 files changed, 133 insertions(+), 127 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 53721cf6f7..0436758e72 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -123,11 +123,11 @@ public: return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply); } - status_t captureDisplay(uint64_t displayOrLayerStack, + status_t captureDisplay(DisplayId displayId, const sp& captureListener) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(data.writeUint64, displayOrLayerStack); + SAFE_PARCEL(data.writeUint64, displayId.value); SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(captureListener)); return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply); @@ -281,9 +281,14 @@ public: NO_ERROR) { std::vector rawIds; if (reply.readUint64Vector(&rawIds) == NO_ERROR) { - std::vector displayIds(rawIds.size()); - std::transform(rawIds.begin(), rawIds.end(), displayIds.begin(), - [](uint64_t rawId) { return PhysicalDisplayId(rawId); }); + std::vector displayIds; + displayIds.reserve(rawIds.size()); + + for (const uint64_t rawId : rawIds) { + if (const auto id = DisplayId::fromValue(rawId)) { + displayIds.push_back(*id); + } + } return displayIds; } } @@ -1296,12 +1301,15 @@ status_t BnSurfaceComposer::onTransact( } case CAPTURE_DISPLAY_BY_ID: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - uint64_t displayOrLayerStack = 0; + uint64_t value; + SAFE_PARCEL(data.readUint64, &value); + const auto id = DisplayId::fromValue(value); + if (!id) return BAD_VALUE; + sp captureListener; - SAFE_PARCEL(data.readUint64, &displayOrLayerStack); SAFE_PARCEL(data.readStrongBinder, &captureListener); - return captureDisplay(displayOrLayerStack, captureListener); + return captureDisplay(*id, captureListener); } case CAPTURE_LAYERS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); @@ -1368,9 +1376,9 @@ status_t BnSurfaceComposer::onTransact( } case GET_PHYSICAL_DISPLAY_TOKEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - PhysicalDisplayId displayId(data.readUint64()); - sp display = getPhysicalDisplayToken(displayId); - reply->writeStrongBinder(display); + const auto id = DisplayId::fromValue(data.readUint64()); + if (!id) return BAD_VALUE; + reply->writeStrongBinder(getPhysicalDisplayToken(*id)); return NO_ERROR; } case GET_DISPLAY_STATE: { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 83124cf0cd..fd72a00339 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2098,12 +2098,12 @@ status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs, return s->captureDisplay(captureArgs, captureListener); } -status_t ScreenshotClient::captureDisplay(uint64_t displayOrLayerStack, +status_t ScreenshotClient::captureDisplay(DisplayId displayId, const sp& captureListener) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; - return s->captureDisplay(displayOrLayerStack, captureListener); + return s->captureDisplay(displayId, captureListener); } status_t ScreenshotClient::captureLayers(const LayerCaptureArgs& captureArgs, diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index cb0468901a..c420e4a8d4 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -114,6 +114,11 @@ public: using EventRegistrationFlags = Flags; + template + struct SpHash { + size_t operator()(const sp& k) const { return std::hash()(k.get()); } + }; + /* * Create a connection with SurfaceFlinger. */ @@ -237,24 +242,17 @@ public: * The subregion can be optionally rotated. It will also be scaled to * match the size of the output buffer. */ - virtual status_t captureDisplay(const DisplayCaptureArgs& args, - const sp& captureListener) = 0; + virtual status_t captureDisplay(const DisplayCaptureArgs&, + const sp&) = 0; - virtual status_t captureDisplay(uint64_t displayOrLayerStack, - const sp& captureListener) = 0; - - template - struct SpHash { - size_t operator()(const sp& k) const { return std::hash()(k.get()); } - }; + virtual status_t captureDisplay(DisplayId, const sp&) = 0; /** * Capture a subtree of the layer hierarchy, potentially ignoring the root node. * This requires READ_FRAME_BUFFER permission. This function will fail if there * is a secure window on screen */ - virtual status_t captureLayers(const LayerCaptureArgs& args, - const sp& captureListener) = 0; + virtual status_t captureLayers(const LayerCaptureArgs&, const sp&) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 5bbd8e3d85..da360e2760 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -608,12 +608,9 @@ private: class ScreenshotClient { public: - static status_t captureDisplay(const DisplayCaptureArgs& captureArgs, - const sp& captureListener); - static status_t captureDisplay(uint64_t displayOrLayerStack, - const sp& captureListener); - static status_t captureLayers(const LayerCaptureArgs& captureArgs, - const sp& captureListener); + static status_t captureDisplay(const DisplayCaptureArgs&, const sp&); + static status_t captureDisplay(DisplayId, const sp&); + static status_t captureLayers(const LayerCaptureArgs&, const sp&); }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ea8c2957a1..7002adf1ba 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -752,21 +752,19 @@ public: } status_t setActiveColorMode(const sp& /*display*/, ColorMode /*colorMode*/) override { return NO_ERROR; } - status_t captureDisplay(const DisplayCaptureArgs& /* captureArgs */, - const sp& /* captureListener */) override { - return NO_ERROR; - } void setAutoLowLatencyMode(const sp& /*display*/, bool /*on*/) override {} void setGameContentType(const sp& /*display*/, bool /*on*/) override {} - status_t captureDisplay(uint64_t /*displayOrLayerStack*/, - const sp& /* captureListener */) override { + + status_t captureDisplay(const DisplayCaptureArgs&, const sp&) override { return NO_ERROR; } - virtual status_t captureLayers( - const LayerCaptureArgs& /* captureArgs */, - const sp& /* captureListener */) override { + status_t captureDisplay(DisplayId, const sp&) override { return NO_ERROR; } + status_t captureLayers(const LayerCaptureArgs&, const sp&) override { + return NO_ERROR; + } + status_t clearAnimationFrameStats() override { return NO_ERROR; } status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override { return NO_ERROR; diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index 0edb213089..e7bd977876 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -306,8 +306,9 @@ void Choreographer::scheduleLatestConfigRequest() { // Fortunately, these events are small so sending packets across the // socket should be atomic across processes. DisplayEventReceiver::Event event; - event.header = DisplayEventReceiver::Event::Header{DisplayEventReceiver::DISPLAY_EVENT_NULL, - PhysicalDisplayId(0), systemTime()}; + event.header = + DisplayEventReceiver::Event::Header{DisplayEventReceiver::DISPLAY_EVENT_NULL, + PhysicalDisplayId::fromPort(0), systemTime()}; injectEvent(event); } } diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h index f196ab901a..9120972a42 100644 --- a/libs/ui/include/ui/DisplayId.h +++ b/libs/ui/include/ui/DisplayId.h @@ -38,12 +38,22 @@ struct DisplayId { uint64_t value; + // For deserialization. + static constexpr std::optional fromValue(uint64_t); + + // As above, but also upcast to Id. + template + static constexpr std::optional fromValue(uint64_t value) { + if (const auto id = Id::tryCast(DisplayId(value))) { + return id; + } + return {}; + } + protected: explicit constexpr DisplayId(uint64_t id) : value(id) {} }; -static_assert(sizeof(DisplayId) == sizeof(uint64_t)); - inline bool operator==(DisplayId lhs, DisplayId rhs) { return lhs.value == rhs.value; } @@ -80,11 +90,8 @@ struct PhysicalDisplayId : DisplayId { // TODO(b/162612135) Remove default constructor PhysicalDisplayId() = default; - // TODO(b/162612135) Remove constructor - explicit constexpr PhysicalDisplayId(uint64_t id) : DisplayId(id) {} constexpr uint16_t getManufacturerId() const { return static_cast(value >> 40); } - constexpr uint8_t getPort() const { return static_cast(value); } private: @@ -96,10 +103,9 @@ private: explicit constexpr PhysicalDisplayId(DisplayId other) : DisplayId(other) {} }; -static_assert(sizeof(PhysicalDisplayId) == sizeof(uint64_t)); - struct VirtualDisplayId : DisplayId { using BaseId = uint32_t; + // Flag indicating that this virtual display is backed by the GPU. static constexpr uint64_t FLAG_GPU = 1ULL << 61; @@ -163,10 +169,23 @@ private: explicit constexpr HalDisplayId(DisplayId other) : DisplayId(other) {} }; +constexpr std::optional DisplayId::fromValue(uint64_t value) { + if (const auto id = fromValue(value)) { + return id; + } + if (const auto id = fromValue(value)) { + return id; + } + return {}; +} + +static_assert(sizeof(DisplayId) == sizeof(uint64_t)); +static_assert(sizeof(HalDisplayId) == sizeof(uint64_t)); static_assert(sizeof(VirtualDisplayId) == sizeof(uint64_t)); + +static_assert(sizeof(PhysicalDisplayId) == sizeof(uint64_t)); static_assert(sizeof(HalVirtualDisplayId) == sizeof(uint64_t)); static_assert(sizeof(GpuVirtualDisplayId) == sizeof(uint64_t)); -static_assert(sizeof(HalDisplayId) == sizeof(uint64_t)); } // namespace android diff --git a/libs/ui/tests/DisplayId_test.cpp b/libs/ui/tests/DisplayId_test.cpp index 1d908b8ef1..8ddee7e740 100644 --- a/libs/ui/tests/DisplayId_test.cpp +++ b/libs/ui/tests/DisplayId_test.cpp @@ -32,6 +32,9 @@ TEST(DisplayIdTest, createPhysicalIdFromEdid) { EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); EXPECT_TRUE(PhysicalDisplayId::tryCast(id)); EXPECT_TRUE(HalDisplayId::tryCast(id)); + + EXPECT_EQ(id, DisplayId::fromValue(id.value)); + EXPECT_EQ(id, DisplayId::fromValue(id.value)); } TEST(DisplayIdTest, createPhysicalIdFromPort) { @@ -43,6 +46,9 @@ TEST(DisplayIdTest, createPhysicalIdFromPort) { EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); EXPECT_TRUE(PhysicalDisplayId::tryCast(id)); EXPECT_TRUE(HalDisplayId::tryCast(id)); + + EXPECT_EQ(id, DisplayId::fromValue(id.value)); + EXPECT_EQ(id, DisplayId::fromValue(id.value)); } TEST(DisplayIdTest, createGpuVirtualId) { @@ -52,6 +58,9 @@ TEST(DisplayIdTest, createGpuVirtualId) { EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); EXPECT_FALSE(HalDisplayId::tryCast(id)); + + EXPECT_EQ(id, DisplayId::fromValue(id.value)); + EXPECT_EQ(id, DisplayId::fromValue(id.value)); } TEST(DisplayIdTest, createHalVirtualId) { @@ -61,6 +70,9 @@ TEST(DisplayIdTest, createHalVirtualId) { EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); EXPECT_TRUE(HalDisplayId::tryCast(id)); + + EXPECT_EQ(id, DisplayId::fromValue(id.value)); + EXPECT_EQ(id, DisplayId::fromValue(id.value)); } } // namespace android::ui diff --git a/services/automotive/display/AutomotiveDisplayProxyService.cpp b/services/automotive/display/AutomotiveDisplayProxyService.cpp index d6fc69562b..d205231033 100644 --- a/services/automotive/display/AutomotiveDisplayProxyService.cpp +++ b/services/automotive/display/AutomotiveDisplayProxyService.cpp @@ -34,7 +34,10 @@ AutomotiveDisplayProxyService::getIGraphicBufferProducer(uint64_t id) { sp displayToken = nullptr; sp surfaceControl = nullptr; if (it == mDisplays.end()) { - displayToken = SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(id)); + if (const auto displayId = DisplayId::fromValue(id)) { + displayToken = SurfaceComposerClient::getPhysicalDisplayToken(*displayId); + } + if (displayToken == nullptr) { ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id); return nullptr; @@ -157,7 +160,11 @@ Return AutomotiveDisplayProxyService::getDisplayInfo(uint64_t id, getDispl HwDisplayConfig activeConfig; HwDisplayState activeState; - auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(id)); + sp displayToken; + if (const auto displayId = DisplayId::fromValue(id)) { + displayToken = SurfaceComposerClient::getPhysicalDisplayToken(*displayId); + } + if (displayToken == nullptr) { ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id); } else { diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 8a83639ce5..b31e64ac0d 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -60,9 +60,10 @@ using testing::Sequence; using testing::SetArgPointee; using testing::StrictMock; -constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId{42}; +constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u); // TODO(b/160679868) Use VirtualDisplayId -constexpr PhysicalDisplayId VIRTUAL_DISPLAY_ID = PhysicalDisplayId{43}; +constexpr PhysicalDisplayId VIRTUAL_DISPLAY_ID = PhysicalDisplayId::fromPort(43u); + constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920; constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080; constexpr int32_t DEFAULT_LAYER_STACK = 123; @@ -1049,4 +1050,4 @@ TEST_F(DisplayFunctionalTest, postFramebufferCriticalCallsAreOrdered) { } // namespace android::compositionengine // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file +#pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index 9aeb290eb5..8579d8c444 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -39,7 +39,7 @@ namespace { constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920; constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080; -constexpr DisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId(123u); +constexpr DisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(123u); const std::string DEFAULT_DISPLAY_NAME = "Mock Display"; using testing::_; @@ -374,4 +374,4 @@ TEST_F(RenderSurfaceTest, flipForwardsSignal) { } // namespace android::compositionengine // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file +#pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 9976e1e43c..68846d35bd 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -282,16 +282,4 @@ struct DisplayDeviceCreationArgs { DisplayModes supportedModes; }; -// Predicates for display lookup. - -struct WithLayerStack { - explicit WithLayerStack(ui::LayerStack layerStack) : layerStack(layerStack) {} - - bool operator()(const DisplayDevice& display) const { - return display.getLayerStack() == layerStack; - } - - ui::LayerStack layerStack; -}; - } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 548aa3262c..eb3ae269eb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5492,37 +5492,24 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r } case 1035: { const int modeId = data.readInt32(); - mDebugDisplayModeSetByBackdoor = false; - - const auto displayId = [&]() -> std::optional { - uint64_t inputDisplayId = 0; - if (data.readUint64(&inputDisplayId) == NO_ERROR) { - const auto token = getPhysicalDisplayToken( - static_cast(inputDisplayId)); - if (!token) { - ALOGE("No display with id: %" PRIu64, inputDisplayId); - return std::nullopt; - } - return std::make_optional(inputDisplayId); + const auto display = [&]() -> sp { + uint64_t value; + if (data.readUint64(&value) != NO_ERROR) { + return getInternalDisplayToken(); } - return getInternalDisplayId(); - }(); - - if (!displayId) { - ALOGE("No display found"); - return NO_ERROR; - } - - status_t result = setActiveMode(getPhysicalDisplayToken(*displayId), modeId); - if (result != NO_ERROR) { - return result; - } + if (const auto id = DisplayId::fromValue(value)) { + return getPhysicalDisplayToken(*id); + } - mDebugDisplayModeSetByBackdoor = true; + ALOGE("Invalid physical display ID"); + return nullptr; + }(); - return NO_ERROR; + const status_t result = setActiveMode(display, modeId); + mDebugDisplayModeSetByBackdoor = result == NO_ERROR; + return result; } case 1036: { if (data.readInt32() > 0) { @@ -5759,7 +5746,7 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, captureListener); } -status_t SurfaceFlinger::captureDisplay(uint64_t displayIdOrLayerStack, +status_t SurfaceFlinger::captureDisplay(DisplayId displayId, const sp& captureListener) { ui::LayerStack layerStack; wp displayWeak; @@ -5767,21 +5754,14 @@ status_t SurfaceFlinger::captureDisplay(uint64_t displayIdOrLayerStack, ui::Dataspace dataspace; { Mutex::Autolock lock(mStateLock); - auto display = getDisplayDeviceLocked(PhysicalDisplayId{displayIdOrLayerStack}); - - // Fall back to first display whose layer stack matches. - if (!display) { - const auto layerStack = static_cast(displayIdOrLayerStack); - display = findDisplay(WithLayerStack(layerStack)); - } + const auto display = getDisplayDeviceLocked(displayId); if (!display) { return NAME_NOT_FOUND; } - layerStack = display->getLayerStack(); displayWeak = display; - + layerStack = display->getLayerStack(); size = display->getLayerStackSpaceRect().getSize(); dataspace = @@ -5863,7 +5843,11 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, } } - const auto display = findDisplay(WithLayerStack(parent->getLayerStack())); + const auto display = + findDisplay([layerStack = parent->getLayerStack()](const auto& display) { + return display.getLayerStack() == layerStack; + }); + if (!display) { return NAME_NOT_FOUND; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index fb82b3ee9e..66702fe836 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -613,12 +613,10 @@ private: sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) override; - status_t captureDisplay(const DisplayCaptureArgs& args, - const sp& captureListener) override; - status_t captureDisplay(uint64_t displayOrLayerStack, - const sp& captureListener) override; - status_t captureLayers(const LayerCaptureArgs& args, - const sp& captureListener) override; + + status_t captureDisplay(const DisplayCaptureArgs&, const sp&) override; + status_t captureDisplay(DisplayId, const sp&) override; + status_t captureLayers(const LayerCaptureArgs&, const sp&) override; status_t getDisplayStats(const sp& displayToken, DisplayStatInfo* stats) override; status_t getDisplayState(const sp& displayToken, ui::DisplayState*) @@ -932,14 +930,6 @@ private: return it == mDisplays.end() ? nullptr : it->second; } - sp getDisplayDeviceLocked(PhysicalDisplayId id) const - REQUIRES(mStateLock) { - if (const auto token = getPhysicalDisplayTokenLocked(id)) { - return getDisplayDeviceLocked(token); - } - return nullptr; - } - sp getDefaultDisplayDeviceLocked() const REQUIRES(mStateLock) { return const_cast(this)->getDefaultDisplayDeviceLocked(); } diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 162711d6f5..a9e935df22 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -279,7 +279,7 @@ protected: } bool waitForHotplugEvent(Display displayId, bool connected) { - return waitForHotplugEvent(PhysicalDisplayId(displayId), connected); + return waitForHotplugEvent(physicalIdFromHwcDisplayId(displayId), connected); } bool waitForHotplugEvent(PhysicalDisplayId displayId, bool connected) { @@ -305,7 +305,7 @@ protected: } bool waitForModeChangedEvent(Display display, int32_t modeId) { - PhysicalDisplayId displayId(display); + PhysicalDisplayId displayId = physicalIdFromHwcDisplayId(display); int waitCount = 20; while (waitCount--) { while (!mReceivedDisplayEvents.empty()) { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 3042450f29..e42cf47657 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -77,7 +77,7 @@ constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DIS constexpr hal::HWLayerId HWC_LAYER = 5000; constexpr Transform DEFAULT_TRANSFORM = static_cast(0); -constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID(42); +constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u); constexpr int DEFAULT_DISPLAY_WIDTH = 1920; constexpr int DEFAULT_DISPLAY_HEIGHT = 1024; diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index a3e810871c..359e555e92 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -118,7 +118,7 @@ void DisplayTransactionTest::injectFakeNativeWindowSurfaceFactory() { sp DisplayTransactionTest::injectDefaultInternalDisplay( std::function injectExtra) { - constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID(777); + constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(255u); constexpr int DEFAULT_DISPLAY_WIDTH = 1080; constexpr int DEFAULT_DISPLAY_HEIGHT = 1920; constexpr HWDisplayId DEFAULT_DISPLAY_HWC_DISPLAY_ID = 0; diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index b4a1481e9c..62acc6b549 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -41,10 +41,13 @@ namespace android { namespace { -constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID(111); -constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID(222); -constexpr PhysicalDisplayId DISPLAY_ID_64BIT(0xabcd12349876fedcULL); +constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = PhysicalDisplayId::fromPort(111u); +constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID = PhysicalDisplayId::fromPort(222u); +constexpr PhysicalDisplayId DISPLAY_ID_64BIT = + PhysicalDisplayId::fromEdid(0xffu, 0xffffu, 0xffff'ffffu); + constexpr std::chrono::duration VSYNC_PERIOD(16ms); + class MockVSyncSource : public VSyncSource { public: const char* getName() const override { return "test"; } diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 38e503fc81..7a6ae5bbc2 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -34,7 +34,7 @@ using testing::Return; namespace android { namespace { -constexpr PhysicalDisplayId PHYSICAL_DISPLAY_ID(999); +constexpr PhysicalDisplayId PHYSICAL_DISPLAY_ID = PhysicalDisplayId::fromPort(255u); class SchedulerTest : public testing::Test { protected: -- 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/SurfaceComposerClient.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