Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2023 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "CapturedTouchpadEventConverter.h" |
| 18 | |
Prabir Pradhan | 132f21c | 2024-07-25 16:48:30 +0000 | [diff] [blame] | 19 | #include <optional> |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 20 | #include <sstream> |
| 21 | |
| 22 | #include <android-base/stringprintf.h> |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 23 | #include <com_android_input_flags.h> |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 24 | #include <input/PrintTools.h> |
| 25 | #include <linux/input-event-codes.h> |
| 26 | #include <log/log_main.h> |
| 27 | |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 28 | namespace input_flags = com::android::input::flags; |
| 29 | |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 30 | namespace android { |
| 31 | |
| 32 | namespace { |
| 33 | |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 34 | static constexpr uint32_t SOURCE = AINPUT_SOURCE_TOUCHPAD; |
| 35 | |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 36 | int32_t actionWithIndex(int32_t action, int32_t index) { |
| 37 | return action | (index << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); |
| 38 | } |
| 39 | |
| 40 | template <typename T> |
| 41 | size_t firstUnmarkedBit(T set) { |
| 42 | // TODO: replace with std::countr_one from <bit> when that's available |
| 43 | LOG_ALWAYS_FATAL_IF(set.all()); |
| 44 | size_t i = 0; |
| 45 | while (set.test(i)) { |
| 46 | i++; |
| 47 | } |
| 48 | return i; |
| 49 | } |
| 50 | |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 51 | void addRawMotionRange(InputDeviceInfo& deviceInfo, int32_t androidAxis, |
| 52 | RawAbsoluteAxisInfo& evdevAxis) { |
| 53 | deviceInfo.addMotionRange(androidAxis, SOURCE, evdevAxis.minValue, evdevAxis.maxValue, |
| 54 | evdevAxis.flat, evdevAxis.fuzz, evdevAxis.resolution); |
| 55 | } |
| 56 | |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 57 | } // namespace |
| 58 | |
| 59 | CapturedTouchpadEventConverter::CapturedTouchpadEventConverter( |
| 60 | InputReaderContext& readerContext, const InputDeviceContext& deviceContext, |
| 61 | MultiTouchMotionAccumulator& motionAccumulator, int32_t deviceId) |
| 62 | : mDeviceId(deviceId), |
| 63 | mReaderContext(readerContext), |
| 64 | mDeviceContext(deviceContext), |
| 65 | mMotionAccumulator(motionAccumulator), |
| 66 | mHasTouchMinor(deviceContext.hasAbsoluteAxis(ABS_MT_TOUCH_MINOR)), |
| 67 | mHasToolMinor(deviceContext.hasAbsoluteAxis(ABS_MT_WIDTH_MINOR)) { |
Prabir Pradhan | 132f21c | 2024-07-25 16:48:30 +0000 | [diff] [blame] | 68 | if (std::optional<RawAbsoluteAxisInfo> orientation = |
| 69 | deviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION); |
| 70 | orientation) { |
| 71 | if (orientation->maxValue > 0) { |
| 72 | mOrientationScale = M_PI_2 / orientation->maxValue; |
| 73 | } else if (orientation->minValue < 0) { |
| 74 | mOrientationScale = -M_PI_2 / orientation->minValue; |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 75 | } |
| 76 | } |
| 77 | |
| 78 | // TODO(b/275369880): support touch.pressure.calibration and .scale properties when captured. |
Prabir Pradhan | 132f21c | 2024-07-25 16:48:30 +0000 | [diff] [blame] | 79 | if (std::optional<RawAbsoluteAxisInfo> pressure = |
| 80 | deviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE); |
| 81 | pressure && pressure->maxValue > 0) { |
| 82 | mPressureScale = 1.0 / pressure->maxValue; |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 83 | } |
| 84 | |
Prabir Pradhan | 132f21c | 2024-07-25 16:48:30 +0000 | [diff] [blame] | 85 | std::optional<RawAbsoluteAxisInfo> touchMajor = |
| 86 | deviceContext.getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR); |
| 87 | std::optional<RawAbsoluteAxisInfo> toolMajor = |
| 88 | deviceContext.getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR); |
| 89 | mHasTouchMajor = touchMajor.has_value(); |
| 90 | mHasToolMajor = toolMajor.has_value(); |
| 91 | if (mHasTouchMajor && touchMajor->maxValue != 0) { |
| 92 | mSizeScale = 1.0f / touchMajor->maxValue; |
| 93 | } else if (mHasToolMajor && toolMajor->maxValue != 0) { |
| 94 | mSizeScale = 1.0f / toolMajor->maxValue; |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 95 | } |
| 96 | } |
| 97 | |
| 98 | std::string CapturedTouchpadEventConverter::dump() const { |
| 99 | std::stringstream out; |
| 100 | out << "Orientation scale: " << mOrientationScale << "\n"; |
| 101 | out << "Pressure scale: " << mPressureScale << "\n"; |
| 102 | out << "Size scale: " << mSizeScale << "\n"; |
| 103 | |
| 104 | out << "Dimension axes:"; |
| 105 | if (mHasTouchMajor) out << " touch major"; |
| 106 | if (mHasTouchMinor) out << ", touch minor"; |
| 107 | if (mHasToolMajor) out << ", tool major"; |
| 108 | if (mHasToolMinor) out << ", tool minor"; |
| 109 | out << "\n"; |
| 110 | |
| 111 | out << "Down time: " << mDownTime << "\n"; |
| 112 | out << StringPrintf("Button state: 0x%08x\n", mButtonState); |
| 113 | |
| 114 | out << StringPrintf("Pointer IDs in use: %s\n", mPointerIdsInUse.to_string().c_str()); |
| 115 | |
| 116 | out << "Pointer IDs for slot numbers:\n"; |
| 117 | out << addLinePrefix(dumpMap(mPointerIdForSlotNumber), " ") << "\n"; |
| 118 | return out.str(); |
| 119 | } |
| 120 | |
| 121 | void CapturedTouchpadEventConverter::populateMotionRanges(InputDeviceInfo& info) const { |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 122 | if (input_flags::include_relative_axis_values_for_captured_touchpads()) { |
| 123 | tryAddRawMotionRangeWithRelative(/*byref*/ info, AMOTION_EVENT_AXIS_X, |
| 124 | AMOTION_EVENT_AXIS_RELATIVE_X, ABS_MT_POSITION_X); |
| 125 | tryAddRawMotionRangeWithRelative(/*byref*/ info, AMOTION_EVENT_AXIS_Y, |
| 126 | AMOTION_EVENT_AXIS_RELATIVE_Y, ABS_MT_POSITION_Y); |
| 127 | } else { |
| 128 | tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_X, ABS_MT_POSITION_X); |
| 129 | tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_Y, ABS_MT_POSITION_Y); |
| 130 | } |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 131 | tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOUCH_MAJOR, ABS_MT_TOUCH_MAJOR); |
| 132 | tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOUCH_MINOR, ABS_MT_TOUCH_MINOR); |
| 133 | tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MAJOR, ABS_MT_WIDTH_MAJOR); |
| 134 | tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MINOR, ABS_MT_WIDTH_MINOR); |
| 135 | |
Prabir Pradhan | 132f21c | 2024-07-25 16:48:30 +0000 | [diff] [blame] | 136 | if (mDeviceContext.hasAbsoluteAxis(ABS_MT_PRESSURE)) { |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 137 | info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, SOURCE, 0, 1, 0, 0, 0); |
| 138 | } |
| 139 | |
Prabir Pradhan | 132f21c | 2024-07-25 16:48:30 +0000 | [diff] [blame] | 140 | if (std::optional<RawAbsoluteAxisInfo> orientation = |
| 141 | mDeviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION); |
| 142 | orientation && (orientation->maxValue > 0 || orientation->minValue < 0)) { |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 143 | info.addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, SOURCE, -M_PI_2, M_PI_2, 0, 0, 0); |
| 144 | } |
| 145 | |
| 146 | if (mHasTouchMajor || mHasToolMajor) { |
| 147 | info.addMotionRange(AMOTION_EVENT_AXIS_SIZE, SOURCE, 0, 1, 0, 0, 0); |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | void CapturedTouchpadEventConverter::tryAddRawMotionRange(InputDeviceInfo& deviceInfo, |
| 152 | int32_t androidAxis, |
| 153 | int32_t evdevAxis) const { |
Prabir Pradhan | 132f21c | 2024-07-25 16:48:30 +0000 | [diff] [blame] | 154 | std::optional<RawAbsoluteAxisInfo> info = mDeviceContext.getAbsoluteAxisInfo(evdevAxis); |
| 155 | if (info) { |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 156 | addRawMotionRange(/*byref*/ deviceInfo, androidAxis, *info); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | void CapturedTouchpadEventConverter::tryAddRawMotionRangeWithRelative(InputDeviceInfo& deviceInfo, |
| 161 | int32_t androidAxis, |
| 162 | int32_t androidRelativeAxis, |
| 163 | int32_t evdevAxis) const { |
| 164 | std::optional<RawAbsoluteAxisInfo> axisInfo = mDeviceContext.getAbsoluteAxisInfo(evdevAxis); |
| 165 | if (axisInfo) { |
| 166 | addRawMotionRange(/*byref*/ deviceInfo, androidAxis, *axisInfo); |
| 167 | |
| 168 | // The largest movement we could possibly report on a relative axis is from the minimum to |
| 169 | // the maximum (or vice versa) of the absolute axis. |
| 170 | float range = axisInfo->maxValue - axisInfo->minValue; |
| 171 | deviceInfo.addMotionRange(androidRelativeAxis, SOURCE, -range, range, axisInfo->flat, |
| 172 | axisInfo->fuzz, axisInfo->resolution); |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 173 | } |
| 174 | } |
| 175 | |
| 176 | void CapturedTouchpadEventConverter::reset() { |
| 177 | mCursorButtonAccumulator.reset(mDeviceContext); |
| 178 | mDownTime = 0; |
| 179 | mPointerIdsInUse.reset(); |
| 180 | mPointerIdForSlotNumber.clear(); |
| 181 | } |
| 182 | |
| 183 | std::list<NotifyArgs> CapturedTouchpadEventConverter::process(const RawEvent& rawEvent) { |
| 184 | std::list<NotifyArgs> out; |
| 185 | if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) { |
| 186 | out = sync(rawEvent.when, rawEvent.readTime); |
| 187 | mMotionAccumulator.finishSync(); |
| 188 | } |
| 189 | |
Harry Cutts | 71953c2 | 2024-06-03 12:54:40 +0000 | [diff] [blame] | 190 | mCursorButtonAccumulator.process(rawEvent); |
| 191 | mMotionAccumulator.process(rawEvent); |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 192 | return out; |
| 193 | } |
| 194 | |
| 195 | std::list<NotifyArgs> CapturedTouchpadEventConverter::sync(nsecs_t when, nsecs_t readTime) { |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 196 | std::list<NotifyArgs> out; |
| 197 | std::vector<PointerCoords> coords; |
| 198 | std::vector<PointerProperties> properties; |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 199 | std::map<size_t /*slotNumber*/, size_t /*coordsIndex*/> coordsIndexForSlotNumber; |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 200 | |
| 201 | // For all the touches that were already down, send a MOVE event with their updated coordinates. |
| 202 | // A convention of the MotionEvent API is that pointer coordinates in UP events match the |
| 203 | // pointer's coordinates from the previous MOVE, so we still include touches here even if |
| 204 | // they've been lifted in this evdev frame. |
| 205 | if (!mPointerIdForSlotNumber.empty()) { |
| 206 | for (const auto [slotNumber, pointerId] : mPointerIdForSlotNumber) { |
| 207 | // Note that we don't check whether the touch has actually moved — it's rare for a touch |
| 208 | // to stay perfectly still between frames, and if it does the worst that can happen is |
| 209 | // an extra MOVE event, so it's not worth the overhead of checking for changes. |
| 210 | coordsIndexForSlotNumber[slotNumber] = coords.size(); |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 211 | coords.push_back(makePointerCoordsForSlot(slotNumber)); |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 212 | properties.push_back({.id = pointerId, .toolType = ToolType::FINGER}); |
| 213 | } |
| 214 | out.push_back( |
| 215 | makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_MOVE, coords, properties)); |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 216 | if (input_flags::include_relative_axis_values_for_captured_touchpads()) { |
| 217 | // For any further events we send from this sync, the pointers won't have moved relative |
| 218 | // to the positions we just reported in this MOVE event, so zero out the relative axes. |
| 219 | for (PointerCoords& pointer : coords) { |
| 220 | pointer.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0); |
| 221 | pointer.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0); |
| 222 | } |
| 223 | } |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 224 | } |
| 225 | |
| 226 | std::vector<size_t> upSlots, downSlots; |
| 227 | for (size_t i = 0; i < mMotionAccumulator.getSlotCount(); i++) { |
Harry Cutts | 892bce5 | 2023-04-12 16:30:09 +0000 | [diff] [blame] | 228 | const MultiTouchMotionAccumulator::Slot& slot = mMotionAccumulator.getSlot(i); |
| 229 | // Some touchpads continue to report contacts even after they've identified them as palms. |
| 230 | // We don't currently have a way to mark these as palms when reporting to apps, so don't |
| 231 | // report them at all. |
| 232 | const bool isInUse = slot.isInUse() && slot.getToolType() != ToolType::PALM; |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 233 | const bool wasInUse = mPointerIdForSlotNumber.find(i) != mPointerIdForSlotNumber.end(); |
| 234 | if (isInUse && !wasInUse) { |
| 235 | downSlots.push_back(i); |
| 236 | } else if (!isInUse && wasInUse) { |
| 237 | upSlots.push_back(i); |
| 238 | } |
| 239 | } |
| 240 | |
Harry Cutts | 23c8dff | 2023-05-10 17:39:59 +0000 | [diff] [blame] | 241 | // Send BUTTON_RELEASE events. (This has to happen before any UP events to avoid sending |
| 242 | // BUTTON_RELEASE events without any pointers.) |
| 243 | uint32_t newButtonState; |
| 244 | if (coords.size() - upSlots.size() + downSlots.size() == 0) { |
| 245 | // If there won't be any pointers down after this evdev sync, we won't be able to send |
| 246 | // button updates on their own, as motion events without pointers are invalid. To avoid |
| 247 | // erroneously reporting buttons being held for long periods, send BUTTON_RELEASE events for |
| 248 | // all pressed buttons when the last pointer is lifted. |
| 249 | // |
| 250 | // This also prevents us from sending BUTTON_PRESS events too early in the case of touchpads |
| 251 | // which report a button press one evdev sync before reporting a touch going down. |
| 252 | newButtonState = 0; |
| 253 | } else { |
| 254 | newButtonState = mCursorButtonAccumulator.getButtonState(); |
| 255 | } |
| 256 | for (uint32_t button = 1; button <= AMOTION_EVENT_BUTTON_FORWARD; button <<= 1) { |
| 257 | if (!(newButtonState & button) && mButtonState & button) { |
| 258 | mButtonState &= ~button; |
| 259 | out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE, |
| 260 | coords, properties, /*actionButton=*/button)); |
| 261 | } |
| 262 | } |
| 263 | |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 264 | // For any touches that were lifted, send UP or POINTER_UP events. |
| 265 | for (size_t slotNumber : upSlots) { |
| 266 | const size_t indexToRemove = coordsIndexForSlotNumber.at(slotNumber); |
Harry Cutts | 892bce5 | 2023-04-12 16:30:09 +0000 | [diff] [blame] | 267 | const bool cancel = mMotionAccumulator.getSlot(slotNumber).getToolType() == ToolType::PALM; |
| 268 | int32_t action; |
| 269 | if (coords.size() == 1) { |
| 270 | action = cancel ? AMOTION_EVENT_ACTION_CANCEL : AMOTION_EVENT_ACTION_UP; |
| 271 | } else { |
| 272 | action = actionWithIndex(AMOTION_EVENT_ACTION_POINTER_UP, indexToRemove); |
| 273 | } |
| 274 | out.push_back(makeMotionArgs(when, readTime, action, coords, properties, /*actionButton=*/0, |
| 275 | /*flags=*/cancel ? AMOTION_EVENT_FLAG_CANCELED : 0)); |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 276 | |
| 277 | freePointerIdForSlot(slotNumber); |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 278 | if (input_flags::include_relative_axis_values_for_captured_touchpads()) { |
| 279 | mPreviousCoordsForSlotNumber.erase(slotNumber); |
| 280 | } |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 281 | coords.erase(coords.begin() + indexToRemove); |
| 282 | properties.erase(properties.begin() + indexToRemove); |
| 283 | // Now that we've removed some coords and properties, we might have to update the slot |
| 284 | // number to coords index mapping. |
| 285 | coordsIndexForSlotNumber.erase(slotNumber); |
| 286 | for (auto& [_, index] : coordsIndexForSlotNumber) { |
| 287 | if (index > indexToRemove) { |
| 288 | index--; |
| 289 | } |
| 290 | } |
| 291 | } |
| 292 | |
| 293 | // For new touches, send DOWN or POINTER_DOWN events. |
| 294 | for (size_t slotNumber : downSlots) { |
| 295 | const size_t coordsIndex = coords.size(); |
| 296 | const int32_t action = coords.empty() |
| 297 | ? AMOTION_EVENT_ACTION_DOWN |
| 298 | : actionWithIndex(AMOTION_EVENT_ACTION_POINTER_DOWN, coordsIndex); |
| 299 | |
| 300 | coordsIndexForSlotNumber[slotNumber] = coordsIndex; |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 301 | coords.push_back(makePointerCoordsForSlot(slotNumber)); |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 302 | properties.push_back( |
| 303 | {.id = allocatePointerIdToSlot(slotNumber), .toolType = ToolType::FINGER}); |
| 304 | |
| 305 | out.push_back(makeMotionArgs(when, readTime, action, coords, properties)); |
| 306 | } |
| 307 | |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 308 | for (uint32_t button = 1; button <= AMOTION_EVENT_BUTTON_FORWARD; button <<= 1) { |
| 309 | if (newButtonState & button && !(mButtonState & button)) { |
| 310 | mButtonState |= button; |
| 311 | out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_PRESS, coords, |
| 312 | properties, /*actionButton=*/button)); |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 313 | } |
| 314 | } |
| 315 | return out; |
| 316 | } |
| 317 | |
| 318 | NotifyMotionArgs CapturedTouchpadEventConverter::makeMotionArgs( |
| 319 | nsecs_t when, nsecs_t readTime, int32_t action, const std::vector<PointerCoords>& coords, |
Harry Cutts | 892bce5 | 2023-04-12 16:30:09 +0000 | [diff] [blame] | 320 | const std::vector<PointerProperties>& properties, int32_t actionButton, int32_t flags) { |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 321 | LOG_ALWAYS_FATAL_IF(coords.size() != properties.size(), |
| 322 | "Mismatched coords and properties arrays."); |
| 323 | return NotifyMotionArgs(mReaderContext.getNextId(), when, readTime, mDeviceId, SOURCE, |
Siarhei Vishniakou | cfbee53 | 2024-05-10 13:41:35 -0700 | [diff] [blame] | 324 | ui::LogicalDisplayId::INVALID, /*policyFlags=*/POLICY_FLAG_WAKE, action, |
Harry Cutts | 892bce5 | 2023-04-12 16:30:09 +0000 | [diff] [blame] | 325 | /*actionButton=*/actionButton, flags, |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 326 | mReaderContext.getGlobalMetaState(), mButtonState, |
| 327 | MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, coords.size(), |
| 328 | properties.data(), coords.data(), /*xPrecision=*/1.0f, |
| 329 | /*yPrecision=*/1.0f, AMOTION_EVENT_INVALID_CURSOR_POSITION, |
| 330 | AMOTION_EVENT_INVALID_CURSOR_POSITION, mDownTime, /*videoFrames=*/{}); |
| 331 | } |
| 332 | |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 333 | PointerCoords CapturedTouchpadEventConverter::makePointerCoordsForSlot(size_t slotNumber) { |
| 334 | const MultiTouchMotionAccumulator::Slot& slot = mMotionAccumulator.getSlot(slotNumber); |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 335 | PointerCoords coords; |
| 336 | coords.clear(); |
| 337 | coords.setAxisValue(AMOTION_EVENT_AXIS_X, slot.getX()); |
| 338 | coords.setAxisValue(AMOTION_EVENT_AXIS_Y, slot.getY()); |
Harry Cutts | 7515534 | 2024-08-23 11:11:13 +0000 | [diff] [blame] | 339 | if (input_flags::include_relative_axis_values_for_captured_touchpads()) { |
| 340 | if (auto it = mPreviousCoordsForSlotNumber.find(slotNumber); |
| 341 | it != mPreviousCoordsForSlotNumber.end()) { |
| 342 | auto [oldX, oldY] = it->second; |
| 343 | coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, slot.getX() - oldX); |
| 344 | coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, slot.getY() - oldY); |
| 345 | } |
| 346 | mPreviousCoordsForSlotNumber[slotNumber] = std::make_pair(slot.getX(), slot.getY()); |
| 347 | } |
| 348 | |
Harry Cutts | bb24e27 | 2023-03-21 10:49:47 +0000 | [diff] [blame] | 349 | coords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, slot.getTouchMajor()); |
| 350 | coords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, slot.getTouchMinor()); |
| 351 | coords.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, slot.getToolMajor()); |
| 352 | coords.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, slot.getToolMinor()); |
| 353 | coords.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, slot.getOrientation() * mOrientationScale); |
| 354 | coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, slot.getPressure() * mPressureScale); |
| 355 | float size = 0; |
| 356 | // TODO(b/275369880): support touch.size.calibration and .isSummed properties when captured. |
| 357 | if (mHasTouchMajor) { |
| 358 | size = mHasTouchMinor ? (slot.getTouchMajor() + slot.getTouchMinor()) / 2 |
| 359 | : slot.getTouchMajor(); |
| 360 | } else if (mHasToolMajor) { |
| 361 | size = mHasToolMinor ? (slot.getToolMajor() + slot.getToolMinor()) / 2 |
| 362 | : slot.getToolMajor(); |
| 363 | } |
| 364 | coords.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size * mSizeScale); |
| 365 | return coords; |
| 366 | } |
| 367 | |
| 368 | int32_t CapturedTouchpadEventConverter::allocatePointerIdToSlot(size_t slotNumber) { |
| 369 | const int32_t pointerId = firstUnmarkedBit(mPointerIdsInUse); |
| 370 | mPointerIdsInUse.set(pointerId); |
| 371 | mPointerIdForSlotNumber[slotNumber] = pointerId; |
| 372 | return pointerId; |
| 373 | } |
| 374 | |
| 375 | void CapturedTouchpadEventConverter::freePointerIdForSlot(size_t slotNumber) { |
| 376 | mPointerIdsInUse.reset(mPointerIdForSlotNumber.at(slotNumber)); |
| 377 | mPointerIdForSlotNumber.erase(slotNumber); |
| 378 | } |
| 379 | |
| 380 | } // namespace android |