blob: fa5be1a7193a770f85ef40bd5ffa020a24bb9815 [file] [log] [blame]
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -08001/*
2 * Copyright (C) 2022 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 "TouchedWindow.h"
18
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070019#include <android-base/logging.h>
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -080020#include <android-base/stringprintf.h>
21#include <input/PrintTools.h>
22
Siarhei Vishniakoue535f972024-03-29 14:55:21 -070023using android::base::Result;
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -080024using android::base::StringPrintf;
25
26namespace android {
27
28namespace inputdispatcher {
29
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080030namespace {
31
32bool hasPointerId(const std::vector<PointerProperties>& pointers, int32_t pointerId) {
33 return std::find_if(pointers.begin(), pointers.end(),
34 [&pointerId](const PointerProperties& properties) {
35 return properties.id == pointerId;
36 }) != pointers.end();
37}
38
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -070039bool hasPointerId(const std::vector<TouchedWindow::HoveringPointer>& pointers, int32_t pointerId) {
40 return std::find_if(pointers.begin(), pointers.end(),
41 [&pointerId](const TouchedWindow::HoveringPointer& pointer) {
42 return pointer.properties.id == pointerId;
43 }) != pointers.end();
44}
45
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080046} // namespace
47
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000048bool TouchedWindow::hasHoveringPointers() const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070049 for (const auto& [_, state] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080050 if (!state.hoveringPointers.empty()) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070051 return true;
52 }
53 }
54 return false;
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000055}
56
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -070057bool TouchedWindow::hasHoveringPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070058 const auto stateIt = mDeviceStates.find(deviceId);
59 if (stateIt == mDeviceStates.end()) {
60 return false;
61 }
62 const DeviceState& state = stateIt->second;
63
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080064 return !state.hoveringPointers.empty();
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -080065}
66
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070067void TouchedWindow::clearHoveringPointers(DeviceId deviceId) {
68 auto stateIt = mDeviceStates.find(deviceId);
69 if (stateIt == mDeviceStates.end()) {
70 return;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070071 }
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070072 DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080073 state.hoveringPointers.clear();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070074 if (!state.hasPointers()) {
75 mDeviceStates.erase(stateIt);
76 }
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000077}
78
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -070079bool TouchedWindow::hasHoveringPointer(DeviceId deviceId, int32_t pointerId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070080 const auto stateIt = mDeviceStates.find(deviceId);
81 if (stateIt == mDeviceStates.end()) {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000082 return false;
83 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070084 const DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080085 return hasPointerId(state.hoveringPointers, pointerId);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000086}
87
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -070088void TouchedWindow::addHoveringPointer(DeviceId deviceId, const PointerProperties& properties,
89 float x, float y) {
90 std::vector<HoveringPointer>& hoveringPointers = mDeviceStates[deviceId].hoveringPointers;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080091 const size_t initialSize = hoveringPointers.size();
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -070092 std::erase_if(hoveringPointers, [&properties](const HoveringPointer& pointer) {
93 return pointer.properties.id == properties.id;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080094 });
95 if (hoveringPointers.size() != initialSize) {
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -070096 LOG(ERROR) << __func__ << ": " << properties << ", device " << deviceId << " was in "
97 << *this;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080098 }
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -070099 hoveringPointers.push_back({properties, x, y});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000100}
101
Siarhei Vishniakoue535f972024-03-29 14:55:21 -0700102Result<void> TouchedWindow::addTouchingPointers(DeviceId deviceId,
103 const std::vector<PointerProperties>& pointers) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800104 std::vector<PointerProperties>& touchingPointers = mDeviceStates[deviceId].touchingPointers;
105 const size_t initialSize = touchingPointers.size();
106 for (const PointerProperties& pointer : pointers) {
107 std::erase_if(touchingPointers, [&pointer](const PointerProperties& properties) {
108 return properties.id == pointer.id;
109 });
110 }
Siarhei Vishniakoue535f972024-03-29 14:55:21 -0700111 const bool foundInconsistentState = touchingPointers.size() != initialSize;
112 touchingPointers.insert(touchingPointers.end(), pointers.begin(), pointers.end());
113 if (foundInconsistentState) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800114 LOG(ERROR) << __func__ << ": " << dumpVector(pointers, streamableToString) << ", device "
115 << deviceId << " already in " << *this;
Siarhei Vishniakoue535f972024-03-29 14:55:21 -0700116 return android::base::Error();
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800117 }
Siarhei Vishniakoue535f972024-03-29 14:55:21 -0700118 return {};
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700119}
120
121bool TouchedWindow::hasTouchingPointers() const {
122 for (const auto& [_, state] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800123 if (!state.touchingPointers.empty()) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700124 return true;
125 }
126 }
127 return false;
128}
129
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700130bool TouchedWindow::hasTouchingPointers(DeviceId deviceId) const {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800131 return !getTouchingPointers(deviceId).empty();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700132}
133
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700134bool TouchedWindow::hasTouchingPointer(DeviceId deviceId, int32_t pointerId) const {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800135 const auto stateIt = mDeviceStates.find(deviceId);
136 if (stateIt == mDeviceStates.end()) {
137 return false;
138 }
139 const DeviceState& state = stateIt->second;
140 return hasPointerId(state.touchingPointers, pointerId);
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700141}
142
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800143std::vector<PointerProperties> TouchedWindow::getTouchingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700144 const auto stateIt = mDeviceStates.find(deviceId);
145 if (stateIt == mDeviceStates.end()) {
146 return {};
147 }
148 const DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800149 return state.touchingPointers;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700150}
151
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700152void TouchedWindow::removeTouchingPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700153 std::bitset<MAX_POINTER_ID + 1> pointerIds;
154 pointerIds.set(pointerId, true);
155
156 removeTouchingPointers(deviceId, pointerIds);
157}
158
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700159void TouchedWindow::removeTouchingPointers(DeviceId deviceId,
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700160 std::bitset<MAX_POINTER_ID + 1> pointers) {
161 const auto stateIt = mDeviceStates.find(deviceId);
162 if (stateIt == mDeviceStates.end()) {
163 return;
164 }
165 DeviceState& state = stateIt->second;
166
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800167 std::erase_if(state.touchingPointers, [&pointers](const PointerProperties& properties) {
168 return pointers.test(properties.id);
169 });
170
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700171 state.pilferingPointerIds &= ~pointers;
172
173 if (!state.hasPointers()) {
174 mDeviceStates.erase(stateIt);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -0800175 }
176}
177
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -0700178bool TouchedWindow::hasActiveStylus() const {
179 for (const auto& [_, state] : mDeviceStates) {
180 for (const PointerProperties& properties : state.touchingPointers) {
181 if (properties.toolType == ToolType::STYLUS) {
182 return true;
183 }
184 }
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -0700185 for (const HoveringPointer& pointer : state.hoveringPointers) {
186 if (pointer.properties.toolType == ToolType::STYLUS) {
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -0700187 return true;
188 }
189 }
190 }
191 return false;
192}
193
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700194std::set<DeviceId> TouchedWindow::getTouchingDeviceIds() const {
195 std::set<DeviceId> deviceIds;
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +0000196 for (const auto& [deviceId, deviceState] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800197 if (!deviceState.touchingPointers.empty()) {
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +0000198 deviceIds.insert(deviceId);
199 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700200 }
201 return deviceIds;
202}
203
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700204bool TouchedWindow::hasPilferingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700205 const auto stateIt = mDeviceStates.find(deviceId);
206 if (stateIt == mDeviceStates.end()) {
207 return false;
208 }
209 const DeviceState& state = stateIt->second;
210
211 return state.pilferingPointerIds.any();
212}
213
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700214void TouchedWindow::addPilferingPointers(DeviceId deviceId,
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700215 std::bitset<MAX_POINTER_ID + 1> pointerIds) {
216 mDeviceStates[deviceId].pilferingPointerIds |= pointerIds;
217}
218
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700219void TouchedWindow::addPilferingPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700220 mDeviceStates[deviceId].pilferingPointerIds.set(pointerId);
221}
222
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700223std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getPilferingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700224 const auto stateIt = mDeviceStates.find(deviceId);
225 if (stateIt == mDeviceStates.end()) {
226 return {};
227 }
228 const DeviceState& state = stateIt->second;
229
230 return state.pilferingPointerIds;
231}
232
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700233std::map<DeviceId, std::bitset<MAX_POINTER_ID + 1>> TouchedWindow::getPilferingPointers() const {
234 std::map<DeviceId, std::bitset<MAX_POINTER_ID + 1>> out;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700235 for (const auto& [deviceId, state] : mDeviceStates) {
236 out.emplace(deviceId, state.pilferingPointerIds);
237 }
238 return out;
239}
240
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700241std::optional<nsecs_t> TouchedWindow::getDownTimeInTarget(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700242 const auto stateIt = mDeviceStates.find(deviceId);
243 if (stateIt == mDeviceStates.end()) {
244 return {};
245 }
246 const DeviceState& state = stateIt->second;
247 return state.downTimeInTarget;
248}
249
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700250void TouchedWindow::trySetDownTimeInTarget(DeviceId deviceId, nsecs_t downTime) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700251 auto [stateIt, _] = mDeviceStates.try_emplace(deviceId);
252 DeviceState& state = stateIt->second;
253
254 if (!state.downTimeInTarget) {
255 state.downTimeInTarget = downTime;
256 }
257}
258
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700259void TouchedWindow::removeAllTouchingPointersForDevice(DeviceId deviceId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700260 const auto stateIt = mDeviceStates.find(deviceId);
261 if (stateIt == mDeviceStates.end()) {
262 return;
263 }
264 DeviceState& state = stateIt->second;
265
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800266 state.touchingPointers.clear();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700267 state.pilferingPointerIds.reset();
268 state.downTimeInTarget.reset();
269
270 if (!state.hasPointers()) {
271 mDeviceStates.erase(stateIt);
272 }
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -0700273}
274
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700275void TouchedWindow::removeHoveringPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700276 const auto stateIt = mDeviceStates.find(deviceId);
277 if (stateIt == mDeviceStates.end()) {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000278 return;
279 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700280 DeviceState& state = stateIt->second;
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000281
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -0700282 std::erase_if(state.hoveringPointers, [&pointerId](const HoveringPointer& pointer) {
283 return pointer.properties.id == pointerId;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800284 });
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700285
286 if (!state.hasPointers()) {
287 mDeviceStates.erase(stateIt);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000288 }
289}
290
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -0700291std::vector<DeviceId> TouchedWindow::eraseHoveringPointersIf(
292 std::function<bool(const PointerProperties&, float /*x*/, float /*y*/)> condition) {
293 std::vector<DeviceId> erasedDevices;
294 for (auto& [deviceId, state] : mDeviceStates) {
295 std::erase_if(state.hoveringPointers, [&](const HoveringPointer& pointer) {
296 if (condition(pointer.properties, pointer.x, pointer.y)) {
297 erasedDevices.push_back(deviceId);
298 return true;
299 }
300 return false;
301 });
302 }
303
304 return erasedDevices;
305}
306
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700307void TouchedWindow::removeAllHoveringPointersForDevice(DeviceId deviceId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700308 const auto stateIt = mDeviceStates.find(deviceId);
309 if (stateIt == mDeviceStates.end()) {
310 return;
311 }
312 DeviceState& state = stateIt->second;
313
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800314 state.hoveringPointers.clear();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700315
316 if (!state.hasPointers()) {
317 mDeviceStates.erase(stateIt);
318 }
319}
320
321std::string TouchedWindow::deviceStateToString(const TouchedWindow::DeviceState& state) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800322 return StringPrintf("[touchingPointers=%s, "
323 "downTimeInTarget=%s, hoveringPointers=%s, pilferingPointerIds=%s]",
324 dumpVector(state.touchingPointers, streamableToString).c_str(),
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700325 toString(state.downTimeInTarget).c_str(),
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800326 dumpVector(state.hoveringPointers, streamableToString).c_str(),
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700327 bitsetToString(state.pilferingPointerIds).c_str());
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -0700328}
329
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800330std::string TouchedWindow::dump() const {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000331 std::string out;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700332 std::string deviceStates =
333 dumpMap(mDeviceStates, constToString, TouchedWindow::deviceStateToString);
334 out += StringPrintf("name='%s', targetFlags=%s, mDeviceStates=%s\n",
335 windowHandle->getName().c_str(), targetFlags.string().c_str(),
336 deviceStates.c_str());
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000337 return out;
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800338}
339
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -0700340std::ostream& operator<<(std::ostream& out, const TouchedWindow::HoveringPointer& pointer) {
341 out << pointer.properties << " at (" << pointer.x << ", " << pointer.y << ")";
342 return out;
343}
344
Siarhei Vishniakou72945a02023-09-18 18:30:25 -0700345std::ostream& operator<<(std::ostream& out, const TouchedWindow& window) {
346 out << window.dump();
347 return out;
348}
349
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800350} // namespace inputdispatcher
351} // namespace android