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 #include <memory>
28
29 namespace android {
30
31 // --- PointerController ---
32
33 // Time to wait before starting the fade when the pointer is inactive.
34 static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
35 static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
36
37 // Time to spend fading out the spot completely.
38 static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
39
40 // Time to spend fading out the pointer completely.
41 static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
42
43 // The number of events to be read at once for DisplayEventReceiver.
44 static const int EVENT_BUFFER_SIZE = 100;
45
create(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController)46 std::shared_ptr<PointerController> PointerController::create(
47 const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
48 const sp<SpriteController>& spriteController) {
49 std::shared_ptr<PointerController> controller = std::shared_ptr<PointerController>(
50 new PointerController(policy, looper, spriteController));
51
52 /*
53 * Now we need to hook up the constructed PointerController object to its callbacks.
54 *
55 * This must be executed after the constructor but before any other methods on PointerController
56 * in order to ensure that the fully constructed object is visible on the Looper thread, since
57 * that may be a different thread than where the PointerController is initially constructed.
58 *
59 * Unfortunately, this cannot be done as part of the constructor since we need to hand out
60 * weak_ptr's which themselves cannot be constructed until there's at least one shared_ptr.
61 */
62
63 controller->mHandler->pointerController = controller;
64 controller->mCallback->pointerController = controller;
65 if (controller->mDisplayEventReceiver.initCheck() == NO_ERROR) {
66 controller->mLooper->addFd(controller->mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
67 Looper::EVENT_INPUT, controller->mCallback, nullptr);
68 } else {
69 ALOGE("Failed to initialize DisplayEventReceiver.");
70 }
71 return controller;
72 }
73
PointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController)74 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
75 const sp<Looper>& looper,
76 const sp<SpriteController>& spriteController)
77 : mPolicy(policy),
78 mLooper(looper),
79 mSpriteController(spriteController),
80 mHandler(new MessageHandler()),
81 mCallback(new LooperCallback()) {
82 AutoMutex _l(mLock);
83
84 mLocked.animationPending = false;
85
86 mLocked.presentation = Presentation::POINTER;
87 mLocked.presentationChanged = false;
88
89 mLocked.inactivityTimeout = InactivityTimeout::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::MessageHandler::handleMessage(const Message& message) {
484 std::shared_ptr<PointerController> controller = pointerController.lock();
485
486 if (controller == nullptr) {
487 ALOGE("PointerController instance was released before processing message: what=%d",
488 message.what);
489 return;
490 }
491 switch (message.what) {
492 case MSG_INACTIVITY_TIMEOUT:
493 controller->doInactivityTimeout();
494 break;
495 }
496 }
497
handleEvent(int,int events,void *)498 int PointerController::LooperCallback::handleEvent(int /* fd */, int events, void* /* data */) {
499 std::shared_ptr<PointerController> controller = pointerController.lock();
500 if (controller == nullptr) {
501 ALOGW("PointerController instance was released with pending callbacks. events=0x%x",
502 events);
503 return 0; // Remove the callback, the PointerController is gone anyways
504 }
505 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
506 ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events);
507 return 0; // remove the callback
508 }
509
510 if (!(events & Looper::EVENT_INPUT)) {
511 ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events);
512 return 1; // keep the callback
513 }
514
515 bool gotVsync = false;
516 ssize_t n;
517 nsecs_t timestamp;
518 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
519 while ((n = controller->mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
520 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
521 if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
522 timestamp = buf[i].header.timestamp;
523 gotVsync = true;
524 }
525 }
526 }
527 if (gotVsync) {
528 controller->doAnimate(timestamp);
529 }
530 return 1; // keep the callback
531 }
532
doAnimate(nsecs_t timestamp)533 void PointerController::doAnimate(nsecs_t timestamp) {
534 AutoMutex _l(mLock);
535
536 mLocked.animationPending = false;
537
538 bool keepFading = doFadingAnimationLocked(timestamp);
539 bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
540 if (keepFading || keepBitmapFlipping) {
541 startAnimationLocked();
542 }
543 }
544
doFadingAnimationLocked(nsecs_t timestamp)545 bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
546 bool keepAnimating = false;
547 nsecs_t frameDelay = timestamp - mLocked.animationTime;
548
549 // Animate pointer fade.
550 if (mLocked.pointerFadeDirection < 0) {
551 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
552 if (mLocked.pointerAlpha <= 0.0f) {
553 mLocked.pointerAlpha = 0.0f;
554 mLocked.pointerFadeDirection = 0;
555 } else {
556 keepAnimating = true;
557 }
558 updatePointerLocked();
559 } else if (mLocked.pointerFadeDirection > 0) {
560 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
561 if (mLocked.pointerAlpha >= 1.0f) {
562 mLocked.pointerAlpha = 1.0f;
563 mLocked.pointerFadeDirection = 0;
564 } else {
565 keepAnimating = true;
566 }
567 updatePointerLocked();
568 }
569
570 // Animate spots that are fading out and being removed.
571 for(auto it = mLocked.spotsByDisplay.begin(); it != mLocked.spotsByDisplay.end();) {
572 std::vector<Spot*>& spots = it->second;
573 size_t numSpots = spots.size();
574 for (size_t i = 0; i < numSpots;) {
575 Spot* spot = spots[i];
576 if (spot->id == Spot::INVALID_ID) {
577 spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
578 if (spot->alpha <= 0) {
579 spots.erase(spots.begin() + i);
580 releaseSpotLocked(spot);
581 numSpots--;
582 continue;
583 } else {
584 spot->sprite->setAlpha(spot->alpha);
585 keepAnimating = true;
586 }
587 }
588 ++i;
589 }
590
591 if (spots.size() == 0) {
592 it = mLocked.spotsByDisplay.erase(it);
593 } else {
594 ++it;
595 }
596 }
597
598 return keepAnimating;
599 }
600
doBitmapAnimationLocked(nsecs_t timestamp)601 bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
602 std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
603 mLocked.requestedPointerType);
604 if (iter == mLocked.animationResources.end()) {
605 return false;
606 }
607
608 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
609 mSpriteController->openTransaction();
610
611 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
612 mLocked.animationFrameIndex += incr;
613 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
614 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
615 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
616 }
617 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
618
619 mSpriteController->closeTransaction();
620 }
621
622 // Keep animating.
623 return true;
624 }
625
doInactivityTimeout()626 void PointerController::doInactivityTimeout() {
627 fade(Transition::GRADUAL);
628 }
629
startAnimationLocked()630 void PointerController::startAnimationLocked() {
631 if (!mLocked.animationPending) {
632 mLocked.animationPending = true;
633 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
634 mDisplayEventReceiver.requestNextVsync();
635 }
636 }
637
resetInactivityTimeoutLocked()638 void PointerController::resetInactivityTimeoutLocked() {
639 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
640
641 nsecs_t timeout = mLocked.inactivityTimeout == InactivityTimeout::SHORT
642 ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT
643 : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
644 mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
645 }
646
removeInactivityTimeoutLocked()647 void PointerController::removeInactivityTimeoutLocked() {
648 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
649 }
650
updatePointerLocked()651 void PointerController::updatePointerLocked() REQUIRES(mLock) {
652 if (!mLocked.viewport.isValid()) {
653 return;
654 }
655
656 mSpriteController->openTransaction();
657
658 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
659 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
660 mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
661
662 if (mLocked.pointerAlpha > 0) {
663 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
664 mLocked.pointerSprite->setVisible(true);
665 } else {
666 mLocked.pointerSprite->setVisible(false);
667 }
668
669 if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
670 if (mLocked.presentation == Presentation::POINTER) {
671 if (mLocked.requestedPointerType == mPolicy->getDefaultPointerIconId()) {
672 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
673 } else {
674 std::map<int32_t, SpriteIcon>::const_iterator iter =
675 mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
676 if (iter != mLocked.additionalMouseResources.end()) {
677 std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
678 mLocked.animationResources.find(mLocked.requestedPointerType);
679 if (anim_iter != mLocked.animationResources.end()) {
680 mLocked.animationFrameIndex = 0;
681 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
682 startAnimationLocked();
683 }
684 mLocked.pointerSprite->setIcon(iter->second);
685 } else {
686 ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
687 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
688 }
689 }
690 } else {
691 mLocked.pointerSprite->setIcon(mResources.spotAnchor);
692 }
693 mLocked.pointerIconChanged = false;
694 mLocked.presentationChanged = false;
695 }
696
697 mSpriteController->closeTransaction();
698 }
699
getSpot(uint32_t id,const std::vector<Spot * > & spots)700 PointerController::Spot* PointerController::getSpot(uint32_t id, const std::vector<Spot*>& spots) {
701 for (size_t i = 0; i < spots.size(); i++) {
702 Spot* spot = spots[i];
703 if (spot->id == id) {
704 return spot;
705 }
706 }
707
708 return nullptr;
709 }
710
createAndAddSpotLocked(uint32_t id,std::vector<Spot * > & spots)711 PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id,
712 std::vector<Spot*>& spots) {
713 // Remove spots until we have fewer than MAX_SPOTS remaining.
714 while (spots.size() >= MAX_SPOTS) {
715 Spot* spot = removeFirstFadingSpotLocked(spots);
716 if (!spot) {
717 spot = spots[0];
718 spots.erase(spots.begin());
719 }
720 releaseSpotLocked(spot);
721 }
722
723 // Obtain a sprite from the recycled pool.
724 sp<Sprite> sprite;
725 if (! mLocked.recycledSprites.empty()) {
726 sprite = mLocked.recycledSprites.back();
727 mLocked.recycledSprites.pop_back();
728 } else {
729 sprite = mSpriteController->createSprite();
730 }
731
732 // Return the new spot.
733 Spot* spot = new Spot(id, sprite);
734 spots.push_back(spot);
735 return spot;
736 }
737
removeFirstFadingSpotLocked(std::vector<Spot * > & spots)738 PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) {
739 for (size_t i = 0; i < spots.size(); i++) {
740 Spot* spot = spots[i];
741 if (spot->id == Spot::INVALID_ID) {
742 spots.erase(spots.begin() + i);
743 return spot;
744 }
745 }
746 return nullptr;
747 }
748
releaseSpotLocked(Spot * spot)749 void PointerController::releaseSpotLocked(Spot* spot) {
750 spot->sprite->clearIcon();
751
752 if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
753 mLocked.recycledSprites.push_back(spot->sprite);
754 }
755
756 delete spot;
757 }
758
fadeOutAndReleaseSpotLocked(Spot * spot)759 void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
760 if (spot->id != Spot::INVALID_ID) {
761 spot->id = Spot::INVALID_ID;
762 startAnimationLocked();
763 }
764 }
765
fadeOutAndReleaseAllSpotsLocked()766 void PointerController::fadeOutAndReleaseAllSpotsLocked() {
767 for (auto& it : mLocked.spotsByDisplay) {
768 const std::vector<Spot*>& spots = it.second;
769 size_t numSpots = spots.size();
770 for (size_t i = 0; i < numSpots; i++) {
771 Spot* spot = spots[i];
772 fadeOutAndReleaseSpotLocked(spot);
773 }
774 }
775 }
776
loadResourcesLocked()777 void PointerController::loadResourcesLocked() REQUIRES(mLock) {
778 if (!mLocked.viewport.isValid()) {
779 return;
780 }
781
782 mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
783 mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
784
785 mLocked.additionalMouseResources.clear();
786 mLocked.animationResources.clear();
787 if (mLocked.presentation == Presentation::POINTER) {
788 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
789 &mLocked.animationResources, mLocked.viewport.displayId);
790 }
791
792 mLocked.pointerIconChanged = true;
793 }
794
795
796 // --- PointerController::Spot ---
797
updateSprite(const SpriteIcon * icon,float x,float y,int32_t displayId)798 void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y,
799 int32_t displayId) {
800 sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
801 sprite->setAlpha(alpha);
802 sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
803 sprite->setPosition(x, y);
804 sprite->setDisplayId(displayId);
805 this->x = x;
806 this->y = y;
807
808 if (icon != lastIcon) {
809 lastIcon = icon;
810 if (icon) {
811 sprite->setIcon(*icon);
812 sprite->setVisible(true);
813 } else {
814 sprite->setVisible(false);
815 }
816 }
817 }
818
819 } // namespace android
820