blob: 6a1167a02c0b3475e7e1a825548581e424fb85aa [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;
Jun Mukai5ec74202015-10-07 16:58:09 +090087 mLocked.requestedPointerShape = 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;
93
Jun Mukai19a56012015-11-24 11:25:52 -080094 mPolicy->loadPointerIcon(&mLocked.pointerIcon);
95
Jeff Brown2352b972011-04-12 22:39:53 -070096 loadResources();
Jun Mukai19a56012015-11-24 11:25:52 -080097
98 if (mLocked.pointerIcon.isValid()) {
99 mLocked.pointerIconChanged = true;
100 updatePointerLocked();
101 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800102}
103
104PointerController::~PointerController() {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800105 mLooper->removeMessages(mHandler);
106
Jeff Brown5541de92011-04-11 11:54:25 -0700107 AutoMutex _l(mLock);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800108
Jeff Brown2352b972011-04-12 22:39:53 -0700109 mLocked.pointerSprite.clear();
110
111 for (size_t i = 0; i < mLocked.spots.size(); i++) {
112 delete mLocked.spots.itemAt(i);
113 }
114 mLocked.spots.clear();
115 mLocked.recycledSprites.clear();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800116}
117
118bool PointerController::getBounds(float* outMinX, float* outMinY,
119 float* outMaxX, float* outMaxY) const {
120 AutoMutex _l(mLock);
121
122 return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
123}
124
125bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
126 float* outMaxX, float* outMaxY) const {
127 if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) {
128 return false;
129 }
130
131 *outMinX = 0;
132 *outMinY = 0;
133 switch (mLocked.displayOrientation) {
134 case DISPLAY_ORIENTATION_90:
135 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800136 *outMaxX = mLocked.displayHeight - 1;
137 *outMaxY = mLocked.displayWidth - 1;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800138 break;
139 default:
Jeff Brownd41cff22011-03-03 02:09:54 -0800140 *outMaxX = mLocked.displayWidth - 1;
141 *outMaxY = mLocked.displayHeight - 1;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800142 break;
143 }
144 return true;
145}
146
147void PointerController::move(float deltaX, float deltaY) {
148#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000149 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800150#endif
151 if (deltaX == 0.0f && deltaY == 0.0f) {
152 return;
153 }
154
155 AutoMutex _l(mLock);
156
157 setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
158}
159
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700160void PointerController::setButtonState(int32_t buttonState) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800161#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000162 ALOGD("Set button state 0x%08x", buttonState);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800163#endif
164 AutoMutex _l(mLock);
165
166 if (mLocked.buttonState != buttonState) {
167 mLocked.buttonState = buttonState;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800168 }
169}
170
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700171int32_t PointerController::getButtonState() const {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800172 AutoMutex _l(mLock);
173
174 return mLocked.buttonState;
175}
176
177void PointerController::setPosition(float x, float y) {
178#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000179 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800180#endif
181 AutoMutex _l(mLock);
182
183 setPositionLocked(x, y);
184}
185
186void PointerController::setPositionLocked(float x, float y) {
187 float minX, minY, maxX, maxY;
188 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
189 if (x <= minX) {
190 mLocked.pointerX = minX;
191 } else if (x >= maxX) {
192 mLocked.pointerX = maxX;
193 } else {
194 mLocked.pointerX = x;
195 }
196 if (y <= minY) {
197 mLocked.pointerY = minY;
198 } else if (y >= maxY) {
199 mLocked.pointerY = maxY;
200 } else {
201 mLocked.pointerY = y;
202 }
Jeff Brown2352b972011-04-12 22:39:53 -0700203 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800204 }
205}
206
207void PointerController::getPosition(float* outX, float* outY) const {
208 AutoMutex _l(mLock);
209
210 *outX = mLocked.pointerX;
211 *outY = mLocked.pointerY;
212}
213
Jeff Brown538881e2011-05-25 18:23:38 -0700214void PointerController::fade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800215 AutoMutex _l(mLock);
216
Jeff Brown538881e2011-05-25 18:23:38 -0700217 // Remove the inactivity timeout, since we are fading now.
218 removeInactivityTimeoutLocked();
219
220 // Start fading.
221 if (transition == TRANSITION_IMMEDIATE) {
222 mLocked.pointerFadeDirection = 0;
223 mLocked.pointerAlpha = 0.0f;
224 updatePointerLocked();
225 } else {
226 mLocked.pointerFadeDirection = -1;
227 startAnimationLocked();
228 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800229}
230
Jeff Brown538881e2011-05-25 18:23:38 -0700231void PointerController::unfade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800232 AutoMutex _l(mLock);
233
Jeff Brown2352b972011-04-12 22:39:53 -0700234 // Always reset the inactivity timer.
235 resetInactivityTimeoutLocked();
236
Jeff Brown538881e2011-05-25 18:23:38 -0700237 // Start unfading.
238 if (transition == TRANSITION_IMMEDIATE) {
239 mLocked.pointerFadeDirection = 0;
Jeff Brown2352b972011-04-12 22:39:53 -0700240 mLocked.pointerAlpha = 1.0f;
241 updatePointerLocked();
Jeff Brown538881e2011-05-25 18:23:38 -0700242 } else {
243 mLocked.pointerFadeDirection = 1;
244 startAnimationLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800245 }
246}
247
Jeff Brown2352b972011-04-12 22:39:53 -0700248void PointerController::setPresentation(Presentation presentation) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800249 AutoMutex _l(mLock);
250
Jun Mukai1db53972015-09-11 18:08:31 -0700251 if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700252 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
253 &mLocked.animationResources);
Jun Mukai1db53972015-09-11 18:08:31 -0700254 }
255
Jeff Brown2352b972011-04-12 22:39:53 -0700256 if (mLocked.presentation != presentation) {
257 mLocked.presentation = presentation;
258 mLocked.presentationChanged = true;
259
260 if (presentation != PRESENTATION_SPOT) {
261 fadeOutAndReleaseAllSpotsLocked();
262 }
263
264 updatePointerLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800265 }
266}
267
Jeff Browncb5ffcf2011-06-06 20:03:18 -0700268void PointerController::setSpots(const PointerCoords* spotCoords,
269 const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
Jeff Brown2352b972011-04-12 22:39:53 -0700270#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000271 ALOGD("setSpots: idBits=%08x", spotIdBits.value);
Jeff Brown2352b972011-04-12 22:39:53 -0700272 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
273 uint32_t id = idBits.firstMarkedBit();
274 idBits.clearBit(id);
275 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
Steve Block5baa3a62011-12-20 16:23:08 +0000276 ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id,
Jeff Brown2352b972011-04-12 22:39:53 -0700277 c.getAxisValue(AMOTION_EVENT_AXIS_X),
278 c.getAxisValue(AMOTION_EVENT_AXIS_Y),
279 c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
280 }
281#endif
282
283 AutoMutex _l(mLock);
284
285 mSpriteController->openTransaction();
286
287 // Add or move spots for fingers that are down.
288 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700289 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown2352b972011-04-12 22:39:53 -0700290 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
291 const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
292 ? mResources.spotTouch : mResources.spotHover;
293 float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
294 float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
295
296 Spot* spot = getSpotLocked(id);
297 if (!spot) {
298 spot = createAndAddSpotLocked(id);
299 }
300
301 spot->updateSprite(&icon, x, y);
302 }
303
304 // Remove spots for fingers that went up.
305 for (size_t i = 0; i < mLocked.spots.size(); i++) {
306 Spot* spot = mLocked.spots.itemAt(i);
307 if (spot->id != Spot::INVALID_ID
308 && !spotIdBits.hasBit(spot->id)) {
309 fadeOutAndReleaseSpotLocked(spot);
310 }
311 }
312
313 mSpriteController->closeTransaction();
314}
315
316void PointerController::clearSpots() {
317#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000318 ALOGD("clearSpots");
Jeff Brown2352b972011-04-12 22:39:53 -0700319#endif
320
321 AutoMutex _l(mLock);
322
323 fadeOutAndReleaseAllSpotsLocked();
324}
325
326void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
327 AutoMutex _l(mLock);
328
329 if (mLocked.inactivityTimeout != inactivityTimeout) {
330 mLocked.inactivityTimeout = inactivityTimeout;
331 resetInactivityTimeoutLocked();
332 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800333}
334
Jun Mukai19a56012015-11-24 11:25:52 -0800335void PointerController::reloadPointerResources() {
336 AutoMutex _l(mLock);
337
338 loadResources();
339
340 if (mLocked.presentation == PRESENTATION_POINTER) {
341 mLocked.additionalMouseResources.clear();
342 mLocked.animationResources.clear();
343 mPolicy->loadPointerIcon(&mLocked.pointerIcon);
344 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
345 &mLocked.animationResources);
346 }
347
348 mLocked.presentationChanged = true;
349 updatePointerLocked();
350}
351
Jeff Brownd728bf52012-09-08 18:05:28 -0700352void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800353 AutoMutex _l(mLock);
354
Jeff Brownd728bf52012-09-08 18:05:28 -0700355 // Adjust to use the display's unrotated coordinate frame.
356 if (orientation == DISPLAY_ORIENTATION_90
357 || orientation == DISPLAY_ORIENTATION_270) {
358 int32_t temp = height;
359 height = width;
360 width = temp;
361 }
362
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800363 if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
364 mLocked.displayWidth = width;
365 mLocked.displayHeight = height;
366
367 float minX, minY, maxX, maxY;
368 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
369 mLocked.pointerX = (minX + maxX) * 0.5f;
370 mLocked.pointerY = (minY + maxY) * 0.5f;
371 } else {
372 mLocked.pointerX = 0;
373 mLocked.pointerY = 0;
374 }
375
Jeff Brown2352b972011-04-12 22:39:53 -0700376 fadeOutAndReleaseAllSpotsLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800377 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800378
379 if (mLocked.displayOrientation != orientation) {
Jeff Brownd41cff22011-03-03 02:09:54 -0800380 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
381 // This creates an invariant frame of reference that we can easily rotate when
382 // taking into account that the pointer may be located at fractional pixel offsets.
383 float x = mLocked.pointerX + 0.5f;
384 float y = mLocked.pointerY + 0.5f;
385 float temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800386
Jeff Brownd41cff22011-03-03 02:09:54 -0800387 // Undo the previous rotation.
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800388 switch (mLocked.displayOrientation) {
389 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800390 temp = x;
391 x = mLocked.displayWidth - y;
392 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800393 break;
394 case DISPLAY_ORIENTATION_180:
Jeff Brownd41cff22011-03-03 02:09:54 -0800395 x = mLocked.displayWidth - x;
396 y = mLocked.displayHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800397 break;
398 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800399 temp = x;
400 x = y;
401 y = mLocked.displayHeight - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800402 break;
403 }
404
Jeff Brownd41cff22011-03-03 02:09:54 -0800405 // Perform the new rotation.
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800406 switch (orientation) {
407 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800408 temp = x;
409 x = y;
Jeff Brown5541de92011-04-11 11:54:25 -0700410 y = mLocked.displayWidth - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800411 break;
412 case DISPLAY_ORIENTATION_180:
Jeff Brownd41cff22011-03-03 02:09:54 -0800413 x = mLocked.displayWidth - x;
414 y = mLocked.displayHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800415 break;
416 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800417 temp = x;
418 x = mLocked.displayHeight - y;
419 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800420 break;
421 }
422
Jeff Brownd41cff22011-03-03 02:09:54 -0800423 // Apply offsets to convert from the pixel center to the pixel top-left corner position
424 // and save the results.
425 mLocked.pointerX = x - 0.5f;
426 mLocked.pointerY = y - 0.5f;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800427 mLocked.displayOrientation = orientation;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800428 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700429
430 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800431}
432
Jun Mukai808196f2015-10-28 16:46:44 -0700433void PointerController::updatePointerShape(int32_t iconId) {
Jun Mukai1db53972015-09-11 18:08:31 -0700434 AutoMutex _l(mLock);
435 if (mLocked.requestedPointerShape != iconId) {
436 mLocked.requestedPointerShape = iconId;
437 mLocked.presentationChanged = true;
438 updatePointerLocked();
439 }
440}
441
Jeff Brown05dc66a2011-03-02 14:41:58 -0800442void PointerController::handleMessage(const Message& message) {
443 switch (message.what) {
Jeff Brown2352b972011-04-12 22:39:53 -0700444 case MSG_INACTIVITY_TIMEOUT:
445 doInactivityTimeout();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800446 break;
447 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800448}
449
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700450int PointerController::handleEvent(int /* fd */, int events, void* /* data */) {
451 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
452 ALOGE("Display event receiver pipe was closed or an error occurred. "
453 "events=0x%x", events);
454 return 0; // remove the callback
455 }
456
457 if (!(events & Looper::EVENT_INPUT)) {
458 ALOGW("Received spurious callback for unhandled poll event. "
459 "events=0x%x", events);
460 return 1; // keep the callback
461 }
462
463 bool gotVsync = false;
464 ssize_t n;
465 nsecs_t timestamp;
466 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
467 while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
468 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
469 if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
470 timestamp = buf[i].header.timestamp;
471 gotVsync = true;
472 }
473 }
474 }
475 if (gotVsync) {
476 doAnimate(timestamp);
477 }
478 return 1; // keep the callback
479}
480
481void PointerController::doAnimate(nsecs_t timestamp) {
Jeff Brown2352b972011-04-12 22:39:53 -0700482 AutoMutex _l(mLock);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800483
Jeff Brown2352b972011-04-12 22:39:53 -0700484 mLocked.animationPending = false;
Jun Mukai808196f2015-10-28 16:46:44 -0700485
486 bool keepFading = doFadingAnimationLocked(timestamp);
487 bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
488 if (keepFading || keepBitmapFlipping) {
489 startAnimationLocked();
490 }
491}
492
493bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
494 bool keepAnimating = false;
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700495 nsecs_t frameDelay = timestamp - mLocked.animationTime;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800496
Jeff Brown2352b972011-04-12 22:39:53 -0700497 // Animate pointer fade.
Jeff Brown538881e2011-05-25 18:23:38 -0700498 if (mLocked.pointerFadeDirection < 0) {
Jeff Brown2352b972011-04-12 22:39:53 -0700499 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
Jeff Brown538881e2011-05-25 18:23:38 -0700500 if (mLocked.pointerAlpha <= 0.0f) {
501 mLocked.pointerAlpha = 0.0f;
502 mLocked.pointerFadeDirection = 0;
503 } else {
504 keepAnimating = true;
505 }
506 updatePointerLocked();
507 } else if (mLocked.pointerFadeDirection > 0) {
508 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
509 if (mLocked.pointerAlpha >= 1.0f) {
510 mLocked.pointerAlpha = 1.0f;
511 mLocked.pointerFadeDirection = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800512 } else {
Jeff Brown2352b972011-04-12 22:39:53 -0700513 keepAnimating = true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800514 }
Jeff Brown2352b972011-04-12 22:39:53 -0700515 updatePointerLocked();
516 }
517
518 // Animate spots that are fading out and being removed.
519 for (size_t i = 0; i < mLocked.spots.size(); i++) {
520 Spot* spot = mLocked.spots.itemAt(i);
521 if (spot->id == Spot::INVALID_ID) {
522 spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
523 if (spot->alpha <= 0) {
524 mLocked.spots.removeAt(i--);
525 releaseSpotLocked(spot);
526 } else {
527 spot->sprite->setAlpha(spot->alpha);
528 keepAnimating = true;
529 }
530 }
531 }
Jun Mukai808196f2015-10-28 16:46:44 -0700532 return keepAnimating;
533}
Jeff Brown2352b972011-04-12 22:39:53 -0700534
Jun Mukai808196f2015-10-28 16:46:44 -0700535bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
536 std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
537 mLocked.requestedPointerShape);
538 if (iter == mLocked.animationResources.end()) {
539 return false;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800540 }
Jun Mukai808196f2015-10-28 16:46:44 -0700541
542 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
543 mSpriteController->openTransaction();
544
545 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
546 mLocked.animationFrameIndex += incr;
547 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
548 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
549 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
550 }
551 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
552
553 mSpriteController->closeTransaction();
554 }
555
556 // Keep animating.
557 return true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800558}
559
Jeff Brown2352b972011-04-12 22:39:53 -0700560void PointerController::doInactivityTimeout() {
Jeff Brown538881e2011-05-25 18:23:38 -0700561 fade(TRANSITION_GRADUAL);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800562}
563
Jeff Brown2352b972011-04-12 22:39:53 -0700564void PointerController::startAnimationLocked() {
565 if (!mLocked.animationPending) {
566 mLocked.animationPending = true;
567 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700568 mDisplayEventReceiver.requestNextVsync();
Jeff Brown2352b972011-04-12 22:39:53 -0700569 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800570}
571
Jeff Brown2352b972011-04-12 22:39:53 -0700572void PointerController::resetInactivityTimeoutLocked() {
573 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
574
575 nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
576 ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
577 mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
578}
579
Jeff Brown538881e2011-05-25 18:23:38 -0700580void PointerController::removeInactivityTimeoutLocked() {
Jeff Brown2352b972011-04-12 22:39:53 -0700581 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
Jeff Brown2352b972011-04-12 22:39:53 -0700582}
583
584void PointerController::updatePointerLocked() {
585 mSpriteController->openTransaction();
586
587 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
588 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
589
590 if (mLocked.pointerAlpha > 0) {
591 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
592 mLocked.pointerSprite->setVisible(true);
593 } else {
594 mLocked.pointerSprite->setVisible(false);
595 }
596
597 if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
Jun Mukai1db53972015-09-11 18:08:31 -0700598 if (mLocked.presentation == PRESENTATION_POINTER) {
Jun Mukai5ec74202015-10-07 16:58:09 +0900599 if (mLocked.requestedPointerShape == mPolicy->getDefaultPointerIconId()) {
Jun Mukai1db53972015-09-11 18:08:31 -0700600 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
601 } else {
Jun Mukai808196f2015-10-28 16:46:44 -0700602 std::map<int32_t, SpriteIcon>::const_iterator iter =
Jun Mukai1db53972015-09-11 18:08:31 -0700603 mLocked.additionalMouseResources.find(mLocked.requestedPointerShape);
604 if (iter != mLocked.additionalMouseResources.end()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700605 std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
606 mLocked.animationResources.find(mLocked.requestedPointerShape);
607 if (anim_iter != mLocked.animationResources.end()) {
608 mLocked.animationFrameIndex = 0;
609 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
610 startAnimationLocked();
611 }
Jun Mukai1db53972015-09-11 18:08:31 -0700612 mLocked.pointerSprite->setIcon(iter->second);
613 } else {
614 ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerShape);
615 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
616 }
617 }
618 } else {
619 mLocked.pointerSprite->setIcon(mResources.spotAnchor);
620 }
Jeff Brown2352b972011-04-12 22:39:53 -0700621 mLocked.pointerIconChanged = false;
622 mLocked.presentationChanged = false;
623 }
624
625 mSpriteController->closeTransaction();
626}
627
628PointerController::Spot* PointerController::getSpotLocked(uint32_t id) {
629 for (size_t i = 0; i < mLocked.spots.size(); i++) {
630 Spot* spot = mLocked.spots.itemAt(i);
631 if (spot->id == id) {
632 return spot;
633 }
634 }
635 return NULL;
636}
637
638PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) {
639 // Remove spots until we have fewer than MAX_SPOTS remaining.
640 while (mLocked.spots.size() >= MAX_SPOTS) {
641 Spot* spot = removeFirstFadingSpotLocked();
642 if (!spot) {
643 spot = mLocked.spots.itemAt(0);
644 mLocked.spots.removeAt(0);
645 }
646 releaseSpotLocked(spot);
647 }
648
649 // Obtain a sprite from the recycled pool.
650 sp<Sprite> sprite;
651 if (! mLocked.recycledSprites.isEmpty()) {
652 sprite = mLocked.recycledSprites.top();
653 mLocked.recycledSprites.pop();
654 } else {
655 sprite = mSpriteController->createSprite();
656 }
657
658 // Return the new spot.
659 Spot* spot = new Spot(id, sprite);
660 mLocked.spots.push(spot);
661 return spot;
662}
663
664PointerController::Spot* PointerController::removeFirstFadingSpotLocked() {
665 for (size_t i = 0; i < mLocked.spots.size(); i++) {
666 Spot* spot = mLocked.spots.itemAt(i);
667 if (spot->id == Spot::INVALID_ID) {
668 mLocked.spots.removeAt(i);
669 return spot;
670 }
671 }
672 return NULL;
673}
674
675void PointerController::releaseSpotLocked(Spot* spot) {
676 spot->sprite->clearIcon();
677
678 if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
679 mLocked.recycledSprites.push(spot->sprite);
680 }
681
682 delete spot;
683}
684
685void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
686 if (spot->id != Spot::INVALID_ID) {
687 spot->id = Spot::INVALID_ID;
688 startAnimationLocked();
689 }
690}
691
692void PointerController::fadeOutAndReleaseAllSpotsLocked() {
693 for (size_t i = 0; i < mLocked.spots.size(); i++) {
694 Spot* spot = mLocked.spots.itemAt(i);
695 fadeOutAndReleaseSpotLocked(spot);
696 }
697}
698
699void PointerController::loadResources() {
700 mPolicy->loadPointerResources(&mResources);
701}
702
703
704// --- PointerController::Spot ---
705
706void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) {
707 sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
708 sprite->setAlpha(alpha);
709 sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
710 sprite->setPosition(x, y);
711
712 this->x = x;
713 this->y = y;
714
715 if (icon != lastIcon) {
716 lastIcon = icon;
717 if (icon) {
718 sprite->setIcon(*icon);
719 sprite->setVisible(true);
720 } else {
721 sprite->setVisible(false);
722 }
723 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800724}
725
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800726} // namespace android