blob: d993b87152608b70f8c4e39a1ea53fded6f50e6a [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
Arpit Singh24c8ba62024-10-25 21:08:08 +000034} // namespace
Liam Harringtonc782be62020-07-17 19:48:24 +000035
Liana Kazanova (xWF)a1d4fe02024-11-18 19:14:42 +000036namespace android {
37
Liam Harringtonc782be62020-07-17 19:48:24 +000038// --- 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
Liana Kazanova (xWF)a1d4fe02024-11-18 19:14:42 +000067void MouseCursorController::move(float deltaX, float deltaY) {
Liam Harringtonc782be62020-07-17 19:48:24 +000068#if DEBUG_MOUSE_CURSOR_UPDATES
69 ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
70#endif
71 if (deltaX == 0.0f && deltaY == 0.0f) {
Liana Kazanova (xWF)a1d4fe02024-11-18 19:14:42 +000072 return;
Liam Harringtonc782be62020-07-17 19:48:24 +000073 }
74
75 std::scoped_lock lock(mLock);
Liana Kazanova (xWF)a1d4fe02024-11-18 19:14:42 +000076
77 setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
Liam Harringtonc782be62020-07-17 19:48:24 +000078}
79
Liam Harringtonc782be62020-07-17 19:48:24 +000080void MouseCursorController::setPosition(float x, float y) {
81#if DEBUG_MOUSE_CURSOR_UPDATES
82 ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
83#endif
84 std::scoped_lock lock(mLock);
85 setPositionLocked(x, y);
86}
87
Liana Kazanova (xWF)a1d4fe02024-11-18 19:14:42 +000088void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) {
89 const auto& v = mLocked.viewport;
90 if (!v.isValid()) return;
91
Prabir Pradhaneb0c5072024-09-09 19:53:06 +000092 // The valid bounds for a mouse cursor. Since the right and bottom edges are considered outside
93 // the display, clip the bounds by one pixel instead of letting the cursor get arbitrarily
94 // close to the outside edge.
Liana Kazanova (xWF)a1d4fe02024-11-18 19:14:42 +000095 const FloatRect bounds{
Prabir Pradhaneb0c5072024-09-09 19:53:06 +000096 static_cast<float>(mLocked.viewport.logicalLeft),
97 static_cast<float>(mLocked.viewport.logicalTop),
98 static_cast<float>(mLocked.viewport.logicalRight - 1),
99 static_cast<float>(mLocked.viewport.logicalBottom - 1),
100 };
101 mLocked.pointerX = std::max(bounds.left, std::min(bounds.right, x));
102 mLocked.pointerY = std::max(bounds.top, std::min(bounds.bottom, y));
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000103
104 updatePointerLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000105}
106
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000107FloatPoint MouseCursorController::getPosition() const {
Liam Harringtonc782be62020-07-17 19:48:24 +0000108 std::scoped_lock lock(mLock);
109
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000110 return {mLocked.pointerX, mLocked.pointerY};
Liam Harringtonc782be62020-07-17 19:48:24 +0000111}
112
Linnan Li0defadf2024-05-05 19:17:05 +0800113ui::LogicalDisplayId MouseCursorController::getDisplayId() const {
Liam Harringtonc782be62020-07-17 19:48:24 +0000114 std::scoped_lock lock(mLock);
115 return mLocked.viewport.displayId;
116}
117
118void MouseCursorController::fade(PointerControllerInterface::Transition transition) {
119 std::scoped_lock lock(mLock);
120
121 // Remove the inactivity timeout, since we are fading now.
122 mContext.removeInactivityTimeout();
123
124 // Start fading.
125 if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
126 mLocked.pointerFadeDirection = 0;
127 mLocked.pointerAlpha = 0.0f;
128 updatePointerLocked();
129 } else {
130 mLocked.pointerFadeDirection = -1;
Liam Harringtonce637132020-08-14 04:00:11 +0000131 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000132 }
133}
134
135void MouseCursorController::unfade(PointerControllerInterface::Transition transition) {
136 std::scoped_lock lock(mLock);
137
138 // Always reset the inactivity timer.
139 mContext.resetInactivityTimeout();
140
141 // Start unfading.
142 if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
143 mLocked.pointerFadeDirection = 0;
144 mLocked.pointerAlpha = 1.0f;
145 updatePointerLocked();
146 } else {
147 mLocked.pointerFadeDirection = 1;
Liam Harringtonce637132020-08-14 04:00:11 +0000148 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000149 }
150}
151
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900152void MouseCursorController::setStylusHoverMode(bool stylusHoverMode) {
153 std::scoped_lock lock(mLock);
154
155 if (mLocked.stylusHoverMode != stylusHoverMode) {
156 mLocked.stylusHoverMode = stylusHoverMode;
157 mLocked.updatePointerIcon = true;
158 }
159}
160
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000161void MouseCursorController::setSkipScreenshot(bool skip) {
162 std::scoped_lock lock(mLock);
163 if (mLocked.skipScreenshot == skip) {
164 return;
165 }
166 mLocked.skipScreenshot = skip;
167 updatePointerLocked();
168}
169
Liam Harringtonc782be62020-07-17 19:48:24 +0000170void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) {
171 std::scoped_lock lock(mLock);
172
173 loadResourcesLocked(getAdditionalMouseResources);
174 updatePointerLocked();
175}
176
177/**
178 * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
179 * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
180 */
181static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
182 width = viewport.deviceWidth;
183 height = viewport.deviceHeight;
184
Michael Wrightecde4d02022-11-25 00:20:19 +0000185 if (viewport.orientation == ui::ROTATION_90 || viewport.orientation == ui::ROTATION_270) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000186 std::swap(width, height);
187 }
188}
189
190void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport,
191 bool getAdditionalMouseResources) {
192 std::scoped_lock lock(mLock);
193
194 if (viewport == mLocked.viewport) {
195 return;
196 }
197
198 const DisplayViewport oldViewport = mLocked.viewport;
199 mLocked.viewport = viewport;
200
201 int32_t oldDisplayWidth, oldDisplayHeight;
202 getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
203 int32_t newDisplayWidth, newDisplayHeight;
204 getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
205
206 // Reset cursor position to center if size or display changed.
207 if (oldViewport.displayId != viewport.displayId || oldDisplayWidth != newDisplayWidth ||
208 oldDisplayHeight != newDisplayHeight) {
Prabir Pradhaneb0c5072024-09-09 19:53:06 +0000209 if (viewport.isValid()) {
210 // Use integer coordinates as the starting point for the cursor location.
211 // We usually expect display sizes to be even numbers, so the flooring is precautionary.
212 mLocked.pointerX = std::floor((viewport.logicalLeft + viewport.logicalRight) / 2);
213 mLocked.pointerY = std::floor((viewport.logicalTop + viewport.logicalBottom) / 2);
Liam Harringtonc782be62020-07-17 19:48:24 +0000214 // Reload icon resources for density may be changed.
215 loadResourcesLocked(getAdditionalMouseResources);
216 } else {
217 mLocked.pointerX = 0;
218 mLocked.pointerY = 0;
219 }
220 } else if (oldViewport.orientation != viewport.orientation) {
221 // Apply offsets to convert from the pixel top-left corner position to the pixel center.
222 // This creates an invariant frame of reference that we can easily rotate when
223 // taking into account that the pointer may be located at fractional pixel offsets.
224 float x = mLocked.pointerX + 0.5f;
225 float y = mLocked.pointerY + 0.5f;
226 float temp;
227
228 // Undo the previous rotation.
229 switch (oldViewport.orientation) {
Michael Wrightecde4d02022-11-25 00:20:19 +0000230 case ui::ROTATION_90:
Liam Harringtonc782be62020-07-17 19:48:24 +0000231 temp = x;
232 x = oldViewport.deviceHeight - y;
233 y = temp;
234 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000235 case ui::ROTATION_180:
Liam Harringtonc782be62020-07-17 19:48:24 +0000236 x = oldViewport.deviceWidth - x;
237 y = oldViewport.deviceHeight - y;
238 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000239 case ui::ROTATION_270:
Liam Harringtonc782be62020-07-17 19:48:24 +0000240 temp = x;
241 x = y;
242 y = oldViewport.deviceWidth - temp;
243 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000244 case ui::ROTATION_0:
245 break;
Liam Harringtonc782be62020-07-17 19:48:24 +0000246 }
247
248 // Perform the new rotation.
249 switch (viewport.orientation) {
Michael Wrightecde4d02022-11-25 00:20:19 +0000250 case ui::ROTATION_90:
Liam Harringtonc782be62020-07-17 19:48:24 +0000251 temp = x;
252 x = y;
253 y = viewport.deviceHeight - temp;
254 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000255 case ui::ROTATION_180:
Liam Harringtonc782be62020-07-17 19:48:24 +0000256 x = viewport.deviceWidth - x;
257 y = viewport.deviceHeight - y;
258 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000259 case ui::ROTATION_270:
Liam Harringtonc782be62020-07-17 19:48:24 +0000260 temp = x;
261 x = viewport.deviceWidth - y;
262 y = temp;
263 break;
Michael Wrightecde4d02022-11-25 00:20:19 +0000264 case ui::ROTATION_0:
265 break;
Liam Harringtonc782be62020-07-17 19:48:24 +0000266 }
267
268 // Apply offsets to convert from the pixel center to the pixel top-left corner position
269 // and save the results.
270 mLocked.pointerX = x - 0.5f;
271 mLocked.pointerY = y - 0.5f;
272 }
273
274 updatePointerLocked();
275}
276
Brandon Pollack015f5d92022-06-02 06:59:33 +0000277void MouseCursorController::updatePointerIcon(PointerIconStyle iconId) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000278 std::scoped_lock lock(mLock);
279
280 if (mLocked.requestedPointerType != iconId) {
281 mLocked.requestedPointerType = iconId;
282 mLocked.updatePointerIcon = true;
283 updatePointerLocked();
284 }
285}
286
287void MouseCursorController::setCustomPointerIcon(const SpriteIcon& icon) {
288 std::scoped_lock lock(mLock);
289
Brandon Pollack015f5d92022-06-02 06:59:33 +0000290 const PointerIconStyle iconId = mContext.getPolicy()->getCustomPointerIconId();
Liam Harringtonc782be62020-07-17 19:48:24 +0000291 mLocked.additionalMouseResources[iconId] = icon;
292 mLocked.requestedPointerType = iconId;
293 mLocked.updatePointerIcon = true;
294 updatePointerLocked();
295}
296
Liam Harringtonce637132020-08-14 04:00:11 +0000297bool MouseCursorController::doFadingAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000298 nsecs_t frameDelay = timestamp - mContext.getAnimationTime();
Liam Harringtonce637132020-08-14 04:00:11 +0000299 bool keepAnimating = false;
Liam Harringtonc782be62020-07-17 19:48:24 +0000300
301 // Animate pointer fade.
302 if (mLocked.pointerFadeDirection < 0) {
303 mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
304 if (mLocked.pointerAlpha <= 0.0f) {
305 mLocked.pointerAlpha = 0.0f;
306 mLocked.pointerFadeDirection = 0;
307 } else {
308 keepAnimating = true;
309 }
310 updatePointerLocked();
311 } else if (mLocked.pointerFadeDirection > 0) {
312 mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
313 if (mLocked.pointerAlpha >= 1.0f) {
314 mLocked.pointerAlpha = 1.0f;
315 mLocked.pointerFadeDirection = 0;
316 } else {
317 keepAnimating = true;
318 }
319 updatePointerLocked();
320 }
Liam Harringtonc782be62020-07-17 19:48:24 +0000321 return keepAnimating;
322}
323
Liam Harringtonce637132020-08-14 04:00:11 +0000324bool MouseCursorController::doBitmapAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000325 std::map<PointerIconStyle, PointerAnimation>::const_iterator iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900326 mLocked.animationResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000327 if (iter == mLocked.animationResources.end()) {
328 return false;
329 }
330
331 if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000332 auto& spriteController = mContext.getSpriteController();
333 spriteController.openTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000334
335 int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
336 mLocked.animationFrameIndex += incr;
337 mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
338 while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
339 mLocked.animationFrameIndex -= iter->second.animationFrames.size();
340 }
341 mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
342
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000343 spriteController.closeTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000344 }
Liam Harringtonc782be62020-07-17 19:48:24 +0000345 // Keep animating.
346 return true;
347}
348
349void MouseCursorController::updatePointerLocked() REQUIRES(mLock) {
350 if (!mLocked.viewport.isValid()) {
351 return;
352 }
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000353 auto& spriteController = mContext.getSpriteController();
354 spriteController.openTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000355
356 mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
357 mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
358 mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000359 mLocked.pointerSprite->setSkipScreenshot(mLocked.skipScreenshot);
Liam Harringtonc782be62020-07-17 19:48:24 +0000360
361 if (mLocked.pointerAlpha > 0) {
362 mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
363 mLocked.pointerSprite->setVisible(true);
364 } else {
365 mLocked.pointerSprite->setVisible(false);
366 }
367
368 if (mLocked.updatePointerIcon) {
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900369 mLocked.resolvedPointerType = mLocked.requestedPointerType;
370 const PointerIconStyle defaultPointerIconId =
371 mContext.getPolicy()->getDefaultPointerIconId();
372 if (mLocked.resolvedPointerType == PointerIconStyle::TYPE_NOT_SPECIFIED) {
373 mLocked.resolvedPointerType = mLocked.stylusHoverMode
374 ? mContext.getPolicy()->getDefaultStylusIconId()
375 : defaultPointerIconId;
376 }
377
378 if (mLocked.resolvedPointerType == defaultPointerIconId) {
Liam Harringtonc782be62020-07-17 19:48:24 +0000379 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
380 } else {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000381 std::map<PointerIconStyle, SpriteIcon>::const_iterator iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900382 mLocked.additionalMouseResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000383 if (iter != mLocked.additionalMouseResources.end()) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000384 std::map<PointerIconStyle, PointerAnimation>::const_iterator anim_iter =
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900385 mLocked.animationResources.find(mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000386 if (anim_iter != mLocked.animationResources.end()) {
387 mLocked.animationFrameIndex = 0;
388 mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
Liam Harringtonce637132020-08-14 04:00:11 +0000389 startAnimationLocked();
Liam Harringtonc782be62020-07-17 19:48:24 +0000390 }
391 mLocked.pointerSprite->setIcon(iter->second);
392 } else {
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900393 ALOGW("Can't find the resource for icon id %d", mLocked.resolvedPointerType);
Liam Harringtonc782be62020-07-17 19:48:24 +0000394 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
395 }
396 }
397 mLocked.updatePointerIcon = false;
398 }
399
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000400 spriteController.closeTransaction();
Liam Harringtonc782be62020-07-17 19:48:24 +0000401}
402
403void MouseCursorController::loadResourcesLocked(bool getAdditionalMouseResources) REQUIRES(mLock) {
404 if (!mLocked.viewport.isValid()) {
405 return;
406 }
407
408 if (!mLocked.resourcesLoaded) mLocked.resourcesLoaded = true;
409
410 sp<PointerControllerPolicyInterface> policy = mContext.getPolicy();
411 policy->loadPointerResources(&mResources, mLocked.viewport.displayId);
412 policy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
413
414 mLocked.additionalMouseResources.clear();
415 mLocked.animationResources.clear();
416 if (getAdditionalMouseResources) {
417 policy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
418 &mLocked.animationResources,
419 mLocked.viewport.displayId);
420 }
421
422 mLocked.updatePointerIcon = true;
423}
424
425bool MouseCursorController::isViewportValid() {
426 std::scoped_lock lock(mLock);
427 return mLocked.viewport.isValid();
428}
429
430void MouseCursorController::getAdditionalMouseResources() {
431 std::scoped_lock lock(mLock);
432
433 if (mLocked.additionalMouseResources.empty()) {
434 mContext.getPolicy()->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
435 &mLocked.animationResources,
436 mLocked.viewport.displayId);
437 }
438 mLocked.updatePointerIcon = true;
439 updatePointerLocked();
440}
441
442bool MouseCursorController::resourcesLoaded() {
443 std::scoped_lock lock(mLock);
444 return mLocked.resourcesLoaded;
445}
446
Arpit Singh05215af2024-08-25 17:49:32 +0000447std::string MouseCursorController::dump() const {
448 std::string dump = INDENT "MouseCursorController:\n";
449 std::scoped_lock lock(mLock);
450 dump += StringPrintf(INDENT2 "viewport: %s\n", mLocked.viewport.toString().c_str());
451 dump += StringPrintf(INDENT2 "stylusHoverMode: %s\n",
452 mLocked.stylusHoverMode ? "true" : "false");
453 dump += StringPrintf(INDENT2 "pointerFadeDirection: %d\n", mLocked.pointerFadeDirection);
454 dump += StringPrintf(INDENT2 "updatePointerIcon: %s\n",
455 mLocked.updatePointerIcon ? "true" : "false");
456 dump += StringPrintf(INDENT2 "resourcesLoaded: %s\n",
457 mLocked.resourcesLoaded ? "true" : "false");
458 dump += StringPrintf(INDENT2 "requestedPointerType: %d\n", mLocked.requestedPointerType);
459 dump += StringPrintf(INDENT2 "resolvedPointerType: %d\n", mLocked.resolvedPointerType);
460 dump += StringPrintf(INDENT2 "skipScreenshot: %s\n", mLocked.skipScreenshot ? "true" : "false");
461 dump += StringPrintf(INDENT2 "animating: %s\n", mLocked.animating ? "true" : "false");
462 return dump;
463}
464
Liam Harringtonce637132020-08-14 04:00:11 +0000465bool MouseCursorController::doAnimations(nsecs_t timestamp) {
466 std::scoped_lock lock(mLock);
467 bool keepFading = doFadingAnimationLocked(timestamp);
468 bool keepBitmap = doBitmapAnimationLocked(timestamp);
469 bool keepAnimating = keepFading || keepBitmap;
470 if (!keepAnimating) {
471 /*
472 * We know that this callback will be removed before another
473 * is added. mLock in PointerAnimator will not be released
474 * until after this is removed, and adding another callback
475 * requires that lock. Thus it's safe to set mLocked.animating
476 * here.
477 */
478 mLocked.animating = false;
479 }
480 return keepAnimating;
481}
482
483void MouseCursorController::startAnimationLocked() REQUIRES(mLock) {
484 using namespace std::placeholders;
485
486 if (mLocked.animating) {
487 return;
488 }
489 mLocked.animating = true;
490
491 std::function<bool(nsecs_t)> func = std::bind(&MouseCursorController::doAnimations, this, _1);
492 /*
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700493 * Using ui::LogicalDisplayId::INVALID for displayId here to avoid removing the callback
Liam Harringtonce637132020-08-14 04:00:11 +0000494 * if a TouchSpotController with the same display is removed.
495 */
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700496 mContext.addAnimationCallback(ui::LogicalDisplayId::INVALID, func);
Liam Harringtonce637132020-08-14 04:00:11 +0000497}
498
Liam Harringtonc782be62020-07-17 19:48:24 +0000499} // namespace android