• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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