blob: 1f86f6635a0edb3f79cc899a3df766cc05954d25 [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
39} // namespace
40
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000041bool TouchedWindow::hasHoveringPointers() const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070042 for (const auto& [_, state] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080043 if (!state.hoveringPointers.empty()) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070044 return true;
45 }
46 }
47 return false;
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000048}
49
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -070050bool TouchedWindow::hasHoveringPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070051 const auto stateIt = mDeviceStates.find(deviceId);
52 if (stateIt == mDeviceStates.end()) {
53 return false;
54 }
55 const DeviceState& state = stateIt->second;
56
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080057 return !state.hoveringPointers.empty();
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -080058}
59
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070060void TouchedWindow::clearHoveringPointers(DeviceId deviceId) {
61 auto stateIt = mDeviceStates.find(deviceId);
62 if (stateIt == mDeviceStates.end()) {
63 return;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070064 }
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070065 DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080066 state.hoveringPointers.clear();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070067 if (!state.hasPointers()) {
68 mDeviceStates.erase(stateIt);
69 }
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000070}
71
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -070072bool TouchedWindow::hasHoveringPointer(DeviceId deviceId, int32_t pointerId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070073 const auto stateIt = mDeviceStates.find(deviceId);
74 if (stateIt == mDeviceStates.end()) {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000075 return false;
76 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070077 const DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080078 return hasPointerId(state.hoveringPointers, pointerId);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000079}
80
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080081void TouchedWindow::addHoveringPointer(DeviceId deviceId, const PointerProperties& pointer) {
82 std::vector<PointerProperties>& hoveringPointers = mDeviceStates[deviceId].hoveringPointers;
83 const size_t initialSize = hoveringPointers.size();
84 std::erase_if(hoveringPointers, [&pointer](const PointerProperties& properties) {
85 return properties.id == pointer.id;
86 });
87 if (hoveringPointers.size() != initialSize) {
88 LOG(ERROR) << __func__ << ": " << pointer << ", device " << deviceId << " was in " << *this;
89 }
90 hoveringPointers.push_back(pointer);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000091}
92
Siarhei Vishniakoue535f972024-03-29 14:55:21 -070093Result<void> TouchedWindow::addTouchingPointers(DeviceId deviceId,
94 const std::vector<PointerProperties>& pointers) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080095 std::vector<PointerProperties>& touchingPointers = mDeviceStates[deviceId].touchingPointers;
96 const size_t initialSize = touchingPointers.size();
97 for (const PointerProperties& pointer : pointers) {
98 std::erase_if(touchingPointers, [&pointer](const PointerProperties& properties) {
99 return properties.id == pointer.id;
100 });
101 }
Siarhei Vishniakoue535f972024-03-29 14:55:21 -0700102 const bool foundInconsistentState = touchingPointers.size() != initialSize;
103 touchingPointers.insert(touchingPointers.end(), pointers.begin(), pointers.end());
104 if (foundInconsistentState) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800105 LOG(ERROR) << __func__ << ": " << dumpVector(pointers, streamableToString) << ", device "
106 << deviceId << " already in " << *this;
Siarhei Vishniakoue535f972024-03-29 14:55:21 -0700107 return android::base::Error();
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800108 }
Siarhei Vishniakoue535f972024-03-29 14:55:21 -0700109 return {};
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700110}
111
112bool TouchedWindow::hasTouchingPointers() const {
113 for (const auto& [_, state] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800114 if (!state.touchingPointers.empty()) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700115 return true;
116 }
117 }
118 return false;
119}
120
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700121bool TouchedWindow::hasTouchingPointers(DeviceId deviceId) const {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800122 return !getTouchingPointers(deviceId).empty();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700123}
124
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700125bool TouchedWindow::hasTouchingPointer(DeviceId deviceId, int32_t pointerId) const {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800126 const auto stateIt = mDeviceStates.find(deviceId);
127 if (stateIt == mDeviceStates.end()) {
128 return false;
129 }
130 const DeviceState& state = stateIt->second;
131 return hasPointerId(state.touchingPointers, pointerId);
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700132}
133
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800134std::vector<PointerProperties> TouchedWindow::getTouchingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700135 const auto stateIt = mDeviceStates.find(deviceId);
136 if (stateIt == mDeviceStates.end()) {
137 return {};
138 }
139 const DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800140 return state.touchingPointers;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700141}
142
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700143void TouchedWindow::removeTouchingPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700144 std::bitset<MAX_POINTER_ID + 1> pointerIds;
145 pointerIds.set(pointerId, true);
146
147 removeTouchingPointers(deviceId, pointerIds);
148}
149
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700150void TouchedWindow::removeTouchingPointers(DeviceId deviceId,
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700151 std::bitset<MAX_POINTER_ID + 1> pointers) {
152 const auto stateIt = mDeviceStates.find(deviceId);
153 if (stateIt == mDeviceStates.end()) {
154 return;
155 }
156 DeviceState& state = stateIt->second;
157
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800158 std::erase_if(state.touchingPointers, [&pointers](const PointerProperties& properties) {
159 return pointers.test(properties.id);
160 });
161
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700162 state.pilferingPointerIds &= ~pointers;
163
164 if (!state.hasPointers()) {
165 mDeviceStates.erase(stateIt);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -0800166 }
167}
168
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -0700169bool TouchedWindow::hasActiveStylus() const {
170 for (const auto& [_, state] : mDeviceStates) {
171 for (const PointerProperties& properties : state.touchingPointers) {
172 if (properties.toolType == ToolType::STYLUS) {
173 return true;
174 }
175 }
176 for (const PointerProperties& properties : state.hoveringPointers) {
177 if (properties.toolType == ToolType::STYLUS) {
178 return true;
179 }
180 }
181 }
182 return false;
183}
184
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700185std::set<DeviceId> TouchedWindow::getTouchingDeviceIds() const {
186 std::set<DeviceId> deviceIds;
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +0000187 for (const auto& [deviceId, deviceState] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800188 if (!deviceState.touchingPointers.empty()) {
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +0000189 deviceIds.insert(deviceId);
190 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700191 }
192 return deviceIds;
193}
194
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700195bool TouchedWindow::hasPilferingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700196 const auto stateIt = mDeviceStates.find(deviceId);
197 if (stateIt == mDeviceStates.end()) {
198 return false;
199 }
200 const DeviceState& state = stateIt->second;
201
202 return state.pilferingPointerIds.any();
203}
204
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700205void TouchedWindow::addPilferingPointers(DeviceId deviceId,
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700206 std::bitset<MAX_POINTER_ID + 1> pointerIds) {
207 mDeviceStates[deviceId].pilferingPointerIds |= pointerIds;
208}
209
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700210void TouchedWindow::addPilferingPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700211 mDeviceStates[deviceId].pilferingPointerIds.set(pointerId);
212}
213
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700214std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getPilferingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700215 const auto stateIt = mDeviceStates.find(deviceId);
216 if (stateIt == mDeviceStates.end()) {
217 return {};
218 }
219 const DeviceState& state = stateIt->second;
220
221 return state.pilferingPointerIds;
222}
223
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700224std::map<DeviceId, std::bitset<MAX_POINTER_ID + 1>> TouchedWindow::getPilferingPointers() const {
225 std::map<DeviceId, std::bitset<MAX_POINTER_ID + 1>> out;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700226 for (const auto& [deviceId, state] : mDeviceStates) {
227 out.emplace(deviceId, state.pilferingPointerIds);
228 }
229 return out;
230}
231
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700232std::optional<nsecs_t> TouchedWindow::getDownTimeInTarget(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700233 const auto stateIt = mDeviceStates.find(deviceId);
234 if (stateIt == mDeviceStates.end()) {
235 return {};
236 }
237 const DeviceState& state = stateIt->second;
238 return state.downTimeInTarget;
239}
240
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700241void TouchedWindow::trySetDownTimeInTarget(DeviceId deviceId, nsecs_t downTime) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700242 auto [stateIt, _] = mDeviceStates.try_emplace(deviceId);
243 DeviceState& state = stateIt->second;
244
245 if (!state.downTimeInTarget) {
246 state.downTimeInTarget = downTime;
247 }
248}
249
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700250void TouchedWindow::removeAllTouchingPointersForDevice(DeviceId deviceId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700251 const auto stateIt = mDeviceStates.find(deviceId);
252 if (stateIt == mDeviceStates.end()) {
253 return;
254 }
255 DeviceState& state = stateIt->second;
256
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800257 state.touchingPointers.clear();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700258 state.pilferingPointerIds.reset();
259 state.downTimeInTarget.reset();
260
261 if (!state.hasPointers()) {
262 mDeviceStates.erase(stateIt);
263 }
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -0700264}
265
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700266void TouchedWindow::removeHoveringPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700267 const auto stateIt = mDeviceStates.find(deviceId);
268 if (stateIt == mDeviceStates.end()) {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000269 return;
270 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700271 DeviceState& state = stateIt->second;
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000272
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800273 std::erase_if(state.hoveringPointers, [&pointerId](const PointerProperties& properties) {
274 return properties.id == pointerId;
275 });
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700276
277 if (!state.hasPointers()) {
278 mDeviceStates.erase(stateIt);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000279 }
280}
281
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700282void TouchedWindow::removeAllHoveringPointersForDevice(DeviceId deviceId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700283 const auto stateIt = mDeviceStates.find(deviceId);
284 if (stateIt == mDeviceStates.end()) {
285 return;
286 }
287 DeviceState& state = stateIt->second;
288
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800289 state.hoveringPointers.clear();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700290
291 if (!state.hasPointers()) {
292 mDeviceStates.erase(stateIt);
293 }
294}
295
296std::string TouchedWindow::deviceStateToString(const TouchedWindow::DeviceState& state) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800297 return StringPrintf("[touchingPointers=%s, "
298 "downTimeInTarget=%s, hoveringPointers=%s, pilferingPointerIds=%s]",
299 dumpVector(state.touchingPointers, streamableToString).c_str(),
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700300 toString(state.downTimeInTarget).c_str(),
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800301 dumpVector(state.hoveringPointers, streamableToString).c_str(),
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700302 bitsetToString(state.pilferingPointerIds).c_str());
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -0700303}
304
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800305std::string TouchedWindow::dump() const {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000306 std::string out;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700307 std::string deviceStates =
308 dumpMap(mDeviceStates, constToString, TouchedWindow::deviceStateToString);
309 out += StringPrintf("name='%s', targetFlags=%s, mDeviceStates=%s\n",
310 windowHandle->getName().c_str(), targetFlags.string().c_str(),
311 deviceStates.c_str());
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000312 return out;
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800313}
314
Siarhei Vishniakou72945a02023-09-18 18:30:25 -0700315std::ostream& operator<<(std::ostream& out, const TouchedWindow& window) {
316 out << window.dump();
317 return out;
318}
319
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800320} // namespace inputdispatcher
321} // namespace android