1 /*
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
19 #include <android-base/logging.h>
20 #include <android-base/stringprintf.h>
21 #include <input/PrintTools.h>
22
23 using android::base::StringPrintf;
24
25 namespace android {
26
27 namespace inputdispatcher {
28
hasHoveringPointers() const29 bool TouchedWindow::hasHoveringPointers() const {
30 for (const auto& [_, state] : mDeviceStates) {
31 if (state.hoveringPointerIds.any()) {
32 return true;
33 }
34 }
35 return false;
36 }
37
hasHoveringPointers(int32_t deviceId) const38 bool TouchedWindow::hasHoveringPointers(int32_t deviceId) const {
39 const auto stateIt = mDeviceStates.find(deviceId);
40 if (stateIt == mDeviceStates.end()) {
41 return false;
42 }
43 const DeviceState& state = stateIt->second;
44
45 return state.hoveringPointerIds.any();
46 }
47
clearHoveringPointers()48 void TouchedWindow::clearHoveringPointers() {
49 for (auto& [_, state] : mDeviceStates) {
50 state.hoveringPointerIds.reset();
51 }
52
53 std::erase_if(mDeviceStates, [](const auto& pair) { return !pair.second.hasPointers(); });
54 }
55
hasHoveringPointer(int32_t deviceId,int32_t pointerId) const56 bool TouchedWindow::hasHoveringPointer(int32_t deviceId, int32_t pointerId) const {
57 const auto stateIt = mDeviceStates.find(deviceId);
58 if (stateIt == mDeviceStates.end()) {
59 return false;
60 }
61 const DeviceState& state = stateIt->second;
62
63 return state.hoveringPointerIds.test(pointerId);
64 }
65
addHoveringPointer(int32_t deviceId,int32_t pointerId)66 void TouchedWindow::addHoveringPointer(int32_t deviceId, int32_t pointerId) {
67 mDeviceStates[deviceId].hoveringPointerIds.set(pointerId);
68 }
69
addTouchingPointer(int32_t deviceId,int32_t pointerId)70 void TouchedWindow::addTouchingPointer(int32_t deviceId, int32_t pointerId) {
71 mDeviceStates[deviceId].touchingPointerIds.set(pointerId);
72 }
73
addTouchingPointers(int32_t deviceId,std::bitset<MAX_POINTER_ID+1> pointers)74 void TouchedWindow::addTouchingPointers(int32_t deviceId,
75 std::bitset<MAX_POINTER_ID + 1> pointers) {
76 mDeviceStates[deviceId].touchingPointerIds |= pointers;
77 }
78
hasTouchingPointers() const79 bool TouchedWindow::hasTouchingPointers() const {
80 for (const auto& [_, state] : mDeviceStates) {
81 if (state.touchingPointerIds.any()) {
82 return true;
83 }
84 }
85 return false;
86 }
87
hasTouchingPointers(int32_t deviceId) const88 bool TouchedWindow::hasTouchingPointers(int32_t deviceId) const {
89 return getTouchingPointers(deviceId).any();
90 }
91
hasTouchingPointer(int32_t deviceId,int32_t pointerId) const92 bool TouchedWindow::hasTouchingPointer(int32_t deviceId, int32_t pointerId) const {
93 return getTouchingPointers(deviceId).test(pointerId);
94 }
95
getTouchingPointers(int32_t deviceId) const96 std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getTouchingPointers(int32_t deviceId) const {
97 const auto stateIt = mDeviceStates.find(deviceId);
98 if (stateIt == mDeviceStates.end()) {
99 return {};
100 }
101 const DeviceState& state = stateIt->second;
102
103 return state.touchingPointerIds;
104 }
105
removeTouchingPointer(int32_t deviceId,int32_t pointerId)106 void TouchedWindow::removeTouchingPointer(int32_t deviceId, int32_t pointerId) {
107 std::bitset<MAX_POINTER_ID + 1> pointerIds;
108 pointerIds.set(pointerId, true);
109
110 removeTouchingPointers(deviceId, pointerIds);
111 }
112
removeTouchingPointers(int32_t deviceId,std::bitset<MAX_POINTER_ID+1> pointers)113 void TouchedWindow::removeTouchingPointers(int32_t deviceId,
114 std::bitset<MAX_POINTER_ID + 1> pointers) {
115 const auto stateIt = mDeviceStates.find(deviceId);
116 if (stateIt == mDeviceStates.end()) {
117 return;
118 }
119 DeviceState& state = stateIt->second;
120
121 state.touchingPointerIds &= ~pointers;
122 state.pilferingPointerIds &= ~pointers;
123
124 if (!state.hasPointers()) {
125 mDeviceStates.erase(stateIt);
126 }
127 }
128
getTouchingDeviceIds() const129 std::set<int32_t> TouchedWindow::getTouchingDeviceIds() const {
130 std::set<int32_t> deviceIds;
131 for (const auto& [deviceId, _] : mDeviceStates) {
132 deviceIds.insert(deviceId);
133 }
134 return deviceIds;
135 }
136
getActiveDeviceIds() const137 std::set<int32_t> TouchedWindow::getActiveDeviceIds() const {
138 std::set<int32_t> out;
139 for (const auto& [deviceId, _] : mDeviceStates) {
140 out.emplace(deviceId);
141 }
142 return out;
143 }
144
hasPilferingPointers(int32_t deviceId) const145 bool TouchedWindow::hasPilferingPointers(int32_t deviceId) const {
146 const auto stateIt = mDeviceStates.find(deviceId);
147 if (stateIt == mDeviceStates.end()) {
148 return false;
149 }
150 const DeviceState& state = stateIt->second;
151
152 return state.pilferingPointerIds.any();
153 }
154
addPilferingPointers(int32_t deviceId,std::bitset<MAX_POINTER_ID+1> pointerIds)155 void TouchedWindow::addPilferingPointers(int32_t deviceId,
156 std::bitset<MAX_POINTER_ID + 1> pointerIds) {
157 mDeviceStates[deviceId].pilferingPointerIds |= pointerIds;
158 }
159
addPilferingPointer(int32_t deviceId,int32_t pointerId)160 void TouchedWindow::addPilferingPointer(int32_t deviceId, int32_t pointerId) {
161 mDeviceStates[deviceId].pilferingPointerIds.set(pointerId);
162 }
163
getPilferingPointers(int32_t deviceId) const164 std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getPilferingPointers(int32_t deviceId) const {
165 const auto stateIt = mDeviceStates.find(deviceId);
166 if (stateIt == mDeviceStates.end()) {
167 return {};
168 }
169 const DeviceState& state = stateIt->second;
170
171 return state.pilferingPointerIds;
172 }
173
getPilferingPointers() const174 std::map<int32_t, std::bitset<MAX_POINTER_ID + 1>> TouchedWindow::getPilferingPointers() const {
175 std::map<int32_t, std::bitset<MAX_POINTER_ID + 1>> out;
176 for (const auto& [deviceId, state] : mDeviceStates) {
177 out.emplace(deviceId, state.pilferingPointerIds);
178 }
179 return out;
180 }
181
getDownTimeInTarget(int32_t deviceId) const182 std::optional<nsecs_t> TouchedWindow::getDownTimeInTarget(int32_t deviceId) const {
183 const auto stateIt = mDeviceStates.find(deviceId);
184 if (stateIt == mDeviceStates.end()) {
185 return {};
186 }
187 const DeviceState& state = stateIt->second;
188 return state.downTimeInTarget;
189 }
190
trySetDownTimeInTarget(int32_t deviceId,nsecs_t downTime)191 void TouchedWindow::trySetDownTimeInTarget(int32_t deviceId, nsecs_t downTime) {
192 auto [stateIt, _] = mDeviceStates.try_emplace(deviceId);
193 DeviceState& state = stateIt->second;
194
195 if (!state.downTimeInTarget) {
196 state.downTimeInTarget = downTime;
197 }
198 }
199
removeAllTouchingPointersForDevice(int32_t deviceId)200 void TouchedWindow::removeAllTouchingPointersForDevice(int32_t deviceId) {
201 const auto stateIt = mDeviceStates.find(deviceId);
202 if (stateIt == mDeviceStates.end()) {
203 return;
204 }
205 DeviceState& state = stateIt->second;
206
207 state.touchingPointerIds.reset();
208 state.pilferingPointerIds.reset();
209 state.downTimeInTarget.reset();
210
211 if (!state.hasPointers()) {
212 mDeviceStates.erase(stateIt);
213 }
214 }
215
removeHoveringPointer(int32_t deviceId,int32_t pointerId)216 void TouchedWindow::removeHoveringPointer(int32_t deviceId, int32_t pointerId) {
217 const auto stateIt = mDeviceStates.find(deviceId);
218 if (stateIt == mDeviceStates.end()) {
219 return;
220 }
221 DeviceState& state = stateIt->second;
222
223 state.hoveringPointerIds.set(pointerId, false);
224
225 if (!state.hasPointers()) {
226 mDeviceStates.erase(stateIt);
227 }
228 }
229
removeAllHoveringPointersForDevice(int32_t deviceId)230 void TouchedWindow::removeAllHoveringPointersForDevice(int32_t deviceId) {
231 const auto stateIt = mDeviceStates.find(deviceId);
232 if (stateIt == mDeviceStates.end()) {
233 return;
234 }
235 DeviceState& state = stateIt->second;
236
237 state.hoveringPointerIds.reset();
238
239 if (!state.hasPointers()) {
240 mDeviceStates.erase(stateIt);
241 }
242 }
243
deviceStateToString(const TouchedWindow::DeviceState & state)244 std::string TouchedWindow::deviceStateToString(const TouchedWindow::DeviceState& state) {
245 return StringPrintf("[touchingPointerIds=%s, "
246 "downTimeInTarget=%s, hoveringPointerIds=%s, pilferingPointerIds=%s]",
247 bitsetToString(state.touchingPointerIds).c_str(),
248 toString(state.downTimeInTarget).c_str(),
249 bitsetToString(state.hoveringPointerIds).c_str(),
250 bitsetToString(state.pilferingPointerIds).c_str());
251 }
252
dump() const253 std::string TouchedWindow::dump() const {
254 std::string out;
255 std::string deviceStates =
256 dumpMap(mDeviceStates, constToString, TouchedWindow::deviceStateToString);
257 out += StringPrintf("name='%s', targetFlags=%s, mDeviceStates=%s\n",
258 windowHandle->getName().c_str(), targetFlags.string().c_str(),
259 deviceStates.c_str());
260 return out;
261 }
262
263 } // namespace inputdispatcher
264 } // namespace android
265