diff options
179 files changed, 3931 insertions, 3078 deletions
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index cc8ac0ab2e..63f382170c 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -700,6 +700,11 @@ Status ServiceManager::registerClientCallback(const std::string& name, const sp< return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath."); } + // make sure all callbacks have been told about a consistent state - b/278038751 + if (serviceIt->second.hasClients) { + cb->onClients(service, true); + } + mNameToClientCallback[name].push_back(cb); return Status::ok(); diff --git a/include/android/input.h b/include/android/input.h index d6f9d633b6..a45f065dd0 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -256,13 +256,13 @@ enum { AKEY_EVENT_FLAG_LONG_PRESS = 0x80, /** - * Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long + * Set when a key event has #AKEY_EVENT_FLAG_CANCELED set because a long * press action was executed while it was down. */ AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100, /** - * Set for AKEY_EVENT_ACTION_UP when this event's key code is still being + * Set for #AKEY_EVENT_ACTION_UP when this event's key code is still being * tracked from its initial down. That is, somebody requested that tracking * started on the key down and a long press has not caused * the tracking to be canceled. @@ -282,7 +282,7 @@ enum { /** * Bit shift for the action bits holding the pointer index as - * defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK. + * defined by #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK. */ #define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8 @@ -293,8 +293,8 @@ enum { /** * Bits in the action code that represent a pointer index, used with - * AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting - * down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer + * #AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting + * down by #AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer * index where the data for the pointer going up or down can be found. */ AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00, @@ -309,8 +309,8 @@ enum { AMOTION_EVENT_ACTION_UP = 1, /** - * A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and - * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as + * A change has happened during a press gesture (between #AMOTION_EVENT_ACTION_DOWN and + * #AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as * any intermediate points since the last down or move event. */ AMOTION_EVENT_ACTION_MOVE = 2, @@ -330,18 +330,18 @@ enum { /** * A non-primary pointer has gone down. - * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed. + * The bits in #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed. */ AMOTION_EVENT_ACTION_POINTER_DOWN = 5, /** * A non-primary pointer has gone up. - * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed. + * The bits in #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed. */ AMOTION_EVENT_ACTION_POINTER_UP = 6, /** - * A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE). + * A change happened but the pointer is not down (unlike #AMOTION_EVENT_ACTION_MOVE). * The motion contains the most recent point, as well as any intermediate points since * the last hover move event. */ @@ -349,8 +349,8 @@ enum { /** * The motion event contains relative vertical and/or horizontal scroll offsets. - * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL - * and AMOTION_EVENT_AXIS_HSCROLL. + * Use {@link AMotionEvent_getAxisValue} to retrieve the information from + * #AMOTION_EVENT_AXIS_VSCROLL and #AMOTION_EVENT_AXIS_HSCROLL. * The pointer may or may not be down when this event is dispatched. * This action is always delivered to the winder under the pointer, which * may not be the window currently touched. @@ -535,7 +535,7 @@ enum { * is pointing in relation to the vertical axis of the current orientation of the screen. * The range is from -PI radians to PI radians, where 0 is pointing up, * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians - * is pointing right. See also {@link AMOTION_EVENT_AXIS_TILT}. + * is pointing right. See also #AMOTION_EVENT_AXIS_TILT. */ AMOTION_EVENT_AXIS_ORIENTATION = 8, /** @@ -688,7 +688,7 @@ enum { /** * Axis constant: The movement of y position of a motion event. * - * Same as {@link AMOTION_EVENT_AXIS_RELATIVE_X}, but for y position. + * Same as #AMOTION_EVENT_AXIS_RELATIVE_X, but for y position. */ AMOTION_EVENT_AXIS_RELATIVE_Y = 28, /** @@ -883,7 +883,8 @@ enum AMotionClassification : uint32_t { * Classification constant: Ambiguous gesture. * * The user's intent with respect to the current event stream is not yet determined. Events - * starting in AMBIGUOUS_GESTURE will eventually resolve into either DEEP_PRESS or NONE. + * starting in #AMOTION_EVENT_CLASSIFICATION_AMBIGUOUS_GESTURE will eventually resolve into + * either #AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS or #AMOTION_EVENT_CLASSIFICATION_NONE. * Gestural actions, such as scrolling, should be inhibited until the classification resolves * to another value or the event stream ends. */ @@ -1006,7 +1007,8 @@ enum { * Refer to the documentation on android.view.InputDevice for more details about input sources * and their correct interpretation. * - * @deprecated These constants are deprecated. Use {@link AMOTION_EVENT_AXIS AMOTION_EVENT_AXIS_*} constants instead. + * @deprecated These constants are deprecated. Use {@link AMOTION_EVENT_AXIS AMOTION_EVENT_AXIS_*} + * constants instead. */ enum { /** x */ @@ -1060,8 +1062,8 @@ int32_t AInputEvent_getSource(const AInputEvent* event); /** * Releases interface objects created by {@link AKeyEvent_fromJava()} * and {@link AMotionEvent_fromJava()}. - * After returning, the specified AInputEvent* object becomes invalid and should no longer be used. - * The underlying Java object remains valid and does not change its state. + * After returning, the specified {@link AInputEvent}* object becomes invalid and should no longer + * be used. The underlying Java object remains valid and does not change its state. * * Available since API level 31. */ @@ -1114,9 +1116,10 @@ int64_t AKeyEvent_getDownTime(const AInputEvent* key_event); int64_t AKeyEvent_getEventTime(const AInputEvent* key_event); /** - * Creates a native AInputEvent* object that is a copy of the specified Java android.view.KeyEvent. - * The result may be used with generic and KeyEvent-specific AInputEvent_* functions. The object - * returned by this function must be disposed using {@link AInputEvent_release()}. + * Creates a native {@link AInputEvent}* object that is a copy of the specified Java + * android.view.KeyEvent. The result may be used with generic and KeyEvent-specific AInputEvent_* + * functions. The object returned by this function must be disposed using + * {@link AInputEvent_release()}. * * Available since API level 31. */ @@ -1304,7 +1307,7 @@ float AMotionEvent_getAxisValue(const AInputEvent* motion_event, /** * Get the number of historical points in this event. These are movements that * have occurred between this event and the previous event. This only applies - * to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0. + * to #AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0. * Historical samples are indexed from oldest to newest. */ size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event); @@ -1465,7 +1468,7 @@ int32_t AMotionEvent_getClassification(const AInputEvent* motion_event) __INTRODUCED_IN(__ANDROID_API_T__); /** - * Creates a native AInputEvent* object that is a copy of the specified Java + * Creates a native {@link AInputEvent}* object that is a copy of the specified Java * android.view.MotionEvent. The result may be used with generic and MotionEvent-specific * AInputEvent_* functions. The object returned by this function must be disposed using * {@link AInputEvent_release()}. @@ -1485,7 +1488,7 @@ typedef struct AInputQueue AInputQueue; /** * Add this input queue to a looper for processing. See - * ALooper_addFd() for information on the ident, callback, and data params. + * {@link ALooper_addFd()} for information on the ident, callback, and data params. */ void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper, int ident, ALooper_callbackFunc callback, void* data); @@ -1520,12 +1523,12 @@ int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event); /** * Report that dispatching has finished with the given event. - * This must be called after receiving an event with AInputQueue_get_event(). + * This must be called after receiving an event with {@link AInputQueue_getEvent()}. */ void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled); /** - * Returns the AInputQueue* object associated with the supplied Java InputQueue + * Returns the {@link AInputQueue}* object associated with the supplied Java InputQueue * object. The returned native object holds a weak reference to the Java object, * and is only valid as long as the Java object has not yet been disposed. You * should ensure that there is a strong reference to the Java object and that it diff --git a/include/ftl/algorithm.h b/include/ftl/algorithm.h index c5ff03b80d..c0f67683ab 100644 --- a/include/ftl/algorithm.h +++ b/include/ftl/algorithm.h @@ -68,4 +68,29 @@ constexpr auto to_mapped_ref(const Pair& pair) -> std::reference_wrapper<const M return std::cref(pair.second); } +// Combinator for ftl::Optional<T>::or_else when T is std::reference_wrapper<const V>. Given a +// lambda argument that returns a `constexpr` value, ftl::static_ref<T> binds a reference to a +// static T initialized to that constant. +// +// const ftl::SmallMap map = ftl::init::map(13, "tiramisu"sv)(14, "upside-down cake"sv); +// assert("???"sv == +// map.get(20).or_else(ftl::static_ref<std::string_view>([] { return "???"sv; }))->get()); +// +// using Map = decltype(map); +// +// assert("snow cone"sv == +// ftl::find_if(map, [](const auto& pair) { return pair.second.front() == 's'; }) +// .transform(ftl::to_mapped_ref<Map>) +// .or_else(ftl::static_ref<std::string_view>([] { return "snow cone"sv; })) +// ->get()); +// +template <typename T, typename F> +constexpr auto static_ref(F&& f) { + return [f = std::forward<F>(f)] { + constexpr auto kInitializer = f(); + static const T kValue = kInitializer; + return Optional(std::cref(kValue)); + }; +} + } // namespace android::ftl diff --git a/include/ftl/flags.h b/include/ftl/flags.h index cdb4e840a4..dbe3148fc5 100644 --- a/include/ftl/flags.h +++ b/include/ftl/flags.h @@ -120,7 +120,7 @@ public: } /* Tests whether any of the given flags are set */ - bool any(Flags<F> f) const { return (mFlags & f.mFlags) != 0; } + bool any(Flags<F> f = ~Flags<F>()) const { return (mFlags & f.mFlags) != 0; } /* Tests whether all of the given flags are set */ bool all(Flags<F> f) const { return (mFlags & f.mFlags) == f.mFlags; } diff --git a/include/input/Input.h b/include/input/Input.h index a033535f4b..1e810b438a 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -210,7 +210,20 @@ vec2 transformWithoutTranslation(const ui::Transform& transform, const vec2& xy) */ float transformAngle(const ui::Transform& transform, float angleRadians); -const char* inputEventTypeToString(int32_t type); +/** + * The type of the InputEvent. + * This should have 1:1 correspondence with the values of anonymous enum defined in input.h. + */ +enum class InputEventType { + KEY = AINPUT_EVENT_TYPE_KEY, + MOTION = AINPUT_EVENT_TYPE_MOTION, + FOCUS = AINPUT_EVENT_TYPE_FOCUS, + CAPTURE = AINPUT_EVENT_TYPE_CAPTURE, + DRAG = AINPUT_EVENT_TYPE_DRAG, + TOUCH_MODE = AINPUT_EVENT_TYPE_TOUCH_MODE, + ftl_first = KEY, + ftl_last = TOUCH_MODE, +}; std::string inputEventSourceToString(int32_t source); @@ -482,7 +495,7 @@ class InputEvent : public AInputEvent { public: virtual ~InputEvent() { } - virtual int32_t getType() const = 0; + virtual InputEventType getType() const = 0; inline int32_t getId() const { return mId; } @@ -513,6 +526,8 @@ protected: std::array<uint8_t, 32> mHmac; }; +std::ostream& operator<<(std::ostream& out, const InputEvent& event); + /* * Key events. */ @@ -520,7 +535,7 @@ class KeyEvent : public InputEvent { public: virtual ~KeyEvent() { } - virtual int32_t getType() const { return AINPUT_EVENT_TYPE_KEY; } + virtual InputEventType getType() const { return InputEventType::KEY; } inline int32_t getAction() const { return mAction; } @@ -571,7 +586,7 @@ class MotionEvent : public InputEvent { public: virtual ~MotionEvent() { } - virtual int32_t getType() const { return AINPUT_EVENT_TYPE_MOTION; } + virtual InputEventType getType() const { return InputEventType::MOTION; } inline int32_t getAction() const { return mAction; } @@ -899,7 +914,7 @@ class FocusEvent : public InputEvent { public: virtual ~FocusEvent() {} - virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_FOCUS; } + virtual InputEventType getType() const override { return InputEventType::FOCUS; } inline bool getHasFocus() const { return mHasFocus; } @@ -918,7 +933,7 @@ class CaptureEvent : public InputEvent { public: virtual ~CaptureEvent() {} - virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_CAPTURE; } + virtual InputEventType getType() const override { return InputEventType::CAPTURE; } inline bool getPointerCaptureEnabled() const { return mPointerCaptureEnabled; } @@ -937,7 +952,7 @@ class DragEvent : public InputEvent { public: virtual ~DragEvent() {} - virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_DRAG; } + virtual InputEventType getType() const override { return InputEventType::DRAG; } inline bool isExiting() const { return mIsExiting; } @@ -961,7 +976,7 @@ class TouchModeEvent : public InputEvent { public: virtual ~TouchModeEvent() {} - virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_TOUCH_MODE; } + virtual InputEventType getType() const override { return InputEventType::TOUCH_MODE; } inline bool isInTouchMode() const { return mIsInTouchMode; } diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index c67310eaec..9423041b68 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -227,7 +227,7 @@ private: status_t parseMapKey(); status_t parseKey(); status_t parseKeyProperty(); - status_t finishKey(Key* key); + status_t finishKey(Key& key); status_t parseModifier(const std::string& token, int32_t* outMetaState); status_t parseCharacterLiteral(char16_t* outCharacter); }; @@ -243,7 +243,7 @@ private: KeyCharacterMap(const std::string& filename); - bool getKey(int32_t keyCode, const Key** outKey) const; + const Key* getKey(int32_t keyCode) const; const Behavior* getKeyBehavior(int32_t keyCode, int32_t metaState) const; static bool matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState); diff --git a/include/input/VirtualInputDevice.h b/include/input/VirtualInputDevice.h index 13ffb581b4..21a28770b6 100644 --- a/include/input/VirtualInputDevice.h +++ b/include/input/VirtualInputDevice.h @@ -34,10 +34,12 @@ public: protected: const android::base::unique_fd mFd; - bool writeInputEvent(uint16_t type, uint16_t code, int32_t value); + bool writeInputEvent(uint16_t type, uint16_t code, int32_t value, + std::chrono::nanoseconds eventTime); bool writeEvKeyEvent(int32_t androidCode, int32_t androidAction, const std::map<int, int>& evKeyCodeMapping, - const std::map<int, UinputAction>& actionMapping); + const std::map<int, UinputAction>& actionMapping, + std::chrono::nanoseconds eventTime); }; class VirtualKeyboard : public VirtualInputDevice { @@ -47,7 +49,8 @@ public: static const std::map<int, UinputAction> KEY_ACTION_MAPPING; VirtualKeyboard(android::base::unique_fd fd); virtual ~VirtualKeyboard() override; - bool writeKeyEvent(int32_t androidKeyCode, int32_t androidAction); + bool writeKeyEvent(int32_t androidKeyCode, int32_t androidAction, + std::chrono::nanoseconds eventTime); }; class VirtualDpad : public VirtualInputDevice { @@ -55,17 +58,20 @@ public: static const std::map<int, int> DPAD_KEY_CODE_MAPPING; VirtualDpad(android::base::unique_fd fd); virtual ~VirtualDpad() override; - bool writeDpadKeyEvent(int32_t androidKeyCode, int32_t androidAction); + bool writeDpadKeyEvent(int32_t androidKeyCode, int32_t androidAction, + std::chrono::nanoseconds eventTime); }; class VirtualMouse : public VirtualInputDevice { public: VirtualMouse(android::base::unique_fd fd); virtual ~VirtualMouse() override; - bool writeButtonEvent(int32_t androidButtonCode, int32_t androidAction); + bool writeButtonEvent(int32_t androidButtonCode, int32_t androidAction, + std::chrono::nanoseconds eventTime); // TODO(b/259554911): changing float parameters to int32_t. - bool writeRelativeEvent(float relativeX, float relativeY); - bool writeScrollEvent(float xAxisMovement, float yAxisMovement); + bool writeRelativeEvent(float relativeX, float relativeY, std::chrono::nanoseconds eventTime); + bool writeScrollEvent(float xAxisMovement, float yAxisMovement, + std::chrono::nanoseconds eventTime); private: static const std::map<int, UinputAction> BUTTON_ACTION_MAPPING; @@ -78,7 +84,8 @@ public: virtual ~VirtualTouchscreen() override; // TODO(b/259554911): changing float parameters to int32_t. bool writeTouchEvent(int32_t pointerId, int32_t toolType, int32_t action, float locationX, - float locationY, float pressure, float majorAxisSize); + float locationY, float pressure, float majorAxisSize, + std::chrono::nanoseconds eventTime); private: static const std::map<int, UinputAction> TOUCH_ACTION_MAPPING; @@ -91,7 +98,7 @@ private: */ std::bitset<MAX_POINTERS> mActivePointers{}; bool isValidPointerId(int32_t pointerId, UinputAction uinputAction); - bool handleTouchDown(int32_t pointerId); - bool handleTouchUp(int32_t pointerId); + bool handleTouchDown(int32_t pointerId, std::chrono::nanoseconds eventTime); + bool handleTouchUp(int32_t pointerId, std::chrono::nanoseconds eventTime); }; } // namespace android diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp index 0de804c3c2..69b11c0ee9 100644 --- a/libs/binder/IBatteryStats.cpp +++ b/libs/binder/IBatteryStats.cpp @@ -128,6 +128,15 @@ public: remote()->transact(NOTE_RESET_FLASHLIGHT_TRANSACTION, data, &reply); } + virtual binder::Status noteWakeupSensorEvent(int64_t elapsedNanos, int uid, int handle) { + Parcel data, reply; + data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor()); + data.writeInt64(elapsedNanos); + data.writeInt32(uid); + data.writeInt32(handle); + status_t ret = remote()->transact(NOTE_WAKEUP_SENSOR_EVENT_TRANSACTION, data, &reply); + return binder::Status::fromStatusT(ret); + } }; IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats") @@ -235,6 +244,16 @@ status_t BnBatteryStats::onTransact( reply->writeNoException(); return NO_ERROR; } break; + case NOTE_WAKEUP_SENSOR_EVENT_TRANSACTION: { + CHECK_INTERFACE(IBatteryStats, data, reply); + int64_t elapsedNanos = data.readInt64(); + int uid = data.readInt32(); + int handle = data.readInt32(); + noteWakeupSensorEvent(elapsedNanos, uid, handle); + reply->writeNoException(); + return NO_ERROR; + } break; + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp index ef58ed365f..1c7613584b 100644 --- a/libs/binder/RecordedTransaction.cpp +++ b/libs/binder/RecordedTransaction.cpp @@ -131,12 +131,12 @@ std::optional<RecordedTransaction> RecordedTransaction::fromDetails( return std::nullopt; } - if (t.mSent.setData(dataParcel.data(), dataParcel.dataSize()) != android::NO_ERROR) { + if (t.mSent.setData(dataParcel.data(), dataParcel.dataBufferSize()) != android::NO_ERROR) { LOG(ERROR) << "Failed to set sent parcel data."; return std::nullopt; } - if (t.mReply.setData(replyParcel.data(), replyParcel.dataSize()) != android::NO_ERROR) { + if (t.mReply.setData(replyParcel.data(), replyParcel.dataBufferSize()) != android::NO_ERROR) { LOG(ERROR) << "Failed to set reply parcel data."; return std::nullopt; } @@ -349,11 +349,11 @@ android::status_t RecordedTransaction::dumpToFile(const unique_fd& fd) const { return UNKNOWN_ERROR; } - if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataSize(), mSent.data())) { + if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataBufferSize(), mSent.data())) { LOG(ERROR) << "Failed to write sent Parcel to fd " << fd.get(); return UNKNOWN_ERROR; } - if (NO_ERROR != writeChunk(fd, REPLY_PARCEL_CHUNK, mReply.dataSize(), mReply.data())) { + if (NO_ERROR != writeChunk(fd, REPLY_PARCEL_CHUNK, mReply.dataBufferSize(), mReply.data())) { LOG(ERROR) << "Failed to write reply Parcel to fd " << fd.get(); return UNKNOWN_ERROR; } diff --git a/libs/binder/include_batterystats/batterystats/IBatteryStats.h b/libs/binder/include_batterystats/batterystats/IBatteryStats.h index 6defc7fb0b..5bb01dd86b 100644 --- a/libs/binder/include_batterystats/batterystats/IBatteryStats.h +++ b/libs/binder/include_batterystats/batterystats/IBatteryStats.h @@ -19,6 +19,7 @@ #ifndef __ANDROID_VNDK__ #include <binder/IInterface.h> +#include <binder/Status.h> namespace android { @@ -43,6 +44,7 @@ public: virtual void noteStopCamera(int uid) = 0; virtual void noteResetCamera() = 0; virtual void noteResetFlashlight() = 0; + virtual binder::Status noteWakeupSensorEvent(int64_t elapsedNanos, int uid, int sensor) = 0; enum { NOTE_START_SENSOR_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, @@ -58,7 +60,8 @@ public: NOTE_START_CAMERA_TRANSACTION, NOTE_STOP_CAMERA_TRANSACTION, NOTE_RESET_CAMERA_TRANSACTION, - NOTE_RESET_FLASHLIGHT_TRANSACTION + NOTE_RESET_FLASHLIGHT_TRANSACTION, + NOTE_WAKEUP_SENSOR_EVENT_TRANSACTION }; }; diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp index 1c875c0375..2d1175be75 100644 --- a/libs/binder/rust/tests/Android.bp +++ b/libs/binder/rust/tests/Android.bp @@ -23,9 +23,6 @@ rust_test { // this cannot be the same as the module name. stem: "rustBinderTestClientBinary", test_suites: ["general-tests"], - data: [ - ":rustBinderTestService", - ], } rust_test { @@ -39,6 +36,10 @@ rust_test { // this cannot be the same as the module name. stem: "rustBinderTestServiceBinary", test_harness: false, + // TODO(b/164473602): Remove this setting and add the module to `data` + // attribute of rustBinderTest. + auto_gen_config: false, + test_suites: ["general-tests"], } cc_test { @@ -99,7 +100,7 @@ cc_test { "libbase", ], static_libs: [ - "libbinder_rs_serialization_test", + "libbinder_rs_serialization_test" ], srcs: [ "serialization.cpp", @@ -115,10 +116,8 @@ rust_bindgen { source_stem: "bindings", cpp_std: "gnu++17", bindgen_flags: [ - "--allowlist-type", - "Transaction", - "--allowlist-var", - "TESTDATA_.*", + "--allowlist-type", "Transaction", + "--allowlist-var", "TESTDATA_.*", ], shared_libs: [ diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 504b3cea48..8d1300779a 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -1126,6 +1126,11 @@ static bool testSupportVsockLoopback() { android::base::unique_fd serverFd( TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); + + if (errno == EAFNOSUPPORT) { + return false; + } + LOG_ALWAYS_FATAL_IF(serverFd == -1, "Could not create socket: %s", strerror(errno)); sockaddr_vm serverAddr{ diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp index 3a99606ec9..68b000849c 100644 --- a/libs/binder/trusty/RpcServerTrusty.cpp +++ b/libs/binder/trusty/RpcServerTrusty.cpp @@ -65,6 +65,10 @@ RpcServerTrusty::RpcServerTrusty(std::unique_ptr<RpcTransportCtx> ctx, std::stri mTipcPort.msg_queue_len = 6; // Three each way mTipcPort.priv = this; + // TODO(b/266741352): follow-up to prevent needing this in the future + // Trusty needs to be set to the latest stable version that is in prebuilts there. + mRpcServer->setProtocolVersion(0); + if (mPortAcl) { // Initialize the array of pointers to uuids. // The pointers in mUuidPtrs should stay valid across moves of diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp index 5f145a149d..d4605ea13a 100644 --- a/libs/bufferqueueconverter/Android.bp +++ b/libs/bufferqueueconverter/Android.bp @@ -13,7 +13,7 @@ cc_library_headers { export_include_dirs: ["include"], } -cc_library_shared { +cc_library { name: "libbufferqueueconverter", vendor_available: true, vndk: { diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp index 97cb810404..5eb33087a2 100644 --- a/libs/dumputils/dump_utils.cpp +++ b/libs/dumputils/dump_utils.cpp @@ -62,7 +62,10 @@ static const char* hidl_hal_interfaces_to_dump[] { "android.hardware.audio@7.0::IDevicesFactory", "android.hardware.automotive.audiocontrol@1.0::IAudioControl", "android.hardware.automotive.audiocontrol@2.0::IAudioControl", + "android.hardware.automotive.can@1.0::ICanBus", + "android.hardware.automotive.can@1.0::ICanController", "android.hardware.automotive.evs@1.0::IEvsCamera", + "android.hardware.automotive.sv@1.0::ISurroundViewService", "android.hardware.automotive.vehicle@2.0::IVehicle", "android.hardware.biometrics.face@1.0::IBiometricsFace", "android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint", @@ -87,7 +90,12 @@ static const char* hidl_hal_interfaces_to_dump[] { /* list of hal interface to dump containing process during native dumps */ static const std::vector<std::string> aidl_interfaces_to_dump { "android.hardware.automotive.audiocontrol.IAudioControl", + "android.hardware.automotive.can.ICanController", "android.hardware.automotive.evs.IEvsEnumerator", + "android.hardware.automotive.ivn.IIvnAndroidDevice", + "android.hardware.automotive.occupant_awareness.IOccupantAwareness", + "android.hardware.automotive.remoteaccess.IRemoteAccess", + "android.hardware.automotive.vehicle.IVehicle", "android.hardware.biometrics.face.IBiometricsFace", "android.hardware.biometrics.fingerprint.IBiometricsFingerprint", "android.hardware.camera.provider.ICameraProvider", diff --git a/libs/ftl/algorithm_test.cpp b/libs/ftl/algorithm_test.cpp index 8052caf642..487b1b8759 100644 --- a/libs/ftl/algorithm_test.cpp +++ b/libs/ftl/algorithm_test.cpp @@ -47,4 +47,20 @@ TEST(Algorithm, FindIf) { EXPECT_EQ(opt->get(), ftl::StaticVector("tiramisu"sv)); } +TEST(Algorithm, StaticRef) { + using namespace std::string_view_literals; + + const ftl::SmallMap map = ftl::init::map(13, "tiramisu"sv)(14, "upside-down cake"sv); + ASSERT_EQ("???"sv, + map.get(20).or_else(ftl::static_ref<std::string_view>([] { return "???"sv; }))->get()); + + using Map = decltype(map); + + ASSERT_EQ("snow cone"sv, + ftl::find_if(map, [](const auto& pair) { return pair.second.front() == 's'; }) + .transform(ftl::to_mapped_ref<Map>) + .or_else(ftl::static_ref<std::string_view>([] { return "snow cone"sv; })) + ->get()); +} + } // namespace android::test diff --git a/libs/ftl/flags_test.cpp b/libs/ftl/flags_test.cpp index eea052ba33..1279d1147d 100644 --- a/libs/ftl/flags_test.cpp +++ b/libs/ftl/flags_test.cpp @@ -35,6 +35,7 @@ TEST(Flags, Test) { TEST(Flags, Any) { Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_TRUE(flags.any()); ASSERT_TRUE(flags.any(TestFlags::ONE)); ASSERT_TRUE(flags.any(TestFlags::TWO)); ASSERT_FALSE(flags.any(TestFlags::THREE)); @@ -42,6 +43,9 @@ TEST(Flags, Any) { ASSERT_TRUE(flags.any(TestFlags::TWO | TestFlags::THREE)); ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::THREE)); ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); + + Flags<TestFlags> emptyFlags; + ASSERT_FALSE(emptyFlags.any()); } TEST(Flags, All) { diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp index 46dd62d3bf..c480056b40 100644 --- a/libs/graphicsenv/GraphicsEnv.cpp +++ b/libs/graphicsenv/GraphicsEnv.cpp @@ -689,4 +689,13 @@ android_namespace_t* GraphicsEnv::getAngleNamespace() { return mAngleNamespace; } +void GraphicsEnv::nativeToggleAngleAsSystemDriver(bool enabled) { + const sp<IGpuService> gpuService = getGpuService(); + if (!gpuService) { + ALOGE("No GPU service"); + return; + } + gpuService->toggleAngleAsSystemDriver(enabled); +} + } // namespace android diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp index ceb52f71d8..4c070aec01 100644 --- a/libs/graphicsenv/IGpuService.cpp +++ b/libs/graphicsenv/IGpuService.cpp @@ -78,6 +78,15 @@ public: IBinder::FLAG_ONEWAY); } + void toggleAngleAsSystemDriver(bool enabled) override { + Parcel data, reply; + data.writeInterfaceToken(IGpuService::getInterfaceDescriptor()); + data.writeBool(enabled); + + remote()->transact(BnGpuService::TOGGLE_ANGLE_AS_SYSTEM_DRIVER, data, &reply, + IBinder::FLAG_ONEWAY); + } + std::string getUpdatableDriverPath() override { Parcel data, reply; data.writeInterfaceToken(IGpuService::getInterfaceDescriptor()); @@ -189,6 +198,15 @@ status_t BnGpuService::onTransact(uint32_t code, const Parcel& data, Parcel* rep return OK; } + case TOGGLE_ANGLE_AS_SYSTEM_DRIVER: { + CHECK_INTERFACE(IGpuService, data, reply); + + bool enableAngleAsSystemDriver; + if ((status = data.readBool(&enableAngleAsSystemDriver)) != OK) return status; + + toggleAngleAsSystemDriver(enableAngleAsSystemDriver); + return OK; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h index b58a6d90fe..1274c46b7b 100644 --- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h +++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h @@ -142,6 +142,8 @@ public: const std::string& getDebugLayers(); // Get the debug layers to load. const std::string& getDebugLayersGLES(); + // Set the persist.graphics.egl system property value. + void nativeToggleAngleAsSystemDriver(bool enabled); private: enum UseAngle { UNKNOWN, YES, NO }; diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h index b708b0fec0..e3857d2ec0 100644 --- a/libs/graphicsenv/include/graphicsenv/IGpuService.h +++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h @@ -50,6 +50,9 @@ public: // setter and getter for updatable driver path. virtual void setUpdatableDriverPath(const std::string& driverPath) = 0; virtual std::string getUpdatableDriverPath() = 0; + + // sets ANGLE as system GLES driver if enabled==true by setting persist.graphics.egl to true. + virtual void toggleAngleAsSystemDriver(bool enabled) = 0; }; class BnGpuService : public BnInterface<IGpuService> { @@ -59,6 +62,7 @@ public: SET_TARGET_STATS, SET_UPDATABLE_DRIVER_PATH, GET_UPDATABLE_DRIVER_PATH, + TOGGLE_ANGLE_AS_SYSTEM_DRIVER, // Always append new enum to the end. }; diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 21900a073a..0a63c1564e 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -66,6 +66,18 @@ filegroup { ], } +filegroup { + name: "android_gui_aidl", + srcs: [ + "android/gui/DisplayInfo.aidl", + "android/gui/FocusRequest.aidl", + "android/gui/InputApplicationInfo.aidl", + "android/gui/IWindowInfosListener.aidl", + "android/gui/IWindowInfosReportedListener.aidl", + "android/gui/WindowInfo.aidl", + ], +} + cc_library_static { name: "libgui_window_info_static", vendor_available: true, @@ -118,6 +130,9 @@ filegroup { name: "libgui_aidl", srcs: ["aidl/**/*.aidl"], path: "aidl/", + aidl: { + deps: [":android_gui_aidl"], + }, } filegroup { diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 821dd37a85..5c324b29cd 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -582,7 +582,8 @@ status_t BLASTBufferQueue::acquireNextBufferLocked( // Only update mSize for destination bounds if the incoming buffer matches the requested size. // Otherwise, it could cause stretching since the destination bounds will update before the // buffer with the new size is acquired. - if (mRequestedSize == getBufferSize(bufferItem)) { + if (mRequestedSize == getBufferSize(bufferItem) || + bufferItem.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { mSize = mRequestedSize; } Rect crop = computeCrop(bufferItem); @@ -800,34 +801,24 @@ void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) { mDequeueTimestamps.erase(bufferId); }; -void BLASTBufferQueue::syncNextTransaction( +bool BLASTBufferQueue::syncNextTransaction( std::function<void(SurfaceComposerClient::Transaction*)> callback, bool acquireSingleBuffer) { - std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr; - SurfaceComposerClient::Transaction* prevTransaction = nullptr; - - { - std::lock_guard _lock{mMutex}; - BBQ_TRACE(); - // We're about to overwrite the previous call so we should invoke that callback - // immediately. - if (mTransactionReadyCallback) { - prevCallback = mTransactionReadyCallback; - prevTransaction = mSyncTransaction; - } + LOG_ALWAYS_FATAL_IF(!callback, + "BLASTBufferQueue: callback passed in to syncNextTransaction must not be " + "NULL"); - mTransactionReadyCallback = callback; - if (callback) { - mSyncTransaction = new SurfaceComposerClient::Transaction(); - } else { - mSyncTransaction = nullptr; - } - mAcquireSingleBuffer = mTransactionReadyCallback ? acquireSingleBuffer : true; + std::lock_guard _lock{mMutex}; + BBQ_TRACE(); + if (mTransactionReadyCallback) { + ALOGW("Attempting to overwrite transaction callback in syncNextTransaction"); + return false; } - if (prevCallback) { - prevCallback(prevTransaction); - } + mTransactionReadyCallback = callback; + mSyncTransaction = new SurfaceComposerClient::Transaction(); + mAcquireSingleBuffer = acquireSingleBuffer; + return true; } void BLASTBufferQueue::stopContinuousSyncTransaction() { @@ -835,20 +826,35 @@ void BLASTBufferQueue::stopContinuousSyncTransaction() { SurfaceComposerClient::Transaction* prevTransaction = nullptr; { std::lock_guard _lock{mMutex}; - bool invokeCallback = mTransactionReadyCallback && !mAcquireSingleBuffer; - if (invokeCallback) { - prevCallback = mTransactionReadyCallback; - prevTransaction = mSyncTransaction; + if (mAcquireSingleBuffer || !mTransactionReadyCallback) { + ALOGW("Attempting to stop continuous sync when none are active"); + return; } + + prevCallback = mTransactionReadyCallback; + prevTransaction = mSyncTransaction; + mTransactionReadyCallback = nullptr; mSyncTransaction = nullptr; mAcquireSingleBuffer = true; } + if (prevCallback) { prevCallback(prevTransaction); } } +void BLASTBufferQueue::clearSyncTransaction() { + std::lock_guard _lock{mMutex}; + if (!mAcquireSingleBuffer) { + ALOGW("Attempting to clear sync transaction when none are active"); + return; + } + + mTransactionReadyCallback = nullptr; + mSyncTransaction = nullptr; +} + bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // Only reject buffers if scaling mode is freeze. diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index 69e9f8a4fb..a49a85984f 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -97,9 +97,10 @@ public: void releaseBufferCallbackLocked(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, std::optional<uint32_t> currentMaxAcquiredBufferCount, bool fakeRelease) REQUIRES(mMutex); - void syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback, + bool syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback, bool acquireSingleBuffer = true); void stopContinuousSyncTransaction(); + void clearSyncTransaction(); void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber); void applyPendingTransactions(uint64_t frameNumber); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index cf2593dc81..a3ad6807c5 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -32,6 +32,7 @@ #include <private/gui/ComposerService.h> #include <private/gui/ComposerServiceAIDL.h> #include <ui/DisplayMode.h> +#include <ui/DisplayState.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicTypes.h> #include <ui/Transform.h> @@ -116,15 +117,17 @@ public: mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); } - void syncNextTransaction(std::function<void(Transaction*)> callback, + bool syncNextTransaction(std::function<void(Transaction*)> callback, bool acquireSingleBuffer = true) { - mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); + return mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); } void stopContinuousSyncTransaction() { mBlastBufferQueueAdapter->stopContinuousSyncTransaction(); } + void clearSyncTransaction() { mBlastBufferQueueAdapter->clearSyncTransaction(); } + int getWidth() { return mBlastBufferQueueAdapter->mSize.width; } int getHeight() { return mBlastBufferQueueAdapter->mSize.height; } @@ -176,13 +179,13 @@ protected: BLASTBufferQueueTest() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name()); + ALOGD("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name()); } ~BLASTBufferQueueTest() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("End test: %s.%s", testInfo->test_case_name(), testInfo->name()); + ALOGD("End test: %s.%s", testInfo->test_case_name(), testInfo->name()); } void SetUp() { @@ -198,11 +201,13 @@ protected: t.apply(); t.clear(); - ui::DisplayMode mode; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &mode)); - const ui::Size& resolution = mode.resolution; + ui::DisplayState displayState; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(mDisplayToken, &displayState)); + const ui::Size& resolution = displayState.layerStackSpaceRect; mDisplayWidth = resolution.getWidth(); mDisplayHeight = resolution.getHeight(); + ALOGD("Display: %dx%d orientation:%d", mDisplayWidth, mDisplayHeight, + displayState.orientation); mSurfaceControl = mClient->createSurface(String8("TestSurface"), mDisplayWidth, mDisplayHeight, PIXEL_FORMAT_RGBA_8888, @@ -1108,7 +1113,11 @@ TEST_F(BLASTBufferQueueTest, SyncNextTransactionOverwrite) { ASSERT_NE(nullptr, adapter.getTransactionReadyCallback()); auto callback2 = [](Transaction*) {}; - adapter.syncNextTransaction(callback2); + ASSERT_FALSE(adapter.syncNextTransaction(callback2)); + + sp<IGraphicBufferProducer> igbProducer; + setUpProducer(adapter, igbProducer); + queueBuffer(igbProducer, 0, 255, 0, 0); std::unique_lock<std::mutex> lock(mutex); if (!receivedCallback) { @@ -1120,6 +1129,37 @@ TEST_F(BLASTBufferQueueTest, SyncNextTransactionOverwrite) { ASSERT_TRUE(receivedCallback); } +TEST_F(BLASTBufferQueueTest, ClearSyncTransaction) { + std::mutex mutex; + std::condition_variable callbackReceivedCv; + bool receivedCallback = false; + + BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); + ASSERT_EQ(nullptr, adapter.getTransactionReadyCallback()); + auto callback = [&](Transaction*) { + std::unique_lock<std::mutex> lock(mutex); + receivedCallback = true; + callbackReceivedCv.notify_one(); + }; + adapter.syncNextTransaction(callback); + ASSERT_NE(nullptr, adapter.getTransactionReadyCallback()); + + adapter.clearSyncTransaction(); + + sp<IGraphicBufferProducer> igbProducer; + setUpProducer(adapter, igbProducer); + queueBuffer(igbProducer, 0, 255, 0, 0); + + std::unique_lock<std::mutex> lock(mutex); + if (!receivedCallback) { + ASSERT_EQ(callbackReceivedCv.wait_for(lock, std::chrono::seconds(3)), + std::cv_status::timeout) + << "did not receive callback"; + } + + ASSERT_FALSE(receivedCallback); +} + TEST_F(BLASTBufferQueueTest, SyncNextTransactionDropBuffer) { uint8_t r = 255; uint8_t g = 0; diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp index fc6551c8e6..6880678050 100644 --- a/libs/gui/tests/BufferItemConsumer_test.cpp +++ b/libs/gui/tests/BufferItemConsumer_test.cpp @@ -68,7 +68,7 @@ class BufferItemConsumerTest : public ::testing::Test { void HandleBufferFreed() { std::lock_guard<std::mutex> lock(mMutex); mFreedBufferCount++; - ALOGV("HandleBufferFreed, mFreedBufferCount=%d", mFreedBufferCount); + ALOGD("HandleBufferFreed, mFreedBufferCount=%d", mFreedBufferCount); } void DequeueBuffer(int* outSlot) { @@ -80,7 +80,7 @@ class BufferItemConsumerTest : public ::testing::Test { nullptr, nullptr); ASSERT_GE(ret, 0); - ALOGV("dequeueBuffer: slot=%d", slot); + ALOGD("dequeueBuffer: slot=%d", slot); if (ret & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { ret = mProducer->requestBuffer(slot, &mBuffers[slot]); ASSERT_EQ(NO_ERROR, ret); @@ -89,7 +89,7 @@ class BufferItemConsumerTest : public ::testing::Test { } void QueueBuffer(int slot) { - ALOGV("enqueueBuffer: slot=%d", slot); + ALOGD("enqueueBuffer: slot=%d", slot); IGraphicBufferProducer::QueueBufferInput bufferInput( 0ULL, true, HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); @@ -104,12 +104,12 @@ class BufferItemConsumerTest : public ::testing::Test { status_t ret = mBIC->acquireBuffer(&buffer, 0, false); ASSERT_EQ(NO_ERROR, ret); - ALOGV("acquireBuffer: slot=%d", buffer.mSlot); + ALOGD("acquireBuffer: slot=%d", buffer.mSlot); *outSlot = buffer.mSlot; } void ReleaseBuffer(int slot) { - ALOGV("releaseBuffer: slot=%d", slot); + ALOGD("releaseBuffer: slot=%d", slot); BufferItem buffer; buffer.mSlot = slot; buffer.mGraphicBuffer = mBuffers[slot]; diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index d1208ee5ae..2f1fd3e78f 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -49,14 +49,14 @@ protected: BufferQueueTest() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("Begin test: %s.%s", testInfo->test_case_name(), + ALOGD("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name()); } ~BufferQueueTest() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("End test: %s.%s", testInfo->test_case_name(), + ALOGD("End test: %s.%s", testInfo->test_case_name(), testInfo->name()); } diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp index 00e32d9124..0a14afac55 100644 --- a/libs/gui/tests/CpuConsumer_test.cpp +++ b/libs/gui/tests/CpuConsumer_test.cpp @@ -62,7 +62,7 @@ protected: const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); CpuConsumerTestParams params = GetParam(); - ALOGV("** Starting test %s (%d x %d, %d, 0x%x)", + ALOGD("** Starting test %s (%d x %d, %d, 0x%x)", test_info->name(), params.width, params.height, params.maxLockedBuffers, params.format); @@ -582,7 +582,7 @@ TEST_P(CpuConsumerTest, FromCpuManyInQueue) { uint32_t stride[numInQueue]; for (int i = 0; i < numInQueue; i++) { - ALOGV("Producing frame %d", i); + ALOGD("Producing frame %d", i); ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time[i], &stride[i])); } @@ -590,7 +590,7 @@ TEST_P(CpuConsumerTest, FromCpuManyInQueue) { // Consume for (int i = 0; i < numInQueue; i++) { - ALOGV("Consuming frame %d", i); + ALOGD("Consuming frame %d", i); CpuConsumer::LockedBuffer b; err = mCC->lockNextBuffer(&b); ASSERT_NO_ERROR(err, "getNextBuffer error: "); @@ -624,7 +624,7 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) { uint32_t stride; for (int i = 0; i < params.maxLockedBuffers + 1; i++) { - ALOGV("Producing frame %d", i); + ALOGD("Producing frame %d", i); ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time, &stride)); } @@ -633,7 +633,7 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) { std::vector<CpuConsumer::LockedBuffer> b(params.maxLockedBuffers); for (int i = 0; i < params.maxLockedBuffers; i++) { - ALOGV("Locking frame %d", i); + ALOGD("Locking frame %d", i); err = mCC->lockNextBuffer(&b[i]); ASSERT_NO_ERROR(err, "getNextBuffer error: "); @@ -647,16 +647,16 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) { checkAnyBuffer(b[i], GetParam().format); } - ALOGV("Locking frame %d (too many)", params.maxLockedBuffers); + ALOGD("Locking frame %d (too many)", params.maxLockedBuffers); CpuConsumer::LockedBuffer bTooMuch; err = mCC->lockNextBuffer(&bTooMuch); ASSERT_TRUE(err == NOT_ENOUGH_DATA) << "Allowing too many locks"; - ALOGV("Unlocking frame 0"); + ALOGD("Unlocking frame 0"); err = mCC->unlockBuffer(b[0]); ASSERT_NO_ERROR(err, "Could not unlock buffer 0: "); - ALOGV("Locking frame %d (should work now)", params.maxLockedBuffers); + ALOGD("Locking frame %d (should work now)", params.maxLockedBuffers); err = mCC->lockNextBuffer(&bTooMuch); ASSERT_NO_ERROR(err, "Did not allow new lock after unlock"); @@ -669,11 +669,11 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) { checkAnyBuffer(bTooMuch, GetParam().format); - ALOGV("Unlocking extra buffer"); + ALOGD("Unlocking extra buffer"); err = mCC->unlockBuffer(bTooMuch); ASSERT_NO_ERROR(err, "Could not unlock extra buffer: "); - ALOGV("Locking frame %d (no more available)", params.maxLockedBuffers + 1); + ALOGD("Locking frame %d (no more available)", params.maxLockedBuffers + 1); err = mCC->lockNextBuffer(&b[0]); ASSERT_EQ(BAD_VALUE, err) << "Not out of buffers somehow"; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 9a9bd4ad31..4ec7a06cb8 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -164,7 +164,7 @@ public: void assertFocusChange(bool hasFocus) { InputEvent *ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, ev->getType()); + ASSERT_EQ(InputEventType::FOCUS, ev->getType()); FocusEvent *focusEvent = static_cast<FocusEvent *>(ev); EXPECT_EQ(hasFocus, focusEvent->getHasFocus()); } @@ -172,7 +172,7 @@ public: void expectTap(int x, int y) { InputEvent* ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); + ASSERT_EQ(InputEventType::MOTION, ev->getType()); MotionEvent* mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); EXPECT_EQ(x, mev->getX(0)); @@ -181,7 +181,7 @@ public: ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); + ASSERT_EQ(InputEventType::MOTION, ev->getType()); mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); @@ -190,7 +190,7 @@ public: void expectTapWithFlag(int x, int y, int32_t flags) { InputEvent *ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); + ASSERT_EQ(InputEventType::MOTION, ev->getType()); MotionEvent *mev = static_cast<MotionEvent *>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); EXPECT_EQ(x, mev->getX(0)); @@ -199,7 +199,7 @@ public: ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); + ASSERT_EQ(InputEventType::MOTION, ev->getType()); mev = static_cast<MotionEvent *>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); EXPECT_EQ(flags, mev->getFlags() & flags); @@ -208,7 +208,7 @@ public: void expectTapInDisplayCoordinates(int displayX, int displayY) { InputEvent *ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); + ASSERT_EQ(InputEventType::MOTION, ev->getType()); MotionEvent *mev = static_cast<MotionEvent *>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); const PointerCoords &coords = *mev->getRawPointerCoords(0 /*pointerIndex*/); @@ -218,7 +218,7 @@ public: ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); + ASSERT_EQ(InputEventType::MOTION, ev->getType()); mev = static_cast<MotionEvent *>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); @@ -227,7 +227,7 @@ public: void expectKey(uint32_t keycode) { InputEvent *ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType()); + ASSERT_EQ(InputEventType::KEY, ev->getType()); KeyEvent *keyEvent = static_cast<KeyEvent *>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, keyEvent->getAction()); EXPECT_EQ(keycode, keyEvent->getKeyCode()); @@ -235,7 +235,7 @@ public: ev = consumeEvent(); ASSERT_NE(ev, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType()); + ASSERT_EQ(InputEventType::KEY, ev->getType()); keyEvent = static_cast<KeyEvent *>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_UP, keyEvent->getAction()); EXPECT_EQ(keycode, keyEvent->getKeyCode()); diff --git a/libs/gui/tests/GLTest.cpp b/libs/gui/tests/GLTest.cpp index a1405fcb11..3ae4b6d052 100644 --- a/libs/gui/tests/GLTest.cpp +++ b/libs/gui/tests/GLTest.cpp @@ -31,7 +31,7 @@ static int abs(int value) { void GLTest::SetUp() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name()); + ALOGD("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name()); mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); ASSERT_EQ(EGL_SUCCESS, eglGetError()); @@ -135,7 +135,7 @@ void GLTest::TearDown() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("End test: %s.%s", testInfo->test_case_name(), testInfo->name()); + ALOGD("End test: %s.%s", testInfo->test_case_name(), testInfo->name()); } EGLint const* GLTest::getConfigAttribs() { diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp index 3427731fff..e6cb89cb83 100644 --- a/libs/gui/tests/IGraphicBufferProducer_test.cpp +++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp @@ -84,7 +84,7 @@ protected: virtual void SetUp() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("Begin test: %s.%s", testInfo->test_case_name(), + ALOGD("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name()); mMC = new MockConsumer; @@ -114,7 +114,7 @@ protected: virtual void TearDown() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("End test: %s.%s", testInfo->test_case_name(), + ALOGD("End test: %s.%s", testInfo->test_case_name(), testInfo->name()); } diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp index b65cddaea3..2f14924a15 100644 --- a/libs/gui/tests/StreamSplitter_test.cpp +++ b/libs/gui/tests/StreamSplitter_test.cpp @@ -36,14 +36,14 @@ protected: StreamSplitterTest() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("Begin test: %s.%s", testInfo->test_case_name(), + ALOGD("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name()); } ~StreamSplitterTest() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("End test: %s.%s", testInfo->test_case_name(), + ALOGD("End test: %s.%s", testInfo->test_case_name(), testInfo->name()); } }; diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index c7458a3755..82b66972d9 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -42,7 +42,7 @@ protected: virtual void SetUp() { const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("Begin test: %s.%s", testInfo->test_case_name(), + ALOGD("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name()); sp<IGraphicBufferProducer> producer; @@ -99,7 +99,7 @@ protected: const ::testing::TestInfo* const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGV("End test: %s.%s", testInfo->test_case_name(), + ALOGD("End test: %s.%s", testInfo->test_case_name(), testInfo->name()); } diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 4dbf575490..00925ba555 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -170,30 +170,6 @@ float transformAngle(const ui::Transform& transform, float angleRadians) { return atan2f(transformedPoint.x, -transformedPoint.y); } -const char* inputEventTypeToString(int32_t type) { - switch (type) { - case AINPUT_EVENT_TYPE_KEY: { - return "KEY"; - } - case AINPUT_EVENT_TYPE_MOTION: { - return "MOTION"; - } - case AINPUT_EVENT_TYPE_FOCUS: { - return "FOCUS"; - } - case AINPUT_EVENT_TYPE_CAPTURE: { - return "CAPTURE"; - } - case AINPUT_EVENT_TYPE_DRAG: { - return "DRAG"; - } - case AINPUT_EVENT_TYPE_TOUCH_MODE: { - return "TOUCH_MODE"; - } - } - return "UNKNOWN"; -} - std::string inputEventSourceToString(int32_t source) { if (source == AINPUT_SOURCE_UNKNOWN) { return "UNKNOWN"; @@ -287,6 +263,37 @@ int32_t InputEvent::nextId() { return idGen.nextId(); } +std::ostream& operator<<(std::ostream& out, const InputEvent& event) { + switch (event.getType()) { + case InputEventType::KEY: { + const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event); + out << keyEvent; + return out; + } + case InputEventType::MOTION: { + const MotionEvent& motionEvent = static_cast<const MotionEvent&>(event); + out << motionEvent; + return out; + } + case InputEventType::FOCUS: { + out << "FocusEvent"; + return out; + } + case InputEventType::CAPTURE: { + out << "CaptureEvent"; + return out; + } + case InputEventType::DRAG: { + out << "DragEvent"; + return out; + } + case InputEventType::TOUCH_MODE: { + out << "TouchModeEvent"; + return out; + } + } +} + // --- KeyEvent --- const char* KeyEvent::getLabel(int32_t keyCode) { @@ -1165,44 +1172,51 @@ TouchModeEvent* PooledInputEventFactory::createTouchModeEvent() { void PooledInputEventFactory::recycle(InputEvent* event) { switch (event->getType()) { - case AINPUT_EVENT_TYPE_KEY: - if (mKeyEventPool.size() < mMaxPoolSize) { - mKeyEventPool.push(std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event))); - return; + case InputEventType::KEY: { + if (mKeyEventPool.size() < mMaxPoolSize) { + mKeyEventPool.push(std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event))); + return; + } + break; } - break; - case AINPUT_EVENT_TYPE_MOTION: - if (mMotionEventPool.size() < mMaxPoolSize) { - mMotionEventPool.push(std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event))); - return; + case InputEventType::MOTION: { + if (mMotionEventPool.size() < mMaxPoolSize) { + mMotionEventPool.push( + std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event))); + return; + } + break; } - break; - case AINPUT_EVENT_TYPE_FOCUS: - if (mFocusEventPool.size() < mMaxPoolSize) { - mFocusEventPool.push(std::unique_ptr<FocusEvent>(static_cast<FocusEvent*>(event))); - return; + case InputEventType::FOCUS: { + if (mFocusEventPool.size() < mMaxPoolSize) { + mFocusEventPool.push(std::unique_ptr<FocusEvent>(static_cast<FocusEvent*>(event))); + return; + } + break; } - break; - case AINPUT_EVENT_TYPE_CAPTURE: - if (mCaptureEventPool.size() < mMaxPoolSize) { - mCaptureEventPool.push( - std::unique_ptr<CaptureEvent>(static_cast<CaptureEvent*>(event))); - return; + case InputEventType::CAPTURE: { + if (mCaptureEventPool.size() < mMaxPoolSize) { + mCaptureEventPool.push( + std::unique_ptr<CaptureEvent>(static_cast<CaptureEvent*>(event))); + return; + } + break; } - break; - case AINPUT_EVENT_TYPE_DRAG: - if (mDragEventPool.size() < mMaxPoolSize) { - mDragEventPool.push(std::unique_ptr<DragEvent>(static_cast<DragEvent*>(event))); - return; + case InputEventType::DRAG: { + if (mDragEventPool.size() < mMaxPoolSize) { + mDragEventPool.push(std::unique_ptr<DragEvent>(static_cast<DragEvent*>(event))); + return; + } + break; } - break; - case AINPUT_EVENT_TYPE_TOUCH_MODE: - if (mTouchModeEventPool.size() < mMaxPoolSize) { - mTouchModeEventPool.push( - std::unique_ptr<TouchModeEvent>(static_cast<TouchModeEvent*>(event))); - return; + case InputEventType::TOUCH_MODE: { + if (mTouchModeEventPool.size() < mMaxPoolSize) { + mTouchModeEventPool.push( + std::unique_ptr<TouchModeEvent>(static_cast<TouchModeEvent*>(event))); + return; + } + break; } - break; } delete event; } diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 737bd15901..f703901ed9 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -272,8 +272,8 @@ const std::string KeyCharacterMap::getLoadFileName() const { char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const { char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { + const Key* key = getKey(keyCode); + if (key != nullptr) { result = key->label; } #if DEBUG_MAPPING @@ -284,8 +284,8 @@ char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const { char16_t KeyCharacterMap::getNumber(int32_t keyCode) const { char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { + const Key* key = getKey(keyCode); + if (key != nullptr) { result = key->number; } #if DEBUG_MAPPING @@ -332,8 +332,8 @@ bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState, char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars, int32_t metaState) const { char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { + const Key* key = getKey(keyCode); + if (key != nullptr) { // Try to find the most general behavior that maps to this character. // For example, the base key behavior will usually be last in the list. // However, if we find a perfect meta state match for one behavior then use that one. @@ -493,19 +493,18 @@ std::pair<int32_t, int32_t> KeyCharacterMap::applyKeyBehavior(int32_t fromKeyCod return std::make_pair(toKeyCode, toMetaState); } -bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const { +const KeyCharacterMap::Key* KeyCharacterMap::getKey(int32_t keyCode) const { ssize_t index = mKeys.indexOfKey(keyCode); if (index >= 0) { - *outKey = mKeys.valueAt(index); - return true; + return mKeys.valueAt(index); } - return false; + return nullptr; } const KeyCharacterMap::Behavior* KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState) const { - const Key* key; - if (getKey(keyCode, &key)) { + const Key* key = getKey(keyCode); + if (key != nullptr) { for (const Behavior& behavior : key->behaviors) { if (matchesMetaState(metaState, behavior.metaState)) { return &behavior; @@ -1048,17 +1047,17 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() { String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER); if (token == "}") { mState = STATE_TOP; - return finishKey(key); + return finishKey(*key); } - Vector<Property> properties; + std::vector<Property> properties; // Parse all comma-delimited property names up to the first colon. for (;;) { if (token == "label") { - properties.add(Property(PROPERTY_LABEL)); + properties.emplace_back(PROPERTY_LABEL); } else if (token == "number") { - properties.add(Property(PROPERTY_NUMBER)); + properties.emplace_back(PROPERTY_NUMBER); } else { int32_t metaState; status_t status = parseModifier(token.string(), &metaState); @@ -1067,7 +1066,7 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() { mTokenizer->getLocation().string(), token.string()); return status; } - properties.add(Property(PROPERTY_META, metaState)); + properties.emplace_back(PROPERTY_META, metaState); } mTokenizer->skipDelimiters(WHITESPACE); @@ -1182,8 +1181,7 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() { } while (!mTokenizer->isEol() && mTokenizer->peekChar() != '#'); // Add the behavior. - for (size_t i = 0; i < properties.size(); i++) { - const Property& property = properties.itemAt(i); + for (const Property& property : properties) { switch (property.property) { case PROPERTY_LABEL: if (key->label) { @@ -1230,12 +1228,12 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() { return NO_ERROR; } -status_t KeyCharacterMap::Parser::finishKey(Key* key) { +status_t KeyCharacterMap::Parser::finishKey(Key& key) { // Fill in default number property. - if (!key->number) { + if (!key.number) { char16_t digit = 0; char16_t symbol = 0; - for (const Behavior& b : key->behaviors) { + for (const Behavior& b : key.behaviors) { char16_t ch = b.character; if (ch) { if (ch >= '0' && ch <= '9') { @@ -1247,7 +1245,7 @@ status_t KeyCharacterMap::Parser::finishKey(Key* key) { } } } - key->number = digit ? digit : symbol; + key.number = digit ? digit : symbol; } return NO_ERROR; } diff --git a/libs/input/VirtualInputDevice.cpp b/libs/input/VirtualInputDevice.cpp index 3c1f2b6b56..af9ce3a38f 100644 --- a/libs/input/VirtualInputDevice.cpp +++ b/libs/input/VirtualInputDevice.cpp @@ -44,15 +44,24 @@ VirtualInputDevice::~VirtualInputDevice() { ioctl(mFd, UI_DEV_DESTROY); } -bool VirtualInputDevice::writeInputEvent(uint16_t type, uint16_t code, int32_t value) { - struct input_event ev = {.type = type, .code = code, .value = value}; +bool VirtualInputDevice::writeInputEvent(uint16_t type, uint16_t code, int32_t value, + std::chrono::nanoseconds eventTime) { + std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(eventTime); + std::chrono::microseconds microseconds = + std::chrono::duration_cast<std::chrono::microseconds>(eventTime - seconds); + struct input_event ev = {.type = type, + .code = code, + .value = value, + .input_event_sec = static_cast<time_t>(seconds.count()), + .input_event_usec = static_cast<suseconds_t>(microseconds.count())}; return TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(struct input_event))) == sizeof(ev); } /** Utility method to write keyboard key events or mouse button events. */ bool VirtualInputDevice::writeEvKeyEvent(int32_t androidCode, int32_t androidAction, const std::map<int, int>& evKeyCodeMapping, - const std::map<int, UinputAction>& actionMapping) { + const std::map<int, UinputAction>& actionMapping, + std::chrono::nanoseconds eventTime) { auto evKeyCodeIterator = evKeyCodeMapping.find(androidCode); if (evKeyCodeIterator == evKeyCodeMapping.end()) { ALOGE("Unsupported native EV keycode for android code %d", androidCode); @@ -63,10 +72,10 @@ bool VirtualInputDevice::writeEvKeyEvent(int32_t androidCode, int32_t androidAct return false; } if (!writeInputEvent(EV_KEY, static_cast<uint16_t>(evKeyCodeIterator->second), - static_cast<int32_t>(actionIterator->second))) { + static_cast<int32_t>(actionIterator->second), eventTime)) { return false; } - if (!writeInputEvent(EV_SYN, SYN_REPORT, 0)) { + if (!writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime)) { return false; } return true; @@ -189,8 +198,10 @@ const std::map<int, int> VirtualKeyboard::KEY_CODE_MAPPING = { VirtualKeyboard::VirtualKeyboard(unique_fd fd) : VirtualInputDevice(std::move(fd)) {} VirtualKeyboard::~VirtualKeyboard() {} -bool VirtualKeyboard::writeKeyEvent(int32_t androidKeyCode, int32_t androidAction) { - return writeEvKeyEvent(androidKeyCode, androidAction, KEY_CODE_MAPPING, KEY_ACTION_MAPPING); +bool VirtualKeyboard::writeKeyEvent(int32_t androidKeyCode, int32_t androidAction, + std::chrono::nanoseconds eventTime) { + return writeEvKeyEvent(androidKeyCode, androidAction, KEY_CODE_MAPPING, KEY_ACTION_MAPPING, + eventTime); } // --- VirtualDpad --- @@ -210,9 +221,10 @@ VirtualDpad::VirtualDpad(unique_fd fd) : VirtualInputDevice(std::move(fd)) {} VirtualDpad::~VirtualDpad() {} -bool VirtualDpad::writeDpadKeyEvent(int32_t androidKeyCode, int32_t androidAction) { +bool VirtualDpad::writeDpadKeyEvent(int32_t androidKeyCode, int32_t androidAction, + std::chrono::nanoseconds eventTime) { return writeEvKeyEvent(androidKeyCode, androidAction, DPAD_KEY_CODE_MAPPING, - VirtualKeyboard::KEY_ACTION_MAPPING); + VirtualKeyboard::KEY_ACTION_MAPPING, eventTime); } // --- VirtualMouse --- @@ -236,20 +248,24 @@ VirtualMouse::VirtualMouse(unique_fd fd) : VirtualInputDevice(std::move(fd)) {} VirtualMouse::~VirtualMouse() {} -bool VirtualMouse::writeButtonEvent(int32_t androidButtonCode, int32_t androidAction) { +bool VirtualMouse::writeButtonEvent(int32_t androidButtonCode, int32_t androidAction, + std::chrono::nanoseconds eventTime) { return writeEvKeyEvent(androidButtonCode, androidAction, BUTTON_CODE_MAPPING, - BUTTON_ACTION_MAPPING); + BUTTON_ACTION_MAPPING, eventTime); } -bool VirtualMouse::writeRelativeEvent(float relativeX, float relativeY) { - return writeInputEvent(EV_REL, REL_X, relativeX) && writeInputEvent(EV_REL, REL_Y, relativeY) && - writeInputEvent(EV_SYN, SYN_REPORT, 0); +bool VirtualMouse::writeRelativeEvent(float relativeX, float relativeY, + std::chrono::nanoseconds eventTime) { + return writeInputEvent(EV_REL, REL_X, relativeX, eventTime) && + writeInputEvent(EV_REL, REL_Y, relativeY, eventTime) && + writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); } -bool VirtualMouse::writeScrollEvent(float xAxisMovement, float yAxisMovement) { - return writeInputEvent(EV_REL, REL_HWHEEL, xAxisMovement) && - writeInputEvent(EV_REL, REL_WHEEL, yAxisMovement) && - writeInputEvent(EV_SYN, SYN_REPORT, 0); +bool VirtualMouse::writeScrollEvent(float xAxisMovement, float yAxisMovement, + std::chrono::nanoseconds eventTime) { + return writeInputEvent(EV_REL, REL_HWHEEL, xAxisMovement, eventTime) && + writeInputEvent(EV_REL, REL_WHEEL, yAxisMovement, eventTime) && + writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); } // --- VirtualTouchscreen --- @@ -291,7 +307,7 @@ bool VirtualTouchscreen::isValidPointerId(int32_t pointerId, UinputAction uinput bool VirtualTouchscreen::writeTouchEvent(int32_t pointerId, int32_t toolType, int32_t action, float locationX, float locationY, float pressure, - float majorAxisSize) { + float majorAxisSize, std::chrono::nanoseconds eventTime) { auto actionIterator = TOUCH_ACTION_MAPPING.find(action); if (actionIterator == TOUCH_ACTION_MAPPING.end()) { return false; @@ -300,44 +316,44 @@ bool VirtualTouchscreen::writeTouchEvent(int32_t pointerId, int32_t toolType, in if (!isValidPointerId(pointerId, uinputAction)) { return false; } - if (!writeInputEvent(EV_ABS, ABS_MT_SLOT, pointerId)) { + if (!writeInputEvent(EV_ABS, ABS_MT_SLOT, pointerId, eventTime)) { return false; } auto toolTypeIterator = TOOL_TYPE_MAPPING.find(toolType); if (toolTypeIterator == TOOL_TYPE_MAPPING.end()) { return false; } - if (!writeInputEvent(EV_ABS, ABS_MT_TOOL_TYPE, - static_cast<int32_t>(toolTypeIterator->second))) { + if (!writeInputEvent(EV_ABS, ABS_MT_TOOL_TYPE, static_cast<int32_t>(toolTypeIterator->second), + eventTime)) { return false; } - if (uinputAction == UinputAction::PRESS && !handleTouchDown(pointerId)) { + if (uinputAction == UinputAction::PRESS && !handleTouchDown(pointerId, eventTime)) { return false; } - if (uinputAction == UinputAction::RELEASE && !handleTouchUp(pointerId)) { + if (uinputAction == UinputAction::RELEASE && !handleTouchUp(pointerId, eventTime)) { return false; } - if (!writeInputEvent(EV_ABS, ABS_MT_POSITION_X, locationX)) { + if (!writeInputEvent(EV_ABS, ABS_MT_POSITION_X, locationX, eventTime)) { return false; } - if (!writeInputEvent(EV_ABS, ABS_MT_POSITION_Y, locationY)) { + if (!writeInputEvent(EV_ABS, ABS_MT_POSITION_Y, locationY, eventTime)) { return false; } if (!isnan(pressure)) { - if (!writeInputEvent(EV_ABS, ABS_MT_PRESSURE, pressure)) { + if (!writeInputEvent(EV_ABS, ABS_MT_PRESSURE, pressure, eventTime)) { return false; } } if (!isnan(majorAxisSize)) { - if (!writeInputEvent(EV_ABS, ABS_MT_TOUCH_MAJOR, majorAxisSize)) { + if (!writeInputEvent(EV_ABS, ABS_MT_TOUCH_MAJOR, majorAxisSize, eventTime)) { return false; } } - return writeInputEvent(EV_SYN, SYN_REPORT, 0); + return writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); } -bool VirtualTouchscreen::handleTouchUp(int32_t pointerId) { - if (!writeInputEvent(EV_ABS, ABS_MT_TRACKING_ID, static_cast<int32_t>(-1))) { +bool VirtualTouchscreen::handleTouchUp(int32_t pointerId, std::chrono::nanoseconds eventTime) { + if (!writeInputEvent(EV_ABS, ABS_MT_TRACKING_ID, static_cast<int32_t>(-1), eventTime)) { return false; } // When a pointer is no longer in touch, remove the pointer id from the corresponding @@ -347,7 +363,8 @@ bool VirtualTouchscreen::handleTouchUp(int32_t pointerId) { // Only sends the BTN UP event when there's no pointers on the touchscreen. if (mActivePointers.none()) { - if (!writeInputEvent(EV_KEY, BTN_TOUCH, static_cast<int32_t>(UinputAction::RELEASE))) { + if (!writeInputEvent(EV_KEY, BTN_TOUCH, static_cast<int32_t>(UinputAction::RELEASE), + eventTime)) { return false; } ALOGD_IF(isDebug(), "No pointers on touchscreen %d, BTN UP event sent.", mFd.get()); @@ -355,12 +372,13 @@ bool VirtualTouchscreen::handleTouchUp(int32_t pointerId) { return true; } -bool VirtualTouchscreen::handleTouchDown(int32_t pointerId) { +bool VirtualTouchscreen::handleTouchDown(int32_t pointerId, std::chrono::nanoseconds eventTime) { // When a new pointer is down on the touchscreen, add the pointer id in the corresponding // entry in the unreleased touches map. if (mActivePointers.none()) { // Only sends the BTN Down event when the first pointer on the touchscreen is down. - if (!writeInputEvent(EV_KEY, BTN_TOUCH, static_cast<int32_t>(UinputAction::PRESS))) { + if (!writeInputEvent(EV_KEY, BTN_TOUCH, static_cast<int32_t>(UinputAction::PRESS), + eventTime)) { return false; } ALOGD_IF(isDebug(), "First pointer %d down under touchscreen %d, BTN DOWN event sent", @@ -369,7 +387,7 @@ bool VirtualTouchscreen::handleTouchDown(int32_t pointerId) { mActivePointers.set(pointerId); ALOGD_IF(isDebug(), "Added pointer %d under touchscreen %d in the map", pointerId, mFd.get()); - if (!writeInputEvent(EV_ABS, ABS_MT_TRACKING_ID, static_cast<int32_t>(pointerId))) { + if (!writeInputEvent(EV_ABS, ABS_MT_TRACKING_ID, static_cast<int32_t>(pointerId), eventTime)) { return false; } return true; diff --git a/libs/input/android/os/InputEventInjectionSync.aidl b/libs/input/android/os/InputEventInjectionSync.aidl index 95d24cb443..2d225fa452 100644 --- a/libs/input/android/os/InputEventInjectionSync.aidl +++ b/libs/input/android/os/InputEventInjectionSync.aidl @@ -33,4 +33,7 @@ enum InputEventInjectionSync { /* Waits for the input event to be completely processed. */ WAIT_FOR_FINISHED = 2, + + ftl_first = NONE, + ftl_last = WAIT_FOR_FINISHED, } diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index 59125dd428..a9655730fc 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -197,7 +197,7 @@ TEST_F(KeyEventTest, Properties) { ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME); ASSERT_EQ(id, event.getId()); - ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType()); + ASSERT_EQ(InputEventType::KEY, event.getType()); ASSERT_EQ(2, event.getDeviceId()); ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource()); ASSERT_EQ(DISPLAY_ID, event.getDisplayId()); @@ -346,7 +346,7 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { // Check properties. ASSERT_EQ(mId, event->getId()); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()); + ASSERT_EQ(InputEventType::MOTION, event->getType()); ASSERT_EQ(2, event->getDeviceId()); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource()); ASSERT_EQ(DISPLAY_ID, event->getDisplayId()); diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index 965fda73b4..3ecf8eed50 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -98,8 +98,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; - ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event->getType()) - << "consumer should have returned a key event"; + ASSERT_EQ(InputEventType::KEY, event->getType()) << "consumer should have returned a key event"; KeyEvent* keyEvent = static_cast<KeyEvent*>(event); EXPECT_EQ(seq, consumeSeq); @@ -207,7 +206,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()) + ASSERT_EQ(InputEventType::MOTION, event->getType()) << "consumer should have returned a motion event"; MotionEvent* motionEvent = static_cast<MotionEvent*>(event); @@ -298,7 +297,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeFocusEvent() { ASSERT_EQ(OK, status) << "consumer consume should return OK"; ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; - ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType()) + ASSERT_EQ(InputEventType::FOCUS, event->getType()) << "consumer should have returned a focus event"; FocusEvent* focusEvent = static_cast<FocusEvent*>(event); @@ -339,7 +338,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeCaptureEvent() { ASSERT_EQ(OK, status) << "consumer consume should return OK"; ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; - ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType()) + ASSERT_EQ(InputEventType::CAPTURE, event->getType()) << "consumer should have returned a capture event"; const CaptureEvent* captureEvent = static_cast<CaptureEvent*>(event); @@ -381,7 +380,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeDragEvent() { ASSERT_EQ(OK, status) << "consumer consume should return OK"; ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; - ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType()) + ASSERT_EQ(InputEventType::DRAG, event->getType()) << "consumer should have returned a drag event"; const DragEvent& dragEvent = static_cast<const DragEvent&>(*event); @@ -423,7 +422,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeTouchModeEvent() { ASSERT_EQ(OK, status) << "consumer consume should return OK"; ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; - ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType()) + ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType()) << "consumer should have returned a touch mode event"; const TouchModeEvent& touchModeEvent = static_cast<const TouchModeEvent&>(*event); diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp index 5c122d4154..932be56cde 100644 --- a/libs/renderengine/skia/AutoBackendTexture.cpp +++ b/libs/renderengine/skia/AutoBackendTexture.cpp @@ -82,6 +82,18 @@ void AutoBackendTexture::releaseImageProc(SkImage::ReleaseContext releaseContext textureRelease->unref(false); } +void logFatalTexture(const char* msg, const GrBackendTexture& tex, ui::Dataspace dataspace, + SkColorType colorType) { + GrGLTextureInfo textureInfo; + bool retrievedTextureInfo = tex.getGLTextureInfo(&textureInfo); + LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" + "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i texType: %i" + "\n\t\tGrGLTextureInfo: success: %i fTarget: %u fFormat: %u colorType %i", + msg, tex.isValid(), dataspace, tex.width(), tex.height(), tex.hasMipmaps(), + tex.isProtected(), static_cast<int>(tex.textureType()), retrievedTextureInfo, + textureInfo.fTarget, textureInfo.fFormat, colorType); +} + sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaType alphaType, GrDirectContext* context) { ATRACE_CALL(); @@ -107,9 +119,9 @@ sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaTyp mImage = image; mDataspace = dataspace; - LOG_ALWAYS_FATAL_IF(mImage == nullptr, - "Unable to generate SkImage. isTextureValid:%d dataspace:%d", - mBackendTexture.isValid(), dataspace); + if (!mImage) { + logFatalTexture("Unable to generate SkImage.", mBackendTexture, dataspace, colorType); + } return mImage; } @@ -131,9 +143,9 @@ sk_sp<SkSurface> AutoBackendTexture::getOrCreateSurface(ui::Dataspace dataspace, } mDataspace = dataspace; - LOG_ALWAYS_FATAL_IF(mSurface == nullptr, - "Unable to generate SkSurface. isTextureValid:%d dataspace:%d", - mBackendTexture.isValid(), dataspace); + if (!mSurface) { + logFatalTexture("Unable to generate SkSurface.", mBackendTexture, dataspace, mColorType); + } return mSurface; } diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp index 936e31679f..b99e3853ee 100644 --- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp @@ -52,6 +52,20 @@ struct VulkanFuncs { PFN_vkDestroyInstance vkDestroyInstance = nullptr; }; +// Ref-Count a semaphore +struct DestroySemaphoreInfo { + VkSemaphore mSemaphore; + // We need to make sure we don't delete the VkSemaphore until it is done being used by both Skia + // (including by the GPU) and inside SkiaVkRenderEngine. So we always start with two refs, one + // owned by Skia and one owned by the SkiaVkRenderEngine. The refs are decremented each time + // delete_semaphore* is called with this object. Skia will call destroy_semaphore* once it is + // done with the semaphore and the GPU has finished work on the semaphore. SkiaVkRenderEngine + // calls delete_semaphore* after sending the semaphore to Skia and exporting it if need be. + int mRefs = 2; + + DestroySemaphoreInfo(VkSemaphore semaphore) : mSemaphore(semaphore) {} +}; + struct VulkanInterface { bool initialized = false; VkInstance instance; @@ -588,14 +602,22 @@ bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) { return true; } -static void delete_semaphore(void* _semaphore) { - VkSemaphore semaphore = (VkSemaphore)_semaphore; - sVulkanInterface.destroySemaphore(semaphore); +static void delete_semaphore(void* semaphore) { + DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore); + --info->mRefs; + if (!info->mRefs) { + sVulkanInterface.destroySemaphore(info->mSemaphore); + delete info; + } } -static void delete_semaphore_protected(void* _semaphore) { - VkSemaphore semaphore = (VkSemaphore)_semaphore; - sProtectedContentVulkanInterface.destroySemaphore(semaphore); +static void delete_semaphore_protected(void* semaphore) { + DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore); + --info->mRefs; + if (!info->mRefs) { + sProtectedContentVulkanInterface.destroySemaphore(info->mSemaphore); + delete info; + } } static VulkanInterface& getVulkanInterface(bool protectedContext) { @@ -624,19 +646,30 @@ void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd } base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) { - VkSemaphore signalSemaphore = getVulkanInterface(isProtected()).createExportableSemaphore(); - GrBackendSemaphore beSignalSemaphore; - beSignalSemaphore.initVulkan(signalSemaphore); + VulkanInterface& vi = getVulkanInterface(isProtected()); + VkSemaphore semaphore = vi.createExportableSemaphore(); + + GrBackendSemaphore backendSemaphore; + backendSemaphore.initVulkan(semaphore); + GrFlushInfo flushInfo; - flushInfo.fNumSemaphores = 1; - flushInfo.fSignalSemaphores = &beSignalSemaphore; - flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore; - flushInfo.fFinishedContext = (void*)signalSemaphore; + DestroySemaphoreInfo* destroySemaphoreInfo = nullptr; + if (semaphore != VK_NULL_HANDLE) { + destroySemaphoreInfo = new DestroySemaphoreInfo(semaphore); + flushInfo.fNumSemaphores = 1; + flushInfo.fSignalSemaphores = &backendSemaphore; + flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore; + flushInfo.fFinishedContext = destroySemaphoreInfo; + } GrSemaphoresSubmitted submitted = grContext->flush(flushInfo); grContext->submit(false /* no cpu sync */); int drawFenceFd = -1; - if (GrSemaphoresSubmitted::kYes == submitted) { - drawFenceFd = getVulkanInterface(isProtected()).exportSemaphoreSyncFd(signalSemaphore); + if (semaphore != VK_NULL_HANDLE) { + if (GrSemaphoresSubmitted::kYes == submitted) { + drawFenceFd = vi.exportSemaphoreSyncFd(semaphore); + } + // Now that drawFenceFd has been created, we can delete our reference to this semaphore + flushInfo.fFinishedProc(destroySemaphoreInfo); } base::unique_fd res(drawFenceFd); return res; diff --git a/libs/jpegrecoverymap/Android.bp b/libs/ultrahdr/Android.bp index a1b0e19509..e3f709b7f5 100644 --- a/libs/jpegrecoverymap/Android.bp +++ b/libs/ultrahdr/Android.bp @@ -22,7 +22,7 @@ package { } cc_library { - name: "libjpegrecoverymap", + name: "libultrahdr", host_supported: true, vendor_available: true, export_include_dirs: ["include"], @@ -31,7 +31,7 @@ cc_library { srcs: [ "icc.cpp", "jpegr.cpp", - "recoverymapmath.cpp", + "gainmapmath.cpp", "jpegrutils.cpp", "multipictureformat.cpp", ], diff --git a/libs/jpegrecoverymap/OWNERS b/libs/ultrahdr/OWNERS index 6ace354d0b..6ace354d0b 100644 --- a/libs/jpegrecoverymap/OWNERS +++ b/libs/ultrahdr/OWNERS diff --git a/libs/jpegrecoverymap/recoverymapmath.cpp b/libs/ultrahdr/gainmapmath.cpp index 8808b55b0c..37c3cf3d3b 100644 --- a/libs/jpegrecoverymap/recoverymapmath.cpp +++ b/libs/ultrahdr/gainmapmath.cpp @@ -16,9 +16,9 @@ #include <cmath> #include <vector> -#include <jpegrecoverymap/recoverymapmath.h> +#include <ultrahdr/gainmapmath.h> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { static const std::vector<float> kPqOETF = [] { std::vector<float> result; @@ -396,59 +396,60 @@ Color bt2100ToP3(Color e) { // TODO: confirm we always want to convert like this before calculating // luminance. -ColorTransformFn getHdrConversionFn(jpegr_color_gamut sdr_gamut, jpegr_color_gamut hdr_gamut) { +ColorTransformFn getHdrConversionFn(ultrahdr_color_gamut sdr_gamut, + ultrahdr_color_gamut hdr_gamut) { switch (sdr_gamut) { - case JPEGR_COLORGAMUT_BT709: + case ULTRAHDR_COLORGAMUT_BT709: switch (hdr_gamut) { - case JPEGR_COLORGAMUT_BT709: + case ULTRAHDR_COLORGAMUT_BT709: return identityConversion; - case JPEGR_COLORGAMUT_P3: + case ULTRAHDR_COLORGAMUT_P3: return p3ToBt709; - case JPEGR_COLORGAMUT_BT2100: + case ULTRAHDR_COLORGAMUT_BT2100: return bt2100ToBt709; - case JPEGR_COLORGAMUT_UNSPECIFIED: + case ULTRAHDR_COLORGAMUT_UNSPECIFIED: return nullptr; } break; - case JPEGR_COLORGAMUT_P3: + case ULTRAHDR_COLORGAMUT_P3: switch (hdr_gamut) { - case JPEGR_COLORGAMUT_BT709: + case ULTRAHDR_COLORGAMUT_BT709: return bt709ToP3; - case JPEGR_COLORGAMUT_P3: + case ULTRAHDR_COLORGAMUT_P3: return identityConversion; - case JPEGR_COLORGAMUT_BT2100: + case ULTRAHDR_COLORGAMUT_BT2100: return bt2100ToP3; - case JPEGR_COLORGAMUT_UNSPECIFIED: + case ULTRAHDR_COLORGAMUT_UNSPECIFIED: return nullptr; } break; - case JPEGR_COLORGAMUT_BT2100: + case ULTRAHDR_COLORGAMUT_BT2100: switch (hdr_gamut) { - case JPEGR_COLORGAMUT_BT709: + case ULTRAHDR_COLORGAMUT_BT709: return bt709ToBt2100; - case JPEGR_COLORGAMUT_P3: + case ULTRAHDR_COLORGAMUT_P3: return p3ToBt2100; - case JPEGR_COLORGAMUT_BT2100: + case ULTRAHDR_COLORGAMUT_BT2100: return identityConversion; - case JPEGR_COLORGAMUT_UNSPECIFIED: + case ULTRAHDR_COLORGAMUT_UNSPECIFIED: return nullptr; } break; - case JPEGR_COLORGAMUT_UNSPECIFIED: + case ULTRAHDR_COLORGAMUT_UNSPECIFIED: return nullptr; } } //////////////////////////////////////////////////////////////////////////////// -// Recovery map calculations -uint8_t encodeRecovery(float y_sdr, float y_hdr, jr_metadata_ptr metadata) { - return encodeRecovery(y_sdr, y_hdr, metadata, - log2(metadata->minContentBoost), log2(metadata->maxContentBoost)); +// Gain map calculations +uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata) { + return encodeGain(y_sdr, y_hdr, metadata, + log2(metadata->minContentBoost), log2(metadata->maxContentBoost)); } -uint8_t encodeRecovery(float y_sdr, float y_hdr, jr_metadata_ptr metadata, - float log2MinContentBoost, float log2MaxContentBoost) { +uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata, + float log2MinContentBoost, float log2MaxContentBoost) { float gain = 1.0f; if (y_sdr > 0.0f) { gain = y_hdr / y_sdr; @@ -462,23 +463,23 @@ uint8_t encodeRecovery(float y_sdr, float y_hdr, jr_metadata_ptr metadata, * 255.0f); } -Color applyRecovery(Color e, float recovery, jr_metadata_ptr metadata) { - float logBoost = log2(metadata->minContentBoost) * (1.0f - recovery) - + log2(metadata->maxContentBoost) * recovery; - float recoveryFactor = exp2(logBoost); - return e * recoveryFactor; +Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata) { + float logBoost = log2(metadata->minContentBoost) * (1.0f - gain) + + log2(metadata->maxContentBoost) * gain; + float gainFactor = exp2(logBoost); + return e * gainFactor; } -Color applyRecovery(Color e, float recovery, jr_metadata_ptr metadata, float displayBoost) { - float logBoost = log2(metadata->minContentBoost) * (1.0f - recovery) - + log2(metadata->maxContentBoost) * recovery; - float recoveryFactor = exp2(logBoost * displayBoost / metadata->maxContentBoost); - return e * recoveryFactor; +Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata, float displayBoost) { + float logBoost = log2(metadata->minContentBoost) * (1.0f - gain) + + log2(metadata->maxContentBoost) * gain; + float gainFactor = exp2(logBoost * displayBoost / metadata->maxContentBoost); + return e * gainFactor; } -Color applyRecoveryLUT(Color e, float recovery, RecoveryLUT& recoveryLUT) { - float recoveryFactor = recoveryLUT.getRecoveryFactor(recovery); - return e * recoveryFactor; +Color applyGainLUT(Color e, float gain, GainLUT& gainLUT) { + float gainFactor = gainLUT.getGainFactor(gain); + return e * gainFactor; } Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { @@ -499,17 +500,28 @@ Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { } Color getP010Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { - size_t pixel_count = image->width * image->height; + size_t luma_stride = image->luma_stride; + size_t chroma_stride = image->chroma_stride; + uint16_t* luma_data = reinterpret_cast<uint16_t*>(image->data); + uint16_t* chroma_data = reinterpret_cast<uint16_t*>(image->chroma_data); - size_t pixel_y_idx = x + y * image->width; - size_t pixel_uv_idx = x / 2 + (y / 2) * (image->width / 2); + if (luma_stride == 0) { + luma_stride = image->width; + } + if (chroma_stride == 0) { + chroma_stride = luma_stride; + } + if (chroma_data == nullptr) { + chroma_data = &reinterpret_cast<uint16_t*>(image->data)[luma_stride * image->height]; + } + + size_t pixel_y_idx = y * luma_stride + x; + size_t pixel_u_idx = (y >> 1) * chroma_stride + (x & ~0x1); + size_t pixel_v_idx = pixel_u_idx + 1; - uint16_t y_uint = reinterpret_cast<uint16_t*>(image->data)[pixel_y_idx] - >> 6; - uint16_t u_uint = reinterpret_cast<uint16_t*>(image->data)[pixel_count + pixel_uv_idx * 2] - >> 6; - uint16_t v_uint = reinterpret_cast<uint16_t*>(image->data)[pixel_count + pixel_uv_idx * 2 + 1] - >> 6; + uint16_t y_uint = luma_data[pixel_y_idx] >> 6; + uint16_t u_uint = chroma_data[pixel_u_idx] >> 6; + uint16_t v_uint = chroma_data[pixel_v_idx] >> 6; // Conversions include taking narrow-range into account. return {{{ (static_cast<float>(y_uint) - 64.0f) / 876.0f, @@ -651,4 +663,4 @@ uint64_t colorToRgbaF16(Color e_gamma) { | (((uint64_t) floatToHalf(1.0f)) << 48); } -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr diff --git a/libs/jpegrecoverymap/icc.cpp b/libs/ultrahdr/icc.cpp index 5412cb1102..c807705528 100644 --- a/libs/jpegrecoverymap/icc.cpp +++ b/libs/ultrahdr/icc.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -#include <jpegrecoverymap/icc.h> -#include <jpegrecoverymap/recoverymapmath.h> +#include <ultrahdr/icc.h> +#include <ultrahdr/gainmapmath.h> #include <vector> #include <utils/Log.h> @@ -23,7 +23,7 @@ #define FLT_MAX 0x1.fffffep127f #endif -namespace android::jpegrecoverymap { +namespace android::ultrahdr { static void Matrix3x3_apply(const Matrix3x3* m, float* x) { float y0 = x[0] * m->vals[0][0] + x[1] * m->vals[0][1] + x[2] * m->vals[0][2]; float y1 = x[0] * m->vals[1][0] + x[1] * m->vals[1][1] + x[2] * m->vals[1][2]; @@ -127,17 +127,17 @@ static void float_XYZD50_to_grid16_lab(const float* xyz_float, uint8_t* grid16_l } } -std::string IccHelper::get_desc_string(const jpegr_transfer_function tf, - const jpegr_color_gamut gamut) { +std::string IccHelper::get_desc_string(const ultrahdr_transfer_function tf, + const ultrahdr_color_gamut gamut) { std::string result; switch (gamut) { - case JPEGR_COLORGAMUT_BT709: + case ULTRAHDR_COLORGAMUT_BT709: result += "sRGB"; break; - case JPEGR_COLORGAMUT_P3: + case ULTRAHDR_COLORGAMUT_P3: result += "Display P3"; break; - case JPEGR_COLORGAMUT_BT2100: + case ULTRAHDR_COLORGAMUT_BT2100: result += "Rec2020"; break; default: @@ -146,16 +146,16 @@ std::string IccHelper::get_desc_string(const jpegr_transfer_function tf, } result += " Gamut with "; switch (tf) { - case JPEGR_TF_SRGB: + case ULTRAHDR_TF_SRGB: result += "sRGB"; break; - case JPEGR_TF_LINEAR: + case ULTRAHDR_TF_LINEAR: result += "Linear"; break; - case JPEGR_TF_PQ: + case ULTRAHDR_TF_PQ: result += "PQ"; break; - case JPEGR_TF_HLG: + case ULTRAHDR_TF_HLG: result += "HLG"; break; default: @@ -234,11 +234,11 @@ sp<DataStruct> IccHelper::write_trc_tag_for_linear() { return dataStruct; } -float IccHelper::compute_tone_map_gain(const jpegr_transfer_function tf, float L) { +float IccHelper::compute_tone_map_gain(const ultrahdr_transfer_function tf, float L) { if (L <= 0.f) { return 1.f; } - if (tf == JPEGR_TF_PQ) { + if (tf == ULTRAHDR_TF_PQ) { // The PQ transfer function will map to the range [0, 1]. Linearly scale // it up to the range [0, 10,000/203]. We will then tone map that back // down to [0, 1]. @@ -251,7 +251,7 @@ float IccHelper::compute_tone_map_gain(const jpegr_transfer_function tf, float L constexpr float kToneMapB = 1.f / kOutputMaxLuminance; return kInputMaxLuminance * (1.f + kToneMapA * L) / (1.f + kToneMapB * L); } - if (tf == JPEGR_TF_HLG) { + if (tf == ULTRAHDR_TF_HLG) { // Let Lw be the brightness of the display in nits. constexpr float Lw = 203.f; const float gamma = 1.2f + 0.42f * std::log(Lw / 1000.f) / std::log(10.f); @@ -295,7 +295,7 @@ void IccHelper::compute_lut_entry(const Matrix3x3& src_to_XYZD50, float rgb[3]) float L = bt2100Luminance({{{rgb[0], rgb[1], rgb[2]}}}); // Compute the tone map gain based on the luminance. - float tone_map_gain = compute_tone_map_gain(JPEGR_TF_PQ, L); + float tone_map_gain = compute_tone_map_gain(ULTRAHDR_TF_PQ, L); // Apply the tone map gain. for (size_t i = 0; i < kNumChannels; ++i) { @@ -397,7 +397,8 @@ sp<DataStruct> IccHelper::write_mAB_or_mBA_tag(uint32_t type, return dataStruct; } -sp<DataStruct> IccHelper::writeIccProfile(jpegr_transfer_function tf, jpegr_color_gamut gamut) { +sp<DataStruct> IccHelper::writeIccProfile(ultrahdr_transfer_function tf, + ultrahdr_color_gamut gamut) { ICCHeader header; std::vector<std::pair<uint32_t, sp<DataStruct>>> tags; @@ -409,13 +410,13 @@ sp<DataStruct> IccHelper::writeIccProfile(jpegr_transfer_function tf, jpegr_colo Matrix3x3 toXYZD50; switch (gamut) { - case JPEGR_COLORGAMUT_BT709: + case ULTRAHDR_COLORGAMUT_BT709: toXYZD50 = kSRGB; break; - case JPEGR_COLORGAMUT_P3: + case ULTRAHDR_COLORGAMUT_P3: toXYZD50 = kDisplayP3; break; - case JPEGR_COLORGAMUT_BT2100: + case ULTRAHDR_COLORGAMUT_BT2100: toXYZD50 = kRec2020; break; default: @@ -437,8 +438,8 @@ sp<DataStruct> IccHelper::writeIccProfile(jpegr_transfer_function tf, jpegr_colo tags.emplace_back(kTAG_wtpt, write_xyz_tag(kD50_x, kD50_y, kD50_z)); // Compute transfer curves. - if (tf != JPEGR_TF_PQ) { - if (tf == JPEGR_TF_HLG) { + if (tf != ULTRAHDR_TF_PQ) { + if (tf == ULTRAHDR_TF_HLG) { std::vector<uint8_t> trc_table; trc_table.resize(kTrcTableSize * 2); for (uint32_t i = 0; i < kTrcTableSize; ++i) { @@ -462,32 +463,32 @@ sp<DataStruct> IccHelper::writeIccProfile(jpegr_transfer_function tf, jpegr_colo } // Compute CICP. - if (tf == JPEGR_TF_HLG || tf == JPEGR_TF_PQ) { + if (tf == ULTRAHDR_TF_HLG || tf == ULTRAHDR_TF_PQ) { // The CICP tag is present in ICC 4.4, so update the header's version. header.version = Endian_SwapBE32(0x04400000); uint32_t color_primaries = 0; - if (gamut == JPEGR_COLORGAMUT_BT709) { + if (gamut == ULTRAHDR_COLORGAMUT_BT709) { color_primaries = kCICPPrimariesSRGB; - } else if (gamut == JPEGR_COLORGAMUT_P3) { + } else if (gamut == ULTRAHDR_COLORGAMUT_P3) { color_primaries = kCICPPrimariesP3; } uint32_t transfer_characteristics = 0; - if (tf == JPEGR_TF_SRGB) { + if (tf == ULTRAHDR_TF_SRGB) { transfer_characteristics = kCICPTrfnSRGB; - } else if (tf == JPEGR_TF_LINEAR) { + } else if (tf == ULTRAHDR_TF_LINEAR) { transfer_characteristics = kCICPTrfnLinear; - } else if (tf == JPEGR_TF_PQ) { + } else if (tf == ULTRAHDR_TF_PQ) { transfer_characteristics = kCICPTrfnPQ; - } else if (tf == JPEGR_TF_HLG) { + } else if (tf == ULTRAHDR_TF_HLG) { transfer_characteristics = kCICPTrfnHLG; } tags.emplace_back(kTAG_cicp, write_cicp_tag(color_primaries, transfer_characteristics)); } // Compute A2B0. - if (tf == JPEGR_TF_PQ) { + if (tf == ULTRAHDR_TF_PQ) { std::vector<uint8_t> a2b_grid; a2b_grid.resize(kGridSize * kGridSize * kGridSize * kNumChannels * 2); size_t a2b_grid_index = 0; @@ -520,7 +521,7 @@ sp<DataStruct> IccHelper::writeIccProfile(jpegr_transfer_function tf, jpegr_colo } // Compute B2A0. - if (tf == JPEGR_TF_PQ) { + if (tf == ULTRAHDR_TF_PQ) { auto b2a_data = write_mAB_or_mBA_tag(kTAG_mBAType, /* has_a_curves */ false, /* grid_points */ nullptr, @@ -541,7 +542,7 @@ sp<DataStruct> IccHelper::writeIccProfile(jpegr_transfer_function tf, jpegr_colo // Write the header. header.data_color_space = Endian_SwapBE32(Signature_RGB); - header.pcs = Endian_SwapBE32(tf == JPEGR_TF_PQ ? Signature_Lab : Signature_XYZ); + header.pcs = Endian_SwapBE32(tf == ULTRAHDR_TF_PQ ? Signature_Lab : Signature_XYZ); header.size = Endian_SwapBE32(profile_size); header.tag_count = Endian_SwapBE32(tags.size()); @@ -581,4 +582,4 @@ sp<DataStruct> IccHelper::writeIccProfile(jpegr_transfer_function tf, jpegr_colo return dataStruct; } -} // namespace android::jpegrecoverymap
\ No newline at end of file +} // namespace android::ultrahdr
\ No newline at end of file diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h b/libs/ultrahdr/include/ultrahdr/gainmapmath.h index a32b29119e..abc93567f2 100644 --- a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h +++ b/libs/ultrahdr/include/ultrahdr/gainmapmath.h @@ -14,15 +14,15 @@ * limitations under the License. */ -#ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAPMATH_H -#define ANDROID_JPEGRECOVERYMAP_RECOVERYMAPMATH_H +#ifndef ANDROID_ULTRAHDR_RECOVERYMAPMATH_H +#define ANDROID_ULTRAHDR_RECOVERYMAPMATH_H #include <cmath> #include <stdint.h> -#include <jpegrecoverymap/jpegr.h> +#include <ultrahdr/jpegr.h> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { #define CLIP3(x, min, max) ((x) < (min)) ? (min) : ((x) > (max)) ? (max) : (x) @@ -129,40 +129,40 @@ inline uint16_t floatToHalf(float f) { | (e > 143) * 0x7FFF; } -constexpr size_t kRecoveryFactorPrecision = 10; -constexpr size_t kRecoveryFactorNumEntries = 1 << kRecoveryFactorPrecision; -struct RecoveryLUT { - RecoveryLUT(jr_metadata_ptr metadata) { - for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) { - float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1); +constexpr size_t kGainFactorPrecision = 10; +constexpr size_t kGainFactorNumEntries = 1 << kGainFactorPrecision; +struct GainLUT { + GainLUT(ultrahdr_metadata_ptr metadata) { + for (int idx = 0; idx < kGainFactorNumEntries; idx++) { + float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1); float logBoost = log2(metadata->minContentBoost) * (1.0f - value) + log2(metadata->maxContentBoost) * value; - mRecoveryTable[idx] = exp2(logBoost); + mGainTable[idx] = exp2(logBoost); } } - RecoveryLUT(jr_metadata_ptr metadata, float displayBoost) { + GainLUT(ultrahdr_metadata_ptr metadata, float displayBoost) { float boostFactor = displayBoost > 0 ? displayBoost / metadata->maxContentBoost : 1.0f; - for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) { - float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1); + for (int idx = 0; idx < kGainFactorNumEntries; idx++) { + float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1); float logBoost = log2(metadata->minContentBoost) * (1.0f - value) + log2(metadata->maxContentBoost) * value; - mRecoveryTable[idx] = exp2(logBoost * boostFactor); + mGainTable[idx] = exp2(logBoost * boostFactor); } } - ~RecoveryLUT() { + ~GainLUT() { } - float getRecoveryFactor(float recovery) { - uint32_t idx = static_cast<uint32_t>(recovery * (kRecoveryFactorNumEntries - 1)); + float getGainFactor(float gain) { + uint32_t idx = static_cast<uint32_t>(gain * (kGainFactorNumEntries - 1)); //TODO() : Remove once conversion modules have appropriate clamping in place - idx = CLIP3(idx, 0, kRecoveryFactorNumEntries - 1); - return mRecoveryTable[idx]; + idx = CLIP3(idx, 0, kGainFactorNumEntries - 1); + return mGainTable[idx]; } private: - float mRecoveryTable[kRecoveryFactorNumEntries]; + float mGainTable[kGainFactorNumEntries]; }; struct ShepardsIDW { @@ -195,11 +195,11 @@ struct ShepardsIDW { // p60 p61 p62 p63 p64 p65 p66 p67 // p70 p71 p72 p73 p74 p75 p76 p77 - // Recovery Map (for 4 scale factor) :- + // Gain Map (for 4 scale factor) :- // m00 p01 // m10 m11 - // Recovery sample of curr 4x4, right 4x4, bottom 4x4, bottom right 4x4 are used during + // Gain sample of curr 4x4, right 4x4, bottom 4x4, bottom right 4x4 are used during // reconstruction. hence table weight size is 4. float* mWeights; // TODO: check if its ok to mWeights at places @@ -354,29 +354,29 @@ Color bt2100ToP3(Color e); inline Color identityConversion(Color e) { return e; } /* - * Get the conversion to apply to the HDR image for recovery map generation + * Get the conversion to apply to the HDR image for gain map generation */ -ColorTransformFn getHdrConversionFn(jpegr_color_gamut sdr_gamut, jpegr_color_gamut hdr_gamut); +ColorTransformFn getHdrConversionFn(ultrahdr_color_gamut sdr_gamut, ultrahdr_color_gamut hdr_gamut); //////////////////////////////////////////////////////////////////////////////// -// Recovery map calculations +// Gain map calculations /* - * Calculate the 8-bit unsigned integer recovery value for the given SDR and HDR + * Calculate the 8-bit unsigned integer gain value for the given SDR and HDR * luminances in linear space, and the hdr ratio to encode against. */ -uint8_t encodeRecovery(float y_sdr, float y_hdr, jr_metadata_ptr metadata); -uint8_t encodeRecovery(float y_sdr, float y_hdr, jr_metadata_ptr metadata, - float log2MinContentBoost, float log2MaxContentBoost); +uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata); +uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata, + float log2MinContentBoost, float log2MaxContentBoost); /* - * Calculates the linear luminance in nits after applying the given recovery + * Calculates the linear luminance in nits after applying the given gain * value, with the given hdr ratio, to the given sdr input in the range [0, 1]. */ -Color applyRecovery(Color e, float recovery, jr_metadata_ptr metadata); -Color applyRecovery(Color e, float recovery, jr_metadata_ptr metadata, float displayBoost); -Color applyRecoveryLUT(Color e, float recovery, RecoveryLUT& recoveryLUT); +Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata); +Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata, float displayBoost); +Color applyGainLUT(Color e, float gain, GainLUT& gainLUT); /* * Helper for sampling from YUV 420 images. @@ -405,7 +405,7 @@ Color sampleYuv420(jr_uncompressed_ptr map, size_t map_scale_factor, size_t x, s Color sampleP010(jr_uncompressed_ptr map, size_t map_scale_factor, size_t x, size_t y); /* - * Sample the recovery value for the map from a given x,y coordinate on a scale + * Sample the gain value for the map from a given x,y coordinate on a scale * that is map scale factor larger than the map size. */ float sampleMap(jr_uncompressed_ptr map, float map_scale_factor, size_t x, size_t y); @@ -426,6 +426,6 @@ uint32_t colorToRgba1010102(Color e_gamma); */ uint64_t colorToRgbaF16(Color e_gamma); -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr -#endif // ANDROID_JPEGRECOVERYMAP_RECOVERYMAPMATH_H +#endif // ANDROID_ULTRAHDR_RECOVERYMAPMATH_H diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/icc.h b/libs/ultrahdr/include/ultrahdr/icc.h index a81aa62627..7f6ab882c6 100644 --- a/libs/jpegrecoverymap/include/jpegrecoverymap/icc.h +++ b/libs/ultrahdr/include/ultrahdr/icc.h @@ -14,11 +14,11 @@ * limitations under the License. */ -#ifndef ANDROID_JPEGRECOVERYMAP_ICC_H -#define ANDROID_JPEGRECOVERYMAP_ICC_H +#ifndef ANDROID_ULTRAHDR_ICC_H +#define ANDROID_ULTRAHDR_ICC_H -#include <jpegrecoverymap/jpegr.h> -#include <jpegrecoverymap/jpegrutils.h> +#include <ultrahdr/jpegr.h> +#include <ultrahdr/jpegrutils.h> #include <utils/RefBase.h> #include <cmath> #include <string> @@ -28,7 +28,7 @@ #define USE_BIG_ENDIAN true #endif -namespace android::jpegrecoverymap { +namespace android::ultrahdr { typedef int32_t Fixed; #define Fixed1 (1 << 16) @@ -210,12 +210,12 @@ private: static constexpr size_t kNumChannels = 3; static sp<DataStruct> write_text_tag(const char* text); - static std::string get_desc_string(const jpegr_transfer_function tf, - const jpegr_color_gamut gamut); + static std::string get_desc_string(const ultrahdr_transfer_function tf, + const ultrahdr_color_gamut gamut); static sp<DataStruct> write_xyz_tag(float x, float y, float z); static sp<DataStruct> write_trc_tag(const int table_entries, const void* table_16); static sp<DataStruct> write_trc_tag_for_linear(); - static float compute_tone_map_gain(const jpegr_transfer_function tf, float L); + static float compute_tone_map_gain(const ultrahdr_transfer_function tf, float L); static sp<DataStruct> write_cicp_tag(uint32_t color_primaries, uint32_t transfer_characteristics); static sp<DataStruct> write_mAB_or_mBA_tag(uint32_t type, @@ -226,9 +226,9 @@ private: static sp<DataStruct> write_clut(const uint8_t* grid_points, const uint8_t* grid_16); public: - static sp<DataStruct> writeIccProfile(const jpegr_transfer_function tf, - const jpegr_color_gamut gamut); + static sp<DataStruct> writeIccProfile(const ultrahdr_transfer_function tf, + const ultrahdr_color_gamut gamut); }; -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr -#endif //ANDROID_JPEGRECOVERYMAP_ICC_H
\ No newline at end of file +#endif //ANDROID_ULTRAHDR_ICC_H
\ No newline at end of file diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h b/libs/ultrahdr/include/ultrahdr/jpegdecoderhelper.h index 874823709c..f642bad89c 100644 --- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h +++ b/libs/ultrahdr/include/ultrahdr/jpegdecoderhelper.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H -#define ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H +#ifndef ANDROID_ULTRAHDR_JPEGDECODERHELPER_H +#define ANDROID_ULTRAHDR_JPEGDECODERHELPER_H // We must include cstdio before jpeglib.h. It is a requirement of libjpeg. #include <cstdio> @@ -25,7 +25,7 @@ extern "C" { } #include <utils/Errors.h> #include <vector> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { /* * Encapsulates a converter from JPEG to raw image (YUV420planer or grey-scale) format. * This class is not thread-safe. @@ -115,6 +115,6 @@ private: // Position of EXIF package, default value is -1 which means no EXIF package appears. size_t mExifPos; }; -} /* namespace android::jpegrecoverymap */ +} /* namespace android::ultrahdr */ -#endif // ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H +#endif // ANDROID_ULTRAHDR_JPEGDECODERHELPER_H diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h b/libs/ultrahdr/include/ultrahdr/jpegencoderhelper.h index 8b82b2b00a..2c6778e299 100644 --- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h +++ b/libs/ultrahdr/include/ultrahdr/jpegencoderhelper.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H -#define ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H +#ifndef ANDROID_ULTRAHDR_JPEGENCODERHELPER_H +#define ANDROID_ULTRAHDR_JPEGENCODERHELPER_H // We must include cstdio before jpeglib.h. It is a requirement of libjpeg. #include <cstdio> @@ -28,7 +28,7 @@ extern "C" { #include <utils/Errors.h> #include <vector> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { /* * Encapsulates a converter from raw image (YUV420planer or grey-scale) to JPEG format. @@ -61,6 +61,11 @@ public: */ size_t getCompressedImageSize(); + /* + * Process 16 lines of Y and 16 lines of U/V each time. + * We must pass at least 16 scanlines according to libjpeg documentation. + */ + static const int kCompressBatchSize = 16; private: // initDestination(), emptyOutputBuffer() and emptyOutputBuffer() are callback functions to be // passed into jpeg library. @@ -82,14 +87,11 @@ private: // The block size for encoded jpeg image buffer. static const int kBlockSize = 16384; - // Process 16 lines of Y and 16 lines of U/V each time. - // We must pass at least 16 scanlines according to libjpeg documentation. - static const int kCompressBatchSize = 16; // The buffer that holds the compressed result. std::vector<JOCTET> mResultBuffer; }; -} /* namespace android::jpegrecoverymap */ +} /* namespace android::ultrahdr */ -#endif // ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H +#endif // ANDROID_ULTRAHDR_JPEGENCODERHELPER_H diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegr.h b/libs/ultrahdr/include/ultrahdr/jpegr.h index 6262e18479..88038f11a4 100644 --- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegr.h +++ b/libs/ultrahdr/include/ultrahdr/jpegr.h @@ -14,41 +14,17 @@ * limitations under the License. */ -#ifndef ANDROID_JPEGRECOVERYMAP_JPEGR_H -#define ANDROID_JPEGRECOVERYMAP_JPEGR_H +#ifndef ANDROID_ULTRAHDR_JPEGR_H +#define ANDROID_ULTRAHDR_JPEGR_H #include "jpegrerrorcode.h" +#include "ultrahdr.h" #ifndef FLT_MAX #define FLT_MAX 0x1.fffffep127f #endif -namespace android::jpegrecoverymap { - -// Color gamuts for image data -typedef enum { - JPEGR_COLORGAMUT_UNSPECIFIED, - JPEGR_COLORGAMUT_BT709, - JPEGR_COLORGAMUT_P3, - JPEGR_COLORGAMUT_BT2100, -} jpegr_color_gamut; - -// Transfer functions for image data -typedef enum { - JPEGR_TF_UNSPECIFIED = -1, - JPEGR_TF_LINEAR = 0, - JPEGR_TF_HLG = 1, - JPEGR_TF_PQ = 2, - JPEGR_TF_SRGB = 3, -} jpegr_transfer_function; - -// Target output formats for decoder -typedef enum { - JPEGR_OUTPUT_SDR, // SDR in RGBA_8888 color format - JPEGR_OUTPUT_HDR_LINEAR, // HDR in F16 color format (linear) - JPEGR_OUTPUT_HDR_PQ, // HDR in RGBA_1010102 color format (PQ transfer function) - JPEGR_OUTPUT_HDR_HLG, // HDR in RGBA_1010102 color format (HLG transfer function) -} jpegr_output_format; +namespace android::ultrahdr { struct jpegr_info_struct { size_t width; @@ -58,21 +34,35 @@ struct jpegr_info_struct { }; /* - * Holds information for uncompressed image or recovery map. + * Holds information for uncompressed image or gain map. */ struct jpegr_uncompressed_struct { // Pointer to the data location. void* data; - // Width of the recovery map or image in pixels. + // Width of the gain map or the luma plane of the image in pixels. int width; - // Height of the recovery map or image in pixels. + // Height of the gain map or the luma plane of the image in pixels. int height; // Color gamut. - jpegr_color_gamut colorGamut; + ultrahdr_color_gamut colorGamut; + + // Values below are optional + // Pointer to chroma data, if it's NULL, chroma plane is considered to be immediately + // following after the luma plane. + // Note: currently this feature is only supported for P010 image (HDR input). + void* chroma_data = nullptr; + // Strides of Y plane in number of pixels, using 0 to present uninitialized, must be + // larger than or equal to luma width. + // Note: currently this feature is only supported for P010 image (HDR input). + int luma_stride = 0; + // Strides of UV plane in number of pixels, using 0 to present uninitialized, must be + // larger than or equal to chroma width. + // Note: currently this feature is only supported for P010 image (HDR input). + int chroma_stride = 0; }; /* - * Holds information for compressed image or recovery map. + * Holds information for compressed image or gain map. */ struct jpegr_compressed_struct { // Pointer to the data location. @@ -82,7 +72,7 @@ struct jpegr_compressed_struct { // Maximum available data length in bytes. int maxLength; // Color gamut. - jpegr_color_gamut colorGamut; + ultrahdr_color_gamut colorGamut; }; /* @@ -95,22 +85,9 @@ struct jpegr_exif_struct { int length; }; -/* - * Holds information for recovery map related metadata. - */ -struct jpegr_metadata_struct { - // JPEG/R version - uint32_t version; - // Max Content Boost for the map - float maxContentBoost; - // Min Content Boost for the map - float minContentBoost; -}; - typedef struct jpegr_uncompressed_struct* jr_uncompressed_ptr; typedef struct jpegr_compressed_struct* jr_compressed_ptr; typedef struct jpegr_exif_struct* jr_exif_ptr; -typedef struct jpegr_metadata_struct* jr_metadata_ptr; typedef struct jpegr_info_struct* jr_info_ptr; class JpegR { @@ -121,19 +98,22 @@ public: * Encode API-0 * Compress JPEGR image from 10-bit HDR YUV. * - * Tonemap the HDR input to a SDR image, generate recovery map from the HDR and SDR images, - * compress SDR YUV to 8-bit JPEG and append the recovery map to the end of the compressed + * Tonemap the HDR input to a SDR image, generate gain map from the HDR and SDR images, + * compress SDR YUV to 8-bit JPEG and append the gain map to the end of the compressed * JPEG. * @param uncompressed_p010_image uncompressed HDR image in P010 color format * @param hdr_tf transfer function of the HDR image - * @param dest destination of the compressed JPEGR image + * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength} + * represents the maximum available size of the desitination buffer, and it must be + * set before calling this method. If the encoded JPEGR size exceeds + * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}. * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is * the highest quality * @param exif pointer to the exif metadata. * @return NO_ERROR if encoding succeeds, error code if error occurs. */ status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, - jpegr_transfer_function hdr_tf, + ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest, int quality, jr_exif_ptr exif); @@ -142,13 +122,16 @@ public: * Encode API-1 * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV. * - * Generate recovery map from the HDR and SDR inputs, compress SDR YUV to 8-bit JPEG and append - * the recovery map to the end of the compressed JPEG. HDR and SDR inputs must be the same + * Generate gain map from the HDR and SDR inputs, compress SDR YUV to 8-bit JPEG and append + * the gain map to the end of the compressed JPEG. HDR and SDR inputs must be the same * resolution. * @param uncompressed_p010_image uncompressed HDR image in P010 color format * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format * @param hdr_tf transfer function of the HDR image - * @param dest destination of the compressed JPEGR image + * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength} + * represents the maximum available size of the desitination buffer, and it must be + * set before calling this method. If the encoded JPEGR size exceeds + * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}. * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is * the highest quality * @param exif pointer to the exif metadata. @@ -156,7 +139,7 @@ public: */ status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jr_uncompressed_ptr uncompressed_yuv_420_image, - jpegr_transfer_function hdr_tf, + ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest, int quality, jr_exif_ptr exif); @@ -167,7 +150,7 @@ public: * * This method requires HAL Hardware JPEG encoder. * - * Generate recovery map from the HDR and SDR inputs, append the recovery map to the end of the + * Generate gain map from the HDR and SDR inputs, append the gain map to the end of the * compressed JPEG. HDR and SDR inputs must be the same resolution and color space. * @param uncompressed_p010_image uncompressed HDR image in P010 color format * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format @@ -175,13 +158,16 @@ public: * input * @param compressed_jpeg_image compressed 8-bit JPEG image * @param hdr_tf transfer function of the HDR image - * @param dest destination of the compressed JPEGR image + * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength} + * represents the maximum available size of the desitination buffer, and it must be + * set before calling this method. If the encoded JPEGR size exceeds + * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}. * @return NO_ERROR if encoding succeeds, error code if error occurs. */ status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jr_uncompressed_ptr uncompressed_yuv_420_image, jr_compressed_ptr compressed_jpeg_image, - jpegr_transfer_function hdr_tf, + ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest); /* @@ -190,18 +176,40 @@ public: * * This method requires HAL Hardware JPEG encoder. * - * Decode the compressed 8-bit JPEG image to YUV SDR, generate recovery map from the HDR input - * and the decoded SDR result, append the recovery map to the end of the compressed JPEG. HDR + * Decode the compressed 8-bit JPEG image to YUV SDR, generate gain map from the HDR input + * and the decoded SDR result, append the gain map to the end of the compressed JPEG. HDR * and SDR inputs must be the same resolution. * @param uncompressed_p010_image uncompressed HDR image in P010 color format * @param compressed_jpeg_image compressed 8-bit JPEG image * @param hdr_tf transfer function of the HDR image - * @param dest destination of the compressed JPEGR image + * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength} + * represents the maximum available size of the desitination buffer, and it must be + * set before calling this method. If the encoded JPEGR size exceeds + * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}. * @return NO_ERROR if encoding succeeds, error code if error occurs. */ status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jr_compressed_ptr compressed_jpeg_image, - jpegr_transfer_function hdr_tf, + ultrahdr_transfer_function hdr_tf, + jr_compressed_ptr dest); + + /* + * Encode API-4 + * Assemble JPEGR image from SDR JPEG and gainmap JPEG. + * + * Assemble the primary JPEG image, the gain map and the metadata to JPEG/R format. + * @param compressed_jpeg_image compressed 8-bit JPEG image + * @param compressed_gainmap compressed 8-bit JPEG single channel image + * @param metadata metadata to be written in XMP of the primary jpeg + * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength} + * represents the maximum available size of the desitination buffer, and it must be + * set before calling this method. If the encoded JPEGR size exceeds + * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}. + * @return NO_ERROR if encoding succeeds, error code if error occurs. + */ + status_t encodeJPEGR(jr_compressed_ptr compressed_jpeg_image, + jr_compressed_ptr compressed_gainmap, + ultrahdr_metadata_ptr metadata, jr_compressed_ptr dest); /* @@ -228,23 +236,23 @@ public: ---------------------------------------------------------------------- | JPEGR_OUTPUT_HDR_HLG | RGBA_1010102 HLG | ---------------------------------------------------------------------- - * @param recovery_map destination of the decoded recovery map. The default value is NULL where + * @param gain_map destination of the decoded gain map. The default value is NULL where the decoder will do nothing about it. If configured not NULL the decoder - will write the decoded recovery_map data into this structure. The format + will write the decoded gain_map data into this structure. The format is defined in {@code jpegr_uncompressed_struct}. * @param metadata destination of the decoded metadata. The default value is NULL where the decoder will do nothing about it. If configured not NULL the decoder will write metadata into this structure. the format of metadata is defined in - {@code jpegr_metadata}. + {@code ultrahdr_metadata_struct}. * @return NO_ERROR if decoding succeeds, error code if error occurs. */ status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, jr_uncompressed_ptr dest, float max_display_boost = FLT_MAX, jr_exif_ptr exif = nullptr, - jpegr_output_format output_format = JPEGR_OUTPUT_HDR_LINEAR, - jr_uncompressed_ptr recovery_map = nullptr, - jr_metadata_ptr metadata = nullptr); + ultrahdr_output_format output_format = ULTRAHDR_OUTPUT_HDR_LINEAR, + jr_uncompressed_ptr gain_map = nullptr, + ultrahdr_metadata_ptr metadata = nullptr); /* * Gets Info from JPEGR file without decoding it. @@ -260,30 +268,30 @@ public: protected: /* * This method is called in the encoding pipeline. It will take the uncompressed 8-bit and - * 10-bit yuv images as input, and calculate the uncompressed recovery map. The input images + * 10-bit yuv images as input, and calculate the uncompressed gain map. The input images * must be the same resolution. * * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format * @param uncompressed_p010_image uncompressed HDR image in P010 color format * @param hdr_tf transfer function of the HDR image - * @param dest recovery map; caller responsible for memory of data + * @param dest gain map; caller responsible for memory of data * @param metadata max_content_boost is filled in * @return NO_ERROR if calculation succeeds, error code if error occurs. */ - status_t generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image, - jr_uncompressed_ptr uncompressed_p010_image, - jpegr_transfer_function hdr_tf, - jr_metadata_ptr metadata, - jr_uncompressed_ptr dest); + status_t generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, + jr_uncompressed_ptr uncompressed_p010_image, + ultrahdr_transfer_function hdr_tf, + ultrahdr_metadata_ptr metadata, + jr_uncompressed_ptr dest); /* * This method is called in the decoding pipeline. It will take the uncompressed (decoded) - * 8-bit yuv image, the uncompressed (decoded) recovery map, and extracted JPEG/R metadata as + * 8-bit yuv image, the uncompressed (decoded) gain map, and extracted JPEG/R metadata as * input, and calculate the 10-bit recovered image. The recovered output image is the same * color gamut as the SDR image, with HLG transfer function, and is in RGBA1010102 data format. * * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format - * @param uncompressed_recovery_map uncompressed recovery map + * @param uncompressed_gain_map uncompressed gain map * @param metadata JPEG/R metadata extracted from XMP. * @param output_format flag for setting output color format. if set to * {@code JPEGR_OUTPUT_SDR}, decoder will only decode the primary image @@ -292,67 +300,67 @@ protected: * @param dest reconstructed HDR image * @return NO_ERROR if calculation succeeds, error code if error occurs. */ - status_t applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image, - jr_uncompressed_ptr uncompressed_recovery_map, - jr_metadata_ptr metadata, - jpegr_output_format output_format, - float max_display_boost, - jr_uncompressed_ptr dest); + status_t applyGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, + jr_uncompressed_ptr uncompressed_gain_map, + ultrahdr_metadata_ptr metadata, + ultrahdr_output_format output_format, + float max_display_boost, + jr_uncompressed_ptr dest); private: /* - * This method is called in the encoding pipeline. It will encode the recovery map. + * This method is called in the encoding pipeline. It will encode the gain map. * - * @param uncompressed_recovery_map uncompressed recovery map + * @param uncompressed_gain_map uncompressed gain map * @param dest encoded recover map * @return NO_ERROR if encoding succeeds, error code if error occurs. */ - status_t compressRecoveryMap(jr_uncompressed_ptr uncompressed_recovery_map, - jr_compressed_ptr dest); + status_t compressGainMap(jr_uncompressed_ptr uncompressed_gain_map, + jr_compressed_ptr dest); /* - * This methoud is called to separate primary image and recovery map image from JPEGR + * This methoud is called to separate primary image and gain map image from JPEGR * * @param compressed_jpegr_image compressed JPEGR image * @param primary_image destination of primary image - * @param recovery_map destination of compressed recovery map + * @param gain_map destination of compressed gain map * @return NO_ERROR if calculation succeeds, error code if error occurs. */ - status_t extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_jpegr_image, - jr_compressed_ptr primary_image, - jr_compressed_ptr recovery_map); + status_t extractPrimaryImageAndGainMap(jr_compressed_ptr compressed_jpegr_image, + jr_compressed_ptr primary_image, + jr_compressed_ptr gain_map); /* * This method is called in the decoding pipeline. It will read XMP metadata to find the start - * position of the compressed recovery map, and will extract the compressed recovery map. + * position of the compressed gain map, and will extract the compressed gain map. * * @param compressed_jpegr_image compressed JPEGR image - * @param dest destination of compressed recovery map + * @param dest destination of compressed gain map * @return NO_ERROR if calculation succeeds, error code if error occurs. */ - status_t extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image, - jr_compressed_ptr dest); + status_t extractGainMap(jr_compressed_ptr compressed_jpegr_image, + jr_compressed_ptr dest); /* * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image, - * the compressed recovery map and optionally the exif package as inputs, and generate the XMP + * the compressed gain map and optionally the exif package as inputs, and generate the XMP * metadata, and finally append everything in the order of: - * SOI, APP2(EXIF) (if EXIF is from outside), APP2(XMP), primary image, recovery map + * SOI, APP2(EXIF) (if EXIF is from outside), APP2(XMP), primary image, gain map * Note that EXIF package is only available for encoding API-0 and API-1. For encoding API-2 and * API-3 this parameter is null, but the primary image in JPEG/R may still have EXIF as long as * the input JPEG has EXIF. * * @param compressed_jpeg_image compressed 8-bit JPEG image - * @param compress_recovery_map compressed recover map + * @param compress_gain_map compressed recover map * @param (nullable) exif EXIF package * @param metadata JPEG/R metadata to encode in XMP of the jpeg * @param dest compressed JPEGR image * @return NO_ERROR if calculation succeeds, error code if error occurs. */ - status_t appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, - jr_compressed_ptr compressed_recovery_map, - jr_exif_ptr exif, - jr_metadata_ptr metadata, - jr_compressed_ptr dest); + status_t appendGainMap(jr_compressed_ptr compressed_jpeg_image, + jr_compressed_ptr compressed_gain_map, + jr_exif_ptr exif, + ultrahdr_metadata_ptr metadata, + jr_compressed_ptr dest); /* * This method will tone map a HDR image to an SDR image. @@ -363,8 +371,18 @@ private: */ status_t toneMap(jr_uncompressed_ptr src, jr_uncompressed_ptr dest); + + /* + * This method will check the validity of the input images. + * + * @param uncompressed_p010_image uncompressed HDR image in P010 color format + * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format + * @return NO_ERROR if the input images are valid, error code is not valid. + */ + status_t areInputImagesValid(jr_uncompressed_ptr uncompressed_p010_image, + jr_uncompressed_ptr uncompressed_yuv_420_image); }; -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr -#endif // ANDROID_JPEGRECOVERYMAP_JPEGR_H +#endif // ANDROID_ULTRAHDR_JPEGR_H diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrerrorcode.h b/libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h index f73034338b..9f59c3eaf3 100644 --- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrerrorcode.h +++ b/libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h @@ -14,9 +14,12 @@ * limitations under the License. */ +#ifndef ANDROID_ULTRAHDR_JPEGRERRORCODE_H +#define ANDROID_ULTRAHDR_JPEGRERRORCODE_H + #include <utils/Errors.h> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { enum { // status_t map for errors in the media framework @@ -46,6 +49,10 @@ enum { ERROR_JPEGR_CALCULATION_ERROR = JPEGR_RUNTIME_ERROR_BASE - 3, ERROR_JPEGR_METADATA_ERROR = JPEGR_RUNTIME_ERROR_BASE - 4, ERROR_JPEGR_TONEMAP_ERROR = JPEGR_RUNTIME_ERROR_BASE - 5, + + ERROR_JPEGR_UNSUPPORTED_FEATURE = -20000, }; -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr + +#endif // ANDROID_ULTRAHDR_JPEGRERRORCODE_H diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h b/libs/ultrahdr/include/ultrahdr/jpegrutils.h index 09f416555c..4ab664e798 100644 --- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h +++ b/libs/ultrahdr/include/ultrahdr/jpegrutils.h @@ -14,10 +14,10 @@ * limitations under the License. */ -#ifndef ANDROID_JPEGRECOVERYMAP_JPEGRUTILS_H -#define ANDROID_JPEGRECOVERYMAP_JPEGRUTILS_H +#ifndef ANDROID_ULTRAHDR_JPEGRUTILS_H +#define ANDROID_ULTRAHDR_JPEGRUTILS_H -#include <jpegrecoverymap/jpegr.h> +#include <ultrahdr/jpegr.h> #include <utils/RefBase.h> #include <sstream> @@ -25,7 +25,7 @@ #include <string> #include <cstdio> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { static constexpr uint32_t EndianSwap32(uint32_t value) { return ((value & 0xFF) << 24) | @@ -45,7 +45,7 @@ static inline uint16_t EndianSwap16(uint16_t value) { #define Endian_SwapBE16(n) (n) #endif -struct jpegr_metadata_struct; +struct ultrahdr_metadata_struct; /* * Mutable data structure. Holds information for metadata. */ @@ -87,7 +87,7 @@ status_t Write(jr_compressed_ptr destination, const void* source, size_t length, * @param metadata place to store HDR metadata values * @return true if metadata is successfully retrieved, false otherwise */ -bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata_struct* metadata); +bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, ultrahdr_metadata_struct* metadata); /* * This method generates XMP metadata for the primary image. @@ -102,7 +102,9 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata_struc * xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> * <rdf:Description * xmlns:Container="http://ns.google.com/photos/1.0/container/" - * xmlns:Item="http://ns.google.com/photos/1.0/container/item/"> + * xmlns:Item="http://ns.google.com/photos/1.0/container/item/" + * xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/" + * hdrgm:Version="1"> * <Container:Directory> * <rdf:Seq> * <rdf:li @@ -127,7 +129,8 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata_struc * @param secondary_image_length length of secondary image * @return XMP metadata in type of string */ -std::string generateXmpForPrimaryImage(int secondary_image_length); +std::string generateXmpForPrimaryImage(int secondary_image_length, + ultrahdr_metadata_struct& metadata); /* * This method generates XMP metadata for the recovery map image. @@ -158,7 +161,7 @@ std::string generateXmpForPrimaryImage(int secondary_image_length); * @param metadata JPEG/R metadata to encode as XMP * @return XMP metadata in type of string */ - std::string generateXmpForSecondaryImage(jpegr_metadata_struct& metadata); -} // namespace android::jpegrecoverymap + std::string generateXmpForSecondaryImage(ultrahdr_metadata_struct& metadata); +} // namespace android::ultrahdr -#endif //ANDROID_JPEGRECOVERYMAP_JPEGRUTILS_H +#endif //ANDROID_ULTRAHDR_JPEGRUTILS_H diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/multipictureformat.h b/libs/ultrahdr/include/ultrahdr/multipictureformat.h index cf3387d9b6..c5bd09d6f2 100644 --- a/libs/jpegrecoverymap/include/jpegrecoverymap/multipictureformat.h +++ b/libs/ultrahdr/include/ultrahdr/multipictureformat.h @@ -14,17 +14,17 @@ * limitations under the License. */ -#ifndef ANDROID_JPEGRECOVERYMAP_MULTIPICTUREFORMAT_H -#define ANDROID_JPEGRECOVERYMAP_MULTIPICTUREFORMAT_H +#ifndef ANDROID_ULTRAHDR_MULTIPICTUREFORMAT_H +#define ANDROID_ULTRAHDR_MULTIPICTUREFORMAT_H -#include <jpegrecoverymap/jpegrutils.h> +#include <ultrahdr/jpegrutils.h> #ifdef USE_BIG_ENDIAN #undef USE_BIG_ENDIAN #define USE_BIG_ENDIAN true #endif -namespace android::jpegrecoverymap { +namespace android::ultrahdr { constexpr size_t kNumPictures = 2; constexpr size_t kMpEndianSize = 4; @@ -59,6 +59,6 @@ size_t calculateMpfSize(); sp<DataStruct> generateMpf(int primary_image_size, int primary_image_offset, int secondary_image_size, int secondary_image_offset); -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr -#endif //ANDROID_JPEGRECOVERYMAP_MULTIPICTUREFORMAT_H +#endif //ANDROID_ULTRAHDR_MULTIPICTUREFORMAT_H diff --git a/libs/ultrahdr/include/ultrahdr/ultrahdr.h b/libs/ultrahdr/include/ultrahdr/ultrahdr.h new file mode 100644 index 0000000000..f9709369ee --- /dev/null +++ b/libs/ultrahdr/include/ultrahdr/ultrahdr.h @@ -0,0 +1,61 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_ULTRAHDR_ULTRAHDR_H +#define ANDROID_ULTRAHDR_ULTRAHDR_H + +namespace android::ultrahdr { +// Color gamuts for image data +typedef enum { + ULTRAHDR_COLORGAMUT_UNSPECIFIED, + ULTRAHDR_COLORGAMUT_BT709, + ULTRAHDR_COLORGAMUT_P3, + ULTRAHDR_COLORGAMUT_BT2100, +} ultrahdr_color_gamut; + +// Transfer functions for image data +typedef enum { + ULTRAHDR_TF_UNSPECIFIED = -1, + ULTRAHDR_TF_LINEAR = 0, + ULTRAHDR_TF_HLG = 1, + ULTRAHDR_TF_PQ = 2, + ULTRAHDR_TF_SRGB = 3, +} ultrahdr_transfer_function; + +// Target output formats for decoder +typedef enum { + ULTRAHDR_OUTPUT_SDR, // SDR in RGBA_8888 color format + ULTRAHDR_OUTPUT_HDR_LINEAR, // HDR in F16 color format (linear) + ULTRAHDR_OUTPUT_HDR_PQ, // HDR in RGBA_1010102 color format (PQ transfer function) + ULTRAHDR_OUTPUT_HDR_HLG, // HDR in RGBA_1010102 color format (HLG transfer function) +} ultrahdr_output_format; + +/* + * Holds information for gain map related metadata. + */ +struct ultrahdr_metadata_struct { + // Ultra HDR library version + const char* version; + // Max Content Boost for the map + float maxContentBoost; + // Min Content Boost for the map + float minContentBoost; +}; +typedef struct ultrahdr_metadata_struct* ultrahdr_metadata_ptr; + +} // namespace android::ultrahdr + +#endif //ANDROID_ULTRAHDR_ULTRAHDR_H diff --git a/libs/jpegrecoverymap/jpegdecoderhelper.cpp b/libs/ultrahdr/jpegdecoderhelper.cpp index d36bbf8165..12217b7906 100644 --- a/libs/jpegrecoverymap/jpegdecoderhelper.cpp +++ b/libs/ultrahdr/jpegdecoderhelper.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <jpegrecoverymap/jpegdecoderhelper.h> +#include <ultrahdr/jpegdecoderhelper.h> #include <utils/Log.h> @@ -24,7 +24,7 @@ using namespace std; -namespace android::jpegrecoverymap { +namespace android::ultrahdr { const uint32_t kAPP0Marker = JPEG_APP0; // JFIF const uint32_t kAPP1Marker = JPEG_APP0 + 1; // EXIF, XMP @@ -413,4 +413,4 @@ bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, c return true; } -} // namespace jpegrecoverymap +} // namespace ultrahdr diff --git a/libs/jpegrecoverymap/jpegencoderhelper.cpp b/libs/ultrahdr/jpegencoderhelper.cpp index 586cd346e4..10a763035f 100644 --- a/libs/jpegrecoverymap/jpegencoderhelper.cpp +++ b/libs/ultrahdr/jpegencoderhelper.cpp @@ -14,13 +14,13 @@ * limitations under the License. */ -#include <jpegrecoverymap/jpegencoderhelper.h> +#include <ultrahdr/jpegencoderhelper.h> #include <utils/Log.h> #include <errno.h> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { // The destination manager that can access |mResultBuffer| in JpegEncoderHelper. struct destination_mgr { @@ -38,11 +38,6 @@ JpegEncoderHelper::~JpegEncoderHelper() { bool JpegEncoderHelper::compressImage(const void* image, int width, int height, int quality, const void* iccBuffer, unsigned int iccSize, bool isSingleChannel) { - if (width % 8 != 0 || height % 2 != 0) { - ALOGE("Image size can not be handled: %dx%d", width, height); - return false; - } - mResultBuffer.clear(); if (!encode(image, width, height, quality, iccBuffer, iccSize, isSingleChannel)) { return false; @@ -236,4 +231,4 @@ bool JpegEncoderHelper::compressSingleChannel(jpeg_compress_struct* cinfo, const return true; } -} // namespace jpegrecoverymap +} // namespace ultrahdr diff --git a/libs/jpegrecoverymap/jpegr.cpp b/libs/ultrahdr/jpegr.cpp index d147130209..0f7aa27354 100644 --- a/libs/jpegrecoverymap/jpegr.cpp +++ b/libs/ultrahdr/jpegr.cpp @@ -14,13 +14,13 @@ * limitations under the License. */ -#include <jpegrecoverymap/jpegr.h> -#include <jpegrecoverymap/jpegencoderhelper.h> -#include <jpegrecoverymap/jpegdecoderhelper.h> -#include <jpegrecoverymap/recoverymapmath.h> -#include <jpegrecoverymap/jpegrutils.h> -#include <jpegrecoverymap/multipictureformat.h> -#include <jpegrecoverymap/icc.h> +#include <ultrahdr/jpegr.h> +#include <ultrahdr/jpegencoderhelper.h> +#include <ultrahdr/jpegdecoderhelper.h> +#include <ultrahdr/gainmapmath.h> +#include <ultrahdr/jpegrutils.h> +#include <ultrahdr/multipictureformat.h> +#include <ultrahdr/icc.h> #include <image_io/jpeg/jpeg_marker.h> #include <image_io/jpeg/jpeg_info.h> @@ -43,14 +43,14 @@ using namespace std; using namespace photos_editing_formats::image_io; -namespace android::jpegrecoverymap { +namespace android::ultrahdr { #define USE_SRGB_INVOETF_LUT 1 #define USE_HLG_OETF_LUT 1 #define USE_PQ_OETF_LUT 1 #define USE_HLG_INVOETF_LUT 1 #define USE_PQ_INVOETF_LUT 1 -#define USE_APPLY_RECOVERY_LUT 1 +#define USE_APPLY_GAIN_LUT 1 #define JPEGR_CHECK(x) \ { \ @@ -61,15 +61,18 @@ namespace android::jpegrecoverymap { } // The current JPEGR version that we encode to -static const uint32_t kJpegrVersion = 1; +static const char* const kJpegrVersion = "1.0"; // Map is quarter res / sixteenth size static const size_t kMapDimensionScaleFactor = 4; // JPEG block size. -// JPEG encoding / decoding will require 8 x 8 DCT transform. -// Width must be 8 dividable, and height must be 2 dividable. -static const size_t kJpegBlock = 8; -// JPEG compress quality (0 ~ 100) for recovery map +// JPEG encoding / decoding will require block based DCT transform 16 x 16 for luma, +// and 8 x 8 for chroma. +// Width must be 16 dividable for luma, and 8 dividable for chroma. +// If this criteria is not ficilitated, we will pad zeros based on the required block size. +static const size_t kJpegBlock = JpegEncoderHelper::kCompressBatchSize; +static const size_t kJpegBlockSquare = kJpegBlock * kJpegBlock; +// JPEG compress quality (0 ~ 100) for gain map static const int kMapCompressQuality = 85; #define CONFIG_MULTITHREAD 1 @@ -86,9 +89,50 @@ int GetCPUCoreCount() { return cpuCoreCount; } +status_t JpegR::areInputImagesValid(jr_uncompressed_ptr uncompressed_p010_image, + jr_uncompressed_ptr uncompressed_yuv_420_image) { + if (uncompressed_p010_image == nullptr) { + return ERROR_JPEGR_INVALID_NULL_PTR; + } + + if (uncompressed_p010_image->luma_stride != 0 + && uncompressed_p010_image->luma_stride < uncompressed_p010_image->width) { + ALOGE("Image stride can not be smaller than width, stride=%d, width=%d", + uncompressed_p010_image->luma_stride, uncompressed_p010_image->width); + return ERROR_JPEGR_INVALID_INPUT_TYPE; + } + + if (uncompressed_yuv_420_image == nullptr) { + return NO_ERROR; + } + + if (uncompressed_yuv_420_image->luma_stride != 0) { + ALOGE("Stride is not supported for YUV420 image"); + return ERROR_JPEGR_UNSUPPORTED_FEATURE; + } + + if (uncompressed_yuv_420_image->chroma_data != nullptr) { + ALOGE("Pointer to chroma plane is not supported for YUV420 image, chroma data must" + "be immediately after the luma data."); + return ERROR_JPEGR_UNSUPPORTED_FEATURE; + } + + if (uncompressed_p010_image->width != uncompressed_yuv_420_image->width + || uncompressed_p010_image->height != uncompressed_yuv_420_image->height) { + ALOGE("Image resolutions mismatch: P010: %dx%d, YUV420: %dx%d", + uncompressed_p010_image->width, + uncompressed_p010_image->height, + uncompressed_yuv_420_image->width, + uncompressed_yuv_420_image->height); + return ERROR_JPEGR_RESOLUTION_MISMATCH; + } + + return NO_ERROR; +} + /* Encode API-0 */ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, - jpegr_transfer_function hdr_tf, + ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest, int quality, jr_exif_ptr exif) { @@ -100,24 +144,27 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, return ERROR_JPEGR_INVALID_INPUT_TYPE; } - if (uncompressed_p010_image->width % kJpegBlock != 0 - || uncompressed_p010_image->height % 2 != 0) { - ALOGE("Image size can not be handled: %dx%d", - uncompressed_p010_image->width, uncompressed_p010_image->height); - return ERROR_JPEGR_INVALID_INPUT_TYPE; + if (status_t ret = areInputImagesValid( + uncompressed_p010_image, /* uncompressed_yuv_420_image */ nullptr) != NO_ERROR) { + return ret; } - jpegr_metadata_struct metadata; + ultrahdr_metadata_struct metadata; metadata.version = kJpegrVersion; jpegr_uncompressed_struct uncompressed_yuv_420_image; - unique_ptr<uint8_t[]> uncompressed_yuv_420_image_data = make_unique<uint8_t[]>( - uncompressed_p010_image->width * uncompressed_p010_image->height * 3 / 2); + size_t gain_map_length = uncompressed_p010_image->width * uncompressed_p010_image->height * 3 / 2; + // Pad a pseudo chroma block (kJpegBlock / 2) x (kJpegBlock / 2) + // if width is not kJpegBlock aligned. + if (uncompressed_p010_image->width % kJpegBlock != 0) { + gain_map_length += kJpegBlockSquare / 4; + } + unique_ptr<uint8_t[]> uncompressed_yuv_420_image_data = make_unique<uint8_t[]>(gain_map_length); uncompressed_yuv_420_image.data = uncompressed_yuv_420_image_data.get(); JPEGR_CHECK(toneMap(uncompressed_p010_image, &uncompressed_yuv_420_image)); jpegr_uncompressed_struct map; - JPEGR_CHECK(generateRecoveryMap( + JPEGR_CHECK(generateGainMap( &uncompressed_yuv_420_image, uncompressed_p010_image, hdr_tf, &metadata, &map)); std::unique_ptr<uint8_t[]> map_data; map_data.reset(reinterpret_cast<uint8_t*>(map.data)); @@ -126,9 +173,9 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, compressed_map.maxLength = map.width * map.height; unique_ptr<uint8_t[]> compressed_map_data = make_unique<uint8_t[]>(compressed_map.maxLength); compressed_map.data = compressed_map_data.get(); - JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map)); + JPEGR_CHECK(compressGainMap(&map, &compressed_map)); - sp<DataStruct> icc = IccHelper::writeIccProfile(JPEGR_TF_SRGB, + sp<DataStruct> icc = IccHelper::writeIccProfile(ULTRAHDR_TF_SRGB, uncompressed_yuv_420_image.colorGamut); JpegEncoderHelper jpeg_encoder; @@ -142,7 +189,7 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jpeg.data = jpeg_encoder.getCompressedImagePtr(); jpeg.length = jpeg_encoder.getCompressedImageSize(); - JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, exif, &metadata, dest)); + JPEGR_CHECK(appendGainMap(&jpeg, &compressed_map, exif, &metadata, dest)); return NO_ERROR; } @@ -150,7 +197,7 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, /* Encode API-1 */ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jr_uncompressed_ptr uncompressed_yuv_420_image, - jpegr_transfer_function hdr_tf, + ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest, int quality, jr_exif_ptr exif) { @@ -164,23 +211,16 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, return ERROR_JPEGR_INVALID_INPUT_TYPE; } - if (uncompressed_p010_image->width != uncompressed_yuv_420_image->width - || uncompressed_p010_image->height != uncompressed_yuv_420_image->height) { - return ERROR_JPEGR_RESOLUTION_MISMATCH; - } - - if (uncompressed_p010_image->width % kJpegBlock != 0 - || uncompressed_p010_image->height % 2 != 0) { - ALOGE("Image size can not be handled: %dx%d", - uncompressed_p010_image->width, uncompressed_p010_image->height); - return ERROR_JPEGR_INVALID_INPUT_TYPE; + if (status_t ret = areInputImagesValid( + uncompressed_p010_image, uncompressed_yuv_420_image) != NO_ERROR) { + return ret; } - jpegr_metadata_struct metadata; + ultrahdr_metadata_struct metadata; metadata.version = kJpegrVersion; jpegr_uncompressed_struct map; - JPEGR_CHECK(generateRecoveryMap( + JPEGR_CHECK(generateGainMap( uncompressed_yuv_420_image, uncompressed_p010_image, hdr_tf, &metadata, &map)); std::unique_ptr<uint8_t[]> map_data; map_data.reset(reinterpret_cast<uint8_t*>(map.data)); @@ -189,9 +229,9 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, compressed_map.maxLength = map.width * map.height; unique_ptr<uint8_t[]> compressed_map_data = make_unique<uint8_t[]>(compressed_map.maxLength); compressed_map.data = compressed_map_data.get(); - JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map)); + JPEGR_CHECK(compressGainMap(&map, &compressed_map)); - sp<DataStruct> icc = IccHelper::writeIccProfile(JPEGR_TF_SRGB, + sp<DataStruct> icc = IccHelper::writeIccProfile(ULTRAHDR_TF_SRGB, uncompressed_yuv_420_image->colorGamut); JpegEncoderHelper jpeg_encoder; @@ -205,7 +245,7 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jpeg.data = jpeg_encoder.getCompressedImagePtr(); jpeg.length = jpeg_encoder.getCompressedImageSize(); - JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, exif, &metadata, dest)); + JPEGR_CHECK(appendGainMap(&jpeg, &compressed_map, exif, &metadata, dest)); return NO_ERROR; } @@ -214,7 +254,7 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jr_uncompressed_ptr uncompressed_yuv_420_image, jr_compressed_ptr compressed_jpeg_image, - jpegr_transfer_function hdr_tf, + ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest) { if (uncompressed_p010_image == nullptr || uncompressed_yuv_420_image == nullptr @@ -223,23 +263,16 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, return ERROR_JPEGR_INVALID_NULL_PTR; } - if (uncompressed_p010_image->width != uncompressed_yuv_420_image->width - || uncompressed_p010_image->height != uncompressed_yuv_420_image->height) { - return ERROR_JPEGR_RESOLUTION_MISMATCH; + if (status_t ret = areInputImagesValid( + uncompressed_p010_image, uncompressed_yuv_420_image) != NO_ERROR) { + return ret; } - if (uncompressed_p010_image->width % kJpegBlock != 0 - || uncompressed_p010_image->height % 2 != 0) { - ALOGE("Image size can not be handled: %dx%d", - uncompressed_p010_image->width, uncompressed_p010_image->height); - return ERROR_JPEGR_INVALID_INPUT_TYPE; - } - - jpegr_metadata_struct metadata; + ultrahdr_metadata_struct metadata; metadata.version = kJpegrVersion; jpegr_uncompressed_struct map; - JPEGR_CHECK(generateRecoveryMap( + JPEGR_CHECK(generateGainMap( uncompressed_yuv_420_image, uncompressed_p010_image, hdr_tf, &metadata, &map)); std::unique_ptr<uint8_t[]> map_data; map_data.reset(reinterpret_cast<uint8_t*>(map.data)); @@ -248,9 +281,9 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, compressed_map.maxLength = map.width * map.height; unique_ptr<uint8_t[]> compressed_map_data = make_unique<uint8_t[]>(compressed_map.maxLength); compressed_map.data = compressed_map_data.get(); - JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map)); + JPEGR_CHECK(compressGainMap(&map, &compressed_map)); - JPEGR_CHECK(appendRecoveryMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest)); + JPEGR_CHECK(appendGainMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest)); return NO_ERROR; } @@ -258,7 +291,7 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, /* Encode API-3 */ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jr_compressed_ptr compressed_jpeg_image, - jpegr_transfer_function hdr_tf, + ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest) { if (uncompressed_p010_image == nullptr || compressed_jpeg_image == nullptr @@ -266,11 +299,9 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, return ERROR_JPEGR_INVALID_NULL_PTR; } - if (uncompressed_p010_image->width % kJpegBlock != 0 - || uncompressed_p010_image->height % 2 != 0) { - ALOGE("Image size can not be handled: %dx%d", - uncompressed_p010_image->width, uncompressed_p010_image->height); - return ERROR_JPEGR_INVALID_INPUT_TYPE; + if (status_t ret = areInputImagesValid( + uncompressed_p010_image, /* uncompressed_yuv_420_image */ nullptr) != NO_ERROR) { + return ret; } JpegDecoderHelper jpeg_decoder; @@ -288,11 +319,11 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, return ERROR_JPEGR_RESOLUTION_MISMATCH; } - jpegr_metadata_struct metadata; + ultrahdr_metadata_struct metadata; metadata.version = kJpegrVersion; jpegr_uncompressed_struct map; - JPEGR_CHECK(generateRecoveryMap( + JPEGR_CHECK(generateGainMap( &uncompressed_yuv_420_image, uncompressed_p010_image, hdr_tf, &metadata, &map)); std::unique_ptr<uint8_t[]> map_data; map_data.reset(reinterpret_cast<uint8_t*>(map.data)); @@ -301,21 +332,31 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, compressed_map.maxLength = map.width * map.height; unique_ptr<uint8_t[]> compressed_map_data = make_unique<uint8_t[]>(compressed_map.maxLength); compressed_map.data = compressed_map_data.get(); - JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map)); + JPEGR_CHECK(compressGainMap(&map, &compressed_map)); - JPEGR_CHECK(appendRecoveryMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest)); + JPEGR_CHECK(appendGainMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest)); return NO_ERROR; } +/* Encode API-4 */ +status_t JpegR::encodeJPEGR(jr_compressed_ptr compressed_jpeg_image, + jr_compressed_ptr compressed_gainmap, + ultrahdr_metadata_ptr metadata, + jr_compressed_ptr dest) { + JPEGR_CHECK(appendGainMap(compressed_jpeg_image, compressed_gainmap, /* exif */ nullptr, + metadata, dest)); + return NO_ERROR; +} + status_t JpegR::getJPEGRInfo(jr_compressed_ptr compressed_jpegr_image, jr_info_ptr jpegr_info) { if (compressed_jpegr_image == nullptr || jpegr_info == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; } - jpegr_compressed_struct primary_image, recovery_map; - JPEGR_CHECK(extractPrimaryImageAndRecoveryMap(compressed_jpegr_image, - &primary_image, &recovery_map)); + jpegr_compressed_struct primary_image, gain_map; + JPEGR_CHECK(extractPrimaryImageAndGainMap(compressed_jpegr_image, + &primary_image, &gain_map)); JpegDecoderHelper jpeg_decoder; if (!jpeg_decoder.getCompressedImageParameters(primary_image.data, primary_image.length, @@ -332,9 +373,9 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, jr_uncompressed_ptr dest, float max_display_boost, jr_exif_ptr exif, - jpegr_output_format output_format, - jr_uncompressed_ptr recovery_map, - jr_metadata_ptr metadata) { + ultrahdr_output_format output_format, + jr_uncompressed_ptr gain_map, + ultrahdr_metadata_ptr metadata) { if (compressed_jpegr_image == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; } @@ -343,7 +384,7 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, return ERROR_JPEGR_INVALID_INPUT_TYPE; } - if (output_format == JPEGR_OUTPUT_SDR) { + if (output_format == ULTRAHDR_OUTPUT_SDR) { JpegDecoderHelper jpeg_decoder; if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length, true)) { @@ -358,7 +399,7 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, dest->width = uncompressed_rgba_image.width; dest->height = uncompressed_rgba_image.height; - if (recovery_map == nullptr && exif == nullptr) { + if (gain_map == nullptr && exif == nullptr) { return NO_ERROR; } @@ -372,40 +413,40 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, memcpy(exif->data, jpeg_decoder.getEXIFPtr(), jpeg_decoder.getEXIFSize()); exif->length = jpeg_decoder.getEXIFSize(); } - if (recovery_map == nullptr) { + if (gain_map == nullptr) { return NO_ERROR; } } jpegr_compressed_struct compressed_map; - JPEGR_CHECK(extractRecoveryMap(compressed_jpegr_image, &compressed_map)); + JPEGR_CHECK(extractGainMap(compressed_jpegr_image, &compressed_map)); - JpegDecoderHelper recovery_map_decoder; - if (!recovery_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) { + JpegDecoderHelper gain_map_decoder; + if (!gain_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) { return ERROR_JPEGR_DECODE_ERROR; } - if (recovery_map != nullptr) { - recovery_map->width = recovery_map_decoder.getDecompressedImageWidth(); - recovery_map->height = recovery_map_decoder.getDecompressedImageHeight(); - int size = recovery_map->width * recovery_map->height; - recovery_map->data = malloc(size); - memcpy(recovery_map->data, recovery_map_decoder.getDecompressedImagePtr(), size); + if (gain_map != nullptr) { + gain_map->width = gain_map_decoder.getDecompressedImageWidth(); + gain_map->height = gain_map_decoder.getDecompressedImageHeight(); + int size = gain_map->width * gain_map->height; + gain_map->data = malloc(size); + memcpy(gain_map->data, gain_map_decoder.getDecompressedImagePtr(), size); } - jpegr_metadata_struct jr_metadata; - if (!getMetadataFromXMP(static_cast<uint8_t*>(recovery_map_decoder.getXMPPtr()), - recovery_map_decoder.getXMPSize(), &jr_metadata)) { + ultrahdr_metadata_struct uhdr_metadata; + if (!getMetadataFromXMP(static_cast<uint8_t*>(gain_map_decoder.getXMPPtr()), + gain_map_decoder.getXMPSize(), &uhdr_metadata)) { return ERROR_JPEGR_DECODE_ERROR; } if (metadata != nullptr) { - metadata->version = jr_metadata.version; - metadata->minContentBoost = jr_metadata.minContentBoost; - metadata->maxContentBoost = jr_metadata.maxContentBoost; + metadata->version = uhdr_metadata.version; + metadata->minContentBoost = uhdr_metadata.minContentBoost; + metadata->maxContentBoost = uhdr_metadata.maxContentBoost; } - if (output_format == JPEGR_OUTPUT_SDR) { + if (output_format == ULTRAHDR_OUTPUT_SDR) { return NO_ERROR; } @@ -426,30 +467,30 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, } jpegr_uncompressed_struct map; - map.data = recovery_map_decoder.getDecompressedImagePtr(); - map.width = recovery_map_decoder.getDecompressedImageWidth(); - map.height = recovery_map_decoder.getDecompressedImageHeight(); + map.data = gain_map_decoder.getDecompressedImagePtr(); + map.width = gain_map_decoder.getDecompressedImageWidth(); + map.height = gain_map_decoder.getDecompressedImageHeight(); jpegr_uncompressed_struct uncompressed_yuv_420_image; uncompressed_yuv_420_image.data = jpeg_decoder.getDecompressedImagePtr(); uncompressed_yuv_420_image.width = jpeg_decoder.getDecompressedImageWidth(); uncompressed_yuv_420_image.height = jpeg_decoder.getDecompressedImageHeight(); - JPEGR_CHECK(applyRecoveryMap(&uncompressed_yuv_420_image, &map, &jr_metadata, output_format, - max_display_boost, dest)); + JPEGR_CHECK(applyGainMap(&uncompressed_yuv_420_image, &map, &uhdr_metadata, output_format, + max_display_boost, dest)); return NO_ERROR; } -status_t JpegR::compressRecoveryMap(jr_uncompressed_ptr uncompressed_recovery_map, - jr_compressed_ptr dest) { - if (uncompressed_recovery_map == nullptr || dest == nullptr) { +status_t JpegR::compressGainMap(jr_uncompressed_ptr uncompressed_gain_map, + jr_compressed_ptr dest) { + if (uncompressed_gain_map == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; } JpegEncoderHelper jpeg_encoder; - if (!jpeg_encoder.compressImage(uncompressed_recovery_map->data, - uncompressed_recovery_map->width, - uncompressed_recovery_map->height, + if (!jpeg_encoder.compressImage(uncompressed_gain_map->data, + uncompressed_gain_map->width, + uncompressed_gain_map->height, kMapCompressQuality, nullptr, 0, @@ -463,7 +504,7 @@ status_t JpegR::compressRecoveryMap(jr_uncompressed_ptr uncompressed_recovery_ma memcpy(dest->data, jpeg_encoder.getCompressedImagePtr(), jpeg_encoder.getCompressedImageSize()); dest->length = jpeg_encoder.getCompressedImageSize(); - dest->colorGamut = JPEGR_COLORGAMUT_UNSPECIFIED; + dest->colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED; return NO_ERROR; } @@ -524,11 +565,11 @@ void JobQueue::reset() { mQueuedAllJobs = false; } -status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image, - jr_uncompressed_ptr uncompressed_p010_image, - jpegr_transfer_function hdr_tf, - jr_metadata_ptr metadata, - jr_uncompressed_ptr dest) { +status_t JpegR::generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, + jr_uncompressed_ptr uncompressed_p010_image, + ultrahdr_transfer_function hdr_tf, + ultrahdr_metadata_ptr metadata, + jr_uncompressed_ptr dest) { if (uncompressed_yuv_420_image == nullptr || uncompressed_p010_image == nullptr || metadata == nullptr @@ -541,8 +582,8 @@ status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_ima return ERROR_JPEGR_RESOLUTION_MISMATCH; } - if (uncompressed_yuv_420_image->colorGamut == JPEGR_COLORGAMUT_UNSPECIFIED - || uncompressed_p010_image->colorGamut == JPEGR_COLORGAMUT_UNSPECIFIED) { + if (uncompressed_yuv_420_image->colorGamut == ULTRAHDR_COLORGAMUT_UNSPECIFIED + || uncompressed_p010_image->colorGamut == ULTRAHDR_COLORGAMUT_UNSPECIFIED) { return ERROR_JPEGR_INVALID_COLORGAMUT; } @@ -556,7 +597,7 @@ status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_ima dest->width = map_stride; dest->height = map_height_aligned; - dest->colorGamut = JPEGR_COLORGAMUT_UNSPECIFIED; + dest->colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED; dest->data = new uint8_t[map_stride * map_height_aligned]; std::unique_ptr<uint8_t[]> map_data; map_data.reset(reinterpret_cast<uint8_t*>(dest->data)); @@ -564,10 +605,10 @@ status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_ima ColorTransformFn hdrInvOetf = nullptr; float hdr_white_nits = 0.0f; switch (hdr_tf) { - case JPEGR_TF_LINEAR: + case ULTRAHDR_TF_LINEAR: hdrInvOetf = identityConversion; break; - case JPEGR_TF_HLG: + case ULTRAHDR_TF_HLG: #if USE_HLG_INVOETF_LUT hdrInvOetf = hlgInvOetfLUT; #else @@ -575,7 +616,7 @@ status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_ima #endif hdr_white_nits = kHlgMaxNits; break; - case JPEGR_TF_PQ: + case ULTRAHDR_TF_PQ: #if USE_PQ_INVOETF_LUT hdrInvOetf = pqInvOetfLUT; #else @@ -598,16 +639,16 @@ status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_ima ColorCalculationFn luminanceFn = nullptr; switch (uncompressed_yuv_420_image->colorGamut) { - case JPEGR_COLORGAMUT_BT709: + case ULTRAHDR_COLORGAMUT_BT709: luminanceFn = srgbLuminance; break; - case JPEGR_COLORGAMUT_P3: + case ULTRAHDR_COLORGAMUT_P3: luminanceFn = p3Luminance; break; - case JPEGR_COLORGAMUT_BT2100: + case ULTRAHDR_COLORGAMUT_BT2100: luminanceFn = bt2100Luminance; break; - case JPEGR_COLORGAMUT_UNSPECIFIED: + case ULTRAHDR_COLORGAMUT_UNSPECIFIED: // Should be impossible to hit after input validation. return ERROR_JPEGR_INVALID_COLORGAMUT; } @@ -645,7 +686,7 @@ status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_ima size_t pixel_idx = x + y * dest_map_stride; reinterpret_cast<uint8_t*>(dest->data)[pixel_idx] = - encodeRecovery(sdr_y_nits, hdr_y_nits, metadata, log2MinBoost, log2MaxBoost); + encodeGain(sdr_y_nits, hdr_y_nits, metadata, log2MinBoost, log2MaxBoost); } } } @@ -671,14 +712,14 @@ status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_ima return NO_ERROR; } -status_t JpegR::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image, - jr_uncompressed_ptr uncompressed_recovery_map, - jr_metadata_ptr metadata, - jpegr_output_format output_format, - float max_display_boost, - jr_uncompressed_ptr dest) { +status_t JpegR::applyGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, + jr_uncompressed_ptr uncompressed_gain_map, + ultrahdr_metadata_ptr metadata, + ultrahdr_output_format output_format, + float max_display_boost, + jr_uncompressed_ptr dest) { if (uncompressed_yuv_420_image == nullptr - || uncompressed_recovery_map == nullptr + || uncompressed_gain_map == nullptr || metadata == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; @@ -688,12 +729,12 @@ status_t JpegR::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image, dest->height = uncompressed_yuv_420_image->height; ShepardsIDW idwTable(kMapDimensionScaleFactor); float display_boost = std::min(max_display_boost, metadata->maxContentBoost); - RecoveryLUT recoveryLUT(metadata, display_boost); + GainLUT gainLUT(metadata, display_boost); JobQueue jobQueue; - std::function<void()> applyRecMap = [uncompressed_yuv_420_image, uncompressed_recovery_map, + std::function<void()> applyRecMap = [uncompressed_yuv_420_image, uncompressed_gain_map, metadata, dest, &jobQueue, &idwTable, output_format, - &recoveryLUT, display_boost]() -> void { + &gainLUT, display_boost]() -> void { size_t width = uncompressed_yuv_420_image->width; size_t height = uncompressed_yuv_420_image->height; @@ -708,34 +749,34 @@ status_t JpegR::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image, #else Color rgb_sdr = srgbInvOetf(rgb_gamma_sdr); #endif - float recovery; + float gain; // TODO: determine map scaling factor based on actual map dims size_t map_scale_factor = kMapDimensionScaleFactor; // TODO: If map_scale_factor is guaranteed to be an integer, then remove the following. // Currently map_scale_factor is of type size_t, but it could be changed to a float // later. if (map_scale_factor != floorf(map_scale_factor)) { - recovery = sampleMap(uncompressed_recovery_map, map_scale_factor, x, y); + gain = sampleMap(uncompressed_gain_map, map_scale_factor, x, y); } else { - recovery = sampleMap(uncompressed_recovery_map, map_scale_factor, x, y, idwTable); + gain = sampleMap(uncompressed_gain_map, map_scale_factor, x, y, idwTable); } -#if USE_APPLY_RECOVERY_LUT - Color rgb_hdr = applyRecoveryLUT(rgb_sdr, recovery, recoveryLUT); +#if USE_APPLY_GAIN_LUT + Color rgb_hdr = applyGainLUT(rgb_sdr, gain, gainLUT); #else - Color rgb_hdr = applyRecovery(rgb_sdr, recovery, metadata, display_boost); + Color rgb_hdr = applyGain(rgb_sdr, gain, metadata, display_boost); #endif rgb_hdr = rgb_hdr / display_boost; size_t pixel_idx = x + y * width; switch (output_format) { - case JPEGR_OUTPUT_HDR_LINEAR: + case ULTRAHDR_OUTPUT_HDR_LINEAR: { uint64_t rgba_f16 = colorToRgbaF16(rgb_hdr); reinterpret_cast<uint64_t*>(dest->data)[pixel_idx] = rgba_f16; break; } - case JPEGR_OUTPUT_HDR_HLG: + case ULTRAHDR_OUTPUT_HDR_HLG: { #if USE_HLG_OETF_LUT ColorTransformFn hdrOetf = hlgOetfLUT; @@ -747,7 +788,7 @@ status_t JpegR::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image, reinterpret_cast<uint32_t*>(dest->data)[pixel_idx] = rgba_1010102; break; } - case JPEGR_OUTPUT_HDR_PQ: + case ULTRAHDR_OUTPUT_HDR_PQ: { #if USE_HLG_OETF_LUT ColorTransformFn hdrOetf = pqOetfLUT; @@ -785,9 +826,9 @@ status_t JpegR::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image, return NO_ERROR; } -status_t JpegR::extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_jpegr_image, - jr_compressed_ptr primary_image, - jr_compressed_ptr recovery_map) { +status_t JpegR::extractPrimaryImageAndGainMap(jr_compressed_ptr compressed_jpegr_image, + jr_compressed_ptr primary_image, + jr_compressed_ptr gain_map) { if (compressed_jpegr_image == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; } @@ -825,23 +866,23 @@ status_t JpegR::extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_j primary_image->length = image_ranges[0].GetLength(); } - if (recovery_map != nullptr) { - recovery_map->data = static_cast<uint8_t*>(compressed_jpegr_image->data) + + if (gain_map != nullptr) { + gain_map->data = static_cast<uint8_t*>(compressed_jpegr_image->data) + image_ranges[1].GetBegin(); - recovery_map->length = image_ranges[1].GetLength(); + gain_map->length = image_ranges[1].GetLength(); } return NO_ERROR; } -status_t JpegR::extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image, - jr_compressed_ptr dest) { +status_t JpegR::extractGainMap(jr_compressed_ptr compressed_jpegr_image, + jr_compressed_ptr dest) { if (compressed_jpegr_image == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; } - return extractPrimaryImageAndRecoveryMap(compressed_jpegr_image, nullptr, dest); + return extractPrimaryImageAndGainMap(compressed_jpegr_image, nullptr, dest); } // JPEG/R structure: @@ -870,20 +911,20 @@ status_t JpegR::extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image, // name space ("http://ns.adobe.com/xap/1.0/\0") // XMP // -// (Required) secondary image (the recovery map, without the first two bytes (SOI)) +// (Required) secondary image (the gain map, without the first two bytes (SOI)) // // Metadata versions we are using: // ECMA TR-98 for JFIF marker // Exif 2.2 spec for EXIF marker // Adobe XMP spec part 3 for XMP marker // ICC v4.3 spec for ICC -status_t JpegR::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, - jr_compressed_ptr compressed_recovery_map, - jr_exif_ptr exif, - jr_metadata_ptr metadata, - jr_compressed_ptr dest) { +status_t JpegR::appendGainMap(jr_compressed_ptr compressed_jpeg_image, + jr_compressed_ptr compressed_gain_map, + jr_exif_ptr exif, + ultrahdr_metadata_ptr metadata, + jr_compressed_ptr dest) { if (compressed_jpeg_image == nullptr - || compressed_recovery_map == nullptr + || compressed_gain_map == nullptr || metadata == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; @@ -900,9 +941,9 @@ status_t JpegR::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, + xmp_secondary.size(); /* length of xmp packet */ const int secondary_image_size = 2 /* 2 bytes length of APP1 sign */ + xmp_secondary_length - + compressed_recovery_map->length; + + compressed_gain_map->length; // primary image - const string xmp_primary = generateXmpForPrimaryImage(secondary_image_size); + const string xmp_primary = generateXmpForPrimaryImage(secondary_image_size, *metadata); // same as primary const int xmp_primary_length = 2 + nameSpaceLength + xmp_primary.size(); @@ -964,7 +1005,7 @@ status_t JpegR::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, (uint8_t*)compressed_jpeg_image->data + 2, compressed_jpeg_image->length - 2, pos)); // Finish primary image - // Begin secondary image (recovery map) + // Begin secondary image (gain map) // Write SOI JPEGR_CHECK(Write(dest, &photos_editing_formats::image_io::JpegMarker::kStart, 1, pos)); JPEGR_CHECK(Write(dest, &photos_editing_formats::image_io::JpegMarker::kSOI, 1, pos)); @@ -984,7 +1025,7 @@ status_t JpegR::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, // Write secondary image JPEGR_CHECK(Write(dest, - (uint8_t*)compressed_recovery_map->data + 2, compressed_recovery_map->length - 2, pos)); + (uint8_t*)compressed_gain_map->data + 2, compressed_gain_map->length - 2, pos)); // Set back length dest->length = pos; @@ -998,25 +1039,43 @@ status_t JpegR::toneMap(jr_uncompressed_ptr src, jr_uncompressed_ptr dest) { return ERROR_JPEGR_INVALID_NULL_PTR; } + size_t src_luma_stride = src->luma_stride; + size_t src_chroma_stride = src->chroma_stride; + uint16_t* src_luma_data = reinterpret_cast<uint16_t*>(src->data); + uint16_t* src_chroma_data = reinterpret_cast<uint16_t*>(src->chroma_data); + + if (src_chroma_data == nullptr) { + src_chroma_data = &reinterpret_cast<uint16_t*>(src->data)[src_luma_stride * src->height]; + } + if (src_luma_stride == 0) { + src_luma_stride = src->width; + } + if (src_chroma_stride == 0) { + src_chroma_stride = src_luma_stride; + } + dest->width = src->width; dest->height = src->height; - size_t pixel_count = src->width * src->height; + size_t dest_luma_pixel_count = dest->width * dest->height; + for (size_t y = 0; y < src->height; ++y) { for (size_t x = 0; x < src->width; ++x) { - size_t pixel_y_idx = x + y * src->width; - size_t pixel_uv_idx = x / 2 + (y / 2) * (src->width / 2); + size_t src_y_idx = y * src_luma_stride + x; + size_t src_u_idx = (y >> 1) * src_chroma_stride + (x & ~0x1); + size_t src_v_idx = src_u_idx + 1; + + uint16_t y_uint = src_luma_data[src_y_idx] >> 6; + uint16_t u_uint = src_chroma_data[src_u_idx] >> 6; + uint16_t v_uint = src_chroma_data[src_v_idx] >> 6; - uint16_t y_uint = reinterpret_cast<uint16_t*>(src->data)[pixel_y_idx] - >> 6; - uint16_t u_uint = reinterpret_cast<uint16_t*>(src->data)[pixel_count + pixel_uv_idx * 2] - >> 6; - uint16_t v_uint = reinterpret_cast<uint16_t*>(src->data)[pixel_count + pixel_uv_idx * 2 + 1] - >> 6; + size_t dest_y_idx = x + y * dest->width; + size_t dest_uv_idx = x / 2 + (y / 2) * (dest->width / 2); - uint8_t* y = &reinterpret_cast<uint8_t*>(dest->data)[pixel_y_idx]; - uint8_t* u = &reinterpret_cast<uint8_t*>(dest->data)[pixel_count + pixel_uv_idx]; - uint8_t* v = &reinterpret_cast<uint8_t*>(dest->data)[pixel_count * 5 / 4 + pixel_uv_idx]; + uint8_t* y = &reinterpret_cast<uint8_t*>(dest->data)[dest_y_idx]; + uint8_t* u = &reinterpret_cast<uint8_t*>(dest->data)[dest_luma_pixel_count + dest_uv_idx]; + uint8_t* v = &reinterpret_cast<uint8_t*>( + dest->data)[dest_luma_pixel_count * 5 / 4 + dest_uv_idx]; *y = static_cast<uint8_t>((y_uint >> 2) & 0xff); *u = static_cast<uint8_t>((u_uint >> 2) & 0xff); @@ -1029,4 +1088,4 @@ status_t JpegR::toneMap(jr_uncompressed_ptr src, jr_uncompressed_ptr dest) { return NO_ERROR; } -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr diff --git a/libs/jpegrecoverymap/jpegrutils.cpp b/libs/ultrahdr/jpegrutils.cpp index cde0ceb520..6430af12c7 100644 --- a/libs/jpegrecoverymap/jpegrutils.cpp +++ b/libs/ultrahdr/jpegrutils.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <jpegrecoverymap/jpegrutils.h> +#include <ultrahdr/jpegrutils.h> #include <algorithm> #include <cmath> @@ -30,7 +30,7 @@ using namespace photos_editing_formats::image_io; using namespace std; -namespace android::jpegrecoverymap { +namespace android::ultrahdr { /* * Helper function used for generating XMP metadata. * @@ -256,7 +256,7 @@ const string kMapBaseRenditionIsHDR = Name(kGainMapPrefix, "BaseRenditionIsHDR") const string XMPXmlHandler::minContentBoostAttrName = kMapGainMapMin; const string XMPXmlHandler::maxContentBoostAttrName = kMapGainMapMax; -bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata_struct* metadata) { +bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, ultrahdr_metadata_struct* metadata) { string nameSpace = "http://ns.adobe.com/xap/1.0/\0"; if (xmp_size < nameSpace.size()+2) { @@ -302,7 +302,7 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata_struc return true; } -string generateXmpForPrimaryImage(int secondary_image_length) { +string generateXmpForPrimaryImage(int secondary_image_length, ultrahdr_metadata_struct& metadata) { const vector<string> kConDirSeq({kConDirectory, string("rdf:Seq")}); const vector<string> kLiItem({string("rdf:li"), kConItem}); @@ -316,6 +316,8 @@ string generateXmpForPrimaryImage(int secondary_image_length) { writer.StartWritingElement("rdf:Description"); writer.WriteXmlns(kContainerPrefix, kContainerUri); writer.WriteXmlns(kItemPrefix, kItemUri); + writer.WriteXmlns(kGainMapPrefix, kGainMapUri); + writer.WriteAttributeNameAndValue(kMapVersion, metadata.version); writer.StartWritingElements(kConDirSeq); @@ -338,7 +340,7 @@ string generateXmpForPrimaryImage(int secondary_image_length) { return ss.str(); } -string generateXmpForSecondaryImage(jpegr_metadata_struct& metadata) { +string generateXmpForSecondaryImage(ultrahdr_metadata_struct& metadata) { const vector<string> kConDirSeq({kConDirectory, string("rdf:Seq")}); std::stringstream ss; @@ -365,4 +367,4 @@ string generateXmpForSecondaryImage(jpegr_metadata_struct& metadata) { return ss.str(); } -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr diff --git a/libs/jpegrecoverymap/multipictureformat.cpp b/libs/ultrahdr/multipictureformat.cpp index a219aef106..7a265c61b7 100644 --- a/libs/jpegrecoverymap/multipictureformat.cpp +++ b/libs/ultrahdr/multipictureformat.cpp @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include <jpegrecoverymap/multipictureformat.h> -#include <jpegrecoverymap/jpegrutils.h> +#include <ultrahdr/multipictureformat.h> +#include <ultrahdr/jpegrutils.h> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { size_t calculateMpfSize() { return sizeof(kMpfSig) + // Signature kMpEndianSize + // Endianness @@ -91,4 +91,4 @@ sp<DataStruct> generateMpf(int primary_image_size, int primary_image_offset, return dataStruct; } -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr diff --git a/libs/jpegrecoverymap/tests/Android.bp b/libs/ultrahdr/tests/Android.bp index d5da7fb646..7dd9d04fbd 100644 --- a/libs/jpegrecoverymap/tests/Android.bp +++ b/libs/ultrahdr/tests/Android.bp @@ -22,11 +22,11 @@ package { } cc_test { - name: "libjpegrecoverymap_test", + name: "libultrahdr_test", test_suites: ["device-tests"], srcs: [ "jpegr_test.cpp", - "recoverymapmath_test.cpp", + "gainmapmath_test.cpp", ], shared_libs: [ "libimage_io", @@ -38,7 +38,7 @@ cc_test { "libgtest", "libjpegdecoder", "libjpegencoder", - "libjpegrecoverymap", + "libultrahdr", "libutils", ], } diff --git a/libs/jpegrecoverymap/tests/data/jpeg_image.jpg b/libs/ultrahdr/tests/data/jpeg_image.jpg Binary files differindex e2857425e7..e2857425e7 100644 --- a/libs/jpegrecoverymap/tests/data/jpeg_image.jpg +++ b/libs/ultrahdr/tests/data/jpeg_image.jpg diff --git a/libs/jpegrecoverymap/tests/data/minnie-318x240.yu12 b/libs/ultrahdr/tests/data/minnie-318x240.yu12 index 7b2fc71bc0..7b2fc71bc0 100644 --- a/libs/jpegrecoverymap/tests/data/minnie-318x240.yu12 +++ b/libs/ultrahdr/tests/data/minnie-318x240.yu12 diff --git a/libs/jpegrecoverymap/tests/data/minnie-320x240-y.jpg b/libs/ultrahdr/tests/data/minnie-320x240-y.jpg Binary files differindex 20b5a2c0df..20b5a2c0df 100644 --- a/libs/jpegrecoverymap/tests/data/minnie-320x240-y.jpg +++ b/libs/ultrahdr/tests/data/minnie-320x240-y.jpg diff --git a/libs/jpegrecoverymap/tests/data/minnie-320x240-yuv.jpg b/libs/ultrahdr/tests/data/minnie-320x240-yuv.jpg Binary files differindex 41300f47f1..41300f47f1 100644 --- a/libs/jpegrecoverymap/tests/data/minnie-320x240-yuv.jpg +++ b/libs/ultrahdr/tests/data/minnie-320x240-yuv.jpg diff --git a/libs/jpegrecoverymap/tests/data/minnie-320x240.y b/libs/ultrahdr/tests/data/minnie-320x240.y index f9d8371c18..f9d8371c18 100644 --- a/libs/jpegrecoverymap/tests/data/minnie-320x240.y +++ b/libs/ultrahdr/tests/data/minnie-320x240.y diff --git a/libs/jpegrecoverymap/tests/data/minnie-320x240.yu12 b/libs/ultrahdr/tests/data/minnie-320x240.yu12 index 0d66f53029..0d66f53029 100644 --- a/libs/jpegrecoverymap/tests/data/minnie-320x240.yu12 +++ b/libs/ultrahdr/tests/data/minnie-320x240.yu12 diff --git a/libs/jpegrecoverymap/tests/data/raw_p010_image.p010 b/libs/ultrahdr/tests/data/raw_p010_image.p010 Binary files differindex 01673bf6d5..01673bf6d5 100644 --- a/libs/jpegrecoverymap/tests/data/raw_p010_image.p010 +++ b/libs/ultrahdr/tests/data/raw_p010_image.p010 diff --git a/libs/ultrahdr/tests/data/raw_p010_image_with_stride.p010 b/libs/ultrahdr/tests/data/raw_p010_image_with_stride.p010 Binary files differnew file mode 100644 index 0000000000..e7a5dc84dc --- /dev/null +++ b/libs/ultrahdr/tests/data/raw_p010_image_with_stride.p010 diff --git a/libs/jpegrecoverymap/tests/data/raw_yuv420_image.yuv420 b/libs/ultrahdr/tests/data/raw_yuv420_image.yuv420 index c043da6423..c043da6423 100644 --- a/libs/jpegrecoverymap/tests/data/raw_yuv420_image.yuv420 +++ b/libs/ultrahdr/tests/data/raw_yuv420_image.yuv420 diff --git a/libs/jpegrecoverymap/tests/recoverymapmath_test.cpp b/libs/ultrahdr/tests/gainmapmath_test.cpp index 2369a7e4e7..c456653821 100644 --- a/libs/jpegrecoverymap/tests/recoverymapmath_test.cpp +++ b/libs/ultrahdr/tests/gainmapmath_test.cpp @@ -17,14 +17,14 @@ #include <cmath> #include <gtest/gtest.h> #include <gmock/gmock.h> -#include <jpegrecoverymap/recoverymapmath.h> +#include <ultrahdr/gainmapmath.h> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { -class RecoveryMapMathTest : public testing::Test { +class GainMapMathTest : public testing::Test { public: - RecoveryMapMathTest(); - ~RecoveryMapMathTest(); + GainMapMathTest(); + ~GainMapMathTest(); float ComparisonEpsilon() { return 1e-4f; } float LuminanceEpsilon() { return 1e-2f; } @@ -88,10 +88,10 @@ public: return luminance_scaled * scale_factor; } - Color Recover(Color yuv_gamma, float recovery, jr_metadata_ptr metadata) { + Color Recover(Color yuv_gamma, float gain, ultrahdr_metadata_ptr metadata) { Color rgb_gamma = srgbYuvToRgb(yuv_gamma); Color rgb = srgbInvOetf(rgb_gamma); - return applyRecovery(rgb, recovery, metadata); + return applyGain(rgb, gain, metadata); } jpegr_uncompressed_struct Yuv420Image() { @@ -108,7 +108,7 @@ public: 0xB0, 0xB1, 0xB2, 0xB3, }; - return { pixels, 4, 4, JPEGR_COLORGAMUT_BT709 }; + return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709 }; } Color (*Yuv420Colors())[4] { @@ -141,7 +141,7 @@ public: 0xA0 << 6, 0xB0 << 6, 0xA1 << 6, 0xB1 << 6, 0xA2 << 6, 0xB2 << 6, 0xA3 << 6, 0xB3 << 6, }; - return { pixels, 4, 4, JPEGR_COLORGAMUT_BT709 }; + return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709 }; } Color (*P010Colors())[4] { @@ -170,7 +170,7 @@ public: 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, }; - return { pixels, 4, 4, JPEGR_COLORGAMUT_UNSPECIFIED }; + return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_UNSPECIFIED }; } float (*MapValues())[4] { @@ -193,11 +193,11 @@ protected: virtual void TearDown(); }; -RecoveryMapMathTest::RecoveryMapMathTest() {} -RecoveryMapMathTest::~RecoveryMapMathTest() {} +GainMapMathTest::GainMapMathTest() {} +GainMapMathTest::~GainMapMathTest() {} -void RecoveryMapMathTest::SetUp() {} -void RecoveryMapMathTest::TearDown() {} +void GainMapMathTest::SetUp() {} +void GainMapMathTest::TearDown() {} #define EXPECT_RGB_EQ(e1, e2) \ EXPECT_FLOAT_EQ((e1).r, (e2).r); \ @@ -231,7 +231,7 @@ void RecoveryMapMathTest::TearDown() {} // TODO: a bunch of these tests can be parameterized. -TEST_F(RecoveryMapMathTest, ColorConstruct) { +TEST_F(GainMapMathTest, ColorConstruct) { Color e1 = {{{ 0.1f, 0.2f, 0.3f }}}; EXPECT_FLOAT_EQ(e1.r, 0.1f); @@ -243,7 +243,7 @@ TEST_F(RecoveryMapMathTest, ColorConstruct) { EXPECT_FLOAT_EQ(e1.v, 0.3f); } -TEST_F(RecoveryMapMathTest, ColorAddColor) { +TEST_F(GainMapMathTest, ColorAddColor) { Color e1 = {{{ 0.1f, 0.2f, 0.3f }}}; Color e2 = e1 + e1; @@ -257,7 +257,7 @@ TEST_F(RecoveryMapMathTest, ColorAddColor) { EXPECT_FLOAT_EQ(e2.b, e1.b * 3.0f); } -TEST_F(RecoveryMapMathTest, ColorAddFloat) { +TEST_F(GainMapMathTest, ColorAddFloat) { Color e1 = {{{ 0.1f, 0.2f, 0.3f }}}; Color e2 = e1 + 0.1f; @@ -271,7 +271,7 @@ TEST_F(RecoveryMapMathTest, ColorAddFloat) { EXPECT_FLOAT_EQ(e2.b, e1.b + 0.2f); } -TEST_F(RecoveryMapMathTest, ColorSubtractColor) { +TEST_F(GainMapMathTest, ColorSubtractColor) { Color e1 = {{{ 0.1f, 0.2f, 0.3f }}}; Color e2 = e1 - e1; @@ -285,7 +285,7 @@ TEST_F(RecoveryMapMathTest, ColorSubtractColor) { EXPECT_FLOAT_EQ(e2.b, -e1.b); } -TEST_F(RecoveryMapMathTest, ColorSubtractFloat) { +TEST_F(GainMapMathTest, ColorSubtractFloat) { Color e1 = {{{ 0.1f, 0.2f, 0.3f }}}; Color e2 = e1 - 0.1f; @@ -299,7 +299,7 @@ TEST_F(RecoveryMapMathTest, ColorSubtractFloat) { EXPECT_FLOAT_EQ(e2.b, e1.b - 0.2f); } -TEST_F(RecoveryMapMathTest, ColorMultiplyFloat) { +TEST_F(GainMapMathTest, ColorMultiplyFloat) { Color e1 = {{{ 0.1f, 0.2f, 0.3f }}}; Color e2 = e1 * 2.0f; @@ -313,7 +313,7 @@ TEST_F(RecoveryMapMathTest, ColorMultiplyFloat) { EXPECT_FLOAT_EQ(e2.b, e1.b * 4.0f); } -TEST_F(RecoveryMapMathTest, ColorDivideFloat) { +TEST_F(GainMapMathTest, ColorDivideFloat) { Color e1 = {{{ 0.1f, 0.2f, 0.3f }}}; Color e2 = e1 / 2.0f; @@ -327,7 +327,7 @@ TEST_F(RecoveryMapMathTest, ColorDivideFloat) { EXPECT_FLOAT_EQ(e2.b, e1.b / 4.0f); } -TEST_F(RecoveryMapMathTest, SrgbLuminance) { +TEST_F(GainMapMathTest, SrgbLuminance) { EXPECT_FLOAT_EQ(srgbLuminance(RgbBlack()), 0.0f); EXPECT_FLOAT_EQ(srgbLuminance(RgbWhite()), 1.0f); EXPECT_FLOAT_EQ(srgbLuminance(RgbRed()), 0.2126f); @@ -335,7 +335,7 @@ TEST_F(RecoveryMapMathTest, SrgbLuminance) { EXPECT_FLOAT_EQ(srgbLuminance(RgbBlue()), 0.0722f); } -TEST_F(RecoveryMapMathTest, SrgbYuvToRgb) { +TEST_F(GainMapMathTest, SrgbYuvToRgb) { Color rgb_black = srgbYuvToRgb(YuvBlack()); EXPECT_RGB_NEAR(rgb_black, RgbBlack()); @@ -352,7 +352,7 @@ TEST_F(RecoveryMapMathTest, SrgbYuvToRgb) { EXPECT_RGB_NEAR(rgb_b, RgbBlue()); } -TEST_F(RecoveryMapMathTest, SrgbRgbToYuv) { +TEST_F(GainMapMathTest, SrgbRgbToYuv) { Color yuv_black = srgbRgbToYuv(RgbBlack()); EXPECT_YUV_NEAR(yuv_black, YuvBlack()); @@ -369,7 +369,7 @@ TEST_F(RecoveryMapMathTest, SrgbRgbToYuv) { EXPECT_YUV_NEAR(yuv_b, SrgbYuvBlue()); } -TEST_F(RecoveryMapMathTest, SrgbRgbYuvRoundtrip) { +TEST_F(GainMapMathTest, SrgbRgbYuvRoundtrip) { Color rgb_black = srgbYuvToRgb(srgbRgbToYuv(RgbBlack())); EXPECT_RGB_NEAR(rgb_black, RgbBlack()); @@ -386,7 +386,7 @@ TEST_F(RecoveryMapMathTest, SrgbRgbYuvRoundtrip) { EXPECT_RGB_NEAR(rgb_b, RgbBlue()); } -TEST_F(RecoveryMapMathTest, SrgbTransferFunction) { +TEST_F(GainMapMathTest, SrgbTransferFunction) { EXPECT_FLOAT_EQ(srgbInvOetf(0.0f), 0.0f); EXPECT_NEAR(srgbInvOetf(0.02f), 0.00154f, ComparisonEpsilon()); EXPECT_NEAR(srgbInvOetf(0.04045f), 0.00313f, ComparisonEpsilon()); @@ -394,7 +394,7 @@ TEST_F(RecoveryMapMathTest, SrgbTransferFunction) { EXPECT_FLOAT_EQ(srgbInvOetf(1.0f), 1.0f); } -TEST_F(RecoveryMapMathTest, P3Luminance) { +TEST_F(GainMapMathTest, P3Luminance) { EXPECT_FLOAT_EQ(p3Luminance(RgbBlack()), 0.0f); EXPECT_FLOAT_EQ(p3Luminance(RgbWhite()), 1.0f); EXPECT_FLOAT_EQ(p3Luminance(RgbRed()), 0.20949f); @@ -402,7 +402,7 @@ TEST_F(RecoveryMapMathTest, P3Luminance) { EXPECT_FLOAT_EQ(p3Luminance(RgbBlue()), 0.06891f); } -TEST_F(RecoveryMapMathTest, Bt2100Luminance) { +TEST_F(GainMapMathTest, Bt2100Luminance) { EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlack()), 0.0f); EXPECT_FLOAT_EQ(bt2100Luminance(RgbWhite()), 1.0f); EXPECT_FLOAT_EQ(bt2100Luminance(RgbRed()), 0.2627f); @@ -410,7 +410,7 @@ TEST_F(RecoveryMapMathTest, Bt2100Luminance) { EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlue()), 0.0593f); } -TEST_F(RecoveryMapMathTest, Bt2100YuvToRgb) { +TEST_F(GainMapMathTest, Bt2100YuvToRgb) { Color rgb_black = bt2100YuvToRgb(YuvBlack()); EXPECT_RGB_NEAR(rgb_black, RgbBlack()); @@ -427,7 +427,7 @@ TEST_F(RecoveryMapMathTest, Bt2100YuvToRgb) { EXPECT_RGB_NEAR(rgb_b, RgbBlue()); } -TEST_F(RecoveryMapMathTest, Bt2100RgbToYuv) { +TEST_F(GainMapMathTest, Bt2100RgbToYuv) { Color yuv_black = bt2100RgbToYuv(RgbBlack()); EXPECT_YUV_NEAR(yuv_black, YuvBlack()); @@ -444,7 +444,7 @@ TEST_F(RecoveryMapMathTest, Bt2100RgbToYuv) { EXPECT_YUV_NEAR(yuv_b, Bt2100YuvBlue()); } -TEST_F(RecoveryMapMathTest, Bt2100RgbYuvRoundtrip) { +TEST_F(GainMapMathTest, Bt2100RgbYuvRoundtrip) { Color rgb_black = bt2100YuvToRgb(bt2100RgbToYuv(RgbBlack())); EXPECT_RGB_NEAR(rgb_black, RgbBlack()); @@ -461,7 +461,7 @@ TEST_F(RecoveryMapMathTest, Bt2100RgbYuvRoundtrip) { EXPECT_RGB_NEAR(rgb_b, RgbBlue()); } -TEST_F(RecoveryMapMathTest, HlgOetf) { +TEST_F(GainMapMathTest, HlgOetf) { EXPECT_FLOAT_EQ(hlgOetf(0.0f), 0.0f); EXPECT_NEAR(hlgOetf(0.04167f), 0.35357f, ComparisonEpsilon()); EXPECT_NEAR(hlgOetf(0.08333f), 0.5f, ComparisonEpsilon()); @@ -473,7 +473,7 @@ TEST_F(RecoveryMapMathTest, HlgOetf) { EXPECT_RGB_NEAR(hlgOetf(e), e_gamma); } -TEST_F(RecoveryMapMathTest, HlgInvOetf) { +TEST_F(GainMapMathTest, HlgInvOetf) { EXPECT_FLOAT_EQ(hlgInvOetf(0.0f), 0.0f); EXPECT_NEAR(hlgInvOetf(0.25f), 0.02083f, ComparisonEpsilon()); EXPECT_NEAR(hlgInvOetf(0.5f), 0.08333f, ComparisonEpsilon()); @@ -485,7 +485,7 @@ TEST_F(RecoveryMapMathTest, HlgInvOetf) { EXPECT_RGB_NEAR(hlgInvOetf(e_gamma), e); } -TEST_F(RecoveryMapMathTest, HlgTransferFunctionRoundtrip) { +TEST_F(GainMapMathTest, HlgTransferFunctionRoundtrip) { EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(0.0f)), 0.0f); EXPECT_NEAR(hlgInvOetf(hlgOetf(0.04167f)), 0.04167f, ComparisonEpsilon()); EXPECT_NEAR(hlgInvOetf(hlgOetf(0.08333f)), 0.08333f, ComparisonEpsilon()); @@ -493,7 +493,7 @@ TEST_F(RecoveryMapMathTest, HlgTransferFunctionRoundtrip) { EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(1.0f)), 1.0f); } -TEST_F(RecoveryMapMathTest, PqOetf) { +TEST_F(GainMapMathTest, PqOetf) { EXPECT_FLOAT_EQ(pqOetf(0.0f), 0.0f); EXPECT_NEAR(pqOetf(0.01f), 0.50808f, ComparisonEpsilon()); EXPECT_NEAR(pqOetf(0.5f), 0.92655f, ComparisonEpsilon()); @@ -505,7 +505,7 @@ TEST_F(RecoveryMapMathTest, PqOetf) { EXPECT_RGB_NEAR(pqOetf(e), e_gamma); } -TEST_F(RecoveryMapMathTest, PqInvOetf) { +TEST_F(GainMapMathTest, PqInvOetf) { EXPECT_FLOAT_EQ(pqInvOetf(0.0f), 0.0f); EXPECT_NEAR(pqInvOetf(0.01f), 2.31017e-7f, ComparisonEpsilon()); EXPECT_NEAR(pqInvOetf(0.5f), 0.00922f, ComparisonEpsilon()); @@ -517,135 +517,135 @@ TEST_F(RecoveryMapMathTest, PqInvOetf) { EXPECT_RGB_NEAR(pqInvOetf(e_gamma), e); } -TEST_F(RecoveryMapMathTest, PqInvOetfLUT) { +TEST_F(GainMapMathTest, PqInvOetfLUT) { for (int idx = 0; idx < kPqInvOETFNumEntries; idx++) { float value = static_cast<float>(idx) / static_cast<float>(kPqInvOETFNumEntries - 1); EXPECT_FLOAT_EQ(pqInvOetf(value), pqInvOetfLUT(value)); } } -TEST_F(RecoveryMapMathTest, HlgInvOetfLUT) { +TEST_F(GainMapMathTest, HlgInvOetfLUT) { for (int idx = 0; idx < kHlgInvOETFNumEntries; idx++) { float value = static_cast<float>(idx) / static_cast<float>(kHlgInvOETFNumEntries - 1); EXPECT_FLOAT_EQ(hlgInvOetf(value), hlgInvOetfLUT(value)); } } -TEST_F(RecoveryMapMathTest, pqOetfLUT) { +TEST_F(GainMapMathTest, pqOetfLUT) { for (int idx = 0; idx < kPqOETFNumEntries; idx++) { float value = static_cast<float>(idx) / static_cast<float>(kPqOETFNumEntries - 1); EXPECT_FLOAT_EQ(pqOetf(value), pqOetfLUT(value)); } } -TEST_F(RecoveryMapMathTest, hlgOetfLUT) { +TEST_F(GainMapMathTest, hlgOetfLUT) { for (int idx = 0; idx < kHlgOETFNumEntries; idx++) { float value = static_cast<float>(idx) / static_cast<float>(kHlgOETFNumEntries - 1); EXPECT_FLOAT_EQ(hlgOetf(value), hlgOetfLUT(value)); } } -TEST_F(RecoveryMapMathTest, srgbInvOetfLUT) { +TEST_F(GainMapMathTest, srgbInvOetfLUT) { for (int idx = 0; idx < kSrgbInvOETFNumEntries; idx++) { float value = static_cast<float>(idx) / static_cast<float>(kSrgbInvOETFNumEntries - 1); EXPECT_FLOAT_EQ(srgbInvOetf(value), srgbInvOetfLUT(value)); } } -TEST_F(RecoveryMapMathTest, applyRecoveryLUT) { +TEST_F(GainMapMathTest, applyGainLUT) { for (int boost = 1; boost <= 10; boost++) { - jpegr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost), + ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost), .minContentBoost = 1.0f / static_cast<float>(boost) }; - RecoveryLUT recoveryLUT(&metadata); - RecoveryLUT recoveryLUTWithBoost(&metadata, metadata.maxContentBoost); - for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) { - float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1); - EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), value, &metadata), - applyRecoveryLUT(RgbBlack(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), value, &metadata), - applyRecoveryLUT(RgbWhite(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbRed(), value, &metadata), - applyRecoveryLUT(RgbRed(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbGreen(), value, &metadata), - applyRecoveryLUT(RgbGreen(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbBlue(), value, &metadata), - applyRecoveryLUT(RgbBlue(), value, recoveryLUT)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlack(), value, recoveryLUT), - applyRecoveryLUT(RgbBlack(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbWhite(), value, recoveryLUT), - applyRecoveryLUT(RgbWhite(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbRed(), value, recoveryLUT), - applyRecoveryLUT(RgbRed(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbGreen(), value, recoveryLUT), - applyRecoveryLUT(RgbGreen(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlue(), value, recoveryLUT), - applyRecoveryLUT(RgbBlue(), value, recoveryLUTWithBoost)); + GainLUT gainLUT(&metadata); + GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost); + for (int idx = 0; idx < kGainFactorNumEntries; idx++) { + float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1); + EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata), + applyGainLUT(RgbBlack(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata), + applyGainLUT(RgbWhite(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata), + applyGainLUT(RgbRed(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata), + applyGainLUT(RgbGreen(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata), + applyGainLUT(RgbBlue(), value, gainLUT)); + EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT), + applyGainLUT(RgbBlack(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT), + applyGainLUT(RgbWhite(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT), + applyGainLUT(RgbRed(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT), + applyGainLUT(RgbGreen(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT), + applyGainLUT(RgbBlue(), value, gainLUTWithBoost)); } } for (int boost = 1; boost <= 10; boost++) { - jpegr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost), + ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost), .minContentBoost = 1.0f }; - RecoveryLUT recoveryLUT(&metadata); - RecoveryLUT recoveryLUTWithBoost(&metadata, metadata.maxContentBoost); - for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) { - float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1); - EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), value, &metadata), - applyRecoveryLUT(RgbBlack(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), value, &metadata), - applyRecoveryLUT(RgbWhite(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbRed(), value, &metadata), - applyRecoveryLUT(RgbRed(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbGreen(), value, &metadata), - applyRecoveryLUT(RgbGreen(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbBlue(), value, &metadata), - applyRecoveryLUT(RgbBlue(), value, recoveryLUT)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlack(), value, recoveryLUT), - applyRecoveryLUT(RgbBlack(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbWhite(), value, recoveryLUT), - applyRecoveryLUT(RgbWhite(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbRed(), value, recoveryLUT), - applyRecoveryLUT(RgbRed(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbGreen(), value, recoveryLUT), - applyRecoveryLUT(RgbGreen(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlue(), value, recoveryLUT), - applyRecoveryLUT(RgbBlue(), value, recoveryLUTWithBoost)); + GainLUT gainLUT(&metadata); + GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost); + for (int idx = 0; idx < kGainFactorNumEntries; idx++) { + float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1); + EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata), + applyGainLUT(RgbBlack(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata), + applyGainLUT(RgbWhite(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata), + applyGainLUT(RgbRed(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata), + applyGainLUT(RgbGreen(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata), + applyGainLUT(RgbBlue(), value, gainLUT)); + EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT), + applyGainLUT(RgbBlack(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT), + applyGainLUT(RgbWhite(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT), + applyGainLUT(RgbRed(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT), + applyGainLUT(RgbGreen(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT), + applyGainLUT(RgbBlue(), value, gainLUTWithBoost)); } } for (int boost = 1; boost <= 10; boost++) { - jpegr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost), + ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost), .minContentBoost = 1.0f / pow(static_cast<float>(boost), 1.0f / 3.0f) }; - RecoveryLUT recoveryLUT(&metadata); - RecoveryLUT recoveryLUTWithBoost(&metadata, metadata.maxContentBoost); - for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) { - float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1); - EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), value, &metadata), - applyRecoveryLUT(RgbBlack(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), value, &metadata), - applyRecoveryLUT(RgbWhite(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbRed(), value, &metadata), - applyRecoveryLUT(RgbRed(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbGreen(), value, &metadata), - applyRecoveryLUT(RgbGreen(), value, recoveryLUT)); - EXPECT_RGB_NEAR(applyRecovery(RgbBlue(), value, &metadata), - applyRecoveryLUT(RgbBlue(), value, recoveryLUT)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlack(), value, recoveryLUT), - applyRecoveryLUT(RgbBlack(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbWhite(), value, recoveryLUT), - applyRecoveryLUT(RgbWhite(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbRed(), value, recoveryLUT), - applyRecoveryLUT(RgbRed(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbGreen(), value, recoveryLUT), - applyRecoveryLUT(RgbGreen(), value, recoveryLUTWithBoost)); - EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlue(), value, recoveryLUT), - applyRecoveryLUT(RgbBlue(), value, recoveryLUTWithBoost)); + GainLUT gainLUT(&metadata); + GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost); + for (int idx = 0; idx < kGainFactorNumEntries; idx++) { + float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1); + EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata), + applyGainLUT(RgbBlack(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata), + applyGainLUT(RgbWhite(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata), + applyGainLUT(RgbRed(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata), + applyGainLUT(RgbGreen(), value, gainLUT)); + EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata), + applyGainLUT(RgbBlue(), value, gainLUT)); + EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT), + applyGainLUT(RgbBlack(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT), + applyGainLUT(RgbWhite(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT), + applyGainLUT(RgbRed(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT), + applyGainLUT(RgbGreen(), value, gainLUTWithBoost)); + EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT), + applyGainLUT(RgbBlue(), value, gainLUTWithBoost)); } } } -TEST_F(RecoveryMapMathTest, PqTransferFunctionRoundtrip) { +TEST_F(GainMapMathTest, PqTransferFunctionRoundtrip) { EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(0.0f)), 0.0f); EXPECT_NEAR(pqInvOetf(pqOetf(0.01f)), 0.01f, ComparisonEpsilon()); EXPECT_NEAR(pqInvOetf(pqOetf(0.5f)), 0.5f, ComparisonEpsilon()); @@ -653,177 +653,177 @@ TEST_F(RecoveryMapMathTest, PqTransferFunctionRoundtrip) { EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(1.0f)), 1.0f); } -TEST_F(RecoveryMapMathTest, ColorConversionLookup) { - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_UNSPECIFIED), +TEST_F(GainMapMathTest, ColorConversionLookup) { + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_UNSPECIFIED), nullptr); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_BT709), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT709), identityConversion); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_P3), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3), p3ToBt709); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_BT2100), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT2100), bt2100ToBt709); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_UNSPECIFIED), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_UNSPECIFIED), nullptr); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_BT709), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT709), bt709ToP3); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_P3), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_P3), identityConversion); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_BT2100), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100), bt2100ToP3); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_UNSPECIFIED), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_UNSPECIFIED), nullptr); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_BT709), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT709), bt709ToBt2100); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_P3), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_P3), p3ToBt2100); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_BT2100), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT2100), identityConversion); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_UNSPECIFIED), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_UNSPECIFIED), nullptr); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_BT709), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT709), nullptr); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_P3), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_P3), nullptr); - EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_BT2100), + EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT2100), nullptr); } -TEST_F(RecoveryMapMathTest, EncodeRecovery) { - jpegr_metadata_struct metadata = { .maxContentBoost = 4.0f, +TEST_F(GainMapMathTest, EncodeGain) { + ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f, .minContentBoost = 1.0f / 4.0f }; - EXPECT_EQ(encodeRecovery(0.0f, 0.0f, &metadata), 127); - EXPECT_EQ(encodeRecovery(0.0f, 1.0f, &metadata), 127); - EXPECT_EQ(encodeRecovery(1.0f, 0.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(0.5f, 0.0f, &metadata), 0); + EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 127); + EXPECT_EQ(encodeGain(0.0f, 1.0f, &metadata), 127); + EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0); + EXPECT_EQ(encodeGain(0.5f, 0.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(1.0f, 1.0f, &metadata), 127); - EXPECT_EQ(encodeRecovery(1.0f, 4.0f, &metadata), 255); - EXPECT_EQ(encodeRecovery(1.0f, 5.0f, &metadata), 255); - EXPECT_EQ(encodeRecovery(4.0f, 1.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(4.0f, 0.5f, &metadata), 0); - EXPECT_EQ(encodeRecovery(1.0f, 2.0f, &metadata), 191); - EXPECT_EQ(encodeRecovery(2.0f, 1.0f, &metadata), 63); + EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 127); + EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 255); + EXPECT_EQ(encodeGain(1.0f, 5.0f, &metadata), 255); + EXPECT_EQ(encodeGain(4.0f, 1.0f, &metadata), 0); + EXPECT_EQ(encodeGain(4.0f, 0.5f, &metadata), 0); + EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 191); + EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 63); metadata.maxContentBoost = 2.0f; metadata.minContentBoost = 1.0f / 2.0f; - EXPECT_EQ(encodeRecovery(1.0f, 2.0f, &metadata), 255); - EXPECT_EQ(encodeRecovery(2.0f, 1.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(1.0f, 1.41421f, &metadata), 191); - EXPECT_EQ(encodeRecovery(1.41421f, 1.0f, &metadata), 63); + EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 255); + EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 0); + EXPECT_EQ(encodeGain(1.0f, 1.41421f, &metadata), 191); + EXPECT_EQ(encodeGain(1.41421f, 1.0f, &metadata), 63); metadata.maxContentBoost = 8.0f; metadata.minContentBoost = 1.0f / 8.0f; - EXPECT_EQ(encodeRecovery(1.0f, 8.0f, &metadata), 255); - EXPECT_EQ(encodeRecovery(8.0f, 1.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(1.0f, 2.82843f, &metadata), 191); - EXPECT_EQ(encodeRecovery(2.82843f, 1.0f, &metadata), 63); + EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255); + EXPECT_EQ(encodeGain(8.0f, 1.0f, &metadata), 0); + EXPECT_EQ(encodeGain(1.0f, 2.82843f, &metadata), 191); + EXPECT_EQ(encodeGain(2.82843f, 1.0f, &metadata), 63); metadata.maxContentBoost = 8.0f; metadata.minContentBoost = 1.0f; - EXPECT_EQ(encodeRecovery(0.0f, 0.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(1.0f, 0.0f, &metadata), 0); + EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 0); + EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(1.0f, 1.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(1.0f, 8.0f, &metadata), 255); - EXPECT_EQ(encodeRecovery(1.0f, 4.0f, &metadata), 170); - EXPECT_EQ(encodeRecovery(1.0f, 2.0f, &metadata), 85); + EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 0); + EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255); + EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 170); + EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 85); metadata.maxContentBoost = 8.0f; metadata.minContentBoost = 0.5f; - EXPECT_EQ(encodeRecovery(0.0f, 0.0f, &metadata), 63); - EXPECT_EQ(encodeRecovery(1.0f, 0.0f, &metadata), 0); + EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 63); + EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0); - EXPECT_EQ(encodeRecovery(1.0f, 1.0f, &metadata), 63); - EXPECT_EQ(encodeRecovery(1.0f, 8.0f, &metadata), 255); - EXPECT_EQ(encodeRecovery(1.0f, 4.0f, &metadata), 191); - EXPECT_EQ(encodeRecovery(1.0f, 2.0f, &metadata), 127); - EXPECT_EQ(encodeRecovery(1.0f, 0.7071f, &metadata), 31); - EXPECT_EQ(encodeRecovery(1.0f, 0.5f, &metadata), 0); + EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 63); + EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255); + EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 191); + EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 127); + EXPECT_EQ(encodeGain(1.0f, 0.7071f, &metadata), 31); + EXPECT_EQ(encodeGain(1.0f, 0.5f, &metadata), 0); } -TEST_F(RecoveryMapMathTest, ApplyRecovery) { - jpegr_metadata_struct metadata = { .maxContentBoost = 4.0f, +TEST_F(GainMapMathTest, ApplyGain) { + ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f, .minContentBoost = 1.0f / 4.0f }; float displayBoost = metadata.maxContentBoost; - EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), 0.0f, &metadata), RgbBlack()); - EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), 0.5f, &metadata), RgbBlack()); - EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), 1.0f, &metadata), RgbBlack()); + EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.0f, &metadata), RgbBlack()); + EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.5f, &metadata), RgbBlack()); + EXPECT_RGB_NEAR(applyGain(RgbBlack(), 1.0f, &metadata), RgbBlack()); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite() / 4.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, &metadata), RgbWhite()); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 4.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 4.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite()); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 4.0f); metadata.maxContentBoost = 2.0f; metadata.minContentBoost = 1.0f / 2.0f; - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.25f, &metadata), RgbWhite() / 1.41421f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, &metadata), RgbWhite()); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.75f, &metadata), RgbWhite() * 1.41421f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 2.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 1.41421f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite()); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 1.41421f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 2.0f); metadata.maxContentBoost = 8.0f; metadata.minContentBoost = 1.0f / 8.0f; - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite() / 8.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.82843f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, &metadata), RgbWhite()); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.82843f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 8.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.82843f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite()); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.82843f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f); metadata.maxContentBoost = 8.0f; metadata.minContentBoost = 1.0f; - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite()); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite()); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f); metadata.maxContentBoost = 8.0f; metadata.minContentBoost = 0.5f; - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.25f, &metadata), RgbWhite()); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, &metadata), RgbWhite() * 2.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.75f, &metadata), RgbWhite() * 4.0f); - EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite()); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite() * 2.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 4.0f); + EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f); Color e = {{{ 0.0f, 0.5f, 1.0f }}}; metadata.maxContentBoost = 4.0f; metadata.minContentBoost = 1.0f / 4.0f; - EXPECT_RGB_NEAR(applyRecovery(e, 0.0f, &metadata), e / 4.0f); - EXPECT_RGB_NEAR(applyRecovery(e, 0.25f, &metadata), e / 2.0f); - EXPECT_RGB_NEAR(applyRecovery(e, 0.5f, &metadata), e); - EXPECT_RGB_NEAR(applyRecovery(e, 0.75f, &metadata), e * 2.0f); - EXPECT_RGB_NEAR(applyRecovery(e, 1.0f, &metadata), e * 4.0f); - - EXPECT_RGB_EQ(applyRecovery(RgbBlack(), 1.0f, &metadata), - applyRecovery(RgbBlack(), 1.0f, &metadata, displayBoost)); - EXPECT_RGB_EQ(applyRecovery(RgbWhite(), 1.0f, &metadata), - applyRecovery(RgbWhite(), 1.0f, &metadata, displayBoost)); - EXPECT_RGB_EQ(applyRecovery(RgbRed(), 1.0f, &metadata), - applyRecovery(RgbRed(), 1.0f, &metadata, displayBoost)); - EXPECT_RGB_EQ(applyRecovery(RgbGreen(), 1.0f, &metadata), - applyRecovery(RgbGreen(), 1.0f, &metadata, displayBoost)); - EXPECT_RGB_EQ(applyRecovery(RgbBlue(), 1.0f, &metadata), - applyRecovery(RgbBlue(), 1.0f, &metadata, displayBoost)); - EXPECT_RGB_EQ(applyRecovery(e, 1.0f, &metadata), - applyRecovery(e, 1.0f, &metadata, displayBoost)); + EXPECT_RGB_NEAR(applyGain(e, 0.0f, &metadata), e / 4.0f); + EXPECT_RGB_NEAR(applyGain(e, 0.25f, &metadata), e / 2.0f); + EXPECT_RGB_NEAR(applyGain(e, 0.5f, &metadata), e); + EXPECT_RGB_NEAR(applyGain(e, 0.75f, &metadata), e * 2.0f); + EXPECT_RGB_NEAR(applyGain(e, 1.0f, &metadata), e * 4.0f); + + EXPECT_RGB_EQ(applyGain(RgbBlack(), 1.0f, &metadata), + applyGain(RgbBlack(), 1.0f, &metadata, displayBoost)); + EXPECT_RGB_EQ(applyGain(RgbWhite(), 1.0f, &metadata), + applyGain(RgbWhite(), 1.0f, &metadata, displayBoost)); + EXPECT_RGB_EQ(applyGain(RgbRed(), 1.0f, &metadata), + applyGain(RgbRed(), 1.0f, &metadata, displayBoost)); + EXPECT_RGB_EQ(applyGain(RgbGreen(), 1.0f, &metadata), + applyGain(RgbGreen(), 1.0f, &metadata, displayBoost)); + EXPECT_RGB_EQ(applyGain(RgbBlue(), 1.0f, &metadata), + applyGain(RgbBlue(), 1.0f, &metadata, displayBoost)); + EXPECT_RGB_EQ(applyGain(e, 1.0f, &metadata), + applyGain(e, 1.0f, &metadata, displayBoost)); } -TEST_F(RecoveryMapMathTest, GetYuv420Pixel) { +TEST_F(GainMapMathTest, GetYuv420Pixel) { jpegr_uncompressed_struct image = Yuv420Image(); Color (*colors)[4] = Yuv420Colors(); @@ -834,7 +834,7 @@ TEST_F(RecoveryMapMathTest, GetYuv420Pixel) { } } -TEST_F(RecoveryMapMathTest, GetP010Pixel) { +TEST_F(GainMapMathTest, GetP010Pixel) { jpegr_uncompressed_struct image = P010Image(); Color (*colors)[4] = P010Colors(); @@ -845,7 +845,7 @@ TEST_F(RecoveryMapMathTest, GetP010Pixel) { } } -TEST_F(RecoveryMapMathTest, SampleYuv420) { +TEST_F(GainMapMathTest, SampleYuv420) { jpegr_uncompressed_struct image = Yuv420Image(); Color (*colors)[4] = Yuv420Colors(); @@ -871,7 +871,7 @@ TEST_F(RecoveryMapMathTest, SampleYuv420) { } } -TEST_F(RecoveryMapMathTest, SampleP010) { +TEST_F(GainMapMathTest, SampleP010) { jpegr_uncompressed_struct image = P010Image(); Color (*colors)[4] = P010Colors(); @@ -897,7 +897,7 @@ TEST_F(RecoveryMapMathTest, SampleP010) { } } -TEST_F(RecoveryMapMathTest, SampleMap) { +TEST_F(GainMapMathTest, SampleMap) { jpegr_uncompressed_struct image = MapImage(); float (*values)[4] = MapValues(); @@ -937,7 +937,7 @@ TEST_F(RecoveryMapMathTest, SampleMap) { } } -TEST_F(RecoveryMapMathTest, ColorToRgba1010102) { +TEST_F(GainMapMathTest, ColorToRgba1010102) { EXPECT_EQ(colorToRgba1010102(RgbBlack()), 0x3 << 30); EXPECT_EQ(colorToRgba1010102(RgbWhite()), 0xFFFFFFFF); EXPECT_EQ(colorToRgba1010102(RgbRed()), 0x3 << 30 | 0x3ff); @@ -952,7 +952,7 @@ TEST_F(RecoveryMapMathTest, ColorToRgba1010102) { | static_cast<uint32_t>(0.3f * static_cast<float>(0x3ff)) << 20); } -TEST_F(RecoveryMapMathTest, ColorToRgbaF16) { +TEST_F(GainMapMathTest, ColorToRgbaF16) { EXPECT_EQ(colorToRgbaF16(RgbBlack()), ((uint64_t) 0x3C00) << 48); EXPECT_EQ(colorToRgbaF16(RgbWhite()), 0x3C003C003C003C00); EXPECT_EQ(colorToRgbaF16(RgbRed()), (((uint64_t) 0x3C00) << 48) | ((uint64_t) 0x3C00)); @@ -963,7 +963,7 @@ TEST_F(RecoveryMapMathTest, ColorToRgbaF16) { EXPECT_EQ(colorToRgbaF16(e_gamma), 0x3C0034CD32662E66); } -TEST_F(RecoveryMapMathTest, Float32ToFloat16) { +TEST_F(GainMapMathTest, Float32ToFloat16) { EXPECT_EQ(floatToHalf(0.1f), 0x2E66); EXPECT_EQ(floatToHalf(0.0f), 0x0); EXPECT_EQ(floatToHalf(1.0f), 0x3C00); @@ -973,7 +973,7 @@ TEST_F(RecoveryMapMathTest, Float32ToFloat16) { EXPECT_EQ(floatToHalf(0x1.0p-126f), 0x0); // float zero } -TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgb) { +TEST_F(GainMapMathTest, GenerateMapLuminanceSrgb) { EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), srgbLuminance), 0.0f); EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), srgbLuminance), @@ -986,7 +986,7 @@ TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgb) { srgbLuminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon()); } -TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgbP3) { +TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbP3) { EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), p3Luminance), 0.0f); EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), p3Luminance), @@ -999,7 +999,7 @@ TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgbP3) { p3Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon()); } -TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgbBt2100) { +TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbBt2100) { EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), bt2100Luminance), 0.0f); EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), bt2100Luminance), @@ -1012,7 +1012,7 @@ TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgbBt2100) { bt2100Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon()); } -TEST_F(RecoveryMapMathTest, GenerateMapLuminanceHlg) { +TEST_F(GainMapMathTest, GenerateMapLuminanceHlg) { EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), hlgInvOetf, identityConversion, bt2100Luminance, kHlgMaxNits), 0.0f); @@ -1030,7 +1030,7 @@ TEST_F(RecoveryMapMathTest, GenerateMapLuminanceHlg) { bt2100Luminance(RgbBlue()) * kHlgMaxNits, LuminanceEpsilon()); } -TEST_F(RecoveryMapMathTest, GenerateMapLuminancePq) { +TEST_F(GainMapMathTest, GenerateMapLuminancePq) { EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), pqInvOetf, identityConversion, bt2100Luminance, kPqMaxNits), 0.0f); @@ -1048,8 +1048,8 @@ TEST_F(RecoveryMapMathTest, GenerateMapLuminancePq) { bt2100Luminance(RgbBlue()) * kPqMaxNits, LuminanceEpsilon()); } -TEST_F(RecoveryMapMathTest, ApplyMap) { - jpegr_metadata_struct metadata = { .maxContentBoost = 8.0f, +TEST_F(GainMapMathTest, ApplyMap) { + ultrahdr_metadata_struct metadata = { .maxContentBoost = 8.0f, .minContentBoost = 1.0f / 8.0f }; EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata), @@ -1134,4 +1134,4 @@ TEST_F(RecoveryMapMathTest, ApplyMap) { RgbWhite() / 2.0f); } -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr diff --git a/libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp b/libs/ultrahdr/tests/jpegdecoderhelper_test.cpp index 2f32a5685b..c79dbe328b 100644 --- a/libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp +++ b/libs/ultrahdr/tests/jpegdecoderhelper_test.cpp @@ -14,13 +14,13 @@ * limitations under the License. */ -#include <jpegrecoverymap/jpegdecoderhelper.h> +#include <ultrahdr/jpegdecoderhelper.h> #include <gtest/gtest.h> #include <utils/Log.h> #include <fcntl.h> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { #define YUV_IMAGE "/sdcard/Documents/minnie-320x240-yuv.jpg" #define YUV_IMAGE_SIZE 20193 @@ -99,4 +99,4 @@ TEST_F(JpegDecoderHelperTest, decodeGreyImage) { ASSERT_GT(decoder.getDecompressedImageSize(), static_cast<uint32_t>(0)); } -} // namespace android::jpegrecoverymap
\ No newline at end of file +} // namespace android::ultrahdr
\ No newline at end of file diff --git a/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp b/libs/ultrahdr/tests/jpegencoderhelper_test.cpp index 095ac2fbf6..8f18ac0004 100644 --- a/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp +++ b/libs/ultrahdr/tests/jpegencoderhelper_test.cpp @@ -14,23 +14,23 @@ * limitations under the License. */ -#include <jpegrecoverymap/jpegencoderhelper.h> +#include <ultrahdr/jpegencoderhelper.h> #include <gtest/gtest.h> #include <utils/Log.h> #include <fcntl.h> -namespace android::jpegrecoverymap { +namespace android::ultrahdr { -#define VALID_IMAGE "/sdcard/Documents/minnie-320x240.yu12" -#define VALID_IMAGE_WIDTH 320 -#define VALID_IMAGE_HEIGHT 240 +#define ALIGNED_IMAGE "/sdcard/Documents/minnie-320x240.yu12" +#define ALIGNED_IMAGE_WIDTH 320 +#define ALIGNED_IMAGE_HEIGHT 240 #define SINGLE_CHANNEL_IMAGE "/sdcard/Documents/minnie-320x240.y" -#define SINGLE_CHANNEL_IMAGE_WIDTH VALID_IMAGE_WIDTH -#define SINGLE_CHANNEL_IMAGE_HEIGHT VALID_IMAGE_HEIGHT -#define INVALID_SIZE_IMAGE "/sdcard/Documents/minnie-318x240.yu12" -#define INVALID_SIZE_IMAGE_WIDTH 318 -#define INVALID_SIZE_IMAGE_HEIGHT 240 +#define SINGLE_CHANNEL_IMAGE_WIDTH ALIGNED_IMAGE_WIDTH +#define SINGLE_CHANNEL_IMAGE_HEIGHT ALIGNED_IMAGE_HEIGHT +#define UNALIGNED_IMAGE "/sdcard/Documents/minnie-318x240.yu12" +#define UNALIGNED_IMAGE_WIDTH 318 +#define UNALIGNED_IMAGE_HEIGHT 240 #define JPEG_QUALITY 90 class JpegEncoderHelperTest : public testing::Test { @@ -46,7 +46,7 @@ protected: virtual void SetUp(); virtual void TearDown(); - Image mValidImage, mInvalidSizeImage, mSingleChannelImage; + Image mAlignedImage, mUnalignedImage, mSingleChannelImage; }; JpegEncoderHelperTest::JpegEncoderHelperTest() {} @@ -82,16 +82,16 @@ static bool loadFile(const char filename[], JpegEncoderHelperTest::Image* result } void JpegEncoderHelperTest::SetUp() { - if (!loadFile(VALID_IMAGE, &mValidImage)) { - FAIL() << "Load file " << VALID_IMAGE << " failed"; + if (!loadFile(ALIGNED_IMAGE, &mAlignedImage)) { + FAIL() << "Load file " << ALIGNED_IMAGE << " failed"; } - mValidImage.width = VALID_IMAGE_WIDTH; - mValidImage.height = VALID_IMAGE_HEIGHT; - if (!loadFile(INVALID_SIZE_IMAGE, &mInvalidSizeImage)) { - FAIL() << "Load file " << INVALID_SIZE_IMAGE << " failed"; + mAlignedImage.width = ALIGNED_IMAGE_WIDTH; + mAlignedImage.height = ALIGNED_IMAGE_HEIGHT; + if (!loadFile(UNALIGNED_IMAGE, &mUnalignedImage)) { + FAIL() << "Load file " << UNALIGNED_IMAGE << " failed"; } - mInvalidSizeImage.width = INVALID_SIZE_IMAGE_WIDTH; - mInvalidSizeImage.height = INVALID_SIZE_IMAGE_HEIGHT; + mUnalignedImage.width = UNALIGNED_IMAGE_WIDTH; + mUnalignedImage.height = UNALIGNED_IMAGE_HEIGHT; if (!loadFile(SINGLE_CHANNEL_IMAGE, &mSingleChannelImage)) { FAIL() << "Load file " << SINGLE_CHANNEL_IMAGE << " failed"; } @@ -101,25 +101,35 @@ void JpegEncoderHelperTest::SetUp() { void JpegEncoderHelperTest::TearDown() {} -TEST_F(JpegEncoderHelperTest, validImage) { +TEST_F(JpegEncoderHelperTest, encodeAlignedImage) { JpegEncoderHelper encoder; - EXPECT_TRUE(encoder.compressImage(mValidImage.buffer.get(), mValidImage.width, - mValidImage.height, JPEG_QUALITY, NULL, 0)); + EXPECT_TRUE(encoder.compressImage(mAlignedImage.buffer.get(), mAlignedImage.width, + mAlignedImage.height, JPEG_QUALITY, NULL, 0)); ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0)); } -TEST_F(JpegEncoderHelperTest, invalidSizeImage) { +// The width of the "unaligned" image is not 16-aligned, and will fail if encoded directly. +// Should pass with the padding zero method. +TEST_F(JpegEncoderHelperTest, encodeUnalignedImage) { JpegEncoderHelper encoder; - EXPECT_FALSE(encoder.compressImage(mInvalidSizeImage.buffer.get(), mInvalidSizeImage.width, - mInvalidSizeImage.height, JPEG_QUALITY, NULL, 0)); + const size_t paddingZeroLength = JpegEncoderHelper::kCompressBatchSize + * JpegEncoderHelper::kCompressBatchSize / 4; + std::unique_ptr<uint8_t[]> imageWithPaddingZeros( + new uint8_t[UNALIGNED_IMAGE_WIDTH * UNALIGNED_IMAGE_HEIGHT * 3 / 2 + + paddingZeroLength]); + memcpy(imageWithPaddingZeros.get(), mUnalignedImage.buffer.get(), + UNALIGNED_IMAGE_WIDTH * UNALIGNED_IMAGE_HEIGHT * 3 / 2); + EXPECT_TRUE(encoder.compressImage(imageWithPaddingZeros.get(), mUnalignedImage.width, + mUnalignedImage.height, JPEG_QUALITY, NULL, 0)); + ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0)); } -TEST_F(JpegEncoderHelperTest, singleChannelImage) { +TEST_F(JpegEncoderHelperTest, encodeSingleChannelImage) { JpegEncoderHelper encoder; EXPECT_TRUE(encoder.compressImage(mSingleChannelImage.buffer.get(), mSingleChannelImage.width, mSingleChannelImage.height, JPEG_QUALITY, NULL, 0, true)); ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0)); } -} // namespace android::jpegrecoverymap +} // namespace android::ultrahdr diff --git a/libs/jpegrecoverymap/tests/jpegr_test.cpp b/libs/ultrahdr/tests/jpegr_test.cpp index 7c669aba0a..58cd8f4711 100644 --- a/libs/jpegrecoverymap/tests/jpegr_test.cpp +++ b/libs/ultrahdr/tests/jpegr_test.cpp @@ -14,9 +14,9 @@ * limitations under the License. */ -#include <jpegrecoverymap/jpegr.h> -#include <jpegrecoverymap/jpegrutils.h> -#include <jpegrecoverymap/recoverymapmath.h> +#include <ultrahdr/jpegr.h> +#include <ultrahdr/jpegrutils.h> +#include <ultrahdr/gainmapmath.h> #include <fcntl.h> #include <fstream> #include <gtest/gtest.h> @@ -24,17 +24,19 @@ #include <utils/Log.h> #define RAW_P010_IMAGE "/sdcard/Documents/raw_p010_image.p010" +#define RAW_P010_IMAGE_WITH_STRIDE "/sdcard/Documents/raw_p010_image_with_stride.p010" #define RAW_YUV420_IMAGE "/sdcard/Documents/raw_yuv420_image.yuv420" #define JPEG_IMAGE "/sdcard/Documents/jpeg_image.jpg" #define TEST_IMAGE_WIDTH 1280 #define TEST_IMAGE_HEIGHT 720 +#define TEST_IMAGE_STRIDE 1288 #define DEFAULT_JPEG_QUALITY 90 #define SAVE_ENCODING_RESULT true #define SAVE_DECODING_RESULT true #define SAVE_INPUT_RGBA true -namespace android::jpegrecoverymap { +namespace android::ultrahdr { struct Timer { struct timeval StartingTime; @@ -97,6 +99,7 @@ protected: virtual void TearDown(); struct jpegr_uncompressed_struct mRawP010Image; + struct jpegr_uncompressed_struct mRawP010ImageWithStride; struct jpegr_uncompressed_struct mRawYuv420Image; struct jpegr_compressed_struct mJpegImage; }; @@ -107,24 +110,25 @@ JpegRTest::~JpegRTest() {} void JpegRTest::SetUp() {} void JpegRTest::TearDown() { free(mRawP010Image.data); + free(mRawP010ImageWithStride.data); free(mRawYuv420Image.data); free(mJpegImage.data); } class JpegRBenchmark : public JpegR { public: - void BenchmarkGenerateRecoveryMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr p010Image, - jr_metadata_ptr metadata, jr_uncompressed_ptr map); - void BenchmarkApplyRecoveryMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr map, - jr_metadata_ptr metadata, jr_uncompressed_ptr dest); + void BenchmarkGenerateGainMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr p010Image, + ultrahdr_metadata_ptr metadata, jr_uncompressed_ptr map); + void BenchmarkApplyGainMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr map, + ultrahdr_metadata_ptr metadata, jr_uncompressed_ptr dest); private: const int kProfileCount = 10; }; -void JpegRBenchmark::BenchmarkGenerateRecoveryMap(jr_uncompressed_ptr yuv420Image, - jr_uncompressed_ptr p010Image, - jr_metadata_ptr metadata, - jr_uncompressed_ptr map) { +void JpegRBenchmark::BenchmarkGenerateGainMap(jr_uncompressed_ptr yuv420Image, + jr_uncompressed_ptr p010Image, + ultrahdr_metadata_ptr metadata, + jr_uncompressed_ptr map) { ASSERT_EQ(yuv420Image->width, p010Image->width); ASSERT_EQ(yuv420Image->height, p010Image->height); @@ -132,50 +136,51 @@ void JpegRBenchmark::BenchmarkGenerateRecoveryMap(jr_uncompressed_ptr yuv420Imag timerStart(&genRecMapTime); for (auto i = 0; i < kProfileCount; i++) { - ASSERT_EQ(OK, generateRecoveryMap( - yuv420Image, p010Image, jpegr_transfer_function::JPEGR_TF_HLG, metadata, map)); + ASSERT_EQ(OK, generateGainMap( + yuv420Image, p010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, metadata, map)); if (i != kProfileCount - 1) delete[] static_cast<uint8_t *>(map->data); } timerStop(&genRecMapTime); - ALOGE("Generate Recovery Map:- Res = %i x %i, time = %f ms", + ALOGE("Generate Gain Map:- Res = %i x %i, time = %f ms", yuv420Image->width, yuv420Image->height, elapsedTime(&genRecMapTime) / (kProfileCount * 1000.f)); } -void JpegRBenchmark::BenchmarkApplyRecoveryMap(jr_uncompressed_ptr yuv420Image, - jr_uncompressed_ptr map, - jr_metadata_ptr metadata, - jr_uncompressed_ptr dest) { +void JpegRBenchmark::BenchmarkApplyGainMap(jr_uncompressed_ptr yuv420Image, + jr_uncompressed_ptr map, + ultrahdr_metadata_ptr metadata, + jr_uncompressed_ptr dest) { Timer applyRecMapTime; timerStart(&applyRecMapTime); for (auto i = 0; i < kProfileCount; i++) { - ASSERT_EQ(OK, applyRecoveryMap(yuv420Image, map, metadata, JPEGR_OUTPUT_HDR_HLG, - metadata->maxContentBoost /* displayBoost */, dest)); + ASSERT_EQ(OK, applyGainMap(yuv420Image, map, metadata, ULTRAHDR_OUTPUT_HDR_HLG, + metadata->maxContentBoost /* displayBoost */, dest)); } timerStop(&applyRecMapTime); - ALOGE("Apply Recovery Map:- Res = %i x %i, time = %f ms", + ALOGE("Apply Gain Map:- Res = %i x %i, time = %f ms", yuv420Image->width, yuv420Image->height, elapsedTime(&applyRecMapTime) / (kProfileCount * 1000.f)); } TEST_F(JpegRTest, build) { - // Force all of the recovery map lib to be linked by calling all public functions. + // Force all of the gain map lib to be linked by calling all public functions. JpegR jpegRCodec; - jpegRCodec.encodeJPEGR(nullptr, static_cast<jpegr_transfer_function>(0), nullptr, 0, nullptr); - jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<jpegr_transfer_function>(0), + jpegRCodec.encodeJPEGR(nullptr, static_cast<ultrahdr_transfer_function>(0), nullptr, 0, nullptr); + jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0), nullptr, 0, nullptr); - jpegRCodec.encodeJPEGR(nullptr, nullptr, nullptr, static_cast<jpegr_transfer_function>(0), + jpegRCodec.encodeJPEGR(nullptr, nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0), nullptr); - jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<jpegr_transfer_function>(0), nullptr); + jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0), nullptr); jpegRCodec.decodeJPEGR(nullptr, nullptr); } TEST_F(JpegRTest, writeXmpThenRead) { - jpegr_metadata_struct metadata_expected; + ultrahdr_metadata_struct metadata_expected; + metadata_expected.version = "1.0"; metadata_expected.maxContentBoost = 1.25; metadata_expected.minContentBoost = 0.75; const std::string nameSpace = "http://ns.adobe.com/xap/1.0/\0"; @@ -190,7 +195,7 @@ TEST_F(JpegRTest, writeXmpThenRead) { xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(xmp.c_str()), reinterpret_cast<const uint8_t*>(xmp.c_str()) + xmp.size()); - jpegr_metadata_struct metadata_read; + ultrahdr_metadata_struct metadata_read; EXPECT_TRUE(getMetadataFromXMP(xmpData.data(), xmpData.size(), &metadata_read)); EXPECT_FLOAT_EQ(metadata_expected.maxContentBoost, metadata_read.maxContentBoost); EXPECT_FLOAT_EQ(metadata_expected.minContentBoost, metadata_read.minContentBoost); @@ -206,7 +211,7 @@ TEST_F(JpegRTest, encodeFromP010ThenDecode) { } mRawP010Image.width = TEST_IMAGE_WIDTH; mRawP010Image.height = TEST_IMAGE_HEIGHT; - mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100; + mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100; JpegR jpegRCodec; @@ -214,7 +219,63 @@ TEST_F(JpegRTest, encodeFromP010ThenDecode) { jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t); jpegR.data = malloc(jpegR.maxLength); ret = jpegRCodec.encodeJPEGR( - &mRawP010Image, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY, nullptr); + &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY, + nullptr); + if (ret != OK) { + FAIL() << "Error code is " << ret; + } + if (SAVE_ENCODING_RESULT) { + // Output image data to file + std::string filePath = "/sdcard/Documents/encoded_from_p010_input.jpgr"; + std::ofstream imageFile(filePath.c_str(), std::ofstream::binary); + if (!imageFile.is_open()) { + ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str()); + } + imageFile.write((const char*)jpegR.data, jpegR.length); + } + + jpegr_uncompressed_struct decodedJpegR; + int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8; + decodedJpegR.data = malloc(decodedJpegRSize); + ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR); + if (ret != OK) { + FAIL() << "Error code is " << ret; + } + if (SAVE_DECODING_RESULT) { + // Output image data to file + std::string filePath = "/sdcard/Documents/decoded_from_p010_input.rgb"; + std::ofstream imageFile(filePath.c_str(), std::ofstream::binary); + if (!imageFile.is_open()) { + ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str()); + } + imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize); + } + + free(jpegR.data); + free(decodedJpegR.data); +} + +/* Test Encode API-0 (with stride) and decode */ +TEST_F(JpegRTest, encodeFromP010WithStrideThenDecode) { + int ret; + + // Load input files. + if (!loadFile(RAW_P010_IMAGE_WITH_STRIDE, mRawP010ImageWithStride.data, nullptr)) { + FAIL() << "Load file " << RAW_P010_IMAGE_WITH_STRIDE << " failed"; + } + mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH; + mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT; + mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE; + mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100; + + JpegR jpegRCodec; + + jpegr_compressed_struct jpegR; + jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t); + jpegR.data = malloc(jpegR.maxLength); + ret = jpegRCodec.encodeJPEGR( + &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, + DEFAULT_JPEG_QUALITY, nullptr); if (ret != OK) { FAIL() << "Error code is " << ret; } @@ -259,14 +320,14 @@ TEST_F(JpegRTest, encodeFromRawHdrAndSdrThenDecode) { } mRawP010Image.width = TEST_IMAGE_WIDTH; mRawP010Image.height = TEST_IMAGE_HEIGHT; - mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100; + mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100; if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) { FAIL() << "Load file " << RAW_P010_IMAGE << " failed"; } mRawYuv420Image.width = TEST_IMAGE_WIDTH; mRawYuv420Image.height = TEST_IMAGE_HEIGHT; - mRawYuv420Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709; + mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709; JpegR jpegRCodec; @@ -274,7 +335,7 @@ TEST_F(JpegRTest, encodeFromRawHdrAndSdrThenDecode) { jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t); jpegR.data = malloc(jpegR.maxLength); ret = jpegRCodec.encodeJPEGR( - &mRawP010Image, &mRawYuv420Image, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR, + &mRawP010Image, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY, nullptr); if (ret != OK) { FAIL() << "Error code is " << ret; @@ -320,19 +381,19 @@ TEST_F(JpegRTest, encodeFromRawHdrAndSdrAndJpegThenDecode) { } mRawP010Image.width = TEST_IMAGE_WIDTH; mRawP010Image.height = TEST_IMAGE_HEIGHT; - mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100; + mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100; if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) { FAIL() << "Load file " << RAW_P010_IMAGE << " failed"; } mRawYuv420Image.width = TEST_IMAGE_WIDTH; mRawYuv420Image.height = TEST_IMAGE_HEIGHT; - mRawYuv420Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709; + mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709; if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) { FAIL() << "Load file " << JPEG_IMAGE << " failed"; } - mJpegImage.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709; + mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709; JpegR jpegRCodec; @@ -340,7 +401,8 @@ TEST_F(JpegRTest, encodeFromRawHdrAndSdrAndJpegThenDecode) { jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t); jpegR.data = malloc(jpegR.maxLength); ret = jpegRCodec.encodeJPEGR( - &mRawP010Image, &mRawYuv420Image, &mJpegImage, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR); + &mRawP010Image, &mRawYuv420Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, + &jpegR); if (ret != OK) { FAIL() << "Error code is " << ret; } @@ -385,7 +447,7 @@ TEST_F(JpegRTest, encodeFromJpegThenDecode) { } mRawP010Image.width = TEST_IMAGE_WIDTH; mRawP010Image.height = TEST_IMAGE_HEIGHT; - mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100; + mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100; if (SAVE_INPUT_RGBA) { size_t rgbaSize = mRawP010Image.width * mRawP010Image.height * sizeof(uint32_t); @@ -413,7 +475,7 @@ TEST_F(JpegRTest, encodeFromJpegThenDecode) { if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) { FAIL() << "Load file " << JPEG_IMAGE << " failed"; } - mJpegImage.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709; + mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709; JpegR jpegRCodec; @@ -421,7 +483,7 @@ TEST_F(JpegRTest, encodeFromJpegThenDecode) { jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t); jpegR.data = malloc(jpegR.maxLength); ret = jpegRCodec.encodeJPEGR( - &mRawP010Image, &mJpegImage, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR); + &mRawP010Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR); if (ret != OK) { FAIL() << "Error code is " << ret; } @@ -456,7 +518,7 @@ TEST_F(JpegRTest, encodeFromJpegThenDecode) { free(decodedJpegR.data); } -TEST_F(JpegRTest, ProfileRecoveryMapFuncs) { +TEST_F(JpegRTest, ProfileGainMapFuncs) { const size_t kWidth = TEST_IMAGE_WIDTH; const size_t kHeight = TEST_IMAGE_HEIGHT; @@ -466,36 +528,36 @@ TEST_F(JpegRTest, ProfileRecoveryMapFuncs) { } mRawP010Image.width = kWidth; mRawP010Image.height = kHeight; - mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100; + mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100; if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) { FAIL() << "Load file " << RAW_P010_IMAGE << " failed"; } mRawYuv420Image.width = kWidth; mRawYuv420Image.height = kHeight; - mRawYuv420Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709; + mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709; JpegRBenchmark benchmark; - jpegr_metadata_struct metadata = { .version = 1, + ultrahdr_metadata_struct metadata = { .version = "1.0", .maxContentBoost = 8.0f, .minContentBoost = 1.0f / 8.0f }; jpegr_uncompressed_struct map = { .data = NULL, .width = 0, .height = 0, - .colorGamut = JPEGR_COLORGAMUT_UNSPECIFIED }; + .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED }; - benchmark.BenchmarkGenerateRecoveryMap(&mRawYuv420Image, &mRawP010Image, &metadata, &map); + benchmark.BenchmarkGenerateGainMap(&mRawYuv420Image, &mRawP010Image, &metadata, &map); const int dstSize = mRawYuv420Image.width * mRawYuv420Image.height * 4; auto bufferDst = std::make_unique<uint8_t[]>(dstSize); jpegr_uncompressed_struct dest = { .data = bufferDst.get(), .width = 0, .height = 0, - .colorGamut = JPEGR_COLORGAMUT_UNSPECIFIED }; + .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED }; - benchmark.BenchmarkApplyRecoveryMap(&mRawYuv420Image, &map, &metadata, &dest); + benchmark.BenchmarkApplyGainMap(&mRawYuv420Image, &map, &metadata, &dest); } -} // namespace android::recoverymap +} // namespace android::ultrahdr diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp index 614a78ecc7..72bd29254d 100644 --- a/services/automotive/display/Android.bp +++ b/services/automotive/display/Android.bp @@ -53,6 +53,4 @@ cc_binary { vintf_fragments: [ "manifest_android.frameworks.automotive.display@1.0.xml", ], - - system_ext_specific: true, } diff --git a/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc b/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc index ea1077a555..5c7f344486 100644 --- a/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc +++ b/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc @@ -1,4 +1,4 @@ -service automotive_display /system_ext/bin/android.frameworks.automotive.display@1.0-service +service automotive_display /system/bin/android.frameworks.automotive.display@1.0-service class hal user graphics group automotive_evs diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp index aaa8c18508..5e7b2e8df8 100644 --- a/services/gpuservice/GpuService.cpp +++ b/services/gpuservice/GpuService.cpp @@ -19,6 +19,7 @@ #include "GpuService.h" #include <android-base/stringprintf.h> +#include <android-base/properties.h> #include <binder/IPCThreadState.h> #include <binder/IResultReceiver.h> #include <binder/Parcel.h> @@ -46,6 +47,8 @@ void dumpGameDriverInfo(std::string* result); } // namespace const String16 sDump("android.permission.DUMP"); +const String16 sAccessGpuServicePermission("android.permission.ACCESS_GPU_SERVICE"); +const std::string sAngleGlesDriverSuffix = "angle"; const char* const GpuService::SERVICE_NAME = "gpu"; @@ -88,6 +91,29 @@ void GpuService::setTargetStatsArray(const std::string& appPackageName, mGpuStats->insertTargetStatsArray(appPackageName, driverVersionCode, stats, values, valueCount); } +void GpuService::toggleAngleAsSystemDriver(bool enabled) { + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + + // only system_server with the ACCESS_GPU_SERVICE permission is allowed to set + // persist.graphics.egl + if (uid != AID_SYSTEM || + !PermissionCache::checkPermission(sAccessGpuServicePermission, pid, uid)) { + ALOGE("Permission Denial: can't set persist.graphics.egl from setAngleAsSystemDriver() " + "pid=%d, uid=%d\n", pid, uid); + return; + } + + std::lock_guard<std::mutex> lock(mLock); + if (enabled) { + android::base::SetProperty("persist.graphics.egl", sAngleGlesDriverSuffix); + } else { + android::base::SetProperty("persist.graphics.egl", ""); + } +} + + void GpuService::setUpdatableDriverPath(const std::string& driverPath) { IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h index e7e0cba689..0e559f2c34 100644 --- a/services/gpuservice/GpuService.h +++ b/services/gpuservice/GpuService.h @@ -61,6 +61,7 @@ private: const uint64_t* values, const uint32_t valueCount) override; void setUpdatableDriverPath(const std::string& driverPath) override; std::string getUpdatableDriverPath() override; + void toggleAngleAsSystemDriver(bool enabled) override; /* * IBinder interface diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index b8854352ad..e04481ca50 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -213,6 +213,7 @@ phony { name: "checkinput", required: [ // native targets + "libgui_test", "libinput", "libinputflinger", "inputflinger_tests", diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp index d33b29888f..aa55873aa5 100644 --- a/services/inputflinger/InputListener.cpp +++ b/services/inputflinger/InputListener.cpp @@ -24,7 +24,6 @@ #include <android-base/stringprintf.h> #include <android/log.h> -#include <math.h> #include <utils/Trace.h> using android::base::StringPrintf; @@ -47,16 +46,15 @@ Visitor(V...) -> Visitor<V...>; void InputListenerInterface::notify(const NotifyArgs& generalArgs) { Visitor v{ - [&](const NotifyConfigurationChangedArgs& args) { notifyConfigurationChanged(&args); }, - [&](const NotifyKeyArgs& args) { notifyKey(&args); }, - [&](const NotifyMotionArgs& args) { notifyMotion(&args); }, - [&](const NotifySwitchArgs& args) { notifySwitch(&args); }, - [&](const NotifySensorArgs& args) { notifySensor(&args); }, - [&](const NotifyVibratorStateArgs& args) { notifyVibratorState(&args); }, - [&](const NotifyDeviceResetArgs& args) { notifyDeviceReset(&args); }, - [&](const NotifyPointerCaptureChangedArgs& args) { - notifyPointerCaptureChanged(&args); - }, + [&](const NotifyInputDevicesChangedArgs& args) { notifyInputDevicesChanged(args); }, + [&](const NotifyConfigurationChangedArgs& args) { notifyConfigurationChanged(args); }, + [&](const NotifyKeyArgs& args) { notifyKey(args); }, + [&](const NotifyMotionArgs& args) { notifyMotion(args); }, + [&](const NotifySwitchArgs& args) { notifySwitch(args); }, + [&](const NotifySensorArgs& args) { notifySensor(args); }, + [&](const NotifyVibratorStateArgs& args) { notifyVibratorState(args); }, + [&](const NotifyDeviceResetArgs& args) { notifyDeviceReset(args); }, + [&](const NotifyPointerCaptureChangedArgs& args) { notifyPointerCaptureChanged(args); }, }; std::visit(v, generalArgs); } @@ -73,45 +71,49 @@ static inline void traceEvent(const char* functionName, int32_t id) { QueuedInputListener::QueuedInputListener(InputListenerInterface& innerListener) : mInnerListener(innerListener) {} -void QueuedInputListener::notifyConfigurationChanged( - const NotifyConfigurationChangedArgs* args) { - traceEvent(__func__, args->id); - mArgsQueue.emplace_back(*args); +void QueuedInputListener::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); } -void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) { - traceEvent(__func__, args->id); - mArgsQueue.emplace_back(*args); +void QueuedInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); } -void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) { - traceEvent(__func__, args->id); - mArgsQueue.emplace_back(*args); +void QueuedInputListener::notifyKey(const NotifyKeyArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); } -void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) { - traceEvent(__func__, args->id); - mArgsQueue.emplace_back(*args); +void QueuedInputListener::notifyMotion(const NotifyMotionArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); } -void QueuedInputListener::notifySensor(const NotifySensorArgs* args) { - traceEvent(__func__, args->id); - mArgsQueue.emplace_back(*args); +void QueuedInputListener::notifySwitch(const NotifySwitchArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); } -void QueuedInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) { - traceEvent(__func__, args->id); - mArgsQueue.emplace_back(*args); +void QueuedInputListener::notifySensor(const NotifySensorArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); } -void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) { - traceEvent(__func__, args->id); - mArgsQueue.emplace_back(*args); +void QueuedInputListener::notifyVibratorState(const NotifyVibratorStateArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); } -void QueuedInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) { - traceEvent(__func__, args->id); - mArgsQueue.emplace_back(*args); +void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); +} + +void QueuedInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) { + traceEvent(__func__, args.id); + mArgsQueue.emplace_back(args); } void QueuedInputListener::flush() { diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index 9182503692..472d7a15b4 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -110,10 +110,6 @@ InputReaderInterface& InputManager::getReader() { return *mReader; } -UnwantedInteractionBlockerInterface& InputManager::getBlocker() { - return *mBlocker; -} - InputProcessorInterface& InputManager::getProcessor() { return *mProcessor; } @@ -129,6 +125,17 @@ void InputManager::monitor() { mDispatcher->monitor(); } +void InputManager::dump(std::string& dump) { + mReader->dump(dump); + dump += '\n'; + mBlocker->dump(dump); + dump += '\n'; + mProcessor->dump(dump); + dump += '\n'; + mDispatcher->dump(dump); + dump += '\n'; +} + // Used by tests only. binder::Status InputManager::createInputChannel(const std::string& name, InputChannel* outChannel) { IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 11371934c2..793757d369 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -82,9 +82,6 @@ public: /* Gets the input reader. */ virtual InputReaderInterface& getReader() = 0; - /* Gets the unwanted interaction blocker. */ - virtual UnwantedInteractionBlockerInterface& getBlocker() = 0; - /* Gets the input processor */ virtual InputProcessorInterface& getProcessor() = 0; @@ -93,6 +90,9 @@ public: /* Check that the input stages have not deadlocked. */ virtual void monitor() = 0; + + /* Dump the state of the components controlled by the input manager. */ + virtual void dump(std::string& dump) = 0; }; class InputManager : public InputManagerInterface, public BnInputFlinger { @@ -108,10 +108,10 @@ public: status_t stop() override; InputReaderInterface& getReader() override; - UnwantedInteractionBlockerInterface& getBlocker() override; InputProcessorInterface& getProcessor() override; InputDispatcherInterface& getDispatcher() override; void monitor() override; + void dump(std::string& dump) override; status_t dump(int fd, const Vector<String16>& args) override; binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override; diff --git a/services/inputflinger/InputProcessor.cpp b/services/inputflinger/InputProcessor.cpp index a98b383037..7a84be93b1 100644 --- a/services/inputflinger/InputProcessor.cpp +++ b/services/inputflinger/InputProcessor.cpp @@ -413,63 +413,69 @@ void InputProcessor::setMotionClassifierEnabled(bool enabled) { } } -void InputProcessor::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { +void InputProcessor::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) { + // pass through + mQueuedListener.notify(args); + mQueuedListener.flush(); +} + +void InputProcessor::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) { // pass through mQueuedListener.notifyConfigurationChanged(args); mQueuedListener.flush(); } -void InputProcessor::notifyKey(const NotifyKeyArgs* args) { +void InputProcessor::notifyKey(const NotifyKeyArgs& args) { // pass through mQueuedListener.notifyKey(args); mQueuedListener.flush(); } -void InputProcessor::notifyMotion(const NotifyMotionArgs* args) { +void InputProcessor::notifyMotion(const NotifyMotionArgs& args) { { // acquire lock std::scoped_lock lock(mLock); // MotionClassifier is only used for touch events, for now - const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(*args); + const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(args); if (!sendToMotionClassifier) { mQueuedListener.notifyMotion(args); } else { - NotifyMotionArgs newArgs(*args); + NotifyMotionArgs newArgs(args); const MotionClassification newClassification = mMotionClassifier->classify(newArgs); - LOG_ALWAYS_FATAL_IF(args->classification != MotionClassification::NONE && + LOG_ALWAYS_FATAL_IF(args.classification != MotionClassification::NONE && newClassification != MotionClassification::NONE, "Conflicting classifications %s (new) and %s (old)!", motionClassificationToString(newClassification), - motionClassificationToString(args->classification)); + motionClassificationToString(args.classification)); newArgs.classification = newClassification; - mQueuedListener.notifyMotion(&newArgs); + mQueuedListener.notifyMotion(newArgs); } } // release lock mQueuedListener.flush(); } -void InputProcessor::notifySensor(const NotifySensorArgs* args) { +void InputProcessor::notifySensor(const NotifySensorArgs& args) { // pass through mQueuedListener.notifySensor(args); mQueuedListener.flush(); } -void InputProcessor::notifyVibratorState(const NotifyVibratorStateArgs* args) { +void InputProcessor::notifyVibratorState(const NotifyVibratorStateArgs& args) { // pass through mQueuedListener.notifyVibratorState(args); mQueuedListener.flush(); } -void InputProcessor::notifySwitch(const NotifySwitchArgs* args) { +void InputProcessor::notifySwitch(const NotifySwitchArgs& args) { // pass through mQueuedListener.notifySwitch(args); mQueuedListener.flush(); } -void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs* args) { +void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs& args) { { // acquire lock std::scoped_lock lock(mLock); if (mMotionClassifier) { - mMotionClassifier->reset(*args); + mMotionClassifier->reset(args); } } // release lock @@ -478,7 +484,7 @@ void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs* args) { mQueuedListener.flush(); } -void InputProcessor::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) { +void InputProcessor::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) { // pass through mQueuedListener.notifyPointerCaptureChanged(args); mQueuedListener.flush(); diff --git a/services/inputflinger/InputProcessor.h b/services/inputflinger/InputProcessor.h index f4d02b6f30..dcbfebc62f 100644 --- a/services/inputflinger/InputProcessor.h +++ b/services/inputflinger/InputProcessor.h @@ -245,14 +245,15 @@ class InputProcessor : public InputProcessorInterface { public: explicit InputProcessor(InputListenerInterface& listener); - void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; - void notifyKey(const NotifyKeyArgs* args) override; - void notifyMotion(const NotifyMotionArgs* args) override; - void notifySwitch(const NotifySwitchArgs* args) override; - void notifySensor(const NotifySensorArgs* args) override; - void notifyVibratorState(const NotifyVibratorStateArgs* args) override; - void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; - void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; + void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override; + void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override; + void notifyKey(const NotifyKeyArgs& args) override; + void notifyMotion(const NotifyMotionArgs& args) override; + void notifySwitch(const NotifySwitchArgs& args) override; + void notifySensor(const NotifySensorArgs& args) override; + void notifyVibratorState(const NotifyVibratorStateArgs& args) override; + void notifyDeviceReset(const NotifyDeviceResetArgs& args) override; + void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override; void dump(std::string& dump) override; void monitor() override; diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp index 2450235ec1..4ec5b898b1 100644 --- a/services/inputflinger/InputReaderBase.cpp +++ b/services/inputflinger/InputReaderBase.cpp @@ -38,50 +38,6 @@ namespace android { // --- InputReaderConfiguration --- -std::string InputReaderConfiguration::changesToString(uint32_t changes) { - if (changes == 0) { - return "<none>"; - } - std::string result; - if (changes & CHANGE_POINTER_SPEED) { - result += "POINTER_SPEED | "; - } - if (changes & CHANGE_POINTER_GESTURE_ENABLEMENT) { - result += "POINTER_GESTURE_ENABLEMENT | "; - } - if (changes & CHANGE_DISPLAY_INFO) { - result += "DISPLAY_INFO | "; - } - if (changes & CHANGE_SHOW_TOUCHES) { - result += "SHOW_TOUCHES | "; - } - if (changes & CHANGE_KEYBOARD_LAYOUTS) { - result += "KEYBOARD_LAYOUTS | "; - } - if (changes & CHANGE_DEVICE_ALIAS) { - result += "DEVICE_ALIAS | "; - } - if (changes & CHANGE_TOUCH_AFFINE_TRANSFORMATION) { - result += "TOUCH_AFFINE_TRANSFORMATION | "; - } - 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 | "; - } - if (changes & CHANGE_TOUCHPAD_SETTINGS) { - result += "TOUCHPAD_SETTINGS | "; - } - if (changes & CHANGE_MUST_REOPEN) { - result += "MUST_REOPEN | "; - } - return result; -} - std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewportByUniqueId( const std::string& uniqueDisplayId) const { if (uniqueDisplayId.empty()) { diff --git a/services/inputflinger/NotifyArgs.cpp b/services/inputflinger/NotifyArgs.cpp index 5f2a22f467..408fbed99e 100644 --- a/services/inputflinger/NotifyArgs.cpp +++ b/services/inputflinger/NotifyArgs.cpp @@ -29,6 +29,12 @@ using android::base::StringPrintf; namespace android { +// --- NotifyInputDevicesChangedArgs --- + +NotifyInputDevicesChangedArgs::NotifyInputDevicesChangedArgs(int32_t id, + std::vector<InputDeviceInfo> infos) + : id(id), inputDeviceInfos(std::move(infos)) {} + // --- NotifyConfigurationChangedArgs --- NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime) @@ -234,6 +240,7 @@ Visitor(V...) -> Visitor<V...>; const char* toString(const NotifyArgs& args) { Visitor toStringVisitor{ + [&](const NotifyInputDevicesChangedArgs&) { return "NotifyInputDevicesChangedArgs"; }, [&](const NotifyConfigurationChangedArgs&) { return "NotifyConfigurationChangedArgs"; }, [&](const NotifyKeyArgs&) { return "NotifyKeyArgs"; }, [&](const NotifyMotionArgs&) { return "NotifyMotionArgs"; }, diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp index ae20f862dc..02bc47d6bb 100644 --- a/services/inputflinger/UnwantedInteractionBlocker.cpp +++ b/services/inputflinger/UnwantedInteractionBlocker.cpp @@ -329,24 +329,24 @@ UnwantedInteractionBlocker::UnwantedInteractionBlocker(InputListenerInterface& l : mQueuedListener(listener), mEnablePalmRejection(enablePalmRejection) {} void UnwantedInteractionBlocker::notifyConfigurationChanged( - const NotifyConfigurationChangedArgs* args) { + const NotifyConfigurationChangedArgs& args) { mQueuedListener.notifyConfigurationChanged(args); mQueuedListener.flush(); } -void UnwantedInteractionBlocker::notifyKey(const NotifyKeyArgs* args) { +void UnwantedInteractionBlocker::notifyKey(const NotifyKeyArgs& args) { mQueuedListener.notifyKey(args); mQueuedListener.flush(); } -void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs* args) { - ALOGD_IF(DEBUG_INBOUND_MOTION, "%s: %s", __func__, args->dump().c_str()); +void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs& args) { + ALOGD_IF(DEBUG_INBOUND_MOTION, "%s: %s", __func__, args.dump().c_str()); { // acquire lock std::scoped_lock lock(mLock); const std::vector<NotifyMotionArgs> processedArgs = - mPreferStylusOverTouchBlocker.processMotion(*args); + mPreferStylusOverTouchBlocker.processMotion(args); for (const NotifyMotionArgs& loopArgs : processedArgs) { - notifyMotionLocked(&loopArgs); + notifyMotionLocked(loopArgs); } } // release lock @@ -356,61 +356,68 @@ void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs* args) { void UnwantedInteractionBlocker::enqueueOutboundMotionLocked(const NotifyMotionArgs& args) { ALOGD_IF(DEBUG_OUTBOUND_MOTION, "%s: %s", __func__, args.dump().c_str()); - mQueuedListener.notifyMotion(&args); + mQueuedListener.notifyMotion(args); } -void UnwantedInteractionBlocker::notifyMotionLocked(const NotifyMotionArgs* args) { - auto it = mPalmRejectors.find(args->deviceId); - const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args->source); +void UnwantedInteractionBlocker::notifyMotionLocked(const NotifyMotionArgs& args) { + auto it = mPalmRejectors.find(args.deviceId); + const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args.source); if (!sendToPalmRejector) { - enqueueOutboundMotionLocked(*args); + enqueueOutboundMotionLocked(args); return; } - std::vector<NotifyMotionArgs> processedArgs = it->second.processMotion(*args); + std::vector<NotifyMotionArgs> processedArgs = it->second.processMotion(args); for (const NotifyMotionArgs& loopArgs : processedArgs) { enqueueOutboundMotionLocked(loopArgs); } } -void UnwantedInteractionBlocker::notifySwitch(const NotifySwitchArgs* args) { +void UnwantedInteractionBlocker::notifySwitch(const NotifySwitchArgs& args) { mQueuedListener.notifySwitch(args); mQueuedListener.flush(); } -void UnwantedInteractionBlocker::notifySensor(const NotifySensorArgs* args) { +void UnwantedInteractionBlocker::notifySensor(const NotifySensorArgs& args) { mQueuedListener.notifySensor(args); mQueuedListener.flush(); } -void UnwantedInteractionBlocker::notifyVibratorState(const NotifyVibratorStateArgs* args) { +void UnwantedInteractionBlocker::notifyVibratorState(const NotifyVibratorStateArgs& args) { mQueuedListener.notifyVibratorState(args); mQueuedListener.flush(); } -void UnwantedInteractionBlocker::notifyDeviceReset(const NotifyDeviceResetArgs* args) { +void UnwantedInteractionBlocker::notifyDeviceReset(const NotifyDeviceResetArgs& args) { { // acquire lock std::scoped_lock lock(mLock); - auto it = mPalmRejectors.find(args->deviceId); + auto it = mPalmRejectors.find(args.deviceId); if (it != mPalmRejectors.end()) { AndroidPalmFilterDeviceInfo info = it->second.getPalmFilterDeviceInfo(); // Re-create the object instead of resetting it mPalmRejectors.erase(it); - mPalmRejectors.emplace(args->deviceId, info); + mPalmRejectors.emplace(args.deviceId, info); } mQueuedListener.notifyDeviceReset(args); - mPreferStylusOverTouchBlocker.notifyDeviceReset(*args); + mPreferStylusOverTouchBlocker.notifyDeviceReset(args); } // release lock // Send events to the next stage without holding the lock mQueuedListener.flush(); } void UnwantedInteractionBlocker::notifyPointerCaptureChanged( - const NotifyPointerCaptureChangedArgs* args) { + const NotifyPointerCaptureChangedArgs& args) { mQueuedListener.notifyPointerCaptureChanged(args); mQueuedListener.flush(); } void UnwantedInteractionBlocker::notifyInputDevicesChanged( + const NotifyInputDevicesChangedArgs& args) { + onInputDevicesChanged(args.inputDeviceInfos); + mQueuedListener.notify(args); + mQueuedListener.flush(); +} + +void UnwantedInteractionBlocker::onInputDevicesChanged( const std::vector<InputDeviceInfo>& inputDevices) { std::scoped_lock lock(mLock); if (!mEnablePalmRejection) { diff --git a/services/inputflinger/UnwantedInteractionBlocker.h b/services/inputflinger/UnwantedInteractionBlocker.h index 5d0dde8e64..419da8366e 100644 --- a/services/inputflinger/UnwantedInteractionBlocker.h +++ b/services/inputflinger/UnwantedInteractionBlocker.h @@ -90,16 +90,16 @@ public: explicit UnwantedInteractionBlocker(InputListenerInterface& listener); explicit UnwantedInteractionBlocker(InputListenerInterface& listener, bool enablePalmRejection); - void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; - void notifyKey(const NotifyKeyArgs* args) override; - void notifyMotion(const NotifyMotionArgs* args) override; - void notifySwitch(const NotifySwitchArgs* args) override; - void notifySensor(const NotifySensorArgs* args) override; - void notifyVibratorState(const NotifyVibratorStateArgs* args) override; - void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; - void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; - - void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override; + void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override; + void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override; + void notifyKey(const NotifyKeyArgs& args) override; + void notifyMotion(const NotifyMotionArgs& args) override; + void notifySwitch(const NotifySwitchArgs& args) override; + void notifySensor(const NotifySensorArgs& args) override; + void notifyVibratorState(const NotifyVibratorStateArgs& args) override; + void notifyDeviceReset(const NotifyDeviceResetArgs& args) override; + void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override; + void dump(std::string& dump) override; void monitor() override; @@ -119,10 +119,12 @@ private: // Use a separate palm rejector for every touch device. std::map<int32_t /*deviceId*/, PalmRejector> mPalmRejectors GUARDED_BY(mLock); // TODO(b/210159205): delete this when simultaneous stylus and touch is supported - void notifyMotionLocked(const NotifyMotionArgs* args) REQUIRES(mLock); + void notifyMotionLocked(const NotifyMotionArgs& args) REQUIRES(mLock); // Call this function for outbound events so that they can be logged when logging is enabled. void enqueueOutboundMotionLocked(const NotifyMotionArgs& args) REQUIRES(mLock); + + void onInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices); }; class SlotState { diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 58324c4762..f852001679 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -277,12 +277,12 @@ static void benchmarkNotifyMotion(benchmark::State& state) { motionArgs.action = AMOTION_EVENT_ACTION_DOWN; motionArgs.downTime = now(); motionArgs.eventTime = motionArgs.downTime; - dispatcher.notifyMotion(&motionArgs); + dispatcher.notifyMotion(motionArgs); // Send ACTION_UP motionArgs.action = AMOTION_EVENT_ACTION_UP; motionArgs.eventTime = now(); - dispatcher.notifyMotion(&motionArgs); + dispatcher.notifyMotion(motionArgs); window->consumeEvent(); window->consumeEvent(); diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp index b4497fd653..ed95de787c 100644 --- a/services/inputflinger/dispatcher/Connection.cpp +++ b/services/inputflinger/dispatcher/Connection.cpp @@ -28,8 +28,6 @@ Connection::Connection(const std::shared_ptr<InputChannel>& inputChannel, bool m inputPublisher(inputChannel), inputState(idGenerator) {} -Connection::~Connection() {} - const std::string Connection::getWindowName() const { if (inputChannel != nullptr) { return inputChannel->getName(); diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h index 6040e9b078..2929d61871 100644 --- a/services/inputflinger/dispatcher/Connection.h +++ b/services/inputflinger/dispatcher/Connection.h @@ -27,10 +27,7 @@ namespace android::inputdispatcher { struct DispatchEntry; /* Manages the dispatch state associated with a single input channel. */ -class Connection : public RefBase { -protected: - virtual ~Connection(); - +class Connection { public: enum class Status { // Everything is peachy. diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 6e2f86223f..6b9ad446ce 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -117,11 +117,7 @@ inline nsecs_t now() { return systemTime(SYSTEM_TIME_MONOTONIC); } -inline const char* toString(bool value) { - return value ? "true" : "false"; -} - -inline const std::string toString(const sp<IBinder>& binder) { +inline const std::string binderToString(const sp<IBinder>& binder) { if (binder == nullptr) { return "<null>"; } @@ -626,7 +622,9 @@ std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState, touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_ENTER; } else { // This pointer was already sent to the window. Use ACTION_HOVER_MOVE. - LOG_ALWAYS_FATAL_IF(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE); + if (CC_UNLIKELY(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE)) { + LOG(FATAL) << "Expected ACTION_HOVER_MOVE instead of " << entry.getDescription(); + } touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_IS; } touchedWindow.pointerIds.set(pointerId); @@ -690,7 +688,7 @@ InputDispatcher::~InputDispatcher() { mCommandQueue.clear(); while (!mConnectionsByToken.empty()) { - sp<Connection> connection = mConnectionsByToken.begin()->second; + std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second; removeInputChannelLocked(connection->inputChannel->getConnectionToken(), /*notify=*/false); } } @@ -804,7 +802,7 @@ nsecs_t InputDispatcher::processAnrsLocked() { } // If we reached here, we have an unresponsive connection. - sp<Connection> connection = getConnectionLocked(mAnrTracker.firstToken()); + std::shared_ptr<Connection> connection = getConnectionLocked(mAnrTracker.firstToken()); if (connection == nullptr) { ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout()); return nextAnrCheck; @@ -817,7 +815,7 @@ nsecs_t InputDispatcher::processAnrsLocked() { } std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked( - const sp<Connection>& connection) { + const std::shared_ptr<Connection>& connection) { if (connection->monitor) { return mMonitorDispatchingTimeout; } @@ -1060,7 +1058,8 @@ bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEnt const std::vector<sp<WindowInfoHandle>> touchedSpies = findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus); for (const auto& windowHandle : touchedSpies) { - const sp<Connection> connection = getConnectionLocked(windowHandle->getToken()); + const std::shared_ptr<Connection> connection = + getConnectionLocked(windowHandle->getToken()); if (connection != nullptr && connection->responsive) { // This spy window could take more input. Drop all events preceding this // event, so that the spy window can get a chance to receive the stream. @@ -1299,7 +1298,7 @@ bool InputDispatcher::isAppSwitchKeyEvent(const KeyEntry& keyEntry) { (keyEntry.policyFlags & POLICY_FLAG_PASS_TO_USER); } -bool InputDispatcher::isAppSwitchPendingLocked() { +bool InputDispatcher::isAppSwitchPendingLocked() const { return mAppSwitchDueTime != LLONG_MAX; } @@ -1897,7 +1896,7 @@ void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, pokeUserActivityLocked(*eventEntry); for (const InputTarget& inputTarget : inputTargets) { - sp<Connection> connection = + std::shared_ptr<Connection> connection = getConnectionLocked(inputTarget.inputChannel->getConnectionToken()); if (connection != nullptr) { prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget); @@ -1911,7 +1910,7 @@ void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, } } -void InputDispatcher::cancelEventsForAnrLocked(const sp<Connection>& connection) { +void InputDispatcher::cancelEventsForAnrLocked(const std::shared_ptr<Connection>& connection) { // We will not be breaking any connections here, even if the policy wants us to abort dispatch. // If the policy decides to close the app, we will get a channel removal event via // unregisterInputChannel, and will clean up the connection that way. We are already not @@ -2103,7 +2102,7 @@ std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked( std::vector<Monitor> responsiveMonitors; std::copy_if(monitors.begin(), monitors.end(), std::back_inserter(responsiveMonitors), [this](const Monitor& monitor) REQUIRES(mLock) { - sp<Connection> connection = + std::shared_ptr<Connection> connection = getConnectionLocked(monitor.inputChannel->getConnectionToken()); if (connection == nullptr) { ALOGE("Could not find connection for monitor %s", @@ -2907,7 +2906,7 @@ std::string InputDispatcher::dumpWindowForTouchOcclusion(const WindowInfo* info, info->frameBottom, dumpRegion(info->touchableRegion).c_str(), info->name.c_str(), info->inputConfig.string().c_str(), toString(info->token != nullptr), info->applicationInfo.name.c_str(), - toString(info->applicationInfo.token).c_str()); + binderToString(info->applicationInfo.token).c_str()); } bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const { @@ -3029,7 +3028,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { } void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection, + const std::shared_ptr<Connection>& connection, std::shared_ptr<EventEntry> eventEntry, const InputTarget& inputTarget) { if (ATRACE_ENABLED()) { @@ -3099,7 +3098,7 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, } void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, - const sp<Connection>& connection, + const std::shared_ptr<Connection>& connection, std::shared_ptr<EventEntry> eventEntry, const InputTarget& inputTarget) { if (ATRACE_ENABLED()) { @@ -3133,7 +3132,7 @@ void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, } } -void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection, +void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection, std::shared_ptr<EventEntry> eventEntry, const InputTarget& inputTarget, ftl::Flags<InputTarget::Flags> dispatchMode) { @@ -3318,14 +3317,14 @@ void InputDispatcher::updateInteractionTokensLocked(const EventEntry& entry, } std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> newConnectionTokens; - std::vector<sp<Connection>> newConnections; + std::vector<std::shared_ptr<Connection>> newConnections; for (const InputTarget& target : targets) { if (target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) { continue; // Skip windows that receive ACTION_OUTSIDE } sp<IBinder> token = target.inputChannel->getConnectionToken(); - sp<Connection> connection = getConnectionLocked(token); + std::shared_ptr<Connection> connection = getConnectionLocked(token); if (connection == nullptr) { continue; } @@ -3338,7 +3337,7 @@ void InputDispatcher::updateInteractionTokensLocked(const EventEntry& entry, mInteractionConnectionTokens = newConnectionTokens; std::string targetList; - for (const sp<Connection>& connection : newConnections) { + for (const std::shared_ptr<Connection>& connection : newConnections) { targetList += connection->getWindowName() + ", "; } std::string message = "Interaction with: " + targetList; @@ -3418,7 +3417,7 @@ status_t InputDispatcher::publishMotionEvent(Connection& connection, } void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection) { + const std::shared_ptr<Connection>& connection) { if (ATRACE_ENABLED()) { std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)", connection->getInputChannelName().c_str()); @@ -3598,8 +3597,8 @@ const std::array<uint8_t, 32> InputDispatcher::getSignature( } void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection, uint32_t seq, - bool handled, nsecs_t consumeTime) { + const std::shared_ptr<Connection>& connection, + uint32_t seq, bool handled, nsecs_t consumeTime) { if (DEBUG_DISPATCH_CYCLE) { ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s", connection->getInputChannelName().c_str(), seq, toString(handled)); @@ -3618,11 +3617,11 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, } void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime, - const sp<Connection>& connection, + const std::shared_ptr<Connection>& connection, bool notify) { if (DEBUG_DISPATCH_CYCLE) { - ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s", - connection->getInputChannelName().c_str(), toString(notify)); + LOG(DEBUG) << "channel '" << connection->getInputChannelName() << "'~ " << __func__ + << " - notify=" << toString(notify); } // Clear the dispatch queues. @@ -3667,7 +3666,7 @@ void InputDispatcher::releaseDispatchEntry(DispatchEntry* dispatchEntry) { int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) { std::scoped_lock _l(mLock); - sp<Connection> connection = getConnectionLocked(connectionToken); + std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken); if (connection == nullptr) { ALOGW("Received looper callback for unknown input channel token %p. events=0x%x", connectionToken.get(), events); @@ -3759,7 +3758,7 @@ void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked( void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked( const std::shared_ptr<InputChannel>& channel, const CancelationOptions& options) { - sp<Connection> connection = getConnectionLocked(channel->getConnectionToken()); + std::shared_ptr<Connection> connection = getConnectionLocked(channel->getConnectionToken()); if (connection == nullptr) { return; } @@ -3768,7 +3767,7 @@ void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked( } void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( - const sp<Connection>& connection, const CancelationOptions& options) { + const std::shared_ptr<Connection>& connection, const CancelationOptions& options) { if (connection->status == Connection::Status::BROKEN) { return; } @@ -3846,7 +3845,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( } void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( - const nsecs_t downTime, const sp<Connection>& connection, + const nsecs_t downTime, const std::shared_ptr<Connection>& connection, ftl::Flags<InputTarget::Flags> targetFlags) { if (connection->status == Connection::Status::BROKEN) { return; @@ -3911,7 +3910,8 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( void InputDispatcher::synthesizeCancelationEventsForWindowLocked( const sp<WindowInfoHandle>& windowHandle, const CancelationOptions& options) { if (windowHandle != nullptr) { - sp<Connection> wallpaperConnection = getConnectionLocked(windowHandle->getToken()); + std::shared_ptr<Connection> wallpaperConnection = + getConnectionLocked(windowHandle->getToken()); if (wallpaperConnection != nullptr) { synthesizeCancelationEventsForConnectionLocked(wallpaperConnection, options); } @@ -4027,9 +4027,9 @@ std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent( return splitMotionEntry; } -void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { +void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) { if (debugInboundEventDetails()) { - ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime); + ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args.eventTime); } bool needWake = false; @@ -4037,7 +4037,7 @@ void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChange std::scoped_lock _l(mLock); std::unique_ptr<ConfigurationChangedEntry> newEntry = - std::make_unique<ConfigurationChangedEntry>(args->id, args->eventTime); + std::make_unique<ConfigurationChangedEntry>(args.id, args.eventTime); needWake = enqueueInboundEventLocked(std::move(newEntry)); } // release lock @@ -4085,23 +4085,22 @@ void InputDispatcher::accelerateMetaShortcuts(const int32_t deviceId, const int3 } } -void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { +void InputDispatcher::notifyKey(const NotifyKeyArgs& args) { ALOGD_IF(debugInboundEventDetails(), "notifyKey - id=%" PRIx32 ", eventTime=%" PRId64 ", deviceId=%d, source=%s, displayId=%" PRId32 "policyFlags=0x%x, action=%s, flags=0x%x, keyCode=%s, scanCode=0x%x, metaState=0x%x, " "downTime=%" PRId64, - args->id, args->eventTime, args->deviceId, - inputEventSourceToString(args->source).c_str(), args->displayId, args->policyFlags, - KeyEvent::actionToString(args->action), args->flags, KeyEvent::getLabel(args->keyCode), - args->scanCode, args->metaState, args->downTime); - if (!validateKeyEvent(args->action)) { + args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(), + args.displayId, args.policyFlags, KeyEvent::actionToString(args.action), args.flags, + KeyEvent::getLabel(args.keyCode), args.scanCode, args.metaState, args.downTime); + if (!validateKeyEvent(args.action)) { return; } - uint32_t policyFlags = args->policyFlags; - int32_t flags = args->flags; - int32_t metaState = args->metaState; + uint32_t policyFlags = args.policyFlags; + int32_t flags = args.flags; + int32_t metaState = args.metaState; // InputDispatcher tracks and generates key repeats on behalf of // whatever notifies it, so repeatCount should always be set to 0 constexpr int32_t repeatCount = 0; @@ -4115,13 +4114,13 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { policyFlags |= POLICY_FLAG_TRUSTED; - int32_t keyCode = args->keyCode; - accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState); + int32_t keyCode = args.keyCode; + accelerateMetaShortcuts(args.deviceId, args.action, keyCode, metaState); KeyEvent event; - event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC, - args->action, flags, keyCode, args->scanCode, metaState, repeatCount, - args->downTime, args->eventTime); + event.initialize(args.id, args.deviceId, args.source, args.displayId, INVALID_HMAC, args.action, + flags, keyCode, args.scanCode, metaState, repeatCount, args.downTime, + args.eventTime); android::base::Timer t; mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); @@ -4146,10 +4145,9 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { } std::unique_ptr<KeyEntry> newEntry = - std::make_unique<KeyEntry>(args->id, args->eventTime, args->deviceId, args->source, - args->displayId, policyFlags, args->action, flags, - keyCode, args->scanCode, metaState, repeatCount, - args->downTime); + std::make_unique<KeyEntry>(args.id, args.eventTime, args.deviceId, args.source, + args.displayId, policyFlags, args.action, flags, keyCode, + args.scanCode, metaState, repeatCount, args.downTime); needWake = enqueueInboundEventLocked(std::move(newEntry)); mLock.unlock(); @@ -4160,50 +4158,50 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { } } -bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) { +bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs& args) { return mInputFilterEnabled; } -void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { +void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) { if (debugInboundEventDetails()) { ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=%s, " "displayId=%" PRId32 ", policyFlags=0x%x, " "action=%s, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, " "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, " "yCursorPosition=%f, downTime=%" PRId64, - args->id, args->eventTime, args->deviceId, - inputEventSourceToString(args->source).c_str(), args->displayId, args->policyFlags, - MotionEvent::actionToString(args->action).c_str(), args->actionButton, args->flags, - args->metaState, args->buttonState, args->edgeFlags, args->xPrecision, - args->yPrecision, args->xCursorPosition, args->yCursorPosition, args->downTime); - for (uint32_t i = 0; i < args->pointerCount; i++) { + args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(), + args.displayId, args.policyFlags, MotionEvent::actionToString(args.action).c_str(), + args.actionButton, args.flags, args.metaState, args.buttonState, args.edgeFlags, + args.xPrecision, args.yPrecision, args.xCursorPosition, args.yCursorPosition, + args.downTime); + for (uint32_t i = 0; i < args.pointerCount; i++) { ALOGD(" Pointer %d: id=%d, toolType=%s, x=%f, y=%f, pressure=%f, size=%f, " "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, orientation=%f", - i, args->pointerProperties[i].id, - ftl::enum_string(args->pointerProperties[i].toolType).c_str(), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), - args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); - } - } - - if (!validateMotionEvent(args->action, args->actionButton, args->pointerCount, - args->pointerProperties)) { - LOG(ERROR) << "Invalid event: " << args->dump(); + i, args.pointerProperties[i].id, + ftl::enum_string(args.pointerProperties[i].toolType).c_str(), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), + args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); + } + } + + if (!validateMotionEvent(args.action, args.actionButton, args.pointerCount, + args.pointerProperties)) { + LOG(ERROR) << "Invalid event: " << args.dump(); return; } - uint32_t policyFlags = args->policyFlags; + uint32_t policyFlags = args.policyFlags; policyFlags |= POLICY_FLAG_TRUSTED; android::base::Timer t; - mPolicy->interceptMotionBeforeQueueing(args->displayId, args->eventTime, /*byref*/ policyFlags); + mPolicy->interceptMotionBeforeQueueing(args.displayId, args.eventTime, policyFlags); if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) { ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms", std::to_string(t.duration().count()).c_str()); @@ -4215,10 +4213,10 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) { // Set the flag anyway if we already have an ongoing gesture. That would allow us to // complete the processing of the current stroke. - const auto touchStateIt = mTouchStatesByDisplay.find(args->displayId); + const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId); if (touchStateIt != mTouchStatesByDisplay.end()) { const TouchState& touchState = touchStateIt->second; - if (touchState.deviceId == args->deviceId && touchState.isDown()) { + if (touchState.deviceId == args.deviceId && touchState.isDown()) { policyFlags |= POLICY_FLAG_PASS_TO_USER; } } @@ -4226,20 +4224,20 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { if (shouldSendMotionToInputFilterLocked(args)) { ui::Transform displayTransform; - if (const auto it = mDisplayInfos.find(args->displayId); it != mDisplayInfos.end()) { + if (const auto it = mDisplayInfos.find(args.displayId); it != mDisplayInfos.end()) { displayTransform = it->second.transform; } mLock.unlock(); MotionEvent event; - event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC, - args->action, args->actionButton, args->flags, args->edgeFlags, - args->metaState, args->buttonState, args->classification, - displayTransform, args->xPrecision, args->yPrecision, - args->xCursorPosition, args->yCursorPosition, displayTransform, - args->downTime, args->eventTime, args->pointerCount, - args->pointerProperties, args->pointerCoords); + event.initialize(args.id, args.deviceId, args.source, args.displayId, INVALID_HMAC, + args.action, args.actionButton, args.flags, args.edgeFlags, + args.metaState, args.buttonState, args.classification, + displayTransform, args.xPrecision, args.yPrecision, + args.xCursorPosition, args.yCursorPosition, displayTransform, + args.downTime, args.eventTime, args.pointerCount, + args.pointerProperties, args.pointerCoords); policyFlags |= POLICY_FLAG_FILTERED; if (!mPolicy->filterInputEvent(&event, policyFlags)) { @@ -4251,21 +4249,20 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { // Just enqueue a new motion event. std::unique_ptr<MotionEntry> newEntry = - std::make_unique<MotionEntry>(args->id, args->eventTime, args->deviceId, - args->source, args->displayId, policyFlags, - args->action, args->actionButton, args->flags, - args->metaState, args->buttonState, - args->classification, args->edgeFlags, - args->xPrecision, args->yPrecision, - args->xCursorPosition, args->yCursorPosition, - args->downTime, args->pointerCount, - args->pointerProperties, args->pointerCoords); - - if (args->id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID && - IdGenerator::getSource(args->id) == IdGenerator::Source::INPUT_READER && + std::make_unique<MotionEntry>(args.id, args.eventTime, args.deviceId, args.source, + args.displayId, policyFlags, args.action, + args.actionButton, args.flags, args.metaState, + args.buttonState, args.classification, args.edgeFlags, + args.xPrecision, args.yPrecision, + args.xCursorPosition, args.yCursorPosition, + args.downTime, args.pointerCount, + args.pointerProperties, args.pointerCoords); + + if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID && + IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER && !mInputFilterEnabled) { - const bool isDown = args->action == AMOTION_EVENT_ACTION_DOWN; - mLatencyTracker.trackListener(args->id, isDown, args->eventTime, args->readTime); + const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN; + mLatencyTracker.trackListener(args.id, isDown, args.eventTime, args.readTime); } needWake = enqueueInboundEventLocked(std::move(newEntry)); @@ -4277,12 +4274,12 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { } } -void InputDispatcher::notifySensor(const NotifySensorArgs* args) { +void InputDispatcher::notifySensor(const NotifySensorArgs& args) { if (debugInboundEventDetails()) { ALOGD("notifySensor - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, " " sensorType=%s", - args->id, args->eventTime, args->deviceId, args->source, - ftl::enum_string(args->sensorType).c_str()); + args.id, args.eventTime, args.deviceId, args.source, + ftl::enum_string(args.sensorType).c_str()); } bool needWake = false; @@ -4291,10 +4288,9 @@ void InputDispatcher::notifySensor(const NotifySensorArgs* args) { // Just enqueue a new sensor event. std::unique_ptr<SensorEntry> newEntry = - std::make_unique<SensorEntry>(args->id, args->eventTime, args->deviceId, - args->source, /* policyFlags=*/0, args->hwTimestamp, - args->sensorType, args->accuracy, - args->accuracyChanged, args->values); + std::make_unique<SensorEntry>(args.id, args.eventTime, args.deviceId, args.source, + /* policyFlags=*/0, args.hwTimestamp, args.sensorType, + args.accuracy, args.accuracyChanged, args.values); needWake = enqueueInboundEventLocked(std::move(newEntry)); mLock.unlock(); @@ -4305,34 +4301,34 @@ void InputDispatcher::notifySensor(const NotifySensorArgs* args) { } } -void InputDispatcher::notifyVibratorState(const NotifyVibratorStateArgs* args) { +void InputDispatcher::notifyVibratorState(const NotifyVibratorStateArgs& args) { if (debugInboundEventDetails()) { - ALOGD("notifyVibratorState - eventTime=%" PRId64 ", device=%d, isOn=%d", args->eventTime, - args->deviceId, args->isOn); + ALOGD("notifyVibratorState - eventTime=%" PRId64 ", device=%d, isOn=%d", args.eventTime, + args.deviceId, args.isOn); } - mPolicy->notifyVibratorState(args->deviceId, args->isOn); + mPolicy->notifyVibratorState(args.deviceId, args.isOn); } -bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) { +bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs& args) { return mInputFilterEnabled; } -void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) { +void InputDispatcher::notifySwitch(const NotifySwitchArgs& args) { if (debugInboundEventDetails()) { ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, " "switchMask=0x%08x", - args->eventTime, args->policyFlags, args->switchValues, args->switchMask); + args.eventTime, args.policyFlags, args.switchValues, args.switchMask); } - uint32_t policyFlags = args->policyFlags; + uint32_t policyFlags = args.policyFlags; policyFlags |= POLICY_FLAG_TRUSTED; - mPolicy->notifySwitch(args->eventTime, args->switchValues, args->switchMask, policyFlags); + mPolicy->notifySwitch(args.eventTime, args.switchValues, args.switchMask, policyFlags); } -void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { +void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs& args) { if (debugInboundEventDetails()) { - ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args->eventTime, - args->deviceId); + ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args.eventTime, + args.deviceId); } bool needWake = false; @@ -4340,7 +4336,7 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { std::scoped_lock _l(mLock); std::unique_ptr<DeviceResetEntry> newEntry = - std::make_unique<DeviceResetEntry>(args->id, args->eventTime, args->deviceId); + std::make_unique<DeviceResetEntry>(args.id, args.eventTime, args.deviceId); needWake = enqueueInboundEventLocked(std::move(newEntry)); } // release lock @@ -4349,17 +4345,17 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) { } } -void InputDispatcher::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) { +void InputDispatcher::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) { if (debugInboundEventDetails()) { - ALOGD("notifyPointerCaptureChanged - eventTime=%" PRId64 ", enabled=%s", args->eventTime, - args->request.enable ? "true" : "false"); + ALOGD("notifyPointerCaptureChanged - eventTime=%" PRId64 ", enabled=%s", args.eventTime, + args.request.enable ? "true" : "false"); } bool needWake = false; { // acquire lock std::scoped_lock _l(mLock); - auto entry = std::make_unique<PointerCaptureChangedEntry>(args->id, args->eventTime, - args->request); + auto entry = + std::make_unique<PointerCaptureChangedEntry>(args.id, args.eventTime, args.request); needWake = enqueueInboundEventLocked(std::move(entry)); } // release lock @@ -4374,10 +4370,10 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev std::chrono::milliseconds timeout, uint32_t policyFlags) { if (debugInboundEventDetails()) { - ALOGD("injectInputEvent - eventType=%d, targetUid=%s, syncMode=%d, timeout=%lld, " - "policyFlags=0x%08x", - event->getType(), targetUid ? std::to_string(*targetUid).c_str() : "none", syncMode, - timeout.count(), policyFlags); + LOG(DEBUG) << __func__ << ": targetUid=" << toString(targetUid) + << ", syncMode=" << ftl::enum_string(syncMode) << ", timeout=" << timeout.count() + << "ms, policyFlags=0x" << std::hex << policyFlags << std::dec + << ", event=" << *event; } nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count(); @@ -4396,7 +4392,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev std::queue<std::unique_ptr<EventEntry>> injectedEntries; switch (event->getType()) { - case AINPUT_EVENT_TYPE_KEY: { + case InputEventType::KEY: { const KeyEvent& incomingKey = static_cast<const KeyEvent&>(*event); int32_t action = incomingKey.getAction(); if (!validateKeyEvent(action)) { @@ -4442,7 +4438,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev break; } - case AINPUT_EVENT_TYPE_MOTION: { + case InputEventType::MOTION: { const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event); const int32_t action = motionEvent.getAction(); const bool isPointerEvent = @@ -4518,7 +4514,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev } default: - ALOGW("Cannot inject %s events", inputEventTypeToString(event->getType())); + LOG(WARNING) << "Cannot inject " << ftl::enum_string(event->getType()) << " events"; return InputEventInjectionResult::FAILED; } @@ -4608,14 +4604,14 @@ std::unique_ptr<VerifiedInputEvent> InputDispatcher::verifyInputEvent(const Inpu std::array<uint8_t, 32> calculatedHmac; std::unique_ptr<VerifiedInputEvent> result; switch (event.getType()) { - case AINPUT_EVENT_TYPE_KEY: { + case InputEventType::KEY: { const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event); VerifiedKeyEvent verifiedKeyEvent = verifiedKeyEventFromKeyEvent(keyEvent); result = std::make_unique<VerifiedKeyEvent>(verifiedKeyEvent); calculatedHmac = sign(verifiedKeyEvent); break; } - case AINPUT_EVENT_TYPE_MOTION: { + case InputEventType::MOTION: { const MotionEvent& motionEvent = static_cast<const MotionEvent&>(event); VerifiedMotionEvent verifiedMotionEvent = verifiedMotionEventFromMotionEvent(motionEvent); @@ -4802,7 +4798,7 @@ bool InputDispatcher::canWindowReceiveMotionLocked(const sp<WindowInfoHandle>& w return false; } - sp<Connection> connection = getConnectionLocked(window->getToken()); + std::shared_ptr<Connection> connection = getConnectionLocked(window->getToken()); if (connection == nullptr) { ALOGW("Not sending touch to %s because there's no corresponding connection", window->getName().c_str()); @@ -5324,8 +5320,8 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< } // Synthesize cancel for old window and down for new window. - sp<Connection> fromConnection = getConnectionLocked(fromToken); - sp<Connection> toConnection = getConnectionLocked(toToken); + std::shared_ptr<Connection> fromConnection = getConnectionLocked(fromToken); + std::shared_ptr<Connection> toConnection = getConnectionLocked(toToken); if (fromConnection != nullptr && toConnection != nullptr) { fromConnection->inputState.mergePointerStateTo(toConnection->inputState); CancelationOptions @@ -5417,7 +5413,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { mReplacedKeys.clear(); } -void InputDispatcher::logDispatchStateLocked() { +void InputDispatcher::logDispatchStateLocked() const { std::string dump; dumpDispatchStateLocked(dump); @@ -5429,7 +5425,7 @@ void InputDispatcher::logDispatchStateLocked() { } } -std::string InputDispatcher::dumpPointerCaptureStateLocked() { +std::string InputDispatcher::dumpPointerCaptureStateLocked() const { std::string dump; dump += StringPrintf(INDENT "Pointer Capture Requested: %s\n", @@ -5447,7 +5443,7 @@ std::string InputDispatcher::dumpPointerCaptureStateLocked() { return dump; } -void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { +void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { dump += StringPrintf(INDENT "DispatchEnabled: %s\n", toString(mDispatchEnabled)); dump += StringPrintf(INDENT "DispatchFrozen: %s\n", toString(mDispatchFrozen)); dump += StringPrintf(INDENT "InputFilterEnabled: %s\n", toString(mInputFilterEnabled)); @@ -5517,14 +5513,14 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { windowInfo->frameTop, windowInfo->frameRight, windowInfo->frameBottom, windowInfo->globalScaleFactor, windowInfo->applicationInfo.name.c_str(), - toString(windowInfo->applicationInfo.token).c_str()); + binderToString(windowInfo->applicationInfo.token).c_str()); dump += dumpRegion(windowInfo->touchableRegion); dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%" PRId64 "ms, hasToken=%s, " "touchOcclusionMode=%s\n", windowInfo->ownerPid, windowInfo->ownerUid, millis(windowInfo->dispatchingTimeout), - toString(windowInfo->token != nullptr), + binderToString(windowInfo->token).c_str(), toString(windowInfo->touchOcclusionMode).c_str()); windowInfo->transform.dump(dump, "transform", INDENT4); } @@ -5550,7 +5546,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { // Dump recently dispatched or dropped events from oldest to newest. if (!mRecentQueue.empty()) { dump += StringPrintf(INDENT "RecentQueue: length=%zu\n", mRecentQueue.size()); - for (std::shared_ptr<EventEntry>& entry : mRecentQueue) { + for (const std::shared_ptr<EventEntry>& entry : mRecentQueue) { dump += INDENT2; dump += entry->getDescription(); dump += StringPrintf(", age=%" PRId64 "ms\n", ns2ms(currentTime - entry->eventTime)); @@ -5573,7 +5569,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { // Dump inbound events from oldest to newest. if (!mInboundQueue.empty()) { dump += StringPrintf(INDENT "InboundQueue: length=%zu\n", mInboundQueue.size()); - for (std::shared_ptr<EventEntry>& entry : mInboundQueue) { + for (const std::shared_ptr<EventEntry>& entry : mInboundQueue) { dump += INDENT2; dump += entry->getDescription(); dump += StringPrintf(", age=%" PRId64 "ms\n", ns2ms(currentTime - entry->eventTime)); @@ -5655,7 +5651,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += mLatencyAggregator.dump(INDENT2); } -void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) { +void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const { const size_t numMonitors = monitors.size(); for (size_t i = 0; i < numMonitors; i++) { const Monitor& monitor = monitors[i]; @@ -5691,8 +5687,9 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::scoped_lock _l(mLock); const sp<IBinder>& token = serverChannel->getConnectionToken(); int fd = serverChannel->getFd(); - sp<Connection> connection = - sp<Connection>::make(std::move(serverChannel), /*monitor=*/false, mIdGenerator); + std::shared_ptr<Connection> connection = + std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false, + mIdGenerator); if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) { ALOGE("Created a new connection, but the token %p is already known", token.get()); @@ -5729,8 +5726,8 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_ << " without a specified display."; } - sp<Connection> connection = - sp<Connection>::make(serverChannel, /*monitor=*/true, mIdGenerator); + std::shared_ptr<Connection> connection = + std::make_shared<Connection>(serverChannel, /*monitor=*/true, mIdGenerator); const sp<IBinder>& token = serverChannel->getConnectionToken(); const int fd = serverChannel->getFd(); @@ -5770,7 +5767,7 @@ status_t InputDispatcher::removeInputChannel(const sp<IBinder>& connectionToken) status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connectionToken, bool notify) { - sp<Connection> connection = getConnectionLocked(connectionToken); + std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken); if (connection == nullptr) { // Connection can be removed via socket hang up or an explicit call to 'removeInputChannel' return BAD_VALUE; @@ -5916,7 +5913,8 @@ std::optional<int32_t> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBi return std::nullopt; } -sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const { +std::shared_ptr<Connection> InputDispatcher::getConnectionLocked( + const sp<IBinder>& inputConnectionToken) const { if (inputConnectionToken == nullptr) { return nullptr; } @@ -5931,21 +5929,22 @@ sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConn } std::string InputDispatcher::getConnectionNameLocked(const sp<IBinder>& connectionToken) const { - sp<Connection> connection = getConnectionLocked(connectionToken); + std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken); if (connection == nullptr) { return "<nullptr>"; } return connection->getInputChannelName(); } -void InputDispatcher::removeConnectionLocked(const sp<Connection>& connection) { +void InputDispatcher::removeConnectionLocked(const std::shared_ptr<Connection>& connection) { mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); mConnectionsByToken.erase(connection->inputChannel->getConnectionToken()); } void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime, - const sp<Connection>& connection, uint32_t seq, - bool handled, nsecs_t consumeTime) { + const std::shared_ptr<Connection>& connection, + uint32_t seq, bool handled, + nsecs_t consumeTime) { // Handle post-event policy actions. std::deque<DispatchEntry*>::iterator dispatchEntryIt = connection->findWaitQueueEntry(seq); if (dispatchEntryIt == connection->waitQueue.end()) { @@ -6023,7 +6022,7 @@ void InputDispatcher::sendDropWindowCommandLocked(const sp<IBinder>& token, floa postCommandLocked(std::move(command)); } -void InputDispatcher::onAnrLocked(const sp<Connection>& connection) { +void InputDispatcher::onAnrLocked(const std::shared_ptr<Connection>& connection) { if (connection == nullptr) { LOG_ALWAYS_FATAL("Caller must check for nullness"); } @@ -6185,9 +6184,9 @@ void InputDispatcher::processConnectionResponsiveLocked(const Connection& connec sendWindowResponsiveCommandLocked(connectionToken, pid); } -bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& connection, - DispatchEntry* dispatchEntry, - KeyEntry& keyEntry, bool handled) { +bool InputDispatcher::afterKeyEventLockedInterruptable( + const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, + KeyEntry& keyEntry, bool handled) { if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) { if (!handled) { // Report the key as unhandled, since the fallback was not handled. @@ -6199,7 +6198,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con // Get the fallback key state. // Clear it out after dispatching the UP. int32_t originalKeyCode = keyEntry.keyCode; - int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode); + std::optional<int32_t> fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode); if (keyEntry.action == AKEY_EVENT_ACTION_UP) { connection->inputState.removeFallbackKey(originalKeyCode); } @@ -6208,7 +6207,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con // If the application handles the original key for which we previously // generated a fallback or if the window is not a foreground window, // then cancel the associated fallback key, if any. - if (fallbackKeyCode != -1) { + if (fallbackKeyCode) { // Dispatch the unhandled key to the policy with the cancel flag. if (DEBUG_OUTBOUND_EVENT_DETAILS) { ALOGD("Unhandled key event: Asking policy to cancel fallback action. " @@ -6227,12 +6226,12 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con mLock.lock(); // Cancel the fallback key. - if (fallbackKeyCode != AKEYCODE_UNKNOWN) { + if (*fallbackKeyCode != AKEYCODE_UNKNOWN) { CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS, "application handled the original non-fallback key " "or is no longer a foreground target, " "canceling previously dispatched fallback key"); - options.keyCode = fallbackKeyCode; + options.keyCode = *fallbackKeyCode; synthesizeCancelationEventsForConnectionLocked(connection, options); } connection->inputState.removeFallbackKey(originalKeyCode); @@ -6242,7 +6241,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con // that we are in a good state to perform unhandled key event processing // Then ask the policy what to do with it. bool initialDown = keyEntry.action == AKEY_EVENT_ACTION_DOWN && keyEntry.repeatCount == 0; - if (fallbackKeyCode == -1 && !initialDown) { + if (!fallbackKeyCode && !initialDown) { if (DEBUG_OUTBOUND_EVENT_DETAILS) { ALOGD("Unhandled key event: Skipping unhandled key event processing " "since this is not an initial down. " @@ -6277,53 +6276,53 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con // The fallback keycode cannot change at any other point in the lifecycle. if (initialDown) { if (fallback) { - fallbackKeyCode = event.getKeyCode(); + *fallbackKeyCode = event.getKeyCode(); } else { - fallbackKeyCode = AKEYCODE_UNKNOWN; + *fallbackKeyCode = AKEYCODE_UNKNOWN; } - connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode); + connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode); } - ALOG_ASSERT(fallbackKeyCode != -1); + ALOG_ASSERT(fallbackKeyCode); // Cancel the fallback key if the policy decides not to send it anymore. // We will continue to dispatch the key to the policy but we will no // longer dispatch a fallback key to the application. - if (fallbackKeyCode != AKEYCODE_UNKNOWN && - (!fallback || fallbackKeyCode != event.getKeyCode())) { + if (*fallbackKeyCode != AKEYCODE_UNKNOWN && + (!fallback || *fallbackKeyCode != event.getKeyCode())) { if (DEBUG_OUTBOUND_EVENT_DETAILS) { if (fallback) { ALOGD("Unhandled key event: Policy requested to send key %d" "as a fallback for %d, but on the DOWN it had requested " "to send %d instead. Fallback canceled.", - event.getKeyCode(), originalKeyCode, fallbackKeyCode); + event.getKeyCode(), originalKeyCode, *fallbackKeyCode); } else { ALOGD("Unhandled key event: Policy did not request fallback for %d, " "but on the DOWN it had requested to send %d. " "Fallback canceled.", - originalKeyCode, fallbackKeyCode); + originalKeyCode, *fallbackKeyCode); } } CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS, "canceling fallback, policy no longer desires it"); - options.keyCode = fallbackKeyCode; + options.keyCode = *fallbackKeyCode; synthesizeCancelationEventsForConnectionLocked(connection, options); fallback = false; - fallbackKeyCode = AKEYCODE_UNKNOWN; + *fallbackKeyCode = AKEYCODE_UNKNOWN; if (keyEntry.action != AKEY_EVENT_ACTION_UP) { - connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode); + connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode); } } if (DEBUG_OUTBOUND_EVENT_DETAILS) { { std::string msg; - const KeyedVector<int32_t, int32_t>& fallbackKeys = + const std::map<int32_t, int32_t>& fallbackKeys = connection->inputState.getFallbackKeys(); - for (size_t i = 0; i < fallbackKeys.size(); i++) { - msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i), fallbackKeys.valueAt(i)); + for (const auto& [key, value] : fallbackKeys) { + msg += StringPrintf(", %d->%d", key, value); } ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.", fallbackKeys.size(), msg.c_str()); @@ -6337,7 +6336,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con keyEntry.source = event.getSource(); keyEntry.displayId = event.getDisplayId(); keyEntry.flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK; - keyEntry.keyCode = fallbackKeyCode; + keyEntry.keyCode = *fallbackKeyCode; keyEntry.scanCode = event.getScanCode(); keyEntry.metaState = event.getMetaState(); keyEntry.repeatCount = event.getRepeatCount(); @@ -6347,7 +6346,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con if (DEBUG_OUTBOUND_EVENT_DETAILS) { ALOGD("Unhandled key event: Dispatching fallback key. " "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x", - originalKeyCode, fallbackKeyCode, keyEntry.metaState); + originalKeyCode, *fallbackKeyCode, keyEntry.metaState); } return true; // restart the event } else { @@ -6362,9 +6361,9 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con return false; } -bool InputDispatcher::afterMotionEventLockedInterruptable(const sp<Connection>& connection, - DispatchEntry* dispatchEntry, - MotionEntry& motionEntry, bool handled) { +bool InputDispatcher::afterMotionEventLockedInterruptable( + const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, + MotionEntry& motionEntry, bool handled) { return false; } @@ -6686,9 +6685,11 @@ void InputDispatcher::transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldT wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED | InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED; state.addOrUpdateWindow(newWallpaper, wallpaperFlags, pointerIds, downTimeInTarget); - sp<Connection> wallpaperConnection = getConnectionLocked(newWallpaper->getToken()); + std::shared_ptr<Connection> wallpaperConnection = + getConnectionLocked(newWallpaper->getToken()); if (wallpaperConnection != nullptr) { - sp<Connection> toConnection = getConnectionLocked(toWindowHandle->getToken()); + std::shared_ptr<Connection> toConnection = + getConnectionLocked(toWindowHandle->getToken()); toConnection->inputState.mergePointerStateTo(wallpaperConnection->inputState); synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, wallpaperConnection, wallpaperFlags); diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 2246d47e48..7aa1a2d313 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -93,14 +93,15 @@ public: status_t start() override; status_t stop() override; - void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; - void notifyKey(const NotifyKeyArgs* args) override; - void notifyMotion(const NotifyMotionArgs* args) override; - void notifySwitch(const NotifySwitchArgs* args) override; - void notifySensor(const NotifySensorArgs* args) override; - void notifyVibratorState(const NotifyVibratorStateArgs* args) override; - void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; - void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; + void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override{}; + void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override; + void notifyKey(const NotifyKeyArgs& args) override; + void notifyMotion(const NotifyMotionArgs& args) override; + void notifySwitch(const NotifySwitchArgs& args) override; + void notifySensor(const NotifySensorArgs& args) override; + void notifyVibratorState(const NotifyVibratorStateArgs& args) override; + void notifyDeviceReset(const NotifyDeviceResetArgs& args) override; + void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override; android::os::InputEventInjectionResult injectInputEvent( const InputEvent* event, std::optional<int32_t> targetUid, @@ -231,7 +232,7 @@ private: nsecs_t mAppSwitchDueTime GUARDED_BY(mLock); bool isAppSwitchKeyEvent(const KeyEntry& keyEntry); - bool isAppSwitchPendingLocked() REQUIRES(mLock); + bool isAppSwitchPendingLocked() const REQUIRES(mLock); void resetPendingAppSwitchLocked(bool handled) REQUIRES(mLock); // Blocked event latency optimization. Drops old events when the user intends @@ -248,12 +249,12 @@ private: sp<android::gui::WindowInfoHandle> findTouchedForegroundWindowLocked(int32_t displayId) const REQUIRES(mLock); - sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const + std::shared_ptr<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const REQUIRES(mLock); std::string getConnectionNameLocked(const sp<IBinder>& connectionToken) const REQUIRES(mLock); - void removeConnectionLocked(const sp<Connection>& connection) REQUIRES(mLock); + void removeConnectionLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock); status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock); @@ -263,8 +264,8 @@ private: }; // All registered connections mapped by input channel token. - std::unordered_map<sp<IBinder>, sp<Connection>, StrongPointerHash<IBinder>> mConnectionsByToken - GUARDED_BY(mLock); + std::unordered_map<sp<IBinder>, std::shared_ptr<Connection>, StrongPointerHash<IBinder>> + mConnectionsByToken GUARDED_BY(mLock); // Find a monitor pid by the provided token. std::optional<int32_t> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); @@ -327,12 +328,12 @@ private: std::chrono::nanoseconds mMonitorDispatchingTimeout GUARDED_BY(mLock); nsecs_t processAnrsLocked() REQUIRES(mLock); - std::chrono::nanoseconds getDispatchingTimeoutLocked(const sp<Connection>& connection) - REQUIRES(mLock); + std::chrono::nanoseconds getDispatchingTimeoutLocked( + const std::shared_ptr<Connection>& connection) REQUIRES(mLock); // Input filter processing. - bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) REQUIRES(mLock); - bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) REQUIRES(mLock); + bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs& args) REQUIRES(mLock); + bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs& args) REQUIRES(mLock); // Inbound event processing. void drainInboundQueueLocked() REQUIRES(mLock); @@ -532,7 +533,7 @@ private: // prevent unneeded wakeups. AnrTracker mAnrTracker GUARDED_BY(mLock); - void cancelEventsForAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); + void cancelEventsForAnrLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock); // If a focused application changes, we should stop counting down the "no focused window" time, // because we will have no way of knowing when the previous application actually added a window. // This also means that we will miss cases like pulling down notification shade when the @@ -593,22 +594,26 @@ private: // These methods are deliberately not Interruptible because doing all of the work // with the mutex held makes it easier to ensure that connection invariants are maintained. // If needed, the methods post commands to run later once the critical bits are done. - void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, + void prepareDispatchCycleLocked(nsecs_t currentTime, + const std::shared_ptr<Connection>& connection, std::shared_ptr<EventEntry>, const InputTarget& inputTarget) REQUIRES(mLock); - void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection, + void enqueueDispatchEntriesLocked(nsecs_t currentTime, + const std::shared_ptr<Connection>& connection, std::shared_ptr<EventEntry>, const InputTarget& inputTarget) REQUIRES(mLock); - void enqueueDispatchEntryLocked(const sp<Connection>& connection, std::shared_ptr<EventEntry>, - const InputTarget& inputTarget, + void enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection, + std::shared_ptr<EventEntry>, const InputTarget& inputTarget, ftl::Flags<InputTarget::Flags> dispatchMode) REQUIRES(mLock); status_t publishMotionEvent(Connection& connection, DispatchEntry& dispatchEntry) const; - void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection) + void startDispatchCycleLocked(nsecs_t currentTime, + const std::shared_ptr<Connection>& connection) REQUIRES(mLock); + void finishDispatchCycleLocked(nsecs_t currentTime, + const std::shared_ptr<Connection>& connection, uint32_t seq, + bool handled, nsecs_t consumeTime) REQUIRES(mLock); + void abortBrokenDispatchCycleLocked(nsecs_t currentTime, + const std::shared_ptr<Connection>& connection, bool notify) REQUIRES(mLock); - void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, - uint32_t seq, bool handled, nsecs_t consumeTime) REQUIRES(mLock); - void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, - bool notify) REQUIRES(mLock); void drainDispatchQueue(std::deque<DispatchEntry*>& queue); void releaseDispatchEntry(DispatchEntry* dispatchEntry); int handleReceiveCallback(int events, sp<IBinder> connectionToken); @@ -623,14 +628,13 @@ private: void synthesizeCancelationEventsForInputChannelLocked( const std::shared_ptr<InputChannel>& channel, const CancelationOptions& options) REQUIRES(mLock); - void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection, - const CancelationOptions& options) + void synthesizeCancelationEventsForConnectionLocked( + const std::shared_ptr<Connection>& connection, const CancelationOptions& options) REQUIRES(mLock); - void synthesizePointerDownEventsForConnectionLocked(const nsecs_t downTime, - const sp<Connection>& connection, - ftl::Flags<InputTarget::Flags> targetFlags) - REQUIRES(mLock); + void synthesizePointerDownEventsForConnectionLocked( + const nsecs_t downTime, const std::shared_ptr<Connection>& connection, + ftl::Flags<InputTarget::Flags> targetFlags) REQUIRES(mLock); void synthesizeCancelationEventsForWindowLocked( const sp<android::gui::WindowInfoHandle>& windowHandle, @@ -646,10 +650,10 @@ private: void resetAndDropEverythingLocked(const char* reason) REQUIRES(mLock); // Dump state. - void dumpDispatchStateLocked(std::string& dump) REQUIRES(mLock); - void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors); - void logDispatchStateLocked() REQUIRES(mLock); - std::string dumpPointerCaptureStateLocked() REQUIRES(mLock); + void dumpDispatchStateLocked(std::string& dump) const REQUIRES(mLock); + void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const; + void logDispatchStateLocked() const REQUIRES(mLock); + std::string dumpPointerCaptureStateLocked() const REQUIRES(mLock); // Registration. void removeMonitorChannelLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock); @@ -657,16 +661,16 @@ private: REQUIRES(mLock); // Interesting events that we might like to log or tell the framework about. - void doDispatchCycleFinishedCommand(nsecs_t finishTime, const sp<Connection>& connection, - uint32_t seq, bool handled, nsecs_t consumeTime) - REQUIRES(mLock); + void doDispatchCycleFinishedCommand(nsecs_t finishTime, + const std::shared_ptr<Connection>& connection, uint32_t seq, + bool handled, nsecs_t consumeTime) REQUIRES(mLock); void doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>& focusedWindowToken, KeyEntry& entry) REQUIRES(mLock); void onFocusChangedLocked(const FocusResolver::FocusChanges& changes) REQUIRES(mLock); void sendFocusChangedCommandLocked(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) REQUIRES(mLock); void sendDropWindowCommandLocked(const sp<IBinder>& token, float x, float y) REQUIRES(mLock); - void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); + void onAnrLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock); void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock); void updateLastAnrStateLocked(const sp<android::gui::WindowInfoHandle>& window, const std::string& reason) REQUIRES(mLock); @@ -674,10 +678,10 @@ private: const std::string& reason) REQUIRES(mLock); void updateLastAnrStateLocked(const std::string& windowLabel, const std::string& reason) REQUIRES(mLock); - bool afterKeyEventLockedInterruptable(const sp<Connection>& connection, + bool afterKeyEventLockedInterruptable(const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, KeyEntry& keyEntry, bool handled) REQUIRES(mLock); - bool afterMotionEventLockedInterruptable(const sp<Connection>& connection, + bool afterMotionEventLockedInterruptable(const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, MotionEntry& motionEntry, bool handled) REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp index 94f38131b6..4652c2dd12 100644 --- a/services/inputflinger/dispatcher/InputState.cpp +++ b/services/inputflinger/dispatcher/InputState.cpp @@ -42,13 +42,8 @@ bool InputState::trackKey(const KeyEntry& entry, int32_t action, int32_t flags) switch (action) { case AKEY_EVENT_ACTION_UP: { if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) { - for (size_t i = 0; i < mFallbackKeys.size();) { - if (mFallbackKeys.valueAt(i) == entry.keyCode) { - mFallbackKeys.removeItemsAt(i); - } else { - i += 1; - } - } + std::erase_if(mFallbackKeys, + [&entry](const auto& item) { return item.second == entry.keyCode; }); } ssize_t index = findKeyMemento(entry); if (index >= 0) { @@ -481,22 +476,20 @@ void InputState::mergePointerStateTo(InputState& other) { } } -int32_t InputState::getFallbackKey(int32_t originalKeyCode) { - ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode); - return index >= 0 ? mFallbackKeys.valueAt(index) : -1; +std::optional<int32_t> InputState::getFallbackKey(int32_t originalKeyCode) { + auto it = mFallbackKeys.find(originalKeyCode); + if (it == mFallbackKeys.end()) { + return {}; + } + return it->second; } void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) { - ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode); - if (index >= 0) { - mFallbackKeys.replaceValueAt(index, fallbackKeyCode); - } else { - mFallbackKeys.add(originalKeyCode, fallbackKeyCode); - } + mFallbackKeys.insert_or_assign(originalKeyCode, fallbackKeyCode); } void InputState::removeFallbackKey(int32_t originalKeyCode) { - mFallbackKeys.removeItem(originalKeyCode); + mFallbackKeys.erase(originalKeyCode); } bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) { diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h index d788e47429..af2a3cbc93 100644 --- a/services/inputflinger/dispatcher/InputState.h +++ b/services/inputflinger/dispatcher/InputState.h @@ -62,9 +62,9 @@ public: void mergePointerStateTo(InputState& other); // Gets the fallback key associated with a keycode. - // Returns -1 if none. + // Returns std::nullopt if none. // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy. - int32_t getFallbackKey(int32_t originalKeyCode); + std::optional<int32_t> getFallbackKey(int32_t originalKeyCode); // Sets the fallback key for a particular keycode. void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode); @@ -72,7 +72,7 @@ public: // Removes the fallback key for a particular keycode. void removeFallbackKey(int32_t originalKeyCode); - inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const { return mFallbackKeys; } + inline const std::map<int32_t, int32_t>& getFallbackKeys() const { return mFallbackKeys; } private: struct KeyMemento { @@ -113,7 +113,7 @@ private: std::vector<KeyMemento> mKeyMementos; std::vector<MotionMemento> mMotionMementos; - KeyedVector<int32_t, int32_t> mFallbackKeys; + std::map</*originalKeyCode*/int32_t, /*fallbackKeyCode*/int32_t> mFallbackKeys; ssize_t findKeyMemento(const KeyEntry& entry) const; ssize_t findMotionMemento(const MotionEntry& entry, bool hovering) const; diff --git a/services/inputflinger/dispatcher/LatencyAggregator.cpp b/services/inputflinger/dispatcher/LatencyAggregator.cpp index a5bfc25e78..96d78c375b 100644 --- a/services/inputflinger/dispatcher/LatencyAggregator.cpp +++ b/services/inputflinger/dispatcher/LatencyAggregator.cpp @@ -256,7 +256,7 @@ void LatencyAggregator::processSlowEvent(const InputEventTimeline& timeline) { } } -std::string LatencyAggregator::dump(const char* prefix) { +std::string LatencyAggregator::dump(const char* prefix) const { std::string sketchDump = StringPrintf("%s Sketches:\n", prefix); for (size_t i = 0; i < SketchIndex::SIZE; i++) { const int64_t numDown = mDownSketches[i]->num_values(); diff --git a/services/inputflinger/dispatcher/LatencyAggregator.h b/services/inputflinger/dispatcher/LatencyAggregator.h index accfc29d8e..60b6813158 100644 --- a/services/inputflinger/dispatcher/LatencyAggregator.h +++ b/services/inputflinger/dispatcher/LatencyAggregator.h @@ -56,7 +56,7 @@ public: */ void processTimeline(const InputEventTimeline& timeline) override; - std::string dump(const char* prefix); + std::string dump(const char* prefix) const; ~LatencyAggregator(); diff --git a/services/inputflinger/dispatcher/LatencyTracker.cpp b/services/inputflinger/dispatcher/LatencyTracker.cpp index 2dd7d3f529..b7c36a8db8 100644 --- a/services/inputflinger/dispatcher/LatencyTracker.cpp +++ b/services/inputflinger/dispatcher/LatencyTracker.cpp @@ -165,7 +165,7 @@ void LatencyTracker::reportAndPruneMatureRecords(nsecs_t newEventTime) { } } -std::string LatencyTracker::dump(const char* prefix) { +std::string LatencyTracker::dump(const char* prefix) const { return StringPrintf("%sLatencyTracker:\n", prefix) + StringPrintf("%s mTimelines.size() = %zu\n", prefix, mTimelines.size()) + StringPrintf("%s mEventTimes.size() = %zu\n", prefix, mEventTimes.size()); diff --git a/services/inputflinger/dispatcher/LatencyTracker.h b/services/inputflinger/dispatcher/LatencyTracker.h index 64dfeef20d..4212da876f 100644 --- a/services/inputflinger/dispatcher/LatencyTracker.h +++ b/services/inputflinger/dispatcher/LatencyTracker.h @@ -55,7 +55,7 @@ public: void trackGraphicsLatency(int32_t inputEventId, const sp<IBinder>& connectionToken, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline); - std::string dump(const char* prefix); + std::string dump(const char* prefix) const; private: /** diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h index 1bb19686e7..4f78f032c7 100644 --- a/services/inputflinger/include/InputListener.h +++ b/services/inputflinger/include/InputListener.h @@ -37,14 +37,15 @@ public: InputListenerInterface& operator=(const InputListenerInterface&) = delete; virtual ~InputListenerInterface() { } - virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0; - virtual void notifyKey(const NotifyKeyArgs* args) = 0; - virtual void notifyMotion(const NotifyMotionArgs* args) = 0; - virtual void notifySwitch(const NotifySwitchArgs* args) = 0; - virtual void notifySensor(const NotifySensorArgs* args) = 0; - virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) = 0; - virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0; - virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0; + virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) = 0; + virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) = 0; + virtual void notifyKey(const NotifyKeyArgs& args) = 0; + virtual void notifyMotion(const NotifyMotionArgs& args) = 0; + virtual void notifySwitch(const NotifySwitchArgs& args) = 0; + virtual void notifySensor(const NotifySensorArgs& args) = 0; + virtual void notifyVibratorState(const NotifyVibratorStateArgs& args) = 0; + virtual void notifyDeviceReset(const NotifyDeviceResetArgs& args) = 0; + virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) = 0; void notify(const NotifyArgs& args); }; @@ -58,14 +59,15 @@ class QueuedInputListener : public InputListenerInterface { public: explicit QueuedInputListener(InputListenerInterface& innerListener); - virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; - virtual void notifyKey(const NotifyKeyArgs* args) override; - virtual void notifyMotion(const NotifyMotionArgs* args) override; - virtual void notifySwitch(const NotifySwitchArgs* args) override; - virtual void notifySensor(const NotifySensorArgs* args) override; - virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; - void notifyVibratorState(const NotifyVibratorStateArgs* args) override; - void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; + virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override; + virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override; + virtual void notifyKey(const NotifyKeyArgs& args) override; + virtual void notifyMotion(const NotifyMotionArgs& args) override; + virtual void notifySwitch(const NotifySwitchArgs& args) override; + virtual void notifySensor(const NotifySensorArgs& args) override; + virtual void notifyDeviceReset(const NotifyDeviceResetArgs& args) override; + void notifyVibratorState(const NotifyVibratorStateArgs& args) override; + void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override; void flush(); diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 1750c64eca..a93a2ea615 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -42,118 +42,6 @@ namespace android { -// --- InputReaderInterface --- - -/* The interface for the InputReader shared library. - * - * Manages one or more threads that process raw input events and sends cooked event data to an - * input listener. - * - * The implementation must guarantee thread safety for this interface. However, since the input - * listener is NOT thread safe, all calls to the listener must happen from the same thread. - */ -class InputReaderInterface { -public: - InputReaderInterface() { } - virtual ~InputReaderInterface() { } - - /* Dumps the state of the input reader. - * - * This method may be called on any thread (usually by the input manager). */ - virtual void dump(std::string& dump) = 0; - - /* Called by the heartbeat to ensures that the reader has not deadlocked. */ - virtual void monitor() = 0; - - /* Returns true if the input device is enabled. */ - virtual bool isInputDeviceEnabled(int32_t deviceId) = 0; - - /* Makes the reader start processing events from the kernel. */ - virtual status_t start() = 0; - - /* Makes the reader stop processing any more events. */ - virtual status_t stop() = 0; - - /* Gets information about all input devices. - * - * This method may be called on any thread (usually by the input manager). - */ - virtual std::vector<InputDeviceInfo> getInputDevices() const = 0; - - /* Query current input state. */ - virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, - int32_t scanCode) = 0; - virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, - int32_t keyCode) = 0; - virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, - int32_t sw) = 0; - - virtual void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, - int32_t toKeyCode) const = 0; - - virtual int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const = 0; - - /* Toggle Caps Lock */ - virtual void toggleCapsLockState(int32_t deviceId) = 0; - - /* Determine whether physical keys exist for the given framework-domain key codes. */ - virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, - const std::vector<int32_t>& keyCodes, uint8_t* outFlags) = 0; - - /* Requests that a reconfiguration of all input devices. - * The changes flag is a bitfield that indicates what has changed and whether - * the input devices must all be reopened. */ - virtual void requestRefreshConfiguration(uint32_t changes) = 0; - - /* Controls the vibrator of a particular input device. */ - virtual void vibrate(int32_t deviceId, const VibrationSequence& sequence, ssize_t repeat, - int32_t token) = 0; - virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0; - - virtual bool isVibrating(int32_t deviceId) = 0; - - virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0; - /* Get battery level of a particular input device. */ - virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) = 0; - /* Get battery status of a particular input device. */ - virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) = 0; - /* Get the device path for the battery of an input device. */ - virtual std::optional<std::string> getBatteryDevicePath(int32_t deviceId) = 0; - - virtual std::vector<InputDeviceLightInfo> getLights(int32_t deviceId) = 0; - - virtual std::vector<InputDeviceSensorInfo> getSensors(int32_t deviceId) = 0; - - /* Return true if the device can send input events to the specified display. */ - virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0; - - /* Enable sensor in input reader mapper. */ - virtual bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, - std::chrono::microseconds samplingPeriod, - std::chrono::microseconds maxBatchReportLatency) = 0; - - /* Disable sensor in input reader mapper. */ - virtual void disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0; - - /* Flush sensor data in input reader mapper. */ - virtual void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0; - - /* Set color for the light */ - virtual bool setLightColor(int32_t deviceId, int32_t lightId, int32_t color) = 0; - /* Set player ID for the light */ - virtual bool setLightPlayerId(int32_t deviceId, int32_t lightId, int32_t playerId) = 0; - /* Get light color */ - virtual std::optional<int32_t> getLightColor(int32_t deviceId, int32_t lightId) = 0; - /* Get light player ID */ - virtual std::optional<int32_t> getLightPlayerId(int32_t deviceId, int32_t lightId) = 0; - - /* Get the Bluetooth address of an input device, if known. */ - virtual std::optional<std::string> getBluetoothAddress(int32_t deviceId) const = 0; - - /* Sysfs node change reported. Recreate device if required to incorporate the new sysfs nodes */ - virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0; -}; - // --- InputReaderConfiguration --- /* @@ -163,51 +51,51 @@ public: */ struct InputReaderConfiguration { // Describes changes that have occurred. - enum { + enum class Change : uint32_t { // The mouse pointer speed changed. - CHANGE_POINTER_SPEED = 1 << 0, + POINTER_SPEED = 1u << 0, // The pointer gesture control changed. - CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1, + POINTER_GESTURE_ENABLEMENT = 1u << 1, // The display size or orientation changed. - CHANGE_DISPLAY_INFO = 1 << 2, + DISPLAY_INFO = 1u << 2, // The visible touches option changed. - CHANGE_SHOW_TOUCHES = 1 << 3, + SHOW_TOUCHES = 1u << 3, // The keyboard layouts must be reloaded. - CHANGE_KEYBOARD_LAYOUTS = 1 << 4, + KEYBOARD_LAYOUTS = 1u << 4, // The device name alias supplied by the may have changed for some devices. - CHANGE_DEVICE_ALIAS = 1 << 5, + DEVICE_ALIAS = 1u << 5, // The location calibration matrix changed. - CHANGE_TOUCH_AFFINE_TRANSFORMATION = 1 << 6, + TOUCH_AFFINE_TRANSFORMATION = 1u << 6, // The presence of an external stylus has changed. - CHANGE_EXTERNAL_STYLUS_PRESENCE = 1 << 7, + EXTERNAL_STYLUS_PRESENCE = 1u << 7, // The pointer capture mode has changed. - CHANGE_POINTER_CAPTURE = 1 << 8, + POINTER_CAPTURE = 1u << 8, // The set of disabled input devices (disabledDevices) has changed. - CHANGE_ENABLED_STATE = 1 << 9, + ENABLED_STATE = 1u << 9, // The device type has been updated. - CHANGE_DEVICE_TYPE = 1 << 10, + DEVICE_TYPE = 1u << 10, // The keyboard layout association has changed. - CHANGE_KEYBOARD_LAYOUT_ASSOCIATION = 1 << 11, + KEYBOARD_LAYOUT_ASSOCIATION = 1u << 11, // The stylus button reporting configurations has changed. - CHANGE_STYLUS_BUTTON_REPORTING = 1 << 12, + STYLUS_BUTTON_REPORTING = 1u << 12, // The touchpad settings changed. - CHANGE_TOUCHPAD_SETTINGS = 1 << 13, + TOUCHPAD_SETTINGS = 1u << 13, // All devices must be reopened. - CHANGE_MUST_REOPEN = 1 << 31, + MUST_REOPEN = 1u << 31, }; // Gets the amount of time to disable virtual keys after the screen is touched @@ -367,8 +255,6 @@ struct InputReaderConfiguration { stylusButtonMotionEventsEnabled(true), stylusPointerIconEnabled(false) {} - static std::string changesToString(uint32_t changes); - std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const; std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId) const; @@ -383,6 +269,116 @@ private: std::vector<DisplayViewport> mDisplays; }; +using ConfigurationChanges = ftl::Flags<InputReaderConfiguration::Change>; + +// --- InputReaderInterface --- + +/* The interface for the InputReader shared library. + * + * Manages one or more threads that process raw input events and sends cooked event data to an + * input listener. + * + * The implementation must guarantee thread safety for this interface. However, since the input + * listener is NOT thread safe, all calls to the listener must happen from the same thread. + */ +class InputReaderInterface { +public: + InputReaderInterface() {} + virtual ~InputReaderInterface() {} + /* Dumps the state of the input reader. + * + * This method may be called on any thread (usually by the input manager). */ + virtual void dump(std::string& dump) = 0; + + /* Called by the heartbeat to ensures that the reader has not deadlocked. */ + virtual void monitor() = 0; + + /* Returns true if the input device is enabled. */ + virtual bool isInputDeviceEnabled(int32_t deviceId) = 0; + + /* Makes the reader start processing events from the kernel. */ + virtual status_t start() = 0; + + /* Makes the reader stop processing any more events. */ + virtual status_t stop() = 0; + + /* Gets information about all input devices. + * + * This method may be called on any thread (usually by the input manager). + */ + virtual std::vector<InputDeviceInfo> getInputDevices() const = 0; + + /* Query current input state. */ + virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) = 0; + virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) = 0; + virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) = 0; + + virtual void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, + int32_t toKeyCode) const = 0; + + virtual int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const = 0; + + /* Toggle Caps Lock */ + virtual void toggleCapsLockState(int32_t deviceId) = 0; + + /* Determine whether physical keys exist for the given framework-domain key codes. */ + virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, + const std::vector<int32_t>& keyCodes, uint8_t* outFlags) = 0; + + /* Requests that a reconfiguration of all input devices. + * The changes flag is a bitfield that indicates what has changed and whether + * the input devices must all be reopened. */ + virtual void requestRefreshConfiguration(ConfigurationChanges changes) = 0; + + /* Controls the vibrator of a particular input device. */ + virtual void vibrate(int32_t deviceId, const VibrationSequence& sequence, ssize_t repeat, + int32_t token) = 0; + virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0; + + virtual bool isVibrating(int32_t deviceId) = 0; + + virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0; + /* Get battery level of a particular input device. */ + virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) = 0; + /* Get battery status of a particular input device. */ + virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) = 0; + /* Get the device path for the battery of an input device. */ + virtual std::optional<std::string> getBatteryDevicePath(int32_t deviceId) = 0; + + virtual std::vector<InputDeviceLightInfo> getLights(int32_t deviceId) = 0; + + virtual std::vector<InputDeviceSensorInfo> getSensors(int32_t deviceId) = 0; + + /* Return true if the device can send input events to the specified display. */ + virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0; + + /* Enable sensor in input reader mapper. */ + virtual bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) = 0; + + /* Disable sensor in input reader mapper. */ + virtual void disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0; + + /* Flush sensor data in input reader mapper. */ + virtual void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0; + + /* Set color for the light */ + virtual bool setLightColor(int32_t deviceId, int32_t lightId, int32_t color) = 0; + /* Set player ID for the light */ + virtual bool setLightPlayerId(int32_t deviceId, int32_t lightId, int32_t playerId) = 0; + /* Get light color */ + virtual std::optional<int32_t> getLightColor(int32_t deviceId, int32_t lightId) = 0; + /* Get light player ID */ + virtual std::optional<int32_t> getLightPlayerId(int32_t deviceId, int32_t lightId) = 0; + + /* Get the Bluetooth address of an input device, if known. */ + virtual std::optional<std::string> getBluetoothAddress(int32_t deviceId) const = 0; + + /* Sysfs node change reported. Recreate device if required to incorporate the new sysfs nodes */ + virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0; +}; + // --- TouchAffineTransformation --- struct TouchAffineTransformation { diff --git a/services/inputflinger/include/NotifyArgs.h b/services/inputflinger/include/NotifyArgs.h index c46f90501f..7d29dd9cb2 100644 --- a/services/inputflinger/include/NotifyArgs.h +++ b/services/inputflinger/include/NotifyArgs.h @@ -24,6 +24,21 @@ namespace android { +/* Describes a change in any of the connected input devices. */ +struct NotifyInputDevicesChangedArgs { + int32_t id; + std::vector<InputDeviceInfo> inputDeviceInfos; + + inline NotifyInputDevicesChangedArgs() {} + + NotifyInputDevicesChangedArgs(int32_t id, std::vector<InputDeviceInfo> infos); + + bool operator==(const NotifyInputDevicesChangedArgs& rhs) const = default; + + NotifyInputDevicesChangedArgs(const NotifyInputDevicesChangedArgs& other) = default; + NotifyInputDevicesChangedArgs& operator=(const NotifyInputDevicesChangedArgs&) = default; +}; + /* Describes a configuration change event. */ struct NotifyConfigurationChangedArgs { int32_t id; @@ -36,6 +51,7 @@ struct NotifyConfigurationChangedArgs { bool operator==(const NotifyConfigurationChangedArgs& rhs) const = default; NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other) = default; + NotifyConfigurationChangedArgs& operator=(const NotifyConfigurationChangedArgs&) = default; }; /* Describes a key event. */ @@ -65,6 +81,7 @@ struct NotifyKeyArgs { bool operator==(const NotifyKeyArgs& rhs) const = default; NotifyKeyArgs(const NotifyKeyArgs& other) = default; + NotifyKeyArgs& operator=(const NotifyKeyArgs&) = default; }; /* Describes a motion event. */ @@ -115,7 +132,6 @@ struct NotifyMotionArgs { const std::vector<TouchVideoFrame>& videoFrames); NotifyMotionArgs(const NotifyMotionArgs& other); - NotifyMotionArgs& operator=(const android::NotifyMotionArgs&) = default; bool operator==(const NotifyMotionArgs& rhs) const; @@ -143,6 +159,7 @@ struct NotifySensorArgs { bool accuracyChanged, nsecs_t hwTimestamp, std::vector<float> values); NotifySensorArgs(const NotifySensorArgs& other) = default; + NotifySensorArgs& operator=(const NotifySensorArgs&) = default; }; /* Describes a switch event. */ @@ -160,6 +177,7 @@ struct NotifySwitchArgs { uint32_t switchMask); NotifySwitchArgs(const NotifySwitchArgs& other) = default; + NotifySwitchArgs& operator=(const NotifySwitchArgs&) = default; bool operator==(const NotifySwitchArgs& rhs) const = default; }; @@ -177,13 +195,13 @@ struct NotifyDeviceResetArgs { NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId); NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) = default; + NotifyDeviceResetArgs& operator=(const NotifyDeviceResetArgs&) = default; bool operator==(const NotifyDeviceResetArgs& rhs) const = default; }; /* Describes a change in the state of Pointer Capture. */ struct NotifyPointerCaptureChangedArgs { - // The sequence number of the Pointer Capture request, if enabled. int32_t id; nsecs_t eventTime; @@ -194,6 +212,7 @@ struct NotifyPointerCaptureChangedArgs { NotifyPointerCaptureChangedArgs(int32_t id, nsecs_t eventTime, const PointerCaptureRequest&); NotifyPointerCaptureChangedArgs(const NotifyPointerCaptureChangedArgs& other) = default; + NotifyPointerCaptureChangedArgs& operator=(const NotifyPointerCaptureChangedArgs&) = default; }; /* Describes a vibrator state event. */ @@ -209,11 +228,13 @@ struct NotifyVibratorStateArgs { NotifyVibratorStateArgs(int32_t id, nsecs_t eventTIme, int32_t deviceId, bool isOn); NotifyVibratorStateArgs(const NotifyVibratorStateArgs& other) = default; + NotifyVibratorStateArgs& operator=(const NotifyVibratorStateArgs&) = default; }; -using NotifyArgs = std::variant<NotifyConfigurationChangedArgs, NotifyKeyArgs, NotifyMotionArgs, - NotifySensorArgs, NotifySwitchArgs, NotifyDeviceResetArgs, - NotifyPointerCaptureChangedArgs, NotifyVibratorStateArgs>; +using NotifyArgs = + std::variant<NotifyInputDevicesChangedArgs, NotifyConfigurationChangedArgs, NotifyKeyArgs, + NotifyMotionArgs, NotifySensorArgs, NotifySwitchArgs, NotifyDeviceResetArgs, + NotifyPointerCaptureChangedArgs, NotifyVibratorStateArgs>; const char* toString(const NotifyArgs& args); diff --git a/services/inputflinger/include/UnwantedInteractionBlockerInterface.h b/services/inputflinger/include/UnwantedInteractionBlockerInterface.h index 1a6f8472a5..64c6114ceb 100644 --- a/services/inputflinger/include/UnwantedInteractionBlockerInterface.h +++ b/services/inputflinger/include/UnwantedInteractionBlockerInterface.h @@ -27,23 +27,13 @@ namespace android { */ class UnwantedInteractionBlockerInterface : public InputListenerInterface { public: - /* Notifies the input reader policy that some input devices have changed - * and provides information about all current input devices. - * Important! This call should happen on the same thread as the calls to the - * InputListenerInterface methods. - * That is, same thread should call 'notifyMotion' and 'notifyInputDevicesChanged' and - * 'notifyDeviceReset'. If this architecture changes, we will need to make the implementation - * of this interface thread-safe. - */ - virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) = 0; - /** * Dump the state of the interaction blocker. * This method may be called on any thread (usually by the input manager on a binder thread). */ virtual void dump(std::string& dump) = 0; - /* Called by the heatbeat to ensures that the blocker has not deadlocked. */ + /* Called by the heartbeat to ensures that the blocker has not deadlocked. */ virtual void monitor() = 0; UnwantedInteractionBlockerInterface() {} diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index eaed987320..b86906b2cd 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -146,98 +146,23 @@ void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) { } } -void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { +void InputDevice::addEmptyEventHubDevice(int32_t eventHubId) { if (mDevices.find(eventHubId) != mDevices.end()) { return; } std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId)); - ftl::Flags<InputDeviceClass> classes = contextPtr->getDeviceClasses(); std::vector<std::unique_ptr<InputMapper>> mappers; - // Check if we should skip population - if (!populateMappers) { - mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))}); - return; - } - - // Switch-like devices. - if (classes.test(InputDeviceClass::SWITCH)) { - mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr)); - } - - // Scroll wheel-like devices. - if (classes.test(InputDeviceClass::ROTARY_ENCODER)) { - mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr)); - } - - // Vibrator-like devices. - if (classes.test(InputDeviceClass::VIBRATOR)) { - mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr)); - } - - // Battery-like devices or light-containing devices. - // PeripheralController will be created with associated EventHub device. - if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) { - mController = std::make_unique<PeripheralController>(*contextPtr); - } - - // Keyboard-like devices. - uint32_t keyboardSource = 0; - int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC; - if (classes.test(InputDeviceClass::KEYBOARD)) { - keyboardSource |= AINPUT_SOURCE_KEYBOARD; - } - if (classes.test(InputDeviceClass::ALPHAKEY)) { - keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC; - } - if (classes.test(InputDeviceClass::DPAD)) { - keyboardSource |= AINPUT_SOURCE_DPAD; - } - if (classes.test(InputDeviceClass::GAMEPAD)) { - keyboardSource |= AINPUT_SOURCE_GAMEPAD; - } - - if (keyboardSource != 0) { - mappers.push_back( - std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType)); - } - - // Cursor-like devices. - if (classes.test(InputDeviceClass::CURSOR)) { - mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr)); - } - - // Touchscreens and touchpad devices. - static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY = - sysprop::InputProperties::enable_touchpad_gestures_library().value_or(true); - // TODO(b/272518665): Fix the new touchpad stack for Sony DualShock 4 (5c4, 9cc) touchpads, or - // at least load this setting from the IDC file. - const InputDeviceIdentifier identifier = contextPtr->getDeviceIdentifier(); - const bool isSonyDualShock4Touchpad = identifier.vendor == 0x054c && - (identifier.product == 0x05c4 || identifier.product == 0x09cc); - if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) && - classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) { - mappers.push_back(std::make_unique<TouchpadInputMapper>(*contextPtr)); - } else if (classes.test(InputDeviceClass::TOUCH_MT)) { - mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr)); - } else if (classes.test(InputDeviceClass::TOUCH)) { - mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr)); - } - - // Joystick-like devices. - if (classes.test(InputDeviceClass::JOYSTICK)) { - mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr)); - } - - // Motion sensor enabled devices. - if (classes.test(InputDeviceClass::SENSOR)) { - mappers.push_back(std::make_unique<SensorInputMapper>(*contextPtr)); - } + mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))}); +} - // External stylus-like devices. - if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) { - mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr)); +void InputDevice::addEventHubDevice(int32_t eventHubId, + const InputReaderConfiguration& readerConfig) { + if (mDevices.find(eventHubId) != mDevices.end()) { + return; } + std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId)); + std::vector<std::unique_ptr<InputMapper>> mappers = createMappers(*contextPtr, readerConfig); // insert the context into the devices set mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))}); @@ -253,8 +178,9 @@ void InputDevice::removeEventHubDevice(int32_t eventHubId) { mDevices.erase(eventHubId); } -std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, - uint32_t changes) { +std::list<NotifyArgs> InputDevice::configure(nsecs_t when, + const InputReaderConfiguration& readerConfig, + ConfigurationChanges changes) { std::list<NotifyArgs> out; mSources = 0; mClasses = ftl::Flags<InputDeviceClass>(0); @@ -275,12 +201,14 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf mIsExternal = mClasses.test(InputDeviceClass::EXTERNAL); mHasMic = mClasses.test(InputDeviceClass::MIC); + using Change = InputReaderConfiguration::Change; + if (!isIgnored()) { // Full configuration should happen the first time configure is called // and when the device type is changed. Changing a device type can // affect various other parameters so should result in a // reconfiguration. - if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_TYPE)) { + if (!changes.any() || changes.test(Change::DEVICE_TYPE)) { mConfiguration.clear(); for_each_subdevice([this](InputDeviceContext& context) { std::optional<PropertyMap> configuration = @@ -291,10 +219,10 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf }); mAssociatedDeviceType = - getValueByKey(config->deviceTypeAssociations, mIdentifier.location); + getValueByKey(readerConfig.deviceTypeAssociations, mIdentifier.location); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) { + if (!changes.any() || changes.test(Change::KEYBOARD_LAYOUTS)) { if (!mClasses.test(InputDeviceClass::VIRTUAL)) { std::shared_ptr<KeyCharacterMap> keyboardLayout = mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier); @@ -311,7 +239,7 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf } } - if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) { + if (!changes.any() || changes.test(Change::DEVICE_ALIAS)) { if (!(mClasses.test(InputDeviceClass::VIRTUAL))) { std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier); if (mAlias != alias) { @@ -321,16 +249,16 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf } } - if (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE) { + if (changes.test(Change::ENABLED_STATE)) { // Do not execute this code on the first configure, because 'setEnabled' would call // InputMapper::reset, and you can't reset a mapper before it has been configured. // The mappers are configured for the first time at the bottom of this function. - auto it = config->disabledDevices.find(mId); - bool enabled = it == config->disabledDevices.end(); + auto it = readerConfig.disabledDevices.find(mId); + bool enabled = it == readerConfig.disabledDevices.end(); out += setEnabled(enabled, when); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { + if (!changes.any() || changes.test(Change::DISPLAY_INFO)) { // In most situations, no port or name will be specified. mAssociatedDisplayPort = std::nullopt; mAssociatedDisplayUniqueId = std::nullopt; @@ -338,13 +266,14 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf // Find the display port that corresponds to the current input port. const std::string& inputPort = mIdentifier.location; if (!inputPort.empty()) { - const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations; + const std::unordered_map<std::string, uint8_t>& ports = + readerConfig.portAssociations; const auto& displayPort = ports.find(inputPort); if (displayPort != ports.end()) { mAssociatedDisplayPort = std::make_optional(displayPort->second); } else { const std::unordered_map<std::string, std::string>& displayUniqueIds = - config->uniqueIdAssociations; + readerConfig.uniqueIdAssociations; const auto& displayUniqueId = displayUniqueIds.find(inputPort); if (displayUniqueId != displayUniqueIds.end()) { mAssociatedDisplayUniqueId = displayUniqueId->second; @@ -356,9 +285,11 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf // "disabledDevices" list. If it is associated with a specific display, and it was not // explicitly disabled, then enable/disable the device based on whether we can find the // corresponding viewport. - bool enabled = (config->disabledDevices.find(mId) == config->disabledDevices.end()); + bool enabled = + (readerConfig.disabledDevices.find(mId) == readerConfig.disabledDevices.end()); if (mAssociatedDisplayPort) { - mAssociatedViewport = config->getDisplayViewportByPort(*mAssociatedDisplayPort); + mAssociatedViewport = + readerConfig.getDisplayViewportByPort(*mAssociatedDisplayPort); if (!mAssociatedViewport) { ALOGW("Input device %s should be associated with display on port %" PRIu8 ", " "but the corresponding viewport is not found.", @@ -367,7 +298,7 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf } } else if (mAssociatedDisplayUniqueId != std::nullopt) { mAssociatedViewport = - config->getDisplayViewportByUniqueId(*mAssociatedDisplayUniqueId); + readerConfig.getDisplayViewportByUniqueId(*mAssociatedDisplayUniqueId); if (!mAssociatedViewport) { ALOGW("Input device %s should be associated with display %s but the " "corresponding viewport cannot be found", @@ -376,7 +307,7 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf } } - if (changes) { + if (changes.any()) { // For first-time configuration, only allow device to be disabled after mappers have // finished configuring. This is because we need to read some of the properties from // the device's open fd. @@ -384,15 +315,16 @@ std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConf } } - for_each_mapper([this, when, &config, changes, &out](InputMapper& mapper) { - out += mapper.reconfigure(when, config, changes); + for_each_mapper([this, when, &readerConfig, changes, &out](InputMapper& mapper) { + out += mapper.reconfigure(when, readerConfig, changes); mSources |= mapper.getSources(); }); // If a device is just plugged but it might be disabled, we need to update some info like // axis range of touch from each InputMapper first, then disable it. - if (!changes) { - out += setEnabled(config->disabledDevices.find(mId) == config->disabledDevices.end(), + if (!changes.any()) { + out += setEnabled(readerConfig.disabledDevices.find(mId) == + readerConfig.disabledDevices.end(), when); } } @@ -507,6 +439,92 @@ int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc ge return result; } +std::vector<std::unique_ptr<InputMapper>> InputDevice::createMappers( + InputDeviceContext& contextPtr, const InputReaderConfiguration& readerConfig) { + ftl::Flags<InputDeviceClass> classes = contextPtr.getDeviceClasses(); + std::vector<std::unique_ptr<InputMapper>> mappers; + + // Switch-like devices. + if (classes.test(InputDeviceClass::SWITCH)) { + mappers.push_back(std::make_unique<SwitchInputMapper>(contextPtr, readerConfig)); + } + + // Scroll wheel-like devices. + if (classes.test(InputDeviceClass::ROTARY_ENCODER)) { + mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(contextPtr, readerConfig)); + } + + // Vibrator-like devices. + if (classes.test(InputDeviceClass::VIBRATOR)) { + mappers.push_back(std::make_unique<VibratorInputMapper>(contextPtr, readerConfig)); + } + + // Battery-like devices or light-containing devices. + // PeripheralController will be created with associated EventHub device. + if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) { + mController = std::make_unique<PeripheralController>(contextPtr); + } + + // Keyboard-like devices. + uint32_t keyboardSource = 0; + int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC; + if (classes.test(InputDeviceClass::KEYBOARD)) { + keyboardSource |= AINPUT_SOURCE_KEYBOARD; + } + if (classes.test(InputDeviceClass::ALPHAKEY)) { + keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC; + } + if (classes.test(InputDeviceClass::DPAD)) { + keyboardSource |= AINPUT_SOURCE_DPAD; + } + if (classes.test(InputDeviceClass::GAMEPAD)) { + keyboardSource |= AINPUT_SOURCE_GAMEPAD; + } + + if (keyboardSource != 0) { + mappers.push_back(std::make_unique<KeyboardInputMapper>(contextPtr, readerConfig, + keyboardSource, keyboardType)); + } + + // Cursor-like devices. + if (classes.test(InputDeviceClass::CURSOR)) { + mappers.push_back(std::make_unique<CursorInputMapper>(contextPtr, readerConfig)); + } + + // Touchscreens and touchpad devices. + static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY = + sysprop::InputProperties::enable_touchpad_gestures_library().value_or(true); + // TODO(b/272518665): Fix the new touchpad stack for Sony DualShock 4 (5c4, 9cc) touchpads, or + // at least load this setting from the IDC file. + const InputDeviceIdentifier identifier = contextPtr.getDeviceIdentifier(); + const bool isSonyDualShock4Touchpad = identifier.vendor == 0x054c && + (identifier.product == 0x05c4 || identifier.product == 0x09cc); + if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) && + classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) { + mappers.push_back(std::make_unique<TouchpadInputMapper>(contextPtr, readerConfig)); + } else if (classes.test(InputDeviceClass::TOUCH_MT)) { + mappers.push_back(std::make_unique<MultiTouchInputMapper>(contextPtr, readerConfig)); + } else if (classes.test(InputDeviceClass::TOUCH)) { + mappers.push_back(std::make_unique<SingleTouchInputMapper>(contextPtr, readerConfig)); + } + + // Joystick-like devices. + if (classes.test(InputDeviceClass::JOYSTICK)) { + mappers.push_back(std::make_unique<JoystickInputMapper>(contextPtr, readerConfig)); + } + + // Motion sensor enabled devices. + if (classes.test(InputDeviceClass::SENSOR)) { + mappers.push_back(std::make_unique<SensorInputMapper>(contextPtr, readerConfig)); + } + + // External stylus-like devices. + if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) { + mappers.push_back(std::make_unique<ExternalStylusInputMapper>(contextPtr, readerConfig)); + } + return mappers; +} + bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes, uint8_t* outFlags) { bool result = false; diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index 81ac03b7b3..ea95f7857a 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -85,7 +85,7 @@ InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub, mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), mConfigurationChangesToRefresh(0) { - refreshConfigurationLocked(0); + refreshConfigurationLocked(/*changes=*/{}); updateGlobalMetaStateLocked(); } @@ -122,9 +122,9 @@ void InputReader::loopOnce() { oldGeneration = mGeneration; timeoutMillis = -1; - uint32_t changes = mConfigurationChangesToRefresh; - if (changes) { - mConfigurationChangesToRefresh = 0; + auto changes = mConfigurationChangesToRefresh; + if (changes.any()) { + mConfigurationChangesToRefresh.clear(); timeoutMillis = 0; refreshConfigurationLocked(changes); } else if (mNextTimeout != LLONG_MAX) { @@ -157,6 +157,8 @@ void InputReader::loopOnce() { if (oldGeneration != mGeneration) { inputDevicesChanged = true; inputDevices = getInputDevicesLocked(); + notifyArgs.emplace_back( + NotifyInputDevicesChangedArgs{mContext.getNextId(), inputDevices}); } } // release lock @@ -234,7 +236,7 @@ void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) { InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId); std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier); - notifyAll(device->configure(when, &mConfig, 0)); + notifyAll(device->configure(when, mConfig, /*changes=*/{})); notifyAll(device->reset(when)); if (device->isIgnored()) { @@ -310,7 +312,7 @@ void InputReader::removeDeviceLocked(nsecs_t when, int32_t eventHubId) { std::list<NotifyArgs> resetEvents; if (device->hasEventHubDevices()) { - resetEvents += device->configure(when, &mConfig, 0); + resetEvents += device->configure(when, mConfig, /*changes=*/{}); } resetEvents += device->reset(when); notifyAll(std::move(resetEvents)); @@ -332,7 +334,7 @@ std::shared_ptr<InputDevice> InputReader::createDeviceLocked( device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(), identifier); } - device->addEventHubDevice(eventHubId); + device->addEventHubDevice(eventHubId, mConfig); return device; } @@ -385,42 +387,40 @@ void InputReader::handleConfigurationChangedLocked(nsecs_t when) { updateGlobalMetaStateLocked(); // Enqueue configuration changed. - NotifyConfigurationChangedArgs args(mContext.getNextId(), when); - mQueuedListener.notifyConfigurationChanged(&args); + mQueuedListener.notifyConfigurationChanged({mContext.getNextId(), when}); } -void InputReader::refreshConfigurationLocked(uint32_t changes) { +void InputReader::refreshConfigurationLocked(ConfigurationChanges changes) { mPolicy->getReaderConfiguration(&mConfig); mEventHub->setExcludedDevices(mConfig.excludedDeviceNames); - if (!changes) return; + using Change = InputReaderConfiguration::Change; + if (!changes.any()) return; - ALOGI("Reconfiguring input devices, changes=%s", - InputReaderConfiguration::changesToString(changes).c_str()); + ALOGI("Reconfiguring input devices, changes=%s", changes.string().c_str()); nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - if (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO) { + if (changes.test(Change::DISPLAY_INFO)) { updatePointerDisplayLocked(); } - if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) { + if (changes.test(Change::MUST_REOPEN)) { mEventHub->requestReopenDevices(); } else { for (auto& devicePair : mDevices) { std::shared_ptr<InputDevice>& device = devicePair.second; - notifyAll(device->configure(now, &mConfig, changes)); + notifyAll(device->configure(now, mConfig, changes)); } } - if (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE) { + if (changes.test(Change::POINTER_CAPTURE)) { 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); + mQueuedListener.notifyPointerCaptureChanged( + {mContext.getNextId(), now, mCurrentPointerCaptureRequest}); } } } @@ -457,7 +457,7 @@ int32_t InputReader::getLedMetaStateLocked() { } void InputReader::notifyExternalStylusPresenceChangedLocked() { - refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE); + refreshConfigurationLocked(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE); } void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) { @@ -671,11 +671,11 @@ int32_t InputReader::getKeyCodeForKeyLocation(int32_t deviceId, int32_t location return device->getKeyCodeForKeyLocation(locationKeyCode); } -void InputReader::requestRefreshConfiguration(uint32_t changes) { +void InputReader::requestRefreshConfiguration(ConfigurationChanges changes) { std::scoped_lock _l(mLock); - if (changes) { - bool needWake = !mConfigurationChangesToRefresh; + if (changes.any()) { + bool needWake = !mConfigurationChangesToRefresh.any(); mConfigurationChangesToRefresh |= changes; if (needWake) { diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 4ae06fe77b..63035466cc 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -80,11 +80,12 @@ public: [[nodiscard]] std::list<NotifyArgs> setEnabled(bool enabled, nsecs_t when); void dump(std::string& dump, const std::string& eventHubDevStr); - void addEventHubDevice(int32_t eventHubId, bool populateMappers = true); + void addEmptyEventHubDevice(int32_t eventHubId); + void addEventHubDevice(int32_t eventHubId, const InputReaderConfiguration& readerConfig); void removeEventHubDevice(int32_t eventHubId); [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes); + const InputReaderConfiguration& readerConfig, + ConfigurationChanges changes); [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when); [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvents, size_t count); [[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when); @@ -137,7 +138,7 @@ public: template <class T, typename... Args> T& addMapper(int32_t eventHubId, Args... args) { // ensure a device entry exists for this eventHubId - addEventHubDevice(eventHubId, false); + addEmptyEventHubDevice(eventHubId); // create mapper auto& devicePair = mDevices[eventHubId]; @@ -152,7 +153,7 @@ public: template <class T> T& addController(int32_t eventHubId) { // ensure a device entry exists for this eventHubId - addEventHubDevice(eventHubId, false); + addEmptyEventHubDevice(eventHubId); // create controller auto& devicePair = mDevices[eventHubId]; @@ -191,6 +192,9 @@ private: typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code); int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc); + std::vector<std::unique_ptr<InputMapper>> createMappers( + InputDeviceContext& contextPtr, const InputReaderConfiguration& readerConfig); + PropertyMap mConfiguration; // helpers to interate over the devices collection @@ -403,7 +407,7 @@ public: inline const std::string getName() const { return mDevice.getName(); } inline const std::string getDescriptor() { return mDevice.getDescriptor(); } inline const std::string getLocation() { return mDevice.getLocation(); } - inline bool isExternal() { return mDevice.isExternal(); } + inline bool isExternal() const { return mDevice.isExternal(); } inline std::optional<uint8_t> getAssociatedDisplayPort() const { return mDevice.getAssociatedDisplayPort(); } @@ -420,7 +424,7 @@ public: return mDevice.cancelTouch(when, readTime); } inline void bumpGeneration() { mDevice.bumpGeneration(); } - inline const PropertyMap& getConfiguration() { return mDevice.getConfiguration(); } + inline const PropertyMap& getConfiguration() const { return mDevice.getConfiguration(); } private: InputDevice& mDevice; diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index 120e15070c..9112913565 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -77,7 +77,7 @@ public: bool hasKeys(int32_t deviceId, uint32_t sourceMask, const std::vector<int32_t>& keyCodes, uint8_t* outFlags) override; - void requestRefreshConfiguration(uint32_t changes) override; + void requestRefreshConfiguration(ConfigurationChanges changes) override; void vibrate(int32_t deviceId, const VibrationSequence& sequence, ssize_t repeat, int32_t token) override; @@ -233,8 +233,8 @@ private: nsecs_t mNextTimeout GUARDED_BY(mLock); void requestTimeoutAtTimeLocked(nsecs_t when) REQUIRES(mLock); - uint32_t mConfigurationChangesToRefresh GUARDED_BY(mLock); - void refreshConfigurationLocked(uint32_t changes) REQUIRES(mLock); + ConfigurationChanges mConfigurationChangesToRefresh GUARDED_BY(mLock); + void refreshConfigurationLocked(ConfigurationChanges changes) REQUIRES(mLock); void notifyAll(std::list<NotifyArgs>&& argsList); diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp index d7dc2aec70..8ef5ff6358 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp @@ -68,8 +68,12 @@ void CursorMotionAccumulator::finishSync() { // --- CursorInputMapper --- -CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext), mLastEventTime(std::numeric_limits<nsecs_t>::min()) {} +CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig), + mLastEventTime(std::numeric_limits<nsecs_t>::min()) { + configureWithZeroChanges(readerConfig); +} CursorInputMapper::~CursorInputMapper() { if (mPointerController != nullptr) { @@ -134,119 +138,28 @@ void CursorInputMapper::dump(std::string& dump) { } std::list<NotifyArgs> CursorInputMapper::reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) { - std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes); - - if (!changes) { // first time only - mCursorScrollAccumulator.configure(getDeviceContext()); - - // Configure basic parameters. - configureParameters(); - - // Configure device mode. - switch (mParameters.mode) { - case Parameters::Mode::POINTER_RELATIVE: - // Should not happen during first time configuration. - ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER"); - mParameters.mode = Parameters::Mode::POINTER; - [[fallthrough]]; - case Parameters::Mode::POINTER: - mSource = AINPUT_SOURCE_MOUSE; - mXPrecision = 1.0f; - mYPrecision = 1.0f; - mXScale = 1.0f; - mYScale = 1.0f; - mPointerController = getContext()->getPointerController(getDeviceId()); - break; - case Parameters::Mode::NAVIGATION: - mSource = AINPUT_SOURCE_TRACKBALL; - mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; - mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; - mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; - mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; - break; - } + const InputReaderConfiguration& readerConfig, + ConfigurationChanges changes) { + std::list<NotifyArgs> out = InputMapper::reconfigure(when, readerConfig, changes); - mVWheelScale = 1.0f; - mHWheelScale = 1.0f; + if (!changes.any()) { + configureWithZeroChanges(readerConfig); + return out; } const bool configurePointerCapture = mParameters.mode != Parameters::Mode::NAVIGATION && - ((!changes && config->pointerCaptureRequest.enable) || - (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)); + changes.test(InputReaderConfiguration::Change::POINTER_CAPTURE); if (configurePointerCapture) { - if (config->pointerCaptureRequest.enable) { - if (mParameters.mode == Parameters::Mode::POINTER) { - mParameters.mode = Parameters::Mode::POINTER_RELATIVE; - mSource = AINPUT_SOURCE_MOUSE_RELATIVE; - // Keep PointerController around in order to preserve the pointer position. - mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE); - } else { - ALOGE("Cannot request pointer capture, device is not in MODE_POINTER"); - } - } else { - if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) { - mParameters.mode = Parameters::Mode::POINTER; - mSource = AINPUT_SOURCE_MOUSE; - } else { - ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE"); - } - } - bumpGeneration(); - if (changes) { - out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId())); - } + configureOnPointerCapture(readerConfig); + out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId())); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED) || - configurePointerCapture) { - if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) { - // Disable any acceleration or scaling for the pointer when Pointer Capture is enabled. - mPointerVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS); - mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS); - mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS); - } else { - mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters); - mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters); - mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters); - } + if (changes.test(InputReaderConfiguration::Change::POINTER_SPEED) || configurePointerCapture) { + configureOnChangePointerSpeed(readerConfig); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO) || - configurePointerCapture) { - const bool isPointer = mParameters.mode == Parameters::Mode::POINTER; - - mDisplayId = ADISPLAY_ID_NONE; - if (auto viewport = mDeviceContext.getAssociatedViewport(); viewport) { - // This InputDevice is associated with a viewport. - // Only generate events for the associated display. - const bool mismatchedPointerDisplay = - isPointer && (viewport->displayId != mPointerController->getDisplayId()); - mDisplayId = mismatchedPointerDisplay ? std::nullopt - : std::make_optional(viewport->displayId); - } else if (isPointer) { - // The InputDevice is not associated with a viewport, but it controls the mouse pointer. - mDisplayId = mPointerController->getDisplayId(); - } - - mOrientation = ui::ROTATION_0; - const bool isOrientedDevice = - (mParameters.orientationAware && mParameters.hasAssociatedDisplay); - // InputReader works in the un-rotated display coordinate space, so we don't need to do - // anything if the device is already orientation-aware. If the device is not - // orientation-aware, then we need to apply the inverse rotation of the display so that - // when the display rotation is applied later as a part of the per-window transform, we - // get the expected screen coordinates. When pointer capture is enabled, we do not apply any - // rotations and report values directly from the input device. - if (!isOrientedDevice && mDisplayId && - mParameters.mode != Parameters::Mode::POINTER_RELATIVE) { - if (auto viewport = config->getDisplayViewportById(*mDisplayId); viewport) { - mOrientation = getInverseRotation(viewport->orientation); - } - } - - bumpGeneration(); + if (changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) || configurePointerCapture) { + configureOnChangeDisplayInfo(readerConfig); } return out; } @@ -511,4 +424,117 @@ std::optional<int32_t> CursorInputMapper::getAssociatedDisplayId() { return mDisplayId; } +void CursorInputMapper::configureWithZeroChanges(const InputReaderConfiguration& readerConfig) { + // Configuration with zero changes + configureBasicParams(); + if (mParameters.mode != Parameters::Mode::NAVIGATION && + readerConfig.pointerCaptureRequest.enable) { + configureOnPointerCapture(readerConfig); + } + configureOnChangePointerSpeed(readerConfig); + configureOnChangeDisplayInfo(readerConfig); +} + +void CursorInputMapper::configureBasicParams() { + mCursorScrollAccumulator.configure(getDeviceContext()); + + // Configure basic parameters. + configureParameters(); + + // Configure device mode. + switch (mParameters.mode) { + case Parameters::Mode::POINTER_RELATIVE: + // Should not happen during first time configuration. + ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER"); + mParameters.mode = Parameters::Mode::POINTER; + [[fallthrough]]; + case Parameters::Mode::POINTER: + mSource = AINPUT_SOURCE_MOUSE; + mXPrecision = 1.0f; + mYPrecision = 1.0f; + mXScale = 1.0f; + mYScale = 1.0f; + mPointerController = getContext()->getPointerController(getDeviceId()); + break; + case Parameters::Mode::NAVIGATION: + mSource = AINPUT_SOURCE_TRACKBALL; + mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; + mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; + mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; + mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; + break; + } + + mVWheelScale = 1.0f; + mHWheelScale = 1.0f; +} + +void CursorInputMapper::configureOnPointerCapture(const InputReaderConfiguration& config) { + if (config.pointerCaptureRequest.enable) { + if (mParameters.mode == Parameters::Mode::POINTER) { + mParameters.mode = Parameters::Mode::POINTER_RELATIVE; + mSource = AINPUT_SOURCE_MOUSE_RELATIVE; + // Keep PointerController around in order to preserve the pointer position. + mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE); + } else { + ALOGE("Cannot request pointer capture, device is not in MODE_POINTER"); + } + } else { + if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) { + mParameters.mode = Parameters::Mode::POINTER; + mSource = AINPUT_SOURCE_MOUSE; + } else { + ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE"); + } + } + bumpGeneration(); +} + +void CursorInputMapper::configureOnChangePointerSpeed(const InputReaderConfiguration& config) { + if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) { + // Disable any acceleration or scaling for the pointer when Pointer Capture is enabled. + mPointerVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS); + mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS); + mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS); + } else { + mPointerVelocityControl.setParameters(config.pointerVelocityControlParameters); + mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters); + mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters); + } +} + +void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfiguration& config) { + const bool isPointer = mParameters.mode == Parameters::Mode::POINTER; + + mDisplayId = ADISPLAY_ID_NONE; + if (auto viewport = mDeviceContext.getAssociatedViewport(); viewport) { + // This InputDevice is associated with a viewport. + // Only generate events for the associated display. + const bool mismatchedPointerDisplay = + isPointer && (viewport->displayId != mPointerController->getDisplayId()); + mDisplayId = + mismatchedPointerDisplay ? std::nullopt : std::make_optional(viewport->displayId); + } else if (isPointer) { + // The InputDevice is not associated with a viewport, but it controls the mouse pointer. + mDisplayId = mPointerController->getDisplayId(); + } + + mOrientation = ui::ROTATION_0; + const bool isOrientedDevice = + (mParameters.orientationAware && mParameters.hasAssociatedDisplay); + // InputReader works in the un-rotated display coordinate space, so we don't need to do + // anything if the device is already orientation-aware. If the device is not + // orientation-aware, then we need to apply the inverse rotation of the display so that + // when the display rotation is applied later as a part of the per-window transform, we + // get the expected screen coordinates. When pointer capture is enabled, we do not apply any + // rotations and report values directly from the input device. + if (!isOrientedDevice && mDisplayId && mParameters.mode != Parameters::Mode::POINTER_RELATIVE) { + if (auto viewport = config.getDisplayViewportById(*mDisplayId); viewport) { + mOrientation = getInverseRotation(viewport->orientation); + } + } + + bumpGeneration(); +} + } // namespace android diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h index 987b9debb9..caf2e5a4c4 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.h +++ b/services/inputflinger/reader/mapper/CursorInputMapper.h @@ -53,15 +53,16 @@ private: class CursorInputMapper : public InputMapper { public: - explicit CursorInputMapper(InputDeviceContext& deviceContext); + explicit CursorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); virtual ~CursorInputMapper(); virtual uint32_t getSources() const override; virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override; virtual void dump(std::string& dump) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) override; + const InputReaderConfiguration& readerConfig, + ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; @@ -126,6 +127,11 @@ private: void configureParameters(); void dumpParameters(std::string& dump); + void configureWithZeroChanges(const InputReaderConfiguration& readerConfig); + void configureBasicParams(); + void configureOnPointerCapture(const InputReaderConfiguration& config); + void configureOnChangePointerSpeed(const InputReaderConfiguration& config); + void configureOnChangeDisplayInfo(const InputReaderConfiguration& config); [[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime); }; diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp index c5a3075657..987d2d0221 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp @@ -23,8 +23,9 @@ namespace android { -ExternalStylusInputMapper::ExternalStylusInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext), mTouchButtonAccumulator(deviceContext) {} +ExternalStylusInputMapper::ExternalStylusInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig), mTouchButtonAccumulator(deviceContext) {} uint32_t ExternalStylusInputMapper::getSources() const { return AINPUT_SOURCE_STYLUS; @@ -47,8 +48,8 @@ void ExternalStylusInputMapper::dump(std::string& dump) { } std::list<NotifyArgs> ExternalStylusInputMapper::reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) { + const InputReaderConfiguration& config, + ConfigurationChanges changes) { getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis); mTouchButtonAccumulator.configure(); return {}; diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h index 0df8cf7b1b..841c437543 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h @@ -26,15 +26,16 @@ namespace android { class ExternalStylusInputMapper : public InputMapper { public: - explicit ExternalStylusInputMapper(InputDeviceContext& deviceContext); + explicit ExternalStylusInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); virtual ~ExternalStylusInputMapper() = default; uint32_t getSources() const override; void populateDeviceInfo(InputDeviceInfo& deviceInfo) override; void dump(std::string& dump) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) override; + const InputReaderConfiguration& config, + ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp index 9d1e9ceb1c..0692dbbe0a 100644 --- a/services/inputflinger/reader/mapper/InputMapper.cpp +++ b/services/inputflinger/reader/mapper/InputMapper.cpp @@ -25,7 +25,9 @@ namespace android { -InputMapper::InputMapper(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {} +InputMapper::InputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : mDeviceContext(deviceContext) {} InputMapper::~InputMapper() {} @@ -35,8 +37,8 @@ void InputMapper::populateDeviceInfo(InputDeviceInfo& info) { void InputMapper::dump(std::string& dump) {} -std::list<NotifyArgs> InputMapper::reconfigure(nsecs_t when, const InputReaderConfiguration* config, - uint32_t changes) { +std::list<NotifyArgs> InputMapper::reconfigure(nsecs_t when, const InputReaderConfiguration& config, + ConfigurationChanges changes) { return {}; } diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h index bb15e4d86b..f017317485 100644 --- a/services/inputflinger/reader/mapper/InputMapper.h +++ b/services/inputflinger/reader/mapper/InputMapper.h @@ -31,16 +31,16 @@ namespace android { * different classes of events. * * InputMapper lifecycle: - * - create - * - configure with 0 changes + * - create and configure with 0 changes * - reset - * - process, process, process (may occasionally reconfigure with non-zero changes or reset) + * - process, process, process (may occasionally reconfigure or reset) * - reset * - destroy */ class InputMapper { public: - explicit InputMapper(InputDeviceContext& deviceContext); + explicit InputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); virtual ~InputMapper(); inline int32_t getDeviceId() { return mDeviceContext.getId(); } @@ -54,8 +54,8 @@ public: virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo); virtual void dump(std::string& dump); [[nodiscard]] virtual std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes); + const InputReaderConfiguration& config, + ConfigurationChanges changes); [[nodiscard]] virtual std::list<NotifyArgs> reset(nsecs_t when); [[nodiscard]] virtual std::list<NotifyArgs> process(const RawEvent* rawEvent) = 0; [[nodiscard]] virtual std::list<NotifyArgs> timeoutExpired(nsecs_t when); diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp index f60035bd00..099a95541e 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp @@ -20,8 +20,9 @@ namespace android { -JoystickInputMapper::JoystickInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext) {} +JoystickInputMapper::JoystickInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig) {} JoystickInputMapper::~JoystickInputMapper() {} @@ -104,11 +105,11 @@ void JoystickInputMapper::dump(std::string& dump) { } std::list<NotifyArgs> JoystickInputMapper::reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) { + const InputReaderConfiguration& config, + ConfigurationChanges changes) { std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes); - if (!changes) { // first time only + if (!changes.any()) { // first time only // Collect all axes. for (int32_t abs = 0; abs <= ABS_MAX; abs++) { if (!(getAbsAxisUsage(abs, getDeviceContext().getDeviceClasses()) diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h index 9adb07fb4e..49673a2f4e 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.h +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h @@ -22,15 +22,16 @@ namespace android { class JoystickInputMapper : public InputMapper { public: - explicit JoystickInputMapper(InputDeviceContext& deviceContext); + explicit JoystickInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); virtual ~JoystickInputMapper(); virtual uint32_t getSources() const override; virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override; virtual void dump(std::string& dump) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) override; + const InputReaderConfiguration& config, + ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index fc00c4886d..582fb46550 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -63,9 +63,10 @@ static bool isSupportedScanCode(int32_t scanCode) { // --- KeyboardInputMapper --- -KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source, - int32_t keyboardType) - : InputMapper(deviceContext), mSource(source), mKeyboardType(keyboardType) {} +KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig, + uint32_t source, int32_t keyboardType) + : InputMapper(deviceContext, readerConfig), mSource(source), mKeyboardType(keyboardType) {} uint32_t KeyboardInputMapper::getSources() const { return mSource; @@ -118,36 +119,37 @@ void KeyboardInputMapper::dump(std::string& dump) { } std::optional<DisplayViewport> KeyboardInputMapper::findViewport( - const InputReaderConfiguration* config) { + const InputReaderConfiguration& readerConfig) { if (getDeviceContext().getAssociatedViewport()) { return getDeviceContext().getAssociatedViewport(); } // No associated display defined, try to find default display if orientationAware. if (mParameters.orientationAware) { - return config->getDisplayViewportByType(ViewportType::INTERNAL); + return readerConfig.getDisplayViewportByType(ViewportType::INTERNAL); } return std::nullopt; } std::list<NotifyArgs> KeyboardInputMapper::reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) { + const InputReaderConfiguration& config, + ConfigurationChanges changes) { std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes); - if (!changes) { // first time only + if (!changes.any()) { // first time only // Configure basic parameters. configureParameters(); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { + if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) { mViewport = findViewport(config); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUT_ASSOCIATION)) { + if (!changes.any() || + changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION)) { mKeyboardLayoutInfo = - getValueByKey(config->keyboardLayoutAssociations, getDeviceContext().getLocation()); + getValueByKey(config.keyboardLayoutAssociations, getDeviceContext().getLocation()); } return out; diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h index 52576c339c..bd27383296 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h @@ -23,15 +23,17 @@ namespace android { class KeyboardInputMapper : public InputMapper { public: - KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source, int32_t keyboardType); + KeyboardInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig, uint32_t source, + int32_t keyboardType); ~KeyboardInputMapper() override = default; uint32_t getSources() const override; void populateDeviceInfo(InputDeviceInfo& deviceInfo) override; void dump(std::string& dump) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) override; + const InputReaderConfiguration& config, + ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; @@ -96,7 +98,7 @@ private: void resetLedState(); void initializeLedState(LedState& ledState, int32_t led); void updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset); - std::optional<DisplayViewport> findViewport(const InputReaderConfiguration* config); + std::optional<DisplayViewport> findViewport(const InputReaderConfiguration& readerConfig); [[nodiscard]] std::list<NotifyArgs> cancelAllDownKeys(nsecs_t when); }; diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp index e87128825d..9c87c62a7c 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp @@ -28,8 +28,9 @@ static constexpr size_t MAX_SLOTS = 32; // --- MultiTouchInputMapper --- -MultiTouchInputMapper::MultiTouchInputMapper(InputDeviceContext& deviceContext) - : TouchInputMapper(deviceContext) {} +MultiTouchInputMapper::MultiTouchInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : TouchInputMapper(deviceContext, readerConfig) {} MultiTouchInputMapper::~MultiTouchInputMapper() {} diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h index 5f8bccf9e6..a617420dc9 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h @@ -23,7 +23,8 @@ namespace android { class MultiTouchInputMapper : public TouchInputMapper { public: - explicit MultiTouchInputMapper(InputDeviceContext& deviceContext); + explicit MultiTouchInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); ~MultiTouchInputMapper() override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp index 5b7b29509e..13f2e59db9 100644 --- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp +++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp @@ -26,8 +26,9 @@ namespace android { -RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext), mOrientation(ui::ROTATION_0) { +RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig), mOrientation(ui::ROTATION_0) { mSource = AINPUT_SOURCE_ROTARY_ENCODER; } @@ -64,15 +65,15 @@ void RotaryEncoderInputMapper::dump(std::string& dump) { } std::list<NotifyArgs> RotaryEncoderInputMapper::reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) { + const InputReaderConfiguration& config, + ConfigurationChanges changes) { std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes); - if (!changes) { + if (!changes.any()) { mRotaryEncoderScrollAccumulator.configure(getDeviceContext()); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { + if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) { std::optional<DisplayViewport> internalViewport = - config->getDisplayViewportByType(ViewportType::INTERNAL); + config.getDisplayViewportByType(ViewportType::INTERNAL); if (internalViewport) { mOrientation = internalViewport->orientation; } else { diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h index 639a9876c7..d3dcbe1bb4 100644 --- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h +++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h @@ -25,15 +25,16 @@ namespace android { class RotaryEncoderInputMapper : public InputMapper { public: - explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext); + explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); virtual ~RotaryEncoderInputMapper(); virtual uint32_t getSources() const override; virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override; virtual void dump(std::string& dump) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) override; + const InputReaderConfiguration& config, + ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp index 720fc6962d..a131e3598f 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp @@ -52,8 +52,9 @@ static void convertFromLinuxToAndroid(std::vector<float>& values, } } -SensorInputMapper::SensorInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext) {} +SensorInputMapper::SensorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig) {} SensorInputMapper::~SensorInputMapper() {} @@ -117,11 +118,11 @@ void SensorInputMapper::dump(std::string& dump) { } std::list<NotifyArgs> SensorInputMapper::reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) { + const InputReaderConfiguration& config, + ConfigurationChanges changes) { std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes); - if (!changes) { // first time only + if (!changes.any()) { // first time only mDeviceEnabled = true; // Check if device has MSC_TIMESTAMP event. mHasHardwareTimestamp = getDeviceContext().hasMscEvent(MSC_TIMESTAMP); diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h index 93cc244481..1f82559db8 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.h +++ b/services/inputflinger/reader/mapper/SensorInputMapper.h @@ -27,15 +27,16 @@ static constexpr ssize_t SENSOR_VEC_LEN = 3; class SensorInputMapper : public InputMapper { public: - explicit SensorInputMapper(InputDeviceContext& deviceContext); + explicit SensorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); ~SensorInputMapper() override; uint32_t getSources() const override; void populateDeviceInfo(InputDeviceInfo& deviceInfo) override; void dump(std::string& dump) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) override; + const InputReaderConfiguration& config, + ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp index f13417a93b..ed0e27067f 100644 --- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp @@ -18,8 +18,9 @@ namespace android { -SingleTouchInputMapper::SingleTouchInputMapper(InputDeviceContext& deviceContext) - : TouchInputMapper(deviceContext) {} +SingleTouchInputMapper::SingleTouchInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : TouchInputMapper(deviceContext, readerConfig) {} SingleTouchInputMapper::~SingleTouchInputMapper() {} diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h index 662e6bca25..93410078d1 100644 --- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h +++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h @@ -23,7 +23,8 @@ namespace android { class SingleTouchInputMapper : public TouchInputMapper { public: - explicit SingleTouchInputMapper(InputDeviceContext& deviceContext); + explicit SingleTouchInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); ~SingleTouchInputMapper() override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp index c4564a4380..05338da146 100644 --- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp @@ -20,8 +20,9 @@ namespace android { -SwitchInputMapper::SwitchInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext), mSwitchValues(0), mUpdatedSwitchMask(0) {} +SwitchInputMapper::SwitchInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig), mSwitchValues(0), mUpdatedSwitchMask(0) {} SwitchInputMapper::~SwitchInputMapper() {} diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.h b/services/inputflinger/reader/mapper/SwitchInputMapper.h index 06d6504684..7ec282b721 100644 --- a/services/inputflinger/reader/mapper/SwitchInputMapper.h +++ b/services/inputflinger/reader/mapper/SwitchInputMapper.h @@ -22,7 +22,8 @@ namespace android { class SwitchInputMapper : public InputMapper { public: - explicit SwitchInputMapper(InputDeviceContext& deviceContext); + explicit SwitchInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); virtual ~SwitchInputMapper(); virtual uint32_t getSources() const override; diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index c19737d672..c72a263dcd 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -121,12 +121,12 @@ void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) con // --- TouchInputMapper --- -TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext), +TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig), mTouchButtonAccumulator(deviceContext), - mSource(0), - mDeviceMode(DeviceMode::DISABLED), - mInputDeviceOrientation(ui::ROTATION_0) {} + mConfig(readerConfig), + mParameters(computeParameters(deviceContext)) {} TouchInputMapper::~TouchInputMapper() {} @@ -288,18 +288,18 @@ void TouchInputMapper::dump(std::string& dump) { } std::list<NotifyArgs> TouchInputMapper::reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) { + const InputReaderConfiguration& config, + ConfigurationChanges changes) { std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes); - mConfig = *config; + mConfig = config; // Full configuration should happen the first time configure is called and // when the device type is changed. Changing a device type can affect // various other parameters so should result in a reconfiguration. - if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_TYPE)) { + if (!changes.any() || changes.test(InputReaderConfiguration::Change::DEVICE_TYPE)) { // Configure basic parameters. - configureParameters(); + mParameters = computeParameters(getDeviceContext()); // Configure common accumulators. mCursorScrollAccumulator.configure(getDeviceContext()); @@ -313,33 +313,34 @@ std::list<NotifyArgs> TouchInputMapper::reconfigure(nsecs_t when, resolveCalibration(); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) { + if (!changes.any() || + changes.test(InputReaderConfiguration::Change::TOUCH_AFFINE_TRANSFORMATION)) { // Update location calibration to reflect current settings updateAffineTransformation(); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { + if (!changes.any() || changes.test(InputReaderConfiguration::Change::POINTER_SPEED)) { // Update pointer speed. mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters); mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters); mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters); } + using namespace ftl::flag_operators; bool resetNeeded = false; - if (!changes || - (changes & - (InputReaderConfiguration::CHANGE_DISPLAY_INFO | - InputReaderConfiguration::CHANGE_POINTER_CAPTURE | - InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT | - InputReaderConfiguration::CHANGE_SHOW_TOUCHES | - InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE | - InputReaderConfiguration::CHANGE_DEVICE_TYPE))) { + if (!changes.any() || + changes.any(InputReaderConfiguration::Change::DISPLAY_INFO | + InputReaderConfiguration::Change::POINTER_CAPTURE | + InputReaderConfiguration::Change::POINTER_GESTURE_ENABLEMENT | + InputReaderConfiguration::Change::SHOW_TOUCHES | + InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE | + InputReaderConfiguration::Change::DEVICE_TYPE)) { // Configure device sources, display dimensions, orientation and // scaling factors. configureInputDevice(when, &resetNeeded); } - if (changes && resetNeeded) { + if (changes.any() && resetNeeded) { out += reset(when); // Send reset, unless this is the first time the device has been configured, @@ -359,112 +360,119 @@ void TouchInputMapper::resolveExternalStylusPresence() { } } -void TouchInputMapper::configureParameters() { +TouchInputMapper::Parameters TouchInputMapper::computeParameters( + const InputDeviceContext& deviceContext) { + Parameters parameters; // Use the pointer presentation mode for devices that do not support distinct // multitouch. The spot-based presentation relies on being able to accurately // locate two or more fingers on the touch pad. - mParameters.gestureMode = getDeviceContext().hasInputProperty(INPUT_PROP_SEMI_MT) + parameters.gestureMode = deviceContext.hasInputProperty(INPUT_PROP_SEMI_MT) ? Parameters::GestureMode::SINGLE_TOUCH : Parameters::GestureMode::MULTI_TOUCH; - const PropertyMap& config = getDeviceContext().getConfiguration(); + const PropertyMap& config = deviceContext.getConfiguration(); std::optional<std::string> gestureModeString = config.getString("touch.gestureMode"); if (gestureModeString.has_value()) { if (*gestureModeString == "single-touch") { - mParameters.gestureMode = Parameters::GestureMode::SINGLE_TOUCH; + parameters.gestureMode = Parameters::GestureMode::SINGLE_TOUCH; } else if (*gestureModeString == "multi-touch") { - mParameters.gestureMode = Parameters::GestureMode::MULTI_TOUCH; + parameters.gestureMode = Parameters::GestureMode::MULTI_TOUCH; } else if (*gestureModeString != "default") { ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString->c_str()); } } - configureDeviceType(); + parameters.deviceType = computeDeviceType(deviceContext); - mParameters.hasButtonUnderPad = getDeviceContext().hasInputProperty(INPUT_PROP_BUTTONPAD); + parameters.hasButtonUnderPad = deviceContext.hasInputProperty(INPUT_PROP_BUTTONPAD); - mParameters.orientationAware = + parameters.orientationAware = config.getBool("touch.orientationAware") - .value_or(mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN); + .value_or(parameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN); - mParameters.orientation = ui::ROTATION_0; + parameters.orientation = ui::ROTATION_0; std::optional<std::string> orientationString = config.getString("touch.orientation"); if (orientationString.has_value()) { - if (mParameters.deviceType != Parameters::DeviceType::TOUCH_SCREEN) { + if (parameters.deviceType != Parameters::DeviceType::TOUCH_SCREEN) { ALOGW("The configuration 'touch.orientation' is only supported for touchscreens."); } else if (*orientationString == "ORIENTATION_90") { - mParameters.orientation = ui::ROTATION_90; + parameters.orientation = ui::ROTATION_90; } else if (*orientationString == "ORIENTATION_180") { - mParameters.orientation = ui::ROTATION_180; + parameters.orientation = ui::ROTATION_180; } else if (*orientationString == "ORIENTATION_270") { - mParameters.orientation = ui::ROTATION_270; + parameters.orientation = ui::ROTATION_270; } else if (*orientationString != "ORIENTATION_0") { ALOGW("Invalid value for touch.orientation: '%s'", orientationString->c_str()); } } - mParameters.hasAssociatedDisplay = false; - mParameters.associatedDisplayIsExternal = false; - if (mParameters.orientationAware || - mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN || - mParameters.deviceType == Parameters::DeviceType::POINTER || - (mParameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION && - getDeviceContext().getAssociatedViewport())) { - mParameters.hasAssociatedDisplay = true; - if (mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN) { - mParameters.associatedDisplayIsExternal = getDeviceContext().isExternal(); - mParameters.uniqueDisplayId = config.getString("touch.displayId").value_or("").c_str(); + parameters.hasAssociatedDisplay = false; + parameters.associatedDisplayIsExternal = false; + if (parameters.orientationAware || + parameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN || + parameters.deviceType == Parameters::DeviceType::POINTER || + (parameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION && + deviceContext.getAssociatedViewport())) { + parameters.hasAssociatedDisplay = true; + if (parameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN) { + parameters.associatedDisplayIsExternal = deviceContext.isExternal(); + parameters.uniqueDisplayId = config.getString("touch.displayId").value_or("").c_str(); } } - if (getDeviceContext().getAssociatedDisplayPort()) { - mParameters.hasAssociatedDisplay = true; + if (deviceContext.getAssociatedDisplayPort()) { + parameters.hasAssociatedDisplay = true; } // Initial downs on external touch devices should wake the device. // Normally we don't do this for internal touch screens to prevent them from waking // up in your pocket but you can enable it using the input device configuration. - mParameters.wake = config.getBool("touch.wake").value_or(getDeviceContext().isExternal()); + parameters.wake = config.getBool("touch.wake").value_or(deviceContext.isExternal()); std::optional<int32_t> usiVersionMajor = config.getInt("touch.usiVersionMajor"); std::optional<int32_t> usiVersionMinor = config.getInt("touch.usiVersionMinor"); if (usiVersionMajor.has_value() && usiVersionMinor.has_value()) { - mParameters.usiVersion = { + parameters.usiVersion = { .majorVersion = *usiVersionMajor, .minorVersion = *usiVersionMinor, }; } - mParameters.enableForInactiveViewport = + parameters.enableForInactiveViewport = config.getBool("touch.enableForInactiveViewport").value_or(false); + + return parameters; } -void TouchInputMapper::configureDeviceType() { - if (getDeviceContext().hasInputProperty(INPUT_PROP_DIRECT)) { +TouchInputMapper::Parameters::DeviceType TouchInputMapper::computeDeviceType( + const InputDeviceContext& deviceContext) { + Parameters::DeviceType deviceType; + if (deviceContext.hasInputProperty(INPUT_PROP_DIRECT)) { // The device is a touch screen. - mParameters.deviceType = Parameters::DeviceType::TOUCH_SCREEN; - } else if (getDeviceContext().hasInputProperty(INPUT_PROP_POINTER)) { + deviceType = Parameters::DeviceType::TOUCH_SCREEN; + } else if (deviceContext.hasInputProperty(INPUT_PROP_POINTER)) { // The device is a pointing device like a track pad. - mParameters.deviceType = Parameters::DeviceType::POINTER; + deviceType = Parameters::DeviceType::POINTER; } else { // The device is a touch pad of unknown purpose. - mParameters.deviceType = Parameters::DeviceType::POINTER; + deviceType = Parameters::DeviceType::POINTER; } // Type association takes precedence over the device type found in the idc file. - std::string deviceTypeString = getDeviceContext().getDeviceTypeAssociation().value_or(""); + std::string deviceTypeString = deviceContext.getDeviceTypeAssociation().value_or(""); if (deviceTypeString.empty()) { deviceTypeString = - getDeviceContext().getConfiguration().getString("touch.deviceType").value_or(""); + deviceContext.getConfiguration().getString("touch.deviceType").value_or(""); } if (deviceTypeString == "touchScreen") { - mParameters.deviceType = Parameters::DeviceType::TOUCH_SCREEN; + deviceType = Parameters::DeviceType::TOUCH_SCREEN; } else if (deviceTypeString == "touchNavigation") { - mParameters.deviceType = Parameters::DeviceType::TOUCH_NAVIGATION; + deviceType = Parameters::DeviceType::TOUCH_NAVIGATION; } else if (deviceTypeString == "pointer") { - mParameters.deviceType = Parameters::DeviceType::POINTER; + deviceType = Parameters::DeviceType::POINTER; } else if (deviceTypeString != "default" && deviceTypeString != "") { ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.c_str()); } + return deviceType; } void TouchInputMapper::dumpParameters(std::string& dump) { @@ -3600,17 +3608,19 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec "%s cannot be used when the device is not in POINTER mode.", __func__); std::list<NotifyArgs> out; int32_t metaState = getContext()->getGlobalMetaState(); + auto cursorPosition = mPointerSimple.currentCoords.getXYValue(); - if (down || hovering) { - mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER); - mPointerController->clearSpots(); - mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE); - } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) { - mPointerController->fade(PointerControllerInterface::Transition::GRADUAL); + if (displayId == mPointerController->getDisplayId()) { + std::tie(cursorPosition.x, cursorPosition.y) = mPointerController->getPosition(); + if (down || hovering) { + mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER); + mPointerController->clearSpots(); + mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE); + } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) { + mPointerController->fade(PointerControllerInterface::Transition::GRADUAL); + } } - const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition(); - if (mPointerSimple.down && !down) { mPointerSimple.down = false; @@ -3620,8 +3630,9 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec 0, metaState, mLastRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, - mOrientedXPrecision, mOrientedYPrecision, xCursorPosition, - yCursorPosition, mPointerSimple.downTime, + mOrientedXPrecision, mOrientedYPrecision, + mPointerSimple.lastCursorX, mPointerSimple.lastCursorY, + mPointerSimple.downTime, /* videoFrames */ {})); } @@ -3629,15 +3640,15 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec mPointerSimple.hovering = false; // Send hover exit. - out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(), - mSource, displayId, policyFlags, - AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, - mLastRawState.buttonState, MotionClassification::NONE, - AMOTION_EVENT_EDGE_FLAG_NONE, 1, - &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, - mOrientedXPrecision, mOrientedYPrecision, xCursorPosition, - yCursorPosition, mPointerSimple.downTime, - /* videoFrames */ {})); + out.push_back( + NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, + metaState, mLastRawState.buttonState, MotionClassification::NONE, + AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties, + &mPointerSimple.lastCoords, mOrientedXPrecision, + mOrientedYPrecision, mPointerSimple.lastCursorX, + mPointerSimple.lastCursorY, mPointerSimple.downTime, + /* videoFrames */ {})); } if (down) { @@ -3653,7 +3664,7 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, - mOrientedYPrecision, xCursorPosition, yCursorPosition, + mOrientedYPrecision, cursorPosition.x, cursorPosition.y, mPointerSimple.downTime, /* videoFrames */ {})); } @@ -3664,7 +3675,7 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, - mOrientedYPrecision, xCursorPosition, yCursorPosition, + mOrientedYPrecision, cursorPosition.x, cursorPosition.y, mPointerSimple.downTime, /* videoFrames */ {})); } @@ -3680,7 +3691,7 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, - mOrientedYPrecision, xCursorPosition, yCursorPosition, + mOrientedYPrecision, cursorPosition.x, cursorPosition.y, mPointerSimple.downTime, /* videoFrames */ {})); } @@ -3691,8 +3702,8 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec metaState, mCurrentRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, - mOrientedXPrecision, mOrientedYPrecision, xCursorPosition, - yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {})); + mOrientedXPrecision, mOrientedYPrecision, cursorPosition.x, + cursorPosition.y, mPointerSimple.downTime, /* videoFrames */ {})); } if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) { @@ -3712,8 +3723,8 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec 0, 0, metaState, mCurrentRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties, &pointerCoords, - mOrientedXPrecision, mOrientedYPrecision, xCursorPosition, - yCursorPosition, mPointerSimple.downTime, + mOrientedXPrecision, mOrientedYPrecision, cursorPosition.x, + cursorPosition.y, mPointerSimple.downTime, /* videoFrames */ {})); } @@ -3723,8 +3734,8 @@ std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsec mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties); mPointerSimple.displayId = displayId; mPointerSimple.source = mSource; - mPointerSimple.lastCursorX = xCursorPosition; - mPointerSimple.lastCursorY = yCursorPosition; + mPointerSimple.lastCursorX = cursorPosition.x; + mPointerSimple.lastCursorY = cursorPosition.y; } else { mPointerSimple.reset(); } diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index d98ae607e9..7141924e83 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -146,15 +146,16 @@ struct CookedPointerData { class TouchInputMapper : public InputMapper { public: - explicit TouchInputMapper(InputDeviceContext& deviceContext); + explicit TouchInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); ~TouchInputMapper() override; uint32_t getSources() const override; void populateDeviceInfo(InputDeviceInfo& deviceInfo) override; void dump(std::string& dump) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) override; + const InputReaderConfiguration& config, + ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; @@ -191,7 +192,7 @@ protected: }; // Input sources and device mode. - uint32_t mSource; + uint32_t mSource{0}; enum class DeviceMode { DISABLED, // input is disabled @@ -202,7 +203,7 @@ protected: ftl_last = POINTER }; - DeviceMode mDeviceMode; + DeviceMode mDeviceMode{DeviceMode::DISABLED}; // The reader's configuration. InputReaderConfiguration mConfig; @@ -376,7 +377,6 @@ protected: std::vector<VirtualKey> mVirtualKeys; - virtual void configureParameters(); virtual void dumpParameters(std::string& dump); virtual void configureRawPointerAxes(); virtual void dumpRawPointerAxes(std::string& dump); @@ -412,7 +412,7 @@ private: // The orientation of the input device relative to that of the display panel. It specifies // the rotation of the input device coordinates required to produce the display panel // orientation, so it will depend on whether the device is orientation aware. - ui::Rotation mInputDeviceOrientation; + ui::Rotation mInputDeviceOrientation{ui::ROTATION_0}; // The transform that maps the input device's raw coordinate space to the un-rotated display's // coordinate space. InputReader generates events in the un-rotated display's coordinate space. @@ -823,8 +823,8 @@ private: // Compute input transforms for DIRECT and POINTER modes. void computeInputTransforms(); - - void configureDeviceType(); + static Parameters::DeviceType computeDeviceType(const InputDeviceContext& deviceContext); + static Parameters computeParameters(const InputDeviceContext& deviceContext); }; } // namespace android diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp index 33f368e9eb..8753b487e3 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp @@ -57,7 +57,7 @@ const std::vector<CurveSegment> segments = { {std::numeric_limits<double>::infinity(), 15.04, -857.758}, }; -const std::vector<double> sensitivityFactors = {1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20}; +const std::vector<double> sensitivityFactors = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18}; std::vector<double> createAccelerationCurveForSensitivity(int32_t sensitivity, size_t propertySize) { @@ -169,8 +169,9 @@ void gestureInterpreterCallback(void* clientData, const Gesture* gesture) { } // namespace -TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext), +TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig), mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter), mPointerController(getContext()->getPointerController(getDeviceId())), mStateConverter(deviceContext), @@ -220,36 +221,36 @@ void TouchpadInputMapper::dump(std::string& dump) { } std::list<NotifyArgs> TouchpadInputMapper::reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) { - if (!changes) { + const InputReaderConfiguration& config, + ConfigurationChanges changes) { + if (!changes.any()) { // First time configuration mPropertyProvider.loadPropertiesFromIdcFile(getDeviceContext().getConfiguration()); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { + if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) { std::optional<int32_t> displayId = mPointerController->getDisplayId(); ui::Rotation orientation = ui::ROTATION_0; if (displayId.has_value()) { - if (auto viewport = config->getDisplayViewportById(*displayId); viewport) { + if (auto viewport = config.getDisplayViewportById(*displayId); viewport) { orientation = getInverseRotation(viewport->orientation); } } mGestureConverter.setOrientation(orientation); } - if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCHPAD_SETTINGS)) { + if (!changes.any() || changes.test(InputReaderConfiguration::Change::TOUCHPAD_SETTINGS)) { mPropertyProvider.getProperty("Use Custom Touchpad Pointer Accel Curve") .setBoolValues({true}); GesturesProp accelCurveProp = mPropertyProvider.getProperty("Pointer Accel Curve"); accelCurveProp.setRealValues( - createAccelerationCurveForSensitivity(config->touchpadPointerSpeed, + createAccelerationCurveForSensitivity(config.touchpadPointerSpeed, accelCurveProp.getCount())); mPropertyProvider.getProperty("Invert Scrolling") - .setBoolValues({config->touchpadNaturalScrollingEnabled}); + .setBoolValues({config.touchpadNaturalScrollingEnabled}); mPropertyProvider.getProperty("Tap Enable") - .setBoolValues({config->touchpadTapToClickEnabled}); + .setBoolValues({config.touchpadTapToClickEnabled}); mPropertyProvider.getProperty("Button Right Click Zone Enable") - .setBoolValues({config->touchpadRightClickZoneEnabled}); + .setBoolValues({config.touchpadRightClickZoneEnabled}); } return {}; } diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h index 6f152fa557..268b275584 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h @@ -37,7 +37,8 @@ namespace android { class TouchpadInputMapper : public InputMapper { public: - explicit TouchpadInputMapper(InputDeviceContext& deviceContext); + explicit TouchpadInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); ~TouchpadInputMapper(); uint32_t getSources() const override; @@ -45,8 +46,8 @@ public: void dump(std::string& dump) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, - const InputReaderConfiguration* config, - uint32_t changes) override; + const InputReaderConfiguration& config, + ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp index 2c77fc47c4..8d78d0fd80 100644 --- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp @@ -20,8 +20,9 @@ namespace android { -VibratorInputMapper::VibratorInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext), mVibrating(false), mSequence(0) {} +VibratorInputMapper::VibratorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig) + : InputMapper(deviceContext, readerConfig), mVibrating(false), mSequence(0) {} VibratorInputMapper::~VibratorInputMapper() {} diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h index e665973818..384c07512a 100644 --- a/services/inputflinger/reader/mapper/VibratorInputMapper.h +++ b/services/inputflinger/reader/mapper/VibratorInputMapper.h @@ -22,7 +22,8 @@ namespace android { class VibratorInputMapper : public InputMapper { public: - explicit VibratorInputMapper(InputDeviceContext& deviceContext); + explicit VibratorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig); virtual ~VibratorInputMapper(); virtual uint32_t getSources() const override; diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp index 30c1719c35..3486d0f2a4 100644 --- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp +++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp @@ -154,8 +154,8 @@ void FakeInputReaderPolicy::setPointerController( mPointerController = std::move(controller); } -const InputReaderConfiguration* FakeInputReaderPolicy::getReaderConfiguration() const { - return &mConfig; +const InputReaderConfiguration& FakeInputReaderPolicy::getReaderConfiguration() const { + return mConfig; } const std::vector<InputDeviceInfo>& FakeInputReaderPolicy::getInputDevices() const { diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h index 28ac505284..85ff01a071 100644 --- a/services/inputflinger/tests/FakeInputReaderPolicy.h +++ b/services/inputflinger/tests/FakeInputReaderPolicy.h @@ -63,7 +63,7 @@ public: void addDisabledDevice(int32_t deviceId); void removeDisabledDevice(int32_t deviceId); void setPointerController(std::shared_ptr<FakePointerController> controller); - const InputReaderConfiguration* getReaderConfiguration() const; + const InputReaderConfiguration& getReaderConfiguration() const; const std::vector<InputDeviceInfo>& getInputDevices() const; TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor, ui::Rotation surfaceRotation); diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index fb808eb2a3..27d7b9c93f 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -213,7 +213,7 @@ public: void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) { assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) { - ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY); + ASSERT_EQ(event.getType(), InputEventType::KEY); EXPECT_EQ(event.getDisplayId(), args.displayId); const auto& keyEvent = static_cast<const KeyEvent&>(event); @@ -224,7 +224,7 @@ public: void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) { assertFilterInputEventWasCalledInternal([&](const InputEvent& event) { - ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION); + ASSERT_EQ(event.getType(), InputEventType::MOTION); EXPECT_EQ(event.getDisplayId(), args.displayId); const auto& motionEvent = static_cast<const MotionEvent&>(event); @@ -530,17 +530,21 @@ private: bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override { std::scoped_lock lock(mLock); switch (inputEvent->getType()) { - case AINPUT_EVENT_TYPE_KEY: { + case InputEventType::KEY: { const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent); mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent); break; } - case AINPUT_EVENT_TYPE_MOTION: { + case InputEventType::MOTION: { const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent); mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent); break; } + default: { + ADD_FAILURE() << "Should only filter keys or motions"; + break; + } } return true; } @@ -814,8 +818,7 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) { constexpr nsecs_t eventTime = 20; - NotifyConfigurationChangedArgs args(/*id=*/10, eventTime); - mDispatcher->notifyConfigurationChanged(&args); + mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime}); ASSERT_TRUE(mDispatcher->waitForIdle()); mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime); @@ -824,7 +827,7 @@ TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) { TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) { NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1, /*switchMask=*/2); - mDispatcher->notifySwitch(&args); + mDispatcher->notifySwitch(args); // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener args.policyFlags |= POLICY_FLAG_TRUSTED; @@ -924,7 +927,7 @@ public: ASSERT_EQ(OK, status); } - void consumeEvent(int32_t expectedEventType, int32_t expectedAction, + void consumeEvent(InputEventType expectedEventType, int32_t expectedAction, std::optional<int32_t> expectedDisplayId, std::optional<int32_t> expectedFlags) { InputEvent* event = consume(); @@ -932,15 +935,15 @@ public: ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event."; ASSERT_EQ(expectedEventType, event->getType()) - << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType) - << " event, got " << inputEventTypeToString(event->getType()) << " event"; + << mName.c_str() << " expected " << ftl::enum_string(expectedEventType) + << " event, got " << *event; if (expectedDisplayId.has_value()) { EXPECT_EQ(expectedDisplayId, event->getDisplayId()); } switch (expectedEventType) { - case AINPUT_EVENT_TYPE_KEY: { + case InputEventType::KEY: { const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event); EXPECT_EQ(expectedAction, keyEvent.getAction()); if (expectedFlags.has_value()) { @@ -948,7 +951,7 @@ public: } break; } - case AINPUT_EVENT_TYPE_MOTION: { + case InputEventType::MOTION: { const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event); assertMotionAction(expectedAction, motionEvent.getAction()); @@ -957,21 +960,18 @@ public: } break; } - case AINPUT_EVENT_TYPE_FOCUS: { + case InputEventType::FOCUS: { FAIL() << "Use 'consumeFocusEvent' for FOCUS events"; } - case AINPUT_EVENT_TYPE_CAPTURE: { + case InputEventType::CAPTURE: { FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events"; } - case AINPUT_EVENT_TYPE_TOUCH_MODE: { + case InputEventType::TOUCH_MODE: { FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events"; } - case AINPUT_EVENT_TYPE_DRAG: { + case InputEventType::DRAG: { FAIL() << "Use 'consumeDragEvent' for DRAG events"; } - default: { - FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType; - } } } @@ -983,9 +983,8 @@ public: return nullptr; } - if (event->getType() != AINPUT_EVENT_TYPE_MOTION) { - ADD_FAILURE() << mName << " expected a MotionEvent, got " - << inputEventTypeToString(event->getType()) << " event"; + if (event->getType() != InputEventType::MOTION) { + ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event; return nullptr; } return static_cast<MotionEvent*>(event); @@ -1001,9 +1000,8 @@ public: InputEvent* event = consume(); ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event."; - ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType()) - << "Got " << inputEventTypeToString(event->getType()) - << " event instead of FOCUS event"; + ASSERT_EQ(InputEventType::FOCUS, event->getType()) + << "Instead of FocusEvent, got " << *event; ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId()) << mName.c_str() << ": event displayId should always be NONE."; @@ -1016,9 +1014,8 @@ public: const InputEvent* event = consume(); ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event."; - ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType()) - << "Got " << inputEventTypeToString(event->getType()) - << " event instead of CAPTURE event"; + ASSERT_EQ(InputEventType::CAPTURE, event->getType()) + << "Instead of CaptureEvent, got " << *event; ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId()) << mName.c_str() << ": event displayId should always be NONE."; @@ -1031,9 +1028,7 @@ public: const InputEvent* event = consume(); ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event."; - ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType()) - << "Got " << inputEventTypeToString(event->getType()) - << " event instead of DRAG event"; + ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event; EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId()) << mName.c_str() << ": event displayId should always be NONE."; @@ -1048,9 +1043,8 @@ public: const InputEvent* event = consume(); ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event."; - ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType()) - << "Got " << inputEventTypeToString(event->getType()) - << " event instead of TOUCH_MODE event"; + ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType()) + << "Instead of TouchModeEvent, got " << *event; ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId()) << mName.c_str() << ": event displayId should always be NONE."; @@ -1063,23 +1057,23 @@ public: if (event == nullptr) { return; } - if (event->getType() == AINPUT_EVENT_TYPE_KEY) { + if (event->getType() == InputEventType::KEY) { KeyEvent& keyEvent = static_cast<KeyEvent&>(*event); ADD_FAILURE() << "Received key event " << KeyEvent::actionToString(keyEvent.getAction()); - } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) { + } else if (event->getType() == InputEventType::MOTION) { MotionEvent& motionEvent = static_cast<MotionEvent&>(*event); ADD_FAILURE() << "Received motion event " << MotionEvent::actionToString(motionEvent.getAction()); - } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) { + } else if (event->getType() == InputEventType::FOCUS) { FocusEvent& focusEvent = static_cast<FocusEvent&>(*event); ADD_FAILURE() << "Received focus event, hasFocus = " << (focusEvent.getHasFocus() ? "true" : "false"); - } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) { + } else if (event->getType() == InputEventType::CAPTURE) { const auto& captureEvent = static_cast<CaptureEvent&>(*event); ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = " << (captureEvent.getPointerCaptureEnabled() ? "true" : "false"); - } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) { + } else if (event->getType() == InputEventType::TOUCH_MODE) { const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event); ADD_FAILURE() << "Received touch mode event, inTouchMode = " << (touchModeEvent.isInTouchMode() ? "true" : "false"); @@ -1239,12 +1233,11 @@ public: void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); } void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) { - consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, - expectedFlags); + consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags); } void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) { - consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags); + consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags); } void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, @@ -1266,7 +1259,7 @@ public: void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt, std::optional<int32_t> expectedFlags = std::nullopt) { - consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId, + consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags); } @@ -1275,25 +1268,25 @@ public: int32_t expectedFlags = 0) { int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags); + consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags); } void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) { int32_t action = AMOTION_EVENT_ACTION_POINTER_UP | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags); + consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags); } void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) { - consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId, + consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId, expectedFlags); } void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) { - consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId, + consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId, expectedFlags); } @@ -1301,7 +1294,7 @@ public: int32_t expectedFlags = 0) { InputEvent* event = consume(); ASSERT_NE(nullptr, event); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()); + ASSERT_EQ(InputEventType::MOTION, event->getType()); const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event); EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked()); EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX()); @@ -1326,7 +1319,7 @@ public: ASSERT_THAT(*motionEvent, matcher); } - void consumeEvent(int32_t expectedEventType, int32_t expectedAction, + void consumeEvent(InputEventType expectedEventType, int32_t expectedAction, std::optional<int32_t> expectedDisplayId, std::optional<int32_t> expectedFlags) { ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver"; @@ -1375,9 +1368,8 @@ public: ADD_FAILURE() << "Consume failed : no event"; return nullptr; } - if (event->getType() != AINPUT_EVENT_TYPE_MOTION) { - ADD_FAILURE() << "Instead of motion event, got " - << inputEventTypeToString(event->getType()); + if (event->getType() != InputEventType::MOTION) { + ADD_FAILURE() << "Instead of motion event, got " << *event; return nullptr; } return static_cast<MotionEvent*>(event); @@ -1750,8 +1742,9 @@ static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLA return args; } -static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId, - const std::vector<PointF>& points) { +[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, + int32_t displayId, + const std::vector<PointF>& points) { size_t pointerCount = points.size(); if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) { EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer"; @@ -1953,26 +1946,20 @@ TEST_F(InputDispatcherTest, CancelAfterPointer0Up) { sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); - NotifyMotionArgs args; // First touch pointer down on right window - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .build()); // Second touch pointer down - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100)) + .build()); // First touch pointer lifts. The second one remains down - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN) - - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100)) + .build()); window->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_0_UP)); @@ -2263,54 +2250,48 @@ TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}}); const int32_t touchDeviceId = 4; - NotifyMotionArgs args; // Two pointers down - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .policyFlags(DEFAULT_POLICY_FLAGS) - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .build())); - - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .policyFlags(DEFAULT_POLICY_FLAGS) - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) - .build())); + mDispatcher->notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .policyFlags(DEFAULT_POLICY_FLAGS) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .build()); + + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .policyFlags(DEFAULT_POLICY_FLAGS) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN)); spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN)); window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN)); // Cancel the current gesture. Send the cancel without the default policy flags. - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .policyFlags(0) - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) - .build())); + mDispatcher->notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .policyFlags(0) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)); window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)); // We don't need to reset the device to reproduce the issue, but the reset event typically // follows, so we keep it here to model the actual listener behaviour more closely. - NotifyDeviceResetArgs resetArgs; - resetArgs.id = 1; // arbitrary id - resetArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC); - resetArgs.deviceId = touchDeviceId; - mDispatcher->notifyDeviceReset(&resetArgs); + mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId}); // Start new gesture - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .policyFlags(DEFAULT_POLICY_FLAGS) - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .build())); + mDispatcher->notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .policyFlags(DEFAULT_POLICY_FLAGS) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN)); window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN)); @@ -2460,53 +2441,49 @@ TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) { NotifyMotionArgs args; // Start hovering over the left window - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) + .build()); leftWindow->consumeMotionEvent( AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId))); // Mouse down on left window - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) + .build()); leftWindow->consumeMotionEvent( AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId))); leftWindow->consumeMotionEvent( AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId))); - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .actionButton(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) - .build())); + mDispatcher->notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .actionButton(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) + .build()); leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)); // First touch pointer down on right window - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) + .build()); leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL)); rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); // Second touch pointer down on left window - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100)) + .build()); leftWindow->consumeMotionEvent( AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId))); // This MOVE event is not necessary (doesn't carry any new information), but it's there in the @@ -2540,57 +2517,52 @@ TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) { NotifyMotionArgs args; // First touch pointer down - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) + .build()); // Second touch pointer down - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100)) + .build()); // First touch pointer lifts. The second one remains down - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100)) + .build()); window->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_0_UP)); // Mouse down. The touch should be canceled - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100)) + .build()); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId), WithPointerCount(1u))); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId))); - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .actionButton(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100)) - .build())); + mDispatcher->notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .actionButton(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100)) + .build()); window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)); // Second touch pointer down. - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100)) + .build()); // The pointer_down event should be ignored window->assertNoEvents(); } @@ -2624,11 +2596,10 @@ TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) { // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer // should be canceled and the new gesture should take over. - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100)) + .build()); window->consumeMotionEvent( AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID))); @@ -2830,46 +2801,38 @@ TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}}); - NotifyMotionArgs args; - // Start hovering with stylus - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) - .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)); // Stop hovering - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS) - .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT)); // Stylus touches down - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS) - .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); // Stylus goes up - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS) - .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP)); // Again hover - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) - .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)); // Stop hovering - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS) - .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT)); // No more events @@ -2898,35 +2861,31 @@ TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) { const int32_t mouseDeviceId = 7; const int32_t touchDeviceId = 4; - NotifyMotionArgs args; // Hover a bit with mouse first - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) + .build()); spyWindow->consumeMotionEvent( AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId))); window->consumeMotionEvent( AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId))); // Start touching - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT)); window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT)); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); window->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); window->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); @@ -2934,20 +2893,18 @@ TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) { EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken())); window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL)); - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); // Mouse down - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) + .build()); spyWindow->consumeMotionEvent( AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId))); @@ -2955,32 +2912,30 @@ TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) { AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId))); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId))); - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .actionButton(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) - .build())); + mDispatcher->notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .actionButton(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)); window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)); // Mouse move! - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110)) + .build()); spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); window->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); // Touch move! - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65)) + .build()); // No more events spyWindow->assertNoEvents(); @@ -2998,16 +2953,15 @@ TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) { sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID); mDispatcher->setInputWindows({{DISPLAY_ID, {window}}}); - NotifyMotionArgs args; // Touch down on the empty space - mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}))); + mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}})); mDispatcher->waitForIdle(); window->assertNoEvents(); // Now touch down on the window with another pointer - mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}))); + mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}})); mDispatcher->waitForIdle(); window->consumeMotionDown(); } @@ -3028,16 +2982,15 @@ TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) { mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}}); - NotifyMotionArgs args; // Touch down on the non-touchable window - mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}))); + mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})); mDispatcher->waitForIdle(); window1->assertNoEvents(); window2->assertNoEvents(); // Now touch down on the window with another pointer - mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}))); + mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})); mDispatcher->waitForIdle(); window2->consumeMotionDown(); } @@ -3057,9 +3010,8 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) { mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}}); - NotifyMotionArgs args; // Touch down on the first window - mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}))); + mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})); mDispatcher->waitForIdle(); InputEvent* inputEvent1 = window1->consume(); @@ -3070,7 +3022,7 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) { ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime()); // Now touch down on the window with another pointer - mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}))); + mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})); mDispatcher->waitForIdle(); InputEvent* inputEvent2 = window2->consume(); ASSERT_NE(inputEvent2, nullptr); @@ -3080,14 +3032,12 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) { ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime()); // Now move the pointer on the second window - mDispatcher->notifyMotion( - &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}))); + mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})); mDispatcher->waitForIdle(); window2->consumeMotionEvent(WithDownTime(downTimeForWindow2)); // Now add new touch down on the second window - mDispatcher->notifyMotion( - &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}))); + mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})); mDispatcher->waitForIdle(); window2->consumeMotionEvent(WithDownTime(downTimeForWindow2)); @@ -3096,13 +3046,13 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) { window1->assertNoEvents(); // Now move the pointer on the first window - mDispatcher->notifyMotion(&( - args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}))); + mDispatcher->notifyMotion( + generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}})); mDispatcher->waitForIdle(); window1->consumeMotionEvent(WithDownTime(downTimeForWindow1)); - mDispatcher->notifyMotion(&( - args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}))); + mDispatcher->notifyMotion( + generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})); mDispatcher->waitForIdle(); window1->consumeMotionEvent(WithDownTime(downTimeForWindow1)); } @@ -3206,52 +3156,47 @@ TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) { const int32_t touchDeviceId = 4; const int32_t mouseDeviceId = 6; - NotifyMotionArgs args; // Two pointers down - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .build())); - - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .build()); + + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) + .build()); window->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN)); // Inject a series of mouse events for a mouse click - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400)) + .build()); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId), WithPointerCount(2u))); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId))); - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) - .actionButton(AMOTION_EVENT_BUTTON_PRIMARY) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400)) - .build())); + mDispatcher->notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) + .actionButton(AMOTION_EVENT_BUTTON_PRIMARY) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400)) + .build()); window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)); // Try to send more touch events while the mouse is down. Since it's a continuation of an // already canceled gesture, it should be ignored. - mDispatcher->notifyMotion(&( - args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101)) - .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121)) + .build()); window->assertNoEvents(); } @@ -3515,23 +3460,20 @@ TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) { const int32_t mouseDeviceId = 7; const int32_t touchDeviceId = 4; - NotifyMotionArgs args; // Start hovering with the mouse - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE) - .deviceId(mouseDeviceId) - .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE) + .deviceId(mouseDeviceId) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10)) + .build()); window->consumeMotionEvent( AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId))); // Touch goes down - mDispatcher->notifyMotion( - &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) - .deviceId(touchDeviceId) - .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) - .build())); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .deviceId(touchDeviceId) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .build()); window->consumeMotionEvent( AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId))); @@ -3557,15 +3499,15 @@ TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) { ADISPLAY_ID_DEFAULT, {{50, 50}}); motionArgs.xCursorPosition = 50; motionArgs.yCursorPosition = 50; - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(motionArgs); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)))); // Tap on the window - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {{10, 10}}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {{10, 10}})); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT), WithSource(AINPUT_SOURCE_MOUSE)))); @@ -3574,9 +3516,8 @@ TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) { window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)))); - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {{10, 10}}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {{10, 10}})); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)))); @@ -3668,17 +3609,15 @@ TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) { window->consumeFocusEvent(true); - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT)); // Window should receive key down event. window->consumeKeyDown(ADISPLAY_ID_DEFAULT); // When device reset happens, that key stream should be terminated with FLAG_CANCELED // on the app side. - NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID); - mDispatcher->notifyDeviceReset(&args); - window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT, + mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID}); + window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED); } @@ -3689,18 +3628,15 @@ TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); // Window should receive motion down event. window->consumeMotionDown(ADISPLAY_ID_DEFAULT); // When device reset happens, that motion stream should be terminated with ACTION_CANCEL // on the app side. - NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID); - mDispatcher->notifyDeviceReset(&args); + mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID}); window->consumeMotionEvent( AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT))); } @@ -3716,11 +3652,11 @@ TEST_F(InputDispatcherTest, InterceptKeyByPolicy) { window->consumeFocusEvent(true); - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); + const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); const std::chrono::milliseconds interceptKeyTimeout = 50ms; const nsecs_t injectTime = keyArgs.eventTime; mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(keyArgs); // The dispatching time should be always greater than or equal to intercept key timeout. window->consumeKeyDown(ADISPLAY_ID_DEFAULT); ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >= @@ -3738,11 +3674,9 @@ TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) { window->consumeFocusEvent(true); - NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT); mFakePolicy->setInterceptKeyTimeout(150ms); - mDispatcher->notifyKey(&keyDown); - mDispatcher->notifyKey(&keyUp); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT)); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT)); // Window should receive key event immediately when same key up. window->consumeKeyDown(ADISPLAY_ID_DEFAULT); @@ -3771,10 +3705,9 @@ TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}}); // Tap on first window. - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {PointF{50, 50}}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {PointF{50, 50}})); window->consumeMotionDown(); // The coordinates of the tap in 'outsideWindow' are relative to its top left corner. // Therefore, we should offset them by (100, 100) relative to the screen's top left corner. @@ -3805,18 +3738,17 @@ TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}}); // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE. - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {PointF{-10, -10}}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {PointF{-10, -10}})); window->assertNoEvents(); secondWindow->assertNoEvents(); // The second pointer lands inside `secondWindow`, which should receive a DOWN event. // Now, `window` should get ACTION_OUTSIDE. - motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {PointF{-10, -10}, PointF{105, 105}}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, + {PointF{-10, -10}, PointF{105, 105}})); const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}}; window->consumeMotionEvent( AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers))); @@ -3825,9 +3757,9 @@ TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) { // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture. - motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion( + generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}})); window->assertNoEvents(); secondWindow->consumeMotionMove(); thirdWindow->consumeMotionDown(); @@ -3844,10 +3776,10 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) { window->consumeFocusEvent(true); - NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyDown); - mDispatcher->notifyKey(&keyUp); + const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); + const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT); + mDispatcher->notifyKey(keyDown); + mDispatcher->notifyKey(keyUp); window->consumeKeyDown(ADISPLAY_ID_DEFAULT); window->consumeKeyUp(ADISPLAY_ID_DEFAULT); @@ -3857,8 +3789,8 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) { window->consumeFocusEvent(false); - mDispatcher->notifyKey(&keyDown); - mDispatcher->notifyKey(&keyUp); + mDispatcher->notifyKey(keyDown); + mDispatcher->notifyKey(keyUp); window->assertNoEvents(); } @@ -3966,10 +3898,9 @@ TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) // Send down to the first window. The point is represented in the display space. The point is // selected so that if the hit test was performed with the point and the bounds being in // different coordinate spaces, the event would end up in the incorrect window. - NotifyMotionArgs downMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {PointF{75, 55}}); - mDispatcher->notifyMotion(&downMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {PointF{75, 55}})); firstWindow->consumeMotionDown(); secondWindow->assertNoEvents(); @@ -4020,10 +3951,9 @@ TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinate auto [firstWindow, secondWindow] = setupScaledDisplayScenario(); // Send down to the second window. - NotifyMotionArgs downMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {PointF{150, 220}}); - mDispatcher->notifyMotion(&downMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {PointF{150, 220}})); firstWindow->assertNoEvents(); const MotionEvent* event = secondWindow->consumeMotion(); @@ -4078,14 +4008,14 @@ TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) for (const auto pointInsideWindow : insidePoints) { const vec2 p = displayTransform.inverse().transform(pointInsideWindow); const PointF pointInDisplaySpace{p.x, p.y}; - const auto down = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {pointInDisplaySpace}); - mDispatcher->notifyMotion(&down); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {pointInDisplaySpace})); window->consumeMotionDown(); - const auto up = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {pointInDisplaySpace}); - mDispatcher->notifyMotion(&up); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {pointInDisplaySpace})); window->consumeMotionUp(); } @@ -4095,13 +4025,13 @@ TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) for (const auto pointOutsideWindow : outsidePoints) { const vec2 p = displayTransform.inverse().transform(pointOutsideWindow); const PointF pointInDisplaySpace{p.x, p.y}; - const auto down = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {pointInDisplaySpace}); - mDispatcher->notifyMotion(&down); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {pointInDisplaySpace})); - const auto up = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {pointInDisplaySpace}); - mDispatcher->notifyMotion(&up); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {pointInDisplaySpace})); } window->assertNoEvents(); } @@ -4139,10 +4069,8 @@ TEST_P(TransferTouchFixture, TransferTouch_OnePointer) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}}); // Send down to the first window - NotifyMotionArgs downMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&downMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); // Only the first window should get the down event firstWindow->consumeMotionDown(); @@ -4159,10 +4087,8 @@ TEST_P(TransferTouchFixture, TransferTouch_OnePointer) { wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); // Send up event to the second window - NotifyMotionArgs upMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&upMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT)); // The first window gets no events and the second gets up firstWindow->assertNoEvents(); secondWindow->consumeMotionUp(); @@ -4198,10 +4124,8 @@ TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}}); // Send down to the first window - NotifyMotionArgs downMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&downMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); // Only the first window and spy should get the down event spyWindow->consumeMotionDown(); firstWindow->consumeMotionDown(); @@ -4216,10 +4140,8 @@ TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) { secondWindow->consumeMotionDown(); // Send up event to the second window - NotifyMotionArgs upMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&upMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT)); // The first window gets no events and the second+spy get up firstWindow->assertNoEvents(); spyWindow->consumeMotionUp(); @@ -4245,19 +4167,16 @@ TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}}); // Send down to the first window - NotifyMotionArgs downMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchPoint}); - mDispatcher->notifyMotion(&downMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {touchPoint})); // Only the first window should get the down event firstWindow->consumeMotionDown(); secondWindow->assertNoEvents(); // Send pointer down to the first window - NotifyMotionArgs pointerDownMotionArgs = - generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {touchPoint, touchPoint}); - mDispatcher->notifyMotion(&pointerDownMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint})); // Only the first window should get the pointer down event firstWindow->consumeMotionPointerDown(1); secondWindow->assertNoEvents(); @@ -4272,19 +4191,15 @@ TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) { secondWindow->consumeMotionPointerDown(1); // Send pointer up to the second window - NotifyMotionArgs pointerUpMotionArgs = - generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {touchPoint, touchPoint}); - mDispatcher->notifyMotion(&pointerUpMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint})); // The first window gets nothing and the second gets pointer up firstWindow->assertNoEvents(); secondWindow->consumeMotionPointerUp(1); // Send up event to the second window - NotifyMotionArgs upMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&upMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT)); // The first window gets nothing and the second gets up firstWindow->assertNoEvents(); secondWindow->consumeMotionUp(); @@ -4315,10 +4230,8 @@ TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) { {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}}); // Send down to the first window - NotifyMotionArgs downMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&downMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); // Only the first window should get the down event firstWindow->consumeMotionDown(); @@ -4338,10 +4251,8 @@ TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) { wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); // Send up event to the second window - NotifyMotionArgs upMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&upMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT)); // The first window gets no events and the second gets up firstWindow->assertNoEvents(); secondWindow->consumeMotionUp(); @@ -4385,19 +4296,17 @@ TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) { PointF pointInSecond = {300, 600}; // Send down to the first window - NotifyMotionArgs firstDownMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {pointInFirst}); - mDispatcher->notifyMotion(&firstDownMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {pointInFirst})); // Only the first window should get the down event firstWindow->consumeMotionDown(); secondWindow->assertNoEvents(); // Send down to the second window - NotifyMotionArgs secondDownMotionArgs = - generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {pointInFirst, pointInSecond}); - mDispatcher->notifyMotion(&secondDownMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, + {pointInFirst, pointInSecond})); // The first window gets a move and the second a down firstWindow->consumeMotionMove(); secondWindow->consumeMotionDown(); @@ -4409,19 +4318,16 @@ TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) { secondWindow->consumeMotionPointerDown(1); // Send pointer up to the second window - NotifyMotionArgs pointerUpMotionArgs = - generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {pointInFirst, pointInSecond}); - mDispatcher->notifyMotion(&pointerUpMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, + {pointInFirst, pointInSecond})); // The first window gets nothing and the second gets pointer up firstWindow->assertNoEvents(); secondWindow->consumeMotionPointerUp(1); // Send up event to the second window - NotifyMotionArgs upMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&upMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT)); // The first window gets nothing and the second gets up firstWindow->assertNoEvents(); secondWindow->consumeMotionUp(); @@ -4451,19 +4357,17 @@ TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) { PointF pointInSecond = {300, 600}; // Send down to the first window - NotifyMotionArgs firstDownMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {pointInFirst}); - mDispatcher->notifyMotion(&firstDownMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {pointInFirst})); // Only the first window should get the down event firstWindow->consumeMotionDown(); secondWindow->assertNoEvents(); // Send down to the second window - NotifyMotionArgs secondDownMotionArgs = - generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {pointInFirst, pointInSecond}); - mDispatcher->notifyMotion(&secondDownMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, + {pointInFirst, pointInSecond})); // The first window gets a move and the second a down firstWindow->consumeMotionMove(); secondWindow->consumeMotionDown(); @@ -4478,19 +4382,16 @@ TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) { // The rest of the dispatch should proceed as normal // Send pointer up to the second window - NotifyMotionArgs pointerUpMotionArgs = - generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {pointInFirst, pointInSecond}); - mDispatcher->notifyMotion(&pointerUpMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, + {pointInFirst, pointInSecond})); // The first window gets MOVE and the second gets pointer up firstWindow->consumeMotionMove(); secondWindow->consumeMotionUp(); // Send up event to the first window - NotifyMotionArgs upMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&upMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT)); // The first window gets nothing and the second gets up firstWindow->consumeMotionUp(); secondWindow->assertNoEvents(); @@ -4625,8 +4526,7 @@ TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) { window->consumeFocusEvent(true); - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT)); // Window should receive key down event. window->consumeKeyDown(ADISPLAY_ID_DEFAULT); @@ -4639,8 +4539,7 @@ TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT)); mDispatcher->waitForIdle(); window->assertNoEvents(); @@ -4655,13 +4554,10 @@ TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) { mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); // Send key - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT)); // Send motion - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); // Window should receive only the motion event window->consumeMotionDown(ADISPLAY_ID_DEFAULT); @@ -4688,19 +4584,17 @@ TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) { PointF pointInSecond = {300, 600}; // Send down to the first window - NotifyMotionArgs firstDownMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {pointInFirst}); - mDispatcher->notifyMotion(&firstDownMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {pointInFirst})); // Only the first window should get the down event firstWindow->consumeMotionDown(); secondWindow->assertNoEvents(); // Send down to the second window - NotifyMotionArgs secondDownMotionArgs = - generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {pointInFirst, pointInSecond}); - mDispatcher->notifyMotion(&secondDownMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, + {pointInFirst, pointInSecond})); // The first window gets a move and the second a down firstWindow->consumeMotionMove(); secondWindow->consumeMotionDown(); @@ -4710,16 +4604,14 @@ TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) { generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond}); pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED; - mDispatcher->notifyMotion(&pointerUpMotionArgs); + mDispatcher->notifyMotion(pointerUpMotionArgs); // The first window gets move and the second gets cancel. firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED); secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED); // Send up event. - NotifyMotionArgs upMotionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&upMotionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT)); // The first window gets up and the second gets nothing. firstWindow->consumeMotionUp(); secondWindow->assertNoEvents(); @@ -4752,8 +4644,8 @@ public: sp<IBinder> getToken() { return mInputReceiver->getToken(); } void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) { - mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, - expectedDisplayId, expectedFlags); + mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, + expectedFlags); } std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); } @@ -4761,17 +4653,17 @@ public: void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); } void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) { - mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, + mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags); } void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) { - mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, + mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId, expectedFlags); } void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) { - mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, + mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId, expectedFlags); } @@ -4785,7 +4677,7 @@ public: void consumeMotionPointerDown(int32_t pointerIdx) { int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT, + mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0); } @@ -4795,8 +4687,8 @@ public: ADD_FAILURE() << "No event was produced"; return nullptr; } - if (event->getType() != AINPUT_EVENT_TYPE_MOTION) { - ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion"; + if (event->getType() != InputEventType::MOTION) { + ADD_FAILURE() << "Expected MotionEvent, got " << *event; return nullptr; } return static_cast<MotionEvent*>(event); @@ -4941,7 +4833,7 @@ TEST_F(InputDispatcherTest, TestMoveEvent) { generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(motionArgs); // Window should receive motion down event. window->consumeMotionDown(ADISPLAY_ID_DEFAULT); @@ -4951,8 +4843,8 @@ TEST_F(InputDispatcherTest, TestMoveEvent) { motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, motionArgs.pointerCoords[0].getX() - 10); - mDispatcher->notifyMotion(&motionArgs); - window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT, + mDispatcher->notifyMotion(motionArgs); + window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0); } @@ -5020,8 +4912,8 @@ TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) { window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true); - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN); - mDispatcher->notifyKey(&keyArgs); + const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN); + mDispatcher->notifyKey(keyArgs); InputEvent* event = window->consume(); ASSERT_NE(event, nullptr); @@ -5062,10 +4954,10 @@ TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) { mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo}); - NotifyMotionArgs motionArgs = + const NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(motionArgs); InputEvent* event = window->consume(); ASSERT_NE(event, nullptr); @@ -5362,17 +5254,17 @@ TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) { {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}}); // Use notifyMotion instead of injecting to avoid dealing with injection permissions - NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {{50, 50}}); - mDispatcher->notifyMotion(&args); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {{50, 50}})); slipperyExitWindow->consumeMotionDown(); slipperyExitWindow->setFrame(Rect(70, 70, 100, 100)); mDispatcher->setInputWindows( {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}}); - args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {{51, 51}}); - mDispatcher->notifyMotion(&args); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {{51, 51}})); slipperyExitWindow->consumeMotionCancel(); @@ -5412,7 +5304,7 @@ protected: NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); keyArgs.deviceId = deviceId; keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(keyArgs); // Window should receive key down event. mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); @@ -5423,8 +5315,7 @@ protected: InputEvent* repeatEvent = mWindow->consume(); ASSERT_NE(nullptr, repeatEvent); - uint32_t eventType = repeatEvent->getType(); - ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType); + ASSERT_EQ(InputEventType::KEY, repeatEvent->getType()); KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent); uint32_t eventAction = repeatKeyEvent->getAction(); @@ -5436,10 +5327,10 @@ protected: NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT); keyArgs.deviceId = deviceId; keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(keyArgs); // Window should receive key down event. - mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT, + mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0); } }; @@ -5499,8 +5390,7 @@ TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingK TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) { sendAndConsumeKeyDown(DEVICE_ID); expectKeyRepeatOnce(/*repeatCount=*/1); - NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID); - mDispatcher->notifyDeviceReset(&args); + mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID}); mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS); mWindow->assertNoEvents(); @@ -5612,7 +5502,7 @@ TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}}); // Old focus should receive a cancel event. - windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE, + windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED); // Test inject a key down, should timeout because of no target window. @@ -5752,10 +5642,10 @@ protected: motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(motionArgs); motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(motionArgs); ASSERT_TRUE(mDispatcher->waitForIdle()); if (expectToBeFiltered) { const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue()); @@ -5769,9 +5659,9 @@ protected: NotifyKeyArgs keyArgs; keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(keyArgs); keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(keyArgs); ASSERT_TRUE(mDispatcher->waitForIdle()); if (expectToBeFiltered) { @@ -5883,7 +5773,7 @@ protected: InputEvent* received = mWindow->consume(); ASSERT_NE(nullptr, received); ASSERT_EQ(resolvedDeviceId, received->getDeviceId()); - ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY); + ASSERT_EQ(received->getType(), InputEventType::KEY); KeyEvent& keyEvent = static_cast<KeyEvent&>(*received); ASSERT_EQ(flags, keyEvent.getFlags()); } @@ -5918,7 +5808,7 @@ protected: InputEvent* received = mWindow->consume(); ASSERT_NE(nullptr, received); ASSERT_EQ(resolvedDeviceId, received->getDeviceId()); - ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION); + ASSERT_EQ(received->getType(), InputEventType::MOTION); MotionEvent& motionEvent = static_cast<MotionEvent&>(*received); ASSERT_EQ(flags, motionEvent.getFlags()); } @@ -6099,9 +5989,8 @@ protected: ASSERT_NE(nullptr, event) << name.c_str() << ": consumer should have returned non-NULL event."; - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()) - << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION) - << " event, got " << inputEventTypeToString(event->getType()) << " event"; + ASSERT_EQ(InputEventType::MOTION, event->getType()) + << name.c_str() << ": expected MotionEvent, got " << *event; const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event); assertMotionAction(expectedAction, motionEvent.getAction()); @@ -6122,9 +6011,8 @@ protected: void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints, std::vector<PointF> expectedPoints) { - NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, touchedPoints)); // Always consume from window1 since it's the window that has the InputReceiver consumeMotionEvent(mWindow1, action, expectedPoints); @@ -6798,7 +6686,7 @@ TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) { FOCUSED_WINDOW_LOCATION)) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mFocusedWindow->consumeMotionDown(); - mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, + mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, ADISPLAY_ID_DEFAULT, /*flags=*/0); // We consumed all events, so no ANR ASSERT_TRUE(mDispatcher->waitForIdle()); @@ -6872,7 +6760,7 @@ TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout // At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events. TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) { tapOnFocusedWindow(); - mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, + mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, ADISPLAY_ID_DEFAULT, /*flags=*/0); // Receive the events, but don't respond std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN @@ -6997,17 +6885,16 @@ TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) { // The other window should not be affected by that. TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) { // Touch Window 1 - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION}); - mDispatcher->notifyMotion(&motionArgs); - mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {FOCUSED_WINDOW_LOCATION})); + mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, ADISPLAY_ID_DEFAULT, /*flags=*/0); // Touch Window 2 - motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, - {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion( + generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION})); const std::chrono::duration timeout = mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); @@ -7022,7 +6909,7 @@ TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) { ASSERT_TRUE(moveOrCancelSequenceNum); mFocusedWindow->finishEvent(*moveOrCancelSequenceNum); ASSERT_NE(nullptr, event); - ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION); + ASSERT_EQ(event->getType(), InputEventType::MOTION); MotionEvent& motionEvent = static_cast<MotionEvent&>(*event); if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) { mFocusedWindow->consumeMotionCancel(); @@ -7079,10 +6966,9 @@ TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_ std::this_thread::sleep_for(10ms); // Touch unfocused window. This should force the pending key to get dropped. - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {UNFOCUSED_WINDOW_LOCATION})); // We do not consume the motion right away, because that would require dispatcher to first // process (== drop) the key event, and by that time, ANR will be raised. @@ -7137,10 +7023,9 @@ protected: TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) { PointF touchedPoint = {10, 10}; - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchedPoint}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {touchedPoint})); mNoInputWindow->assertNoEvents(); // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have @@ -7165,10 +7050,9 @@ TEST_F(InputDispatcherMultiWindowOcclusionTests, PointF touchedPoint = {10, 10}; - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchedPoint}); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {touchedPoint})); mNoInputWindow->assertNoEvents(); mBottomWindow->assertNoEvents(); @@ -7341,8 +7225,7 @@ protected: } void notifyPointerCaptureChanged(const PointerCaptureRequest& request) { - const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request); - mDispatcher->notifyPointerCaptureChanged(&args); + mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request)); } PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window, @@ -7518,10 +7401,9 @@ protected: } void touch(const std::vector<PointF>& points = {PointF{100, 200}}) { - NotifyMotionArgs args = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, points); - mDispatcher->notifyMotion(&args); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + points)); } }; @@ -8234,7 +8116,7 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { .displayId(SECOND_DISPLAY_ID) .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100)) .build())); - windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, + windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, SECOND_DISPLAY_ID, /*expectedFlag=*/0); // Update window again. mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); @@ -8331,27 +8213,22 @@ TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true); // With the flag set, window should not get any input - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT)); window->assertNoEvents(); - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); window->assertNoEvents(); // With the flag cleared, the window should get input window->setDropInput(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); - keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT)); window->consumeKeyUp(ADISPLAY_ID_DEFAULT); - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); window->consumeMotionDown(ADISPLAY_ID_DEFAULT); window->assertNoEvents(); } @@ -8377,27 +8254,22 @@ TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) { window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true); // With the flag set, window should not get any input - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT)); window->assertNoEvents(); - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); window->assertNoEvents(); // With the flag cleared, the window should get input window->setDropInputIfObscured(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}}); - keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT)); window->consumeKeyUp(ADISPLAY_ID_DEFAULT); - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED); window->assertNoEvents(); } @@ -8423,26 +8295,21 @@ TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) { window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true); // With the flag set, window should not get any input - NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT)); window->assertNoEvents(); - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); window->assertNoEvents(); // When the window is no longer obscured because it went on top, it should get input mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}}); - keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT); - mDispatcher->notifyKey(&keyArgs); + mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT)); window->consumeKeyUp(ADISPLAY_ID_DEFAULT); - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT); - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)); window->consumeMotionDown(ADISPLAY_ID_DEFAULT); window->assertNoEvents(); } @@ -9176,10 +9043,9 @@ public: } void sendFingerEvent(int32_t action) { - NotifyMotionArgs motionArgs = + mDispatcher->notifyMotion( generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, - ADISPLAY_ID_DEFAULT, {PointF{20, 20}}); - mDispatcher->notifyMotion(&motionArgs); + ADISPLAY_ID_DEFAULT, {PointF{20, 20}})); } void sendStylusEvent(int32_t action) { @@ -9187,7 +9053,7 @@ public: generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT, {PointF{30, 40}}); motionArgs.pointerProperties[0].toolType = ToolType::STYLUS; - mDispatcher->notifyMotion(&motionArgs); + mDispatcher->notifyMotion(motionArgs); } }; diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp index ae300066d2..ad48a79731 100644 --- a/services/inputflinger/tests/InputMapperTest.cpp +++ b/services/inputflinger/tests/InputMapperTest.cpp @@ -50,12 +50,12 @@ void InputMapperTest::addConfigurationProperty(const char* key, const char* valu mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, key, value); } -std::list<NotifyArgs> InputMapperTest::configureDevice(uint32_t changes) { - if (!changes || - (changes & - (InputReaderConfiguration::CHANGE_DISPLAY_INFO | - InputReaderConfiguration::CHANGE_POINTER_CAPTURE | - InputReaderConfiguration::CHANGE_DEVICE_TYPE))) { +std::list<NotifyArgs> InputMapperTest::configureDevice(ConfigurationChanges changes) { + using namespace ftl::flag_operators; + if (!changes.any() || + (changes.any(InputReaderConfiguration::Change::DISPLAY_INFO | + InputReaderConfiguration::Change::POINTER_CAPTURE | + InputReaderConfiguration::Change::DEVICE_TYPE))) { mReader->requestRefreshConfiguration(changes); mReader->loopOnce(); } @@ -94,7 +94,7 @@ void InputMapperTest::setDisplayInfoAndReconfigure(int32_t displayId, int32_t wi ViewportType viewportType) { mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /* isActive= */ true, uniqueId, physicalPort, viewportType); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); } void InputMapperTest::clearViewports() { diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h index 63ca44c402..d9690349fb 100644 --- a/services/inputflinger/tests/InputMapperTest.h +++ b/services/inputflinger/tests/InputMapperTest.h @@ -54,14 +54,15 @@ protected: void TearDown() override; void addConfigurationProperty(const char* key, const char* value); - std::list<NotifyArgs> configureDevice(uint32_t changes); + std::list<NotifyArgs> configureDevice(ConfigurationChanges changes); std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name, const std::string& location, int32_t eventHubId, ftl::Flags<InputDeviceClass> classes, int bus = 0); template <class T, typename... Args> T& addMapperAndConfigure(Args... args) { - T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...); - configureDevice(0); + T& mapper = + mDevice->addMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), args...); + configureDevice(/*changes=*/{}); std::list<NotifyArgs> resetArgList = mDevice->reset(ARBITRARY_TIME); resetArgList += mapper.reset(ARBITRARY_TIME); // Loop the reader to flush the input listener queue. diff --git a/services/inputflinger/tests/InputProcessor_test.cpp b/services/inputflinger/tests/InputProcessor_test.cpp index 0ffdef9daa..3b7cbfac5c 100644 --- a/services/inputflinger/tests/InputProcessor_test.cpp +++ b/services/inputflinger/tests/InputProcessor_test.cpp @@ -72,7 +72,7 @@ TEST_F(InputProcessorTest, SendToNextStage_NotifyConfigurationChangedArgs) { // Create a basic configuration change and send to processor NotifyConfigurationChangedArgs args(/*sequenceNum=*/1, /*eventTime=*/2); - mProcessor->notifyConfigurationChanged(&args); + mProcessor->notifyConfigurationChanged(args); NotifyConfigurationChangedArgs outArgs; ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyConfigurationChangedWasCalled(&outArgs)); ASSERT_EQ(args, outArgs); @@ -85,10 +85,8 @@ TEST_F(InputProcessorTest, SendToNextStage_NotifyKeyArgs) { AKEY_EVENT_ACTION_DOWN, /*flags=*/4, AKEYCODE_HOME, /*scanCode=*/5, AMETA_NONE, /*downTime=*/6); - mProcessor->notifyKey(&args); - NotifyKeyArgs outArgs; - ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(&outArgs)); - ASSERT_EQ(args, outArgs); + mProcessor->notifyKey(args); + ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(testing::Eq(args))); } /** @@ -97,10 +95,8 @@ TEST_F(InputProcessorTest, SendToNextStage_NotifyKeyArgs) { */ TEST_F(InputProcessorTest, SendToNextStage_NotifyMotionArgs) { NotifyMotionArgs motionArgs = generateBasicMotionArgs(); - mProcessor->notifyMotion(&motionArgs); - NotifyMotionArgs args; - ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(&args)); - ASSERT_EQ(motionArgs, args); + mProcessor->notifyMotion(motionArgs); + ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(testing::Eq(motionArgs))); } /** @@ -111,7 +107,7 @@ TEST_F(InputProcessorTest, SendToNextStage_NotifySwitchArgs) { NotifySwitchArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*policyFlags=*/3, /*switchValues=*/4, /*switchMask=*/5); - mProcessor->notifySwitch(&args); + mProcessor->notifySwitch(args); NotifySwitchArgs outArgs; ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifySwitchWasCalled(&outArgs)); ASSERT_EQ(args, outArgs); @@ -124,7 +120,7 @@ TEST_F(InputProcessorTest, SendToNextStage_NotifySwitchArgs) { TEST_F(InputProcessorTest, SendToNextStage_NotifyDeviceResetArgs) { NotifyDeviceResetArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*deviceId=*/3); - mProcessor->notifyDeviceReset(&args); + mProcessor->notifyDeviceReset(args); NotifyDeviceResetArgs outArgs; ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyDeviceResetWasCalled(&outArgs)); ASSERT_EQ(args, outArgs); diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index fb082da8e1..0b505045bd 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -171,8 +171,9 @@ class FakeInputMapper : public InputMapper { std::optional<DisplayViewport> mViewport; public: - FakeInputMapper(InputDeviceContext& deviceContext, uint32_t sources) - : InputMapper(deviceContext), + FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig, + uint32_t sources) + : InputMapper(deviceContext, readerConfig), mSources(sources), mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE), mMetaState(0), @@ -263,15 +264,15 @@ private: } } - std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration* config, - uint32_t changes) override { + std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config, + ConfigurationChanges changes) override { std::scoped_lock<std::mutex> lock(mLock); mConfigureWasCalled = true; // Find the associated viewport if exist. const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort(); - if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { - mViewport = config->getDisplayViewportByPort(*displayPort); + if (displayPort && changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) { + mViewport = config.getDisplayViewportByPort(*displayPort); } mStateChangedCondition.notify_all(); @@ -603,17 +604,18 @@ protected: mReader->loopOnce(); mReader->loopOnce(); ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyInputDevicesChangedWasCalled()); ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty()); } void disableDevice(int32_t deviceId) { mFakePolicy->addDisabledDevice(deviceId); - mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_ENABLED_STATE); + mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE); } void enableDevice(int32_t deviceId) { mFakePolicy->removeDisabledDevice(deviceId); - mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_ENABLED_STATE); + mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE); } FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId, @@ -622,7 +624,9 @@ protected: uint32_t sources, const PropertyMap* configuration) { std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name); - FakeInputMapper& mapper = device->addMapper<FakeInputMapper>(eventHubId, sources); + FakeInputMapper& mapper = + device->addMapper<FakeInputMapper>(eventHubId, + mFakePolicy->getReaderConfiguration(), sources); mReader->pushNextDevice(device); addDevice(eventHubId, name, classes, configuration); return mapper; @@ -674,8 +678,10 @@ TEST_F(InputReaderTest, GetMergedInputDevices) { // Add two subdevices to device std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! - device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD); - device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); // Push same device instance for next device to be added, so they'll have same identifier. mReader->pushNextDevice(device); @@ -695,8 +701,10 @@ TEST_F(InputReaderTest, GetMergedInputDevicesEnabled) { // Add two subdevices to device std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! - device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD); - device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); // Push same device instance for next device to be added, so they'll have same identifier. mReader->pushNextDevice(device); @@ -721,7 +729,8 @@ TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { constexpr int32_t eventHubId = 1; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! - device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); mReader->pushNextDevice(device); ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr)); @@ -967,7 +976,8 @@ TEST_F(InputReaderTest, DeviceReset_RandomId) { constexpr int32_t eventHubId = 1; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! - device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); mReader->pushNextDevice(device); ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr)); @@ -1000,7 +1010,8 @@ TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) { constexpr int32_t eventHubId = 1; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! - device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); mReader->pushNextDevice(device); ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr)); @@ -1016,7 +1027,8 @@ TEST_F(InputReaderTest, Device_CanDispatchToDisplay) { const char* DEVICE_LOCATION = "USB1"; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); FakeInputMapper& mapper = - device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_TOUCHSCREEN); + device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_TOUCHSCREEN); mReader->pushNextDevice(device); const uint8_t hdmi1 = 1; @@ -1031,7 +1043,7 @@ TEST_F(InputReaderTest, Device_CanDispatchToDisplay) { mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1, ViewportType::EXTERNAL); - mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO); mReader->loopOnce(); // Add the device, and make sure all of the callbacks are triggered. @@ -1059,8 +1071,10 @@ TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) { constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1}; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake"); // Must add at least one mapper or the device will be ignored! - device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD); - device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); mReader->pushNextDevice(device); mReader->pushNextDevice(device); ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr)); @@ -1101,9 +1115,13 @@ TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) { // Add two subdevices to device std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake"); FakeInputMapper& mapperDevice1 = - device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubIds[0], + mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); FakeInputMapper& mapperDevice2 = - device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeInputMapper>(eventHubIds[1], + mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); mReader->pushNextDevice(device); mReader->pushNextDevice(device); ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr)); @@ -1124,29 +1142,30 @@ TEST_F(InputReaderTest, ChangingPointerCaptureNotifiesInputListener) { NotifyPointerCaptureChangedArgs args; auto request = mFakePolicy->setPointerCapture(true); - mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); + mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE); mReader->loopOnce(); mFakeListener->assertNotifyCaptureWasCalled(&args); 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->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE); mReader->loopOnce(); mFakeListener->assertNotifyCaptureWasCalled(&args); ASSERT_FALSE(args.request.enable) << "Pointer Capture should be disabled."; // Verify that the Pointer Capture state is not updated when the configuration value // does not change. - mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); + mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE); mReader->loopOnce(); mFakeListener->assertNotifyCaptureWasNotCalled(); } class FakeVibratorInputMapper : public FakeInputMapper { public: - FakeVibratorInputMapper(InputDeviceContext& deviceContext, uint32_t sources) - : FakeInputMapper(deviceContext, sources) {} + FakeVibratorInputMapper(InputDeviceContext& deviceContext, + const InputReaderConfiguration& readerConfig, uint32_t sources) + : FakeInputMapper(deviceContext, readerConfig, sources) {} std::vector<int32_t> getVibratorIds() override { return getDeviceContext().getVibratorIds(); } }; @@ -1159,7 +1178,9 @@ TEST_F(InputReaderTest, VibratorGetVibratorIds) { const char* DEVICE_LOCATION = "BLUETOOTH"; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); FakeVibratorInputMapper& mapper = - device->addMapper<FakeVibratorInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD); + device->addMapper<FakeVibratorInputMapper>(eventHubId, + mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); mReader->pushNextDevice(device); ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr)); @@ -1324,6 +1345,7 @@ protected: // to the test device will show up in mReader. We wait for those input devices to // show up before beginning the tests. ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged()); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled()); ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled()); } @@ -1505,7 +1527,7 @@ protected: ViewportType viewportType) { mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true, uniqueId, physicalPort, viewportType); - mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO); } void assertReceivedMotion(int32_t action, const std::vector<Point>& points) { @@ -2048,7 +2070,7 @@ TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsWithinTouchGesture TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonMotionEventsDisabled) { TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false); TestFixture::mReader->requestRefreshConfiguration( - InputReaderConfiguration::CHANGE_STYLUS_BUTTON_REPORTING); + InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING); const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint(); const auto touchscreenId = TestFixture::mTouchscreenInfo.getId(); @@ -2319,7 +2341,7 @@ TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) { TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) { // Configuration. InputReaderConfiguration config; - std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, &config, 0); + std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{}); // Reset. unused += mDevice->reset(ARBITRARY_TIME); @@ -2362,7 +2384,8 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value"); FakeInputMapper& mapper1 = - mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD); + mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC); mapper1.setMetaState(AMETA_ALT_ON); mapper1.addSupportedKeyCode(AKEYCODE_A); @@ -2374,11 +2397,12 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe mapper1.setSwitchState(4, AKEY_STATE_DOWN); FakeInputMapper& mapper2 = - mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_TOUCHSCREEN); + mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_TOUCHSCREEN); mapper2.setMetaState(AMETA_SHIFT_ON); InputReaderConfiguration config; - std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, &config, 0); + std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{}); std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key"); ASSERT_TRUE(propertyValue.has_value()) @@ -2455,11 +2479,13 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe // 1. Device is disabled if the viewport corresponding to the associated display is not found // 2. Device is disabled when setEnabled API is called TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) { - mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_TOUCHSCREEN); + mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_TOUCHSCREEN); // First Configuration. std::list<NotifyArgs> unused = - mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0); + mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), + /*changes=*/{}); // Device should be enabled by default. ASSERT_TRUE(mDevice->isEnabled()); @@ -2470,7 +2496,7 @@ TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) { mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi); unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); // Device should be disabled because it is associated with a specific display via // input port <-> display port association, but the corresponding display is not found ASSERT_FALSE(mDevice->isEnabled()); @@ -2480,34 +2506,36 @@ TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) { ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi, ViewportType::INTERNAL); unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); ASSERT_TRUE(mDevice->isEnabled()); // Device should be disabled after set disable. mFakePolicy->addDisabledDevice(mDevice->getId()); unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_ENABLED_STATE); + InputReaderConfiguration::Change::ENABLED_STATE); ASSERT_FALSE(mDevice->isEnabled()); // Device should still be disabled even found the associated display. unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); ASSERT_FALSE(mDevice->isEnabled()); } TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) { // Device should be enabled by default. mFakePolicy->clearViewports(); - mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD); + mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); std::list<NotifyArgs> unused = - mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0); + mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), + /*changes=*/{}); ASSERT_TRUE(mDevice->isEnabled()); // Device should be disabled because it is associated with a specific display, but the // corresponding display is not found. mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID); unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); ASSERT_FALSE(mDevice->isEnabled()); // Device should be enabled when a display is found. @@ -2515,33 +2543,35 @@ TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) { ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID, NO_PORT, ViewportType::INTERNAL); unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); ASSERT_TRUE(mDevice->isEnabled()); // Device should be disabled after set disable. mFakePolicy->addDisabledDevice(mDevice->getId()); unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_ENABLED_STATE); + InputReaderConfiguration::Change::ENABLED_STATE); ASSERT_FALSE(mDevice->isEnabled()); // Device should still be disabled even found the associated display. unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); ASSERT_FALSE(mDevice->isEnabled()); } TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) { mFakePolicy->clearViewports(); - mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD); + mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD); std::list<NotifyArgs> unused = - mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0); + mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), + /*changes=*/{}); mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID); mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID, NO_PORT, ViewportType::INTERNAL); unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueId()); } @@ -2554,7 +2584,7 @@ TEST_F(InputDeviceTest, DumpDoesNotCrash) { mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY); InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{}); - device.addEventHubDevice(TEST_EVENTHUB_ID, /*populateMappers=*/true); + device.addEventHubDevice(TEST_EVENTHUB_ID, mFakePolicy->getReaderConfiguration()); device.removeEventHubDevice(TEST_EVENTHUB_ID); std::string dumpStr, eventHubDevStr; device.dump(dumpStr, eventHubDevStr); @@ -3390,11 +3420,13 @@ TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) { AINPUT_KEYBOARD_TYPE_ALPHABETIC); KeyboardInputMapper& mapper2 = - device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD, + device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, + mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); std::list<NotifyArgs> unused = device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - /*changes=*/0); + /*changes=*/{}); unused += device2->reset(ARBITRARY_TIME); // Prepared displays and associated info. @@ -3407,7 +3439,7 @@ TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) { // No associated display viewport found, should disable the device. unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); ASSERT_FALSE(device2->isEnabled()); // Prepare second display. @@ -3418,7 +3450,7 @@ TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) { SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL); // Default device will reconfigure above, need additional reconfiguration for another device. unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO); + InputReaderConfiguration::Change::DISPLAY_INFO); // Device should be enabled after the associated display is found. ASSERT_TRUE(mDevice->isEnabled()); @@ -3500,11 +3532,13 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) { mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0); KeyboardInputMapper& mapper2 = - device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD, + device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, + mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); std::list<NotifyArgs> unused = device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - /*changes=*/0); + /*changes=*/{}); unused += device2->reset(ARBITRARY_TIME); ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL)); @@ -3561,11 +3595,13 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) { mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0); KeyboardInputMapper& mapper2 = - device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD, + device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, + mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); std::list<NotifyArgs> unused = device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - /*changes=*/0); + /*changes=*/{}); unused += device2->reset(ARBITRARY_TIME); // Initial metastate is AMETA_NONE. @@ -3634,7 +3670,7 @@ TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) { // Disable device, it should synthesize cancellation events for down events. mFakePolicy->addDisabledDevice(DEVICE_ID); - configureDevice(InputReaderConfiguration::CHANGE_ENABLED_STATE); + configureDevice(InputReaderConfiguration::Change::ENABLED_STATE); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); @@ -3644,15 +3680,17 @@ TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) { } TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) { - mDevice->addMapper<KeyboardInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD, + mDevice->addMapper<KeyboardInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), + AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); std::list<NotifyArgs> unused = - mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0); + mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), + /*changes=*/{}); mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO); unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUT_ASSOCIATION); + InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION); InputDeviceInfo deviceInfo = mDevice->getDeviceInfo(); ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag, @@ -3669,7 +3707,7 @@ TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) { addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); InputReaderConfiguration config; - std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, &config, 0); + std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{}); ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag); ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType); @@ -4475,7 +4513,7 @@ TEST_F(CursorInputMapperTest, Process_PointerCapture) { // and events are generated the usual way. const uint32_t generation = mReader->getContext()->getGeneration(); mFakePolicy->setPointerCapture(false); - configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); + configureDevice(InputReaderConfiguration::Change::POINTER_CAPTURE); ASSERT_TRUE(mReader->getContext()->getGeneration() != generation); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); @@ -4524,7 +4562,7 @@ TEST_F(CursorInputMapperTest, PointerCaptureDisablesVelocityProcessing) { // Enable Pointer Capture mFakePolicy->setPointerCapture(true); - configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); + configureDevice(InputReaderConfiguration::Change::POINTER_CAPTURE); NotifyPointerCaptureChangedArgs captureArgs; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyCaptureWasCalled(&captureArgs)); ASSERT_TRUE(captureArgs.request.enable); @@ -4566,7 +4604,7 @@ TEST_F(CursorInputMapperTest, PointerCaptureDisablesOrientationChanges) { // Enable Pointer Capture. mFakePolicy->setPointerCapture(true); - configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); + configureDevice(InputReaderConfiguration::Change::POINTER_CAPTURE); NotifyPointerCaptureChangedArgs captureArgs; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyCaptureWasCalled(&captureArgs)); ASSERT_TRUE(captureArgs.request.enable); @@ -4592,7 +4630,7 @@ TEST_F(CursorInputMapperTest, ConfigureDisplayId_NoAssociatedViewport) { // The InputDevice is not associated with any display. prepareSecondaryDisplay(); mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); mFakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1); mFakePointerController->setPosition(100, 200); @@ -4619,7 +4657,7 @@ TEST_F(CursorInputMapperTest, ConfigureDisplayId_WithAssociatedViewport) { prepareSecondaryDisplay(); mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID); mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, SECONDARY_DISPLAY_UNIQUE_ID); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); mFakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1); mFakePointerController->setPosition(100, 200); @@ -4644,7 +4682,7 @@ TEST_F(CursorInputMapperTest, ConfigureDisplayId_IgnoresEventsForMismatchedPoint // Associate the InputDevice with the secondary display. prepareSecondaryDisplay(); mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, SECONDARY_DISPLAY_UNIQUE_ID); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); // The mapper should not generate any events because it is associated with a display that is // different from the pointer display. @@ -5811,7 +5849,7 @@ TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) { viewport->physicalRight = 30; viewport->physicalBottom = 610; mFakePolicy->updateViewport(*viewport); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); // Start the touch. process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1); @@ -6536,7 +6574,7 @@ TEST_F(SingleTouchInputMapperTest, auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL); viewport->isActive = false; mFakePolicy->updateViewport(*viewport); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); // We should receive a cancel event for the ongoing gesture. ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); @@ -6561,7 +6599,7 @@ TEST_F(SingleTouchInputMapperTest, // Make the viewport active again. The device should resume processing events. viewport->isActive = true; mFakePolicy->updateViewport(*viewport); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); // The device is reset because it changes back to direct mode, without generating any events. ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled()); @@ -6729,7 +6767,7 @@ TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_upda // Send update to the mapper. std::list<NotifyArgs> unused2 = mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DEVICE_TYPE /*changes*/); + InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/); // Check whether device type update was successful. ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mDevice->getSources()); @@ -6750,7 +6788,7 @@ TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) { viewport->physicalRight = DISPLAY_WIDTH / 2; viewport->physicalBottom = DISPLAY_HEIGHT / 2; mFakePolicy->updateViewport(*viewport); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>(); @@ -6839,7 +6877,7 @@ public: v.uniqueId = UNIQUE_ID; v.type = ViewportType::INTERNAL; mFakePolicy->updateViewport(v); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); } void assertReceivedMove(const Point& point) { @@ -7199,7 +7237,7 @@ public: mStylusState.pressure = 0.f; mStylusState.toolType = ToolType::STYLUS; mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo}); - configureDevice(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE); + configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE); processExternalStylusState(mapper); return mapper; } @@ -9255,7 +9293,7 @@ TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) { // Don't set touch.enableForInactiveViewport to verify the default behavior. mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0, /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); prepareAxes(POSITION); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); @@ -9275,7 +9313,7 @@ TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) { addConfigurationProperty("touch.enableForInactiveViewport", "1"); mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0, /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); prepareAxes(POSITION); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); @@ -9297,7 +9335,7 @@ TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) { ASSERT_TRUE(optionalDisplayViewport.has_value()); DisplayViewport displayViewport = *optionalDisplayViewport; - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); prepareAxes(POSITION); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); @@ -9313,7 +9351,7 @@ TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) { // Deactivate display viewport displayViewport.isActive = false; ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport)); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); // The ongoing touch should be canceled immediately ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); @@ -9328,7 +9366,7 @@ TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) { // Reactivate display viewport displayViewport.isActive = true; ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport)); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); // Finger move again starts new gesture x += 10, y += 10; @@ -9366,10 +9404,12 @@ TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) { String8("touchScreen")); // Setup the second touch screen device. - MultiTouchInputMapper& mapper2 = device2->addMapper<MultiTouchInputMapper>(SECOND_EVENTHUB_ID); + MultiTouchInputMapper& mapper2 = + device2->addMapper<MultiTouchInputMapper>(SECOND_EVENTHUB_ID, + mFakePolicy->getReaderConfiguration()); std::list<NotifyArgs> unused = device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - /*changes=*/0); + /*changes=*/{}); unused += device2->reset(ARBITRARY_TIME); // Setup PointerController. @@ -9390,8 +9430,8 @@ TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) { // Default device will reconfigure above, need additional reconfiguration for another device. unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_DISPLAY_INFO | - InputReaderConfiguration::CHANGE_SHOW_TOUCHES); + InputReaderConfiguration::Change::DISPLAY_INFO | + InputReaderConfiguration::Change::SHOW_TOUCHES); // Two fingers down at default display. int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500; @@ -9422,7 +9462,7 @@ TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) { // Disable the show touches configuration and ensure the spots are cleared. mFakePolicy->setShowTouches(false); unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), - InputReaderConfiguration::CHANGE_SHOW_TOUCHES); + InputReaderConfiguration::Change::SHOW_TOUCHES); ASSERT_TRUE(fakePointerController->getSpots().empty()); } @@ -10332,7 +10372,7 @@ TEST_F(MultiTouchInputMapperTest, Process_TouchpadCapture) { // non captured touchpad should be a mouse source mFakePolicy->setPointerCapture(false); - configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); + configureDevice(InputReaderConfiguration::Change::POINTER_CAPTURE); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources()); } @@ -10417,7 +10457,7 @@ TEST_F(MultiTouchInputMapperTest, WhenCapturedAndNotCaptured_GetSources) { // captured touchpad should be a touchpad device mFakePolicy->setPointerCapture(true); - configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE); + configureDevice(InputReaderConfiguration::Change::POINTER_CAPTURE); ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources()); } @@ -10803,7 +10843,7 @@ TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGesture auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL); viewport->isActive = false; mFakePolicy->updateViewport(*viewport); - configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL), WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS), @@ -10911,14 +10951,6 @@ protected: mFakePolicy.clear(); } - std::list<NotifyArgs> configureDevice(uint32_t changes) { - if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { - mReader->requestRefreshConfiguration(changes); - mReader->loopOnce(); - } - return mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes); - } - std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name, const std::string& location, int32_t eventHubId, ftl::Flags<InputDeviceClass> classes) { diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp index 2801072b6a..fc917dd582 100644 --- a/services/inputflinger/tests/TestInputListener.cpp +++ b/services/inputflinger/tests/TestInputListener.cpp @@ -29,6 +29,14 @@ TestInputListener::TestInputListener(std::chrono::milliseconds eventHappenedTime TestInputListener::~TestInputListener() {} +void TestInputListener::assertNotifyInputDevicesChangedWasCalled( + NotifyInputDevicesChangedArgs* outEventArgs) { + ASSERT_NO_FATAL_FAILURE( + assertCalled<NotifyInputDevicesChangedArgs>(outEventArgs, + "Expected notifyInputDevicesChanged() " + "to have been called.")); +} + void TestInputListener::assertNotifyConfigurationChangedWasCalled( NotifyConfigurationChangedArgs* outEventArgs) { ASSERT_NO_FATAL_FAILURE( @@ -160,43 +168,47 @@ void TestInputListener::assertNotCalled(std::string message, std::optional<TimeP } template <class NotifyArgsType> -void TestInputListener::addToQueue(const NotifyArgsType* args) { +void TestInputListener::addToQueue(const NotifyArgsType& args) { std::scoped_lock<std::mutex> lock(mLock); std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues); - queue.push_back(*args); + queue.push_back(args); mCondition.notify_all(); } -void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { +void TestInputListener::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) { + addToQueue<NotifyInputDevicesChangedArgs>(args); +} + +void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) { addToQueue<NotifyConfigurationChangedArgs>(args); } -void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) { +void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs& args) { addToQueue<NotifyDeviceResetArgs>(args); } -void TestInputListener::notifyKey(const NotifyKeyArgs* args) { +void TestInputListener::notifyKey(const NotifyKeyArgs& args) { addToQueue<NotifyKeyArgs>(args); } -void TestInputListener::notifyMotion(const NotifyMotionArgs* args) { +void TestInputListener::notifyMotion(const NotifyMotionArgs& args) { addToQueue<NotifyMotionArgs>(args); } -void TestInputListener::notifySwitch(const NotifySwitchArgs* args) { +void TestInputListener::notifySwitch(const NotifySwitchArgs& args) { addToQueue<NotifySwitchArgs>(args); } -void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) { +void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) { addToQueue<NotifyPointerCaptureChangedArgs>(args); } -void TestInputListener::notifySensor(const NotifySensorArgs* args) { +void TestInputListener::notifySensor(const NotifySensorArgs& args) { addToQueue<NotifySensorArgs>(args); } -void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) { +void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs& args) { addToQueue<NotifyVibratorStateArgs>(args); } diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h index 9665f702a1..deb60483fb 100644 --- a/services/inputflinger/tests/TestInputListener.h +++ b/services/inputflinger/tests/TestInputListener.h @@ -35,6 +35,9 @@ public: using TimePoint = std::chrono::time_point<std::chrono::system_clock>; + void assertNotifyInputDevicesChangedWasCalled( + NotifyInputDevicesChangedArgs* outEventArgs = nullptr); + void assertNotifyConfigurationChangedWasCalled( NotifyConfigurationChangedArgs* outEventArgs = nullptr); @@ -74,30 +77,33 @@ private: void assertNotCalled(std::string message, std::optional<TimePoint> timeout = {}); template <class NotifyArgsType> - void addToQueue(const NotifyArgsType* args); + void addToQueue(const NotifyArgsType& args); + + virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override; - virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; + virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override; - virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; + virtual void notifyDeviceReset(const NotifyDeviceResetArgs& args) override; - virtual void notifyKey(const NotifyKeyArgs* args) override; + virtual void notifyKey(const NotifyKeyArgs& args) override; - virtual void notifyMotion(const NotifyMotionArgs* args) override; + virtual void notifyMotion(const NotifyMotionArgs& args) override; - virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySwitch(const NotifySwitchArgs& args) override; - virtual void notifySensor(const NotifySensorArgs* args) override; + virtual void notifySensor(const NotifySensorArgs& args) override; - virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override; + virtual void notifyVibratorState(const NotifyVibratorStateArgs& args) override; - virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; + virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override; std::mutex mLock; std::condition_variable mCondition; const std::chrono::milliseconds mEventHappenedTimeout; const std::chrono::milliseconds mEventDidNotHappenTimeout; - std::tuple<std::vector<NotifyConfigurationChangedArgs>, // + std::tuple<std::vector<NotifyInputDevicesChangedArgs>, // + std::vector<NotifyConfigurationChangedArgs>, // std::vector<NotifyDeviceResetArgs>, // std::vector<NotifyKeyArgs>, // std::vector<NotifyMotionArgs>, // diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp index 2a9ace00c5..1fff2c7590 100644 --- a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp +++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp @@ -421,7 +421,7 @@ TEST_F(UnwantedInteractionBlockerTest, ConfigurationChangedIsPassedToNextListene // Create a basic configuration change and send to blocker NotifyConfigurationChangedArgs args(/*sequenceNum=*/1, /*eventTime=*/2); - mBlocker->notifyConfigurationChanged(&args); + mBlocker->notifyConfigurationChanged(args); NotifyConfigurationChangedArgs outArgs; ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyConfigurationChangedWasCalled(&outArgs)); ASSERT_EQ(args, outArgs); @@ -438,10 +438,8 @@ TEST_F(UnwantedInteractionBlockerTest, KeyIsPassedToNextListener) { AKEY_EVENT_ACTION_DOWN, /*flags=*/4, AKEYCODE_HOME, /*scanCode=*/5, AMETA_NONE, /*downTime=*/6); - mBlocker->notifyKey(&args); - NotifyKeyArgs outArgs; - ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(&outArgs)); - ASSERT_EQ(args, outArgs); + mBlocker->notifyKey(args); + ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(testing::Eq(args))); } /** @@ -452,10 +450,8 @@ TEST_F(UnwantedInteractionBlockerTest, KeyIsPassedToNextListener) { TEST_F(UnwantedInteractionBlockerTest, DownEventIsPassedToNextListener) { NotifyMotionArgs motionArgs = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}); - mBlocker->notifyMotion(&motionArgs); - NotifyMotionArgs args; - ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(&args)); - ASSERT_EQ(motionArgs, args); + mBlocker->notifyMotion(motionArgs); + ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(testing::Eq(motionArgs))); } /** @@ -466,7 +462,7 @@ TEST_F(UnwantedInteractionBlockerTest, SwitchIsPassedToNextListener) { NotifySwitchArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*policyFlags=*/3, /*switchValues=*/4, /*switchMask=*/5); - mBlocker->notifySwitch(&args); + mBlocker->notifySwitch(args); NotifySwitchArgs outArgs; ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifySwitchWasCalled(&outArgs)); ASSERT_EQ(args, outArgs); @@ -479,7 +475,7 @@ TEST_F(UnwantedInteractionBlockerTest, SwitchIsPassedToNextListener) { TEST_F(UnwantedInteractionBlockerTest, DeviceResetIsPassedToNextListener) { NotifyDeviceResetArgs args(/*sequenceNum=*/1, /*eventTime=*/2, DEVICE_ID); - mBlocker->notifyDeviceReset(&args); + mBlocker->notifyDeviceReset(args); NotifyDeviceResetArgs outArgs; ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyDeviceResetWasCalled(&outArgs)); ASSERT_EQ(args, outArgs); @@ -491,25 +487,20 @@ TEST_F(UnwantedInteractionBlockerTest, DeviceResetIsPassedToNextListener) { * a crash due to inconsistent event stream could have occurred. */ TEST_F(UnwantedInteractionBlockerTest, NoCrashWhenResetHappens) { - NotifyMotionArgs args; - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); - mBlocker->notifyMotion( - &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}}))); - mBlocker->notifyMotion( - &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}}))); - NotifyDeviceResetArgs resetArgs(/*sequenceNum=*/1, /*eventTime=*/3, DEVICE_ID); - mBlocker->notifyDeviceReset(&resetArgs); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}})); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}})); + mBlocker->notifyDeviceReset({/*sequenceNum=*/1, /*eventTime=*/3, DEVICE_ID}); // Start a new gesture with a DOWN event, even though the previous event stream was incomplete. - mBlocker->notifyMotion( - &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, DOWN, {{7, 8, 9}}))); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, DOWN, {{7, 8, 9}})); } TEST_F(UnwantedInteractionBlockerTest, NoCrashWhenStylusSourceWithFingerToolIsReceived) { - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); NotifyMotionArgs args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}}); args.pointerProperties[0].toolType = ToolType::FINGER; args.source = AINPUT_SOURCE_STYLUS; - mBlocker->notifyMotion(&args); + mBlocker->notifyMotion(args); } /** @@ -517,48 +508,41 @@ TEST_F(UnwantedInteractionBlockerTest, NoCrashWhenStylusSourceWithFingerToolIsRe * UnwantedInteractionBlocker has not changed, there should not be a reset. */ TEST_F(UnwantedInteractionBlockerTest, NoResetIfDeviceInfoChanges) { - NotifyMotionArgs args; - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); - mBlocker->notifyMotion( - &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}}))); - mBlocker->notifyMotion( - &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}}))); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}})); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}})); // Now pretend the device changed, even though nothing is different for DEVICE_ID in practice. - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); // The MOVE event continues the gesture that started before 'devices changed', so it should not // cause a crash. - mBlocker->notifyMotion( - &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, MOVE, {{7, 8, 9}}))); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, MOVE, {{7, 8, 9}})); } /** * Send a touch event, and then a stylus event. Make sure that both work. */ TEST_F(UnwantedInteractionBlockerTest, StylusAfterTouchWorks) { - NotifyMotionArgs args; - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); - args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}); - mBlocker->notifyMotion(&args); - args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{4, 5, 6}}); - mBlocker->notifyMotion(&args); - args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, UP, {{4, 5, 6}}); - mBlocker->notifyMotion(&args); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}})); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{4, 5, 6}})); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, UP, {{4, 5, 6}})); // Now touch down stylus + NotifyMotionArgs args; args = generateMotionArgs(/*downTime=*/3, /*eventTime=*/3, DOWN, {{10, 20, 30}}); args.pointerProperties[0].toolType = ToolType::STYLUS; args.source |= AINPUT_SOURCE_STYLUS; - mBlocker->notifyMotion(&args); + mBlocker->notifyMotion(args); args = generateMotionArgs(/*downTime=*/3, /*eventTime=*/4, MOVE, {{40, 50, 60}}); args.pointerProperties[0].toolType = ToolType::STYLUS; args.source |= AINPUT_SOURCE_STYLUS; - mBlocker->notifyMotion(&args); + mBlocker->notifyMotion(args); args = generateMotionArgs(/*downTime=*/3, /*eventTime=*/5, UP, {{40, 50, 60}}); args.pointerProperties[0].toolType = ToolType::STYLUS; args.source |= AINPUT_SOURCE_STYLUS; - mBlocker->notifyMotion(&args); + mBlocker->notifyMotion(args); } /** @@ -568,17 +552,14 @@ TEST_F(UnwantedInteractionBlockerTest, StylusAfterTouchWorks) { * options */ TEST_F(UnwantedInteractionBlockerTest, DumpCanBeAccessedOnAnotherThread) { - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); - NotifyMotionArgs args1 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}); - mBlocker->notifyMotion(&args1); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}})); std::thread dumpThread([this]() { std::string dump; mBlocker->dump(dump); }); - NotifyMotionArgs args2 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{4, 5, 6}}); - mBlocker->notifyMotion(&args2); - NotifyMotionArgs args3 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, UP, {{4, 5, 6}}); - mBlocker->notifyMotion(&args3); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{4, 5, 6}})); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, UP, {{4, 5, 6}})); dumpThread.join(); } @@ -587,22 +568,19 @@ TEST_F(UnwantedInteractionBlockerTest, DumpCanBeAccessedOnAnotherThread) { * of the touch is large. This is an integration test that checks that this filter kicks in. */ TEST_F(UnwantedInteractionBlockerTest, HeuristicFilterWorks) { - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); // Small touch down - NotifyMotionArgs args1 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}); - mBlocker->notifyMotion(&args1); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}})); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(DOWN)); // Large touch oval on the next move - NotifyMotionArgs args2 = - generateMotionArgs(/*downTime=*/0, RESAMPLE_PERIOD, MOVE, {{4, 5, 200}}); - mBlocker->notifyMotion(&args2); + mBlocker->notifyMotion( + generateMotionArgs(/*downTime=*/0, RESAMPLE_PERIOD, MOVE, {{4, 5, 200}})); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(MOVE)); // Lift up the touch to force the model to decide on whether it's a palm - NotifyMotionArgs args3 = - generateMotionArgs(/*downTime=*/0, 2 * RESAMPLE_PERIOD, UP, {{4, 5, 200}}); - mBlocker->notifyMotion(&args3); + mBlocker->notifyMotion( + generateMotionArgs(/*downTime=*/0, 2 * RESAMPLE_PERIOD, UP, {{4, 5, 200}})); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(CANCEL)); } @@ -613,19 +591,19 @@ TEST_F(UnwantedInteractionBlockerTest, HeuristicFilterWorks) { * This is similar to `HeuristicFilterWorks` test, but for stylus tool. */ TEST_F(UnwantedInteractionBlockerTest, StylusIsNotBlocked) { - InputDeviceInfo info = generateTestDeviceInfo(); - info.addSource(AINPUT_SOURCE_STYLUS); - mBlocker->notifyInputDevicesChanged({info}); + NotifyInputDevicesChangedArgs deviceChangedArgs = {/*id=*/0, {generateTestDeviceInfo()}}; + deviceChangedArgs.inputDeviceInfos[0].addSource(AINPUT_SOURCE_STYLUS); + mBlocker->notifyInputDevicesChanged(deviceChangedArgs); NotifyMotionArgs args1 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}); args1.pointerProperties[0].toolType = ToolType::STYLUS; - mBlocker->notifyMotion(&args1); + mBlocker->notifyMotion(args1); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(DOWN)); // Move the stylus, setting large TOUCH_MAJOR/TOUCH_MINOR dimensions NotifyMotionArgs args2 = generateMotionArgs(/*downTime=*/0, RESAMPLE_PERIOD, MOVE, {{4, 5, 200}}); args2.pointerProperties[0].toolType = ToolType::STYLUS; - mBlocker->notifyMotion(&args2); + mBlocker->notifyMotion(args2); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(MOVE)); // Lift up the stylus. If it were a touch event, this would force the model to decide on whether @@ -633,7 +611,7 @@ TEST_F(UnwantedInteractionBlockerTest, StylusIsNotBlocked) { NotifyMotionArgs args3 = generateMotionArgs(/*downTime=*/0, 2 * RESAMPLE_PERIOD, UP, {{4, 5, 200}}); args3.pointerProperties[0].toolType = ToolType::STYLUS; - mBlocker->notifyMotion(&args3); + mBlocker->notifyMotion(args3); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(UP)); } @@ -643,34 +621,34 @@ TEST_F(UnwantedInteractionBlockerTest, StylusIsNotBlocked) { * Stylus event should continue to work even after touch is detected as a palm. */ TEST_F(UnwantedInteractionBlockerTest, TouchIsBlockedWhenMixedWithStylus) { - InputDeviceInfo info = generateTestDeviceInfo(); - info.addSource(AINPUT_SOURCE_STYLUS); - mBlocker->notifyInputDevicesChanged({info}); + NotifyInputDevicesChangedArgs deviceChangedArgs = {/*id=*/0, {generateTestDeviceInfo()}}; + deviceChangedArgs.inputDeviceInfos[0].addSource(AINPUT_SOURCE_STYLUS); + mBlocker->notifyInputDevicesChanged(deviceChangedArgs); // Touch down NotifyMotionArgs args1 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}); - mBlocker->notifyMotion(&args1); + mBlocker->notifyMotion(args1); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(DOWN)); // Stylus pointer down NotifyMotionArgs args2 = generateMotionArgs(/*downTime=*/0, RESAMPLE_PERIOD, POINTER_1_DOWN, {{1, 2, 3}, {10, 20, 30}}); args2.pointerProperties[1].toolType = ToolType::STYLUS; - mBlocker->notifyMotion(&args2); + mBlocker->notifyMotion(args2); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(POINTER_1_DOWN)); // Large touch oval on the next finger move NotifyMotionArgs args3 = generateMotionArgs(/*downTime=*/0, 2 * RESAMPLE_PERIOD, MOVE, {{1, 2, 300}, {11, 21, 30}}); args3.pointerProperties[1].toolType = ToolType::STYLUS; - mBlocker->notifyMotion(&args3); + mBlocker->notifyMotion(args3); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(MOVE)); // Lift up the finger pointer. It should be canceled due to the heuristic filter. NotifyMotionArgs args4 = generateMotionArgs(/*downTime=*/0, 3 * RESAMPLE_PERIOD, POINTER_0_UP, {{1, 2, 300}, {11, 21, 30}}); args4.pointerProperties[1].toolType = ToolType::STYLUS; - mBlocker->notifyMotion(&args4); + mBlocker->notifyMotion(args4); mTestListener.assertNotifyMotionWasCalled( AllOf(WithMotionAction(POINTER_0_UP), WithFlags(FLAG_CANCELED))); @@ -678,7 +656,7 @@ TEST_F(UnwantedInteractionBlockerTest, TouchIsBlockedWhenMixedWithStylus) { generateMotionArgs(/*downTime=*/0, 4 * RESAMPLE_PERIOD, MOVE, {{12, 22, 30}}); args5.pointerProperties[0].id = args4.pointerProperties[1].id; args5.pointerProperties[0].toolType = ToolType::STYLUS; - mBlocker->notifyMotion(&args5); + mBlocker->notifyMotion(args5); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(MOVE)); // Lift up the stylus pointer @@ -686,7 +664,7 @@ TEST_F(UnwantedInteractionBlockerTest, TouchIsBlockedWhenMixedWithStylus) { generateMotionArgs(/*downTime=*/0, 5 * RESAMPLE_PERIOD, UP, {{4, 5, 200}}); args6.pointerProperties[0].id = args4.pointerProperties[1].id; args6.pointerProperties[0].toolType = ToolType::STYLUS; - mBlocker->notifyMotion(&args6); + mBlocker->notifyMotion(args6); mTestListener.assertNotifyMotionWasCalled(WithMotionAction(UP)); } @@ -699,18 +677,16 @@ using UnwantedInteractionBlockerTestDeathTest = UnwantedInteractionBlockerTest; TEST_F(UnwantedInteractionBlockerTestDeathTest, InconsistentEventAfterResetCausesACrash) { ScopedSilentDeath _silentDeath; NotifyMotionArgs args; - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); - mBlocker->notifyMotion( - &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}}))); - mBlocker->notifyMotion( - &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}}))); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}})); + mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}})); NotifyDeviceResetArgs resetArgs(/*sequenceNum=*/1, /*eventTime=*/3, DEVICE_ID); - mBlocker->notifyDeviceReset(&resetArgs); + mBlocker->notifyDeviceReset(resetArgs); // Sending MOVE without a DOWN -> should crash! ASSERT_DEATH( { - mBlocker->notifyMotion(&(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, - MOVE, {{7, 8, 9}}))); + mBlocker->notifyMotion( + generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, MOVE, {{7, 8, 9}})); }, "Could not find slot"); } @@ -720,9 +696,13 @@ TEST_F(UnwantedInteractionBlockerTestDeathTest, InconsistentEventAfterResetCause */ TEST_F(UnwantedInteractionBlockerTestDeathTest, WhenMoveWithoutDownCausesACrash) { ScopedSilentDeath _silentDeath; - NotifyMotionArgs args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{1, 2, 3}}); - mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()}); - ASSERT_DEATH({ mBlocker->notifyMotion(&args); }, "Could not find slot"); + mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); + ASSERT_DEATH( + { + mBlocker->notifyMotion( + generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{1, 2, 3}})); + }, + "Could not find slot"); } class PalmRejectorTest : public testing::Test { diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp index 0d5f30c046..8098ef2edd 100644 --- a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp @@ -38,8 +38,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { std::make_shared<ThreadSafeFuzzedDataProvider>(data, size); FuzzContainer fuzzer(fdp); - CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>(); auto policyConfig = fuzzer.getPolicyConfig(); + CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>(policyConfig); // Loop through mapper operations until randomness is exhausted. while (fdp->remaining_bytes() > 0) { @@ -52,13 +52,15 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { [&]() -> void { mapper.getSources(); }, [&]() -> void { std::list<NotifyArgs> unused = - mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, - fdp->ConsumeIntegral<int32_t>()); + mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, + InputReaderConfiguration::Change( + fdp->ConsumeIntegral<int32_t>())); }, [&]() -> void { // Need to reconfigure with 0 or you risk a NPE. std::list<NotifyArgs> unused = - mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, + InputReaderConfiguration::Change(0)); InputDeviceInfo info; mapper.populateDeviceInfo(info); }, @@ -71,7 +73,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { // Need to reconfigure with 0 or you risk a NPE. std::list<NotifyArgs> unused = - mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, + InputReaderConfiguration::Change(0)); RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), fdp->ConsumeIntegral<nsecs_t>(), fdp->ConsumeIntegral<int32_t>(), @@ -90,7 +93,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { [&]() -> void { // Need to reconfigure with 0 or you risk a NPE. std::list<NotifyArgs> unused = - mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, + InputReaderConfiguration::Change(0)); mapper.getAssociatedDisplayId(); }, })(); diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h index 76d2bcd03d..84ac0fd262 100644 --- a/services/inputflinger/tests/fuzzers/FuzzContainer.h +++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h @@ -59,7 +59,7 @@ public: void configureDevice() { nsecs_t arbitraryTime = mFdp->ConsumeIntegral<nsecs_t>(); std::list<NotifyArgs> out; - out += mFuzzDevice->configure(arbitraryTime, &mPolicyConfig, 0); + out += mFuzzDevice->configure(arbitraryTime, mPolicyConfig, /*changes=*/{}); out += mFuzzDevice->reset(arbitraryTime); for (const NotifyArgs& args : out) { mFuzzListener.notify(args); diff --git a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp index 6617f65adf..f8ebc97ccd 100644 --- a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp @@ -67,51 +67,42 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { fdp.PickValueInArray<std::function<void()>>({ [&]() -> void { // SendToNextStage_NotifyConfigurationChangedArgs - NotifyConfigurationChangedArgs - args(/*sequenceNum=*/fdp.ConsumeIntegral<uint32_t>(), - /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>()); - mClassifier->notifyConfigurationChanged(&args); + mClassifier->notifyConfigurationChanged( + {/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(), + /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>()}); }, [&]() -> void { // SendToNextStage_NotifyKeyArgs const nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>(); const nsecs_t readTime = eventTime + fdp.ConsumeIntegralInRange<nsecs_t>(0, 1E8); - NotifyKeyArgs keyArgs(/*sequenceNum=*/fdp.ConsumeIntegral<uint32_t>(), - eventTime, readTime, - /*deviceId=*/fdp.ConsumeIntegral<int32_t>(), - AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT, - /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(), - AKEY_EVENT_ACTION_DOWN, - /*flags=*/fdp.ConsumeIntegral<int32_t>(), AKEYCODE_HOME, - /*scanCode=*/fdp.ConsumeIntegral<int32_t>(), AMETA_NONE, - /*downTime=*/fdp.ConsumeIntegral<nsecs_t>()); - - mClassifier->notifyKey(&keyArgs); + mClassifier->notifyKey({/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(), + eventTime, readTime, + /*deviceId=*/fdp.ConsumeIntegral<int32_t>(), + AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT, + /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(), + AKEY_EVENT_ACTION_DOWN, + /*flags=*/fdp.ConsumeIntegral<int32_t>(), AKEYCODE_HOME, + /*scanCode=*/fdp.ConsumeIntegral<int32_t>(), AMETA_NONE, + /*downTime=*/fdp.ConsumeIntegral<nsecs_t>()}); }, [&]() -> void { // SendToNextStage_NotifyMotionArgs - NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp); - mClassifier->notifyMotion(&motionArgs); + mClassifier->notifyMotion(generateFuzzedMotionArgs(fdp)); }, [&]() -> void { // SendToNextStage_NotifySwitchArgs - NotifySwitchArgs switchArgs(/*sequenceNum=*/fdp.ConsumeIntegral<uint32_t>(), - /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>(), - /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(), - /*switchValues=*/fdp.ConsumeIntegral<uint32_t>(), - /*switchMask=*/fdp.ConsumeIntegral<uint32_t>()); - - mClassifier->notifySwitch(&switchArgs); + mClassifier->notifySwitch({/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(), + /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>(), + /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(), + /*switchValues=*/fdp.ConsumeIntegral<uint32_t>(), + /*switchMask=*/fdp.ConsumeIntegral<uint32_t>()}); }, [&]() -> void { // SendToNextStage_NotifyDeviceResetArgs - NotifyDeviceResetArgs resetArgs( - /*sequenceNum=*/fdp.ConsumeIntegral<uint32_t>(), - /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>(), - /*deviceId=*/fdp.ConsumeIntegral<int32_t>()); - - mClassifier->notifyDeviceReset(&resetArgs); + mClassifier->notifyDeviceReset({/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(), + /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>(), + /*deviceId=*/fdp.ConsumeIntegral<int32_t>()}); }, [&]() -> void { // InputClassifierConverterTest diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp index baece3c110..9223287114 100644 --- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp @@ -82,7 +82,7 @@ public: return reader->hasKeys(deviceId, sourceMask, keyCodes, outFlags); } - void requestRefreshConfiguration(uint32_t changes) { + void requestRefreshConfiguration(ConfigurationChanges changes) { reader->requestRefreshConfiguration(changes); } @@ -232,7 +232,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { fdp->ConsumeIntegral<uint32_t>(), keyCodes, outFlags.data()); }, [&]() -> void { - reader->requestRefreshConfiguration(fdp->ConsumeIntegral<uint32_t>()); + reader->requestRefreshConfiguration( + InputReaderConfiguration::Change(fdp->ConsumeIntegral<uint32_t>())); }, [&]() -> void { reader->cancelVibrate(fdp->ConsumeIntegral<int32_t>(), diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp index 14cb8a5280..616e870811 100644 --- a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp @@ -44,10 +44,10 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { std::make_shared<ThreadSafeFuzzedDataProvider>(data, size); FuzzContainer fuzzer(fdp); + auto policyConfig = fuzzer.getPolicyConfig(); KeyboardInputMapper& mapper = - fuzzer.getMapper<KeyboardInputMapper>(fdp->ConsumeIntegral<uint32_t>(), + fuzzer.getMapper<KeyboardInputMapper>(policyConfig, fdp->ConsumeIntegral<uint32_t>(), fdp->ConsumeIntegral<int32_t>()); - auto policyConfig = fuzzer.getPolicyConfig(); // Loop through mapper operations until randomness is exhausted. while (fdp->remaining_bytes() > 0) { @@ -64,8 +64,9 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { [&]() -> void { mapper.getSources(); }, [&]() -> void { std::list<NotifyArgs> unused = - mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, - fdp->ConsumeIntegral<uint32_t>()); + mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, + InputReaderConfiguration::Change( + fdp->ConsumeIntegral<uint32_t>())); }, [&]() -> void { std::list<NotifyArgs> unused = mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index 9f4aa5cd5e..1e44e0fba0 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -293,14 +293,15 @@ public: class FuzzInputListener : public virtual InputListenerInterface { public: - void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override {} - void notifyKey(const NotifyKeyArgs* args) override {} - void notifyMotion(const NotifyMotionArgs* args) override {} - void notifySwitch(const NotifySwitchArgs* args) override {} - void notifySensor(const NotifySensorArgs* args) override{}; - void notifyVibratorState(const NotifyVibratorStateArgs* args) override{}; - void notifyDeviceReset(const NotifyDeviceResetArgs* args) override {} - void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override{}; + void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override {} + void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override {} + void notifyKey(const NotifyKeyArgs& args) override {} + void notifyMotion(const NotifyMotionArgs& args) override {} + void notifySwitch(const NotifySwitchArgs& args) override {} + void notifySensor(const NotifySensorArgs& args) override{}; + void notifyVibratorState(const NotifyVibratorStateArgs& args) override{}; + void notifyDeviceReset(const NotifyDeviceResetArgs& args) override {} + void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override{}; }; class FuzzInputReaderContext : public InputReaderContext { diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp index 8352a9011e..212462d700 100644 --- a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp @@ -61,8 +61,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { std::make_shared<ThreadSafeFuzzedDataProvider>(data, size); FuzzContainer fuzzer(fdp); - MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>(); auto policyConfig = fuzzer.getPolicyConfig(); + MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>(policyConfig); // Loop through mapper operations until randomness is exhausted. while (fdp->remaining_bytes() > 0) { @@ -79,8 +79,9 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { [&]() -> void { mapper.getSources(); }, [&]() -> void { std::list<NotifyArgs> unused = - mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, - fdp->ConsumeIntegral<uint32_t>()); + mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, + InputReaderConfiguration::Change( + fdp->ConsumeIntegral<uint32_t>())); }, [&]() -> void { std::list<NotifyArgs> unused = mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp index c4938f2aec..590207ea22 100644 --- a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp @@ -24,8 +24,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { std::make_shared<ThreadSafeFuzzedDataProvider>(data, size); FuzzContainer fuzzer(fdp); - SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>(); auto policyConfig = fuzzer.getPolicyConfig(); + SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>(policyConfig); // Loop through mapper operations until randomness is exhausted. while (fdp->remaining_bytes() > 0) { diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp index 94de55c124..b0fbe5dc4e 100644 --- a/services/sensorservice/BatteryService.cpp +++ b/services/sensorservice/BatteryService.cpp @@ -74,6 +74,14 @@ void BatteryService::disableSensorImpl(uid_t uid, int handle) { } } +void BatteryService::noteWakeupSensorEventImpl(int64_t elapsedNanos, uid_t uid, int handle) { + if (checkService()) { + int64_t identity = IPCThreadState::self()->clearCallingIdentity(); + mBatteryStatService->noteWakeupSensorEvent(elapsedNanos, uid, handle); + IPCThreadState::self()->restoreCallingIdentity(identity); + } +} + bool BatteryService::checkService() { if (mBatteryStatService == nullptr) { const sp<IServiceManager> sm(defaultServiceManager()); diff --git a/services/sensorservice/BatteryService.h b/services/sensorservice/BatteryService.h index 13fc58aadb..60ef03f685 100644 --- a/services/sensorservice/BatteryService.h +++ b/services/sensorservice/BatteryService.h @@ -19,11 +19,14 @@ #include <batterystats/IBatteryStats.h> #include <utils/Singleton.h> +#include <utils/SortedVector.h> +#include <utils/SystemClock.h> namespace android { // --------------------------------------------------------------------------- class BatteryService : public Singleton<BatteryService> { + static constexpr int64_t WAKEUP_SENSOR_EVENT_DEBOUNCE_MS = 1000; friend class Singleton<BatteryService>; sp<IBatteryStats> mBatteryStatService; @@ -32,6 +35,7 @@ class BatteryService : public Singleton<BatteryService> { void enableSensorImpl(uid_t uid, int handle); void disableSensorImpl(uid_t uid, int handle); + void noteWakeupSensorEventImpl(int64_t elapsedNanos, uid_t uid, int handle); struct Info { uid_t uid; @@ -44,6 +48,7 @@ class BatteryService : public Singleton<BatteryService> { } }; + int64_t mLastWakeupSensorEventReportedMs; Mutex mActivationsLock; SortedVector<Info> mActivations; bool addSensor(uid_t uid, int handle); @@ -57,6 +62,15 @@ public: static void disableSensor(uid_t uid, int handle) { BatteryService::getInstance().disableSensorImpl(uid, handle); } + static void noteWakeupSensorEvent(int64_t elapsed, uid_t uid, int handle) { + BatteryService& instance = BatteryService::getInstance(); + const int64_t nowElapsedMs = elapsedRealtime(); + if (nowElapsedMs >= (instance.mLastWakeupSensorEventReportedMs + + WAKEUP_SENSOR_EVENT_DEBOUNCE_MS)) { + instance.noteWakeupSensorEventImpl(elapsed, uid, handle); + instance.mLastWakeupSensorEventReportedMs = nowElapsedMs; + } + } }; // --------------------------------------------------------------------------- diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp index 7a6b31d642..dc5070c315 100644 --- a/services/sensorservice/SensorEventConnection.cpp +++ b/services/sensorservice/SensorEventConnection.cpp @@ -23,6 +23,7 @@ #include <sensor/SensorEventQueue.h> #include "vec.h" +#include "BatteryService.h" #include "SensorEventConnection.h" #include "SensorDevice.h" @@ -391,6 +392,8 @@ status_t SensorService::SensorEventConnection::sendEvents( if (hasSensorAccess()) { index_wake_up_event = findWakeUpSensorEventLocked(scratch, count); if (index_wake_up_event >= 0) { + BatteryService::noteWakeupSensorEvent(scratch[index_wake_up_event].timestamp, + mUid, scratch[index_wake_up_event].sensor); scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK; ++mWakeLockRefCount; #if DEBUG_CONNECTIONS diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 01db0cdfdb..20f4de1d67 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -535,8 +535,8 @@ void DisplayDevice::clearDesiredActiveModeState() { } void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { - using fps_approx_ops::operator==; - if (mRequestedRefreshRate == 0_Hz) { + using fps_approx_ops::operator<=; + if (mRequestedRefreshRate <= 0_Hz) { return; } @@ -547,7 +547,12 @@ void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { } unsigned divisor = static_cast<unsigned>( - std::round(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); + std::floor(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); + if (divisor == 0) { + mAdjustedRefreshRate = 0_Hz; + return; + } + mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor; } diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp b/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp index 6af352c9f4..cfa2b031e9 100644 --- a/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp +++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp @@ -23,6 +23,7 @@ namespace android::surfaceflinger { std::atomic<uint32_t> LayerCreationArgs::sSequence{1}; +std::atomic<uint32_t> LayerCreationArgs::sInternalSequence{1}; uint32_t LayerCreationArgs::getInternalLayerId(uint32_t id) { return id | INTERNAL_LAYER_PREFIX; @@ -48,13 +49,11 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, metadata.getInt32(gui::METADATA_OWNER_UID, static_cast<int32_t>(ownerUid))); } - if (id) { + if (internalLayer) { + sequence = getInternalLayerId(sInternalSequence++); + } else if (id) { sequence = *id; - if (internalLayer) { - sequence = getInternalLayerId(*id); - } else { - sSequence = *id + 1; - } + sSequence = *id + 1; } else { sequence = sSequence++; if (sequence >= INTERNAL_LAYER_PREFIX) { diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h index 3a0fc6d7a3..c26edb5d22 100644 --- a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h +++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h @@ -36,6 +36,7 @@ namespace android::surfaceflinger { struct LayerCreationArgs { static std::atomic<uint32_t> sSequence; + static std::atomic<uint32_t> sInternalSequence; static uint32_t getInternalLayerId(uint32_t id); static LayerCreationArgs fromOtherArgs(const LayerCreationArgs& other); diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index c30465fbd4..5913d4b589 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -30,7 +30,7 @@ auto layerZCompare = [](const std::pair<LayerHierarchy*, LayerHierarchy::Variant auto lhsLayer = lhs.first->getLayer(); auto rhsLayer = rhs.first->getLayer(); if (lhsLayer->layerStack.id != rhsLayer->layerStack.id) { - return lhsLayer->layerStack.id > rhsLayer->layerStack.id; + return lhsLayer->layerStack.id < rhsLayer->layerStack.id; } if (lhsLayer->z != rhsLayer->z) { return lhsLayer->z < rhsLayer->z; diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp index 33d9dbe796..6cacfb5946 100644 --- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp +++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp @@ -41,7 +41,7 @@ void LayerLifecycleManager::addLayers(std::vector<std::unique_ptr<RequestedLayer LOG_ALWAYS_FATAL("Duplicate layer id %d found. Existing layer: %s", layer.id, it->second.owner.getDebugString().c_str()); } - + mAddedLayers.push_back(newLayer.get()); layer.parentId = linkLayer(layer.parentId, layer.id); layer.relativeParentId = linkLayer(layer.relativeParentId, layer.id); if (layer.layerStackToMirror != ui::INVALID_LAYER_STACK) { @@ -258,23 +258,19 @@ void LayerLifecycleManager::applyTransactions(const std::vector<TransactionState } void LayerLifecycleManager::commitChanges() { - for (auto& layer : mLayers) { - if (layer->changes.test(RequestedLayerState::Changes::Created)) { - for (auto listener : mListeners) { - listener->onLayerAdded(*layer); - } + for (auto layer : mAddedLayers) { + for (auto& listener : mListeners) { + listener->onLayerAdded(*layer); } + } + mAddedLayers.clear(); + + for (auto& layer : mLayers) { layer->clearChanges(); } for (auto& destroyedLayer : mDestroyedLayers) { - if (destroyedLayer->changes.test(RequestedLayerState::Changes::Created)) { - for (auto listener : mListeners) { - listener->onLayerAdded(*destroyedLayer); - } - } - - for (auto listener : mListeners) { + for (auto& listener : mListeners) { listener->onLayerDestroyed(*destroyedLayer); } } diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h index f258678598..f0d2c22e5a 100644 --- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h +++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h @@ -108,6 +108,9 @@ private: std::vector<std::unique_ptr<RequestedLayerState>> mLayers; // Layers pending destruction. Layers will be destroyed once changes are committed. std::vector<std::unique_ptr<RequestedLayerState>> mDestroyedLayers; + // Keeps track of all the layers that were added in order. Changes will be cleared once + // committed. + std::vector<RequestedLayerState*> mAddedLayers; }; } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 1e931a7a1a..a9925843df 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -27,7 +27,6 @@ using namespace ftl::flag_operators; LayerSnapshot::LayerSnapshot(const RequestedLayerState& state, const LayerHierarchy::TraversalPath& path) : path(path) { - static uint32_t sUniqueSequenceId = 0; // Provide a unique id for all snapshots. // A front end layer can generate multiple snapshots if its mirrored. // Additionally, if the layer is not reachable, we may choose to destroy @@ -35,7 +34,12 @@ LayerSnapshot::LayerSnapshot(const RequestedLayerState& state, // change. The consumer shouldn't tie any lifetimes to this unique id but // register a LayerLifecycleManager::ILifecycleListener or get a list of // destroyed layers from LayerLifecycleManager. - uniqueSequence = sUniqueSequenceId++; + if (path.isClone()) { + uniqueSequence = + LayerCreationArgs::getInternalLayerId(LayerCreationArgs::sInternalSequence++); + } else { + uniqueSequence = state.id; + } sequence = static_cast<int32_t>(state.id); name = state.name; textureName = state.textureName; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 25cbe7ae54..ce7d37e69b 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -817,7 +817,8 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority; } - if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content)) { + if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content) || + snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) { snapshot.color.rgb = requested.getColor().rgb; snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic; snapshot.backgroundBlurRadius = args.supportsBlur @@ -1069,6 +1070,10 @@ void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot, // touches from going outside the cloned area. if (path.isClone()) { snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE; + // Cloned layers shouldn't handle watch outside since their z order is not determined by + // WM or the client. + snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH); + mNeedsTouchableRegionCrop.insert(path); } } diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index 4dcdd964b3..b397b82a27 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -32,10 +32,6 @@ using ftl::Flags; using namespace ftl::flag_operators; namespace { -std::string layerIdToString(uint32_t layerId) { - return layerId == UNASSIGNED_LAYER_ID ? "none" : std::to_string(layerId); -} - std::string layerIdsToString(const std::vector<uint32_t>& layerIds) { std::stringstream stream; stream << "{"; @@ -326,9 +322,13 @@ ui::Transform RequestedLayerState::getTransform(uint32_t displayRotationFlags) c std::string RequestedLayerState::getDebugString() const { std::stringstream debug; - debug << "RequestedLayerState{" << name << " parent=" << layerIdToString(parentId) - << " relativeParent=" << layerIdToString(relativeParentId) - << " mirrorId=" << layerIdsToString(mirrorIds) << " handle=" << handleAlive << " z=" << z; + debug << "RequestedLayerState{" << name; + if (parentId != UNASSIGNED_LAYER_ID) debug << " parentId=" << parentId; + if (relativeParentId != UNASSIGNED_LAYER_ID) debug << " relativeParentId=" << relativeParentId; + if (!mirrorIds.empty()) debug << " mirrorId=" << layerIdsToString(mirrorIds); + if (!handleAlive) debug << " !handle"; + if (z != 0) debug << " z=" << z; + if (layerStack.id != 0) debug << " layerStack=" << layerStack.id; return debug.str(); } diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp index a209cad612..9cbe0bb224 100644 --- a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp +++ b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp @@ -21,6 +21,7 @@ #include <cutils/trace.h> #include <utils/Log.h> +#include <utils/Trace.h> #include "TransactionHandler.h" @@ -73,12 +74,13 @@ std::vector<TransactionState> TransactionHandler::flushTransactions() { void TransactionHandler::applyUnsignaledBufferTransaction( std::vector<TransactionState>& transactions, TransactionFlushState& flushState) { - // only apply an unsignaled buffer transaction if it's the first one - if (!transactions.empty()) { + if (!flushState.queueWithUnsignaledBuffer) { return; } - if (!flushState.queueWithUnsignaledBuffer) { + // only apply an unsignaled buffer transaction if it's the first one + if (!transactions.empty()) { + ATRACE_NAME("fence unsignaled"); return; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a538c6d6fb..9c232b11a7 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2442,16 +2442,7 @@ WindowInfo Layer::fillInputInfo(const InputDisplayArgs& displayArgs) { info.inputConfig |= WindowInfo::InputConfig::NOT_TOUCHABLE; } - // For compatibility reasons we let layers which can receive input - // receive input before they have actually submitted a buffer. Because - // of this we use canReceiveInput instead of isVisible to check the - // policy-visibility, ignoring the buffer state. However for layers with - // hasInputInfo()==false we can use the real visibility state. - // We are just using these layers for occlusion detection in - // InputDispatcher, and obviously if they aren't visible they can't occlude - // anything. - const bool visible = hasInputInfo() ? canReceiveInput() : isVisible(); - info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible); + info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !isVisibleForInput()); info.alpha = getAlpha(); fillTouchOcclusionMode(info); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index acdd01da77..8d7c362241 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -372,6 +372,21 @@ public: bool canReceiveInput() const; /* + * Whether or not the layer should be considered visible for input calculations. + */ + virtual bool isVisibleForInput() const { + // For compatibility reasons we let layers which can receive input + // receive input before they have actually submitted a buffer. Because + // of this we use canReceiveInput instead of isVisible to check the + // policy-visibility, ignoring the buffer state. However for layers with + // hasInputInfo()==false we can use the real visibility state. + // We are just using these layers for occlusion detection in + // InputDispatcher, and obviously if they aren't visible they can't occlude + // anything. + return hasInputInfo() ? canReceiveInput() : isVisible(); + } + + /* * isProtected - true if the layer may contain protected contents in the * GRALLOC_USAGE_PROTECTED sense. */ diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 5d924852a4..3472d201f3 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -392,7 +392,11 @@ void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, layerInfo->set_id(snapshot.uniqueSequence); layerInfo->set_original_id(snapshot.sequence); - layerInfo->set_name(requestedState.name); + if (!snapshot.path.isClone()) { + layerInfo->set_name(requestedState.name); + } else { + layerInfo->set_name(requestedState.name + "(Mirror)"); + } layerInfo->set_type("Layer"); LayerProtoHelper::writeToProto(requestedState.transparentRegion, diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index ed65bc607d..67e1b9c2ea 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -22,6 +22,7 @@ #include <string> #include <android-base/stringprintf.h> +#include <ftl/algorithm.h> #include <ftl/small_map.h> #include <utils/Timers.h> @@ -82,12 +83,18 @@ public: flushTime(); TotalTimes totalTimes = ftl::init::map("ScreenOff", mScreenOffTime); - const auto zero = std::chrono::milliseconds::zero(); // Sum the times for modes that map to the same name, e.g. "60 Hz". for (const auto& [fps, time] : mFpsTotalTimes) { const auto string = to_string(fps); - const auto total = std::as_const(totalTimes).get(string).value_or(std::cref(zero)); + const auto total = std::as_const(totalTimes) + .get(string) + .or_else(ftl::static_ref<std::chrono::milliseconds>([] { + using namespace std::chrono_literals; + return 0ms; + })) + .value(); + totalTimes.emplace_or_replace(string, total.get() + time); } @@ -114,15 +121,18 @@ private: mPreviousRecordedTime = currentTime; const auto duration = std::chrono::milliseconds{ns2ms(timeElapsed)}; - const auto zero = std::chrono::milliseconds::zero(); - uint32_t fps = 0; if (mCurrentPowerMode == PowerMode::ON) { // Normal power mode is counted under different config modes. const auto total = std::as_const(mFpsTotalTimes) .get(mCurrentRefreshRate) - .value_or(std::cref(zero)); + .or_else(ftl::static_ref<std::chrono::milliseconds>([] { + using namespace std::chrono_literals; + return 0ms; + })) + .value(); + mFpsTotalTimes.emplace_or_replace(mCurrentRefreshRate, total.get() + duration); fps = static_cast<uint32_t>(mCurrentRefreshRate.getIntValue()); diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 3423652163..1f6d378d5a 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -32,6 +32,7 @@ #include <ui/GraphicTypes.h> #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" +#include <ftl/algorithm.h> #include <ftl/fake_guard.h> #include <ftl/optional.h> #include <scheduler/Features.h> @@ -436,13 +437,13 @@ private: RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) { ftl::FakeGuard guard(kMainThreadContext); - const RefreshRateSelectorPtr noPacesetter; return mPacesetterDisplayId .and_then([this](PhysicalDisplayId pacesetterId) REQUIRES(mDisplayLock, kMainThreadContext) { return mRefreshRateSelectors.get(pacesetterId); }) - .value_or(std::cref(noPacesetter)); + .or_else(ftl::static_ref<RefreshRateSelectorPtr>([] { return nullptr; })) + .value(); } std::shared_ptr<const VsyncSchedule> getVsyncScheduleLocked( diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 38bde2b173..38f8db0945 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3715,17 +3715,33 @@ void SurfaceFlinger::updateInputFlinger() { return; } + std::unordered_set<Layer*> visibleLayers; + mDrawingState.traverse([&visibleLayers](Layer* layer) { + if (layer->isVisibleForInput()) { + visibleLayers.insert(layer); + } + }); + bool visibleLayersChanged = false; + if (visibleLayers != mVisibleLayers) { + visibleLayersChanged = true; + mVisibleLayers = std::move(visibleLayers); + } + BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo, windowInfos = std::move(windowInfos), displayInfos = std::move(displayInfos), inputWindowCommands = std::move(mInputWindowCommands), - inputFlinger = mInputFlinger, this]() { + inputFlinger = mInputFlinger, this, + visibleLayersChanged]() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker - ->windowInfosChanged(windowInfos, displayInfos, - inputWindowCommands.windowInfosReportedListeners); + ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos), + std::move( + inputWindowCommands.windowInfosReportedListeners), + /* forceImmediateCall= */ visibleLayersChanged || + !inputWindowCommands.focusRequests.empty()); } else { // If there are listeners but no changes to input windows, call the listeners // immediately. @@ -4187,20 +4203,20 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyTimelin const TransactionHandler::TransactionFlushState& flushState) { using TransactionReadiness = TransactionHandler::TransactionReadiness; const auto& transaction = *flushState.transaction; - ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, - transaction.frameTimelineInfo.vsyncId); TimePoint desiredPresentTime = TimePoint::fromNs(transaction.desiredPresentTime); // Do not present if the desiredPresentTime has not passed unless it is more than // one second in the future. We ignore timestamps more than 1 second in the future // for stability reasons. if (!transaction.isAutoTimestamp && desiredPresentTime >= mExpectedPresentTime && desiredPresentTime < mExpectedPresentTime + 1s) { - ATRACE_NAME("not current"); + ATRACE_FORMAT("not current desiredPresentTime: %" PRId64 " expectedPresentTime: %" PRId64, + desiredPresentTime, mExpectedPresentTime); return TransactionReadiness::NotReady; } if (!mScheduler->isVsyncValid(mExpectedPresentTime, transaction.originUid)) { - ATRACE_NAME("!isVsyncValid"); + ATRACE_FORMAT("!isVsyncValid expectedPresentTime: %" PRId64 " uid: %d", + mExpectedPresentTime, transaction.originUid); return TransactionReadiness::NotReady; } @@ -4208,7 +4224,8 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyTimelin // expected present time of this transaction. if (transaction.isAutoTimestamp && frameIsEarly(mExpectedPresentTime, VsyncId{transaction.frameTimelineInfo.vsyncId})) { - ATRACE_NAME("frameIsEarly"); + ATRACE_FORMAT("frameIsEarly vsyncId: %" PRId64 " expectedPresentTime: %" PRId64, + transaction.frameTimelineInfo.vsyncId, mExpectedPresentTime); return TransactionReadiness::NotReady; } return TransactionReadiness::Ready; @@ -4238,7 +4255,9 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC s.bufferData->acquireFence); // Delete the entire state at this point and not just release the buffer because // everything associated with the Layer in this Transaction is now out of date. - ATRACE_NAME("DeleteStaleBuffer"); + ATRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d", + layer->getDebugName(), layer->getDrawingState().barrierProducerId, + s.bufferData->producerId); return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL; } @@ -4248,7 +4267,10 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC ((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >= s.bufferData->barrierFrameNumber)); if (!willApplyBarrierFrame) { - ATRACE_NAME("NotReadyBarrier"); + ATRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 " > %" PRId64, + layer->getDebugName(), + layer->getDrawingState().barrierFrameNumber, + s.bufferData->barrierFrameNumber); ready = TransactionReadiness::NotReadyBarrier; return TraverseBuffersReturnValues::STOP_TRAVERSAL; } @@ -4260,7 +4282,7 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC const bool hasPendingBuffer = flushState.bufferLayersReadyToPresent.contains(s.surface.get()); if (layer->backpressureEnabled() && hasPendingBuffer && transaction.isAutoTimestamp) { - ATRACE_NAME("hasPendingBuffer"); + ATRACE_FORMAT("hasPendingBuffer %s", layer->getDebugName()); ready = TransactionReadiness::NotReady; return TraverseBuffersReturnValues::STOP_TRAVERSAL; } @@ -4277,9 +4299,9 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC const bool allowLatchUnsignaled = shouldLatchUnsignaled(layer, s, transaction.states.size(), flushState.firstTransaction); - ATRACE_FORMAT("%s allowLatchUnsignaled=%s", layer->getName().c_str(), - allowLatchUnsignaled ? "true" : "false"); if (allowLatchUnsignaled) { + ATRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s", + layer->getDebugName()); ready = TransactionReadiness::NotReadyUnsignaled; } else { ready = TransactionReadiness::NotReady; @@ -4292,12 +4314,12 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC "Buffer processing hung up due to stuck " "fence. Indicates GPU hang"); } + ATRACE_FORMAT("fence unsignaled %s", layer->getDebugName()); return TraverseBuffersReturnValues::STOP_TRAVERSAL; } } return TraverseBuffersReturnValues::CONTINUE_TRAVERSAL; }); - ATRACE_INT("TransactionReadiness", static_cast<int>(ready)); return ready; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5783c8dc58..04fcfb9097 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -28,6 +28,7 @@ #include <android/gui/ISurfaceComposerClient.h> #include <cutils/atomic.h> #include <cutils/compiler.h> +#include <ftl/algorithm.h> #include <ftl/future.h> #include <ftl/non_null.h> #include <gui/BufferQueue.h> @@ -499,7 +500,7 @@ private: // Implements ISurfaceComposer sp<IBinder> createDisplay(const String8& displayName, bool secure, - float requestedRefreshRate = 0); + float requestedRefreshRate = 0.0f); void destroyDisplay(const sp<IBinder>& displayToken); std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const EXCLUDES(mStateLock) { Mutex::Autolock lock(mStateLock); @@ -854,8 +855,9 @@ private: } sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) REQUIRES(mStateLock) { - const sp<DisplayDevice> nullDisplay; - return mDisplays.get(displayToken).value_or(std::cref(nullDisplay)); + return mDisplays.get(displayToken) + .or_else(ftl::static_ref<sp<DisplayDevice>>([] { return nullptr; })) + .value(); } sp<const DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) const @@ -1011,10 +1013,10 @@ private: */ sp<display::DisplayToken> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const REQUIRES(mStateLock) { - const sp<display::DisplayToken> nullToken; return mPhysicalDisplays.get(displayId) .transform([](const display::PhysicalDisplay& display) { return display.token(); }) - .value_or(std::cref(nullToken)); + .or_else([] { return std::optional<sp<display::DisplayToken>>(nullptr); }) + .value(); } std::optional<PhysicalDisplayId> getPhysicalDisplayIdLocked( @@ -1424,6 +1426,11 @@ private: TransactionHandler mTransactionHandler; display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> mFrontEndDisplayInfos; bool mFrontEndDisplayInfosChanged = false; + + // Layers visible during the last commit. This set should only be used for testing set equality + // and membership. The pointers should not be dereferenced as it's possible the set contains + // pointers to freed layers. + std::unordered_set<Layer*> mVisibleLayers; }; class SurfaceComposerAIDL : public gui::BnSurfaceComposer { diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp index 292083b9bc..856fbbbf33 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -25,20 +25,17 @@ using gui::DisplayInfo; using gui::IWindowInfosListener; using gui::WindowInfo; -struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowInfosReportedListener, - DeathRecipient { - explicit WindowInfosReportedListener( - size_t callbackCount, - const std::unordered_set<sp<gui::IWindowInfosReportedListener>, - SpHash<gui::IWindowInfosReportedListener>>& - windowInfosReportedListeners) - : mCallbacksPending(callbackCount), - mWindowInfosReportedListeners(windowInfosReportedListeners) {} +using WindowInfosListenerVector = ftl::SmallVector<const sp<IWindowInfosListener>, 3>; + +struct WindowInfosReportedListenerInvoker : gui::BnWindowInfosReportedListener, + IBinder::DeathRecipient { + WindowInfosReportedListenerInvoker(WindowInfosListenerVector windowInfosListeners, + WindowInfosReportedListenerSet windowInfosReportedListeners) + : mCallbacksPending(windowInfosListeners.size()), + mWindowInfosListeners(std::move(windowInfosListeners)), + mWindowInfosReportedListeners(std::move(windowInfosReportedListeners)) {} binder::Status onWindowInfosReported() override { - // TODO(b/222421815) There could potentially be callbacks that we don't need to wait for - // before calling the WindowInfosReportedListeners coming from InputWindowCommands. Filter - // the list of callbacks down to those from system server. if (--mCallbacksPending == 0) { for (const auto& listener : mWindowInfosReportedListeners) { sp<IBinder> asBinder = IInterface::asBinder(listener); @@ -46,6 +43,12 @@ struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowIn listener->onWindowInfosReported(); } } + + auto wpThis = wp<WindowInfosReportedListenerInvoker>::fromExisting(this); + for (const auto& listener : mWindowInfosListeners) { + sp<IBinder> binder = IInterface::asBinder(listener); + binder->unlinkToDeath(wpThis); + } } return binder::Status::ok(); } @@ -54,9 +57,9 @@ struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowIn private: std::atomic<size_t> mCallbacksPending; - std::unordered_set<sp<gui::IWindowInfosReportedListener>, - SpHash<gui::IWindowInfosReportedListener>> - mWindowInfosReportedListeners; + static constexpr size_t kStaticCapacity = 3; + const WindowInfosListenerVector mWindowInfosListeners; + WindowInfosReportedListenerSet mWindowInfosReportedListeners; }; void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) { @@ -82,38 +85,81 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { } void WindowInfosListenerInvoker::windowInfosChanged( - const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos, - const std::unordered_set<sp<gui::IWindowInfosReportedListener>, - SpHash<gui::IWindowInfosReportedListener>>& - windowInfosReportedListeners) { - ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; + std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, + WindowInfosReportedListenerSet reportedListeners, bool forceImmediateCall) { + reportedListeners.insert(sp<WindowInfosListenerInvoker>::fromExisting(this)); + auto callListeners = [this, windowInfos = std::move(windowInfos), + displayInfos = std::move(displayInfos)]( + WindowInfosReportedListenerSet reportedListeners) mutable { + WindowInfosListenerVector windowInfosListeners; + { + std::scoped_lock lock(mListenersMutex); + for (const auto& [_, listener] : mWindowInfosListeners) { + windowInfosListeners.push_back(listener); + } + } + + auto reportedInvoker = + sp<WindowInfosReportedListenerInvoker>::make(windowInfosListeners, + std::move(reportedListeners)); + + for (const auto& listener : windowInfosListeners) { + sp<IBinder> asBinder = IInterface::asBinder(listener); + + // linkToDeath is used here to ensure that the windowInfosReportedListeners + // are called even if one of the windowInfosListeners dies before + // calling onWindowInfosReported. + asBinder->linkToDeath(reportedInvoker); + + auto status = + listener->onWindowInfosChanged(windowInfos, displayInfos, reportedInvoker); + if (!status.isOk()) { + reportedInvoker->onWindowInfosReported(); + } + } + }; + { - std::scoped_lock lock(mListenersMutex); - for (const auto& [_, listener] : mWindowInfosListeners) { - windowInfosListeners.push_back(listener); + std::scoped_lock lock(mMessagesMutex); + // If there are unacked messages and this isn't a forced call, then return immediately. + // If a forced window infos change doesn't happen first, the update will be sent after + // the WindowInfosReportedListeners are called. If a forced window infos change happens or + // if there are subsequent delayed messages before this update is sent, then this message + // will be dropped and the listeners will only be called with the latest info. This is done + // to reduce the amount of binder memory used. + if (mActiveMessageCount > 0 && !forceImmediateCall) { + mWindowInfosChangedDelayed = std::move(callListeners); + mReportedListenersDelayed.merge(reportedListeners); + return; } + + mWindowInfosChangedDelayed = nullptr; + reportedListeners.merge(mReportedListenersDelayed); + mActiveMessageCount++; } + callListeners(std::move(reportedListeners)); +} - auto windowInfosReportedListener = windowInfosReportedListeners.empty() - ? nullptr - : sp<WindowInfosReportedListener>::make(windowInfosListeners.size(), - windowInfosReportedListeners); - for (const auto& listener : windowInfosListeners) { - sp<IBinder> asBinder = IInterface::asBinder(listener); - - // linkToDeath is used here to ensure that the windowInfosReportedListeners - // are called even if one of the windowInfosListeners dies before - // calling onWindowInfosReported. - if (windowInfosReportedListener) { - asBinder->linkToDeath(windowInfosReportedListener); - } +binder::Status WindowInfosListenerInvoker::onWindowInfosReported() { + std::function<void(WindowInfosReportedListenerSet)> callListeners; + WindowInfosReportedListenerSet reportedListeners; - auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, - windowInfosReportedListener); - if (windowInfosReportedListener && !status.isOk()) { - windowInfosReportedListener->onWindowInfosReported(); + { + std::scoped_lock lock{mMessagesMutex}; + mActiveMessageCount--; + if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) { + return binder::Status::ok(); } + + mActiveMessageCount++; + callListeners = std::move(mWindowInfosChangedDelayed); + mWindowInfosChangedDelayed = nullptr; + reportedListeners = std::move(mReportedListenersDelayed); + mReportedListenersDelayed.clear(); } + + callListeners(std::move(reportedListeners)); + return binder::Status::ok(); } } // namespace android diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h index d60a9c4157..4da98282a9 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.h +++ b/services/surfaceflinger/WindowInfosListenerInvoker.h @@ -23,34 +23,42 @@ #include <android/gui/IWindowInfosReportedListener.h> #include <binder/IBinder.h> #include <ftl/small_map.h> +#include <gui/SpHash.h> #include <utils/Mutex.h> namespace android { -class SurfaceFlinger; +using WindowInfosReportedListenerSet = + std::unordered_set<sp<gui::IWindowInfosReportedListener>, + gui::SpHash<gui::IWindowInfosReportedListener>>; -class WindowInfosListenerInvoker : public IBinder::DeathRecipient { +class WindowInfosListenerInvoker : public gui::BnWindowInfosReportedListener, + public IBinder::DeathRecipient { public: void addWindowInfosListener(sp<gui::IWindowInfosListener>); void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); - void windowInfosChanged(const std::vector<gui::WindowInfo>&, - const std::vector<gui::DisplayInfo>&, - const std::unordered_set<sp<gui::IWindowInfosReportedListener>, - SpHash<gui::IWindowInfosReportedListener>>& - windowInfosReportedListeners); + void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>, + WindowInfosReportedListenerSet windowInfosReportedListeners, + bool forceImmediateCall); + + binder::Status onWindowInfosReported() override; protected: void binderDied(const wp<IBinder>& who) override; private: - struct WindowInfosReportedListener; - std::mutex mListenersMutex; static constexpr size_t kStaticCapacity = 3; ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); + + std::mutex mMessagesMutex; + uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0; + std::function<void(WindowInfosReportedListenerSet)> mWindowInfosChangedDelayed + GUARDED_BY(mMessagesMutex); + WindowInfosReportedListenerSet mReportedListenersDelayed; }; } // namespace android diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp index ddf3363244..e4f49e863b 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp @@ -466,7 +466,8 @@ TEST_F(LayerHierarchyTest, backgroundLayersAreBehindParentLayer) { updateBackgroundColor(1, 0.5); UPDATE_AND_VERIFY(hierarchyBuilder); - auto bgLayerId = LayerCreationArgs::getInternalLayerId(1); + auto hierarchy = hierarchyBuilder.getPartialHierarchy(1, /*childrenOnly=*/true); + auto bgLayerId = hierarchy.mChildren.front().first->getLayer()->id; std::vector<uint32_t> expectedTraversalPath = {1, bgLayerId, 11, 111, 12, 121, 122, 1221, 13, 2}; EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath); @@ -662,10 +663,9 @@ TEST_F(LayerHierarchyTest, zorderRespectsLayerStack) { mLifecycleManager.commitChanges(); LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers()); UPDATE_AND_VERIFY(hierarchyBuilder); - std::vector<uint32_t> expectedTraversalPath = {1, 11, 2, 21}; + std::vector<uint32_t> expectedTraversalPath = {2, 21, 1, 11}; EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath); - expectedTraversalPath = {1, 11, 2, 21}; EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath); expectedTraversalPath = {}; EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath); @@ -678,8 +678,8 @@ TEST_F(LayerHierarchyTest, canMirrorDisplay) { setLayerStack(3, 1); UPDATE_AND_VERIFY(hierarchyBuilder); - std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2, - 1, 11, 111, 12, 121, 122, 1221, 13, 2}; + std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3, + 1, 11, 111, 12, 121, 122, 1221, 13, 2}; EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected); EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected); expected = {}; @@ -693,7 +693,7 @@ TEST_F(LayerHierarchyTest, mirrorNonExistingDisplay) { setLayerStack(3, 1); UPDATE_AND_VERIFY(hierarchyBuilder); - std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2}; + std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3}; EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected); EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected); expected = {}; @@ -710,8 +710,8 @@ TEST_F(LayerHierarchyTest, newRootLayerIsMirrored) { createRootLayer(4); UPDATE_AND_VERIFY(hierarchyBuilder); - std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2, 4, - 1, 11, 111, 12, 121, 122, 1221, 13, 2, 4}; + std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 4, 3, + 1, 11, 111, 12, 121, 122, 1221, 13, 2, 4}; EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected); EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected); expected = {}; @@ -729,7 +729,7 @@ TEST_F(LayerHierarchyTest, removedRootLayerIsNoLongerMirrored) { destroyLayerHandle(1); UPDATE_AND_VERIFY(hierarchyBuilder); - std::vector<uint32_t> expected = {3, 2, 2}; + std::vector<uint32_t> expected = {2, 3, 2}; EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected); EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected); expected = {11, 111, 12, 121, 122, 1221, 13}; diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h index 79cfd6a891..43011863ff 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h @@ -297,6 +297,17 @@ protected: mLifecycleManager.applyTransactions(transactions); } + void setBackgroundBlurRadius(uint32_t id, uint32_t backgroundBlurRadius) { + std::vector<TransactionState> transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + + transactions.back().states.front().state.what = layer_state_t::eBackgroundBlurRadiusChanged; + transactions.back().states.front().layerId = id; + transactions.back().states.front().state.backgroundBlurRadius = backgroundBlurRadius; + mLifecycleManager.applyTransactions(transactions); + } + LayerLifecycleManager mLifecycleManager; }; diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp index 14b8e4bbac..97ef5a268d 100644 --- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp @@ -36,13 +36,13 @@ namespace android::surfaceflinger::frontend { class ExpectLayerLifecycleListener : public LayerLifecycleManager::ILifecycleListener { public: void onLayerAdded(const RequestedLayerState& layer) override { - mActualLayersAdded.emplace(layer.id); + mActualLayersAdded.push_back(layer.id); }; void onLayerDestroyed(const RequestedLayerState& layer) override { mActualLayersDestroyed.emplace(layer.id); }; - void expectLayersAdded(const std::unordered_set<uint32_t>& expectedLayersAdded) { + void expectLayersAdded(const std::vector<uint32_t>& expectedLayersAdded) { EXPECT_EQ(expectedLayersAdded, mActualLayersAdded); mActualLayersAdded.clear(); } @@ -51,7 +51,7 @@ public: mActualLayersDestroyed.clear(); } - std::unordered_set<uint32_t> mActualLayersAdded; + std::vector<uint32_t> mActualLayersAdded; std::unordered_set<uint32_t> mActualLayersDestroyed; }; @@ -318,7 +318,8 @@ TEST_F(LayerLifecycleManagerTest, canAddBackgroundLayer) { EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)); lifecycleManager.commitChanges(); - auto bgLayerId = LayerCreationArgs::getInternalLayerId(1); + ASSERT_EQ(listener->mActualLayersAdded.size(), 2u); + auto bgLayerId = listener->mActualLayersAdded[1]; listener->expectLayersAdded({1, bgLayerId}); listener->expectLayersDestroyed({}); EXPECT_EQ(getRequestedLayerState(lifecycleManager, bgLayerId)->color.a, 0.5_hf); @@ -352,7 +353,8 @@ TEST_F(LayerLifecycleManagerTest, canDestroyBackgroundLayer) { EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)); lifecycleManager.commitChanges(); - auto bgLayerId = LayerCreationArgs::getInternalLayerId(1); + ASSERT_EQ(listener->mActualLayersAdded.size(), 2u); + auto bgLayerId = listener->mActualLayersAdded[1]; listener->expectLayersAdded({1, bgLayerId}); listener->expectLayersDestroyed({bgLayerId}); } @@ -381,7 +383,8 @@ TEST_F(LayerLifecycleManagerTest, onParentDestroyDestroysBackgroundLayer) { EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)); lifecycleManager.commitChanges(); - auto bgLayerId = LayerCreationArgs::getInternalLayerId(1); + ASSERT_EQ(listener->mActualLayersAdded.size(), 2u); + auto bgLayerId = listener->mActualLayersAdded[1]; listener->expectLayersAdded({1, bgLayerId}); listener->expectLayersDestroyed({1, bgLayerId}); } diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 5a066a6482..b8a7446b3a 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -79,6 +79,7 @@ protected: .displays = mFrontEndDisplayInfos, .displayChanges = hasDisplayChanges, .globalShadowSettings = globalShadowSettings, + .supportsBlur = true, .supportedLayerGenericMetadata = {}, .genericLayerMetadataKeyMap = {}}; actualBuilder.update(args); @@ -333,6 +334,19 @@ TEST_F(LayerSnapshotTest, canCropTouchableRegion) { EXPECT_EQ(getSnapshot({.id = 111})->inputInfo.touchableRegion.bounds(), modifiedTouchCrop); } +TEST_F(LayerSnapshotTest, blurUpdatesWhenAlphaChanges) { + static constexpr int blurRadius = 42; + setBackgroundBlurRadius(1221, blurRadius); + + UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + EXPECT_EQ(getSnapshot({.id = 1221})->backgroundBlurRadius, blurRadius); + + static constexpr float alpha = 0.5; + setAlpha(12, alpha); + UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + EXPECT_EQ(getSnapshot({.id = 1221})->backgroundBlurRadius, blurRadius * alpha); +} + // Display Mirroring Tests // tree with 3 levels of children // ROOT (DISPLAY 0) @@ -352,7 +366,7 @@ TEST_F(LayerSnapshotTest, displayMirrorRespectsLayerSkipScreenshotFlag) { createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0)); setLayerStack(3, 1); - std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 12, 121, 122, 1221, 13, 2}; + std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3, 1, 11, 111, 13, 2}; UPDATE_AND_VERIFY(mSnapshotBuilder, expected); } @@ -371,8 +385,8 @@ TEST_F(LayerSnapshotTest, mirrorLayerGetsCorrectLayerStack) { createDisplayMirrorLayer(4, ui::LayerStack::fromValue(0)); setLayerStack(4, 4); - std::vector<uint32_t> expected = {4, 1, 11, 111, 13, 2, 3, 1, 11, - 111, 13, 2, 1, 11, 111, 13, 2}; + std::vector<uint32_t> expected = {1, 11, 111, 13, 2, 3, 1, 11, 111, + 13, 2, 4, 1, 11, 111, 13, 2}; UPDATE_AND_VERIFY(mSnapshotBuilder, expected); EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 3})->outputFilter.layerStack.id, 3u); EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 4})->outputFilter.layerStack.id, 4u); @@ -395,7 +409,7 @@ TEST_F(LayerSnapshotTest, mirrorLayerTouchIsCroppedByMirrorRoot) { setCrop(111, Rect{200, 200}); Region touch{Rect{0, 0, 1000, 1000}}; setTouchableRegion(111, touch); - std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 13, 2}; + std::vector<uint32_t> expected = {1, 11, 111, 13, 2, 3, 1, 11, 111, 13, 2}; UPDATE_AND_VERIFY(mSnapshotBuilder, expected); EXPECT_TRUE(getSnapshot({.id = 111})->inputInfo.touchableRegion.hasSameRects(touch)); Region touchCroppedByMirrorRoot{Rect{0, 0, 50, 50}}; @@ -407,7 +421,7 @@ TEST_F(LayerSnapshotTest, canRemoveDisplayMirror) { setFlags(12, layer_state_t::eLayerSkipScreenshot, layer_state_t::eLayerSkipScreenshot); createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0)); setLayerStack(3, 1); - std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 12, 121, 122, 1221, 13, 2}; + std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3, 1, 11, 111, 13, 2}; UPDATE_AND_VERIFY(mSnapshotBuilder, expected); destroyLayerHandle(3); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); @@ -417,8 +431,8 @@ TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterMirroring) { size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size(); createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0)); setLayerStack(3, 1); - std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2, - 1, 11, 111, 12, 121, 122, 1221, 13, 2}; + std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3, + 1, 11, 111, 12, 121, 122, 1221, 13, 2}; UPDATE_AND_VERIFY(mSnapshotBuilder, expected); destroyLayerHandle(3); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp index 6a9c970bc3..1cc9ba40bd 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp @@ -17,12 +17,60 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" +#include <scheduler/Fps.h> + #include "DisplayTransactionTestHelpers.h" +#include "FpsOps.h" namespace android { namespace { -class CreateDisplayTest : public DisplayTransactionTest {}; +class CreateDisplayTest : public DisplayTransactionTest { +public: + void createDisplayWithRequestedRefreshRate(const String8& name, uint64_t displayId, + float pacesetterDisplayRefreshRate, + float requestedRefreshRate, + float expectedAdjustedRefreshRate) { + // -------------------------------------------------------------------- + // Call Expectations + + // -------------------------------------------------------------------- + // Invocation + + sp<IBinder> displayToken = mFlinger.createDisplay(name, false, requestedRefreshRate); + + // -------------------------------------------------------------------- + // Postconditions + + // The display should have been added to the current state + ASSERT_TRUE(hasCurrentDisplayState(displayToken)); + const auto& display = getCurrentDisplayState(displayToken); + EXPECT_TRUE(display.isVirtual()); + EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate)); + EXPECT_EQ(name.string(), display.displayName); + + std::optional<VirtualDisplayId> vid = + DisplayId::fromValue<VirtualDisplayId>(displayId | DisplayId::FLAG_VIRTUAL); + ASSERT_TRUE(vid.has_value()); + + sp<DisplayDevice> device = + mFlinger.createVirtualDisplayDevice(displayToken, *vid, requestedRefreshRate); + EXPECT_TRUE(device->isVirtual()); + device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate)); + // verifying desired value + EXPECT_EQ(device->getAdjustedRefreshRate(), Fps::fromValue(expectedAdjustedRefreshRate)); + // verifying rounding up + if (requestedRefreshRate < pacesetterDisplayRefreshRate) { + EXPECT_GE(device->getAdjustedRefreshRate(), Fps::fromValue(requestedRefreshRate)); + } else { + EXPECT_EQ(device->getAdjustedRefreshRate(), + Fps::fromValue(pacesetterDisplayRefreshRate)); + } + + // -------------------------------------------------------------------- + // Cleanup conditions + } +}; TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForNonsecureDisplay) { const String8 name("virtual.test"); @@ -84,5 +132,82 @@ TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) { EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); } +// Requesting 0 tells SF not to do anything, i.e., default to refresh as physical displays +TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRate0) { + const String8 displayName("virtual.test"); + const uint64_t displayId = 123ull; + const float kPacesetterDisplayRefreshRate = 60.f; + const float kRequestedRefreshRate = 0.f; + const float kExpectedAdjustedRefreshRate = 0.f; + createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, + kRequestedRefreshRate, kExpectedAdjustedRefreshRate); +} + +// Requesting negative refresh rate, will be ignored, same as requesting 0 +TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNegative) { + const String8 displayName("virtual.test"); + const uint64_t displayId = 123ull; + const float kPacesetterDisplayRefreshRate = 60.f; + const float kRequestedRefreshRate = -60.f; + const float kExpectedAdjustedRefreshRate = 0.f; + createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, + kRequestedRefreshRate, kExpectedAdjustedRefreshRate); +} + +// Requesting a higher refresh rate than the pacesetter +TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateHigh) { + const String8 displayName("virtual.test"); + const uint64_t displayId = 123ull; + const float kPacesetterDisplayRefreshRate = 60.f; + const float kRequestedRefreshRate = 90.f; + const float kExpectedAdjustedRefreshRate = 60.f; + createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, + kRequestedRefreshRate, kExpectedAdjustedRefreshRate); +} + +// Requesting the same refresh rate as the pacesetter +TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateSame) { + const String8 displayName("virtual.test"); + const uint64_t displayId = 123ull; + const float kPacesetterDisplayRefreshRate = 60.f; + const float kRequestedRefreshRate = 60.f; + const float kExpectedAdjustedRefreshRate = 60.f; + createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, + kRequestedRefreshRate, kExpectedAdjustedRefreshRate); +} + +// Requesting a divisor (30) of the pacesetter (60) should be honored +TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateDivisor) { + const String8 displayName("virtual.test"); + const uint64_t displayId = 123ull; + const float kPacesetterDisplayRefreshRate = 60.f; + const float kRequestedRefreshRate = 30.f; + const float kExpectedAdjustedRefreshRate = 30.f; + createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, + kRequestedRefreshRate, kExpectedAdjustedRefreshRate); +} + +// Requesting a non divisor (45) of the pacesetter (120) should round up to a divisor (60) +TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisor) { + const String8 displayName("virtual.test"); + const uint64_t displayId = 123ull; + const float kPacesetterDisplayRefreshRate = 120.f; + const float kRequestedRefreshRate = 45.f; + const float kExpectedAdjustedRefreshRate = 60.f; + createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, + kRequestedRefreshRate, kExpectedAdjustedRefreshRate); +} + +// Requesting a non divisor (75) of the pacesetter (120) should round up to pacesetter (120) +TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisorMax) { + const String8 displayName("virtual.test"); + const uint64_t displayId = 123ull; + const float kPacesetterDisplayRefreshRate = 120.f; + const float kRequestedRefreshRate = 75.f; + const float kExpectedAdjustedRefreshRate = 120.f; + createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate, + kRequestedRefreshRate, kExpectedAdjustedRefreshRate); +} + } // namespace } // namespace android diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 6f48df8be2..cfa366f803 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -48,10 +48,12 @@ #include "TestableScheduler.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/DisplayHardware/MockDisplayMode.h" +#include "mock/DisplayHardware/MockPowerAdvisor.h" #include "mock/MockEventThread.h" #include "mock/MockFrameTimeline.h" #include "mock/MockFrameTracer.h" #include "mock/MockSchedulerCallback.h" +#include "mock/system/window/MockNativeWindow.h" namespace android { namespace renderengine { @@ -375,8 +377,8 @@ public: void commitAndComposite() { mFlinger->composite(commit(), kVsyncId); } - auto createDisplay(const String8& displayName, bool secure) { - return mFlinger->createDisplay(displayName, secure); + auto createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0.0f) { + return mFlinger->createDisplay(displayName, secure, requestedRefreshRate); } auto destroyDisplay(const sp<IBinder>& displayToken) { @@ -525,6 +527,24 @@ public: mFlinger->getDynamicDisplayInfoFromToken(displayToken, dynamicDisplayInfo); } + sp<DisplayDevice> createVirtualDisplayDevice(const sp<IBinder> displayToken, + VirtualDisplayId displayId, + float requestedRefreshRate) { + constexpr ui::Size kResolution = {1080, 1920}; + auto compositionDisplay = compositionengine::impl:: + createDisplay(mFlinger->getCompositionEngine(), + compositionengine::DisplayCreationArgsBuilder() + .setId(displayId) + .setPixels(kResolution) + .setPowerAdvisor(&mPowerAdvisor) + .build()); + DisplayDeviceCreationArgs creationArgs(mFlinger, mFlinger->getHwComposer(), displayToken, + compositionDisplay); + creationArgs.requestedRefreshRate = Fps::fromValue(requestedRefreshRate); + creationArgs.nativeWindow = sp<mock::NativeWindow>::make(); + return sp<DisplayDevice>::make(creationArgs); + } + /* ------------------------------------------------------------------------ * Read-only access to private data to assert post-conditions. */ @@ -962,6 +982,7 @@ private: scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback; std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager; scheduler::TestableScheduler* mScheduler = nullptr; + Hwc2::mock::PowerAdvisor mPowerAdvisor; }; } // namespace android diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index dec3b20831..5965953b38 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -227,6 +227,10 @@ struct Surface { android::sp<ANativeWindow> window; VkSwapchainKHR swapchain_handle; uint64_t consumer_usage; + + // Indicate whether this surface has been used by a swapchain, no matter the + // swapchain is still current or has been destroyed. + bool used_by_swapchain; }; VkSurfaceKHR HandleFromSurface(Surface* surface) { @@ -252,27 +256,31 @@ struct Swapchain { Swapchain(Surface& surface_, uint32_t num_images_, VkPresentModeKHR present_mode, - int pre_transform_) + int pre_transform_, + int64_t refresh_duration_) : surface(surface_), num_images(num_images_), mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR), pre_transform(pre_transform_), frame_timestamps_enabled(false), + refresh_duration(refresh_duration_), acquire_next_image_timeout(-1), shared(IsSharedPresentMode(present_mode)) { - ANativeWindow* window = surface.window.get(); - native_window_get_refresh_cycle_duration( - window, - &refresh_duration); } - uint64_t get_refresh_duration() + + VkResult get_refresh_duration(uint64_t& outRefreshDuration) { ANativeWindow* window = surface.window.get(); - native_window_get_refresh_cycle_duration( + int err = native_window_get_refresh_cycle_duration( window, &refresh_duration); - return static_cast<uint64_t>(refresh_duration); - + if (err != android::OK) { + ALOGE("%s:native_window_get_refresh_cycle_duration failed: %s (%d)", + __func__, strerror(-err), err ); + return VK_ERROR_SURFACE_LOST_KHR; + } + outRefreshDuration = refresh_duration; + return VK_SUCCESS; } Surface& surface; @@ -597,6 +605,7 @@ VkResult CreateAndroidSurfaceKHR( surface->window = pCreateInfo->window; surface->swapchain_handle = VK_NULL_HANDLE; + surface->used_by_swapchain = false; int err = native_window_get_consumer_usage(surface->window.get(), &surface->consumer_usage); if (err != android::OK) { @@ -1390,14 +1399,20 @@ VkResult CreateSwapchainKHR(VkDevice device, // orphans the previous buffers, getting us back to the state where we can // dequeue all buffers. // + // This is not necessary if the surface was never used previously. + // // TODO(http://b/134186185) recycle swapchain images more efficiently ANativeWindow* window = surface.window.get(); - err = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); - ALOGW_IF(err != android::OK, "native_window_api_disconnect failed: %s (%d)", - strerror(-err), err); - err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); - ALOGW_IF(err != android::OK, "native_window_api_connect failed: %s (%d)", - strerror(-err), err); + if (surface.used_by_swapchain) { + err = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); + ALOGW_IF(err != android::OK, + "native_window_api_disconnect failed: %s (%d)", strerror(-err), + err); + err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); + ALOGW_IF(err != android::OK, + "native_window_api_connect failed: %s (%d)", strerror(-err), + err); + } err = window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, nsecs_t{-1}); @@ -1626,6 +1641,13 @@ VkResult CreateSwapchainKHR(VkDevice device, return VK_ERROR_SURFACE_LOST_KHR; } + int64_t refresh_duration; + err = native_window_get_refresh_cycle_duration(window, &refresh_duration); + if (err != android::OK) { + ALOGE("native_window_get_refresh_cycle_duration query failed: %s (%d)", + strerror(-err), err); + return VK_ERROR_SURFACE_LOST_KHR; + } // -- Allocate our Swapchain object -- // After this point, we must deallocate the swapchain on error. @@ -1636,8 +1658,8 @@ VkResult CreateSwapchainKHR(VkDevice device, return VK_ERROR_OUT_OF_HOST_MEMORY; Swapchain* swapchain = new (mem) Swapchain(surface, num_images, create_info->presentMode, - TranslateVulkanToNativeTransform(create_info->preTransform)); - + TranslateVulkanToNativeTransform(create_info->preTransform), + refresh_duration); VkSwapchainImageCreateInfoANDROID swapchain_image_create = { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wold-style-cast" @@ -1776,6 +1798,7 @@ VkResult CreateSwapchainKHR(VkDevice device, android::GraphicsEnv::getInstance().setTargetStats( android::GpuStatsInfo::Stats::CREATED_VULKAN_SWAPCHAIN); + surface.used_by_swapchain = true; surface.swapchain_handle = HandleFromSwapchain(swapchain); *swapchain_handle = surface.swapchain_handle; return VK_SUCCESS; @@ -2308,9 +2331,7 @@ VkResult GetRefreshCycleDurationGOOGLE( ATRACE_CALL(); Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); - VkResult result = VK_SUCCESS; - - pDisplayTimingProperties->refreshDuration = swapchain.get_refresh_duration(); + VkResult result = swapchain.get_refresh_duration(pDisplayTimingProperties->refreshDuration); return result; } |