• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <SkBitmap.h>
28 #include <SkCanvas.h>
29 #include <SkColor.h>
30 #include <SkPaint.h>
31 #include <SkBlendMode.h>
32 
33 namespace android {
34 
35 // --- WeakLooperCallback ---
36 
37 class WeakLooperCallback: public LooperCallback {
38 protected:
~WeakLooperCallback()39     virtual ~WeakLooperCallback() { }
40 
41 public:
WeakLooperCallback(const wp<LooperCallback> & callback)42     explicit WeakLooperCallback(const wp<LooperCallback>& callback) :
43         mCallback(callback) {
44     }
45 
handleEvent(int fd,int events,void * data)46     virtual int handleEvent(int fd, int events, void* data) {
47         sp<LooperCallback> callback = mCallback.promote();
48         if (callback != NULL) {
49             return callback->handleEvent(fd, events, data);
50         }
51         return 0; // the client is gone, remove the callback
52     }
53 
54 private:
55     wp<LooperCallback> mCallback;
56 };
57 
58 // --- PointerController ---
59 
60 // Time to wait before starting the fade when the pointer is inactive.
61 static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
62 static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
63 
64 // Time to spend fading out the spot completely.
65 static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
66 
67 // Time to spend fading out the pointer completely.
68 static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
69 
70 // The number of events to be read at once for DisplayEventReceiver.
71 static const int EVENT_BUFFER_SIZE = 100;
72 
73 // --- PointerController ---
74 
PointerController(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController)75 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
76         const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
77         mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
78     mHandler = new WeakMessageHandler(this);
79     mCallback = new WeakLooperCallback(this);
80 
81     if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
82         mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
83                        Looper::EVENT_INPUT, mCallback, nullptr);
84     } else {
85         ALOGE("Failed to initialize DisplayEventReceiver.");
86     }
87 
88     AutoMutex _l(mLock);
89 
90     mLocked.animationPending = false;
91 
92     mLocked.presentation = PRESENTATION_POINTER;
93     mLocked.presentationChanged = false;
94 
95     mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
96 
97     mLocked.pointerFadeDirection = 0;
98     mLocked.pointerX = 0;
99     mLocked.pointerY = 0;
100     mLocked.pointerAlpha = 0.0f; // pointer is initially faded
101     mLocked.pointerSprite = mSpriteController->createSprite();
102     mLocked.pointerIconChanged = false;
103     mLocked.requestedPointerType = mPolicy->getDefaultPointerIconId();
104 
105     mLocked.animationFrameIndex = 0;
106     mLocked.lastFrameUpdatedTime = 0;
107 
108     mLocked.buttonState = 0;
109 }
110 
~PointerController()111 PointerController::~PointerController() {
112     mLooper->removeMessages(mHandler);
113 
114     AutoMutex _l(mLock);
115 
116     mLocked.pointerSprite.clear();
117 
118     for (auto& it : mLocked.spotsByDisplay) {
119         const std::vector<Spot*>& spots = it.second;
120         size_t numSpots = spots.size();
121         for (size_t i = 0; i < numSpots; i++) {
122             delete spots[i];
123         }
124     }
125     mLocked.spotsByDisplay.clear();
126     mLocked.recycledSprites.clear();
127 }
128 
getBounds(float * outMinX,float * outMinY,float * outMaxX,float * outMaxY) const129 bool PointerController::getBounds(float* outMinX, float* outMinY,
130         float* outMaxX, float* outMaxY) const {
131     AutoMutex _l(mLock);
132 
133     return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
134 }
135 
getBoundsLocked(float * outMinX,float * outMinY,float * outMaxX,float * outMaxY) const136 bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
137         float* outMaxX, float* outMaxY) const {
138 
139     if (!mLocked.viewport.isValid()) {
140         return false;
141     }
142 
143     *outMinX = mLocked.viewport.logicalLeft;
144     *outMinY = mLocked.viewport.logicalTop;
145     *outMaxX = mLocked.viewport.logicalRight - 1;
146     *outMaxY = mLocked.viewport.logicalBottom - 1;
147     return true;
148 }
149 
move(float deltaX,float deltaY)150 void PointerController::move(float deltaX, float deltaY) {
151 #if DEBUG_POINTER_UPDATES
152     ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
153 #endif
154     if (deltaX == 0.0f && deltaY == 0.0f) {
155         return;
156     }
157 
158     AutoMutex _l(mLock);
159 
160     setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
161 }
162 
setButtonState(int32_t buttonState)163 void PointerController::setButtonState(int32_t buttonState) {
164 #if DEBUG_POINTER_UPDATES
165     ALOGD("Set button state 0x%08x", buttonState);
166 #endif
167     AutoMutex _l(mLock);
168 
169     if (mLocked.buttonState != buttonState) {
170         mLocked.buttonState = buttonState;
171     }
172 }
173 
getButtonState() const174 int32_t PointerController::getButtonState() const {
175     AutoMutex _l(mLock);
176 
177     return mLocked.buttonState;
178 }
179 
setPosition(float x,float y)180 void PointerController::setPosition(float x, float y) {
181 #if DEBUG_POINTER_UPDATES
182     ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
183 #endif
184     AutoMutex _l(mLock);
185 
186     setPositionLocked(x, y);
187 }
188 
setPositionLocked(float x,float y)189 void PointerController::setPositionLocked(float x, float y) {
190     float minX, minY, maxX, maxY;
191     if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
192         if (x <= minX) {
193             mLocked.pointerX = minX;
194         } else if (x >= maxX) {
195             mLocked.pointerX = maxX;
196         } else {
197             mLocked.pointerX = x;
198         }
199         if (y <= minY) {
200             mLocked.pointerY = minY;
201         } else if (y >= maxY) {
202             mLocked.pointerY = maxY;
203         } else {
204             mLocked.pointerY = y;
205         }
206         updatePointerLocked();
207     }
208 }
209 
getPosition(float * outX,float * outY) const210 void PointerController::getPosition(float* outX, float* outY) const {
211     AutoMutex _l(mLock);
212 
213     *outX = mLocked.pointerX;
214     *outY = mLocked.pointerY;
215 }
216 
getDisplayId() const217 int32_t PointerController::getDisplayId() const {
218     AutoMutex _l(mLock);
219 
220     return mLocked.viewport.displayId;
221 }
222 
fade(Transition transition)223 void PointerController::fade(Transition transition) {
224     AutoMutex _l(mLock);
225 
226     // Remove the inactivity timeout, since we are fading now.
227     removeInactivityTimeoutLocked();
228 
229     // 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     }
238 }
239 
unfade(Transition transition)240 void PointerController::unfade(Transition transition) {
241     AutoMutex _l(mLock);
242 
243     // Always reset the inactivity timer.
244     resetInactivityTimeoutLocked();
245 
246     // Start unfading.
247     if (transition == TRANSITION_IMMEDIATE) {
248         mLocked.pointerFadeDirection = 0;
249         mLocked.pointerAlpha = 1.0f;
250         updatePointerLocked();
251     } else {
252         mLocked.pointerFadeDirection = 1;
253         startAnimationLocked();
254     }
255 }
256 
setPresentation(Presentation presentation)257 void PointerController::setPresentation(Presentation presentation) {
258     AutoMutex _l(mLock);
259 
260     if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
261         mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
262                 &mLocked.animationResources, mLocked.viewport.displayId);
263     }
264 
265     if (mLocked.presentation != presentation) {
266         mLocked.presentation = presentation;
267         mLocked.presentationChanged = true;
268 
269         if (presentation != PRESENTATION_SPOT) {
270             fadeOutAndReleaseAllSpotsLocked();
271         }
272 
273         updatePointerLocked();
274     }
275 }
276 
setSpots(const PointerCoords * spotCoords,const uint32_t * spotIdToIndex,BitSet32 spotIdBits,int32_t displayId)277 void PointerController::setSpots(const PointerCoords* spotCoords,
278         const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId) {
279 #if DEBUG_POINTER_UPDATES
280     ALOGD("setSpots: idBits=%08x", spotIdBits.value);
281     for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
282         uint32_t id = idBits.firstMarkedBit();
283         idBits.clearBit(id);
284         const PointerCoords& c = spotCoords[spotIdToIndex[id]];
285         ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id,
286                 c.getAxisValue(AMOTION_EVENT_AXIS_X),
287                 c.getAxisValue(AMOTION_EVENT_AXIS_Y),
288                 c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
289                 displayId);
290     }
291 #endif
292 
293     AutoMutex _l(mLock);
294 
295     std::vector<Spot*> newSpots;
296     std::map<int32_t, std::vector<Spot*>>::const_iterator iter =
297             mLocked.spotsByDisplay.find(displayId);
298     if (iter != mLocked.spotsByDisplay.end()) {
299         newSpots = iter->second;
300     }
301 
302     mSpriteController->openTransaction();
303 
304     // Add or move spots for fingers that are down.
305     for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
306         uint32_t id = idBits.clearFirstMarkedBit();
307         const PointerCoords& c = spotCoords[spotIdToIndex[id]];
308         const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
309                 ? mResources.spotTouch : mResources.spotHover;
310         float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
311         float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
312 
313         Spot* spot = getSpot(id, newSpots);
314         if (!spot) {
315             spot = createAndAddSpotLocked(id, newSpots);
316         }
317 
318         spot->updateSprite(&icon, x, y, displayId);
319     }
320 
321     // Remove spots for fingers that went up.
322     for (size_t i = 0; i < newSpots.size(); i++) {
323         Spot* spot = newSpots[i];
324         if (spot->id != Spot::INVALID_ID
325                 && !spotIdBits.hasBit(spot->id)) {
326             fadeOutAndReleaseSpotLocked(spot);
327         }
328     }
329 
330     mSpriteController->closeTransaction();
331     mLocked.spotsByDisplay[displayId] = newSpots;
332 }
333 
clearSpots()334 void PointerController::clearSpots() {
335 #if DEBUG_POINTER_UPDATES
336     ALOGD("clearSpots");
337 #endif
338 
339     AutoMutex _l(mLock);
340 
341     fadeOutAndReleaseAllSpotsLocked();
342 }
343 
setInactivityTimeout(InactivityTimeout inactivityTimeout)344 void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
345     AutoMutex _l(mLock);
346 
347     if (mLocked.inactivityTimeout != inactivityTimeout) {
348         mLocked.inactivityTimeout = inactivityTimeout;
349         resetInactivityTimeoutLocked();
350     }
351 }
352 
reloadPointerResources()353 void PointerController::reloadPointerResources() {
354     AutoMutex _l(mLock);
355 
356     loadResourcesLocked();
357     updatePointerLocked();
358 }
359 
360 /**
361  * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
362  * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
363  */
getNonRotatedSize(const DisplayViewport & viewport,int32_t & width,int32_t & height)364 static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
365     width = viewport.deviceWidth;
366     height = viewport.deviceHeight;
367 
368     if (viewport.orientation == DISPLAY_ORIENTATION_90
369             || viewport.orientation == DISPLAY_ORIENTATION_270) {
370         std::swap(width, height);
371     }
372 }
373 
setDisplayViewport(const DisplayViewport & viewport)374 void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
375     AutoMutex _l(mLock);
376     if (viewport == mLocked.viewport) {
377         return;
378     }
379 
380     const DisplayViewport oldViewport = mLocked.viewport;
381     mLocked.viewport = viewport;
382 
383     int32_t oldDisplayWidth, oldDisplayHeight;
384     getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
385     int32_t newDisplayWidth, newDisplayHeight;
386     getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
387 
388     // Reset cursor position to center if size or display changed.
389     if (oldViewport.displayId != viewport.displayId
390             || oldDisplayWidth != newDisplayWidth
391             || oldDisplayHeight != newDisplayHeight) {
392 
393         float minX, minY, maxX, maxY;
394         if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
395             mLocked.pointerX = (minX + maxX) * 0.5f;
396             mLocked.pointerY = (minY + maxY) * 0.5f;
397             // Reload icon resources for density may be changed.
398             loadResourcesLocked();
399         } else {
400             mLocked.pointerX = 0;
401             mLocked.pointerY = 0;
402         }
403 
404         fadeOutAndReleaseAllSpotsLocked();
405     } else if (oldViewport.orientation != viewport.orientation) {
406         // Apply offsets to convert from the pixel top-left corner position to the pixel center.
407         // This creates an invariant frame of reference that we can easily rotate when
408         // taking into account that the pointer may be located at fractional pixel offsets.
409         float x = mLocked.pointerX + 0.5f;
410         float y = mLocked.pointerY + 0.5f;
411         float temp;
412 
413         // Undo the previous rotation.
414         switch (oldViewport.orientation) {
415         case DISPLAY_ORIENTATION_90:
416             temp = x;
417             x =  oldViewport.deviceHeight - y;
418             y = temp;
419             break;
420         case DISPLAY_ORIENTATION_180:
421             x = oldViewport.deviceWidth - x;
422             y = oldViewport.deviceHeight - y;
423             break;
424         case DISPLAY_ORIENTATION_270:
425             temp = x;
426             x = y;
427             y = oldViewport.deviceWidth - temp;
428             break;
429         }
430 
431         // Perform the new rotation.
432         switch (viewport.orientation) {
433         case DISPLAY_ORIENTATION_90:
434             temp = x;
435             x = y;
436             y = viewport.deviceHeight - temp;
437             break;
438         case DISPLAY_ORIENTATION_180:
439             x = viewport.deviceWidth - x;
440             y = viewport.deviceHeight - y;
441             break;
442         case DISPLAY_ORIENTATION_270:
443             temp = x;
444             x = viewport.deviceWidth - y;
445             y = temp;
446             break;
447         }
448 
449         // Apply offsets to convert from the pixel center to the pixel top-left corner position
450         // and save the results.
451         mLocked.pointerX = x - 0.5f;
452         mLocked.pointerY = y - 0.5f;
453     }
454 
455     updatePointerLocked();
456 }
457 
updatePointerIcon(int32_t iconId)458 void PointerController::updatePointerIcon(int32_t iconId) {
459     AutoMutex _l(mLock);
460     if (mLocked.requestedPointerType != iconId) {
461         mLocked.requestedPointerType = iconId;
462         mLocked.presentationChanged = true;
463         updatePointerLocked();
464     }
465 }
466 
setCustomPointerIcon(const SpriteIcon & icon)467 void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
468     AutoMutex _l(mLock);
469 
470     const int32_t iconId = mPolicy->getCustomPointerIconId();
471     mLocked.additionalMouseResources[iconId] = icon;
472     mLocked.requestedPointerType = iconId;
473     mLocked.presentationChanged = true;
474 
475     updatePointerLocked();
476 }
477 
handleMessage(const Message & message)478 void PointerController::handleMessage(const Message& message) {
479     switch (message.what) {
480     case MSG_INACTIVITY_TIMEOUT:
481         doInactivityTimeout();
482         break;
483     }
484 }
485 
handleEvent(int,int events,void *)486 int PointerController::handleEvent(int /* fd */, int events, void* /* data */) {
487     if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
488         ALOGE("Display event receiver pipe was closed or an error occurred.  "
489               "events=0x%x", events);
490         return 0; // remove the callback
491     }
492 
493     if (!(events & Looper::EVENT_INPUT)) {
494         ALOGW("Received spurious callback for unhandled poll event.  "
495               "events=0x%x", events);
496         return 1; // keep the callback
497     }
498 
499     bool gotVsync = false;
500     ssize_t n;
501     nsecs_t timestamp;
502     DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
503     while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
504         for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
505             if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
506                 timestamp = buf[i].header.timestamp;
507                 gotVsync = true;
508             }
509         }
510     }
511     if (gotVsync) {
512         doAnimate(timestamp);
513     }
514     return 1;  // keep the callback
515 }
516 
doAnimate(nsecs_t timestamp)517 void PointerController::doAnimate(nsecs_t timestamp) {
518     AutoMutex _l(mLock);
519 
520     mLocked.animationPending = false;
521 
522     bool keepFading = doFadingAnimationLocked(timestamp);
523     bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
524     if (keepFading || keepBitmapFlipping) {
525         startAnimationLocked();
526     }
527 }
528 
doFadingAnimationLocked(nsecs_t timestamp)529 bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
530     bool keepAnimating = false;
531     nsecs_t frameDelay = timestamp - mLocked.animationTime;
532 
533     // Animate pointer fade.
534     if (mLocked.pointerFadeDirection < 0) {
535         mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
536         if (mLocked.pointerAlpha <= 0.0f) {
537             mLocked.pointerAlpha = 0.0f;
538             mLocked.pointerFadeDirection = 0;
539         } else {
540             keepAnimating = true;
541         }
542         updatePointerLocked();
543     } else if (mLocked.pointerFadeDirection > 0) {
544         mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
545         if (mLocked.pointerAlpha >= 1.0f) {
546             mLocked.pointerAlpha = 1.0f;
547             mLocked.pointerFadeDirection = 0;
548         } else {
549             keepAnimating = true;
550         }
551         updatePointerLocked();
552     }
553 
554     // Animate spots that are fading out and being removed.
555     for(auto it = mLocked.spotsByDisplay.begin(); it != mLocked.spotsByDisplay.end();) {
556         std::vector<Spot*>& spots = it->second;
557         size_t numSpots = spots.size();
558         for (size_t i = 0; i < numSpots;) {
559             Spot* spot = spots[i];
560             if (spot->id == Spot::INVALID_ID) {
561                 spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
562                 if (spot->alpha <= 0) {
563                     spots.erase(spots.begin() + i);
564                     releaseSpotLocked(spot);
565                     numSpots--;
566                     continue;
567                 } else {
568                     spot->sprite->setAlpha(spot->alpha);
569                     keepAnimating = true;
570                 }
571             }
572             ++i;
573         }
574 
575         if (spots.size() == 0) {
576             it = mLocked.spotsByDisplay.erase(it);
577         } else {
578             ++it;
579         }
580     }
581 
582     return keepAnimating;
583 }
584 
doBitmapAnimationLocked(nsecs_t timestamp)585 bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
586     std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
587             mLocked.requestedPointerType);
588     if (iter == mLocked.animationResources.end()) {
589         return false;
590     }
591 
592     if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
593         mSpriteController->openTransaction();
594 
595         int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
596         mLocked.animationFrameIndex += incr;
597         mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
598         while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
599             mLocked.animationFrameIndex -= iter->second.animationFrames.size();
600         }
601         mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
602 
603         mSpriteController->closeTransaction();
604     }
605 
606     // Keep animating.
607     return true;
608 }
609 
doInactivityTimeout()610 void PointerController::doInactivityTimeout() {
611     fade(TRANSITION_GRADUAL);
612 }
613 
startAnimationLocked()614 void PointerController::startAnimationLocked() {
615     if (!mLocked.animationPending) {
616         mLocked.animationPending = true;
617         mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
618         mDisplayEventReceiver.requestNextVsync();
619     }
620 }
621 
resetInactivityTimeoutLocked()622 void PointerController::resetInactivityTimeoutLocked() {
623     mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
624 
625     nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
626             ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
627     mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
628 }
629 
removeInactivityTimeoutLocked()630 void PointerController::removeInactivityTimeoutLocked() {
631     mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
632 }
633 
updatePointerLocked()634 void PointerController::updatePointerLocked() REQUIRES(mLock) {
635     if (!mLocked.viewport.isValid()) {
636         return;
637     }
638 
639     mSpriteController->openTransaction();
640 
641     mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
642     mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
643     mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
644 
645     if (mLocked.pointerAlpha > 0) {
646         mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
647         mLocked.pointerSprite->setVisible(true);
648     } else {
649         mLocked.pointerSprite->setVisible(false);
650     }
651 
652     if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
653         if (mLocked.presentation == PRESENTATION_POINTER) {
654             if (mLocked.requestedPointerType == mPolicy->getDefaultPointerIconId()) {
655                 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
656             } else {
657                 std::map<int32_t, SpriteIcon>::const_iterator iter =
658                     mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
659                 if (iter != mLocked.additionalMouseResources.end()) {
660                     std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
661                             mLocked.animationResources.find(mLocked.requestedPointerType);
662                     if (anim_iter != mLocked.animationResources.end()) {
663                         mLocked.animationFrameIndex = 0;
664                         mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
665                         startAnimationLocked();
666                     }
667                     mLocked.pointerSprite->setIcon(iter->second);
668                 } else {
669                     ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
670                     mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
671                 }
672             }
673         } else {
674             mLocked.pointerSprite->setIcon(mResources.spotAnchor);
675         }
676         mLocked.pointerIconChanged = false;
677         mLocked.presentationChanged = false;
678     }
679 
680     mSpriteController->closeTransaction();
681 }
682 
getSpot(uint32_t id,const std::vector<Spot * > & spots)683 PointerController::Spot* PointerController::getSpot(uint32_t id, const std::vector<Spot*>& spots) {
684     for (size_t i = 0; i < spots.size(); i++) {
685         Spot* spot = spots[i];
686         if (spot->id == id) {
687             return spot;
688         }
689     }
690 
691     return nullptr;
692 }
693 
createAndAddSpotLocked(uint32_t id,std::vector<Spot * > & spots)694 PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id,
695         std::vector<Spot*>& spots) {
696     // Remove spots until we have fewer than MAX_SPOTS remaining.
697     while (spots.size() >= MAX_SPOTS) {
698         Spot* spot = removeFirstFadingSpotLocked(spots);
699         if (!spot) {
700             spot = spots[0];
701             spots.erase(spots.begin());
702         }
703         releaseSpotLocked(spot);
704     }
705 
706     // Obtain a sprite from the recycled pool.
707     sp<Sprite> sprite;
708     if (! mLocked.recycledSprites.empty()) {
709         sprite = mLocked.recycledSprites.back();
710         mLocked.recycledSprites.pop_back();
711     } else {
712         sprite = mSpriteController->createSprite();
713     }
714 
715     // Return the new spot.
716     Spot* spot = new Spot(id, sprite);
717     spots.push_back(spot);
718     return spot;
719 }
720 
removeFirstFadingSpotLocked(std::vector<Spot * > & spots)721 PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) {
722     for (size_t i = 0; i < spots.size(); i++) {
723         Spot* spot = spots[i];
724         if (spot->id == Spot::INVALID_ID) {
725             spots.erase(spots.begin() + i);
726             return spot;
727         }
728     }
729     return NULL;
730 }
731 
releaseSpotLocked(Spot * spot)732 void PointerController::releaseSpotLocked(Spot* spot) {
733     spot->sprite->clearIcon();
734 
735     if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
736         mLocked.recycledSprites.push_back(spot->sprite);
737     }
738 
739     delete spot;
740 }
741 
fadeOutAndReleaseSpotLocked(Spot * spot)742 void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
743     if (spot->id != Spot::INVALID_ID) {
744         spot->id = Spot::INVALID_ID;
745         startAnimationLocked();
746     }
747 }
748 
fadeOutAndReleaseAllSpotsLocked()749 void PointerController::fadeOutAndReleaseAllSpotsLocked() {
750     for (auto& it : mLocked.spotsByDisplay) {
751         const std::vector<Spot*>& spots = it.second;
752         size_t numSpots = spots.size();
753         for (size_t i = 0; i < numSpots; i++) {
754             Spot* spot = spots[i];
755             fadeOutAndReleaseSpotLocked(spot);
756         }
757     }
758 }
759 
loadResourcesLocked()760 void PointerController::loadResourcesLocked() REQUIRES(mLock) {
761     mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
762     mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
763 
764     mLocked.additionalMouseResources.clear();
765     mLocked.animationResources.clear();
766     if (mLocked.presentation == PRESENTATION_POINTER) {
767         mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
768                 &mLocked.animationResources, mLocked.viewport.displayId);
769     }
770 
771     mLocked.pointerIconChanged = true;
772 }
773 
774 
775 // --- PointerController::Spot ---
776 
updateSprite(const SpriteIcon * icon,float x,float y,int32_t displayId)777 void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y,
778         int32_t displayId) {
779     sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
780     sprite->setAlpha(alpha);
781     sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
782     sprite->setPosition(x, y);
783     sprite->setDisplayId(displayId);
784     this->x = x;
785     this->y = y;
786 
787     if (icon != lastIcon) {
788         lastIcon = icon;
789         if (icon) {
790             sprite->setIcon(*icon);
791             sprite->setVisible(true);
792         } else {
793             sprite->setVisible(false);
794         }
795     }
796 }
797 
798 } // namespace android
799