blob: 1afef75bc7419488cf0ba07f304d0eaddc44065c [file] [log] [blame]
Liam Harringtonc782be62020-07-17 19:48:24 +00001/*
2 * Copyright (C) 2020 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 "MouseCursorController"
18//#define LOG_NDEBUG 0
19
20// Log debug messages about pointer updates
21#define DEBUG_MOUSE_CURSOR_UPDATES 0
22
23#include "MouseCursorController.h"
24
Brandon Pollack015f5d92022-06-02 06:59:33 +000025#include <input/Input.h>
Liam Harringtonc782be62020-07-17 19:48:24 +000026#include <log/log.h>
27
Arpit Singh05215af2024-08-25 17:49:32 +000028#define INDENT " "
29#define INDENT2 " "
30
Liam Harringtonc782be62020-07-17 19:48:24 +000031namespace {
32// Time to spend fading out the pointer completely.
33const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
34} // namespace
35
36namespace android {
37
38// --- MouseCursorController ---
39
40MouseCursorController::MouseCursorController(PointerControllerContext& context)
41 : mContext(context) {
42 std::scoped_lock lock(mLock);
43
Seunghwan Choi670b33d2023-01-13 21:12:59 +090044 mLocked.stylusHoverMode = false;
45
Liam Harringtonc782be62020-07-17 19:48:24 +000046 mLocked.animationFrameIndex = 0;
47 mLocked.lastFrameUpdatedTime = 0;
48
49 mLocked.pointerFadeDirection = 0;
50 mLocked.pointerX = 0;
51 mLocked.pointerY = 0;
52 mLocked.pointerAlpha = 0.0f; // pointer is initially faded
Prabir Pradhan27c6d992023-08-18 19:44:55 +000053 mLocked.pointerSprite = mContext.getSpriteController().createSprite();
Liam Harringtonc782be62020-07-17 19:48:24 +000054 mLocked.updatePointerIcon = false;
Seunghwan Choi670b33d2023-01-13 21:12:59 +090055 mLocked.requestedPointerType = PointerIconStyle::TYPE_NOT_SPECIFIED;
56 mLocked.resolvedPointerType = PointerIconStyle::TYPE_NOT_SPECIFIED;
Liam Harringtonc782be62020-07-17 19:48:24 +000057
58 mLocked.resourcesLoaded = false;
Liam Harringtonc782be62020-07-17 19:48:24 +000059}
60
61MouseCursorController::~MouseCursorController() {
62 std::scoped_lock lock(mLock);
63
64 mLocked.pointerSprite.clear();
65}
66
Prabir Pradhanb5dadec2023-02-28 17:43:09 +000067std::optional<FloatRect> MouseCursorController::getBounds() const {
Liam Harringtonc782be62020-07-17 19:48:24 +000068 std::scoped_lock lock(mLock);
69
Prabir Pradhanb5dadec2023-02-28 17:43:09 +000070 return getBoundsLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +000071}
72
Prabir Pradhanb5dadec2023-02-28 17:43:09 +000073std::optional<FloatRect> MouseCursorController::getBoundsLocked() const REQUIRES(mLock) {
Liam Harringtonc782be62020-07-17 19:48:24 +000074 if (!mLocked.viewport.isValid()) {
Prabir Pradhanb5dadec2023-02-28 17:43:09 +000075 return {};
Liam Harringtonc782be62020-07-17 19:48:24 +000076 }
77
Prabir Pradhanb5dadec2023-02-28 17:43:09 +000078 return FloatRect{
79 static_cast<float>(mLocked.viewport.logicalLeft),
80 static_cast<float>(mLocked.viewport.logicalTop),
81 static_cast<float>(mLocked.viewport.logicalRight - 1),
82 static_cast<float>(mLocked.viewport.logicalBottom - 1),
83 };
Liam Harringtonc782be62020-07-17 19:48:24 +000084}
85
86void MouseCursorController::move(float deltaX, float deltaY) {
87#if DEBUG_MOUSE_CURSOR_UPDATES
88 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
89#endif
90 if (deltaX == 0.0f && deltaY == 0.0f) {
91 return;
92 }
93
94 std::scoped_lock lock(mLock);
95
96 setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
97}
98
Liam Harringtonc782be62020-07-17 19:48:24 +000099void MouseCursorController::setPosition(float x, float y) {
100#if DEBUG_MOUSE_CURSOR_UPDATES
101 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
102#endif
103 std::scoped_lock lock(mLock);
104 setPositionLocked(x, y);
105}
106
107void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) {
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000108 const auto bounds = getBoundsLocked();
109 if (!bounds) return;
110
111 mLocked.pointerX = std::max(bounds->left, std::min(bounds->right, x));
112 mLocked.pointerY = std::max(bounds->top, std::min(bounds->bottom, y));
113
114 updatePointerLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000115}
116
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000117FloatPoint MouseCursorController::getPosition() const {
Liam Harringtonc782be62020-07-17 19:48:24 +0000118 std::scoped_lock lock(mLock);
119
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000120 return {mLocked.pointerX, mLocked.pointerY};
Liam Harringtonc782be62020-07-17 19:48:24 +0000121}
122
Linnan Li0defadf2024-05-05 19:17:05 +0800123ui::LogicalDisplayId MouseCursorController::getDisplayId() const {
Liam Harringtonc782be62020-07-17 19:48:24 +0000124 std::scoped_lock lock(mLock);
125 return mLocked.viewport.displayId;
126}
127
128void MouseCursorController::fade(PointerControllerInterface::Transition transition) {
129 std::scoped_lock lock(mLock);
130
131 // Remove the inactivity timeout, since we are fading now.
132 mContext.removeInactivityTimeout();
133
134 // Start fading.
135 if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
136 mLocked.pointerFadeDirection = 0;
137 mLocked.pointerAlpha = 0.0f;
138 updatePointerLocked();
139 } else {
140 mLocked.pointerFadeDirection = -1;
Liam Harringtonce637132020-08-14 04:00:11 +0000141 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000142 }
143}
144
145void MouseCursorController::unfade(PointerControllerInterface::Transition transition) {
146 std::scoped_lock lock(mLock);
147
148 // Always reset the inactivity timer.
149 mContext.resetInactivityTimeout();
150
151 // Start unfading.
152 if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
153 mLocked.pointerFadeDirection = 0;
154 mLocked.pointerAlpha = 1.0f;
155 updatePointerLocked();
156 } else {
157 mLocked.pointerFadeDirection = 1;
Liam Harringtonce637132020-08-14 04:00:11 +0000158 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000159 }
160}
161
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900162void MouseCursorController::setStylusHoverMode(bool stylusHoverMode) {
163 std::scoped_lock lock(mLock);
164
165 if (mLocked.stylusHoverMode != stylusHoverMode) {
166 mLocked.stylusHoverMode = stylusHoverMode;
167 mLocked.updatePointerIcon = true;
168 }
169}
170
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000171void MouseCursorController::setSkipScreenshot(bool skip) {
172 std::scoped_lock lock(mLock);
173 if (mLocked.skipScreenshot == skip) {
174 return;
175 }
176 mLocked.skipScreenshot = skip;
177 updatePointerLocked();
178}
179
Liam Harringtonc782be62020-07-17 19:48:24 +0000180void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) {
181 std::scoped_lock lock(mLock);
182
183 loadResourcesLocked(getAdditionalMouseResources);
184 updatePointerLocked();
185}
186
187/**
188 * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
189 * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
190 */
191static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
192 width = viewport.deviceWidth;
193 height = viewport.deviceHeight;
194
Michael Wrightecde4d02022-11-25 00:20:19 +0000195 if (viewport.orientation == ui::ROTATION_90 || viewport.orientation == ui::ROTATION_270) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000196 std::swap(width, height);
197 }
198}
199
200void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport,
201 bool getAdditionalMouseResources) {
202 std::scoped_lock lock(mLock);
203
204 if (viewport == mLocked.viewport) {
205 return;
206 }
207
208 const DisplayViewport oldViewport = mLocked.viewport;
209 mLocked.viewport = viewport;
210
211 int32_t oldDisplayWidth, oldDisplayHeight;
212 getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
213 int32_t newDisplayWidth, newDisplayHeight;
214 getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
215
216 // Reset cursor position to center if size or display changed.
217 if (oldViewport.displayId != viewport.displayId || oldDisplayWidth != newDisplayWidth ||
218 oldDisplayHeight != newDisplayHeight) {
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000219 if (const auto bounds = getBoundsLocked(); bounds) {
220 mLocked.pointerX = (bounds->left + bounds->right) * 0.5f;
221 mLocked.pointerY = (bounds->top + bounds->bottom) * 0.5f;
Liam Harringtonc782be62020-07-17 19:48:24 +0000222 // Reload icon resources for density may be changed.
223 loadResourcesLocked(getAdditionalMouseResources);
224 } else {
225 mLocked.pointerX = 0;
226 mLocked.pointerY = 0;
227 }
228 } else if (oldViewport.orientation != viewport.orientation) {
229 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
230 // This creates an invariant frame of reference that we can easily rotate when
231 // taking into account that the pointer may be located at fractional pixel offsets.
232 float x = mLocked.pointerX + 0.5f;
233 float y = mLocked.pointerY + 0.5f;
234 float temp;
235
236 // Undo the previous rotation.
237 switch (oldViewport.orientation) {
Michael Wrightecde4d02022-11-25 00:20:19 +0000238 case ui::ROTATION_90:
Liam Harringtonc782be62020-07-17 19:48:24 +0000239 temp = x;
240 x = oldViewport.deviceHeight - y;
241 y = temp;
242 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000243 case ui::ROTATION_180:
Liam Harringtonc782be62020-07-17 19:48:24 +0000244 x = oldViewport.deviceWidth - x;
245 y = oldViewport.deviceHeight - y;
246 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000247 case ui::ROTATION_270:
Liam Harringtonc782be62020-07-17 19:48:24 +0000248 temp = x;
249 x = y;
250 y = oldViewport.deviceWidth - temp;
251 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000252 case ui::ROTATION_0:
253 break;
Liam Harringtonc782be62020-07-17 19:48:24 +0000254 }
255
256 // Perform the new rotation.
257 switch (viewport.orientation) {
Michael Wrightecde4d02022-11-25 00:20:19 +0000258 case ui::ROTATION_90:
Liam Harringtonc782be62020-07-17 19:48:24 +0000259 temp = x;
260 x = y;
261 y = viewport.deviceHeight - temp;
262 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000263 case ui::ROTATION_180:
Liam Harringtonc782be62020-07-17 19:48:24 +0000264 x = viewport.deviceWidth - x;
265 y = viewport.deviceHeight - y;
266 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000267 case ui::ROTATION_270:
Liam Harringtonc782be62020-07-17 19:48:24 +0000268 temp = x;
269 x = viewport.deviceWidth - y;
270 y = temp;
271 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000272 case ui::ROTATION_0:
273 break;
Liam Harringtonc782be62020-07-17 19:48:24 +0000274 }
275
276 // Apply offsets to convert from the pixel center to the pixel top-left corner position
277 // and save the results.
278 mLocked.pointerX = x - 0.5f;
279 mLocked.pointerY = y - 0.5f;
280 }
281
282 updatePointerLocked();
283}
284
Brandon Pollack015f5d92022-06-02 06:59:33 +0000285void MouseCursorController::updatePointerIcon(PointerIconStyle iconId) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000286 std::scoped_lock lock(mLock);
287
288 if (mLocked.requestedPointerType != iconId) {
289 mLocked.requestedPointerType = iconId;
290 mLocked.updatePointerIcon = true;
291 updatePointerLocked();
292 }
293}
294
295void MouseCursorController::setCustomPointerIcon(const SpriteIcon& icon) {
296 std::scoped_lock lock(mLock);
297
Brandon Pollack015f5d92022-06-02 06:59:33 +0000298 const PointerIconStyle iconId = mContext.getPolicy()->getCustomPointerIconId();
Liam Harringtonc782be62020-07-17 19:48:24 +0000299 mLocked.additionalMouseResources[iconId] = icon;
300 mLocked.requestedPointerType = iconId;
301 mLocked.updatePointerIcon = true;
302 updatePointerLocked();
303}
304
Liam Harringtonce637132020-08-14 04:00:11 +0000305bool MouseCursorController::doFadingAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000306 nsecs_t frameDelay = timestamp - mContext.getAnimationTime();
Liam Harringtonce637132020-08-14 04:00:11 +0000307 bool keepAnimating = false;
Liam Harringtonc782be62020-07-17 19:48:24 +0000308
309 // Animate pointer fade.
310 if (mLocked.pointerFadeDirection < 0) {
311 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
312 if (mLocked.pointerAlpha <= 0.0f) {
313 mLocked.pointerAlpha = 0.0f;
314 mLocked.pointerFadeDirection = 0;
315 } else {
316 keepAnimating = true;
317 }
318 updatePointerLocked();
319 } else if (mLocked.pointerFadeDirection > 0) {
320 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
321 if (mLocked.pointerAlpha >= 1.0f) {
322 mLocked.pointerAlpha = 1.0f;
323 mLocked.pointerFadeDirection = 0;
324 } else {
325 keepAnimating = true;
326 }
327 updatePointerLocked();
328 }
Liam Harringtonc782be62020-07-17 19:48:24 +0000329 return keepAnimating;
330}
331
Liam Harringtonce637132020-08-14 04:00:11 +0000332bool MouseCursorController::doBitmapAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000333 std::map<PointerIconStyle, PointerAnimation>::const_iterator iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900334 mLocked.animationResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000335 if (iter == mLocked.animationResources.end()) {
336 return false;
337 }
338
339 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000340 auto& spriteController = mContext.getSpriteController();
341 spriteController.openTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000342
343 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
344 mLocked.animationFrameIndex += incr;
345 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
346 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
347 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
348 }
349 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
350
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000351 spriteController.closeTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000352 }
Liam Harringtonc782be62020-07-17 19:48:24 +0000353 // Keep animating.
354 return true;
355}
356
357void MouseCursorController::updatePointerLocked() REQUIRES(mLock) {
358 if (!mLocked.viewport.isValid()) {
359 return;
360 }
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000361 auto& spriteController = mContext.getSpriteController();
362 spriteController.openTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000363
364 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
365 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
366 mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000367 mLocked.pointerSprite->setSkipScreenshot(mLocked.skipScreenshot);
Liam Harringtonc782be62020-07-17 19:48:24 +0000368
369 if (mLocked.pointerAlpha > 0) {
370 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
371 mLocked.pointerSprite->setVisible(true);
372 } else {
373 mLocked.pointerSprite->setVisible(false);
374 }
375
376 if (mLocked.updatePointerIcon) {
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900377 mLocked.resolvedPointerType = mLocked.requestedPointerType;
378 const PointerIconStyle defaultPointerIconId =
379 mContext.getPolicy()->getDefaultPointerIconId();
380 if (mLocked.resolvedPointerType == PointerIconStyle::TYPE_NOT_SPECIFIED) {
381 mLocked.resolvedPointerType = mLocked.stylusHoverMode
382 ? mContext.getPolicy()->getDefaultStylusIconId()
383 : defaultPointerIconId;
384 }
385
386 if (mLocked.resolvedPointerType == defaultPointerIconId) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000387 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
388 } else {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000389 std::map<PointerIconStyle, SpriteIcon>::const_iterator iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900390 mLocked.additionalMouseResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000391 if (iter != mLocked.additionalMouseResources.end()) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000392 std::map<PointerIconStyle, PointerAnimation>::const_iterator anim_iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900393 mLocked.animationResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000394 if (anim_iter != mLocked.animationResources.end()) {
395 mLocked.animationFrameIndex = 0;
396 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
Liam Harringtonce637132020-08-14 04:00:11 +0000397 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000398 }
399 mLocked.pointerSprite->setIcon(iter->second);
400 } else {
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900401 ALOGW("Can't find the resource for icon id %d", mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000402 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
403 }
404 }
405 mLocked.updatePointerIcon = false;
406 }
407
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000408 spriteController.closeTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000409}
410
411void MouseCursorController::loadResourcesLocked(bool getAdditionalMouseResources) REQUIRES(mLock) {
412 if (!mLocked.viewport.isValid()) {
413 return;
414 }
415
416 if (!mLocked.resourcesLoaded) mLocked.resourcesLoaded = true;
417
418 sp<PointerControllerPolicyInterface> policy = mContext.getPolicy();
419 policy->loadPointerResources(&mResources, mLocked.viewport.displayId);
420 policy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
421
422 mLocked.additionalMouseResources.clear();
423 mLocked.animationResources.clear();
424 if (getAdditionalMouseResources) {
425 policy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
426 &mLocked.animationResources,
427 mLocked.viewport.displayId);
428 }
429
430 mLocked.updatePointerIcon = true;
431}
432
433bool MouseCursorController::isViewportValid() {
434 std::scoped_lock lock(mLock);
435 return mLocked.viewport.isValid();
436}
437
438void MouseCursorController::getAdditionalMouseResources() {
439 std::scoped_lock lock(mLock);
440
441 if (mLocked.additionalMouseResources.empty()) {
442 mContext.getPolicy()->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
443 &mLocked.animationResources,
444 mLocked.viewport.displayId);
445 }
446 mLocked.updatePointerIcon = true;
447 updatePointerLocked();
448}
449
450bool MouseCursorController::resourcesLoaded() {
451 std::scoped_lock lock(mLock);
452 return mLocked.resourcesLoaded;
453}
454
Arpit Singh05215af2024-08-25 17:49:32 +0000455std::string MouseCursorController::dump() const {
456 std::string dump = INDENT "MouseCursorController:\n";
457 std::scoped_lock lock(mLock);
458 dump += StringPrintf(INDENT2 "viewport: %s\n", mLocked.viewport.toString().c_str());
459 dump += StringPrintf(INDENT2 "stylusHoverMode: %s\n",
460 mLocked.stylusHoverMode ? "true" : "false");
461 dump += StringPrintf(INDENT2 "pointerFadeDirection: %d\n", mLocked.pointerFadeDirection);
462 dump += StringPrintf(INDENT2 "updatePointerIcon: %s\n",
463 mLocked.updatePointerIcon ? "true" : "false");
464 dump += StringPrintf(INDENT2 "resourcesLoaded: %s\n",
465 mLocked.resourcesLoaded ? "true" : "false");
466 dump += StringPrintf(INDENT2 "requestedPointerType: %d\n", mLocked.requestedPointerType);
467 dump += StringPrintf(INDENT2 "resolvedPointerType: %d\n", mLocked.resolvedPointerType);
468 dump += StringPrintf(INDENT2 "skipScreenshot: %s\n", mLocked.skipScreenshot ? "true" : "false");
469 dump += StringPrintf(INDENT2 "animating: %s\n", mLocked.animating ? "true" : "false");
470 return dump;
471}
472
Liam Harringtonce637132020-08-14 04:00:11 +0000473bool MouseCursorController::doAnimations(nsecs_t timestamp) {
474 std::scoped_lock lock(mLock);
475 bool keepFading = doFadingAnimationLocked(timestamp);
476 bool keepBitmap = doBitmapAnimationLocked(timestamp);
477 bool keepAnimating = keepFading || keepBitmap;
478 if (!keepAnimating) {
479 /*
480 * We know that this callback will be removed before another
481 * is added. mLock in PointerAnimator will not be released
482 * until after this is removed, and adding another callback
483 * requires that lock. Thus it's safe to set mLocked.animating
484 * here.
485 */
486 mLocked.animating = false;
487 }
488 return keepAnimating;
489}
490
491void MouseCursorController::startAnimationLocked() REQUIRES(mLock) {
492 using namespace std::placeholders;
493
494 if (mLocked.animating) {
495 return;
496 }
497 mLocked.animating = true;
498
499 std::function<bool(nsecs_t)> func = std::bind(&MouseCursorController::doAnimations, this, _1);
500 /*
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700501 * Using ui::LogicalDisplayId::INVALID for displayId here to avoid removing the callback
Liam Harringtonce637132020-08-14 04:00:11 +0000502 * if a TouchSpotController with the same display is removed.
503 */
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700504 mContext.addAnimationCallback(ui::LogicalDisplayId::INVALID, func);
Liam Harringtonce637132020-08-14 04:00:11 +0000505}
506
Liam Harringtonc782be62020-07-17 19:48:24 +0000507} // namespace android