1 /*
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 
17 #include <input/InputWindow.h>
18 
19 #include "InputTarget.h"
20 
21 #include "TouchState.h"
22 
23 using android::InputWindowHandle;
24 
25 namespace android::inputdispatcher {
26 
TouchState()27 TouchState::TouchState()
28       : down(false), split(false), deviceId(-1), source(0), displayId(ADISPLAY_ID_NONE) {}
29 
~TouchState()30 TouchState::~TouchState() {}
31 
reset()32 void TouchState::reset() {
33     down = false;
34     split = false;
35     deviceId = -1;
36     source = 0;
37     displayId = ADISPLAY_ID_NONE;
38     windows.clear();
39     portalWindows.clear();
40     gestureMonitors.clear();
41 }
42 
copyFrom(const TouchState & other)43 void TouchState::copyFrom(const TouchState& other) {
44     down = other.down;
45     split = other.split;
46     deviceId = other.deviceId;
47     source = other.source;
48     displayId = other.displayId;
49     windows = other.windows;
50     portalWindows = other.portalWindows;
51     gestureMonitors = other.gestureMonitors;
52 }
53 
addOrUpdateWindow(const sp<InputWindowHandle> & windowHandle,int32_t targetFlags,BitSet32 pointerIds)54 void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags,
55                                    BitSet32 pointerIds) {
56     if (targetFlags & InputTarget::FLAG_SPLIT) {
57         split = true;
58     }
59 
60     for (size_t i = 0; i < windows.size(); i++) {
61         TouchedWindow& touchedWindow = windows[i];
62         if (touchedWindow.windowHandle == windowHandle) {
63             touchedWindow.targetFlags |= targetFlags;
64             if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
65                 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
66             }
67             touchedWindow.pointerIds.value |= pointerIds.value;
68             return;
69         }
70     }
71 
72     TouchedWindow touchedWindow;
73     touchedWindow.windowHandle = windowHandle;
74     touchedWindow.targetFlags = targetFlags;
75     touchedWindow.pointerIds = pointerIds;
76     windows.push_back(touchedWindow);
77 }
78 
addPortalWindow(const sp<InputWindowHandle> & windowHandle)79 void TouchState::addPortalWindow(const sp<InputWindowHandle>& windowHandle) {
80     size_t numWindows = portalWindows.size();
81     for (size_t i = 0; i < numWindows; i++) {
82         if (portalWindows[i] == windowHandle) {
83             return;
84         }
85     }
86     portalWindows.push_back(windowHandle);
87 }
88 
addGestureMonitors(const std::vector<TouchedMonitor> & newMonitors)89 void TouchState::addGestureMonitors(const std::vector<TouchedMonitor>& newMonitors) {
90     const size_t newSize = gestureMonitors.size() + newMonitors.size();
91     gestureMonitors.reserve(newSize);
92     gestureMonitors.insert(std::end(gestureMonitors), std::begin(newMonitors),
93                            std::end(newMonitors));
94 }
95 
removeWindowByToken(const sp<IBinder> & token)96 void TouchState::removeWindowByToken(const sp<IBinder>& token) {
97     for (size_t i = 0; i < windows.size(); i++) {
98         if (windows[i].windowHandle->getToken() == token) {
99             windows.erase(windows.begin() + i);
100             return;
101         }
102     }
103 }
104 
filterNonAsIsTouchWindows()105 void TouchState::filterNonAsIsTouchWindows() {
106     for (size_t i = 0; i < windows.size();) {
107         TouchedWindow& window = windows[i];
108         if (window.targetFlags &
109             (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
110             window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
111             window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
112             i += 1;
113         } else {
114             windows.erase(windows.begin() + i);
115         }
116     }
117 }
118 
filterNonMonitors()119 void TouchState::filterNonMonitors() {
120     windows.clear();
121     portalWindows.clear();
122 }
123 
getFirstForegroundWindowHandle() const124 sp<InputWindowHandle> TouchState::getFirstForegroundWindowHandle() const {
125     for (size_t i = 0; i < windows.size(); i++) {
126         const TouchedWindow& window = windows[i];
127         if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
128             return window.windowHandle;
129         }
130     }
131     return nullptr;
132 }
133 
isSlippery() const134 bool TouchState::isSlippery() const {
135     // Must have exactly one foreground window.
136     bool haveSlipperyForegroundWindow = false;
137     for (const TouchedWindow& window : windows) {
138         if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
139             if (haveSlipperyForegroundWindow ||
140                 !(window.windowHandle->getInfo()->layoutParamsFlags &
141                   InputWindowInfo::FLAG_SLIPPERY)) {
142                 return false;
143             }
144             haveSlipperyForegroundWindow = true;
145         }
146     }
147     return haveSlipperyForegroundWindow;
148 }
149 
150 } // namespace android::inputdispatcher
151