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