blob: 037d7c8e99020622b5e9593423e8295bac51e245 [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
23using android::base::StringPrintf;
24
25namespace android {
26
27namespace inputdispatcher {
28
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080029namespace {
30
31bool hasPointerId(const std::vector<PointerProperties>& pointers, int32_t pointerId) {
32 return std::find_if(pointers.begin(), pointers.end(),
33 [&pointerId](const PointerProperties& properties) {
34 return properties.id == pointerId;
35 }) != pointers.end();
36}
37
38} // namespace
39
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000040bool TouchedWindow::hasHoveringPointers() const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070041 for (const auto& [_, state] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080042 if (!state.hoveringPointers.empty()) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070043 return true;
44 }
45 }
46 return false;
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000047}
48
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -070049bool TouchedWindow::hasHoveringPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070050 const auto stateIt = mDeviceStates.find(deviceId);
51 if (stateIt == mDeviceStates.end()) {
52 return false;
53 }
54 const DeviceState& state = stateIt->second;
55
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080056 return !state.hoveringPointers.empty();
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -080057}
58
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070059void TouchedWindow::clearHoveringPointers(DeviceId deviceId) {
60 auto stateIt = mDeviceStates.find(deviceId);
61 if (stateIt == mDeviceStates.end()) {
62 return;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070063 }
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070064 DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080065 state.hoveringPointers.clear();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070066 if (!state.hasPointers()) {
67 mDeviceStates.erase(stateIt);
68 }
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000069}
70
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -070071bool TouchedWindow::hasHoveringPointer(DeviceId deviceId, int32_t pointerId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070072 const auto stateIt = mDeviceStates.find(deviceId);
73 if (stateIt == mDeviceStates.end()) {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000074 return false;
75 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -070076 const DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080077 return hasPointerId(state.hoveringPointers, pointerId);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000078}
79
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080080void TouchedWindow::addHoveringPointer(DeviceId deviceId, const PointerProperties& pointer) {
81 std::vector<PointerProperties>& hoveringPointers = mDeviceStates[deviceId].hoveringPointers;
82 const size_t initialSize = hoveringPointers.size();
83 std::erase_if(hoveringPointers, [&pointer](const PointerProperties& properties) {
84 return properties.id == pointer.id;
85 });
86 if (hoveringPointers.size() != initialSize) {
87 LOG(ERROR) << __func__ << ": " << pointer << ", device " << deviceId << " was in " << *this;
88 }
89 hoveringPointers.push_back(pointer);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +000090}
91
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -070092void TouchedWindow::addTouchingPointers(DeviceId deviceId,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080093 const std::vector<PointerProperties>& pointers) {
94 std::vector<PointerProperties>& touchingPointers = mDeviceStates[deviceId].touchingPointers;
95 const size_t initialSize = touchingPointers.size();
96 for (const PointerProperties& pointer : pointers) {
97 std::erase_if(touchingPointers, [&pointer](const PointerProperties& properties) {
98 return properties.id == pointer.id;
99 });
100 }
101 if (touchingPointers.size() != initialSize) {
102 LOG(ERROR) << __func__ << ": " << dumpVector(pointers, streamableToString) << ", device "
103 << deviceId << " already in " << *this;
104 }
105 touchingPointers.insert(touchingPointers.end(), pointers.begin(), pointers.end());
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700106}
107
108bool TouchedWindow::hasTouchingPointers() const {
109 for (const auto& [_, state] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800110 if (!state.touchingPointers.empty()) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700111 return true;
112 }
113 }
114 return false;
115}
116
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700117bool TouchedWindow::hasTouchingPointers(DeviceId deviceId) const {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800118 return !getTouchingPointers(deviceId).empty();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700119}
120
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700121bool TouchedWindow::hasTouchingPointer(DeviceId deviceId, int32_t pointerId) const {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800122 const auto stateIt = mDeviceStates.find(deviceId);
123 if (stateIt == mDeviceStates.end()) {
124 return false;
125 }
126 const DeviceState& state = stateIt->second;
127 return hasPointerId(state.touchingPointers, pointerId);
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700128}
129
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800130std::vector<PointerProperties> TouchedWindow::getTouchingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700131 const auto stateIt = mDeviceStates.find(deviceId);
132 if (stateIt == mDeviceStates.end()) {
133 return {};
134 }
135 const DeviceState& state = stateIt->second;
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800136 return state.touchingPointers;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700137}
138
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700139void TouchedWindow::removeTouchingPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700140 std::bitset<MAX_POINTER_ID + 1> pointerIds;
141 pointerIds.set(pointerId, true);
142
143 removeTouchingPointers(deviceId, pointerIds);
144}
145
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700146void TouchedWindow::removeTouchingPointers(DeviceId deviceId,
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700147 std::bitset<MAX_POINTER_ID + 1> pointers) {
148 const auto stateIt = mDeviceStates.find(deviceId);
149 if (stateIt == mDeviceStates.end()) {
150 return;
151 }
152 DeviceState& state = stateIt->second;
153
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800154 std::erase_if(state.touchingPointers, [&pointers](const PointerProperties& properties) {
155 return pointers.test(properties.id);
156 });
157
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700158 state.pilferingPointerIds &= ~pointers;
159
160 if (!state.hasPointers()) {
161 mDeviceStates.erase(stateIt);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -0800162 }
163}
164
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -0700165bool TouchedWindow::hasActiveStylus() const {
166 for (const auto& [_, state] : mDeviceStates) {
167 for (const PointerProperties& properties : state.touchingPointers) {
168 if (properties.toolType == ToolType::STYLUS) {
169 return true;
170 }
171 }
172 for (const PointerProperties& properties : state.hoveringPointers) {
173 if (properties.toolType == ToolType::STYLUS) {
174 return true;
175 }
176 }
177 }
178 return false;
179}
180
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700181std::set<DeviceId> TouchedWindow::getTouchingDeviceIds() const {
182 std::set<DeviceId> deviceIds;
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +0000183 for (const auto& [deviceId, deviceState] : mDeviceStates) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800184 if (!deviceState.touchingPointers.empty()) {
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +0000185 deviceIds.insert(deviceId);
186 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700187 }
188 return deviceIds;
189}
190
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700191bool TouchedWindow::hasPilferingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700192 const auto stateIt = mDeviceStates.find(deviceId);
193 if (stateIt == mDeviceStates.end()) {
194 return false;
195 }
196 const DeviceState& state = stateIt->second;
197
198 return state.pilferingPointerIds.any();
199}
200
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700201void TouchedWindow::addPilferingPointers(DeviceId deviceId,
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700202 std::bitset<MAX_POINTER_ID + 1> pointerIds) {
203 mDeviceStates[deviceId].pilferingPointerIds |= pointerIds;
204}
205
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700206void TouchedWindow::addPilferingPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700207 mDeviceStates[deviceId].pilferingPointerIds.set(pointerId);
208}
209
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700210std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getPilferingPointers(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700211 const auto stateIt = mDeviceStates.find(deviceId);
212 if (stateIt == mDeviceStates.end()) {
213 return {};
214 }
215 const DeviceState& state = stateIt->second;
216
217 return state.pilferingPointerIds;
218}
219
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700220std::map<DeviceId, std::bitset<MAX_POINTER_ID + 1>> TouchedWindow::getPilferingPointers() const {
221 std::map<DeviceId, std::bitset<MAX_POINTER_ID + 1>> out;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700222 for (const auto& [deviceId, state] : mDeviceStates) {
223 out.emplace(deviceId, state.pilferingPointerIds);
224 }
225 return out;
226}
227
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700228std::optional<nsecs_t> TouchedWindow::getDownTimeInTarget(DeviceId deviceId) const {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700229 const auto stateIt = mDeviceStates.find(deviceId);
230 if (stateIt == mDeviceStates.end()) {
231 return {};
232 }
233 const DeviceState& state = stateIt->second;
234 return state.downTimeInTarget;
235}
236
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700237void TouchedWindow::trySetDownTimeInTarget(DeviceId deviceId, nsecs_t downTime) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700238 auto [stateIt, _] = mDeviceStates.try_emplace(deviceId);
239 DeviceState& state = stateIt->second;
240
241 if (!state.downTimeInTarget) {
242 state.downTimeInTarget = downTime;
243 }
244}
245
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700246void TouchedWindow::removeAllTouchingPointersForDevice(DeviceId deviceId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700247 const auto stateIt = mDeviceStates.find(deviceId);
248 if (stateIt == mDeviceStates.end()) {
249 return;
250 }
251 DeviceState& state = stateIt->second;
252
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800253 state.touchingPointers.clear();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700254 state.pilferingPointerIds.reset();
255 state.downTimeInTarget.reset();
256
257 if (!state.hasPointers()) {
258 mDeviceStates.erase(stateIt);
259 }
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -0700260}
261
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700262void TouchedWindow::removeHoveringPointer(DeviceId deviceId, int32_t pointerId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700263 const auto stateIt = mDeviceStates.find(deviceId);
264 if (stateIt == mDeviceStates.end()) {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000265 return;
266 }
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700267 DeviceState& state = stateIt->second;
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000268
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800269 std::erase_if(state.hoveringPointers, [&pointerId](const PointerProperties& properties) {
270 return properties.id == pointerId;
271 });
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700272
273 if (!state.hasPointers()) {
274 mDeviceStates.erase(stateIt);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000275 }
276}
277
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700278void TouchedWindow::removeAllHoveringPointersForDevice(DeviceId deviceId) {
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700279 const auto stateIt = mDeviceStates.find(deviceId);
280 if (stateIt == mDeviceStates.end()) {
281 return;
282 }
283 DeviceState& state = stateIt->second;
284
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800285 state.hoveringPointers.clear();
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700286
287 if (!state.hasPointers()) {
288 mDeviceStates.erase(stateIt);
289 }
290}
291
292std::string TouchedWindow::deviceStateToString(const TouchedWindow::DeviceState& state) {
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800293 return StringPrintf("[touchingPointers=%s, "
294 "downTimeInTarget=%s, hoveringPointers=%s, pilferingPointerIds=%s]",
295 dumpVector(state.touchingPointers, streamableToString).c_str(),
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700296 toString(state.downTimeInTarget).c_str(),
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800297 dumpVector(state.hoveringPointers, streamableToString).c_str(),
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700298 bitsetToString(state.pilferingPointerIds).c_str());
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -0700299}
300
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800301std::string TouchedWindow::dump() const {
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000302 std::string out;
Siarhei Vishniakou0836a302023-05-03 13:54:30 -0700303 std::string deviceStates =
304 dumpMap(mDeviceStates, constToString, TouchedWindow::deviceStateToString);
305 out += StringPrintf("name='%s', targetFlags=%s, mDeviceStates=%s\n",
306 windowHandle->getName().c_str(), targetFlags.string().c_str(),
307 deviceStates.c_str());
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +0000308 return out;
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800309}
310
Siarhei Vishniakou72945a02023-09-18 18:30:25 -0700311std::ostream& operator<<(std::ostream& out, const TouchedWindow& window) {
312 out << window.dump();
313 return out;
314}
315
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800316} // namespace inputdispatcher
317} // namespace android