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 --- services/inputflinger/InputReaderBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/inputflinger/InputReaderBase.cpp') diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp index 9cc777d450..f26a9a986d 100644 --- a/services/inputflinger/InputReaderBase.cpp +++ b/services/inputflinger/InputReaderBase.cpp @@ -19,9 +19,9 @@ //#define LOG_NDEBUG 0 #include "InputReaderBase.h" +#include #include "input/DisplayViewport.h" #include "input/Input.h" -#include "input/NamedEnum.h" #include #include -- cgit v1.2.3-59-g8ed1b From 5cc1a69bd232d2291861607d64a0e43c1fa1409b Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Fri, 6 Aug 2021 14:01:18 +0000 Subject: Use sequence numbers to synchronize enabling Pointer Capture (1/2) InputReader only processes configuration change from its main thread. This means that if there is more than one Pointer Capture change request when the thread is busy or sleeping, it will only process the latest one. To ensure requests to enable Pointer Capture are synchronized with Dispatcher, we must use sequence numbers. Requests to enable Pointer Capture have a sequence number. Requests to disable Pointer Capture do not have a value. Bug: 195312888 Test: atest inputflinger_tests Test: manual with GeforceNow app, see bug. Change-Id: I6ae9c5498dc2f783b4c7211fa3665d42e29d2919 --- include/input/Input.h | 19 +++++ services/inputflinger/InputListener.cpp | 10 +-- services/inputflinger/InputReaderBase.cpp | 3 + .../benchmarks/InputDispatcher_benchmarks.cpp | 2 +- services/inputflinger/dispatcher/Entry.cpp | 6 +- services/inputflinger/dispatcher/Entry.h | 4 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 85 ++++++++++++--------- services/inputflinger/dispatcher/InputDispatcher.h | 12 +-- .../include/InputDispatcherPolicyInterface.h | 2 +- services/inputflinger/docs/pointer_capture.md | 4 +- services/inputflinger/include/InputListener.h | 5 +- services/inputflinger/include/InputReaderBase.h | 25 +++--- services/inputflinger/reader/InputReader.cpp | 12 ++- services/inputflinger/reader/include/InputReader.h | 2 + .../reader/mapper/CursorInputMapper.cpp | 4 +- .../reader/mapper/TouchInputMapper.cpp | 7 +- .../inputflinger/tests/InputDispatcher_test.cpp | 88 ++++++++++++++-------- services/inputflinger/tests/InputReader_test.cpp | 19 +++-- services/inputflinger/tests/TestInputListener.cpp | 5 ++ services/inputflinger/tests/TestInputListener.h | 1 + 20 files changed, 200 insertions(+), 115 deletions(-) (limited to 'services/inputflinger/InputReaderBase.cpp') diff --git a/include/input/Input.h b/include/input/Input.h index 2e424097e1..d2d9fd48e8 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -1025,6 +1025,25 @@ private: std::queue> mTouchModeEventPool; }; +/* + * Describes a unique request to enable or disable Pointer Capture. + */ +struct PointerCaptureRequest { +public: + inline PointerCaptureRequest() : enable(false), seq(0) {} + inline PointerCaptureRequest(bool enable, uint32_t seq) : enable(enable), seq(seq) {} + inline bool operator==(const PointerCaptureRequest& other) const { + return enable == other.enable && seq == other.seq; + } + explicit inline operator bool() const { return enable; } + + // True iff this is a request to enable Pointer Capture. + bool enable; + + // The sequence number for the request. + uint32_t seq; +}; + } // namespace android #endif // _LIBINPUT_INPUT_H diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp index 33b3e1ee2f..71b0f5fec9 100644 --- a/services/inputflinger/InputListener.cpp +++ b/services/inputflinger/InputListener.cpp @@ -287,16 +287,16 @@ void NotifyDeviceResetArgs::notify(const sp& listener) c // --- NotifyPointerCaptureChangedArgs --- -NotifyPointerCaptureChangedArgs::NotifyPointerCaptureChangedArgs(int32_t id, nsecs_t eventTime, - bool enabled) - : NotifyArgs(id, eventTime), enabled(enabled) {} +NotifyPointerCaptureChangedArgs::NotifyPointerCaptureChangedArgs( + int32_t id, nsecs_t eventTime, const PointerCaptureRequest& request) + : NotifyArgs(id, eventTime), request(request) {} NotifyPointerCaptureChangedArgs::NotifyPointerCaptureChangedArgs( const NotifyPointerCaptureChangedArgs& other) - : NotifyArgs(other.id, other.eventTime), enabled(other.enabled) {} + : NotifyArgs(other.id, other.eventTime), request(other.request) {} bool NotifyPointerCaptureChangedArgs::operator==(const NotifyPointerCaptureChangedArgs& rhs) const { - return id == rhs.id && eventTime == rhs.eventTime && enabled == rhs.enabled; + return id == rhs.id && eventTime == rhs.eventTime && request == rhs.request; } void NotifyPointerCaptureChangedArgs::notify(const sp& listener) const { diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp index f26a9a986d..05ef489133 100644 --- a/services/inputflinger/InputReaderBase.cpp +++ b/services/inputflinger/InputReaderBase.cpp @@ -67,6 +67,9 @@ std::string InputReaderConfiguration::changesToString(uint32_t changes) { if (changes & CHANGE_EXTERNAL_STYLUS_PRESENCE) { result += "EXTERNAL_STYLUS_PRESENCE | "; } + if (changes & CHANGE_POINTER_CAPTURE) { + result += "POINTER_CAPTURE | "; + } if (changes & CHANGE_ENABLED_STATE) { result += "ENABLED_STATE | "; } diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 5e9facf47e..6ce0313929 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -116,7 +116,7 @@ private: void onPointerDownOutsideFocus(const sp& newToken) override {} - void setPointerCapture(bool enabled) override {} + void setPointerCapture(const PointerCaptureRequest&) override {} void notifyDropWindow(const sp&, float x, float y) override {} diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index 288068f584..9744920714 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -119,15 +119,15 @@ std::string FocusEntry::getDescription() const { // PointerCaptureChanged notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER // for all entries. PointerCaptureChangedEntry::PointerCaptureChangedEntry(int32_t id, nsecs_t eventTime, - bool hasPointerCapture) + const PointerCaptureRequest& request) : EventEntry(id, Type::POINTER_CAPTURE_CHANGED, eventTime, POLICY_FLAG_PASS_TO_USER), - pointerCaptureEnabled(hasPointerCapture) {} + pointerCaptureRequest(request) {} PointerCaptureChangedEntry::~PointerCaptureChangedEntry() {} std::string PointerCaptureChangedEntry::getDescription() const { return StringPrintf("PointerCaptureChangedEvent(pointerCaptureEnabled=%s)", - pointerCaptureEnabled ? "true" : "false"); + pointerCaptureRequest.enable ? "true" : "false"); } // --- DragEntry --- diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index 8feb98243b..44c35c127b 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -104,9 +104,9 @@ struct FocusEntry : EventEntry { }; struct PointerCaptureChangedEntry : EventEntry { - bool pointerCaptureEnabled; + const PointerCaptureRequest pointerCaptureRequest; - PointerCaptureChangedEntry(int32_t id, nsecs_t eventTime, bool hasPointerCapture); + PointerCaptureChangedEntry(int32_t id, nsecs_t eventTime, const PointerCaptureRequest&); std::string getDescription() const override; ~PointerCaptureChangedEntry() override; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 59cb419d2b..e097773370 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -559,7 +559,6 @@ InputDispatcher::InputDispatcher(const sp& polic mInTouchMode(true), mMaximumObscuringOpacityForTouch(1.0f), mFocusedDisplayId(ADISPLAY_ID_DEFAULT), - mFocusedWindowRequestedPointerCapture(false), mWindowTokenWithPointerCapture(nullptr), mLatencyAggregator(), mLatencyTracker(&mLatencyAggregator), @@ -1331,36 +1330,51 @@ void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, std::shared_ptr& entry, DropReason& dropReason) { - const bool haveWindowWithPointerCapture = mWindowTokenWithPointerCapture != nullptr; - if (entry->pointerCaptureEnabled && haveWindowWithPointerCapture) { - LOG_ALWAYS_FATAL("Pointer Capture has already been enabled for the window."); - } - if (!entry->pointerCaptureEnabled && !haveWindowWithPointerCapture) { - // Pointer capture was already forcefully disabled because of focus change. - dropReason = DropReason::NOT_DROPPED; - return; - } - - // Set drop reason for early returns - dropReason = DropReason::NO_POINTER_CAPTURE; + dropReason = DropReason::NOT_DROPPED; + const bool haveWindowWithPointerCapture = mWindowTokenWithPointerCapture != nullptr; sp token; - if (entry->pointerCaptureEnabled) { - // Enable Pointer Capture - if (!mFocusedWindowRequestedPointerCapture) { + + if (entry->pointerCaptureRequest.enable) { + // Enable Pointer Capture. + if (haveWindowWithPointerCapture && + (entry->pointerCaptureRequest == mCurrentPointerCaptureRequest)) { + LOG_ALWAYS_FATAL("This request to enable Pointer Capture has already been dispatched " + "to the window."); + } + if (!mCurrentPointerCaptureRequest.enable) { // This can happen if a window requests capture and immediately releases capture. ALOGW("No window requested Pointer Capture."); + dropReason = DropReason::NO_POINTER_CAPTURE; + return; + } + if (entry->pointerCaptureRequest.seq != mCurrentPointerCaptureRequest.seq) { + ALOGI("Skipping dispatch of Pointer Capture being enabled: sequence number mismatch."); return; } + token = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId); LOG_ALWAYS_FATAL_IF(!token, "Cannot find focused window for Pointer Capture."); mWindowTokenWithPointerCapture = token; } else { - // Disable Pointer Capture + // Disable Pointer Capture. + // We do not check if the sequence number matches for requests to disable Pointer Capture + // for two reasons: + // 1. Pointer Capture can be disabled by a focus change, which means we can get two entries + // to disable capture with the same sequence number: one generated by + // disablePointerCaptureForcedLocked() and another as an acknowledgement of Pointer + // Capture being disabled in InputReader. + // 2. We respect any request to disable Pointer Capture generated by InputReader, since the + // actual Pointer Capture state that affects events being generated by input devices is + // in InputReader. + if (!haveWindowWithPointerCapture) { + // Pointer capture was already forcefully disabled because of focus change. + dropReason = DropReason::NOT_DROPPED; + return; + } token = mWindowTokenWithPointerCapture; mWindowTokenWithPointerCapture = nullptr; - if (mFocusedWindowRequestedPointerCapture) { - mFocusedWindowRequestedPointerCapture = false; + if (mCurrentPointerCaptureRequest.enable) { setPointerCaptureLocked(false); } } @@ -1369,8 +1383,7 @@ void InputDispatcher::dispatchPointerCaptureChangedLocked( if (channel == nullptr) { // Window has gone away, clean up Pointer Capture state. mWindowTokenWithPointerCapture = nullptr; - if (mFocusedWindowRequestedPointerCapture) { - mFocusedWindowRequestedPointerCapture = false; + if (mCurrentPointerCaptureRequest.enable) { setPointerCaptureLocked(false); } return; @@ -3183,7 +3196,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, static_cast(eventEntry); status = connection->inputPublisher .publishCaptureEvent(dispatchEntry->seq, captureEntry.id, - captureEntry.pointerCaptureEnabled); + captureEntry.pointerCaptureRequest.enable); break; } @@ -3999,14 +4012,14 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { void InputDispatcher::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) { if (DEBUG_INBOUND_EVENT_DETAILS) { ALOGD("notifyPointerCaptureChanged - eventTime=%" PRId64 ", enabled=%s", args->eventTime, - args->enabled ? "true" : "false"); + args->request.enable ? "true" : "false"); } bool needWake; { // acquire lock std::scoped_lock _l(mLock); auto entry = std::make_unique(args->id, args->eventTime, - args->enabled); + args->request); needWake = enqueueInboundEventLocked(std::move(entry)); } // release lock @@ -4944,8 +4957,8 @@ void InputDispatcher::logDispatchStateLocked() { std::string InputDispatcher::dumpPointerCaptureStateLocked() { std::string dump; - dump += StringPrintf(INDENT "FocusedWindowRequestedPointerCapture: %s\n", - toString(mFocusedWindowRequestedPointerCapture)); + dump += StringPrintf(INDENT "Pointer Capture Requested: %s\n", + toString(mCurrentPointerCaptureRequest.enable)); std::string windowName = "None"; if (mWindowTokenWithPointerCapture) { @@ -4954,7 +4967,7 @@ std::string InputDispatcher::dumpPointerCaptureStateLocked() { windowName = captureWindowHandle ? captureWindowHandle->getName().c_str() : "token has capture without window"; } - dump += StringPrintf(INDENT "CurrentWindowWithPointerCapture: %s\n", windowName.c_str()); + dump += StringPrintf(INDENT "Current Window with Pointer Capture: %s\n", windowName.c_str()); return dump; } @@ -5420,14 +5433,13 @@ void InputDispatcher::requestPointerCapture(const sp& windowToken, bool return; } - if (enabled == mFocusedWindowRequestedPointerCapture) { + if (enabled == mCurrentPointerCaptureRequest.enable) { ALOGW("Ignoring request to %s Pointer Capture: " "window has %s requested pointer capture.", enabled ? "enable" : "disable", enabled ? "already" : "not"); return; } - mFocusedWindowRequestedPointerCapture = enabled; setPointerCaptureLocked(enabled); } // release lock @@ -6048,14 +6060,13 @@ void InputDispatcher::onFocusChangedLocked(const FocusResolver::FocusChanges& ch } void InputDispatcher::disablePointerCaptureForcedLocked() { - if (!mFocusedWindowRequestedPointerCapture && !mWindowTokenWithPointerCapture) { + if (!mCurrentPointerCaptureRequest.enable && !mWindowTokenWithPointerCapture) { return; } ALOGD_IF(DEBUG_FOCUS, "Disabling Pointer Capture because the window lost focus."); - if (mFocusedWindowRequestedPointerCapture) { - mFocusedWindowRequestedPointerCapture = false; + if (mCurrentPointerCaptureRequest.enable) { setPointerCaptureLocked(false); } @@ -6072,14 +6083,16 @@ void InputDispatcher::disablePointerCaptureForcedLocked() { } auto entry = std::make_unique(mIdGenerator.nextId(), now(), - false /* hasCapture */); + mCurrentPointerCaptureRequest); mInboundQueue.push_front(std::move(entry)); } -void InputDispatcher::setPointerCaptureLocked(bool enabled) { - auto command = [this, enabled]() REQUIRES(mLock) { +void InputDispatcher::setPointerCaptureLocked(bool enable) { + mCurrentPointerCaptureRequest.enable = enable; + mCurrentPointerCaptureRequest.seq++; + auto command = [this, request = mCurrentPointerCaptureRequest]() REQUIRES(mLock) { scoped_unlock unlock(mLock); - mPolicy->setPointerCapture(enabled); + mPolicy->setPointerCapture(request); }; postCommandLocked(std::move(command)); } diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 6df333a154..d0d58a40ad 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -383,10 +383,12 @@ private: // Keeps track of the focused window per display and determines focus changes. FocusResolver mFocusResolver GUARDED_BY(mLock); - // Whether the focused window on the focused display has requested Pointer Capture. - // The state of this variable should always be in sync with the state of Pointer Capture in the - // policy, which is updated through setPointerCaptureLocked(enabled). - bool mFocusedWindowRequestedPointerCapture GUARDED_BY(mLock); + + // The enabled state of this request is true iff the focused window on the focused display has + // requested Pointer Capture. This request also contains the sequence number associated with the + // current request. The state of this variable should always be in sync with the state of + // Pointer Capture in the policy, and is only updated through setPointerCaptureLocked(request). + PointerCaptureRequest mCurrentPointerCaptureRequest GUARDED_BY(mLock); // The window token that has Pointer Capture. // This should be in sync with PointerCaptureChangedEvents dispatched to the input channel. @@ -396,7 +398,7 @@ private: void disablePointerCaptureForcedLocked() REQUIRES(mLock); // Set the Pointer Capture state in the Policy. - void setPointerCaptureLocked(bool enabled) REQUIRES(mLock); + void setPointerCaptureLocked(bool enable) REQUIRES(mLock); // Dispatcher state at time of last ANR. std::string mLastAnrState GUARDED_BY(mLock); diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index ebfcbe17b2..3c1e6370b7 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -156,7 +156,7 @@ public: * * InputDispatcher is solely responsible for updating the Pointer Capture state. */ - virtual void setPointerCapture(bool enabled) = 0; + virtual void setPointerCapture(const PointerCaptureRequest&) = 0; /* Notifies the policy that the drag window has moved over to another window */ virtual void notifyDropWindow(const sp& token, float x, float y) = 0; diff --git a/services/inputflinger/docs/pointer_capture.md b/services/inputflinger/docs/pointer_capture.md index 8da699dc56..0b44187c08 100644 --- a/services/inputflinger/docs/pointer_capture.md +++ b/services/inputflinger/docs/pointer_capture.md @@ -17,6 +17,8 @@ `InputDispatcher` is responsible for controlling the state of Pointer Capture. Since the feature requires changes to how events are generated, Pointer Capture is configured in `InputReader`. +We use a sequence number to synchronize different requests to enable Pointer Capture between InputReader and InputDispatcher. + ### Enabling Pointer Capture There are four key steps that take place when Pointer Capture is enabled: @@ -40,5 +42,5 @@ When an `InputWindow` with Pointer Capture loses focus, Pointer Capture is disab `InputDispatcher` tracks two pieces of state information regarding Pointer Capture: -- `mFocusedWindowRequestedPointerCapture`: Whether or not the focused window has requested Pointer Capture. This is updated whenever the Dispatcher receives requests from `InputManagerService`. +- `mCurrentPointerCaptureRequest`: The sequence number of the current Pointer Capture request. This request is enabled iff the focused window has requested Pointer Capture. This is updated whenever the Dispatcher receives requests from `InputManagerService`. - `mWindowTokenWithPointerCapture`: The Binder token of the `InputWindow` that currently has Pointer Capture. This is only updated during the dispatch cycle. If it is not `nullptr`, it signifies that the window was notified that it has Pointer Capture. diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h index 4b7d26df2b..fe74214b36 100644 --- a/services/inputflinger/include/InputListener.h +++ b/services/inputflinger/include/InputListener.h @@ -211,11 +211,12 @@ struct NotifyDeviceResetArgs : public NotifyArgs { /* Describes a change in the state of Pointer Capture. */ struct NotifyPointerCaptureChangedArgs : public NotifyArgs { - bool enabled; + // The sequence number of the Pointer Capture request, if enabled. + PointerCaptureRequest request; inline NotifyPointerCaptureChangedArgs() {} - NotifyPointerCaptureChangedArgs(int32_t id, nsecs_t eventTime, bool enabled); + NotifyPointerCaptureChangedArgs(int32_t id, nsecs_t eventTime, const PointerCaptureRequest&); NotifyPointerCaptureChangedArgs(const NotifyPointerCaptureChangedArgs& other); diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 7fdbbfdac4..3c8ac1cf7b 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -279,29 +279,30 @@ struct InputReaderConfiguration { // True to show the location of touches on the touch screen as spots. bool showTouches; - // True if pointer capture is enabled. - bool pointerCapture; + // The latest request to enable or disable Pointer Capture. + PointerCaptureRequest pointerCaptureRequest; // The set of currently disabled input devices. std::set disabledDevices; - InputReaderConfiguration() : - virtualKeyQuietTime(0), + InputReaderConfiguration() + : virtualKeyQuietTime(0), pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f), wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f), pointerGesturesEnabled(true), - pointerGestureQuietInterval(100 * 1000000LL), // 100 ms - pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second - pointerGestureTapInterval(150 * 1000000LL), // 150 ms - pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms - pointerGestureTapSlop(10.0f), // 10 pixels + pointerGestureQuietInterval(100 * 1000000LL), // 100 ms + pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second + pointerGestureTapInterval(150 * 1000000LL), // 150 ms + pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms + pointerGestureTapSlop(10.0f), // 10 pixels pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms - pointerGestureMultitouchMinDistance(15), // 15 pixels - pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees + pointerGestureMultitouchMinDistance(15), // 15 pixels + pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees pointerGestureSwipeMaxWidthRatio(0.25f), pointerGestureMovementSpeedRatio(0.8f), pointerGestureZoomSpeedRatio(0.3f), - showTouches(false), pointerCapture(false) { } + showTouches(false), + pointerCaptureRequest() {} static std::string changesToString(uint32_t changes); diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index e71a9e90ed..86d4c26469 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -367,9 +367,15 @@ void InputReader::refreshConfigurationLocked(uint32_t changes) { } if (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE) { - const NotifyPointerCaptureChangedArgs args(mContext.getNextId(), now, - mConfig.pointerCapture); - mQueuedListener->notifyPointerCaptureChanged(&args); + if (mCurrentPointerCaptureRequest == mConfig.pointerCaptureRequest) { + ALOGV("Skipping notifying pointer capture changes: " + "There was no change in the pointer capture state."); + } else { + mCurrentPointerCaptureRequest = mConfig.pointerCaptureRequest; + const NotifyPointerCaptureChangedArgs args(mContext.getNextId(), now, + mCurrentPointerCaptureRequest); + mQueuedListener->notifyPointerCaptureChanged(&args); + } } } diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index a00c5af4dc..e44aa0fe27 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -230,6 +230,8 @@ private: uint32_t mConfigurationChangesToRefresh GUARDED_BY(mLock); void refreshConfigurationLocked(uint32_t changes) REQUIRES(mLock); + PointerCaptureRequest mCurrentPointerCaptureRequest GUARDED_BY(mLock); + // state queries typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code); int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code, diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp index 437902a79b..2ac41b1e67 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp @@ -154,9 +154,9 @@ void CursorInputMapper::configure(nsecs_t when, const InputReaderConfiguration* mHWheelScale = 1.0f; } - if ((!changes && config->pointerCapture) || + if ((!changes && config->pointerCaptureRequest.enable) || (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)) { - if (config->pointerCapture) { + if (config->pointerCaptureRequest.enable) { if (mParameters.mode == Parameters::MODE_POINTER) { mParameters.mode = Parameters::MODE_POINTER_RELATIVE; mSource = AINPUT_SOURCE_MOUSE_RELATIVE; diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index a9f024733f..4cc8f90a22 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -603,7 +603,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { // Determine device mode. if (mParameters.deviceType == Parameters::DeviceType::POINTER && - mConfig.pointerGesturesEnabled && !mConfig.pointerCapture) { + mConfig.pointerGesturesEnabled && !mConfig.pointerCaptureRequest.enable) { mSource = AINPUT_SOURCE_MOUSE; mDeviceMode = DeviceMode::POINTER; if (hasStylus()) { @@ -776,11 +776,12 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { // preserve the cursor position. if (mDeviceMode == DeviceMode::POINTER || (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches) || - (mParameters.deviceType == Parameters::DeviceType::POINTER && mConfig.pointerCapture)) { + (mParameters.deviceType == Parameters::DeviceType::POINTER && + mConfig.pointerCaptureRequest.enable)) { if (mPointerController == nullptr) { mPointerController = getContext()->getPointerController(getDeviceId()); } - if (mConfig.pointerCapture) { + if (mConfig.pointerCaptureRequest.enable) { mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE); } } else { diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 0fc4708548..f997cb75eb 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -243,19 +243,22 @@ public: mConfig.keyRepeatDelay = delay; } - void waitForSetPointerCapture(bool enabled) { + PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) { std::unique_lock lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms, [this, enabled]() REQUIRES(mLock) { - return mPointerCaptureEnabled && - *mPointerCaptureEnabled == + return mPointerCaptureRequest->enable == enabled; })) { - FAIL() << "Timed out waiting for setPointerCapture(" << enabled << ") to be called."; + ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled + << ") to be called."; + return {}; } - mPointerCaptureEnabled.reset(); + auto request = *mPointerCaptureRequest; + mPointerCaptureRequest.reset(); + return request; } void assertSetPointerCaptureNotCalled() { @@ -263,11 +266,11 @@ public: base::ScopedLockAssertion assumeLocked(mLock); if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) { - FAIL() << "Expected setPointerCapture(enabled) to not be called, but was called. " + FAIL() << "Expected setPointerCapture(request) to not be called, but was called. " "enabled = " - << *mPointerCaptureEnabled; + << std::to_string(mPointerCaptureRequest->enable); } - mPointerCaptureEnabled.reset(); + mPointerCaptureRequest.reset(); } void assertDropTargetEquals(const sp& targetToken) { @@ -285,7 +288,8 @@ private: std::optional mLastNotifySwitch GUARDED_BY(mLock); std::condition_variable mPointerCaptureChangedCondition; - std::optional mPointerCaptureEnabled GUARDED_BY(mLock); + + std::optional mPointerCaptureRequest GUARDED_BY(mLock); // ANR handling std::queue> mAnrApplications GUARDED_BY(mLock); @@ -402,9 +406,9 @@ private: mOnPointerDownToken = newToken; } - void setPointerCapture(bool enabled) override { + void setPointerCapture(const PointerCaptureRequest& request) override { std::scoped_lock lock(mLock); - mPointerCaptureEnabled = {enabled}; + mPointerCaptureRequest = {request}; mPointerCaptureChangedCondition.notify_all(); } @@ -1385,8 +1389,9 @@ static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32 return generateMotionArgs(action, source, displayId, {PointF{100, 200}}); } -static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(bool enabled) { - return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), enabled); +static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs( + const PointerCaptureRequest& request) { + return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request); } TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) { @@ -4596,16 +4601,18 @@ protected: mWindow->consumeFocusEvent(true); } - void notifyPointerCaptureChanged(bool enabled) { - const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(enabled); + void notifyPointerCaptureChanged(const PointerCaptureRequest& request) { + const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request); mDispatcher->notifyPointerCaptureChanged(&args); } - void requestAndVerifyPointerCapture(const sp& window, bool enabled) { + PointerCaptureRequest requestAndVerifyPointerCapture(const sp& window, + bool enabled) { mDispatcher->requestPointerCapture(window->getToken(), enabled); - mFakePolicy->waitForSetPointerCapture(enabled); - notifyPointerCaptureChanged(enabled); + auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled); + notifyPointerCaptureChanged(request); window->consumeCaptureEvent(enabled); + return request; } }; @@ -4627,7 +4634,7 @@ TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) { } TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) { - requestAndVerifyPointerCapture(mWindow, true); + auto request = requestAndVerifyPointerCapture(mWindow, true); setFocusedWindow(mSecondWindow); @@ -4635,26 +4642,26 @@ TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLose mWindow->consumeCaptureEvent(false); mWindow->consumeFocusEvent(false); mSecondWindow->consumeFocusEvent(true); - mFakePolicy->waitForSetPointerCapture(false); + mFakePolicy->assertSetPointerCaptureCalled(false); // Ensure that additional state changes from InputReader are not sent to the window. - notifyPointerCaptureChanged(false); - notifyPointerCaptureChanged(true); - notifyPointerCaptureChanged(false); + notifyPointerCaptureChanged({}); + notifyPointerCaptureChanged(request); + notifyPointerCaptureChanged({}); mWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); mFakePolicy->assertSetPointerCaptureNotCalled(); } TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) { - requestAndVerifyPointerCapture(mWindow, true); + auto request = requestAndVerifyPointerCapture(mWindow, true); // InputReader unexpectedly disables and enables pointer capture. - notifyPointerCaptureChanged(false); - notifyPointerCaptureChanged(true); + notifyPointerCaptureChanged({}); + notifyPointerCaptureChanged(request); // Ensure that Pointer Capture is disabled. - mFakePolicy->waitForSetPointerCapture(false); + mFakePolicy->assertSetPointerCaptureCalled(false); mWindow->consumeCaptureEvent(false); mWindow->assertNoEvents(); } @@ -4664,24 +4671,43 @@ TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) { // The first window loses focus. setFocusedWindow(mSecondWindow); - mFakePolicy->waitForSetPointerCapture(false); + mFakePolicy->assertSetPointerCaptureCalled(false); mWindow->consumeCaptureEvent(false); // Request Pointer Capture from the second window before the notification from InputReader // arrives. mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true); - mFakePolicy->waitForSetPointerCapture(true); + auto request = mFakePolicy->assertSetPointerCaptureCalled(true); // InputReader notifies Pointer Capture was disabled (because of the focus change). - notifyPointerCaptureChanged(false); + notifyPointerCaptureChanged({}); // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request). - notifyPointerCaptureChanged(true); + notifyPointerCaptureChanged(request); mSecondWindow->consumeFocusEvent(true); mSecondWindow->consumeCaptureEvent(true); } +TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) { + // App repeatedly enables and disables capture. + mDispatcher->requestPointerCapture(mWindow->getToken(), true); + auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true); + mDispatcher->requestPointerCapture(mWindow->getToken(), false); + mFakePolicy->assertSetPointerCaptureCalled(false); + mDispatcher->requestPointerCapture(mWindow->getToken(), true); + auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true); + + // InputReader notifies that PointerCapture has been enabled for the first request. Since the + // first request is now stale, this should do nothing. + notifyPointerCaptureChanged(firstRequest); + mWindow->assertNoEvents(); + + // InputReader notifies that the second request was enabled. + notifyPointerCaptureChanged(secondRequest); + mWindow->consumeCaptureEvent(true); +} + class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest { protected: constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8; diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index c76ed38adb..91d246a35f 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -312,8 +312,9 @@ public: transform = t; } - void setPointerCapture(bool enabled) { - mConfig.pointerCapture = enabled; + PointerCaptureRequest setPointerCapture(bool enabled) { + mConfig.pointerCaptureRequest = {enabled, mNextPointerCaptureSequenceNumber++}; + return mConfig.pointerCaptureRequest; } void setShowTouches(bool enabled) { @@ -327,6 +328,8 @@ public: float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; } private: + uint32_t mNextPointerCaptureSequenceNumber = 0; + DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation, bool isActive, const std::string& uniqueId, @@ -1993,24 +1996,24 @@ TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) { TEST_F(InputReaderTest, ChangingPointerCaptureNotifiesInputListener) { NotifyPointerCaptureChangedArgs args; - mFakePolicy->setPointerCapture(true); + auto request = mFakePolicy->setPointerCapture(true); mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); mReader->loopOnce(); mFakeListener->assertNotifyCaptureWasCalled(&args); - ASSERT_TRUE(args.enabled) << "Pointer Capture should be enabled."; + ASSERT_TRUE(args.request.enable) << "Pointer Capture should be enabled."; + ASSERT_EQ(args.request, request) << "Pointer Capture sequence number should match."; mFakePolicy->setPointerCapture(false); mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); mReader->loopOnce(); mFakeListener->assertNotifyCaptureWasCalled(&args); - ASSERT_FALSE(args.enabled) << "Pointer Capture should be disabled."; + ASSERT_FALSE(args.request.enable) << "Pointer Capture should be disabled."; - // Verify that the Pointer Capture state is re-configured correctly when the configuration value + // Verify that the Pointer Capture state is not updated when the configuration value // does not change. mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); mReader->loopOnce(); - mFakeListener->assertNotifyCaptureWasCalled(&args); - ASSERT_FALSE(args.enabled) << "Pointer Capture should be disabled."; + mFakeListener->assertNotifyCaptureWasNotCalled(); } class FakeVibratorInputMapper : public FakeInputMapper { diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp index fb7de97b49..6a26c636d9 100644 --- a/services/inputflinger/tests/TestInputListener.cpp +++ b/services/inputflinger/tests/TestInputListener.cpp @@ -100,6 +100,11 @@ void TestInputListener::assertNotifyCaptureWasCalled( "to have been called.")); } +void TestInputListener::assertNotifyCaptureWasNotCalled() { + ASSERT_NO_FATAL_FAILURE(assertNotCalled( + "notifyPointerCaptureChanged() should not be called.")); +} + template void TestInputListener::assertCalled(NotifyArgsType* outEventArgs, std::string message) { std::unique_lock lock(mLock); diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h index 0ffcaaa527..0a1dc4b0b9 100644 --- a/services/inputflinger/tests/TestInputListener.h +++ b/services/inputflinger/tests/TestInputListener.h @@ -55,6 +55,7 @@ public: void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = nullptr); void assertNotifyCaptureWasCalled(NotifyPointerCaptureChangedArgs* outEventArgs = nullptr); + void assertNotifyCaptureWasNotCalled(); void assertNotifySensorWasCalled(NotifySensorArgs* outEventArgs = nullptr); void assertNotifyVibratorStateWasCalled(NotifyVibratorStateArgs* outEventArgs = nullptr); -- cgit v1.2.3-59-g8ed1b From 7578845a3480cb4237f28729994e19a09caceb55 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Tue, 9 Feb 2021 18:51:25 -0800 Subject: FTL: Extend enum utilities imported from IF Generalize compile-time and run-time lookup of enumerator names by recognizing ftl_first and ftl_last to customize the range. Add enum_range() for iteration using range-based `for` loop. Bug: 185536303 Test: Check assembly for small LUT in .rodata, and unrolled loops. Test: ftl_test, libinput_tests, inputflinger_tests Test: m libinputflinger Change-Id: I0581611f4cfcf5837b0293867cb323742afb2c87 --- include/ftl/Flags.h | 99 ++----- include/ftl/NamedEnum.h | 129 --------- include/ftl/enum.h | 299 +++++++++++++++++++++ include/input/DisplayViewport.h | 10 +- include/input/InputDevice.h | 5 + include/input/InputTransport.h | 2 + libs/ftl/Android.bp | 4 +- libs/ftl/Flags_test.cpp | 20 +- libs/ftl/NamedEnum_test.cpp | 101 ------- libs/ftl/enum_test.cpp | 164 +++++++++++ libs/gui/include/gui/WindowInfo.h | 77 +++--- libs/input/InputDevice.cpp | 4 +- libs/input/InputTransport.cpp | 10 +- libs/input/KeyLayoutMap.cpp | 77 +++--- services/inputflinger/InputReaderBase.cpp | 6 +- services/inputflinger/dispatcher/Entry.h | 2 + services/inputflinger/dispatcher/FocusResolver.cpp | 12 +- services/inputflinger/dispatcher/FocusResolver.h | 4 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 34 +-- services/inputflinger/reader/EventHub.cpp | 3 +- .../reader/controller/PeripheralController.cpp | 10 +- services/inputflinger/reader/include/EventHub.h | 2 + .../reader/mapper/SensorInputMapper.cpp | 18 +- .../reader/mapper/TouchInputMapper.cpp | 11 +- .../inputflinger/reader/mapper/TouchInputMapper.h | 10 +- services/surfaceflinger/ClientCache.cpp | 21 +- .../CompositionEngine/src/planner/LayerState.cpp | 12 +- 27 files changed, 669 insertions(+), 477 deletions(-) delete mode 100644 include/ftl/NamedEnum.h create mode 100644 include/ftl/enum.h delete mode 100644 libs/ftl/NamedEnum_test.cpp create mode 100644 libs/ftl/enum_test.cpp (limited to 'services/inputflinger/InputReaderBase.cpp') diff --git a/include/ftl/Flags.h b/include/ftl/Flags.h index 27c84769cb..ae708313fd 100644 --- a/include/ftl/Flags.h +++ b/include/ftl/Flags.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * 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. @@ -14,79 +14,22 @@ * limitations under the License. */ -#include +#pragma once + +#include +#include -#include #include -#include +#include #include #include -#include #include "utils/BitSet.h" -#pragma once +// TODO(b/185536303): Align with FTL style and namespace. 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 { @@ -94,7 +37,7 @@ class Flags { // 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; + using U = std::underlying_type_t; public: constexpr Flags(F f) : mFlags(static_cast(f)) {} @@ -106,11 +49,10 @@ public: // 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) {} + constexpr Flags(T t, std::enable_if_t, T>* = nullptr) : mFlags(t) {} + template - explicit constexpr Flags(T t, - typename std::enable_if_t, T>* = nullptr) + explicit constexpr Flags(T t, std::enable_if_t, T>* = nullptr) : mFlags(t) {} class Iterator { @@ -229,16 +171,16 @@ public: bool first = true; U unstringified = 0; for (const F f : *this) { - std::optional flagString = flag_name(f); - if (flagString) { - appendFlag(result, flagString.value(), first); + if (const auto flagName = ftl::flag_name(f)) { + appendFlag(result, flagName.value(), first); } else { unstringified |= static_cast(f); } } if (unstringified != 0) { - appendFlag(result, base::StringPrintf("0x%08x", unstringified), first); + constexpr auto radix = sizeof(U) == 1 ? ftl::Radix::kBin : ftl::Radix::kHex; + appendFlag(result, ftl::to_string(unstringified, radix), first); } if (first) { @@ -265,15 +207,14 @@ private: // as flags. In order to use these, add them via a `using namespace` declaration. namespace flag_operators { -template >> +template >> inline Flags operator~(F f) { - using U = typename std::underlying_type_t; - return static_cast(~static_cast(f)); + return static_cast(~ftl::enum_cast(f)); } -template >> + +template >> Flags operator|(F lhs, F rhs) { - using U = typename std::underlying_type_t; - return static_cast(static_cast(lhs) | static_cast(rhs)); + return static_cast(ftl::enum_cast(lhs) | ftl::enum_cast(rhs)); } } // namespace flag_operators diff --git a/include/ftl/NamedEnum.h b/include/ftl/NamedEnum.h deleted file mode 100644 index 6e98feeb87..0000000000 --- a/include/ftl/NamedEnum.h +++ /dev/null @@ -1,129 +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 - -#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); - // Check invalid enum values with cast, like V = (android::test::TestEnums)8. - if (view.find('(') != std::string::npos) { - return std::nullopt; - } - 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/ftl/enum.h b/include/ftl/enum.h new file mode 100644 index 0000000000..dfe3a0976b --- /dev/null +++ b/include/ftl/enum.h @@ -0,0 +1,299 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +// Returns the name of enumerator E::V (i.e. "V") as std::optional by parsing the +// compiler-generated string literal for the signature of this function. The function is defined in +// the global namespace with a short name and inferred return type to reduce bloat in the read-only +// data segment. +template +constexpr auto ftl_enum() { + static_assert(std::is_enum_v); + + using R = std::optional; + using namespace std::literals; + + // The "pretty" signature has the following format: + // + // auto ftl_enum() [E = android::test::Enum, V = android::test::Enum::kValue] + // + std::string_view view = __PRETTY_FUNCTION__; + const auto template_begin = view.rfind('['); + const auto template_end = view.rfind(']'); + if (template_begin == view.npos || template_end == view.npos) return R{}; + + // Extract the template parameters without the enclosing brackets. Example (cont'd): + // + // E = android::test::Enum, V = android::test::Enum::kValue + // + view = view.substr(template_begin + 1, template_end - template_begin - 1); + const auto value_begin = view.rfind("V = "sv); + if (value_begin == view.npos) return R{}; + + // Example (cont'd): + // + // V = android::test::Enum::kValue + // + view = view.substr(value_begin); + const auto name_begin = view.rfind("::"sv); + if (name_begin == view.npos) return R{}; + + // Chop off the leading "::". + const auto name = view.substr(name_begin + 2); + + // A value that is not enumerated has the format "Enum)42". + return name.find(')') == view.npos ? R{name} : R{}; +} + +namespace android::ftl { + +// Trait for determining whether a type is specifically a scoped enum or not. By definition, a +// scoped enum is one that is not implicitly convertible to its underlying type. +// +// TODO: Replace with std::is_scoped_enum in C++23. +// +template > +struct is_scoped_enum : std::false_type {}; + +template +struct is_scoped_enum : std::negation>> { +}; + +template +inline constexpr bool is_scoped_enum_v = is_scoped_enum::value; + +// Shorthand for casting an enumerator to its integral value. +// +// enum class E { A, B, C }; +// static_assert(ftl::enum_cast(E::B) == 1); +// +template +constexpr auto enum_cast(E v) { + return static_cast>(v); +} + +// Traits for retrieving an enum's range. An enum specifies its range by defining enumerators named +// ftl_first and ftl_last. If omitted, ftl_first defaults to 0, whereas ftl_last defaults to N - 1 +// where N is the bit width of the underlying type, but only if that type is unsigned, assuming the +// enumerators are flags. Also, note that unscoped enums must define both bounds, as casting out-of- +// range values results in undefined behavior if the underlying type is not fixed. +// +// enum class E { A, B, C, F = 5, ftl_last = F }; +// +// static_assert(ftl::enum_begin_v == E::A); +// static_assert(ftl::enum_last_v == E::F); +// static_assert(ftl::enum_size_v == 6); +// +// enum class F : std::uint16_t { X = 0b1, Y = 0b10, Z = 0b100 }; +// +// static_assert(ftl::enum_begin_v == F{0}); +// static_assert(ftl::enum_last_v == F{15}); +// static_assert(ftl::enum_size_v == 16); +// +template +struct enum_begin { + static_assert(is_scoped_enum_v, "Missing ftl_first enumerator"); + static constexpr E value{0}; +}; + +template +struct enum_begin> { + static constexpr E value = E::ftl_first; +}; + +template +inline constexpr E enum_begin_v = enum_begin::value; + +template +struct enum_end { + using U = std::underlying_type_t; + static_assert(is_scoped_enum_v && std::is_unsigned_v, "Missing ftl_last enumerator"); + + static constexpr E value{std::numeric_limits::digits}; +}; + +template +struct enum_end> { + static constexpr E value = E{enum_cast(E::ftl_last) + 1}; +}; + +template +inline constexpr E enum_end_v = enum_end::value; + +template +inline constexpr E enum_last_v = E{enum_cast(enum_end_v) - 1}; + +template +struct enum_size { + static constexpr auto kBegin = enum_cast(enum_begin_v); + static constexpr auto kEnd = enum_cast(enum_end_v); + static_assert(kBegin < kEnd, "Invalid range"); + + static constexpr std::size_t value = kEnd - kBegin; + static_assert(value <= 64, "Excessive range size"); +}; + +template +inline constexpr std::size_t enum_size_v = enum_size::value; + +namespace details { + +template +struct Identity { + static constexpr auto value = V; +}; + +template +using make_enum_sequence = std::make_integer_sequence, enum_size_v>; + +template class = Identity, typename = make_enum_sequence> +struct EnumRange; + +template class F, typename T, T... Vs> +struct EnumRange> { + static constexpr auto kBegin = enum_cast(enum_begin_v); + static constexpr auto kSize = enum_size_v; + + using R = decltype(F::value); + const R values[kSize] = {F(Vs + kBegin)>::value...}; + + constexpr const auto* begin() const { return values; } + constexpr const auto* end() const { return values + kSize; } +}; + +template +struct EnumName { + static constexpr auto value = ftl_enum(); +}; + +template +struct FlagName { + using E = decltype(I); + using U = std::underlying_type_t; + + static constexpr E V{U{1} << enum_cast(I)}; + static constexpr auto value = ftl_enum(); +}; + +} // namespace details + +// Returns an iterable over the range of an enum. +// +// enum class E { A, B, C, F = 5, ftl_last = F }; +// +// std::string string; +// for (E v : ftl::enum_range()) { +// string += ftl::enum_name(v).value_or("?"); +// } +// +// assert(string == "ABC??F"); +// +template +constexpr auto enum_range() { + return details::EnumRange{}; +} + +// Returns a stringified enumerator at compile time. +// +// enum class E { A, B, C }; +// static_assert(ftl::enum_name() == "B"); +// +template +constexpr std::string_view enum_name() { + constexpr auto kName = ftl_enum(); + static_assert(kName, "Unknown enumerator"); + return *kName; +} + +// Returns a stringified enumerator, possibly at compile time. +// +// enum class E { A, B, C, F = 5, ftl_last = F }; +// +// static_assert(ftl::enum_name(E::C).value_or("?") == "C"); +// static_assert(ftl::enum_name(E{3}).value_or("?") == "?"); +// +template +constexpr std::optional enum_name(E v) { + const auto value = enum_cast(v); + + constexpr auto kBegin = enum_cast(enum_begin_v); + constexpr auto kLast = enum_cast(enum_last_v); + if (value < kBegin || value > kLast) return {}; + + constexpr auto kRange = details::EnumRange{}; + return kRange.values[value - kBegin]; +} + +// Returns a stringified flag enumerator, possibly at compile time. +// +// enum class F : std::uint16_t { X = 0b1, Y = 0b10, Z = 0b100 }; +// +// static_assert(ftl::flag_name(F::Z).value_or("?") == "Z"); +// static_assert(ftl::flag_name(F{0b111}).value_or("?") == "?"); +// +template +constexpr std::optional flag_name(E v) { + const auto value = enum_cast(v); + + // TODO: Replace with std::popcount and std::countr_zero in C++20. + if (__builtin_popcountl(value) != 1) return {}; + + constexpr auto kRange = details::EnumRange{}; + return kRange.values[__builtin_ctzl(value)]; +} + +// Returns a stringified enumerator, or its integral value if not named. +// +// enum class E { A, B, C, F = 5, ftl_last = F }; +// +// assert(ftl::enum_string(E::C) == "C"); +// assert(ftl::enum_string(E{3}) == "3"); +// +template +inline std::string enum_string(E v) { + if (const auto name = enum_name(v)) { + return std::string(*name); + } + return to_string(enum_cast(v)); +} + +// Returns a stringified flag enumerator, or its integral value if not named. +// +// enum class F : std::uint16_t { X = 0b1, Y = 0b10, Z = 0b100 }; +// +// assert(ftl::flag_string(F::Z) == "Z"); +// assert(ftl::flag_string(F{7}) == "0b111"); +// +template +inline std::string flag_string(E v) { + if (const auto name = flag_name(v)) { + return std::string(*name); + } + constexpr auto radix = sizeof(E) == 1 ? Radix::kBin : Radix::kHex; + return to_string(enum_cast(v), radix); +} + +} // namespace android::ftl diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h index a6213f3ddd..9148fee532 100644 --- a/include/input/DisplayViewport.h +++ b/include/input/DisplayViewport.h @@ -18,7 +18,8 @@ #define _LIBINPUT_DISPLAY_VIEWPORT_H #include -#include +#include +#include #include #include @@ -44,6 +45,8 @@ enum class ViewportType : int32_t { INTERNAL = 1, EXTERNAL = 2, VIRTUAL = 3, + + ftl_last = VIRTUAL }; /* @@ -132,9 +135,8 @@ struct DisplayViewport { "physicalFrame=[%d, %d, %d, %d], " "deviceSize=[%d, %d], " "isActive=[%d]", - NamedEnum::string(type).c_str(), displayId, uniqueId.c_str(), - physicalPort ? StringPrintf("%" PRIu8, *physicalPort).c_str() - : "", + ftl::enum_string(type).c_str(), displayId, uniqueId.c_str(), + physicalPort ? ftl::to_string(*physicalPort).c_str() : "", orientation, logicalLeft, logicalTop, logicalRight, logicalBottom, physicalLeft, physicalTop, physicalRight, physicalBottom, deviceWidth, deviceHeight, isActive); diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 7f0324a4a8..22aae196c6 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -84,6 +84,9 @@ enum class InputDeviceSensorType : int32_t { GAME_ROTATION_VECTOR = ASENSOR_TYPE_GAME_ROTATION_VECTOR, GYROSCOPE_UNCALIBRATED = ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED, SIGNIFICANT_MOTION = ASENSOR_TYPE_SIGNIFICANT_MOTION, + + ftl_first = ACCELEROMETER, + ftl_last = SIGNIFICANT_MOTION }; enum class InputDeviceSensorAccuracy : int32_t { @@ -105,6 +108,8 @@ enum class InputDeviceLightType : int32_t { PLAYER_ID = 1, RGB = 2, MULTI_COLOR = 3, + + ftl_last = MULTI_COLOR }; struct InputDeviceSensorInfo { diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 9a150eb0e2..7632b30bd2 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -73,6 +73,8 @@ struct InputMessage { DRAG, TIMELINE, TOUCH_MODE, + + ftl_last = TOUCH_MODE }; struct Header { diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp index 3026921044..5a80ad067c 100644 --- a/libs/ftl/Android.bp +++ b/libs/ftl/Android.bp @@ -14,10 +14,10 @@ cc_test { address: true, }, srcs: [ - "cast_test.cpp", "Flags_test.cpp", + "cast_test.cpp", + "enum_test.cpp", "future_test.cpp", - "NamedEnum_test.cpp", "small_map_test.cpp", "small_vector_test.cpp", "static_vector_test.cpp", diff --git a/libs/ftl/Flags_test.cpp b/libs/ftl/Flags_test.cpp index 8c00b5299b..d241fa272a 100644 --- a/libs/ftl/Flags_test.cpp +++ b/libs/ftl/Flags_test.cpp @@ -23,7 +23,7 @@ namespace android::test { using namespace android::flag_operators; -enum class TestFlags { ONE = 0x1, TWO = 0x2, THREE = 0x4 }; +enum class TestFlags : uint8_t { ONE = 0x1, TWO = 0x2, THREE = 0x4 }; TEST(Flags, Test) { Flags flags = TestFlags::ONE; @@ -165,7 +165,7 @@ TEST(Flags, String_KnownValues) { TEST(Flags, String_UnknownValues) { auto flags = Flags(0b1011); - ASSERT_EQ(flags.string(), "ONE | TWO | 0x00000008"); + ASSERT_EQ(flags.string(), "ONE | TWO | 0b1000"); } TEST(FlagsIterator, IteratesOverAllFlags) { @@ -210,18 +210,4 @@ TEST(FlagsIterator, PreFixIncrement) { 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 +} // namespace android::test diff --git a/libs/ftl/NamedEnum_test.cpp b/libs/ftl/NamedEnum_test.cpp deleted file mode 100644 index dff2b8aaa1..0000000000 --- a/libs/ftl/NamedEnum_test.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#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/ftl/enum_test.cpp b/libs/ftl/enum_test.cpp new file mode 100644 index 0000000000..1fd43abbc6 --- /dev/null +++ b/libs/ftl/enum_test.cpp @@ -0,0 +1,164 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace android::test { + +// Keep in sync with example usage in header file. +namespace { + +enum class E { A, B, C, F = 5, ftl_last = F }; + +static_assert(ftl::enum_begin_v == E::A); +static_assert(ftl::enum_last_v == E::F); +static_assert(ftl::enum_size_v == 6); + +static_assert(ftl::enum_name() == "B"); +static_assert(ftl::enum_name() == "F"); +static_assert(ftl::enum_name(E::C).value_or("?") == "C"); +static_assert(ftl::enum_name(E{3}).value_or("?") == "?"); + +enum class F : std::uint16_t { X = 0b1, Y = 0b10, Z = 0b100 }; + +static_assert(ftl::enum_begin_v == F{0}); +static_assert(ftl::enum_last_v == F{15}); +static_assert(ftl::enum_size_v == 16); + +static_assert(ftl::flag_name(F::Z).value_or("?") == "Z"); +static_assert(ftl::flag_name(F{0b111}).value_or("?") == "?"); + +// If a scoped enum is unsigned, its implicit range corresponds to its bit indices. +enum class Flags : std::uint8_t { + kNone = 0, + kFlag1 = 0b0000'0010, + kFlag4 = 0b0001'0000, + kFlag7 = 0b1000'0000, + kMask = kFlag1 | kFlag4 | kFlag7, + kAll = 0b1111'1111 +}; + +static_assert(ftl::enum_begin_v == Flags{0}); +static_assert(ftl::enum_last_v == Flags{7}); +static_assert(ftl::enum_size_v == 8); + +static_assert(ftl::enum_name() == "kNone"); +static_assert(ftl::enum_name() == "kFlag4"); +static_assert(ftl::enum_name() == "kFlag7"); + +// Though not flags, the enumerators are within the implicit range of bit indices. +enum class Planet : std::uint8_t { + kMercury, + kVenus, + kEarth, + kMars, + kJupiter, + kSaturn, + kUranus, + kNeptune +}; + +constexpr Planet kPluto{ftl::enum_cast(Planet::kNeptune) + 1}; // Honorable mention. + +static_assert(ftl::enum_begin_v == Planet::kMercury); +static_assert(ftl::enum_last_v == Planet::kNeptune); +static_assert(ftl::enum_size_v == 8); + +static_assert(ftl::enum_name() == "kMercury"); +static_assert(ftl::enum_name() == "kSaturn"); + +// Unscoped enum must define explicit range, even if the underlying type is fixed. +enum Temperature : int { + kRoom = 20, + kFridge = 4, + kFreezer = -18, + + ftl_first = kFreezer, + ftl_last = kRoom +}; + +static_assert(ftl::enum_begin_v == kFreezer); +static_assert(ftl::enum_last_v == kRoom); +static_assert(ftl::enum_size_v == 39); + +static_assert(ftl::enum_name() == "kFreezer"); +static_assert(ftl::enum_name() == "kFridge"); +static_assert(ftl::enum_name() == "kRoom"); + +} // namespace + +TEST(Enum, Range) { + std::string string; + for (E v : ftl::enum_range()) { + string += ftl::enum_name(v).value_or("?"); + } + EXPECT_EQ(string, "ABC??F"); +} + +TEST(Enum, Name) { + { + EXPECT_EQ(ftl::flag_name(Flags::kFlag1), "kFlag1"); + EXPECT_EQ(ftl::flag_name(Flags::kFlag7), "kFlag7"); + + EXPECT_EQ(ftl::flag_name(Flags::kNone), std::nullopt); + EXPECT_EQ(ftl::flag_name(Flags::kMask), std::nullopt); + EXPECT_EQ(ftl::flag_name(Flags::kAll), std::nullopt); + } + { + EXPECT_EQ(ftl::enum_name(Planet::kEarth), "kEarth"); + EXPECT_EQ(ftl::enum_name(Planet::kNeptune), "kNeptune"); + + EXPECT_EQ(ftl::enum_name(kPluto), std::nullopt); + } + { + EXPECT_EQ(ftl::enum_name(kRoom), "kRoom"); + EXPECT_EQ(ftl::enum_name(kFridge), "kFridge"); + EXPECT_EQ(ftl::enum_name(kFreezer), "kFreezer"); + + EXPECT_EQ(ftl::enum_name(static_cast(-30)), std::nullopt); + EXPECT_EQ(ftl::enum_name(static_cast(0)), std::nullopt); + EXPECT_EQ(ftl::enum_name(static_cast(100)), std::nullopt); + } +} + +TEST(Enum, String) { + { + EXPECT_EQ(ftl::flag_string(Flags::kFlag1), "kFlag1"); + EXPECT_EQ(ftl::flag_string(Flags::kFlag7), "kFlag7"); + + EXPECT_EQ(ftl::flag_string(Flags::kNone), "0b0"); + EXPECT_EQ(ftl::flag_string(Flags::kMask), "0b10010010"); + EXPECT_EQ(ftl::flag_string(Flags::kAll), "0b11111111"); + } + { + EXPECT_EQ(ftl::enum_string(Planet::kEarth), "kEarth"); + EXPECT_EQ(ftl::enum_string(Planet::kNeptune), "kNeptune"); + + EXPECT_EQ(ftl::enum_string(kPluto), "8"); + } + { + EXPECT_EQ(ftl::enum_string(kRoom), "kRoom"); + EXPECT_EQ(ftl::enum_string(kFridge), "kFridge"); + EXPECT_EQ(ftl::enum_string(kFreezer), "kFreezer"); + + EXPECT_EQ(ftl::enum_string(static_cast(-30)), "-30"); + EXPECT_EQ(ftl::enum_string(static_cast(0)), "0"); + EXPECT_EQ(ftl::enum_string(static_cast(100)), "100"); + } +} + +} // namespace android::test diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h index f090c63228..47f6c05bff 100644 --- a/libs/gui/include/gui/WindowInfo.h +++ b/libs/gui/include/gui/WindowInfo.h @@ -71,8 +71,9 @@ struct WindowInfo : public Parcelable { SLIPPERY = 0x20000000, LAYOUT_ATTACHED_IN_DECOR = 0x40000000, DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000, - }; // Window types from WindowManager.LayoutParams + }; + // Window types from WindowManager.LayoutParams enum class Type : int32_t { UNKNOWN = 0, FIRST_APPLICATION_WINDOW = 1, @@ -87,40 +88,50 @@ struct WindowInfo : public Parcelable { 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, + +#define 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, + + FIRST_SYSTEM_WINDOW = FIRST_SYSTEM_WINDOW_, LAST_SYSTEM_WINDOW = 2999, + +#undef FIRST_SYSTEM_WINDOW_ + + // Small range to limit LUT size. + ftl_first = FIRST_SYSTEM_WINDOW, + ftl_last = FIRST_SYSTEM_WINDOW + 15 }; - enum class Feature { + enum class Feature : uint32_t { DISABLE_TOUCH_PAD_GESTURES = 0x00000001, NO_INPUT_CHANNEL = 0x00000002, DISABLE_USER_ACTIVITY = 0x00000004, @@ -265,4 +276,4 @@ protected: WindowInfo mInfo; }; -} // namespace android::gui \ No newline at end of file +} // namespace android::gui diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 220c8e1e6e..69ae9a02ec 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -228,7 +228,7 @@ void InputDeviceInfo::addMotionRange(const MotionRange& range) { void InputDeviceInfo::addSensorInfo(const InputDeviceSensorInfo& info) { if (mSensors.find(info.type) != mSensors.end()) { ALOGW("Sensor type %s already exists, will be replaced by new sensor added.", - NamedEnum::string(info.type).c_str()); + ftl::enum_string(info.type).c_str()); } mSensors.insert_or_assign(info.type, info); } diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 1e93dfb488..91ab008161 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -30,10 +30,10 @@ static constexpr bool DEBUG_TRANSPORT_ACTIONS = false; #include #include #include +#include #include #include -#include #include using android::base::StringPrintf; @@ -714,7 +714,7 @@ android::base::Result InputPublisher::receiveC } ALOGE("channel '%s' publisher ~ Received unexpected %s message from consumer", - mChannel->getName().c_str(), NamedEnum::string(msg.header.type).c_str()); + mChannel->getName().c_str(), ftl::enum_string(msg.header.type).c_str()); return android::base::Error(UNKNOWN_ERROR); } @@ -856,7 +856,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consum case InputMessage::Type::TIMELINE: { LOG_ALWAYS_FATAL("Consumed a %s message, which should never be seen by " "InputConsumer!", - NamedEnum::string(mMsg.header.type).c_str()); + ftl::enum_string(mMsg.header.type).c_str()); break; } @@ -1449,14 +1449,14 @@ std::string InputConsumer::dump() const { out = out + "mChannel = " + mChannel->getName() + "\n"; out = out + "mMsgDeferred: " + toString(mMsgDeferred) + "\n"; if (mMsgDeferred) { - out = out + "mMsg : " + NamedEnum::string(mMsg.header.type) + "\n"; + out = out + "mMsg : " + ftl::enum_string(mMsg.header.type) + "\n"; } out += "Batches:\n"; for (const Batch& batch : mBatches) { out += " Batch:\n"; for (const InputMessage& msg : batch.samples) { out += android::base::StringPrintf(" Message %" PRIu32 ": %s ", msg.header.seq, - NamedEnum::string(msg.header.type).c_str()); + ftl::enum_string(msg.header.type).c_str()); switch (msg.header.type) { case InputMessage::Type::KEY: { out += android::base::StringPrintf("action=%s keycode=%" PRId32, diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index c365ab070e..7c25cda9ac 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -16,10 +16,8 @@ #define LOG_TAG "KeyLayoutMap" -#include - #include -#include +#include #include #include #include @@ -28,6 +26,10 @@ #include #include +#include +#include +#include + // Enables debug output for the parser. #define DEBUG_PARSER 0 @@ -39,37 +41,39 @@ namespace android { +namespace { -static const char* WHITESPACE = " \t\r"; - -#define SENSOR_ENTRY(type) NamedEnum::string(type), type -static const std::unordered_map SENSOR_LIST = - {{SENSOR_ENTRY(InputDeviceSensorType::ACCELEROMETER)}, - {SENSOR_ENTRY(InputDeviceSensorType::MAGNETIC_FIELD)}, - {SENSOR_ENTRY(InputDeviceSensorType::ORIENTATION)}, - {SENSOR_ENTRY(InputDeviceSensorType::GYROSCOPE)}, - {SENSOR_ENTRY(InputDeviceSensorType::LIGHT)}, - {SENSOR_ENTRY(InputDeviceSensorType::PRESSURE)}, - {SENSOR_ENTRY(InputDeviceSensorType::TEMPERATURE)}, - {SENSOR_ENTRY(InputDeviceSensorType::PROXIMITY)}, - {SENSOR_ENTRY(InputDeviceSensorType::GRAVITY)}, - {SENSOR_ENTRY(InputDeviceSensorType::LINEAR_ACCELERATION)}, - {SENSOR_ENTRY(InputDeviceSensorType::ROTATION_VECTOR)}, - {SENSOR_ENTRY(InputDeviceSensorType::RELATIVE_HUMIDITY)}, - {SENSOR_ENTRY(InputDeviceSensorType::AMBIENT_TEMPERATURE)}, - {SENSOR_ENTRY(InputDeviceSensorType::MAGNETIC_FIELD_UNCALIBRATED)}, - {SENSOR_ENTRY(InputDeviceSensorType::GAME_ROTATION_VECTOR)}, - {SENSOR_ENTRY(InputDeviceSensorType::GYROSCOPE_UNCALIBRATED)}, - {SENSOR_ENTRY(InputDeviceSensorType::SIGNIFICANT_MOTION)}}; - -// --- KeyLayoutMap --- - -KeyLayoutMap::KeyLayoutMap() { -} +constexpr const char* WHITESPACE = " \t\r"; -KeyLayoutMap::~KeyLayoutMap() { +template +constexpr auto sensorPair() { + return std::make_pair(ftl::enum_name(), S); } +static const std::unordered_map SENSOR_LIST = + {sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair(), + sensorPair()}; + +} // namespace + +KeyLayoutMap::KeyLayoutMap() = default; +KeyLayoutMap::~KeyLayoutMap() = default; + base::Result> KeyLayoutMap::loadContents(const std::string& filename, const char* contents) { Tokenizer* tokenizer; @@ -160,8 +164,8 @@ base::Result> KeyLayoutMap::mapSensor( const Sensor& sensor = it->second; #if DEBUG_MAPPING - ALOGD("mapSensor: absCode=%d, sensorType=0x%0x, sensorDataIndex=0x%x.", absCode, - NamedEnum::string(sensor.sensorType), sensor.sensorDataIndex); + ALOGD("mapSensor: absCode=%d, sensorType=%s, sensorDataIndex=0x%x.", absCode, + ftl::enum_string(sensor.sensorType).c_str(), sensor.sensorDataIndex); #endif return std::make_pair(sensor.sensorType, sensor.sensorDataIndex); } @@ -513,7 +517,7 @@ status_t KeyLayoutMap::Parser::parseLed() { } static std::optional getSensorType(const char* token) { - auto it = SENSOR_LIST.find(std::string(token)); + auto it = SENSOR_LIST.find(token); if (it == SENSOR_LIST.end()) { return std::nullopt; } @@ -581,8 +585,8 @@ status_t KeyLayoutMap::Parser::parseSensor() { int32_t sensorDataIndex = indexOpt.value(); #if DEBUG_PARSER - ALOGD("Parsed sensor: abs code=%d, sensorType=%d, sensorDataIndex=%d.", code, - NamedEnum::string(sensorType).c_str(), sensorDataIndex); + ALOGD("Parsed sensor: abs code=%d, sensorType=%s, sensorDataIndex=%d.", code, + ftl::enum_string(sensorType).c_str(), sensorDataIndex); #endif Sensor sensor; @@ -591,4 +595,5 @@ status_t KeyLayoutMap::Parser::parseSensor() { map.emplace(code, sensor); return NO_ERROR; } -}; + +} // namespace android diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp index 05ef489133..a864cf8202 100644 --- a/services/inputflinger/InputReaderBase.cpp +++ b/services/inputflinger/InputReaderBase.cpp @@ -19,12 +19,12 @@ //#define LOG_NDEBUG 0 #include "InputReaderBase.h" -#include #include "input/DisplayViewport.h" #include "input/Input.h" -#include #include +#include +#include #define INDENT " " #define INDENT2 " " @@ -117,7 +117,7 @@ std::optional InputReaderConfiguration::getDisplayViewportByTyp } if (count > 1) { ALOGW("Found %zu viewports with type %s, but expected 1 at most", count, - NamedEnum::string(type).c_str()); + ftl::enum_string(type).c_str()); } return result; } diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index 547021ca22..5365a78b0a 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -40,6 +40,8 @@ struct EventEntry { POINTER_CAPTURE_CHANGED, DRAG, TOUCH_MODE_CHANGED, + + ftl_last = TOUCH_MODE_CHANGED }; int32_t id; diff --git a/services/inputflinger/dispatcher/FocusResolver.cpp b/services/inputflinger/dispatcher/FocusResolver.cpp index 4a75773201..600f02ba80 100644 --- a/services/inputflinger/dispatcher/FocusResolver.cpp +++ b/services/inputflinger/dispatcher/FocusResolver.cpp @@ -27,7 +27,7 @@ static constexpr bool DEBUG_FOCUS = false; #include #include -#include +#include #include #include @@ -65,7 +65,7 @@ std::optional FocusResolver::setInputWindows( if (result == Focusability::OK) { return std::nullopt; } - removeFocusReason = NamedEnum::string(result); + removeFocusReason = ftl::enum_string(result); } // We don't have a focused window or the currently focused window is no longer focusable. Check @@ -79,7 +79,7 @@ std::optional FocusResolver::setInputWindows( if (result == Focusability::OK) { return updateFocusedWindow(displayId, "Window became focusable. Previous reason: " + - NamedEnum::string(previousResult), + ftl::enum_string(previousResult), requestedFocus, request->windowName); } } @@ -116,7 +116,7 @@ std::optional FocusResolver::setFocusedWindow( request.token, request.windowName); } ALOGW("setFocusedWindow %s on display %" PRId32 " ignored, reason: %s", - request.windowName.c_str(), displayId, NamedEnum::string(result).c_str()); + request.windowName.c_str(), displayId, ftl::enum_string(result).c_str()); return std::nullopt; } @@ -134,7 +134,7 @@ std::optional FocusResolver::setFocusedWindow( // The requested window is not currently focusable. Wait for the window to become focusable // but remove focus from the current window so that input events can go into a pending queue // and be sent to the window when it becomes focused. - return updateFocusedWindow(displayId, "Waiting for window because " + NamedEnum::string(result), + return updateFocusedWindow(displayId, "Waiting for window because " + ftl::enum_string(result), nullptr); } @@ -212,7 +212,7 @@ std::string FocusResolver::dump() const { for (const auto& [displayId, request] : mFocusRequestByDisplay) { auto it = mLastFocusResultByDisplay.find(displayId); std::string result = - it != mLastFocusResultByDisplay.end() ? NamedEnum::string(it->second) : ""; + it != mLastFocusResultByDisplay.end() ? ftl::enum_string(it->second) : ""; dump += base::StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s' result='%s'\n", displayId, request.windowName.c_str(), result.c_str()); } diff --git a/services/inputflinger/dispatcher/FocusResolver.h b/services/inputflinger/dispatcher/FocusResolver.h index 1d6cd9a5fa..6d11a77aad 100644 --- a/services/inputflinger/dispatcher/FocusResolver.h +++ b/services/inputflinger/dispatcher/FocusResolver.h @@ -77,6 +77,8 @@ private: NO_WINDOW, NOT_FOCUSABLE, NOT_VISIBLE, + + ftl_last = NOT_VISIBLE }; // Checks if the window token can be focused on a display. The token can be focused if there is @@ -113,4 +115,4 @@ private: std::optional getFocusRequest(int32_t displayId); }; -} // namespace android::inputdispatcher \ No newline at end of file +} // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 92ba52c3f4..9da71925ce 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1151,7 +1152,7 @@ void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason case EventEntry::Type::TOUCH_MODE_CHANGED: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { - LOG_ALWAYS_FATAL("Should not drop %s events", NamedEnum::string(entry.type).c_str()); + LOG_ALWAYS_FATAL("Should not drop %s events", ftl::enum_string(entry.type).c_str()); break; } } @@ -1573,7 +1574,7 @@ void InputDispatcher::dispatchSensorLocked(nsecs_t currentTime, ALOGD("notifySensorEvent eventTime=%" PRId64 ", hwTimestamp=%" PRId64 ", deviceId=%d, " "source=0x%x, sensorType=%s", entry->eventTime, entry->hwTimestamp, entry->deviceId, entry->source, - NamedEnum::string(entry->sensorType).c_str()); + ftl::enum_string(entry->sensorType).c_str()); } auto command = [this, entry]() REQUIRES(mLock) { scoped_unlock unlock(mLock); @@ -1590,7 +1591,7 @@ void InputDispatcher::dispatchSensorLocked(nsecs_t currentTime, bool InputDispatcher::flushSensor(int deviceId, InputDeviceSensorType sensorType) { if (DEBUG_OUTBOUND_EVENT_DETAILS) { ALOGD("flushSensor deviceId=%d, sensorType=%s", deviceId, - NamedEnum::string(sensorType).c_str()); + ftl::enum_string(sensorType).c_str()); } { // acquire lock std::scoped_lock _l(mLock); @@ -1811,7 +1812,7 @@ int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) { case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: case EventEntry::Type::DRAG: { - ALOGE("%s events do not have a target display", NamedEnum::string(entry.type).c_str()); + ALOGE("%s events do not have a target display", ftl::enum_string(entry.type).c_str()); return ADISPLAY_ID_NONE; } } @@ -1863,7 +1864,7 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked( if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) { ALOGI("Dropping %s event because there is no focused window or focused application in " "display %" PRId32 ".", - NamedEnum::string(entry.type).c_str(), displayId); + ftl::enum_string(entry.type).c_str(), displayId); return InputEventInjectionResult::FAILED; } @@ -1888,7 +1889,7 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked( } else if (currentTime > *mNoFocusedWindowTimeoutTime) { // Already raised ANR. Drop the event ALOGE("Dropping %s event because there is no focused window", - NamedEnum::string(entry.type).c_str()); + ftl::enum_string(entry.type).c_str()); return InputEventInjectionResult::FAILED; } else { // Still waiting for the focused window @@ -2676,8 +2677,7 @@ std::string InputDispatcher::dumpWindowForTouchOcclusion(const WindowInfo* info, "frame=[%" PRId32 ",%" PRId32 "][%" PRId32 ",%" PRId32 "], touchableRegion=%s, window={%s}, flags={%s}, inputFeatures={%s}, " "hasToken=%s, applicationInfo.name=%s, applicationInfo.token=%s\n", - (isTouchedWindow) ? "[TOUCHED] " : "", - NamedEnum::string(info->type, "%" PRId32).c_str(), + isTouchedWindow ? "[TOUCHED] " : "", ftl::enum_string(info->type).c_str(), info->packageName.c_str(), info->ownerUid, info->id, toString(info->touchOcclusionMode).c_str(), info->alpha, info->frameLeft, info->frameTop, info->frameRight, info->frameBottom, @@ -2804,7 +2804,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("%s events are not user activity", - NamedEnum::string(eventEntry.type).c_str()); + ftl::enum_string(eventEntry.type).c_str()); break; } } @@ -2849,7 +2849,7 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, if (inputTarget.flags & InputTarget::FLAG_SPLIT) { LOG_ALWAYS_FATAL_IF(eventEntry->type != EventEntry::Type::MOTION, "Entry type %s should not have FLAG_SPLIT", - NamedEnum::string(eventEntry->type).c_str()); + ftl::enum_string(eventEntry->type).c_str()); const MotionEntry& originalMotionEntry = static_cast(*eventEntry); if (inputTarget.pointerIds.count() != originalMotionEntry.pointerCount) { @@ -3037,7 +3037,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp& connectio case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events should not go to apps", - NamedEnum::string(newEntry.type).c_str()); + ftl::enum_string(newEntry.type).c_str()); break; } } @@ -3276,7 +3276,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: { LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events", - NamedEnum::string(eventEntry.type).c_str()); + ftl::enum_string(eventEntry.type).c_str()); return; } } @@ -3592,14 +3592,14 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("Canceling %s events is not supported", - NamedEnum::string(cancelationEventEntry->type).c_str()); + ftl::enum_string(cancelationEventEntry->type).c_str()); break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", - NamedEnum::string(cancelationEventEntry->type).c_str()); + ftl::enum_string(cancelationEventEntry->type).c_str()); break; } } @@ -3659,7 +3659,7 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( case EventEntry::Type::SENSOR: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", - NamedEnum::string(downEventEntry->type).c_str()); + ftl::enum_string(downEventEntry->type).c_str()); break; } } @@ -4007,7 +4007,7 @@ void InputDispatcher::notifySensor(const NotifySensorArgs* args) { ALOGD("notifySensor - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, " " sensorType=%s", args->id, args->eventTime, args->deviceId, args->source, - NamedEnum::string(args->sensorType).c_str()); + ftl::enum_string(args->sensorType).c_str()); } bool needWake; @@ -5115,7 +5115,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { toString(windowInfo->hasWallpaper), toString(windowInfo->visible), windowInfo->alpha, windowInfo->flags.string().c_str(), - NamedEnum::string(windowInfo->type).c_str(), + ftl::enum_string(windowInfo->type).c_str(), windowInfo->frameLeft, windowInfo->frameTop, windowInfo->frameRight, windowInfo->frameBottom, windowInfo->globalScaleFactor, diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 0f0ad0a102..d10f8b6605 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -263,7 +264,7 @@ static std::vector allFilesInPath(const std::filesystem:: */ static std::vector findSysfsNodes(const std::filesystem::path& sysfsRoot, SysfsClass clazz) { - std::string nodeStr = NamedEnum::string(clazz); + std::string nodeStr = ftl::enum_string(clazz); std::for_each(nodeStr.begin(), nodeStr.end(), [](char& c) { c = std::tolower(static_cast(c)); }); std::vector nodes; diff --git a/services/inputflinger/reader/controller/PeripheralController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp index 9c8a29a059..a6934960c9 100644 --- a/services/inputflinger/reader/controller/PeripheralController.cpp +++ b/services/inputflinger/reader/controller/PeripheralController.cpp @@ -17,9 +17,9 @@ #include #include -#include "../Macros.h" +#include -#include +#include "../Macros.h" #include "PeripheralController.h" // Log detailed debug messages about input device lights. @@ -286,7 +286,7 @@ void PeripheralController::dump(std::string& dump) { for (const auto& [lightId, light] : mLights) { dump += StringPrintf(INDENT4 "Id: %d", lightId); dump += StringPrintf(INDENT4 "Name: %s", light->name.c_str()); - dump += StringPrintf(INDENT4 "Type: %s", NamedEnum::string(light->type).c_str()); + dump += StringPrintf(INDENT4 "Type: %s", ftl::enum_string(light->type).c_str()); light->dump(dump); } } @@ -487,7 +487,7 @@ bool PeripheralController::setLightColor(int32_t lightId, int32_t color) { auto& light = it->second; if (DEBUG_LIGHT_DETAILS) { ALOGD("setLightColor lightId %d type %s color 0x%x", lightId, - NamedEnum::string(light->type).c_str(), color); + ftl::enum_string(light->type).c_str(), color); } return light->setLightColor(color); } @@ -501,7 +501,7 @@ std::optional PeripheralController::getLightColor(int32_t lightId) { std::optional color = light->getLightColor(); if (DEBUG_LIGHT_DETAILS) { ALOGD("getLightColor lightId %d type %s color 0x%x", lightId, - NamedEnum::string(light->type).c_str(), color.value_or(0)); + ftl::enum_string(light->type).c_str(), color.value_or(0)); } return color; } diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 7a00bace6e..1f96294e96 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -146,6 +146,8 @@ enum class InputDeviceClass : uint32_t { enum class SysfsClass : uint32_t { POWER_SUPPLY = 0, LEDS = 1, + + ftl_last = LEDS }; enum class LightColor : uint32_t { diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp index a507632d0e..a1bd548403 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp @@ -16,8 +16,9 @@ #include -#include "../Macros.h" +#include +#include "../Macros.h" #include "SensorInputMapper.h" // Log detailed debug messages about each sensor event notification to the dispatcher. @@ -93,7 +94,7 @@ void SensorInputMapper::dump(std::string& dump) { dump += StringPrintf(INDENT3 " mHasHardwareTimestamp %d\n", mHasHardwareTimestamp); dump += INDENT3 "Sensors:\n"; for (const auto& [sensorType, sensor] : mSensors) { - dump += StringPrintf(INDENT4 "%s\n", NamedEnum::string(sensorType).c_str()); + dump += StringPrintf(INDENT4 "%s\n", ftl::enum_string(sensorType).c_str()); dump += StringPrintf(INDENT5 "enabled: %d\n", sensor.enabled); dump += StringPrintf(INDENT5 "samplingPeriod: %lld\n", sensor.samplingPeriod.count()); dump += StringPrintf(INDENT5 "maxBatchReportLatency: %lld\n", @@ -208,10 +209,10 @@ SensorInputMapper::Sensor SensorInputMapper::createSensor(InputDeviceSensorType axis.max /* maxRange */, axis.scale /* resolution */, 0.0f /* power */, 0 /* minDelay */, 0 /* fifoReservedEventCount */, 0 /* fifoMaxEventCount */, - NamedEnum::string(sensorType), 0 /* maxDelay */, 0 /* flags */, + ftl::enum_string(sensorType), 0 /* maxDelay */, 0 /* flags */, getDeviceId()); - std::string prefix = "sensor." + NamedEnum::string(sensorType); + std::string prefix = "sensor." + ftl::enum_string(sensorType); transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower); int32_t reportingMode = 0; @@ -335,7 +336,7 @@ bool SensorInputMapper::enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds maxBatchReportLatency) { if (DEBUG_SENSOR_EVENT_DETAILS) { ALOGD("Enable Sensor %s samplingPeriod %lld maxBatchReportLatency %lld", - NamedEnum::string(sensorType).c_str(), samplingPeriod.count(), + ftl::enum_string(sensorType).c_str(), samplingPeriod.count(), maxBatchReportLatency.count()); } @@ -359,7 +360,7 @@ bool SensorInputMapper::enableSensor(InputDeviceSensorType sensorType, void SensorInputMapper::disableSensor(InputDeviceSensorType sensorType) { if (DEBUG_SENSOR_EVENT_DETAILS) { - ALOGD("Disable Sensor %s", NamedEnum::string(sensorType).c_str()); + ALOGD("Disable Sensor %s", ftl::enum_string(sensorType).c_str()); } if (!setSensorEnabled(sensorType, false /* enabled */)) { @@ -393,13 +394,12 @@ void SensorInputMapper::sync(nsecs_t when, bool force) { nsecs_t timestamp = mHasHardwareTimestamp ? mHardwareTimestamp : when; if (DEBUG_SENSOR_EVENT_DETAILS) { ALOGD("Sensor %s timestamp %" PRIu64 " values [%f %f %f]", - NamedEnum::string(sensorType).c_str(), timestamp, values[0], values[1], - values[2]); + ftl::enum_string(sensorType).c_str(), timestamp, values[0], values[1], values[2]); } if (sensor.lastSampleTimeNs.has_value() && timestamp - sensor.lastSampleTimeNs.value() < sensor.samplingPeriod.count()) { if (DEBUG_SENSOR_EVENT_DETAILS) { - ALOGD("Sensor %s Skip a sample.", NamedEnum::string(sensorType).c_str()); + ALOGD("Sensor %s Skip a sample.", ftl::enum_string(sensorType).c_str()); } } else { // Convert to Android unit diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index ac5f6b652b..419b0d0eed 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -18,9 +18,10 @@ #include "../Macros.h" // clang-format on -#include #include "TouchInputMapper.h" +#include + #include "CursorButtonAccumulator.h" #include "CursorScrollAccumulator.h" #include "TouchButtonAccumulator.h" @@ -259,7 +260,7 @@ void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { void TouchInputMapper::dump(std::string& dump) { dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n", - NamedEnum::string(mDeviceMode).c_str()); + ftl::enum_string(mDeviceMode).c_str()); dumpParameters(dump); dumpVirtualKeys(dump); dumpRawPointerAxes(dump); @@ -515,9 +516,9 @@ void TouchInputMapper::configureParameters() { void TouchInputMapper::dumpParameters(std::string& dump) { dump += INDENT3 "Parameters:\n"; - dump += INDENT4 "GestureMode: " + NamedEnum::string(mParameters.gestureMode) + "\n"; + dump += INDENT4 "GestureMode: " + ftl::enum_string(mParameters.gestureMode) + "\n"; - dump += INDENT4 "DeviceType: " + NamedEnum::string(mParameters.deviceType) + "\n"; + dump += INDENT4 "DeviceType: " + ftl::enum_string(mParameters.deviceType) + "\n"; dump += StringPrintf(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, " "displayId='%s'\n", @@ -525,7 +526,7 @@ void TouchInputMapper::dumpParameters(std::string& dump) { toString(mParameters.associatedDisplayIsExternal), mParameters.uniqueDisplayId.c_str()); dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware)); - dump += INDENT4 "Orientation: " + NamedEnum::string(mParameters.orientation) + "\n"; + dump += INDENT4 "Orientation: " + ftl::enum_string(mParameters.orientation) + "\n"; } void TouchInputMapper::configureRawPointerAxes() { diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index e104220e47..a56468f445 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -185,6 +185,8 @@ protected: UNSCALED, // unscaled mapping (touchpad) NAVIGATION, // unscaled mapping with assist gesture (touch navigation) POINTER, // pointer mapping (pointer) + + ftl_last = POINTER }; DeviceMode mDeviceMode; @@ -198,6 +200,8 @@ protected: TOUCH_PAD, TOUCH_NAVIGATION, POINTER, + + ftl_last = POINTER }; DeviceType deviceType; @@ -210,6 +214,8 @@ protected: ORIENTATION_90 = DISPLAY_ORIENTATION_90, ORIENTATION_180 = DISPLAY_ORIENTATION_180, ORIENTATION_270 = DISPLAY_ORIENTATION_270, + + ftl_last = ORIENTATION_270 }; Orientation orientation; @@ -219,6 +225,8 @@ protected: enum class GestureMode { SINGLE_TOUCH, MULTI_TOUCH, + + ftl_last = MULTI_TOUCH }; GestureMode gestureMode; @@ -818,4 +826,4 @@ private: } // namespace android -#endif // _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H \ No newline at end of file +#endif // _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp index f310738423..1ef8f78894 100644 --- a/services/surfaceflinger/ClientCache.cpp +++ b/services/surfaceflinger/ClientCache.cpp @@ -21,12 +21,12 @@ #include +#include + #include "ClientCache.h" namespace android { -using base::StringAppendF; - ANDROID_SINGLETON_STATIC_INSTANCE(ClientCache); ClientCache::ClientCache() : mDeathRecipient(new CacheDeathRecipient) {} @@ -212,16 +212,15 @@ void ClientCache::CacheDeathRecipient::binderDied(const wp& who) { void ClientCache::dump(std::string& result) { std::lock_guard lock(mMutex); - for (auto i : mBuffers) { - const sp& cacheOwner = i.second.first; - StringAppendF(&result," Cache owner: %p\n", cacheOwner.get()); - auto &buffers = i.second.second; - for (auto& [id, clientCacheBuffer] : buffers) { - StringAppendF(&result, "\t ID: %d, Width/Height: %d,%d\n", (int)id, - (int)clientCacheBuffer.buffer->getBuffer()->getWidth(), - (int)clientCacheBuffer.buffer->getBuffer()->getHeight()); + for (const auto& [_, cache] : mBuffers) { + base::StringAppendF(&result, " Cache owner: %p\n", cache.first.get()); + + for (const auto& [id, entry] : cache.second) { + const auto& buffer = entry.buffer->getBuffer(); + base::StringAppendF(&result, "\tID: %" PRIu64 ", size: %ux%u\n", id, buffer->getWidth(), + buffer->getHeight()); } } } -}; // namespace android +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp index 936dba3b29..2532e3df5d 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp @@ -93,11 +93,7 @@ Flags LayerState::getDifferingFields(const LayerState& other) c void LayerState::dump(std::string& result) const { for (const StateInterface* field : getNonUniqueFields()) { - if (auto viewOpt = flag_name(field->getField()); viewOpt) { - base::StringAppendF(&result, " %16s: ", std::string(*viewOpt).c_str()); - } else { - result.append(":\n"); - } + base::StringAppendF(&result, " %16s: ", ftl::flag_string(field->getField()).c_str()); bool first = true; for (const std::string& line : field->toStrings()) { @@ -126,11 +122,7 @@ std::optional LayerState::compare(const LayerState& other) const { continue; } - if (auto viewOpt = flag_name(thisField->getField()); viewOpt) { - base::StringAppendF(&result, " %16s: ", std::string(*viewOpt).c_str()); - } else { - result.append(":\n"); - } + base::StringAppendF(&result, " %16s: ", ftl::flag_string(thisField->getField()).c_str()); const auto& thisStrings = thisField->toStrings(); const auto& otherStrings = otherField->toStrings(); -- cgit v1.2.3-59-g8ed1b