blob: e4348f2a9b2106d178adf8f489a32ebe0704a1fd [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"
Jeff Brownb4ff35d2011-01-02 16:37:43 -080018//#define LOG_NDEBUG 0
19
20// Log debug messages about pointer updates
21#define DEBUG_POINTER_UPDATES 0
22
23#include "PointerController.h"
24
Mark Salyzyn52eb4e02016-09-28 16:15:30 -070025#include <log/log.h>
Jeff Brownb4ff35d2011-01-02 16:37:43 -080026
Jeff Brownb4ff35d2011-01-02 16:37:43 -080027namespace android {
28
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070029// --- WeakLooperCallback ---
30
31class WeakLooperCallback: public LooperCallback {
32protected:
33 virtual ~WeakLooperCallback() { }
34
35public:
Chih-Hung Hsieh0c29f392018-12-20 13:51:01 -080036 explicit WeakLooperCallback(const wp<LooperCallback>& callback) :
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070037 mCallback(callback) {
38 }
39
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
48private:
49 wp<LooperCallback> mCallback;
50};
51
Jeff Brownb4ff35d2011-01-02 16:37:43 -080052// --- PointerController ---
53
Jeff Brown05dc66a2011-03-02 14:41:58 -080054// Time to wait before starting the fade when the pointer is inactive.
Jeff Brown2352b972011-04-12 22:39:53 -070055static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
56static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
57
Jeff Brown2352b972011-04-12 22:39:53 -070058// Time to spend fading out the spot completely.
59static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
Jeff Brown05dc66a2011-03-02 14:41:58 -080060
61// Time to spend fading out the pointer completely.
Jeff Brown2352b972011-04-12 22:39:53 -070062static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
Jeff Brown05dc66a2011-03-02 14:41:58 -080063
Jun Mukaic0c0ac32015-10-27 10:09:21 -070064// The number of events to be read at once for DisplayEventReceiver.
65static const int EVENT_BUFFER_SIZE = 100;
Jeff Brown05dc66a2011-03-02 14:41:58 -080066
Jeff Brown2352b972011-04-12 22:39:53 -070067// --- PointerController ---
68
69PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
70 const sp<Looper>& looper, const sp<SpriteController>& spriteController) :
71 mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
Jeff Brown5541de92011-04-11 11:54:25 -070072 mHandler = new WeakMessageHandler(this);
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070073 mCallback = new WeakLooperCallback(this);
Jeff Brown5541de92011-04-11 11:54:25 -070074
Jun Mukaic0c0ac32015-10-27 10:09:21 -070075 if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
76 mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
Vladislav Kaznacheev33c59032016-09-09 10:03:31 -070077 Looper::EVENT_INPUT, mCallback, nullptr);
Jun Mukaic0c0ac32015-10-27 10:09:21 -070078 } else {
79 ALOGE("Failed to initialize DisplayEventReceiver.");
80 }
81
Jeff Brownb4ff35d2011-01-02 16:37:43 -080082 AutoMutex _l(mLock);
83
Jeff Brown2352b972011-04-12 22:39:53 -070084 mLocked.animationPending = false;
85
Jeff Brown2352b972011-04-12 22:39:53 -070086 mLocked.presentation = PRESENTATION_POINTER;
87 mLocked.presentationChanged = false;
88
89 mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
90
Jeff Brown538881e2011-05-25 18:23:38 -070091 mLocked.pointerFadeDirection = 0;
Jeff Brownb4ff35d2011-01-02 16:37:43 -080092 mLocked.pointerX = 0;
93 mLocked.pointerY = 0;
Jeff Brown538881e2011-05-25 18:23:38 -070094 mLocked.pointerAlpha = 0.0f; // pointer is initially faded
Jeff Brown2352b972011-04-12 22:39:53 -070095 mLocked.pointerSprite = mSpriteController->createSprite();
96 mLocked.pointerIconChanged = false;
Michael Wrighte051f6f2016-05-13 17:44:16 +010097 mLocked.requestedPointerType = mPolicy->getDefaultPointerIconId();
Jeff Brown2352b972011-04-12 22:39:53 -070098
Jun Mukai808196f2015-10-28 16:46:44 -070099 mLocked.animationFrameIndex = 0;
100 mLocked.lastFrameUpdatedTime = 0;
101
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800102 mLocked.buttonState = 0;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800103}
104
105PointerController::~PointerController() {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800106 mLooper->removeMessages(mHandler);
107
Jeff Brown5541de92011-04-11 11:54:25 -0700108 AutoMutex _l(mLock);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800109
Jeff Brown2352b972011-04-12 22:39:53 -0700110 mLocked.pointerSprite.clear();
111
Arthur Hungd25699a2019-01-25 17:53:22 +0800112 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 }
Jeff Brown2352b972011-04-12 22:39:53 -0700118 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800119 mLocked.spotsByDisplay.clear();
Jeff Brown2352b972011-04-12 22:39:53 -0700120 mLocked.recycledSprites.clear();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800121}
122
123bool 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
130bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
131 float* outMaxX, float* outMaxY) const {
Arthur Hungb9b32002018-12-18 17:39:43 +0800132
133 if (!mLocked.viewport.isValid()) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800134 return false;
135 }
136
Arthur Hungb9b32002018-12-18 17:39:43 +0800137 *outMinX = mLocked.viewport.logicalLeft;
138 *outMinY = mLocked.viewport.logicalTop;
139 *outMaxX = mLocked.viewport.logicalRight - 1;
140 *outMaxY = mLocked.viewport.logicalBottom - 1;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800141 return true;
142}
143
144void PointerController::move(float deltaX, float deltaY) {
145#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000146 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800147#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
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700157void PointerController::setButtonState(int32_t buttonState) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800158#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000159 ALOGD("Set button state 0x%08x", buttonState);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800160#endif
161 AutoMutex _l(mLock);
162
163 if (mLocked.buttonState != buttonState) {
164 mLocked.buttonState = buttonState;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800165 }
166}
167
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700168int32_t PointerController::getButtonState() const {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800169 AutoMutex _l(mLock);
170
171 return mLocked.buttonState;
172}
173
174void PointerController::setPosition(float x, float y) {
175#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000176 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800177#endif
178 AutoMutex _l(mLock);
179
180 setPositionLocked(x, y);
181}
182
183void 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 }
Jeff Brown2352b972011-04-12 22:39:53 -0700200 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800201 }
202}
203
204void PointerController::getPosition(float* outX, float* outY) const {
205 AutoMutex _l(mLock);
206
207 *outX = mLocked.pointerX;
208 *outY = mLocked.pointerY;
209}
210
Arthur Hungb9b32002018-12-18 17:39:43 +0800211int32_t PointerController::getDisplayId() const {
212 AutoMutex _l(mLock);
213
214 return mLocked.viewport.displayId;
215}
216
Jeff Brown538881e2011-05-25 18:23:38 -0700217void PointerController::fade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800218 AutoMutex _l(mLock);
219
Jeff Brown538881e2011-05-25 18:23:38 -0700220 // 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 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800232}
233
Jeff Brown538881e2011-05-25 18:23:38 -0700234void PointerController::unfade(Transition transition) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800235 AutoMutex _l(mLock);
236
Jeff Brown2352b972011-04-12 22:39:53 -0700237 // Always reset the inactivity timer.
238 resetInactivityTimeoutLocked();
239
Jeff Brown538881e2011-05-25 18:23:38 -0700240 // Start unfading.
241 if (transition == TRANSITION_IMMEDIATE) {
242 mLocked.pointerFadeDirection = 0;
Jeff Brown2352b972011-04-12 22:39:53 -0700243 mLocked.pointerAlpha = 1.0f;
244 updatePointerLocked();
Jeff Brown538881e2011-05-25 18:23:38 -0700245 } else {
246 mLocked.pointerFadeDirection = 1;
247 startAnimationLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800248 }
249}
250
Jeff Brown2352b972011-04-12 22:39:53 -0700251void PointerController::setPresentation(Presentation presentation) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800252 AutoMutex _l(mLock);
253
Jun Mukai1db53972015-09-11 18:08:31 -0700254 if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700255 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
Andrii Kulianfd8666d2018-10-05 16:58:39 -0700256 &mLocked.animationResources, mLocked.viewport.displayId);
Jun Mukai1db53972015-09-11 18:08:31 -0700257 }
258
Jeff Brown2352b972011-04-12 22:39:53 -0700259 if (mLocked.presentation != presentation) {
260 mLocked.presentation = presentation;
261 mLocked.presentationChanged = true;
262
263 if (presentation != PRESENTATION_SPOT) {
264 fadeOutAndReleaseAllSpotsLocked();
265 }
266
267 updatePointerLocked();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800268 }
269}
270
Jeff Browncb5ffcf2011-06-06 20:03:18 -0700271void PointerController::setSpots(const PointerCoords* spotCoords,
Arthur Hungd25699a2019-01-25 17:53:22 +0800272 const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId) {
Jeff Brown2352b972011-04-12 22:39:53 -0700273#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000274 ALOGD("setSpots: idBits=%08x", spotIdBits.value);
Jeff Brown2352b972011-04-12 22:39:53 -0700275 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
276 uint32_t id = idBits.firstMarkedBit();
277 idBits.clearBit(id);
278 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
Arthur Hungd25699a2019-01-25 17:53:22 +0800279 ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id,
Jeff Brown2352b972011-04-12 22:39:53 -0700280 c.getAxisValue(AMOTION_EVENT_AXIS_X),
281 c.getAxisValue(AMOTION_EVENT_AXIS_Y),
Arthur Hungd25699a2019-01-25 17:53:22 +0800282 c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
283 displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700284 }
285#endif
286
287 AutoMutex _l(mLock);
288
Arthur Hungd25699a2019-01-25 17:53:22 +0800289 std::vector<Spot*> newSpots;
290 std::map<int32_t, std::vector<Spot*>>::const_iterator iter =
291 mLocked.spotsByDisplay.find(displayId);
292 if (iter != mLocked.spotsByDisplay.end()) {
293 newSpots = iter->second;
294 }
295
Jeff Brown2352b972011-04-12 22:39:53 -0700296 mSpriteController->openTransaction();
297
298 // Add or move spots for fingers that are down.
299 for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700300 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown2352b972011-04-12 22:39:53 -0700301 const PointerCoords& c = spotCoords[spotIdToIndex[id]];
302 const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
303 ? mResources.spotTouch : mResources.spotHover;
304 float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
305 float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
306
Arthur Hungd25699a2019-01-25 17:53:22 +0800307 Spot* spot = getSpot(id, newSpots);
Jeff Brown2352b972011-04-12 22:39:53 -0700308 if (!spot) {
Arthur Hungd25699a2019-01-25 17:53:22 +0800309 spot = createAndAddSpotLocked(id, newSpots);
Jeff Brown2352b972011-04-12 22:39:53 -0700310 }
311
Arthur Hungd25699a2019-01-25 17:53:22 +0800312 spot->updateSprite(&icon, x, y, displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700313 }
314
315 // Remove spots for fingers that went up.
Arthur Hungd25699a2019-01-25 17:53:22 +0800316 for (size_t i = 0; i < newSpots.size(); i++) {
317 Spot* spot = newSpots[i];
Jeff Brown2352b972011-04-12 22:39:53 -0700318 if (spot->id != Spot::INVALID_ID
319 && !spotIdBits.hasBit(spot->id)) {
320 fadeOutAndReleaseSpotLocked(spot);
321 }
322 }
323
324 mSpriteController->closeTransaction();
Arthur Hungd25699a2019-01-25 17:53:22 +0800325 mLocked.spotsByDisplay[displayId] = newSpots;
Jeff Brown2352b972011-04-12 22:39:53 -0700326}
327
328void PointerController::clearSpots() {
329#if DEBUG_POINTER_UPDATES
Steve Block5baa3a62011-12-20 16:23:08 +0000330 ALOGD("clearSpots");
Jeff Brown2352b972011-04-12 22:39:53 -0700331#endif
332
333 AutoMutex _l(mLock);
334
335 fadeOutAndReleaseAllSpotsLocked();
336}
337
338void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
339 AutoMutex _l(mLock);
340
341 if (mLocked.inactivityTimeout != inactivityTimeout) {
342 mLocked.inactivityTimeout = inactivityTimeout;
343 resetInactivityTimeoutLocked();
344 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800345}
346
Jun Mukai19a56012015-11-24 11:25:52 -0800347void PointerController::reloadPointerResources() {
348 AutoMutex _l(mLock);
349
Arthur Hungb9b32002018-12-18 17:39:43 +0800350 loadResourcesLocked();
Jun Mukai19a56012015-11-24 11:25:52 -0800351 updatePointerLocked();
352}
353
Arthur Hungb9b32002018-12-18 17:39:43 +0800354/**
355 * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
356 * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
357 */
358static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
359 width = viewport.deviceWidth;
360 height = viewport.deviceHeight;
Andrii Kuliand44026f2018-12-17 18:59:36 +0000361
Arthur Hungb9b32002018-12-18 17:39:43 +0800362 if (viewport.orientation == DISPLAY_ORIENTATION_90
363 || viewport.orientation == DISPLAY_ORIENTATION_270) {
364 std::swap(width, height);
365 }
366}
367
368void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
369 AutoMutex _l(mLock);
370 if (viewport == mLocked.viewport) {
371 return;
Jeff Brownd728bf52012-09-08 18:05:28 -0700372 }
373
Arthur Hungb9b32002018-12-18 17:39:43 +0800374 const DisplayViewport oldViewport = mLocked.viewport;
375 mLocked.viewport = viewport;
376
377 int32_t oldDisplayWidth, oldDisplayHeight;
378 getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
379 int32_t newDisplayWidth, newDisplayHeight;
380 getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
381
382 // Reset cursor position to center if size or display changed.
383 if (oldViewport.displayId != viewport.displayId
384 || oldDisplayWidth != newDisplayWidth
385 || oldDisplayHeight != newDisplayHeight) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800386
387 float minX, minY, maxX, maxY;
388 if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
389 mLocked.pointerX = (minX + maxX) * 0.5f;
390 mLocked.pointerY = (minY + maxY) * 0.5f;
Arthur Hungb9b32002018-12-18 17:39:43 +0800391 // Reload icon resources for density may be changed.
392 loadResourcesLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800393 } else {
394 mLocked.pointerX = 0;
395 mLocked.pointerY = 0;
396 }
397
Jeff Brown2352b972011-04-12 22:39:53 -0700398 fadeOutAndReleaseAllSpotsLocked();
Arthur Hungb9b32002018-12-18 17:39:43 +0800399 } else if (oldViewport.orientation != viewport.orientation) {
Jeff Brownd41cff22011-03-03 02:09:54 -0800400 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
401 // This creates an invariant frame of reference that we can easily rotate when
402 // taking into account that the pointer may be located at fractional pixel offsets.
403 float x = mLocked.pointerX + 0.5f;
404 float y = mLocked.pointerY + 0.5f;
405 float temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800406
Jeff Brownd41cff22011-03-03 02:09:54 -0800407 // Undo the previous rotation.
Arthur Hungb9b32002018-12-18 17:39:43 +0800408 switch (oldViewport.orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800409 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800410 temp = x;
Arthur Hungb9b32002018-12-18 17:39:43 +0800411 x = oldViewport.deviceHeight - y;
Jeff Brownd41cff22011-03-03 02:09:54 -0800412 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800413 break;
414 case DISPLAY_ORIENTATION_180:
Arthur Hungb9b32002018-12-18 17:39:43 +0800415 x = oldViewport.deviceWidth - x;
416 y = oldViewport.deviceHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800417 break;
418 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800419 temp = x;
420 x = y;
Arthur Hungb9b32002018-12-18 17:39:43 +0800421 y = oldViewport.deviceWidth - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800422 break;
423 }
424
Jeff Brownd41cff22011-03-03 02:09:54 -0800425 // Perform the new rotation.
Arthur Hungb9b32002018-12-18 17:39:43 +0800426 switch (viewport.orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800427 case DISPLAY_ORIENTATION_90:
Jeff Brownd41cff22011-03-03 02:09:54 -0800428 temp = x;
429 x = y;
Arthur Hungb9b32002018-12-18 17:39:43 +0800430 y = viewport.deviceHeight - temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800431 break;
432 case DISPLAY_ORIENTATION_180:
Arthur Hungb9b32002018-12-18 17:39:43 +0800433 x = viewport.deviceWidth - x;
434 y = viewport.deviceHeight - y;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800435 break;
436 case DISPLAY_ORIENTATION_270:
Jeff Brownd41cff22011-03-03 02:09:54 -0800437 temp = x;
Arthur Hungb9b32002018-12-18 17:39:43 +0800438 x = viewport.deviceWidth - y;
Jeff Brownd41cff22011-03-03 02:09:54 -0800439 y = temp;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800440 break;
441 }
442
Jeff Brownd41cff22011-03-03 02:09:54 -0800443 // Apply offsets to convert from the pixel center to the pixel top-left corner position
444 // and save the results.
445 mLocked.pointerX = x - 0.5f;
446 mLocked.pointerY = y - 0.5f;
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800447 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700448
449 updatePointerLocked();
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800450}
451
Michael Wrighte051f6f2016-05-13 17:44:16 +0100452void PointerController::updatePointerIcon(int32_t iconId) {
Jun Mukai1db53972015-09-11 18:08:31 -0700453 AutoMutex _l(mLock);
Michael Wrighte051f6f2016-05-13 17:44:16 +0100454 if (mLocked.requestedPointerType != iconId) {
455 mLocked.requestedPointerType = iconId;
Jun Mukai1db53972015-09-11 18:08:31 -0700456 mLocked.presentationChanged = true;
457 updatePointerLocked();
458 }
459}
460
Jun Mukaid4eaef72015-10-30 15:54:33 -0700461void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
462 AutoMutex _l(mLock);
463
464 const int32_t iconId = mPolicy->getCustomPointerIconId();
465 mLocked.additionalMouseResources[iconId] = icon;
Michael Wrighte051f6f2016-05-13 17:44:16 +0100466 mLocked.requestedPointerType = iconId;
Jun Mukaid4eaef72015-10-30 15:54:33 -0700467 mLocked.presentationChanged = true;
468
469 updatePointerLocked();
470}
471
Jeff Brown05dc66a2011-03-02 14:41:58 -0800472void PointerController::handleMessage(const Message& message) {
473 switch (message.what) {
Jeff Brown2352b972011-04-12 22:39:53 -0700474 case MSG_INACTIVITY_TIMEOUT:
475 doInactivityTimeout();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800476 break;
477 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800478}
479
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700480int PointerController::handleEvent(int /* fd */, int events, void* /* data */) {
481 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
482 ALOGE("Display event receiver pipe was closed or an error occurred. "
483 "events=0x%x", events);
484 return 0; // remove the callback
485 }
486
487 if (!(events & Looper::EVENT_INPUT)) {
488 ALOGW("Received spurious callback for unhandled poll event. "
489 "events=0x%x", events);
490 return 1; // keep the callback
491 }
492
493 bool gotVsync = false;
494 ssize_t n;
495 nsecs_t timestamp;
496 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
497 while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
498 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
499 if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
500 timestamp = buf[i].header.timestamp;
501 gotVsync = true;
502 }
503 }
504 }
505 if (gotVsync) {
506 doAnimate(timestamp);
507 }
508 return 1; // keep the callback
509}
510
511void PointerController::doAnimate(nsecs_t timestamp) {
Jeff Brown2352b972011-04-12 22:39:53 -0700512 AutoMutex _l(mLock);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800513
Jeff Brown2352b972011-04-12 22:39:53 -0700514 mLocked.animationPending = false;
Jun Mukai808196f2015-10-28 16:46:44 -0700515
516 bool keepFading = doFadingAnimationLocked(timestamp);
517 bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
518 if (keepFading || keepBitmapFlipping) {
519 startAnimationLocked();
520 }
521}
522
523bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
524 bool keepAnimating = false;
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700525 nsecs_t frameDelay = timestamp - mLocked.animationTime;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800526
Jeff Brown2352b972011-04-12 22:39:53 -0700527 // Animate pointer fade.
Jeff Brown538881e2011-05-25 18:23:38 -0700528 if (mLocked.pointerFadeDirection < 0) {
Jeff Brown2352b972011-04-12 22:39:53 -0700529 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
Jeff Brown538881e2011-05-25 18:23:38 -0700530 if (mLocked.pointerAlpha <= 0.0f) {
531 mLocked.pointerAlpha = 0.0f;
532 mLocked.pointerFadeDirection = 0;
533 } else {
534 keepAnimating = true;
535 }
536 updatePointerLocked();
537 } else if (mLocked.pointerFadeDirection > 0) {
538 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
539 if (mLocked.pointerAlpha >= 1.0f) {
540 mLocked.pointerAlpha = 1.0f;
541 mLocked.pointerFadeDirection = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800542 } else {
Jeff Brown2352b972011-04-12 22:39:53 -0700543 keepAnimating = true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800544 }
Jeff Brown2352b972011-04-12 22:39:53 -0700545 updatePointerLocked();
546 }
547
548 // Animate spots that are fading out and being removed.
Arthur Hungd25699a2019-01-25 17:53:22 +0800549 for(auto it = mLocked.spotsByDisplay.begin(); it != mLocked.spotsByDisplay.end();) {
550 std::vector<Spot*>& spots = it->second;
551 size_t numSpots = spots.size();
552 for (size_t i = 0; i < numSpots;) {
553 Spot* spot = spots[i];
554 if (spot->id == Spot::INVALID_ID) {
555 spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
556 if (spot->alpha <= 0) {
557 spots.erase(spots.begin() + i);
558 releaseSpotLocked(spot);
559 numSpots--;
560 continue;
561 } else {
562 spot->sprite->setAlpha(spot->alpha);
563 keepAnimating = true;
564 }
Jeff Brown2352b972011-04-12 22:39:53 -0700565 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800566 ++i;
Jeff Brown2352b972011-04-12 22:39:53 -0700567 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800568
569 if (spots.size() == 0) {
570 it = mLocked.spotsByDisplay.erase(it);
571 } else {
572 ++it;
573 }
Jeff Brown2352b972011-04-12 22:39:53 -0700574 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800575
Jun Mukai808196f2015-10-28 16:46:44 -0700576 return keepAnimating;
577}
Jeff Brown2352b972011-04-12 22:39:53 -0700578
Jun Mukai808196f2015-10-28 16:46:44 -0700579bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
580 std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
Michael Wrighte051f6f2016-05-13 17:44:16 +0100581 mLocked.requestedPointerType);
Jun Mukai808196f2015-10-28 16:46:44 -0700582 if (iter == mLocked.animationResources.end()) {
583 return false;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800584 }
Jun Mukai808196f2015-10-28 16:46:44 -0700585
586 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
587 mSpriteController->openTransaction();
588
589 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
590 mLocked.animationFrameIndex += incr;
591 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
592 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
593 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
594 }
595 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
596
597 mSpriteController->closeTransaction();
598 }
599
600 // Keep animating.
601 return true;
Jeff Brown05dc66a2011-03-02 14:41:58 -0800602}
603
Jeff Brown2352b972011-04-12 22:39:53 -0700604void PointerController::doInactivityTimeout() {
Jeff Brown538881e2011-05-25 18:23:38 -0700605 fade(TRANSITION_GRADUAL);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800606}
607
Jeff Brown2352b972011-04-12 22:39:53 -0700608void PointerController::startAnimationLocked() {
609 if (!mLocked.animationPending) {
610 mLocked.animationPending = true;
611 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
Jun Mukaic0c0ac32015-10-27 10:09:21 -0700612 mDisplayEventReceiver.requestNextVsync();
Jeff Brown2352b972011-04-12 22:39:53 -0700613 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800614}
615
Jeff Brown2352b972011-04-12 22:39:53 -0700616void PointerController::resetInactivityTimeoutLocked() {
617 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
618
619 nsecs_t timeout = mLocked.inactivityTimeout == INACTIVITY_TIMEOUT_SHORT
620 ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
621 mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
622}
623
Jeff Brown538881e2011-05-25 18:23:38 -0700624void PointerController::removeInactivityTimeoutLocked() {
Jeff Brown2352b972011-04-12 22:39:53 -0700625 mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
Jeff Brown2352b972011-04-12 22:39:53 -0700626}
627
Arthur Hungb9b32002018-12-18 17:39:43 +0800628void PointerController::updatePointerLocked() REQUIRES(mLock) {
629 if (!mLocked.viewport.isValid()) {
630 return;
631 }
632
Jeff Brown2352b972011-04-12 22:39:53 -0700633 mSpriteController->openTransaction();
634
635 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
636 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
Arthur Hungb9b32002018-12-18 17:39:43 +0800637 mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700638
639 if (mLocked.pointerAlpha > 0) {
640 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
641 mLocked.pointerSprite->setVisible(true);
642 } else {
643 mLocked.pointerSprite->setVisible(false);
644 }
645
646 if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
Jun Mukai1db53972015-09-11 18:08:31 -0700647 if (mLocked.presentation == PRESENTATION_POINTER) {
Michael Wrighte051f6f2016-05-13 17:44:16 +0100648 if (mLocked.requestedPointerType == mPolicy->getDefaultPointerIconId()) {
Jun Mukai1db53972015-09-11 18:08:31 -0700649 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
650 } else {
Jun Mukai808196f2015-10-28 16:46:44 -0700651 std::map<int32_t, SpriteIcon>::const_iterator iter =
Michael Wrighte051f6f2016-05-13 17:44:16 +0100652 mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
Jun Mukai1db53972015-09-11 18:08:31 -0700653 if (iter != mLocked.additionalMouseResources.end()) {
Jun Mukai808196f2015-10-28 16:46:44 -0700654 std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
Michael Wrighte051f6f2016-05-13 17:44:16 +0100655 mLocked.animationResources.find(mLocked.requestedPointerType);
Jun Mukai808196f2015-10-28 16:46:44 -0700656 if (anim_iter != mLocked.animationResources.end()) {
657 mLocked.animationFrameIndex = 0;
658 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
659 startAnimationLocked();
660 }
Jun Mukai1db53972015-09-11 18:08:31 -0700661 mLocked.pointerSprite->setIcon(iter->second);
662 } else {
Michael Wrighte051f6f2016-05-13 17:44:16 +0100663 ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
Jun Mukai1db53972015-09-11 18:08:31 -0700664 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
665 }
666 }
667 } else {
668 mLocked.pointerSprite->setIcon(mResources.spotAnchor);
669 }
Jeff Brown2352b972011-04-12 22:39:53 -0700670 mLocked.pointerIconChanged = false;
671 mLocked.presentationChanged = false;
672 }
673
674 mSpriteController->closeTransaction();
675}
676
Arthur Hungd25699a2019-01-25 17:53:22 +0800677PointerController::Spot* PointerController::getSpot(uint32_t id, const std::vector<Spot*>& spots) {
678 for (size_t i = 0; i < spots.size(); i++) {
679 Spot* spot = spots[i];
Jeff Brown2352b972011-04-12 22:39:53 -0700680 if (spot->id == id) {
681 return spot;
682 }
683 }
Arthur Hungd25699a2019-01-25 17:53:22 +0800684
685 return nullptr;
Jeff Brown2352b972011-04-12 22:39:53 -0700686}
687
Arthur Hungd25699a2019-01-25 17:53:22 +0800688PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id,
689 std::vector<Spot*>& spots) {
Jeff Brown2352b972011-04-12 22:39:53 -0700690 // Remove spots until we have fewer than MAX_SPOTS remaining.
Arthur Hungd25699a2019-01-25 17:53:22 +0800691 while (spots.size() >= MAX_SPOTS) {
692 Spot* spot = removeFirstFadingSpotLocked(spots);
Jeff Brown2352b972011-04-12 22:39:53 -0700693 if (!spot) {
Arthur Hungd25699a2019-01-25 17:53:22 +0800694 spot = spots[0];
695 spots.erase(spots.begin());
Jeff Brown2352b972011-04-12 22:39:53 -0700696 }
697 releaseSpotLocked(spot);
698 }
699
700 // Obtain a sprite from the recycled pool.
701 sp<Sprite> sprite;
Arthur Hungd25699a2019-01-25 17:53:22 +0800702 if (! mLocked.recycledSprites.empty()) {
703 sprite = mLocked.recycledSprites.back();
704 mLocked.recycledSprites.pop_back();
Jeff Brown2352b972011-04-12 22:39:53 -0700705 } else {
706 sprite = mSpriteController->createSprite();
707 }
708
709 // Return the new spot.
710 Spot* spot = new Spot(id, sprite);
Arthur Hungd25699a2019-01-25 17:53:22 +0800711 spots.push_back(spot);
Jeff Brown2352b972011-04-12 22:39:53 -0700712 return spot;
713}
714
Arthur Hungd25699a2019-01-25 17:53:22 +0800715PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) {
716 for (size_t i = 0; i < spots.size(); i++) {
717 Spot* spot = spots[i];
Jeff Brown2352b972011-04-12 22:39:53 -0700718 if (spot->id == Spot::INVALID_ID) {
Arthur Hungd25699a2019-01-25 17:53:22 +0800719 spots.erase(spots.begin() + i);
Jeff Brown2352b972011-04-12 22:39:53 -0700720 return spot;
721 }
722 }
723 return NULL;
724}
725
726void PointerController::releaseSpotLocked(Spot* spot) {
727 spot->sprite->clearIcon();
728
729 if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
Arthur Hungd25699a2019-01-25 17:53:22 +0800730 mLocked.recycledSprites.push_back(spot->sprite);
Jeff Brown2352b972011-04-12 22:39:53 -0700731 }
732
733 delete spot;
734}
735
736void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
737 if (spot->id != Spot::INVALID_ID) {
738 spot->id = Spot::INVALID_ID;
739 startAnimationLocked();
740 }
741}
742
743void PointerController::fadeOutAndReleaseAllSpotsLocked() {
Arthur Hungd25699a2019-01-25 17:53:22 +0800744 for (auto& it : mLocked.spotsByDisplay) {
745 const std::vector<Spot*>& spots = it.second;
746 size_t numSpots = spots.size();
747 for (size_t i = 0; i < numSpots; i++) {
748 Spot* spot = spots[i];
749 fadeOutAndReleaseSpotLocked(spot);
750 }
Jeff Brown2352b972011-04-12 22:39:53 -0700751 }
752}
753
Arthur Hungb9b32002018-12-18 17:39:43 +0800754void PointerController::loadResourcesLocked() REQUIRES(mLock) {
Andrii Kulianfd8666d2018-10-05 16:58:39 -0700755 mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
Arthur Hung350896b2019-02-26 16:35:01 +0800756 mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
Arthur Hungb9b32002018-12-18 17:39:43 +0800757
Arthur Hung350896b2019-02-26 16:35:01 +0800758 mLocked.additionalMouseResources.clear();
759 mLocked.animationResources.clear();
Arthur Hungb9b32002018-12-18 17:39:43 +0800760 if (mLocked.presentation == PRESENTATION_POINTER) {
Arthur Hungb9b32002018-12-18 17:39:43 +0800761 mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
Andrii Kulianfd8666d2018-10-05 16:58:39 -0700762 &mLocked.animationResources, mLocked.viewport.displayId);
Arthur Hungb9b32002018-12-18 17:39:43 +0800763 }
764
765 mLocked.pointerIconChanged = true;
Jeff Brown2352b972011-04-12 22:39:53 -0700766}
767
768
769// --- PointerController::Spot ---
770
Arthur Hungd25699a2019-01-25 17:53:22 +0800771void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y,
772 int32_t displayId) {
Jeff Brown2352b972011-04-12 22:39:53 -0700773 sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
774 sprite->setAlpha(alpha);
775 sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
776 sprite->setPosition(x, y);
Arthur Hungd25699a2019-01-25 17:53:22 +0800777 sprite->setDisplayId(displayId);
Jeff Brown2352b972011-04-12 22:39:53 -0700778 this->x = x;
779 this->y = y;
780
781 if (icon != lastIcon) {
782 lastIcon = icon;
783 if (icon) {
784 sprite->setIcon(*icon);
785 sprite->setVisible(true);
786 } else {
787 sprite->setVisible(false);
788 }
789 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800790}
791
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800792} // namespace android