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