1 /*
2 * Copyright (C) 2010 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 #define LOG_TAG "PointerController"
18 //#define LOG_NDEBUG 0
19
20 #include "PointerController.h"
21
22 #include <SkBlendMode.h>
23 #include <SkCanvas.h>
24 #include <SkColor.h>
25 #include <android-base/thread_annotations.h>
26
27 #include "PointerControllerContext.h"
28
29 namespace android {
30
31 namespace {
32
33 const ui::Transform kIdentityTransform;
34
35 } // namespace
36
37 // --- PointerController::DisplayInfoListener ---
38
onWindowInfosChanged(const std::vector<android::gui::WindowInfo> &,const std::vector<android::gui::DisplayInfo> & displayInfos)39 void PointerController::DisplayInfoListener::onWindowInfosChanged(
40 const std::vector<android::gui::WindowInfo>&,
41 const std::vector<android::gui::DisplayInfo>& displayInfos) {
42 std::scoped_lock lock(mLock);
43 if (mPointerController == nullptr) return;
44
45 // PointerController uses DisplayInfoListener's lock.
46 base::ScopedLockAssertion assumeLocked(mPointerController->getLock());
47 mPointerController->onDisplayInfosChangedLocked(displayInfos);
48 }
49
onPointerControllerDestroyed()50 void PointerController::DisplayInfoListener::onPointerControllerDestroyed() {
51 std::scoped_lock lock(mLock);
52 mPointerController = nullptr;
53 }
54
55 // --- PointerController ---
56
create(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController)57 std::shared_ptr<PointerController> PointerController::create(
58 const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
59 const sp<SpriteController>& spriteController) {
60 // using 'new' to access non-public constructor
61 std::shared_ptr<PointerController> controller = std::shared_ptr<PointerController>(
62 new PointerController(policy, looper, spriteController));
63
64 /*
65 * Now we need to hook up the constructed PointerController object to its callbacks.
66 *
67 * This must be executed after the constructor but before any other methods on PointerController
68 * in order to ensure that the fully constructed object is visible on the Looper thread, since
69 * that may be a different thread than where the PointerController is initially constructed.
70 *
71 * Unfortunately, this cannot be done as part of the constructor since we need to hand out
72 * weak_ptr's which themselves cannot be constructed until there's at least one shared_ptr.
73 */
74
75 controller->mContext.setHandlerController(controller);
76 controller->mContext.setCallbackController(controller);
77 return controller;
78 }
79
PointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController)80 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
81 const sp<Looper>& looper,
82 const sp<SpriteController>& spriteController)
83 : PointerController(
84 policy, looper, spriteController,
85 [](const sp<android::gui::WindowInfosListener>& listener) {
86 SurfaceComposerClient::getDefault()->addWindowInfosListener(listener);
87 },
__anon20adca130302(const sp<android::gui::WindowInfosListener>& listener) 88 [](const sp<android::gui::WindowInfosListener>& listener) {
89 SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener);
90 }) {}
91
PointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController,WindowListenerConsumer registerListener,WindowListenerConsumer unregisterListener)92 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
93 const sp<Looper>& looper,
94 const sp<SpriteController>& spriteController,
95 WindowListenerConsumer registerListener,
96 WindowListenerConsumer unregisterListener)
97 : mContext(policy, looper, spriteController, *this),
98 mCursorController(mContext),
99 mDisplayInfoListener(new DisplayInfoListener(this)),
100 mUnregisterWindowInfosListener(std::move(unregisterListener)) {
101 std::scoped_lock lock(getLock());
102 mLocked.presentation = Presentation::SPOT;
103 registerListener(mDisplayInfoListener);
104 }
105
~PointerController()106 PointerController::~PointerController() {
107 mDisplayInfoListener->onPointerControllerDestroyed();
108 mUnregisterWindowInfosListener(mDisplayInfoListener);
109 mContext.getPolicy()->onPointerDisplayIdChanged(ADISPLAY_ID_NONE, 0, 0);
110 }
111
getLock() const112 std::mutex& PointerController::getLock() const {
113 return mDisplayInfoListener->mLock;
114 }
115
getBounds(float * outMinX,float * outMinY,float * outMaxX,float * outMaxY) const116 bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
117 float* outMaxY) const {
118 return mCursorController.getBounds(outMinX, outMinY, outMaxX, outMaxY);
119 }
120
move(float deltaX,float deltaY)121 void PointerController::move(float deltaX, float deltaY) {
122 const int32_t displayId = mCursorController.getDisplayId();
123 vec2 transformed;
124 {
125 std::scoped_lock lock(getLock());
126 const auto& transform = getTransformForDisplayLocked(displayId);
127 transformed = transformWithoutTranslation(transform, {deltaX, deltaY});
128 }
129 mCursorController.move(transformed.x, transformed.y);
130 }
131
setButtonState(int32_t buttonState)132 void PointerController::setButtonState(int32_t buttonState) {
133 mCursorController.setButtonState(buttonState);
134 }
135
getButtonState() const136 int32_t PointerController::getButtonState() const {
137 return mCursorController.getButtonState();
138 }
139
setPosition(float x,float y)140 void PointerController::setPosition(float x, float y) {
141 const int32_t displayId = mCursorController.getDisplayId();
142 vec2 transformed;
143 {
144 std::scoped_lock lock(getLock());
145 const auto& transform = getTransformForDisplayLocked(displayId);
146 transformed = transform.transform(x, y);
147 }
148 mCursorController.setPosition(transformed.x, transformed.y);
149 }
150
getPosition(float * outX,float * outY) const151 void PointerController::getPosition(float* outX, float* outY) const {
152 const int32_t displayId = mCursorController.getDisplayId();
153 mCursorController.getPosition(outX, outY);
154 {
155 std::scoped_lock lock(getLock());
156 const auto& transform = getTransformForDisplayLocked(displayId);
157 const auto xy = transform.inverse().transform(*outX, *outY);
158 *outX = xy.x;
159 *outY = xy.y;
160 }
161 }
162
getDisplayId() const163 int32_t PointerController::getDisplayId() const {
164 return mCursorController.getDisplayId();
165 }
166
fade(Transition transition)167 void PointerController::fade(Transition transition) {
168 std::scoped_lock lock(getLock());
169 mCursorController.fade(transition);
170 }
171
unfade(Transition transition)172 void PointerController::unfade(Transition transition) {
173 std::scoped_lock lock(getLock());
174 mCursorController.unfade(transition);
175 }
176
setPresentation(Presentation presentation)177 void PointerController::setPresentation(Presentation presentation) {
178 std::scoped_lock lock(getLock());
179
180 if (mLocked.presentation == presentation) {
181 return;
182 }
183
184 mLocked.presentation = presentation;
185
186 if (!mCursorController.isViewportValid()) {
187 return;
188 }
189
190 if (presentation == Presentation::POINTER) {
191 mCursorController.getAdditionalMouseResources();
192 clearSpotsLocked();
193 }
194 }
195
setSpots(const PointerCoords * spotCoords,const uint32_t * spotIdToIndex,BitSet32 spotIdBits,int32_t displayId)196 void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
197 BitSet32 spotIdBits, int32_t displayId) {
198 std::scoped_lock lock(getLock());
199 std::array<PointerCoords, MAX_POINTERS> outSpotCoords{};
200 const ui::Transform& transform = getTransformForDisplayLocked(displayId);
201
202 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
203 const uint32_t index = spotIdToIndex[idBits.clearFirstMarkedBit()];
204
205 const vec2 xy = transform.transform(spotCoords[index].getXYValue());
206 outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
207 outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
208
209 float pressure = spotCoords[index].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
210 outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
211 }
212
213 auto it = mLocked.spotControllers.find(displayId);
214 if (it == mLocked.spotControllers.end()) {
215 mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
216 }
217 mLocked.spotControllers.at(displayId).setSpots(outSpotCoords.data(), spotIdToIndex, spotIdBits);
218 }
219
clearSpots()220 void PointerController::clearSpots() {
221 std::scoped_lock lock(getLock());
222 clearSpotsLocked();
223 }
224
clearSpotsLocked()225 void PointerController::clearSpotsLocked() {
226 for (auto& [displayID, spotController] : mLocked.spotControllers) {
227 spotController.clearSpots();
228 }
229 }
230
setInactivityTimeout(InactivityTimeout inactivityTimeout)231 void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
232 mContext.setInactivityTimeout(inactivityTimeout);
233 }
234
reloadPointerResources()235 void PointerController::reloadPointerResources() {
236 std::scoped_lock lock(getLock());
237
238 for (auto& [displayID, spotController] : mLocked.spotControllers) {
239 spotController.reloadSpotResources();
240 }
241
242 if (mCursorController.resourcesLoaded()) {
243 bool getAdditionalMouseResources = false;
244 if (mLocked.presentation == PointerController::Presentation::POINTER) {
245 getAdditionalMouseResources = true;
246 }
247 mCursorController.reloadPointerResources(getAdditionalMouseResources);
248 }
249 }
250
setDisplayViewport(const DisplayViewport & viewport)251 void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
252 std::scoped_lock lock(getLock());
253
254 bool getAdditionalMouseResources = false;
255 if (mLocked.presentation == PointerController::Presentation::POINTER) {
256 getAdditionalMouseResources = true;
257 }
258 mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
259 if (viewport.displayId != mLocked.pointerDisplayId) {
260 float xPos, yPos;
261 mCursorController.getPosition(&xPos, &yPos);
262 mContext.getPolicy()->onPointerDisplayIdChanged(viewport.displayId, xPos, yPos);
263 mLocked.pointerDisplayId = viewport.displayId;
264 }
265 }
266
updatePointerIcon(int32_t iconId)267 void PointerController::updatePointerIcon(int32_t iconId) {
268 std::scoped_lock lock(getLock());
269 mCursorController.updatePointerIcon(iconId);
270 }
271
setCustomPointerIcon(const SpriteIcon & icon)272 void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
273 std::scoped_lock lock(getLock());
274 mCursorController.setCustomPointerIcon(icon);
275 }
276
doInactivityTimeout()277 void PointerController::doInactivityTimeout() {
278 fade(Transition::GRADUAL);
279 }
280
onDisplayViewportsUpdated(std::vector<DisplayViewport> & viewports)281 void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports) {
282 std::unordered_set<int32_t> displayIdSet;
283 for (const DisplayViewport& viewport : viewports) {
284 displayIdSet.insert(viewport.displayId);
285 }
286
287 std::scoped_lock lock(getLock());
288 for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) {
289 int32_t displayID = it->first;
290 if (!displayIdSet.count(displayID)) {
291 /*
292 * Ensures that an in-progress animation won't dereference
293 * a null pointer to TouchSpotController.
294 */
295 mContext.removeAnimationCallback(displayID);
296 it = mLocked.spotControllers.erase(it);
297 } else {
298 ++it;
299 }
300 }
301 }
302
onDisplayInfosChangedLocked(const std::vector<gui::DisplayInfo> & displayInfo)303 void PointerController::onDisplayInfosChangedLocked(
304 const std::vector<gui::DisplayInfo>& displayInfo) {
305 mLocked.mDisplayInfos = displayInfo;
306 }
307
getTransformForDisplayLocked(int displayId) const308 const ui::Transform& PointerController::getTransformForDisplayLocked(int displayId) const {
309 const auto& di = mLocked.mDisplayInfos;
310 auto it = std::find_if(di.begin(), di.end(), [displayId](const gui::DisplayInfo& info) {
311 return info.displayId == displayId;
312 });
313 return it != di.end() ? it->transform : kIdentityTransform;
314 }
315
316 } // namespace android
317