blob: 3b494e9129dbaef9e48cd9908cd475691f6db09c [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
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"
Jeff Brownb4ff35d2011-01-02 16:37:43 -080018//#define LOG_NDEBUG 0
19
20// Log debug messages about pointer updates
21#define DEBUG_POINTER_UPDATES 0
22
23#include "PointerController.h"
24
Mark Salyzyn52eb4e02016-09-28 16:15:30 -070025#include <log/log.h>
Jeff Brownb4ff35d2011-01-02 16:37:43 -080026
Jeff Brownb4ff35d2011-01-02 16:37:43 -080027namespace android {
28
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070029// --- WeakLooperCallback ---
30
31class WeakLooperCallback: public LooperCallback {
32protected:
33 virtual ~WeakLooperCallback() { }
34
35public:
Chih-Hung Hsieh0c29f392018-12-20 13:51:01 -080036 explicit WeakLooperCallback(const wp<LooperCallback>& callback) :
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070037 mCallback(callback) {
38 }
39
40 virtual int handleEvent(int fd, int events, void* data) {
41 sp<LooperCallback> callback = mCallback.promote();
42 if (callback != NULL) {
43 return callback->handleEvent(fd, events, data);
44 }
45 return 0; // the client is gone, remove the callback
46 }
47
48private:
49 wp<LooperCallback> mCallback;
50};
51
Jeff Brownb4ff35d2011-01-02 16:37:43 -080052// --- PointerController ---
53
Jeff Brown05dc66a2011-03-02 14:41:58 -080054// Time to wait before starting the fade when the pointer is inactive.
Jeff Brown2352b972011-04-12 22:39:53 -070055static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
56static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
57
Jeff Brown2352b972011-04-12 22:39:53 -070058// Time to spend fading out the spot completely.
59static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
Jeff Brown05dc66a2011-03-02 14:41:58 -080060
61// Time to spend fading out the pointer completely.
Jeff Brown2352b972011-04-12 22:39:53 -070062static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
Jeff Brown05dc66a2011-03-02 14:41:58 -080063
Jun Mukaic0c0ac32015-10-27 10:09:21 -070064// The number of events to be read at once for DisplayEventReceiver.
65static const int EVENT_BUFFER_SIZE = 100;
Jeff Brown05dc66a2011-03-02 14:41:58 -080066
Jeff Brown2352b972011-04-12 22:39:53 -070067// --- PointerController ---
68
69PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
70 const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
71 mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
Jeff Brown5541de92011-04-11 11:54:25 -070072 mHandler = new WeakMessageHandler(this);
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070073 mCallback = new WeakLooperCallback(this);
Jeff Brown5541de92011-04-11 11:54:25 -070074
Jun Mukaic0c0ac32015-10-27 10:09:21 -070075 if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
76 mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070077 Looper::EVENT_INPUT, mCallback, nullptr);
Jun Mukaic0c0ac32015-10-27 10:09:21 -070078 } else {
79 ALOGE("Failed to initialize DisplayEventReceiver.");
80 }
81
Jeff Brownb4ff35d2011-01-02 16:37:43 -080082 AutoMutex _l(mLock);
83
Jeff Brown2352b972011-04-12 22:39:53 -070084 mLocked.animationPending = false;
85
Jeff Brown2352b972011-04-12 22:39:53 -070086 mLocked.presentation = PRESENTATION_POINTER;
87 mLocked.presentationChanged = false;
88
89 mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
90
Jeff Brown538881e2011-05-25 18:23:38 -070091 mLocked.pointerFadeDirection = 0;
Jeff Brownb4ff35d2011-01-02 16:37:43 -080092 mLocked.pointerX = 0;
93 mLocked.pointerY = 0;
Jeff Brown538881e2011-05-25 18:23:38 -070094 mLocked.pointerAlpha = 0.0f; // pointer is initially faded
Jeff Brown2352b972011-04-12 22:39:53 -070095 mLocked.pointerSprite = mSpriteController->createSprite();
96 mLocked.pointerIconChanged = false;
Michael Wrighte051f6f2016-05-13 17:44:16 +010097 mLocked.requestedPointerType = mPolicy->getDefaultPointerIconId();
Jeff Brown2352b972011-04-12 22:39:53 -070098
Jun Mukai808196f2015-10-28 16:46:44 -070099 mLocked.animationFrameIndex = 0;
100 mLocked.lastFrameUpdatedTime = 0;
101
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800102 mLocked.buttonState = 0;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800103}
104
105PointerController::~PointerController() {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800106 mLooper->removeMessages(mHandler);
107
Jeff Brown5541de92011-04-11 11:54:25 -0700108 AutoMutex _l(mLock);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800109
Jeff Brown2352b972011-04-12 22:39:53 -0700110 mLocked.pointerSprite.clear();
111
Arthur Hungd25699a2019-01-25 17:53:22 +0800112 for (auto& it : mLocked.spotsByDisplay) {
113 const std::vector<Spot*>& spots = it.second;
114 size_t numSpots = spots.size();
115 for (size_t i = 0; i < numSpots; i++) {
116 delete spots[i];
117 }
Jeff Brown2352b972011-04-12 22:39:53 -0700118 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800119 mLocked.spotsByDisplay.clear();
Jeff Brown2352b972011-04-12 22:39:53 -0700120 mLocked.recycledSprites.clear();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800121}
122
123bool PointerController::getBounds(float* outMinX, float* outMinY,
124 float* outMaxX, float* outMaxY) const {
125 AutoMutex _l(mLock);
126
127 return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
128}
129
130bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
131 float* outMaxX, float* outMaxY) const {
Arthur Hungb9b32002018-12-18 17:39:43 +0800132
133 if (!mLocked.viewport.isValid()) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800134 return false;
135 }
136
Arthur Hungb9b32002018-12-18 17:39:43 +0800137 *outMinX = mLocked.viewport.logicalLeft;
138 *outMinY = mLocked.viewport.logicalTop;
139 *outMaxX = mLocked.viewport.logicalRight - 1;
140 *outMaxY = mLocked.viewport.logicalBottom - 1;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800141 return true;
142}
143
144void PointerController::move(float deltaX, float deltaY) {
145#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000146 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800147#endif
148 if (deltaX == 0.0f && deltaY == 0.0f) {
149 return;
150 }
151
152 AutoMutex _l(mLock);
153
154 setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
155}
156
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700157void PointerController::setButtonState(int32_t buttonState) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800158#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000159 ALOGD("Set button state 0x%08x", buttonState);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800160#endif
161 AutoMutex _l(mLock);
162
163 if (mLocked.buttonState != buttonState) {
164 mLocked.buttonState = buttonState;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800165 }
166}
167
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700168int32_t PointerController::getButtonState() const {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800169 AutoMutex _l(mLock);
170
171 return mLocked.buttonState;
172}
173
174void PointerController::setPosition(float x, float y) {
175#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000176 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800177#endif
178 AutoMutex _l(mLock);
179
180 setPositionLocked(x, y);
181}
182
183void PointerController::setPositionLocked(float x, float y) {
184 float minX, minY, maxX, maxY;
185 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
186 if (x <= minX) {
187 mLocked.pointerX = minX;
188 } else if (x >= maxX) {
189 mLocked.pointerX = maxX;
190 } else {
191 mLocked.pointerX = x;
192 }
193 if (y <= minY) {
194 mLocked.pointerY = minY;
195 } else if (y >= maxY) {
196 mLocked.pointerY = maxY;
197 } else {
198 mLocked.pointerY = y;
199 }
Jeff Brown2352b972011-04-12 22:39:53 -0700200 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800201 }
202}
203
204void PointerController::getPosition(float* outX, float* outY) const {
205 AutoMutex _l(mLock);
206
207 *outX = mLocked.pointerX;
208 *outY = mLocked.pointerY;
209}
210
Arthur Hungb9b32002018-12-18 17:39:43 +0800211int32_t PointerController::getDisplayId() const {
212 AutoMutex _l(mLock);
213
214 return mLocked.viewport.displayId;
215}
216
Jeff Brown538881e2011-05-25 18:23:38 -0700217void PointerController::fade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800218 AutoMutex _l(mLock);
219
Jeff Brown538881e2011-05-25 18:23:38 -0700220 // Remove the inactivity timeout, since we are fading now.
221 removeInactivityTimeoutLocked();
222
223 // Start fading.
224 if (transition == TRANSITION_IMMEDIATE) {
225 mLocked.pointerFadeDirection = 0;
226 mLocked.pointerAlpha = 0.0f;
227 updatePointerLocked();
228 } else {
229 mLocked.pointerFadeDirection = -1;
230 startAnimationLocked();
231 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800232}
233
Jeff Brown538881e2011-05-25 18:23:38 -0700234void PointerController::unfade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800235 AutoMutex _l(mLock);
236
Jeff Brown2352b972011-04-12 22:39:53 -0700237 // Always reset the inactivity timer.
238 resetInactivityTimeoutLocked();
239
Jeff Brown538881e2011-05-25 18:23:38 -0700240 // Start unfading.
241 if (transition == TRANSITION_IMMEDIATE) {
242 mLocked.pointerFadeDirection = 0;
Jeff Brown2352b972011-04-12 22:39:53 -0700243 mLocked.pointerAlpha = 1.0f;
244 updatePointerLocked();
Jeff Brown538881e2011-05-25 18:23:38 -0700245 } else {
246 mLocked.pointerFadeDirection = 1;
247 startAnimationLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800248 }
249}
250
Jeff Brown2352b972011-04-12 22:39:53 -0700251void PointerController::setPresentation(Presentation presentation) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800252 AutoMutex _l(mLock);
253
Prabir Pradhanbe845952020-01-31 17:42:34 -0800254 if (mLocked.presentation == presentation) {
255 return;
Jun Mukai1db53972015-09-11 18:08:31 -0700256 }
257
Prabir Pradhanbe845952020-01-31 17:42:34 -0800258 mLocked.presentation = presentation;
259 mLocked.presentationChanged = true;
Jeff Brown2352b972011-04-12 22:39:53 -0700260
Prabir Pradhanbe845952020-01-31 17:42:34 -0800261 if (!mLocked.viewport.isValid()) {
262 return;
263 }
264
265 if (presentation == PRESENTATION_POINTER) {
266 if (mLocked.additionalMouseResources.empty()) {
267 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
268 &mLocked.animationResources,
269 mLocked.viewport.displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700270 }
Prabir Pradhanbe845952020-01-31 17:42:34 -0800271 fadeOutAndReleaseAllSpotsLocked();
Jeff Brown2352b972011-04-12 22:39:53 -0700272 updatePointerLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800273 }
274}
275
Jeff Browncb5ffcf2011-06-06 20:03:18 -0700276void PointerController::setSpots(const PointerCoords* spotCoords,
Arthur Hungd25699a2019-01-25 17:53:22 +0800277 const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId) {
Jeff Brown2352b972011-04-12 22:39:53 -0700278#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000279 ALOGD("setSpots: idBits=%08x", spotIdBits.value);
Jeff Brown2352b972011-04-12 22:39:53 -0700280 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
281 uint32_t id = idBits.firstMarkedBit();
282 idBits.clearBit(id);
283 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
Arthur Hungd25699a2019-01-25 17:53:22 +0800284 ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id,
Jeff Brown2352b972011-04-12 22:39:53 -0700285 c.getAxisValue(AMOTION_EVENT_AXIS_X),
286 c.getAxisValue(AMOTION_EVENT_AXIS_Y),
Arthur Hungd25699a2019-01-25 17:53:22 +0800287 c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
288 displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700289 }
290#endif
291
292 AutoMutex _l(mLock);
Prabir Pradhanbe845952020-01-31 17:42:34 -0800293 if (!mLocked.viewport.isValid()) {
294 return;
295 }
Jeff Brown2352b972011-04-12 22:39:53 -0700296
Arthur Hungd25699a2019-01-25 17:53:22 +0800297 std::vector<Spot*> newSpots;
298 std::map<int32_t, std::vector<Spot*>>::const_iterator iter =
299 mLocked.spotsByDisplay.find(displayId);
300 if (iter != mLocked.spotsByDisplay.end()) {
301 newSpots = iter->second;
302 }
303
Jeff Brown2352b972011-04-12 22:39:53 -0700304 mSpriteController->openTransaction();
305
306 // Add or move spots for fingers that are down.
307 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700308 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown2352b972011-04-12 22:39:53 -0700309 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
310 const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
311 ? mResources.spotTouch : mResources.spotHover;
312 float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
313 float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
314
Arthur Hungd25699a2019-01-25 17:53:22 +0800315 Spot* spot = getSpot(id, newSpots);
Jeff Brown2352b972011-04-12 22:39:53 -0700316 if (!spot) {
Arthur Hungd25699a2019-01-25 17:53:22 +0800317 spot = createAndAddSpotLocked(id, newSpots);
Jeff Brown2352b972011-04-12 22:39:53 -0700318 }
319
Arthur Hungd25699a2019-01-25 17:53:22 +0800320 spot->updateSprite(&icon, x, y, displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700321 }
322
323 // Remove spots for fingers that went up.
Arthur Hungd25699a2019-01-25 17:53:22 +0800324 for (size_t i = 0; i < newSpots.size(); i++) {
325 Spot* spot = newSpots[i];
Jeff Brown2352b972011-04-12 22:39:53 -0700326 if (spot->id != Spot::INVALID_ID
327 && !spotIdBits.hasBit(spot->id)) {
328 fadeOutAndReleaseSpotLocked(spot);
329 }
330 }
331
332 mSpriteController->closeTransaction();
Arthur Hungd25699a2019-01-25 17:53:22 +0800333 mLocked.spotsByDisplay[displayId] = newSpots;
Jeff Brown2352b972011-04-12 22:39:53 -0700334}
335
336void PointerController::clearSpots() {
337#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000338 ALOGD("clearSpots");
Jeff Brown2352b972011-04-12 22:39:53 -0700339#endif
340
341 AutoMutex _l(mLock);
Prabir Pradhanbe845952020-01-31 17:42:34 -0800342 if (!mLocked.viewport.isValid()) {
343 return;
344 }
Jeff Brown2352b972011-04-12 22:39:53 -0700345
346 fadeOutAndReleaseAllSpotsLocked();
347}
348
349void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
350 AutoMutex _l(mLock);
351
352 if (mLocked.inactivityTimeout != inactivityTimeout) {
353 mLocked.inactivityTimeout = inactivityTimeout;
354 resetInactivityTimeoutLocked();
355 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800356}
357
Jun Mukai19a56012015-11-24 11:25:52 -0800358void PointerController::reloadPointerResources() {
359 AutoMutex _l(mLock);
360
Arthur Hungb9b32002018-12-18 17:39:43 +0800361 loadResourcesLocked();
Jun Mukai19a56012015-11-24 11:25:52 -0800362 updatePointerLocked();
363}
364
Arthur Hungb9b32002018-12-18 17:39:43 +0800365/**
366 * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
367 * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
368 */
369static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
370 width = viewport.deviceWidth;
371 height = viewport.deviceHeight;
Andrii Kuliand44026f2018-12-17 18:59:36 +0000372
Arthur Hungb9b32002018-12-18 17:39:43 +0800373 if (viewport.orientation == DISPLAY_ORIENTATION_90
374 || viewport.orientation == DISPLAY_ORIENTATION_270) {
375 std::swap(width, height);
376 }
377}
378
379void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
380 AutoMutex _l(mLock);
381 if (viewport == mLocked.viewport) {
382 return;
Jeff Brownd728bf52012-09-08 18:05:28 -0700383 }
384
Arthur Hungb9b32002018-12-18 17:39:43 +0800385 const DisplayViewport oldViewport = mLocked.viewport;
386 mLocked.viewport = viewport;
387
388 int32_t oldDisplayWidth, oldDisplayHeight;
389 getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
390 int32_t newDisplayWidth, newDisplayHeight;
391 getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
392
393 // Reset cursor position to center if size or display changed.
394 if (oldViewport.displayId != viewport.displayId
395 || oldDisplayWidth != newDisplayWidth
396 || oldDisplayHeight != newDisplayHeight) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800397
398 float minX, minY, maxX, maxY;
399 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
400 mLocked.pointerX = (minX + maxX) * 0.5f;
401 mLocked.pointerY = (minY + maxY) * 0.5f;
Arthur Hungb9b32002018-12-18 17:39:43 +0800402 // Reload icon resources for density may be changed.
403 loadResourcesLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800404 } else {
405 mLocked.pointerX = 0;
406 mLocked.pointerY = 0;
407 }
408
Jeff Brown2352b972011-04-12 22:39:53 -0700409 fadeOutAndReleaseAllSpotsLocked();
Arthur Hungb9b32002018-12-18 17:39:43 +0800410 } else if (oldViewport.orientation != viewport.orientation) {
Jeff Brownd41cff22011-03-03 02:09:54 -0800411 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
412 // This creates an invariant frame of reference that we can easily rotate when
413 // taking into account that the pointer may be located at fractional pixel offsets.
414 float x = mLocked.pointerX + 0.5f;
415 float y = mLocked.pointerY + 0.5f;
416 float temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800417
Jeff Brownd41cff22011-03-03 02:09:54 -0800418 // Undo the previous rotation.
Arthur Hungb9b32002018-12-18 17:39:43 +0800419 switch (oldViewport.orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800420 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800421 temp = x;
Arthur Hungb9b32002018-12-18 17:39:43 +0800422 x = oldViewport.deviceHeight - y;
Jeff Brownd41cff22011-03-03 02:09:54 -0800423 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800424 break;
425 case DISPLAY_ORIENTATION_180:
Arthur Hungb9b32002018-12-18 17:39:43 +0800426 x = oldViewport.deviceWidth - x;
427 y = oldViewport.deviceHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800428 break;
429 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800430 temp = x;
431 x = y;
Arthur Hungb9b32002018-12-18 17:39:43 +0800432 y = oldViewport.deviceWidth - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800433 break;
434 }
435
Jeff Brownd41cff22011-03-03 02:09:54 -0800436 // Perform the new rotation.
Arthur Hungb9b32002018-12-18 17:39:43 +0800437 switch (viewport.orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800438 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800439 temp = x;
440 x = y;
Arthur Hungb9b32002018-12-18 17:39:43 +0800441 y = viewport.deviceHeight - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800442 break;
443 case DISPLAY_ORIENTATION_180:
Arthur Hungb9b32002018-12-18 17:39:43 +0800444 x = viewport.deviceWidth - x;
445 y = viewport.deviceHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800446 break;
447 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800448 temp = x;
Arthur Hungb9b32002018-12-18 17:39:43 +0800449 x = viewport.deviceWidth - y;
Jeff Brownd41cff22011-03-03 02:09:54 -0800450 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800451 break;
452 }
453
Jeff Brownd41cff22011-03-03 02:09:54 -0800454 // Apply offsets to convert from the pixel center to the pixel top-left corner position
455 // and save the results.
456 mLocked.pointerX = x - 0.5f;
457 mLocked.pointerY = y - 0.5f;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800458 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700459
460 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800461}
462
Michael Wrighte051f6f2016-05-13 17:44:16 +0100463void PointerController::updatePointerIcon(int32_t iconId) {
Jun Mukai1db53972015-09-11 18:08:31 -0700464 AutoMutex _l(mLock);
Michael Wrighte051f6f2016-05-13 17:44:16 +0100465 if (mLocked.requestedPointerType != iconId) {
466 mLocked.requestedPointerType = iconId;
Jun Mukai1db53972015-09-11 18:08:31 -0700467 mLocked.presentationChanged = true;
468 updatePointerLocked();
469 }
470}
471
Jun Mukaid4eaef72015-10-30 15:54:33 -0700472void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
473 AutoMutex _l(mLock);
474
475 const int32_t iconId = mPolicy->getCustomPointerIconId();
476 mLocked.additionalMouseResources[iconId] = icon;
Michael Wrighte051f6f2016-05-13 17:44:16 +0100477 mLocked.requestedPointerType = iconId;
Jun Mukaid4eaef72015-10-30 15:54:33 -0700478 mLocked.presentationChanged = true;
479
480 updatePointerLocked();
481}
482
Jeff Brown05dc66a2011-03-02 14:41:58 -0800483void PointerController::handleMessage(const Message& message) {
484 switch (message.what) {
Jeff Brown2352b972011-04-12 22:39:53 -0700485 case MSG_INACTIVITY_TIMEOUT:
486 doInactivityTimeout();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800487 break;
488 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800489}
490
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700491int PointerController::handleEvent(int /* fd */, int events, void* /* data */) {
492 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
493 ALOGE("Display event receiver pipe was closed or an error occurred. "
494 "events=0x%x", events);
495 return 0; // remove the callback
496 }
497
498 if (!(events & Looper::EVENT_INPUT)) {
499 ALOGW("Received spurious callback for unhandled poll event. "
500 "events=0x%x", events);
501 return 1; // keep the callback
502 }
503
504 bool gotVsync = false;
505 ssize_t n;
506 nsecs_t timestamp;
507 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
508 while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
509 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
510 if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
511 timestamp = buf[i].header.timestamp;
512 gotVsync = true;
513 }
514 }
515 }
516 if (gotVsync) {
517 doAnimate(timestamp);
518 }
519 return 1; // keep the callback
520}
521
522void PointerController::doAnimate(nsecs_t timestamp) {
Jeff Brown2352b972011-04-12 22:39:53 -0700523 AutoMutex _l(mLock);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800524
Jeff Brown2352b972011-04-12 22:39:53 -0700525 mLocked.animationPending = false;
Jun Mukai808196f2015-10-28 16:46:44 -0700526
527 bool keepFading = doFadingAnimationLocked(timestamp);
528 bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
529 if (keepFading || keepBitmapFlipping) {
530 startAnimationLocked();
531 }
532}
533
534bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
535 bool keepAnimating = false;
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700536 nsecs_t frameDelay = timestamp - mLocked.animationTime;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800537
Jeff Brown2352b972011-04-12 22:39:53 -0700538 // Animate pointer fade.
Jeff Brown538881e2011-05-25 18:23:38 -0700539 if (mLocked.pointerFadeDirection < 0) {
Jeff Brown2352b972011-04-12 22:39:53 -0700540 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
Jeff Brown538881e2011-05-25 18:23:38 -0700541 if (mLocked.pointerAlpha <= 0.0f) {
542 mLocked.pointerAlpha = 0.0f;
543 mLocked.pointerFadeDirection = 0;
544 } else {
545 keepAnimating = true;
546 }
547 updatePointerLocked();
548 } else if (mLocked.pointerFadeDirection > 0) {
549 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
550 if (mLocked.pointerAlpha >= 1.0f) {
551 mLocked.pointerAlpha = 1.0f;
552 mLocked.pointerFadeDirection = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800553 } else {
Jeff Brown2352b972011-04-12 22:39:53 -0700554 keepAnimating = true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800555 }
Jeff Brown2352b972011-04-12 22:39:53 -0700556 updatePointerLocked();
557 }
558
559 // Animate spots that are fading out and being removed.
Arthur Hungd25699a2019-01-25 17:53:22 +0800560 for(auto it = mLocked.spotsByDisplay.begin(); it != mLocked.spotsByDisplay.end();) {
561 std::vector<Spot*>& spots = it->second;
562 size_t numSpots = spots.size();
563 for (size_t i = 0; i < numSpots;) {
564 Spot* spot = spots[i];
565 if (spot->id == Spot::INVALID_ID) {
566 spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
567 if (spot->alpha <= 0) {
568 spots.erase(spots.begin() + i);
569 releaseSpotLocked(spot);
570 numSpots--;
571 continue;
572 } else {
573 spot->sprite->setAlpha(spot->alpha);
574 keepAnimating = true;
575 }
Jeff Brown2352b972011-04-12 22:39:53 -0700576 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800577 ++i;
Jeff Brown2352b972011-04-12 22:39:53 -0700578 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800579
580 if (spots.size() == 0) {
581 it = mLocked.spotsByDisplay.erase(it);
582 } else {
583 ++it;
584 }
Jeff Brown2352b972011-04-12 22:39:53 -0700585 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800586
Jun Mukai808196f2015-10-28 16:46:44 -0700587 return keepAnimating;
588}
Jeff Brown2352b972011-04-12 22:39:53 -0700589
Jun Mukai808196f2015-10-28 16:46:44 -0700590bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
591 std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
Michael Wrighte051f6f2016-05-13 17:44:16 +0100592 mLocked.requestedPointerType);
Jun Mukai808196f2015-10-28 16:46:44 -0700593 if (iter == mLocked.animationResources.end()) {
594 return false;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800595 }
Jun Mukai808196f2015-10-28 16:46:44 -0700596
597 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
598 mSpriteController->openTransaction();
599
600 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
601 mLocked.animationFrameIndex += incr;
602 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
603 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
604 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
605 }
606 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
607
608 mSpriteController->closeTransaction();
609 }
610
611 // Keep animating.
612 return true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800613}
614
Jeff Brown2352b972011-04-12 22:39:53 -0700615void PointerController::doInactivityTimeout() {
Jeff Brown538881e2011-05-25 18:23:38 -0700616 fade(TRANSITION_GRADUAL);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800617}
618
Jeff Brown2352b972011-04-12 22:39:53 -0700619void PointerController::startAnimationLocked() {
620 if (!mLocked.animationPending) {
621 mLocked.animationPending = true;
622 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700623 mDisplayEventReceiver.requestNextVsync();
Jeff Brown2352b972011-04-12 22:39:53 -0700624 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800625}
626
Jeff Brown2352b972011-04-12 22:39:53 -0700627void PointerController::resetInactivityTimeoutLocked() {
628 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
629
630 nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
631 ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
632 mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
633}
634
Jeff Brown538881e2011-05-25 18:23:38 -0700635void PointerController::removeInactivityTimeoutLocked() {
Jeff Brown2352b972011-04-12 22:39:53 -0700636 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
Jeff Brown2352b972011-04-12 22:39:53 -0700637}
638
Arthur Hungb9b32002018-12-18 17:39:43 +0800639void PointerController::updatePointerLocked() REQUIRES(mLock) {
640 if (!mLocked.viewport.isValid()) {
641 return;
642 }
643
Jeff Brown2352b972011-04-12 22:39:53 -0700644 mSpriteController->openTransaction();
645
646 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
647 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
Arthur Hungb9b32002018-12-18 17:39:43 +0800648 mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700649
650 if (mLocked.pointerAlpha > 0) {
651 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
652 mLocked.pointerSprite->setVisible(true);
653 } else {
654 mLocked.pointerSprite->setVisible(false);
655 }
656
657 if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
Jun Mukai1db53972015-09-11 18:08:31 -0700658 if (mLocked.presentation == PRESENTATION_POINTER) {
Michael Wrighte051f6f2016-05-13 17:44:16 +0100659 if (mLocked.requestedPointerType == mPolicy->getDefaultPointerIconId()) {
Jun Mukai1db53972015-09-11 18:08:31 -0700660 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
661 } else {
Jun Mukai808196f2015-10-28 16:46:44 -0700662 std::map<int32_t, SpriteIcon>::const_iterator iter =
Michael Wrighte051f6f2016-05-13 17:44:16 +0100663 mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
Jun Mukai1db53972015-09-11 18:08:31 -0700664 if (iter != mLocked.additionalMouseResources.end()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700665 std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
Michael Wrighte051f6f2016-05-13 17:44:16 +0100666 mLocked.animationResources.find(mLocked.requestedPointerType);
Jun Mukai808196f2015-10-28 16:46:44 -0700667 if (anim_iter != mLocked.animationResources.end()) {
668 mLocked.animationFrameIndex = 0;
669 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
670 startAnimationLocked();
671 }
Jun Mukai1db53972015-09-11 18:08:31 -0700672 mLocked.pointerSprite->setIcon(iter->second);
673 } else {
Michael Wrighte051f6f2016-05-13 17:44:16 +0100674 ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
Jun Mukai1db53972015-09-11 18:08:31 -0700675 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
676 }
677 }
678 } else {
679 mLocked.pointerSprite->setIcon(mResources.spotAnchor);
680 }
Jeff Brown2352b972011-04-12 22:39:53 -0700681 mLocked.pointerIconChanged = false;
682 mLocked.presentationChanged = false;
683 }
684
685 mSpriteController->closeTransaction();
686}
687
Arthur Hungd25699a2019-01-25 17:53:22 +0800688PointerController::Spot* PointerController::getSpot(uint32_t id, const std::vector<Spot*>& spots) {
689 for (size_t i = 0; i < spots.size(); i++) {
690 Spot* spot = spots[i];
Jeff Brown2352b972011-04-12 22:39:53 -0700691 if (spot->id == id) {
692 return spot;
693 }
694 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800695
696 return nullptr;
Jeff Brown2352b972011-04-12 22:39:53 -0700697}
698
Arthur Hungd25699a2019-01-25 17:53:22 +0800699PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id,
700 std::vector<Spot*>& spots) {
Jeff Brown2352b972011-04-12 22:39:53 -0700701 // Remove spots until we have fewer than MAX_SPOTS remaining.
Arthur Hungd25699a2019-01-25 17:53:22 +0800702 while (spots.size() >= MAX_SPOTS) {
703 Spot* spot = removeFirstFadingSpotLocked(spots);
Jeff Brown2352b972011-04-12 22:39:53 -0700704 if (!spot) {
Arthur Hungd25699a2019-01-25 17:53:22 +0800705 spot = spots[0];
706 spots.erase(spots.begin());
Jeff Brown2352b972011-04-12 22:39:53 -0700707 }
708 releaseSpotLocked(spot);
709 }
710
711 // Obtain a sprite from the recycled pool.
712 sp<Sprite> sprite;
Arthur Hungd25699a2019-01-25 17:53:22 +0800713 if (! mLocked.recycledSprites.empty()) {
714 sprite = mLocked.recycledSprites.back();
715 mLocked.recycledSprites.pop_back();
Jeff Brown2352b972011-04-12 22:39:53 -0700716 } else {
717 sprite = mSpriteController->createSprite();
718 }
719
720 // Return the new spot.
721 Spot* spot = new Spot(id, sprite);
Arthur Hungd25699a2019-01-25 17:53:22 +0800722 spots.push_back(spot);
Jeff Brown2352b972011-04-12 22:39:53 -0700723 return spot;
724}
725
Arthur Hungd25699a2019-01-25 17:53:22 +0800726PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) {
727 for (size_t i = 0; i < spots.size(); i++) {
728 Spot* spot = spots[i];
Jeff Brown2352b972011-04-12 22:39:53 -0700729 if (spot->id == Spot::INVALID_ID) {
Arthur Hungd25699a2019-01-25 17:53:22 +0800730 spots.erase(spots.begin() + i);
Jeff Brown2352b972011-04-12 22:39:53 -0700731 return spot;
732 }
733 }
734 return NULL;
735}
736
737void PointerController::releaseSpotLocked(Spot* spot) {
738 spot->sprite->clearIcon();
739
740 if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
Arthur Hungd25699a2019-01-25 17:53:22 +0800741 mLocked.recycledSprites.push_back(spot->sprite);
Jeff Brown2352b972011-04-12 22:39:53 -0700742 }
743
744 delete spot;
745}
746
747void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
748 if (spot->id != Spot::INVALID_ID) {
749 spot->id = Spot::INVALID_ID;
750 startAnimationLocked();
751 }
752}
753
754void PointerController::fadeOutAndReleaseAllSpotsLocked() {
Arthur Hungd25699a2019-01-25 17:53:22 +0800755 for (auto& it : mLocked.spotsByDisplay) {
756 const std::vector<Spot*>& spots = it.second;
757 size_t numSpots = spots.size();
758 for (size_t i = 0; i < numSpots; i++) {
759 Spot* spot = spots[i];
760 fadeOutAndReleaseSpotLocked(spot);
761 }
Jeff Brown2352b972011-04-12 22:39:53 -0700762 }
763}
764
Arthur Hungb9b32002018-12-18 17:39:43 +0800765void PointerController::loadResourcesLocked() REQUIRES(mLock) {
Prabir Pradhanbe845952020-01-31 17:42:34 -0800766 if (!mLocked.viewport.isValid()) {
767 return;
768 }
769
Andrii Kulianfd8666d2018-10-05 16:58:39 -0700770 mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
Arthur Hung350896b2019-02-26 16:35:01 +0800771 mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
Arthur Hungb9b32002018-12-18 17:39:43 +0800772
Arthur Hung350896b2019-02-26 16:35:01 +0800773 mLocked.additionalMouseResources.clear();
774 mLocked.animationResources.clear();
Arthur Hungb9b32002018-12-18 17:39:43 +0800775 if (mLocked.presentation == PRESENTATION_POINTER) {
Arthur Hungb9b32002018-12-18 17:39:43 +0800776 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
Andrii Kulianfd8666d2018-10-05 16:58:39 -0700777 &mLocked.animationResources, mLocked.viewport.displayId);
Arthur Hungb9b32002018-12-18 17:39:43 +0800778 }
779
780 mLocked.pointerIconChanged = true;
Jeff Brown2352b972011-04-12 22:39:53 -0700781}
782
783
784// --- PointerController::Spot ---
785
Arthur Hungd25699a2019-01-25 17:53:22 +0800786void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y,
787 int32_t displayId) {
Jeff Brown2352b972011-04-12 22:39:53 -0700788 sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
789 sprite->setAlpha(alpha);
790 sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
791 sprite->setPosition(x, y);
Arthur Hungd25699a2019-01-25 17:53:22 +0800792 sprite->setDisplayId(displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700793 this->x = x;
794 this->y = y;
795
796 if (icon != lastIcon) {
797 lastIcon = icon;
798 if (icon) {
799 sprite->setIcon(*icon);
800 sprite->setVisible(true);
801 } else {
802 sprite->setVisible(false);
803 }
804 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800805}
806
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800807} // namespace android