blob: abef66f9ecd9f13f13baa00e196b9ac114b13fbb [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"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages about pointer updates
22#define DEBUG_POINTER_UPDATES 0
23
24#include "PointerController.h"
25
26#include <cutils/log.h>
27
Andreas Gampe6b83b762014-11-10 15:55:11 -080028#pragma GCC diagnostic push
29#pragma GCC diagnostic ignored "-Wunused-parameter"
Jeff Brownb4ff35d2011-01-02 16:37:43 -080030#include <SkBitmap.h>
31#include <SkCanvas.h>
32#include <SkColor.h>
33#include <SkPaint.h>
34#include <SkXfermode.h>
Andreas Gampe6b83b762014-11-10 15:55:11 -080035#pragma GCC diagnostic pop
Jeff Brownb4ff35d2011-01-02 16:37:43 -080036
37namespace android {
38
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070039// --- WeakLooperCallback ---
40
41class WeakLooperCallback: public LooperCallback {
42protected:
43 virtual ~WeakLooperCallback() { }
44
45public:
46 WeakLooperCallback(const wp<LooperCallback>& callback) :
47 mCallback(callback) {
48 }
49
50 virtual int handleEvent(int fd, int events, void* data) {
51 sp<LooperCallback> callback = mCallback.promote();
52 if (callback != NULL) {
53 return callback->handleEvent(fd, events, data);
54 }
55 return 0; // the client is gone, remove the callback
56 }
57
58private:
59 wp<LooperCallback> mCallback;
60};
61
Jeff Brownb4ff35d2011-01-02 16:37:43 -080062// --- PointerController ---
63
Jeff Brown05dc66a2011-03-02 14:41:58 -080064// Time to wait before starting the fade when the pointer is inactive.
Jeff Brown2352b972011-04-12 22:39:53 -070065static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
66static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
67
Jeff Brown2352b972011-04-12 22:39:53 -070068// Time to spend fading out the spot completely.
69static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
Jeff Brown05dc66a2011-03-02 14:41:58 -080070
71// Time to spend fading out the pointer completely.
Jeff Brown2352b972011-04-12 22:39:53 -070072static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
Jeff Brown05dc66a2011-03-02 14:41:58 -080073
Jun Mukaic0c0ac32015-10-27 10:09:21 -070074// The number of events to be read at once for DisplayEventReceiver.
75static const int EVENT_BUFFER_SIZE = 100;
Jeff Brown05dc66a2011-03-02 14:41:58 -080076
Jeff Brown2352b972011-04-12 22:39:53 -070077// --- PointerController ---
78
79PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
80 const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
81 mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
Jeff Brown5541de92011-04-11 11:54:25 -070082 mHandler = new WeakMessageHandler(this);
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070083 mCallback = new WeakLooperCallback(this);
Jeff Brown5541de92011-04-11 11:54:25 -070084
Jun Mukaic0c0ac32015-10-27 10:09:21 -070085 if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
86 mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070087 Looper::EVENT_INPUT, mCallback, nullptr);
Jun Mukaic0c0ac32015-10-27 10:09:21 -070088 } else {
89 ALOGE("Failed to initialize DisplayEventReceiver.");
90 }
91
Jeff Brownb4ff35d2011-01-02 16:37:43 -080092 AutoMutex _l(mLock);
93
Jeff Brown2352b972011-04-12 22:39:53 -070094 mLocked.animationPending = false;
95
Jeff Brownb4ff35d2011-01-02 16:37:43 -080096 mLocked.displayWidth = -1;
97 mLocked.displayHeight = -1;
98 mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
99
Jeff Brown2352b972011-04-12 22:39:53 -0700100 mLocked.presentation = PRESENTATION_POINTER;
101 mLocked.presentationChanged = false;
102
103 mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
104
Jeff Brown538881e2011-05-25 18:23:38 -0700105 mLocked.pointerFadeDirection = 0;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800106 mLocked.pointerX = 0;
107 mLocked.pointerY = 0;
Jeff Brown538881e2011-05-25 18:23:38 -0700108 mLocked.pointerAlpha = 0.0f; // pointer is initially faded
Jeff Brown2352b972011-04-12 22:39:53 -0700109 mLocked.pointerSprite = mSpriteController->createSprite();
110 mLocked.pointerIconChanged = false;
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100111 mLocked.requestedPointerType= mPolicy->getDefaultPointerIconId();
Jeff Brown2352b972011-04-12 22:39:53 -0700112
Jun Mukai808196f2015-10-28 16:46:44 -0700113 mLocked.animationFrameIndex = 0;
114 mLocked.lastFrameUpdatedTime = 0;
115
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800116 mLocked.buttonState = 0;
117
Jun Mukai19a56012015-11-24 11:25:52 -0800118 mPolicy->loadPointerIcon(&mLocked.pointerIcon);
119
Jeff Brown2352b972011-04-12 22:39:53 -0700120 loadResources();
Jun Mukai19a56012015-11-24 11:25:52 -0800121
122 if (mLocked.pointerIcon.isValid()) {
123 mLocked.pointerIconChanged = true;
124 updatePointerLocked();
125 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800126}
127
128PointerController::~PointerController() {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800129 mLooper->removeMessages(mHandler);
130
Jeff Brown5541de92011-04-11 11:54:25 -0700131 AutoMutex _l(mLock);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800132
Jeff Brown2352b972011-04-12 22:39:53 -0700133 mLocked.pointerSprite.clear();
134
135 for (size_t i = 0; i < mLocked.spots.size(); i++) {
136 delete mLocked.spots.itemAt(i);
137 }
138 mLocked.spots.clear();
139 mLocked.recycledSprites.clear();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800140}
141
142bool PointerController::getBounds(float* outMinX, float* outMinY,
143 float* outMaxX, float* outMaxY) const {
144 AutoMutex _l(mLock);
145
146 return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
147}
148
149bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
150 float* outMaxX, float* outMaxY) const {
151 if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) {
152 return false;
153 }
154
155 *outMinX = 0;
156 *outMinY = 0;
157 switch (mLocked.displayOrientation) {
158 case DISPLAY_ORIENTATION_90:
159 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800160 *outMaxX = mLocked.displayHeight - 1;
161 *outMaxY = mLocked.displayWidth - 1;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800162 break;
163 default:
Jeff Brownd41cff22011-03-03 02:09:54 -0800164 *outMaxX = mLocked.displayWidth - 1;
165 *outMaxY = mLocked.displayHeight - 1;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800166 break;
167 }
168 return true;
169}
170
171void PointerController::move(float deltaX, float deltaY) {
172#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000173 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800174#endif
175 if (deltaX == 0.0f && deltaY == 0.0f) {
176 return;
177 }
178
179 AutoMutex _l(mLock);
180
181 setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
182}
183
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700184void PointerController::setButtonState(int32_t buttonState) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800185#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000186 ALOGD("Set button state 0x%08x", buttonState);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800187#endif
188 AutoMutex _l(mLock);
189
190 if (mLocked.buttonState != buttonState) {
191 mLocked.buttonState = buttonState;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800192 }
193}
194
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700195int32_t PointerController::getButtonState() const {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800196 AutoMutex _l(mLock);
197
198 return mLocked.buttonState;
199}
200
201void PointerController::setPosition(float x, float y) {
202#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000203 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800204#endif
205 AutoMutex _l(mLock);
206
207 setPositionLocked(x, y);
208}
209
210void PointerController::setPositionLocked(float x, float y) {
211 float minX, minY, maxX, maxY;
212 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
213 if (x <= minX) {
214 mLocked.pointerX = minX;
215 } else if (x >= maxX) {
216 mLocked.pointerX = maxX;
217 } else {
218 mLocked.pointerX = x;
219 }
220 if (y <= minY) {
221 mLocked.pointerY = minY;
222 } else if (y >= maxY) {
223 mLocked.pointerY = maxY;
224 } else {
225 mLocked.pointerY = y;
226 }
Jeff Brown2352b972011-04-12 22:39:53 -0700227 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800228 }
229}
230
231void PointerController::getPosition(float* outX, float* outY) const {
232 AutoMutex _l(mLock);
233
234 *outX = mLocked.pointerX;
235 *outY = mLocked.pointerY;
236}
237
Jeff Brown538881e2011-05-25 18:23:38 -0700238void PointerController::fade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800239 AutoMutex _l(mLock);
240
Jeff Brown538881e2011-05-25 18:23:38 -0700241 // Remove the inactivity timeout, since we are fading now.
242 removeInactivityTimeoutLocked();
243
244 // Start fading.
245 if (transition == TRANSITION_IMMEDIATE) {
246 mLocked.pointerFadeDirection = 0;
247 mLocked.pointerAlpha = 0.0f;
248 updatePointerLocked();
249 } else {
250 mLocked.pointerFadeDirection = -1;
251 startAnimationLocked();
252 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800253}
254
Jeff Brown538881e2011-05-25 18:23:38 -0700255void PointerController::unfade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800256 AutoMutex _l(mLock);
257
Jeff Brown2352b972011-04-12 22:39:53 -0700258 // Always reset the inactivity timer.
259 resetInactivityTimeoutLocked();
260
Jeff Brown538881e2011-05-25 18:23:38 -0700261 // Start unfading.
262 if (transition == TRANSITION_IMMEDIATE) {
263 mLocked.pointerFadeDirection = 0;
Jeff Brown2352b972011-04-12 22:39:53 -0700264 mLocked.pointerAlpha = 1.0f;
265 updatePointerLocked();
Jeff Brown538881e2011-05-25 18:23:38 -0700266 } else {
267 mLocked.pointerFadeDirection = 1;
268 startAnimationLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800269 }
270}
271
Jeff Brown2352b972011-04-12 22:39:53 -0700272void PointerController::setPresentation(Presentation presentation) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800273 AutoMutex _l(mLock);
274
Jun Mukai1db53972015-09-11 18:08:31 -0700275 if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700276 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
277 &mLocked.animationResources);
Jun Mukai1db53972015-09-11 18:08:31 -0700278 }
279
Jeff Brown2352b972011-04-12 22:39:53 -0700280 if (mLocked.presentation != presentation) {
281 mLocked.presentation = presentation;
282 mLocked.presentationChanged = true;
283
284 if (presentation != PRESENTATION_SPOT) {
285 fadeOutAndReleaseAllSpotsLocked();
286 }
287
288 updatePointerLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800289 }
290}
291
Jeff Browncb5ffcf2011-06-06 20:03:18 -0700292void PointerController::setSpots(const PointerCoords* spotCoords,
293 const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
Jeff Brown2352b972011-04-12 22:39:53 -0700294#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000295 ALOGD("setSpots: idBits=%08x", spotIdBits.value);
Jeff Brown2352b972011-04-12 22:39:53 -0700296 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
297 uint32_t id = idBits.firstMarkedBit();
298 idBits.clearBit(id);
299 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
Steve Block5baa3a62011-12-20 16:23:08 +0000300 ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id,
Jeff Brown2352b972011-04-12 22:39:53 -0700301 c.getAxisValue(AMOTION_EVENT_AXIS_X),
302 c.getAxisValue(AMOTION_EVENT_AXIS_Y),
303 c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
304 }
305#endif
306
307 AutoMutex _l(mLock);
308
309 mSpriteController->openTransaction();
310
311 // Add or move spots for fingers that are down.
312 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700313 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown2352b972011-04-12 22:39:53 -0700314 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
315 const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
316 ? mResources.spotTouch : mResources.spotHover;
317 float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
318 float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
319
320 Spot* spot = getSpotLocked(id);
321 if (!spot) {
322 spot = createAndAddSpotLocked(id);
323 }
324
325 spot->updateSprite(&icon, x, y);
326 }
327
328 // Remove spots for fingers that went up.
329 for (size_t i = 0; i < mLocked.spots.size(); i++) {
330 Spot* spot = mLocked.spots.itemAt(i);
331 if (spot->id != Spot::INVALID_ID
332 && !spotIdBits.hasBit(spot->id)) {
333 fadeOutAndReleaseSpotLocked(spot);
334 }
335 }
336
337 mSpriteController->closeTransaction();
338}
339
340void PointerController::clearSpots() {
341#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000342 ALOGD("clearSpots");
Jeff Brown2352b972011-04-12 22:39:53 -0700343#endif
344
345 AutoMutex _l(mLock);
346
347 fadeOutAndReleaseAllSpotsLocked();
348}
349
350void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
351 AutoMutex _l(mLock);
352
353 if (mLocked.inactivityTimeout != inactivityTimeout) {
354 mLocked.inactivityTimeout = inactivityTimeout;
355 resetInactivityTimeoutLocked();
356 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800357}
358
Jun Mukai19a56012015-11-24 11:25:52 -0800359void PointerController::reloadPointerResources() {
360 AutoMutex _l(mLock);
361
362 loadResources();
363
364 if (mLocked.presentation == PRESENTATION_POINTER) {
365 mLocked.additionalMouseResources.clear();
366 mLocked.animationResources.clear();
367 mPolicy->loadPointerIcon(&mLocked.pointerIcon);
368 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
369 &mLocked.animationResources);
370 }
371
372 mLocked.presentationChanged = true;
373 updatePointerLocked();
374}
375
Jeff Brownd728bf52012-09-08 18:05:28 -0700376void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800377 AutoMutex _l(mLock);
378
Jeff Brownd728bf52012-09-08 18:05:28 -0700379 // Adjust to use the display's unrotated coordinate frame.
380 if (orientation == DISPLAY_ORIENTATION_90
381 || orientation == DISPLAY_ORIENTATION_270) {
382 int32_t temp = height;
383 height = width;
384 width = temp;
385 }
386
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800387 if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
388 mLocked.displayWidth = width;
389 mLocked.displayHeight = height;
390
391 float minX, minY, maxX, maxY;
392 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
393 mLocked.pointerX = (minX + maxX) * 0.5f;
394 mLocked.pointerY = (minY + maxY) * 0.5f;
395 } else {
396 mLocked.pointerX = 0;
397 mLocked.pointerY = 0;
398 }
399
Jeff Brown2352b972011-04-12 22:39:53 -0700400 fadeOutAndReleaseAllSpotsLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800401 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800402
403 if (mLocked.displayOrientation != orientation) {
Jeff Brownd41cff22011-03-03 02:09:54 -0800404 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
405 // This creates an invariant frame of reference that we can easily rotate when
406 // taking into account that the pointer may be located at fractional pixel offsets.
407 float x = mLocked.pointerX + 0.5f;
408 float y = mLocked.pointerY + 0.5f;
409 float temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800410
Jeff Brownd41cff22011-03-03 02:09:54 -0800411 // Undo the previous rotation.
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800412 switch (mLocked.displayOrientation) {
413 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800414 temp = x;
415 x = mLocked.displayWidth - y;
416 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800417 break;
418 case DISPLAY_ORIENTATION_180:
Jeff Brownd41cff22011-03-03 02:09:54 -0800419 x = mLocked.displayWidth - x;
420 y = mLocked.displayHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800421 break;
422 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800423 temp = x;
424 x = y;
425 y = mLocked.displayHeight - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800426 break;
427 }
428
Jeff Brownd41cff22011-03-03 02:09:54 -0800429 // Perform the new rotation.
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800430 switch (orientation) {
431 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800432 temp = x;
433 x = y;
Jeff Brown5541de92011-04-11 11:54:25 -0700434 y = mLocked.displayWidth - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800435 break;
436 case DISPLAY_ORIENTATION_180:
Jeff Brownd41cff22011-03-03 02:09:54 -0800437 x = mLocked.displayWidth - x;
438 y = mLocked.displayHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800439 break;
440 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800441 temp = x;
442 x = mLocked.displayHeight - y;
443 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800444 break;
445 }
446
Jeff Brownd41cff22011-03-03 02:09:54 -0800447 // Apply offsets to convert from the pixel center to the pixel top-left corner position
448 // and save the results.
449 mLocked.pointerX = x - 0.5f;
450 mLocked.pointerY = y - 0.5f;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800451 mLocked.displayOrientation = orientation;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800452 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700453
454 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800455}
456
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100457void PointerController::updatePointerIcon(int32_t iconId) {
Jun Mukai1db53972015-09-11 18:08:31 -0700458 AutoMutex _l(mLock);
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100459 if (mLocked.requestedPointerType != iconId) {
460 mLocked.requestedPointerType = iconId;
Jun Mukai1db53972015-09-11 18:08:31 -0700461 mLocked.presentationChanged = true;
462 updatePointerLocked();
463 }
464}
465
Jun Mukaid4eaef72015-10-30 15:54:33 -0700466void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
467 AutoMutex _l(mLock);
468
469 const int32_t iconId = mPolicy->getCustomPointerIconId();
470 mLocked.additionalMouseResources[iconId] = icon;
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100471 mLocked.requestedPointerType = iconId;
Jun Mukaid4eaef72015-10-30 15:54:33 -0700472 mLocked.presentationChanged = true;
473
474 updatePointerLocked();
475}
476
Jeff Brown05dc66a2011-03-02 14:41:58 -0800477void PointerController::handleMessage(const Message& message) {
478 switch (message.what) {
Jeff Brown2352b972011-04-12 22:39:53 -0700479 case MSG_INACTIVITY_TIMEOUT:
480 doInactivityTimeout();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800481 break;
482 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800483}
484
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700485int PointerController::handleEvent(int /* fd */, int events, void* /* data */) {
486 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
487 ALOGE("Display event receiver pipe was closed or an error occurred. "
488 "events=0x%x", events);
489 return 0; // remove the callback
490 }
491
492 if (!(events & Looper::EVENT_INPUT)) {
493 ALOGW("Received spurious callback for unhandled poll event. "
494 "events=0x%x", events);
495 return 1; // keep the callback
496 }
497
498 bool gotVsync = false;
499 ssize_t n;
500 nsecs_t timestamp;
501 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
502 while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
503 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
504 if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
505 timestamp = buf[i].header.timestamp;
506 gotVsync = true;
507 }
508 }
509 }
510 if (gotVsync) {
511 doAnimate(timestamp);
512 }
513 return 1; // keep the callback
514}
515
516void PointerController::doAnimate(nsecs_t timestamp) {
Jeff Brown2352b972011-04-12 22:39:53 -0700517 AutoMutex _l(mLock);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800518
Jeff Brown2352b972011-04-12 22:39:53 -0700519 mLocked.animationPending = false;
Jun Mukai808196f2015-10-28 16:46:44 -0700520
521 bool keepFading = doFadingAnimationLocked(timestamp);
522 bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
523 if (keepFading || keepBitmapFlipping) {
524 startAnimationLocked();
525 }
526}
527
528bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
529 bool keepAnimating = false;
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700530 nsecs_t frameDelay = timestamp - mLocked.animationTime;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800531
Jeff Brown2352b972011-04-12 22:39:53 -0700532 // Animate pointer fade.
Jeff Brown538881e2011-05-25 18:23:38 -0700533 if (mLocked.pointerFadeDirection < 0) {
Jeff Brown2352b972011-04-12 22:39:53 -0700534 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
Jeff Brown538881e2011-05-25 18:23:38 -0700535 if (mLocked.pointerAlpha <= 0.0f) {
536 mLocked.pointerAlpha = 0.0f;
537 mLocked.pointerFadeDirection = 0;
538 } else {
539 keepAnimating = true;
540 }
541 updatePointerLocked();
542 } else if (mLocked.pointerFadeDirection > 0) {
543 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
544 if (mLocked.pointerAlpha >= 1.0f) {
545 mLocked.pointerAlpha = 1.0f;
546 mLocked.pointerFadeDirection = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800547 } else {
Jeff Brown2352b972011-04-12 22:39:53 -0700548 keepAnimating = true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800549 }
Jeff Brown2352b972011-04-12 22:39:53 -0700550 updatePointerLocked();
551 }
552
553 // Animate spots that are fading out and being removed.
554 for (size_t i = 0; i < mLocked.spots.size(); i++) {
555 Spot* spot = mLocked.spots.itemAt(i);
556 if (spot->id == Spot::INVALID_ID) {
557 spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
558 if (spot->alpha <= 0) {
559 mLocked.spots.removeAt(i--);
560 releaseSpotLocked(spot);
561 } else {
562 spot->sprite->setAlpha(spot->alpha);
563 keepAnimating = true;
564 }
565 }
566 }
Jun Mukai808196f2015-10-28 16:46:44 -0700567 return keepAnimating;
568}
Jeff Brown2352b972011-04-12 22:39:53 -0700569
Jun Mukai808196f2015-10-28 16:46:44 -0700570bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
571 std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100572 mLocked.requestedPointerType);
Jun Mukai808196f2015-10-28 16:46:44 -0700573 if (iter == mLocked.animationResources.end()) {
574 return false;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800575 }
Jun Mukai808196f2015-10-28 16:46:44 -0700576
577 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
578 mSpriteController->openTransaction();
579
580 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
581 mLocked.animationFrameIndex += incr;
582 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
583 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
584 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
585 }
586 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
587
588 mSpriteController->closeTransaction();
589 }
590
591 // Keep animating.
592 return true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800593}
594
Jeff Brown2352b972011-04-12 22:39:53 -0700595void PointerController::doInactivityTimeout() {
Jeff Brown538881e2011-05-25 18:23:38 -0700596 fade(TRANSITION_GRADUAL);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800597}
598
Jeff Brown2352b972011-04-12 22:39:53 -0700599void PointerController::startAnimationLocked() {
600 if (!mLocked.animationPending) {
601 mLocked.animationPending = true;
602 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700603 mDisplayEventReceiver.requestNextVsync();
Jeff Brown2352b972011-04-12 22:39:53 -0700604 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800605}
606
Jeff Brown2352b972011-04-12 22:39:53 -0700607void PointerController::resetInactivityTimeoutLocked() {
608 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
609
610 nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
611 ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
612 mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
613}
614
Jeff Brown538881e2011-05-25 18:23:38 -0700615void PointerController::removeInactivityTimeoutLocked() {
Jeff Brown2352b972011-04-12 22:39:53 -0700616 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
Jeff Brown2352b972011-04-12 22:39:53 -0700617}
618
619void PointerController::updatePointerLocked() {
620 mSpriteController->openTransaction();
621
622 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
623 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
624
625 if (mLocked.pointerAlpha > 0) {
626 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
627 mLocked.pointerSprite->setVisible(true);
628 } else {
629 mLocked.pointerSprite->setVisible(false);
630 }
631
632 if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
Jun Mukai1db53972015-09-11 18:08:31 -0700633 if (mLocked.presentation == PRESENTATION_POINTER) {
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100634 if (mLocked.requestedPointerType== mPolicy->getDefaultPointerIconId()) {
Jun Mukai1db53972015-09-11 18:08:31 -0700635 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
636 } else {
Jun Mukai808196f2015-10-28 16:46:44 -0700637 std::map<int32_t, SpriteIcon>::const_iterator iter =
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100638 mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
Jun Mukai1db53972015-09-11 18:08:31 -0700639 if (iter != mLocked.additionalMouseResources.end()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700640 std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100641 mLocked.animationResources.find(mLocked.requestedPointerType);
Jun Mukai808196f2015-10-28 16:46:44 -0700642 if (anim_iter != mLocked.animationResources.end()) {
643 mLocked.animationFrameIndex = 0;
644 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
645 startAnimationLocked();
646 }
Jun Mukai1db53972015-09-11 18:08:31 -0700647 mLocked.pointerSprite->setIcon(iter->second);
648 } else {
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100649 ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
Jun Mukai1db53972015-09-11 18:08:31 -0700650 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
651 }
652 }
653 } else {
654 mLocked.pointerSprite->setIcon(mResources.spotAnchor);
655 }
Jeff Brown2352b972011-04-12 22:39:53 -0700656 mLocked.pointerIconChanged = false;
657 mLocked.presentationChanged = false;
658 }
659
660 mSpriteController->closeTransaction();
661}
662
663PointerController::Spot* PointerController::getSpotLocked(uint32_t id) {
664 for (size_t i = 0; i < mLocked.spots.size(); i++) {
665 Spot* spot = mLocked.spots.itemAt(i);
666 if (spot->id == id) {
667 return spot;
668 }
669 }
670 return NULL;
671}
672
673PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) {
674 // Remove spots until we have fewer than MAX_SPOTS remaining.
675 while (mLocked.spots.size() >= MAX_SPOTS) {
676 Spot* spot = removeFirstFadingSpotLocked();
677 if (!spot) {
678 spot = mLocked.spots.itemAt(0);
679 mLocked.spots.removeAt(0);
680 }
681 releaseSpotLocked(spot);
682 }
683
684 // Obtain a sprite from the recycled pool.
685 sp<Sprite> sprite;
686 if (! mLocked.recycledSprites.isEmpty()) {
687 sprite = mLocked.recycledSprites.top();
688 mLocked.recycledSprites.pop();
689 } else {
690 sprite = mSpriteController->createSprite();
691 }
692
693 // Return the new spot.
694 Spot* spot = new Spot(id, sprite);
695 mLocked.spots.push(spot);
696 return spot;
697}
698
699PointerController::Spot* PointerController::removeFirstFadingSpotLocked() {
700 for (size_t i = 0; i < mLocked.spots.size(); i++) {
701 Spot* spot = mLocked.spots.itemAt(i);
702 if (spot->id == Spot::INVALID_ID) {
703 mLocked.spots.removeAt(i);
704 return spot;
705 }
706 }
707 return NULL;
708}
709
710void PointerController::releaseSpotLocked(Spot* spot) {
711 spot->sprite->clearIcon();
712
713 if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
714 mLocked.recycledSprites.push(spot->sprite);
715 }
716
717 delete spot;
718}
719
720void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
721 if (spot->id != Spot::INVALID_ID) {
722 spot->id = Spot::INVALID_ID;
723 startAnimationLocked();
724 }
725}
726
727void PointerController::fadeOutAndReleaseAllSpotsLocked() {
728 for (size_t i = 0; i < mLocked.spots.size(); i++) {
729 Spot* spot = mLocked.spots.itemAt(i);
730 fadeOutAndReleaseSpotLocked(spot);
731 }
732}
733
734void PointerController::loadResources() {
735 mPolicy->loadPointerResources(&mResources);
736}
737
738
739// --- PointerController::Spot ---
740
741void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) {
742 sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
743 sprite->setAlpha(alpha);
744 sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
745 sprite->setPosition(x, y);
746
747 this->x = x;
748 this->y = y;
749
750 if (icon != lastIcon) {
751 lastIcon = icon;
752 if (icon) {
753 sprite->setIcon(*icon);
754 sprite->setVisible(true);
755 } else {
756 sprite->setVisible(false);
757 }
758 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800759}
760
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800761} // namespace android