blob: ad9e2d7b6e16ddab07a3f87750b486439e9a327b [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
39// --- PointerController ---
40
Jeff Brown05dc66a2011-03-02 14:41:58 -080041// Time to wait before starting the fade when the pointer is inactive.
Jeff Brown2352b972011-04-12 22:39:53 -070042static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
43static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
44
Jeff Brown2352b972011-04-12 22:39:53 -070045// Time to spend fading out the spot completely.
46static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
Jeff Brown05dc66a2011-03-02 14:41:58 -080047
48// Time to spend fading out the pointer completely.
Jeff Brown2352b972011-04-12 22:39:53 -070049static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
Jeff Brown05dc66a2011-03-02 14:41:58 -080050
Jun Mukaic0c0ac32015-10-27 10:09:21 -070051// The number of events to be read at once for DisplayEventReceiver.
52static const int EVENT_BUFFER_SIZE = 100;
Jeff Brown05dc66a2011-03-02 14:41:58 -080053
Jeff Brown2352b972011-04-12 22:39:53 -070054// --- PointerController ---
55
56PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
57 const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
58 mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
Jeff Brown5541de92011-04-11 11:54:25 -070059 mHandler = new WeakMessageHandler(this);
60
Jun Mukaic0c0ac32015-10-27 10:09:21 -070061 if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
62 mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
63 Looper::EVENT_INPUT, this, nullptr);
64 } else {
65 ALOGE("Failed to initialize DisplayEventReceiver.");
66 }
67
Jeff Brownb4ff35d2011-01-02 16:37:43 -080068 AutoMutex _l(mLock);
69
Jeff Brown2352b972011-04-12 22:39:53 -070070 mLocked.animationPending = false;
71
Jeff Brownb4ff35d2011-01-02 16:37:43 -080072 mLocked.displayWidth = -1;
73 mLocked.displayHeight = -1;
74 mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
75
Jeff Brown2352b972011-04-12 22:39:53 -070076 mLocked.presentation = PRESENTATION_POINTER;
77 mLocked.presentationChanged = false;
78
79 mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
80
Jeff Brown538881e2011-05-25 18:23:38 -070081 mLocked.pointerFadeDirection = 0;
Jeff Brownb4ff35d2011-01-02 16:37:43 -080082 mLocked.pointerX = 0;
83 mLocked.pointerY = 0;
Jeff Brown538881e2011-05-25 18:23:38 -070084 mLocked.pointerAlpha = 0.0f; // pointer is initially faded
Jeff Brown2352b972011-04-12 22:39:53 -070085 mLocked.pointerSprite = mSpriteController->createSprite();
86 mLocked.pointerIconChanged = false;
Michael Wrighte051f6f2016-05-13 17:44:16 +010087 mLocked.requestedPointerType = mPolicy->getDefaultPointerIconId();
Jeff Brown2352b972011-04-12 22:39:53 -070088
Jun Mukai808196f2015-10-28 16:46:44 -070089 mLocked.animationFrameIndex = 0;
90 mLocked.lastFrameUpdatedTime = 0;
91
Jeff Brownb4ff35d2011-01-02 16:37:43 -080092 mLocked.buttonState = 0;
Jun Mukai347e5d42015-12-03 01:13:31 -080093 mLocked.iconDetached = false;
Jeff Brownb4ff35d2011-01-02 16:37:43 -080094
Jun Mukai19a56012015-11-24 11:25:52 -080095 mPolicy->loadPointerIcon(&mLocked.pointerIcon);
96
Jeff Brown2352b972011-04-12 22:39:53 -070097 loadResources();
Jun Mukai19a56012015-11-24 11:25:52 -080098
99 if (mLocked.pointerIcon.isValid()) {
100 mLocked.pointerIconChanged = true;
101 updatePointerLocked();
102 }
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
112 for (size_t i = 0; i < mLocked.spots.size(); i++) {
113 delete mLocked.spots.itemAt(i);
114 }
115 mLocked.spots.clear();
116 mLocked.recycledSprites.clear();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800117}
118
119bool PointerController::getBounds(float* outMinX, float* outMinY,
120 float* outMaxX, float* outMaxY) const {
121 AutoMutex _l(mLock);
122
123 return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
124}
125
126bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
127 float* outMaxX, float* outMaxY) const {
128 if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) {
129 return false;
130 }
131
132 *outMinX = 0;
133 *outMinY = 0;
134 switch (mLocked.displayOrientation) {
135 case DISPLAY_ORIENTATION_90:
136 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800137 *outMaxX = mLocked.displayHeight - 1;
138 *outMaxY = mLocked.displayWidth - 1;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800139 break;
140 default:
Jeff Brownd41cff22011-03-03 02:09:54 -0800141 *outMaxX = mLocked.displayWidth - 1;
142 *outMaxY = mLocked.displayHeight - 1;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800143 break;
144 }
145 return true;
146}
147
148void PointerController::move(float deltaX, float deltaY) {
149#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000150 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800151#endif
152 if (deltaX == 0.0f && deltaY == 0.0f) {
153 return;
154 }
155
156 AutoMutex _l(mLock);
157
158 setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
159}
160
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700161void PointerController::setButtonState(int32_t buttonState) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800162#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000163 ALOGD("Set button state 0x%08x", buttonState);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800164#endif
165 AutoMutex _l(mLock);
166
167 if (mLocked.buttonState != buttonState) {
168 mLocked.buttonState = buttonState;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800169 }
170}
171
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700172int32_t PointerController::getButtonState() const {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800173 AutoMutex _l(mLock);
174
175 return mLocked.buttonState;
176}
177
178void PointerController::setPosition(float x, float y) {
179#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000180 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800181#endif
182 AutoMutex _l(mLock);
183
184 setPositionLocked(x, y);
185}
186
187void PointerController::setPositionLocked(float x, float y) {
Jun Mukai347e5d42015-12-03 01:13:31 -0800188 if (mLocked.iconDetached) {
189 return;
190 }
191
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800192 float minX, minY, maxX, maxY;
193 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
194 if (x <= minX) {
195 mLocked.pointerX = minX;
196 } else if (x >= maxX) {
197 mLocked.pointerX = maxX;
198 } else {
199 mLocked.pointerX = x;
200 }
201 if (y <= minY) {
202 mLocked.pointerY = minY;
203 } else if (y >= maxY) {
204 mLocked.pointerY = maxY;
205 } else {
206 mLocked.pointerY = y;
207 }
Jeff Brown2352b972011-04-12 22:39:53 -0700208 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800209 }
210}
211
212void PointerController::getPosition(float* outX, float* outY) const {
213 AutoMutex _l(mLock);
214
215 *outX = mLocked.pointerX;
216 *outY = mLocked.pointerY;
217}
218
Jeff Brown538881e2011-05-25 18:23:38 -0700219void PointerController::fade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800220 AutoMutex _l(mLock);
221
Jeff Brown538881e2011-05-25 18:23:38 -0700222 // Remove the inactivity timeout, since we are fading now.
223 removeInactivityTimeoutLocked();
224
Jun Mukai347e5d42015-12-03 01:13:31 -0800225 if (mLocked.iconDetached) {
226 return;
227 }
228
Jeff Brown538881e2011-05-25 18:23:38 -0700229 // Start fading.
230 if (transition == TRANSITION_IMMEDIATE) {
231 mLocked.pointerFadeDirection = 0;
232 mLocked.pointerAlpha = 0.0f;
233 updatePointerLocked();
234 } else {
235 mLocked.pointerFadeDirection = -1;
236 startAnimationLocked();
237 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800238}
239
Jeff Brown538881e2011-05-25 18:23:38 -0700240void PointerController::unfade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800241 AutoMutex _l(mLock);
242
Jeff Brown2352b972011-04-12 22:39:53 -0700243 // Always reset the inactivity timer.
244 resetInactivityTimeoutLocked();
245
Jun Mukai347e5d42015-12-03 01:13:31 -0800246 if (mLocked.iconDetached) {
247 return;
248 }
249
Jeff Brown538881e2011-05-25 18:23:38 -0700250 // Start unfading.
251 if (transition == TRANSITION_IMMEDIATE) {
252 mLocked.pointerFadeDirection = 0;
Jeff Brown2352b972011-04-12 22:39:53 -0700253 mLocked.pointerAlpha = 1.0f;
254 updatePointerLocked();
Jeff Brown538881e2011-05-25 18:23:38 -0700255 } else {
256 mLocked.pointerFadeDirection = 1;
257 startAnimationLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800258 }
259}
260
Jeff Brown2352b972011-04-12 22:39:53 -0700261void PointerController::setPresentation(Presentation presentation) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800262 AutoMutex _l(mLock);
263
Jun Mukai1db53972015-09-11 18:08:31 -0700264 if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700265 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
266 &mLocked.animationResources);
Jun Mukai1db53972015-09-11 18:08:31 -0700267 }
268
Jeff Brown2352b972011-04-12 22:39:53 -0700269 if (mLocked.presentation != presentation) {
270 mLocked.presentation = presentation;
271 mLocked.presentationChanged = true;
272
273 if (presentation != PRESENTATION_SPOT) {
274 fadeOutAndReleaseAllSpotsLocked();
275 }
276
277 updatePointerLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800278 }
279}
280
Jeff Browncb5ffcf2011-06-06 20:03:18 -0700281void PointerController::setSpots(const PointerCoords* spotCoords,
282 const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
Jeff Brown2352b972011-04-12 22:39:53 -0700283#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000284 ALOGD("setSpots: idBits=%08x", spotIdBits.value);
Jeff Brown2352b972011-04-12 22:39:53 -0700285 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
286 uint32_t id = idBits.firstMarkedBit();
287 idBits.clearBit(id);
288 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
Steve Block5baa3a62011-12-20 16:23:08 +0000289 ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id,
Jeff Brown2352b972011-04-12 22:39:53 -0700290 c.getAxisValue(AMOTION_EVENT_AXIS_X),
291 c.getAxisValue(AMOTION_EVENT_AXIS_Y),
292 c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
293 }
294#endif
295
296 AutoMutex _l(mLock);
297
298 mSpriteController->openTransaction();
299
300 // Add or move spots for fingers that are down.
301 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700302 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown2352b972011-04-12 22:39:53 -0700303 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
304 const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
305 ? mResources.spotTouch : mResources.spotHover;
306 float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
307 float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
308
309 Spot* spot = getSpotLocked(id);
310 if (!spot) {
311 spot = createAndAddSpotLocked(id);
312 }
313
314 spot->updateSprite(&icon, x, y);
315 }
316
317 // Remove spots for fingers that went up.
318 for (size_t i = 0; i < mLocked.spots.size(); i++) {
319 Spot* spot = mLocked.spots.itemAt(i);
320 if (spot->id != Spot::INVALID_ID
321 && !spotIdBits.hasBit(spot->id)) {
322 fadeOutAndReleaseSpotLocked(spot);
323 }
324 }
325
326 mSpriteController->closeTransaction();
327}
328
329void PointerController::clearSpots() {
330#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000331 ALOGD("clearSpots");
Jeff Brown2352b972011-04-12 22:39:53 -0700332#endif
333
334 AutoMutex _l(mLock);
335
336 fadeOutAndReleaseAllSpotsLocked();
337}
338
339void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
340 AutoMutex _l(mLock);
341
342 if (mLocked.inactivityTimeout != inactivityTimeout) {
343 mLocked.inactivityTimeout = inactivityTimeout;
344 resetInactivityTimeoutLocked();
345 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800346}
347
Jun Mukai19a56012015-11-24 11:25:52 -0800348void PointerController::reloadPointerResources() {
349 AutoMutex _l(mLock);
350
351 loadResources();
352
353 if (mLocked.presentation == PRESENTATION_POINTER) {
354 mLocked.additionalMouseResources.clear();
355 mLocked.animationResources.clear();
356 mPolicy->loadPointerIcon(&mLocked.pointerIcon);
357 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
358 &mLocked.animationResources);
359 }
360
361 mLocked.presentationChanged = true;
362 updatePointerLocked();
363}
364
Jun Mukai347e5d42015-12-03 01:13:31 -0800365void PointerController::detachPointerIcon(bool detached) {
366 AutoMutex _l(mLock);
367
368 if (mLocked.iconDetached == detached) {
369 return;
370 }
371
372 mLocked.iconDetached = detached;
373 if (detached) {
374 mLocked.pointerFadeDirection = -1;
375 } else {
376 mLocked.pointerFadeDirection = 1;
377 }
378 startAnimationLocked();
379}
380
Jeff Brownd728bf52012-09-08 18:05:28 -0700381void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800382 AutoMutex _l(mLock);
383
Jeff Brownd728bf52012-09-08 18:05:28 -0700384 // Adjust to use the display's unrotated coordinate frame.
385 if (orientation == DISPLAY_ORIENTATION_90
386 || orientation == DISPLAY_ORIENTATION_270) {
387 int32_t temp = height;
388 height = width;
389 width = temp;
390 }
391
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800392 if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
393 mLocked.displayWidth = width;
394 mLocked.displayHeight = height;
395
396 float minX, minY, maxX, maxY;
397 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
398 mLocked.pointerX = (minX + maxX) * 0.5f;
399 mLocked.pointerY = (minY + maxY) * 0.5f;
400 } else {
401 mLocked.pointerX = 0;
402 mLocked.pointerY = 0;
403 }
404
Jeff Brown2352b972011-04-12 22:39:53 -0700405 fadeOutAndReleaseAllSpotsLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800406 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800407
408 if (mLocked.displayOrientation != orientation) {
Jeff Brownd41cff22011-03-03 02:09:54 -0800409 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
410 // This creates an invariant frame of reference that we can easily rotate when
411 // taking into account that the pointer may be located at fractional pixel offsets.
412 float x = mLocked.pointerX + 0.5f;
413 float y = mLocked.pointerY + 0.5f;
414 float temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800415
Jeff Brownd41cff22011-03-03 02:09:54 -0800416 // Undo the previous rotation.
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800417 switch (mLocked.displayOrientation) {
418 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800419 temp = x;
420 x = mLocked.displayWidth - y;
421 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800422 break;
423 case DISPLAY_ORIENTATION_180:
Jeff Brownd41cff22011-03-03 02:09:54 -0800424 x = mLocked.displayWidth - x;
425 y = mLocked.displayHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800426 break;
427 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800428 temp = x;
429 x = y;
430 y = mLocked.displayHeight - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800431 break;
432 }
433
Jeff Brownd41cff22011-03-03 02:09:54 -0800434 // Perform the new rotation.
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800435 switch (orientation) {
436 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800437 temp = x;
438 x = y;
Jeff Brown5541de92011-04-11 11:54:25 -0700439 y = mLocked.displayWidth - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800440 break;
441 case DISPLAY_ORIENTATION_180:
Jeff Brownd41cff22011-03-03 02:09:54 -0800442 x = mLocked.displayWidth - x;
443 y = mLocked.displayHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800444 break;
445 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800446 temp = x;
447 x = mLocked.displayHeight - y;
448 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800449 break;
450 }
451
Jeff Brownd41cff22011-03-03 02:09:54 -0800452 // Apply offsets to convert from the pixel center to the pixel top-left corner position
453 // and save the results.
454 mLocked.pointerX = x - 0.5f;
455 mLocked.pointerY = y - 0.5f;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800456 mLocked.displayOrientation = orientation;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800457 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700458
459 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800460}
461
Michael Wrighte051f6f2016-05-13 17:44:16 +0100462void PointerController::updatePointerIcon(int32_t iconId) {
Jun Mukai1db53972015-09-11 18:08:31 -0700463 AutoMutex _l(mLock);
Michael Wrighte051f6f2016-05-13 17:44:16 +0100464 if (mLocked.requestedPointerType != iconId) {
465 mLocked.requestedPointerType = iconId;
Jun Mukai1db53972015-09-11 18:08:31 -0700466 mLocked.presentationChanged = true;
467 updatePointerLocked();
468 }
469}
470
Jun Mukaid4eaef72015-10-30 15:54:33 -0700471void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
472 AutoMutex _l(mLock);
473
474 const int32_t iconId = mPolicy->getCustomPointerIconId();
475 mLocked.additionalMouseResources[iconId] = icon;
Michael Wrighte051f6f2016-05-13 17:44:16 +0100476 mLocked.requestedPointerType = iconId;
Jun Mukaid4eaef72015-10-30 15:54:33 -0700477 mLocked.presentationChanged = true;
478
479 updatePointerLocked();
480}
481
Jeff Brown05dc66a2011-03-02 14:41:58 -0800482void PointerController::handleMessage(const Message& message) {
483 switch (message.what) {
Jeff Brown2352b972011-04-12 22:39:53 -0700484 case MSG_INACTIVITY_TIMEOUT:
485 doInactivityTimeout();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800486 break;
487 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800488}
489
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700490int PointerController::handleEvent(int /* fd */, int events, void* /* data */) {
491 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
492 ALOGE("Display event receiver pipe was closed or an error occurred. "
493 "events=0x%x", events);
494 return 0; // remove the callback
495 }
496
497 if (!(events & Looper::EVENT_INPUT)) {
498 ALOGW("Received spurious callback for unhandled poll event. "
499 "events=0x%x", events);
500 return 1; // keep the callback
501 }
502
503 bool gotVsync = false;
504 ssize_t n;
505 nsecs_t timestamp;
506 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
507 while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
508 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
509 if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
510 timestamp = buf[i].header.timestamp;
511 gotVsync = true;
512 }
513 }
514 }
515 if (gotVsync) {
516 doAnimate(timestamp);
517 }
518 return 1; // keep the callback
519}
520
521void PointerController::doAnimate(nsecs_t timestamp) {
Jeff Brown2352b972011-04-12 22:39:53 -0700522 AutoMutex _l(mLock);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800523
Jeff Brown2352b972011-04-12 22:39:53 -0700524 mLocked.animationPending = false;
Jun Mukai808196f2015-10-28 16:46:44 -0700525
526 bool keepFading = doFadingAnimationLocked(timestamp);
527 bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
528 if (keepFading || keepBitmapFlipping) {
529 startAnimationLocked();
530 }
531}
532
533bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
534 bool keepAnimating = false;
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700535 nsecs_t frameDelay = timestamp - mLocked.animationTime;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800536
Jeff Brown2352b972011-04-12 22:39:53 -0700537 // Animate pointer fade.
Jeff Brown538881e2011-05-25 18:23:38 -0700538 if (mLocked.pointerFadeDirection < 0) {
Jeff Brown2352b972011-04-12 22:39:53 -0700539 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
Jeff Brown538881e2011-05-25 18:23:38 -0700540 if (mLocked.pointerAlpha <= 0.0f) {
541 mLocked.pointerAlpha = 0.0f;
542 mLocked.pointerFadeDirection = 0;
543 } else {
544 keepAnimating = true;
545 }
546 updatePointerLocked();
547 } else if (mLocked.pointerFadeDirection > 0) {
548 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
549 if (mLocked.pointerAlpha >= 1.0f) {
550 mLocked.pointerAlpha = 1.0f;
551 mLocked.pointerFadeDirection = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800552 } else {
Jeff Brown2352b972011-04-12 22:39:53 -0700553 keepAnimating = true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800554 }
Jeff Brown2352b972011-04-12 22:39:53 -0700555 updatePointerLocked();
556 }
557
558 // Animate spots that are fading out and being removed.
559 for (size_t i = 0; i < mLocked.spots.size(); i++) {
560 Spot* spot = mLocked.spots.itemAt(i);
561 if (spot->id == Spot::INVALID_ID) {
562 spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
563 if (spot->alpha <= 0) {
564 mLocked.spots.removeAt(i--);
565 releaseSpotLocked(spot);
566 } else {
567 spot->sprite->setAlpha(spot->alpha);
568 keepAnimating = true;
569 }
570 }
571 }
Jun Mukai808196f2015-10-28 16:46:44 -0700572 return keepAnimating;
573}
Jeff Brown2352b972011-04-12 22:39:53 -0700574
Jun Mukai808196f2015-10-28 16:46:44 -0700575bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
576 std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
Michael Wrighte051f6f2016-05-13 17:44:16 +0100577 mLocked.requestedPointerType);
Jun Mukai808196f2015-10-28 16:46:44 -0700578 if (iter == mLocked.animationResources.end()) {
579 return false;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800580 }
Jun Mukai808196f2015-10-28 16:46:44 -0700581
582 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
583 mSpriteController->openTransaction();
584
585 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
586 mLocked.animationFrameIndex += incr;
587 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
588 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
589 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
590 }
591 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
592
593 mSpriteController->closeTransaction();
594 }
595
596 // Keep animating.
597 return true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800598}
599
Jeff Brown2352b972011-04-12 22:39:53 -0700600void PointerController::doInactivityTimeout() {
Jeff Brown538881e2011-05-25 18:23:38 -0700601 fade(TRANSITION_GRADUAL);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800602}
603
Jeff Brown2352b972011-04-12 22:39:53 -0700604void PointerController::startAnimationLocked() {
605 if (!mLocked.animationPending) {
606 mLocked.animationPending = true;
607 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700608 mDisplayEventReceiver.requestNextVsync();
Jeff Brown2352b972011-04-12 22:39:53 -0700609 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800610}
611
Jeff Brown2352b972011-04-12 22:39:53 -0700612void PointerController::resetInactivityTimeoutLocked() {
613 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
614
615 nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
616 ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
617 mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
618}
619
Jeff Brown538881e2011-05-25 18:23:38 -0700620void PointerController::removeInactivityTimeoutLocked() {
Jeff Brown2352b972011-04-12 22:39:53 -0700621 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
Jeff Brown2352b972011-04-12 22:39:53 -0700622}
623
624void PointerController::updatePointerLocked() {
625 mSpriteController->openTransaction();
626
627 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
628 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
629
630 if (mLocked.pointerAlpha > 0) {
631 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
632 mLocked.pointerSprite->setVisible(true);
633 } else {
634 mLocked.pointerSprite->setVisible(false);
635 }
636
637 if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
Jun Mukai1db53972015-09-11 18:08:31 -0700638 if (mLocked.presentation == PRESENTATION_POINTER) {
Michael Wrighte051f6f2016-05-13 17:44:16 +0100639 if (mLocked.requestedPointerType == mPolicy->getDefaultPointerIconId()) {
Jun Mukai1db53972015-09-11 18:08:31 -0700640 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
641 } else {
Jun Mukai808196f2015-10-28 16:46:44 -0700642 std::map<int32_t, SpriteIcon>::const_iterator iter =
Michael Wrighte051f6f2016-05-13 17:44:16 +0100643 mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
Jun Mukai1db53972015-09-11 18:08:31 -0700644 if (iter != mLocked.additionalMouseResources.end()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700645 std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
Michael Wrighte051f6f2016-05-13 17:44:16 +0100646 mLocked.animationResources.find(mLocked.requestedPointerType);
Jun Mukai808196f2015-10-28 16:46:44 -0700647 if (anim_iter != mLocked.animationResources.end()) {
648 mLocked.animationFrameIndex = 0;
649 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
650 startAnimationLocked();
651 }
Jun Mukai1db53972015-09-11 18:08:31 -0700652 mLocked.pointerSprite->setIcon(iter->second);
653 } else {
Michael Wrighte051f6f2016-05-13 17:44:16 +0100654 ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
Jun Mukai1db53972015-09-11 18:08:31 -0700655 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
656 }
657 }
658 } else {
659 mLocked.pointerSprite->setIcon(mResources.spotAnchor);
660 }
Jeff Brown2352b972011-04-12 22:39:53 -0700661 mLocked.pointerIconChanged = false;
662 mLocked.presentationChanged = false;
663 }
664
665 mSpriteController->closeTransaction();
666}
667
668PointerController::Spot* PointerController::getSpotLocked(uint32_t id) {
669 for (size_t i = 0; i < mLocked.spots.size(); i++) {
670 Spot* spot = mLocked.spots.itemAt(i);
671 if (spot->id == id) {
672 return spot;
673 }
674 }
675 return NULL;
676}
677
678PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) {
679 // Remove spots until we have fewer than MAX_SPOTS remaining.
680 while (mLocked.spots.size() >= MAX_SPOTS) {
681 Spot* spot = removeFirstFadingSpotLocked();
682 if (!spot) {
683 spot = mLocked.spots.itemAt(0);
684 mLocked.spots.removeAt(0);
685 }
686 releaseSpotLocked(spot);
687 }
688
689 // Obtain a sprite from the recycled pool.
690 sp<Sprite> sprite;
691 if (! mLocked.recycledSprites.isEmpty()) {
692 sprite = mLocked.recycledSprites.top();
693 mLocked.recycledSprites.pop();
694 } else {
695 sprite = mSpriteController->createSprite();
696 }
697
698 // Return the new spot.
699 Spot* spot = new Spot(id, sprite);
700 mLocked.spots.push(spot);
701 return spot;
702}
703
704PointerController::Spot* PointerController::removeFirstFadingSpotLocked() {
705 for (size_t i = 0; i < mLocked.spots.size(); i++) {
706 Spot* spot = mLocked.spots.itemAt(i);
707 if (spot->id == Spot::INVALID_ID) {
708 mLocked.spots.removeAt(i);
709 return spot;
710 }
711 }
712 return NULL;
713}
714
715void PointerController::releaseSpotLocked(Spot* spot) {
716 spot->sprite->clearIcon();
717
718 if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
719 mLocked.recycledSprites.push(spot->sprite);
720 }
721
722 delete spot;
723}
724
725void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
726 if (spot->id != Spot::INVALID_ID) {
727 spot->id = Spot::INVALID_ID;
728 startAnimationLocked();
729 }
730}
731
732void PointerController::fadeOutAndReleaseAllSpotsLocked() {
733 for (size_t i = 0; i < mLocked.spots.size(); i++) {
734 Spot* spot = mLocked.spots.itemAt(i);
735 fadeOutAndReleaseSpotLocked(spot);
736 }
737}
738
739void PointerController::loadResources() {
740 mPolicy->loadPointerResources(&mResources);
741}
742
743
744// --- PointerController::Spot ---
745
746void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) {
747 sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
748 sprite->setAlpha(alpha);
749 sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
750 sprite->setPosition(x, y);
751
752 this->x = x;
753 this->y = y;
754
755 if (icon != lastIcon) {
756 lastIcon = icon;
757 if (icon) {
758 sprite->setIcon(*icon);
759 sprite->setVisible(true);
760 } else {
761 sprite->setVisible(false);
762 }
763 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800764}
765
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800766} // namespace android