blob: c21af9e0b587982696f55f2a869487a6b6504457 [file] [log] [blame]
Garfield Tane84e6f92019-08-29 17:28:41 -07001/*
2 * Copyright (C) 2019 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
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -080017#include <android-base/stringprintf.h>
chaviw98318de2021-05-19 16:45:23 -050018#include <gui/WindowInfo.h>
Garfield Tane84e6f92019-08-29 17:28:41 -070019
20#include "InputTarget.h"
Garfield Tane84e6f92019-08-29 17:28:41 -070021#include "TouchState.h"
22
Siarhei Vishniakou253f4642022-11-09 13:42:06 -080023using namespace android::ftl::flag_operators;
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -080024using android::base::StringPrintf;
chaviw98318de2021-05-19 16:45:23 -050025using android::gui::WindowInfo;
26using android::gui::WindowInfoHandle;
Garfield Tane84e6f92019-08-29 17:28:41 -070027
28namespace android::inputdispatcher {
29
Garfield Tane84e6f92019-08-29 17:28:41 -070030void TouchState::reset() {
Prabir Pradhane680f9b2022-02-04 04:24:00 -080031 *this = TouchState();
Garfield Tane84e6f92019-08-29 17:28:41 -070032}
33
Siarhei Vishniakou253f4642022-11-09 13:42:06 -080034void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
35 ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
36 std::optional<nsecs_t> eventTime) {
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -080037 for (TouchedWindow& touchedWindow : windows) {
Garfield Tane84e6f92019-08-29 17:28:41 -070038 if (touchedWindow.windowHandle == windowHandle) {
39 touchedWindow.targetFlags |= targetFlags;
Siarhei Vishniakou253f4642022-11-09 13:42:06 -080040 if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
41 touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_IS);
Garfield Tane84e6f92019-08-29 17:28:41 -070042 }
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000043 // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
44 // downTime set initially. Need to update existing window when an pointer is down for
45 // the window.
Garfield Tane84e6f92019-08-29 17:28:41 -070046 touchedWindow.pointerIds.value |= pointerIds.value;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000047 if (!touchedWindow.firstDownTimeInTarget.has_value()) {
48 touchedWindow.firstDownTimeInTarget = eventTime;
49 }
Garfield Tane84e6f92019-08-29 17:28:41 -070050 return;
51 }
52 }
53
54 TouchedWindow touchedWindow;
55 touchedWindow.windowHandle = windowHandle;
56 touchedWindow.targetFlags = targetFlags;
57 touchedWindow.pointerIds = pointerIds;
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000058 touchedWindow.firstDownTimeInTarget = eventTime;
Garfield Tane84e6f92019-08-29 17:28:41 -070059 windows.push_back(touchedWindow);
60}
61
Garfield Tane84e6f92019-08-29 17:28:41 -070062void TouchState::removeWindowByToken(const sp<IBinder>& token) {
63 for (size_t i = 0; i < windows.size(); i++) {
64 if (windows[i].windowHandle->getToken() == token) {
65 windows.erase(windows.begin() + i);
66 return;
67 }
68 }
69}
70
71void TouchState::filterNonAsIsTouchWindows() {
72 for (size_t i = 0; i < windows.size();) {
73 TouchedWindow& window = windows[i];
Siarhei Vishniakou253f4642022-11-09 13:42:06 -080074 if (window.targetFlags.any(InputTarget::Flags::DISPATCH_AS_IS |
75 InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
76 window.targetFlags.clear(InputTarget::DISPATCH_MASK);
77 window.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS;
Garfield Tane84e6f92019-08-29 17:28:41 -070078 i += 1;
79 } else {
80 windows.erase(windows.begin() + i);
81 }
82 }
83}
84
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000085void TouchState::cancelPointersForWindowsExcept(const BitSet32 pointerIds,
86 const sp<IBinder>& token) {
87 if (pointerIds.isEmpty()) return;
88 std::for_each(windows.begin(), windows.end(), [&pointerIds, &token](TouchedWindow& w) {
89 if (w.windowHandle->getToken() != token) {
90 w.pointerIds &= BitSet32(~pointerIds.value);
91 }
92 });
93 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
94}
95
96void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) {
97 if (pointerIds.isEmpty()) return;
98 std::for_each(windows.begin(), windows.end(), [&pointerIds](TouchedWindow& w) {
99 if (!w.isPilferingPointers) {
100 w.pointerIds &= BitSet32(~pointerIds.value);
101 }
102 });
103 std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
104}
105
chaviw98318de2021-05-19 16:45:23 -0500106sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700107 for (size_t i = 0; i < windows.size(); i++) {
108 const TouchedWindow& window = windows[i];
Siarhei Vishniakou253f4642022-11-09 13:42:06 -0800109 if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700110 return window.windowHandle;
111 }
112 }
113 return nullptr;
114}
115
116bool TouchState::isSlippery() const {
117 // Must have exactly one foreground window.
118 bool haveSlipperyForegroundWindow = false;
119 for (const TouchedWindow& window : windows) {
Siarhei Vishniakou253f4642022-11-09 13:42:06 -0800120 if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700121 if (haveSlipperyForegroundWindow ||
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800122 !window.windowHandle->getInfo()->inputConfig.test(
123 WindowInfo::InputConfig::SLIPPERY)) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700124 return false;
125 }
126 haveSlipperyForegroundWindow = true;
127 }
128 }
129 return haveSlipperyForegroundWindow;
130}
131
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000132sp<WindowInfoHandle> TouchState::getWallpaperWindow() const {
133 for (size_t i = 0; i < windows.size(); i++) {
134 const TouchedWindow& window = windows[i];
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800135 if (window.windowHandle->getInfo()->inputConfig.test(
136 gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000137 return window.windowHandle;
138 }
139 }
140 return nullptr;
141}
142
Siarhei Vishniakou3ad385b2022-11-04 10:09:53 -0700143bool TouchState::isDown() const {
144 return std::any_of(windows.begin(), windows.end(),
145 [](const TouchedWindow& window) { return !window.pointerIds.isEmpty(); });
146}
147
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800148std::string TouchState::dump() const {
149 std::string out;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800150 out += StringPrintf("deviceId=%d, source=%s\n", deviceId,
151 inputEventSourceToString(source).c_str());
Siarhei Vishniakou6e1e9872022-11-08 17:51:35 -0800152 if (!windows.empty()) {
153 out += " Windows:\n";
154 for (size_t i = 0; i < windows.size(); i++) {
155 const TouchedWindow& touchedWindow = windows[i];
156 out += StringPrintf(" %zu : ", i) + touchedWindow.dump();
157 }
158 } else {
159 out += " Windows: <none>\n";
160 }
161 return out;
162}
163
Garfield Tane84e6f92019-08-29 17:28:41 -0700164} // namespace android::inputdispatcher