xref: /aosp_15_r20/frameworks/base/libs/input/PointerController.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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/stringprintf.h>
26 #include <android-base/thread_annotations.h>
27 #include <ftl/enum.h>
28 #include <input/PrintTools.h>
29 
30 #include <mutex>
31 
32 #include "PointerControllerContext.h"
33 
34 #define INDENT "  "
35 #define INDENT2 "    "
36 #define INDENT3 "      "
37 
38 namespace android {
39 
40 namespace {
41 
42 const ui::Transform kIdentityTransform;
43 
44 } // namespace
45 
46 // --- PointerController::DisplayInfoListener ---
47 
onWindowInfosChanged(const gui::WindowInfosUpdate & update)48 void PointerController::DisplayInfoListener::onWindowInfosChanged(
49         const gui::WindowInfosUpdate& update) {
50     std::scoped_lock lock(mLock);
51     if (mPointerController == nullptr) return;
52 
53     // PointerController uses DisplayInfoListener's lock.
54     base::ScopedLockAssertion assumeLocked(mPointerController->getLock());
55     mPointerController->onDisplayInfosChangedLocked(update.displayInfos);
56 }
57 
onPointerControllerDestroyed()58 void PointerController::DisplayInfoListener::onPointerControllerDestroyed() {
59     std::scoped_lock lock(mLock);
60     mPointerController = nullptr;
61 }
62 
63 // --- PointerController ---
64 
create(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,SpriteController & spriteController,ControllerType type)65 std::shared_ptr<PointerController> PointerController::create(
66         const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
67         SpriteController& spriteController, ControllerType type) {
68     // using 'new' to access non-public constructor
69     std::shared_ptr<PointerController> controller;
70     switch (type) {
71         case ControllerType::MOUSE:
72             controller = std::shared_ptr<PointerController>(
73                     new MousePointerController(policy, looper, spriteController));
74             break;
75         case ControllerType::TOUCH:
76             controller = std::shared_ptr<PointerController>(
77                     new TouchPointerController(policy, looper, spriteController));
78             break;
79         case ControllerType::STYLUS:
80             controller = std::shared_ptr<PointerController>(
81                     new StylusPointerController(policy, looper, spriteController));
82             break;
83         default:
84             LOG_ALWAYS_FATAL("Invalid ControllerType: %d", static_cast<int>(type));
85     }
86 
87     /*
88      * Now we need to hook up the constructed PointerController object to its callbacks.
89      *
90      * This must be executed after the constructor but before any other methods on PointerController
91      * in order to ensure that the fully constructed object is visible on the Looper thread, since
92      * that may be a different thread than where the PointerController is initially constructed.
93      *
94      * Unfortunately, this cannot be done as part of the constructor since we need to hand out
95      * weak_ptr's which themselves cannot be constructed until there's at least one shared_ptr.
96      */
97 
98     controller->mContext.setHandlerController(controller);
99     controller->mContext.setCallbackController(controller);
100     return controller;
101 }
102 
PointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,SpriteController & spriteController)103 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
104                                      const sp<Looper>& looper, SpriteController& spriteController)
105       : PointerController(
106                 policy, looper, spriteController,
107                 [](const sp<android::gui::WindowInfosListener>& listener) {
108                     auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
109                                                       std::vector<android::gui::DisplayInfo>{});
110                     SurfaceComposerClient::getDefault()->addWindowInfosListener(listener,
111                                                                                 &initialInfo);
112                     return initialInfo.second;
113                 },
__anon84f4461d0302(const sp<android::gui::WindowInfosListener>& listener) 114                 [](const sp<android::gui::WindowInfosListener>& listener) {
115                     SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener);
116                 }) {}
117 
PointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,SpriteController & spriteController,const WindowListenerRegisterConsumer & registerListener,WindowListenerUnregisterConsumer unregisterListener)118 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
119                                      const sp<Looper>& looper, SpriteController& spriteController,
120                                      const WindowListenerRegisterConsumer& registerListener,
121                                      WindowListenerUnregisterConsumer unregisterListener)
122       : mContext(policy, looper, spriteController, *this),
123         mCursorController(mContext),
124         mDisplayInfoListener(sp<DisplayInfoListener>::make(this)),
125         mUnregisterWindowInfosListener(std::move(unregisterListener)) {
126     std::scoped_lock lock(getLock());
127     mLocked.presentation = Presentation::SPOT;
128     const auto& initialDisplayInfos = registerListener(mDisplayInfoListener);
129     onDisplayInfosChangedLocked(initialDisplayInfos);
130 }
131 
~PointerController()132 PointerController::~PointerController() {
133     mDisplayInfoListener->onPointerControllerDestroyed();
134     mUnregisterWindowInfosListener(mDisplayInfoListener);
135 }
136 
getLock() const137 std::mutex& PointerController::getLock() const {
138     return mDisplayInfoListener->mLock;
139 }
140 
move(float deltaX,float deltaY)141 vec2 PointerController::move(float deltaX, float deltaY) {
142     const ui::LogicalDisplayId displayId = mCursorController.getDisplayId();
143     ui::Transform transform;
144     {
145         std::scoped_lock lock(getLock());
146         transform = getTransformForDisplayLocked(displayId);
147     }
148 
149     const vec2 transformed = transformWithoutTranslation(transform, {deltaX, deltaY});
150     return transformWithoutTranslation(transform.inverse(), mCursorController.move(transformed));
151 }
152 
setPosition(float x,float y)153 void PointerController::setPosition(float x, float y) {
154     const ui::LogicalDisplayId displayId = mCursorController.getDisplayId();
155     vec2 transformed;
156     {
157         std::scoped_lock lock(getLock());
158         const auto& transform = getTransformForDisplayLocked(displayId);
159         transformed = transform.transform(x, y);
160     }
161     mCursorController.setPosition(transformed);
162 }
163 
getPosition() const164 vec2 PointerController::getPosition() const {
165     const ui::LogicalDisplayId displayId = mCursorController.getDisplayId();
166     const auto p = mCursorController.getPosition();
167     {
168         std::scoped_lock lock(getLock());
169         return getTransformForDisplayLocked(displayId).inverse().transform(p.x, p.y);
170     }
171 }
172 
getDisplayId() const173 ui::LogicalDisplayId PointerController::getDisplayId() const {
174     return mCursorController.getDisplayId();
175 }
176 
fade(Transition transition)177 void PointerController::fade(Transition transition) {
178     std::scoped_lock lock(getLock());
179     mCursorController.fade(transition);
180 }
181 
unfade(Transition transition)182 void PointerController::unfade(Transition transition) {
183     std::scoped_lock lock(getLock());
184     mCursorController.unfade(transition);
185 }
186 
setPresentation(Presentation presentation)187 void PointerController::setPresentation(Presentation presentation) {
188     std::scoped_lock lock(getLock());
189 
190     if (mLocked.presentation == presentation) {
191         return;
192     }
193 
194     mLocked.presentation = presentation;
195 
196     // The presentation mode is only set once when the PointerController is constructed,
197     // before the display viewport is provided.
198     mCursorController.setStylusHoverMode(presentation == Presentation::STYLUS_HOVER);
199 }
200 
setSpots(const PointerCoords * spotCoords,const uint32_t * spotIdToIndex,BitSet32 spotIdBits,ui::LogicalDisplayId displayId)201 void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
202                                  BitSet32 spotIdBits, ui::LogicalDisplayId displayId) {
203     std::scoped_lock lock(getLock());
204     std::array<PointerCoords, MAX_POINTERS> outSpotCoords{};
205     const ui::Transform& transform = getTransformForDisplayLocked(displayId);
206 
207     for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
208         const uint32_t index = spotIdToIndex[idBits.clearFirstMarkedBit()];
209 
210         const vec2 xy = transform.transform(spotCoords[index].getXYValue());
211         outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
212         outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
213 
214         float pressure = spotCoords[index].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
215         outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
216     }
217 
218     auto it = mLocked.spotControllers.find(displayId);
219     if (it == mLocked.spotControllers.end()) {
220         mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
221     }
222     bool skipScreenshot = mLocked.displaysToSkipScreenshot.find(displayId) !=
223             mLocked.displaysToSkipScreenshot.end();
224     mLocked.spotControllers.at(displayId).setSpots(outSpotCoords.data(), spotIdToIndex, spotIdBits,
225                                                    skipScreenshot);
226 }
227 
clearSpots()228 void PointerController::clearSpots() {
229     std::scoped_lock lock(getLock());
230     clearSpotsLocked();
231 }
232 
clearSpotsLocked()233 void PointerController::clearSpotsLocked() {
234     for (auto& [displayId, spotController] : mLocked.spotControllers) {
235         spotController.clearSpots();
236     }
237 }
238 
setInactivityTimeout(InactivityTimeout inactivityTimeout)239 void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
240     mContext.setInactivityTimeout(inactivityTimeout);
241 }
242 
reloadPointerResources()243 void PointerController::reloadPointerResources() {
244     std::scoped_lock lock(getLock());
245 
246     for (auto& [displayId, spotController] : mLocked.spotControllers) {
247         spotController.reloadSpotResources();
248     }
249 
250     if (mCursorController.resourcesLoaded()) {
251         bool getAdditionalMouseResources = false;
252         if (mLocked.presentation == PointerController::Presentation::POINTER ||
253             mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
254             getAdditionalMouseResources = true;
255         }
256         mCursorController.reloadPointerResources(getAdditionalMouseResources);
257     }
258 }
259 
setDisplayViewport(const DisplayViewport & viewport)260 void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
261     { // acquire lock
262         std::scoped_lock lock(getLock());
263 
264         bool getAdditionalMouseResources = false;
265         if (mLocked.presentation == PointerController::Presentation::POINTER ||
266             mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
267             getAdditionalMouseResources = true;
268         }
269         mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
270         if (viewport.displayId != mLocked.pointerDisplayId) {
271             mLocked.pointerDisplayId = viewport.displayId;
272         }
273     } // release lock
274 }
275 
updatePointerIcon(PointerIconStyle iconId)276 void PointerController::updatePointerIcon(PointerIconStyle iconId) {
277     std::scoped_lock lock(getLock());
278     mCursorController.updatePointerIcon(iconId);
279 }
280 
setCustomPointerIcon(const SpriteIcon & icon)281 void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
282     std::scoped_lock lock(getLock());
283     mCursorController.setCustomPointerIcon(icon);
284 }
285 
setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId)286 void PointerController::setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) {
287     std::scoped_lock lock(getLock());
288     mLocked.displaysToSkipScreenshot.insert(displayId);
289     mCursorController.setSkipScreenshot(true);
290 }
291 
clearSkipScreenshotFlags()292 void PointerController::clearSkipScreenshotFlags() {
293     std::scoped_lock lock(getLock());
294     mLocked.displaysToSkipScreenshot.clear();
295     mCursorController.setSkipScreenshot(false);
296 }
297 
getDisplayTransform() const298 ui::Transform PointerController::getDisplayTransform() const {
299     std::scoped_lock lock(getLock());
300     return getTransformForDisplayLocked(mLocked.pointerDisplayId);
301 }
302 
doInactivityTimeout()303 void PointerController::doInactivityTimeout() {
304     fade(Transition::GRADUAL);
305 }
306 
onDisplayViewportsUpdated(const std::vector<DisplayViewport> & viewports)307 void PointerController::onDisplayViewportsUpdated(const std::vector<DisplayViewport>& viewports) {
308     std::unordered_set<ui::LogicalDisplayId> displayIdSet;
309     for (const DisplayViewport& viewport : viewports) {
310         displayIdSet.insert(viewport.displayId);
311     }
312 
313     std::scoped_lock lock(getLock());
314     for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) {
315         ui::LogicalDisplayId displayId = it->first;
316         if (!displayIdSet.count(displayId)) {
317             /*
318              * Ensures that an in-progress animation won't dereference
319              * a null pointer to TouchSpotController.
320              */
321             mContext.removeAnimationCallback(displayId);
322             it = mLocked.spotControllers.erase(it);
323         } else {
324             ++it;
325         }
326     }
327 }
328 
onDisplayInfosChangedLocked(const std::vector<gui::DisplayInfo> & displayInfo)329 void PointerController::onDisplayInfosChangedLocked(
330         const std::vector<gui::DisplayInfo>& displayInfo) {
331     mLocked.mDisplayInfos = displayInfo;
332 }
333 
getTransformForDisplayLocked(ui::LogicalDisplayId displayId) const334 const ui::Transform& PointerController::getTransformForDisplayLocked(
335         ui::LogicalDisplayId displayId) const {
336     const auto& di = mLocked.mDisplayInfos;
337     auto it = std::find_if(di.begin(), di.end(), [displayId](const gui::DisplayInfo& info) {
338         return info.displayId == displayId;
339     });
340     return it != di.end() ? it->transform : kIdentityTransform;
341 }
342 
dump()343 std::string PointerController::dump() {
344     std::string dump = INDENT "PointerController:\n";
345     std::scoped_lock lock(getLock());
346     dump += StringPrintf(INDENT2 "Presentation: %s\n",
347                          ftl::enum_string(mLocked.presentation).c_str());
348     dump += StringPrintf(INDENT2 "Pointer Display ID: %s\n",
349                          mLocked.pointerDisplayId.toString().c_str());
350     dump += StringPrintf(INDENT2 "Viewports:\n");
351     for (const auto& info : mLocked.mDisplayInfos) {
352         info.dump(dump, INDENT3);
353     }
354     dump += INDENT2 "Spot Controllers:\n";
355     for (const auto& [_, spotController] : mLocked.spotControllers) {
356         spotController.dump(dump, INDENT3);
357     }
358     dump += INDENT2 "Cursor Controller:\n";
359     dump += addLinePrefix(mCursorController.dump(), INDENT3);
360     return dump;
361 }
362 
363 // --- MousePointerController ---
364 
MousePointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,SpriteController & spriteController)365 MousePointerController::MousePointerController(const sp<PointerControllerPolicyInterface>& policy,
366                                                const sp<Looper>& looper,
367                                                SpriteController& spriteController)
368       : PointerController(policy, looper, spriteController) {
369     PointerController::setPresentation(Presentation::POINTER);
370 }
371 
~MousePointerController()372 MousePointerController::~MousePointerController() {
373     MousePointerController::fade(Transition::IMMEDIATE);
374 }
375 
376 // --- TouchPointerController ---
377 
TouchPointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,SpriteController & spriteController)378 TouchPointerController::TouchPointerController(const sp<PointerControllerPolicyInterface>& policy,
379                                                const sp<Looper>& looper,
380                                                SpriteController& spriteController)
381       : PointerController(policy, looper, spriteController) {
382     PointerController::setPresentation(Presentation::SPOT);
383 }
384 
~TouchPointerController()385 TouchPointerController::~TouchPointerController() {
386     TouchPointerController::clearSpots();
387 }
388 
389 // --- StylusPointerController ---
390 
StylusPointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,SpriteController & spriteController)391 StylusPointerController::StylusPointerController(const sp<PointerControllerPolicyInterface>& policy,
392                                                  const sp<Looper>& looper,
393                                                  SpriteController& spriteController)
394       : PointerController(policy, looper, spriteController) {
395     PointerController::setPresentation(Presentation::STYLUS_HOVER);
396 }
397 
~StylusPointerController()398 StylusPointerController::~StylusPointerController() {
399     StylusPointerController::fade(Transition::IMMEDIATE);
400 }
401 
402 } // namespace android
403