1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "PointerController"
18 //#define LOG_NDEBUG 0
19
20 // Log debug messages about pointer updates
21 #define DEBUG_POINTER_UPDATES 0
22
23 #include "PointerController.h"
24
25 #include <log/log.h>
26
27 namespace android {
28
29 // --- WeakLooperCallback ---
30
31 class WeakLooperCallback: public LooperCallback {
32 protected:
~WeakLooperCallback()33 virtual ~WeakLooperCallback() { }
34
35 public:
WeakLooperCallback(const wp<LooperCallback> & callback)36 explicit WeakLooperCallback(const wp<LooperCallback>& callback) :
37 mCallback(callback) {
38 }
39
handleEvent(int fd,int events,void * data)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
48 private:
49 wp<LooperCallback> mCallback;
50 };
51
52 // --- PointerController ---
53
54 // Time to wait before starting the fade when the pointer is inactive.
55 static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
56 static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
57
58 // Time to spend fading out the spot completely.
59 static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
60
61 // Time to spend fading out the pointer completely.
62 static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
63
64 // The number of events to be read at once for DisplayEventReceiver.
65 static const int EVENT_BUFFER_SIZE = 100;
66
67 // --- PointerController ---
68
PointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController)69 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
70 const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
71 mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
72 mHandler = new WeakMessageHandler(this);
73 mCallback = new WeakLooperCallback(this);
74
75 if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
76 mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
77 Looper::EVENT_INPUT, mCallback, nullptr);
78 } else {
79 ALOGE("Failed to initialize DisplayEventReceiver.");
80 }
81
82 AutoMutex _l(mLock);
83
84 mLocked.animationPending = false;
85
86 mLocked.presentation = PRESENTATION_POINTER;
87 mLocked.presentationChanged = false;
88
89 mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
90
91 mLocked.pointerFadeDirection = 0;
92 mLocked.pointerX = 0;
93 mLocked.pointerY = 0;
94 mLocked.pointerAlpha = 0.0f; // pointer is initially faded
95 mLocked.pointerSprite = mSpriteController->createSprite();
96 mLocked.pointerIconChanged = false;
97 mLocked.requestedPointerType = mPolicy->getDefaultPointerIconId();
98
99 mLocked.animationFrameIndex = 0;
100 mLocked.lastFrameUpdatedTime = 0;
101
102 mLocked.buttonState = 0;
103 }
104
~PointerController()105 PointerController::~PointerController() {
106 mLooper->removeMessages(mHandler);
107
108 AutoMutex _l(mLock);
109
110 mLocked.pointerSprite.clear();
111
112 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 }
118 }
119 mLocked.spotsByDisplay.clear();
120 mLocked.recycledSprites.clear();
121 }
122
getBounds(float * outMinX,float * outMinY,float * outMaxX,float * outMaxY) const123 bool 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
getBoundsLocked(float * outMinX,float * outMinY,float * outMaxX,float * outMaxY) const130 bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
131 float* outMaxX, float* outMaxY) const {
132
133 if (!mLocked.viewport.isValid()) {
134 return false;
135 }
136
137 *outMinX = mLocked.viewport.logicalLeft;
138 *outMinY = mLocked.viewport.logicalTop;
139 *outMaxX = mLocked.viewport.logicalRight - 1;
140 *outMaxY = mLocked.viewport.logicalBottom - 1;
141 return true;
142 }
143
move(float deltaX,float deltaY)144 void PointerController::move(float deltaX, float deltaY) {
145 #if DEBUG_POINTER_UPDATES
146 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
147 #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
setButtonState(int32_t buttonState)157 void PointerController::setButtonState(int32_t buttonState) {
158 #if DEBUG_POINTER_UPDATES
159 ALOGD("Set button state 0x%08x", buttonState);
160 #endif
161 AutoMutex _l(mLock);
162
163 if (mLocked.buttonState != buttonState) {
164 mLocked.buttonState = buttonState;
165 }
166 }
167
getButtonState() const168 int32_t PointerController::getButtonState() const {
169 AutoMutex _l(mLock);
170
171 return mLocked.buttonState;
172 }
173
setPosition(float x,float y)174 void PointerController::setPosition(float x, float y) {
175 #if DEBUG_POINTER_UPDATES
176 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
177 #endif
178 AutoMutex _l(mLock);
179
180 setPositionLocked(x, y);
181 }
182
setPositionLocked(float x,float y)183 void 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 }
200 updatePointerLocked();
201 }
202 }
203
getPosition(float * outX,float * outY) const204 void PointerController::getPosition(float* outX, float* outY) const {
205 AutoMutex _l(mLock);
206
207 *outX = mLocked.pointerX;
208 *outY = mLocked.pointerY;
209 }
210
getDisplayId() const211 int32_t PointerController::getDisplayId() const {
212 AutoMutex _l(mLock);
213
214 return mLocked.viewport.displayId;
215 }
216
fade(Transition transition)217 void PointerController::fade(Transition transition) {
218 AutoMutex _l(mLock);
219
220 // 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 }
232 }
233
unfade(Transition transition)234 void PointerController::unfade(Transition transition) {
235 AutoMutex _l(mLock);
236
237 // Always reset the inactivity timer.
238 resetInactivityTimeoutLocked();
239
240 // Start unfading.
241 if (transition == TRANSITION_IMMEDIATE) {
242 mLocked.pointerFadeDirection = 0;
243 mLocked.pointerAlpha = 1.0f;
244 updatePointerLocked();
245 } else {
246 mLocked.pointerFadeDirection = 1;
247 startAnimationLocked();
248 }
249 }
250
setPresentation(Presentation presentation)251 void PointerController::setPresentation(Presentation presentation) {
252 AutoMutex _l(mLock);
253
254 if (mLocked.presentation == presentation) {
255 return;
256 }
257
258 mLocked.presentation = presentation;
259 mLocked.presentationChanged = true;
260
261 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);
270 }
271 fadeOutAndReleaseAllSpotsLocked();
272 updatePointerLocked();
273 }
274 }
275
setSpots(const PointerCoords * spotCoords,const uint32_t * spotIdToIndex,BitSet32 spotIdBits,int32_t displayId)276 void PointerController::setSpots(const PointerCoords* spotCoords,
277 const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId) {
278 #if DEBUG_POINTER_UPDATES
279 ALOGD("setSpots: idBits=%08x", spotIdBits.value);
280 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
281 uint32_t id = idBits.firstMarkedBit();
282 idBits.clearBit(id);
283 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
284 ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id,
285 c.getAxisValue(AMOTION_EVENT_AXIS_X),
286 c.getAxisValue(AMOTION_EVENT_AXIS_Y),
287 c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
288 displayId);
289 }
290 #endif
291
292 AutoMutex _l(mLock);
293 if (!mLocked.viewport.isValid()) {
294 return;
295 }
296
297 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
304 mSpriteController->openTransaction();
305
306 // Add or move spots for fingers that are down.
307 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
308 uint32_t id = idBits.clearFirstMarkedBit();
309 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
315 Spot* spot = getSpot(id, newSpots);
316 if (!spot) {
317 spot = createAndAddSpotLocked(id, newSpots);
318 }
319
320 spot->updateSprite(&icon, x, y, displayId);
321 }
322
323 // Remove spots for fingers that went up.
324 for (size_t i = 0; i < newSpots.size(); i++) {
325 Spot* spot = newSpots[i];
326 if (spot->id != Spot::INVALID_ID
327 && !spotIdBits.hasBit(spot->id)) {
328 fadeOutAndReleaseSpotLocked(spot);
329 }
330 }
331
332 mSpriteController->closeTransaction();
333 mLocked.spotsByDisplay[displayId] = newSpots;
334 }
335
clearSpots()336 void PointerController::clearSpots() {
337 #if DEBUG_POINTER_UPDATES
338 ALOGD("clearSpots");
339 #endif
340
341 AutoMutex _l(mLock);
342 if (!mLocked.viewport.isValid()) {
343 return;
344 }
345
346 fadeOutAndReleaseAllSpotsLocked();
347 }
348
setInactivityTimeout(InactivityTimeout inactivityTimeout)349 void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
350 AutoMutex _l(mLock);
351
352 if (mLocked.inactivityTimeout != inactivityTimeout) {
353 mLocked.inactivityTimeout = inactivityTimeout;
354 resetInactivityTimeoutLocked();
355 }
356 }
357
reloadPointerResources()358 void PointerController::reloadPointerResources() {
359 AutoMutex _l(mLock);
360
361 loadResourcesLocked();
362 updatePointerLocked();
363 }
364
365 /**
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 */
getNonRotatedSize(const DisplayViewport & viewport,int32_t & width,int32_t & height)369 static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
370 width = viewport.deviceWidth;
371 height = viewport.deviceHeight;
372
373 if (viewport.orientation == DISPLAY_ORIENTATION_90
374 || viewport.orientation == DISPLAY_ORIENTATION_270) {
375 std::swap(width, height);
376 }
377 }
378
setDisplayViewport(const DisplayViewport & viewport)379 void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
380 AutoMutex _l(mLock);
381 if (viewport == mLocked.viewport) {
382 return;
383 }
384
385 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) {
397
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;
402 // Reload icon resources for density may be changed.
403 loadResourcesLocked();
404 } else {
405 mLocked.pointerX = 0;
406 mLocked.pointerY = 0;
407 }
408
409 fadeOutAndReleaseAllSpotsLocked();
410 } else if (oldViewport.orientation != viewport.orientation) {
411 // 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;
417
418 // Undo the previous rotation.
419 switch (oldViewport.orientation) {
420 case DISPLAY_ORIENTATION_90:
421 temp = x;
422 x = oldViewport.deviceHeight - y;
423 y = temp;
424 break;
425 case DISPLAY_ORIENTATION_180:
426 x = oldViewport.deviceWidth - x;
427 y = oldViewport.deviceHeight - y;
428 break;
429 case DISPLAY_ORIENTATION_270:
430 temp = x;
431 x = y;
432 y = oldViewport.deviceWidth - temp;
433 break;
434 }
435
436 // Perform the new rotation.
437 switch (viewport.orientation) {
438 case DISPLAY_ORIENTATION_90:
439 temp = x;
440 x = y;
441 y = viewport.deviceHeight - temp;
442 break;
443 case DISPLAY_ORIENTATION_180:
444 x = viewport.deviceWidth - x;
445 y = viewport.deviceHeight - y;
446 break;
447 case DISPLAY_ORIENTATION_270:
448 temp = x;
449 x = viewport.deviceWidth - y;
450 y = temp;
451 break;
452 }
453
454 // 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;
458 }
459
460 updatePointerLocked();
461 }
462
updatePointerIcon(int32_t iconId)463 void PointerController::updatePointerIcon(int32_t iconId) {
464 AutoMutex _l(mLock);
465 if (mLocked.requestedPointerType != iconId) {
466 mLocked.requestedPointerType = iconId;
467 mLocked.presentationChanged = true;
468 updatePointerLocked();
469 }
470 }
471
setCustomPointerIcon(const SpriteIcon & icon)472 void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
473 AutoMutex _l(mLock);
474
475 const int32_t iconId = mPolicy->getCustomPointerIconId();
476 mLocked.additionalMouseResources[iconId] = icon;
477 mLocked.requestedPointerType = iconId;
478 mLocked.presentationChanged = true;
479
480 updatePointerLocked();
481 }
482
handleMessage(const Message & message)483 void PointerController::handleMessage(const Message& message) {
484 switch (message.what) {
485 case MSG_INACTIVITY_TIMEOUT:
486 doInactivityTimeout();
487 break;
488 }
489 }
490
handleEvent(int,int events,void *)491 int 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
doAnimate(nsecs_t timestamp)522 void PointerController::doAnimate(nsecs_t timestamp) {
523 AutoMutex _l(mLock);
524
525 mLocked.animationPending = false;
526
527 bool keepFading = doFadingAnimationLocked(timestamp);
528 bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
529 if (keepFading || keepBitmapFlipping) {
530 startAnimationLocked();
531 }
532 }
533
doFadingAnimationLocked(nsecs_t timestamp)534 bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
535 bool keepAnimating = false;
536 nsecs_t frameDelay = timestamp - mLocked.animationTime;
537
538 // Animate pointer fade.
539 if (mLocked.pointerFadeDirection < 0) {
540 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
541 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;
553 } else {
554 keepAnimating = true;
555 }
556 updatePointerLocked();
557 }
558
559 // Animate spots that are fading out and being removed.
560 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 }
576 }
577 ++i;
578 }
579
580 if (spots.size() == 0) {
581 it = mLocked.spotsByDisplay.erase(it);
582 } else {
583 ++it;
584 }
585 }
586
587 return keepAnimating;
588 }
589
doBitmapAnimationLocked(nsecs_t timestamp)590 bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
591 std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
592 mLocked.requestedPointerType);
593 if (iter == mLocked.animationResources.end()) {
594 return false;
595 }
596
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;
613 }
614
doInactivityTimeout()615 void PointerController::doInactivityTimeout() {
616 fade(TRANSITION_GRADUAL);
617 }
618
startAnimationLocked()619 void PointerController::startAnimationLocked() {
620 if (!mLocked.animationPending) {
621 mLocked.animationPending = true;
622 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
623 mDisplayEventReceiver.requestNextVsync();
624 }
625 }
626
resetInactivityTimeoutLocked()627 void 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
removeInactivityTimeoutLocked()635 void PointerController::removeInactivityTimeoutLocked() {
636 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
637 }
638
updatePointerLocked()639 void PointerController::updatePointerLocked() REQUIRES(mLock) {
640 if (!mLocked.viewport.isValid()) {
641 return;
642 }
643
644 mSpriteController->openTransaction();
645
646 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
647 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
648 mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
649
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) {
658 if (mLocked.presentation == PRESENTATION_POINTER) {
659 if (mLocked.requestedPointerType == mPolicy->getDefaultPointerIconId()) {
660 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
661 } else {
662 std::map<int32_t, SpriteIcon>::const_iterator iter =
663 mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
664 if (iter != mLocked.additionalMouseResources.end()) {
665 std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
666 mLocked.animationResources.find(mLocked.requestedPointerType);
667 if (anim_iter != mLocked.animationResources.end()) {
668 mLocked.animationFrameIndex = 0;
669 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
670 startAnimationLocked();
671 }
672 mLocked.pointerSprite->setIcon(iter->second);
673 } else {
674 ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
675 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
676 }
677 }
678 } else {
679 mLocked.pointerSprite->setIcon(mResources.spotAnchor);
680 }
681 mLocked.pointerIconChanged = false;
682 mLocked.presentationChanged = false;
683 }
684
685 mSpriteController->closeTransaction();
686 }
687
getSpot(uint32_t id,const std::vector<Spot * > & spots)688 PointerController::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];
691 if (spot->id == id) {
692 return spot;
693 }
694 }
695
696 return nullptr;
697 }
698
createAndAddSpotLocked(uint32_t id,std::vector<Spot * > & spots)699 PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id,
700 std::vector<Spot*>& spots) {
701 // Remove spots until we have fewer than MAX_SPOTS remaining.
702 while (spots.size() >= MAX_SPOTS) {
703 Spot* spot = removeFirstFadingSpotLocked(spots);
704 if (!spot) {
705 spot = spots[0];
706 spots.erase(spots.begin());
707 }
708 releaseSpotLocked(spot);
709 }
710
711 // Obtain a sprite from the recycled pool.
712 sp<Sprite> sprite;
713 if (! mLocked.recycledSprites.empty()) {
714 sprite = mLocked.recycledSprites.back();
715 mLocked.recycledSprites.pop_back();
716 } else {
717 sprite = mSpriteController->createSprite();
718 }
719
720 // Return the new spot.
721 Spot* spot = new Spot(id, sprite);
722 spots.push_back(spot);
723 return spot;
724 }
725
removeFirstFadingSpotLocked(std::vector<Spot * > & spots)726 PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) {
727 for (size_t i = 0; i < spots.size(); i++) {
728 Spot* spot = spots[i];
729 if (spot->id == Spot::INVALID_ID) {
730 spots.erase(spots.begin() + i);
731 return spot;
732 }
733 }
734 return NULL;
735 }
736
releaseSpotLocked(Spot * spot)737 void PointerController::releaseSpotLocked(Spot* spot) {
738 spot->sprite->clearIcon();
739
740 if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
741 mLocked.recycledSprites.push_back(spot->sprite);
742 }
743
744 delete spot;
745 }
746
fadeOutAndReleaseSpotLocked(Spot * spot)747 void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
748 if (spot->id != Spot::INVALID_ID) {
749 spot->id = Spot::INVALID_ID;
750 startAnimationLocked();
751 }
752 }
753
fadeOutAndReleaseAllSpotsLocked()754 void PointerController::fadeOutAndReleaseAllSpotsLocked() {
755 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 }
762 }
763 }
764
loadResourcesLocked()765 void PointerController::loadResourcesLocked() REQUIRES(mLock) {
766 if (!mLocked.viewport.isValid()) {
767 return;
768 }
769
770 mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
771 mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
772
773 mLocked.additionalMouseResources.clear();
774 mLocked.animationResources.clear();
775 if (mLocked.presentation == PRESENTATION_POINTER) {
776 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
777 &mLocked.animationResources, mLocked.viewport.displayId);
778 }
779
780 mLocked.pointerIconChanged = true;
781 }
782
783
784 // --- PointerController::Spot ---
785
updateSprite(const SpriteIcon * icon,float x,float y,int32_t displayId)786 void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y,
787 int32_t displayId) {
788 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);
792 sprite->setDisplayId(displayId);
793 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 }
805 }
806
807 } // namespace android
808