• 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/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