blob: a3d0c2b4888daccbfe95bdeaf59312ec663aa866 [file] [log] [blame]
Prabir Pradhanb56e92c2023-06-09 23:40:37 +00001/*
2 * Copyright 2023 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 "PointerChoreographer"
18
Byoungho Jungda10dd32023-10-06 17:03:45 +090019#include <android-base/logging.h>
Arpit Singh4b6ad2d2024-04-04 11:54:20 +000020#include <com_android_input_flags.h>
21#if defined(__ANDROID__)
22#include <gui/SurfaceComposerClient.h>
23#endif
Byoungho Jungda10dd32023-10-06 17:03:45 +090024#include <input/PrintTools.h>
Arpit Singh4b6ad2d2024-04-04 11:54:20 +000025#include <unordered_set>
Byoungho Jungda10dd32023-10-06 17:03:45 +090026
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000027#include "PointerChoreographer.h"
28
Byoungho Jungda10dd32023-10-06 17:03:45 +090029#define INDENT " "
30
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000031namespace android {
32
Arpit Singh4b6ad2d2024-04-04 11:54:20 +000033namespace input_flags = com::android::input::flags;
34static const bool HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS =
35 input_flags::hide_pointer_indicators_for_secure_windows();
36
Byoungho Jungda10dd32023-10-06 17:03:45 +090037namespace {
Prabir Pradhan5a51a222024-03-05 03:54:00 +000038
Byoungho Jungda10dd32023-10-06 17:03:45 +090039bool isFromMouse(const NotifyMotionArgs& args) {
40 return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
41 args.pointerProperties[0].toolType == ToolType::MOUSE;
42}
43
Byoungho Jungee6268f2023-10-30 17:27:26 +090044bool isFromTouchpad(const NotifyMotionArgs& args) {
45 return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
46 args.pointerProperties[0].toolType == ToolType::FINGER;
47}
48
Prabir Pradhan4c977a42024-03-15 16:47:37 +000049bool isFromDrawingTablet(const NotifyMotionArgs& args) {
50 return isFromSource(args.source, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS) &&
51 isStylusToolType(args.pointerProperties[0].toolType);
52}
53
Byoungho Jungd6fe27b2023-10-27 20:49:38 +090054bool isHoverAction(int32_t action) {
55 return action == AMOTION_EVENT_ACTION_HOVER_ENTER ||
56 action == AMOTION_EVENT_ACTION_HOVER_MOVE || action == AMOTION_EVENT_ACTION_HOVER_EXIT;
57}
58
59bool isStylusHoverEvent(const NotifyMotionArgs& args) {
60 return isStylusEvent(args.source, args.pointerProperties) && isHoverAction(args.action);
61}
Prabir Pradhan5a51a222024-03-05 03:54:00 +000062
Prabir Pradhan4c977a42024-03-15 16:47:37 +000063bool isMouseOrTouchpad(uint32_t sources) {
64 // Check if this is a mouse or touchpad, but not a drawing tablet.
65 return isFromSource(sources, AINPUT_SOURCE_MOUSE_RELATIVE) ||
66 (isFromSource(sources, AINPUT_SOURCE_MOUSE) &&
67 !isFromSource(sources, AINPUT_SOURCE_STYLUS));
68}
69
Prabir Pradhan5a51a222024-03-05 03:54:00 +000070inline void notifyPointerDisplayChange(std::optional<std::tuple<int32_t, FloatPoint>> change,
71 PointerChoreographerPolicyInterface& policy) {
72 if (!change) {
73 return;
74 }
75 const auto& [displayId, cursorPosition] = *change;
76 policy.notifyPointerDisplayIdChanged(displayId, cursorPosition);
77}
78
Prabir Pradhan4c977a42024-03-15 16:47:37 +000079void setIconForController(const std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle>& icon,
80 PointerControllerInterface& controller) {
81 if (std::holds_alternative<std::unique_ptr<SpriteIcon>>(icon)) {
82 if (std::get<std::unique_ptr<SpriteIcon>>(icon) == nullptr) {
83 LOG(FATAL) << "SpriteIcon should not be null";
84 }
85 controller.setCustomPointerIcon(*std::get<std::unique_ptr<SpriteIcon>>(icon));
86 } else {
87 controller.updatePointerIcon(std::get<PointerIconStyle>(icon));
88 }
89}
90
Byoungho Jungda10dd32023-10-06 17:03:45 +090091} // namespace
92
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000093// --- PointerChoreographer ---
94
95PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
96 PointerChoreographerPolicyInterface& policy)
Prabir Pradhan5a51a222024-03-05 03:54:00 +000097 : mTouchControllerConstructor([this]() {
Prabir Pradhan16788792023-11-08 21:07:21 +000098 return mPolicy.createPointerController(
99 PointerControllerInterface::ControllerType::TOUCH);
100 }),
101 mNextListener(listener),
Byoungho Jungda10dd32023-10-06 17:03:45 +0900102 mPolicy(policy),
103 mDefaultMouseDisplayId(ADISPLAY_ID_DEFAULT),
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900104 mNotifiedPointerDisplayId(ADISPLAY_ID_NONE),
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900105 mShowTouchesEnabled(false),
106 mStylusPointerIconEnabled(false) {}
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000107
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000108PointerChoreographer::~PointerChoreographer() {
109 std::scoped_lock _l(mLock);
110 if (mWindowInfoListener == nullptr) {
111 return;
112 }
113 mWindowInfoListener->onPointerChoreographerDestroyed();
114}
115
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000116void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000117 PointerDisplayChange pointerDisplayChange;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900118
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000119 { // acquire lock
120 std::scoped_lock _l(mLock);
121
122 mInputDeviceInfos = args.inputDeviceInfos;
123 pointerDisplayChange = updatePointerControllersLocked();
124 } // release lock
125
126 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000127 mNextListener.notify(args);
128}
129
130void PointerChoreographer::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
131 mNextListener.notify(args);
132}
133
134void PointerChoreographer::notifyKey(const NotifyKeyArgs& args) {
135 mNextListener.notify(args);
136}
137
138void PointerChoreographer::notifyMotion(const NotifyMotionArgs& args) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900139 NotifyMotionArgs newArgs = processMotion(args);
140
141 mNextListener.notify(newArgs);
142}
143
144NotifyMotionArgs PointerChoreographer::processMotion(const NotifyMotionArgs& args) {
145 std::scoped_lock _l(mLock);
146
147 if (isFromMouse(args)) {
148 return processMouseEventLocked(args);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900149 } else if (isFromTouchpad(args)) {
150 return processTouchpadEventLocked(args);
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000151 } else if (isFromDrawingTablet(args)) {
152 processDrawingTabletEventLocked(args);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900153 } else if (mStylusPointerIconEnabled && isStylusHoverEvent(args)) {
154 processStylusHoverEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900155 } else if (isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN)) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900156 processTouchscreenAndStylusEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900157 }
158 return args;
159}
160
161NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotionArgs& args) {
162 if (args.getPointerCount() != 1) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000163 LOG(FATAL) << "Only mouse events with a single pointer are currently supported: "
164 << args.dump();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900165 }
166
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000167 mMouseDevices.emplace(args.deviceId);
Prabir Pradhan990d8712024-03-05 00:31:36 +0000168 auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
Nergi Rahardie0a4cfe2024-03-11 13:18:59 +0900169 NotifyMotionArgs newArgs(args);
170 newArgs.displayId = displayId;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900171
Nergi Rahardie0a4cfe2024-03-11 13:18:59 +0900172 if (MotionEvent::isValidCursorPosition(args.xCursorPosition, args.yCursorPosition)) {
173 // This is an absolute mouse device that knows about the location of the cursor on the
174 // display, so set the cursor position to the specified location.
175 const auto [x, y] = pc.getPosition();
176 const float deltaX = args.xCursorPosition - x;
177 const float deltaY = args.yCursorPosition - y;
178 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
179 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
180 pc.setPosition(args.xCursorPosition, args.yCursorPosition);
181 } else {
182 // This is a relative mouse, so move the cursor by the specified amount.
183 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
184 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
185 pc.move(deltaX, deltaY);
186 const auto [x, y] = pc.getPosition();
187 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
188 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
189 newArgs.xCursorPosition = x;
190 newArgs.yCursorPosition = y;
191 }
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000192 if (canUnfadeOnDisplay(displayId)) {
193 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
194 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900195 return newArgs;
196}
197
Byoungho Jungee6268f2023-10-30 17:27:26 +0900198NotifyMotionArgs PointerChoreographer::processTouchpadEventLocked(const NotifyMotionArgs& args) {
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000199 mMouseDevices.emplace(args.deviceId);
Prabir Pradhan990d8712024-03-05 00:31:36 +0000200 auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900201
202 NotifyMotionArgs newArgs(args);
203 newArgs.displayId = displayId;
204 if (args.getPointerCount() == 1 && args.classification == MotionClassification::NONE) {
205 // This is a movement of the mouse pointer.
206 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
207 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
208 pc.move(deltaX, deltaY);
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000209 if (canUnfadeOnDisplay(displayId)) {
210 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
211 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900212
213 const auto [x, y] = pc.getPosition();
214 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
215 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
216 newArgs.xCursorPosition = x;
217 newArgs.yCursorPosition = y;
218 } else {
219 // This is a trackpad gesture with fake finger(s) that should not move the mouse pointer.
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000220 if (canUnfadeOnDisplay(displayId)) {
221 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
222 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900223
224 const auto [x, y] = pc.getPosition();
225 for (uint32_t i = 0; i < newArgs.getPointerCount(); i++) {
226 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X,
227 args.pointerCoords[i].getX() + x);
228 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y,
229 args.pointerCoords[i].getY() + y);
230 }
231 newArgs.xCursorPosition = x;
232 newArgs.yCursorPosition = y;
233 }
234 return newArgs;
235}
236
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000237void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
238 if (args.displayId == ADISPLAY_ID_NONE) {
239 return;
240 }
241
242 if (args.getPointerCount() != 1) {
243 LOG(WARNING) << "Only drawing tablet events with a single pointer are currently supported: "
244 << args.dump();
245 }
246
247 // Use a mouse pointer controller for drawing tablets, or create one if it doesn't exist.
248 auto [it, _] = mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
249 getMouseControllerConstructor(
250 args.displayId));
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000251 // TODO (b/325252005): Add handing for drawing tablets mouse pointer controller
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000252
253 PointerControllerInterface& pc = *it->second;
254
255 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
256 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
257 pc.setPosition(x, y);
258 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
259 // TODO(b/315815559): Do not fade and reset the icon if the hover exit will be followed
260 // immediately by a DOWN event.
261 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
262 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
263 } else if (canUnfadeOnDisplay(args.displayId)) {
264 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
265 }
266}
267
Byoungho Jungda10dd32023-10-06 17:03:45 +0900268/**
269 * When screen is touched, fade the mouse pointer on that display. We only call fade for
270 * ACTION_DOWN events.This would allow both mouse and touch to be used at the same time if the
271 * mouse device keeps moving and unfades the cursor.
272 * For touch events, we do not need to populate the cursor position.
273 */
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900274void PointerChoreographer::processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) {
275 if (args.displayId == ADISPLAY_ID_NONE) {
276 return;
277 }
278
Byoungho Jungda10dd32023-10-06 17:03:45 +0900279 if (const auto it = mMousePointersByDisplay.find(args.displayId);
280 it != mMousePointersByDisplay.end() && args.action == AMOTION_EVENT_ACTION_DOWN) {
281 it->second->fade(PointerControllerInterface::Transition::GRADUAL);
282 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900283
284 if (!mShowTouchesEnabled) {
285 return;
286 }
287
288 // Get the touch pointer controller for the device, or create one if it doesn't exist.
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000289 auto [it, controllerAdded] =
290 mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
291 if (controllerAdded) {
292 onControllerAddedOrRemoved();
293 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900294
295 PointerControllerInterface& pc = *it->second;
296
297 const PointerCoords* coords = args.pointerCoords.data();
298 const int32_t maskedAction = MotionEvent::getActionMasked(args.action);
299 const uint8_t actionIndex = MotionEvent::getActionIndex(args.action);
300 std::array<uint32_t, MAX_POINTER_ID + 1> idToIndex;
301 BitSet32 idBits;
302 if (maskedAction != AMOTION_EVENT_ACTION_UP && maskedAction != AMOTION_EVENT_ACTION_CANCEL) {
303 for (size_t i = 0; i < args.getPointerCount(); i++) {
304 if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP && actionIndex == i) {
305 continue;
306 }
307 uint32_t id = args.pointerProperties[i].id;
308 idToIndex[id] = i;
309 idBits.markBit(id);
310 }
311 }
312 // The PointerController already handles setting spots per-display, so
313 // we do not need to manually manage display changes for touch spots for now.
314 pc.setSpots(coords, idToIndex.cbegin(), idBits, args.displayId);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000315}
316
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900317void PointerChoreographer::processStylusHoverEventLocked(const NotifyMotionArgs& args) {
318 if (args.displayId == ADISPLAY_ID_NONE) {
319 return;
320 }
321
322 if (args.getPointerCount() != 1) {
323 LOG(WARNING) << "Only stylus hover events with a single pointer are currently supported: "
324 << args.dump();
325 }
326
327 // Get the stylus pointer controller for the device, or create one if it doesn't exist.
328 auto [it, _] =
329 mStylusPointersByDevice.try_emplace(args.deviceId,
330 getStylusControllerConstructor(args.displayId));
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000331 // TODO (b/325252005): Add handing for stylus pointer controller
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900332
333 PointerControllerInterface& pc = *it->second;
334
335 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
336 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
337 pc.setPosition(x, y);
338 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000339 // TODO(b/315815559): Do not fade and reset the icon if the hover exit will be followed
340 // immediately by a DOWN event.
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900341 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
Prabir Pradhan4b36db92024-01-03 20:56:57 +0000342 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000343 } else if (canUnfadeOnDisplay(args.displayId)) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900344 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
345 }
346}
347
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000348void PointerChoreographer::notifySwitch(const NotifySwitchArgs& args) {
349 mNextListener.notify(args);
350}
351
352void PointerChoreographer::notifySensor(const NotifySensorArgs& args) {
353 mNextListener.notify(args);
354}
355
356void PointerChoreographer::notifyVibratorState(const NotifyVibratorStateArgs& args) {
357 mNextListener.notify(args);
358}
359
360void PointerChoreographer::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900361 processDeviceReset(args);
362
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000363 mNextListener.notify(args);
364}
365
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900366void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) {
367 std::scoped_lock _l(mLock);
Prabir Pradhan16788792023-11-08 21:07:21 +0000368 mTouchPointersByDevice.erase(args.deviceId);
369 mStylusPointersByDevice.erase(args.deviceId);
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000370 mDrawingTabletPointersByDevice.erase(args.deviceId);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000371 onControllerAddedOrRemoved();
372}
373
374void PointerChoreographer::onControllerAddedOrRemoved() {
375 if (!HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS) {
376 return;
377 }
378 bool requireListener = !mTouchPointersByDevice.empty();
379 // TODO (b/325252005): Update for other types of pointer controllers
380
381 if (requireListener && mWindowInfoListener == nullptr) {
382 mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this);
383 auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
384 std::vector<android::gui::DisplayInfo>{});
385#if defined(__ANDROID__)
386 SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener,
387 &initialInfo);
388#endif
389 onWindowInfosChangedLocked(initialInfo.first);
390 } else if (!requireListener && mWindowInfoListener != nullptr) {
391#if defined(__ANDROID__)
392 SurfaceComposerClient::getDefault()->removeWindowInfosListener(mWindowInfoListener);
393#endif
394 mWindowInfoListener = nullptr;
395 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900396}
397
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000398void PointerChoreographer::notifyPointerCaptureChanged(
399 const NotifyPointerCaptureChangedArgs& args) {
Hiroki Sato25040232024-02-22 17:21:22 +0900400 if (args.request.isEnable()) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900401 std::scoped_lock _l(mLock);
402 for (const auto& [_, mousePointerController] : mMousePointersByDisplay) {
403 mousePointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
404 }
405 }
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000406 mNextListener.notify(args);
407}
408
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000409void PointerChoreographer::onWindowInfosChanged(
410 const std::vector<android::gui::WindowInfo>& windowInfos) {
411 std::scoped_lock _l(mLock);
412 onWindowInfosChangedLocked(windowInfos);
413}
414
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000415void PointerChoreographer::dump(std::string& dump) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900416 std::scoped_lock _l(mLock);
417
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000418 dump += "PointerChoreographer:\n";
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900419 dump += StringPrintf("show touches: %s\n", mShowTouchesEnabled ? "true" : "false");
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900420 dump += StringPrintf("stylus pointer icon enabled: %s\n",
421 mStylusPointerIconEnabled ? "true" : "false");
Byoungho Jungda10dd32023-10-06 17:03:45 +0900422
423 dump += INDENT "MousePointerControllers:\n";
424 for (const auto& [displayId, mousePointerController] : mMousePointersByDisplay) {
425 std::string pointerControllerDump = addLinePrefix(mousePointerController->dump(), INDENT);
426 dump += INDENT + std::to_string(displayId) + " : " + pointerControllerDump;
427 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900428 dump += INDENT "TouchPointerControllers:\n";
429 for (const auto& [deviceId, touchPointerController] : mTouchPointersByDevice) {
430 std::string pointerControllerDump = addLinePrefix(touchPointerController->dump(), INDENT);
431 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
432 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900433 dump += INDENT "StylusPointerControllers:\n";
434 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
435 std::string pointerControllerDump = addLinePrefix(stylusPointerController->dump(), INDENT);
436 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
437 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000438 dump += INDENT "DrawingTabletControllers:\n";
439 for (const auto& [deviceId, drawingTabletController] : mDrawingTabletPointersByDevice) {
440 std::string pointerControllerDump = addLinePrefix(drawingTabletController->dump(), INDENT);
441 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
442 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900443 dump += "\n";
444}
445
446const DisplayViewport* PointerChoreographer::findViewportByIdLocked(int32_t displayId) const {
447 for (auto& viewport : mViewports) {
448 if (viewport.displayId == displayId) {
449 return &viewport;
450 }
451 }
452 return nullptr;
453}
454
455int32_t PointerChoreographer::getTargetMouseDisplayLocked(int32_t associatedDisplayId) const {
456 return associatedDisplayId == ADISPLAY_ID_NONE ? mDefaultMouseDisplayId : associatedDisplayId;
457}
458
Prabir Pradhan990d8712024-03-05 00:31:36 +0000459std::pair<int32_t, PointerControllerInterface&> PointerChoreographer::ensureMouseControllerLocked(
460 int32_t associatedDisplayId) {
Byoungho Jungee6268f2023-10-30 17:27:26 +0900461 const int32_t displayId = getTargetMouseDisplayLocked(associatedDisplayId);
462
Prabir Pradhan990d8712024-03-05 00:31:36 +0000463 auto it = mMousePointersByDisplay.find(displayId);
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000464 if (it == mMousePointersByDisplay.end()) {
465 it = mMousePointersByDisplay.emplace(displayId, getMouseControllerConstructor(displayId))
466 .first;
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000467 // TODO (b/325252005): Add handing for mouse pointer controller
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000468 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900469
470 return {displayId, *it->second};
471}
472
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900473InputDeviceInfo* PointerChoreographer::findInputDeviceLocked(DeviceId deviceId) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000474 auto it = std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
475 [deviceId](const auto& info) { return info.getId() == deviceId; });
476 return it != mInputDeviceInfos.end() ? &(*it) : nullptr;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900477}
478
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000479bool PointerChoreographer::canUnfadeOnDisplay(int32_t displayId) {
480 return mDisplaysWithPointersHidden.find(displayId) == mDisplaysWithPointersHidden.end();
481}
482
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000483PointerChoreographer::PointerDisplayChange PointerChoreographer::updatePointerControllersLocked() {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900484 std::set<int32_t /*displayId*/> mouseDisplaysToKeep;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900485 std::set<DeviceId> touchDevicesToKeep;
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900486 std::set<DeviceId> stylusDevicesToKeep;
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000487 std::set<DeviceId> drawingTabletDevicesToKeep;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900488
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000489 // Mark the displayIds or deviceIds of PointerControllers currently needed, and create
490 // new PointerControllers if necessary.
Byoungho Jungda10dd32023-10-06 17:03:45 +0900491 for (const auto& info : mInputDeviceInfos) {
Linnan Li48f80da2024-04-22 18:38:16 +0000492 if (!info.isEnabled()) {
493 // If device is disabled, we should not keep it, and should not show pointer for
494 // disabled mouse device.
495 continue;
496 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900497 const uint32_t sources = info.getSources();
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000498 const bool isKnownMouse = mMouseDevices.count(info.getId()) != 0;
499
500 if (isMouseOrTouchpad(sources) || isKnownMouse) {
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000501 const int32_t displayId = getTargetMouseDisplayLocked(info.getAssociatedDisplayId());
502 mouseDisplaysToKeep.insert(displayId);
503 // For mice, show the cursor immediately when the device is first connected or
504 // when it moves to a new display.
505 auto [mousePointerIt, isNewMousePointer] =
506 mMousePointersByDisplay.try_emplace(displayId,
507 getMouseControllerConstructor(displayId));
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000508 // TODO (b/325252005): Add handing for mouse pointer controller
509
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000510 mMouseDevices.emplace(info.getId());
511 if ((!isKnownMouse || isNewMousePointer) && canUnfadeOnDisplay(displayId)) {
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000512 mousePointerIt->second->unfade(PointerControllerInterface::Transition::IMMEDIATE);
513 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900514 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900515 if (isFromSource(sources, AINPUT_SOURCE_TOUCHSCREEN) && mShowTouchesEnabled &&
516 info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
517 touchDevicesToKeep.insert(info.getId());
518 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900519 if (isFromSource(sources, AINPUT_SOURCE_STYLUS) && mStylusPointerIconEnabled &&
520 info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
521 stylusDevicesToKeep.insert(info.getId());
522 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000523 if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE) &&
524 info.getAssociatedDisplayId() != ADISPLAY_ID_NONE) {
525 drawingTabletDevicesToKeep.insert(info.getId());
526 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900527 }
528
529 // Remove PointerControllers no longer needed.
Prabir Pradhan19767602023-11-03 16:53:31 +0000530 std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000531 return mouseDisplaysToKeep.find(pair.first) == mouseDisplaysToKeep.end();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900532 });
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900533 std::erase_if(mTouchPointersByDevice, [&touchDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000534 return touchDevicesToKeep.find(pair.first) == touchDevicesToKeep.end();
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900535 });
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900536 std::erase_if(mStylusPointersByDevice, [&stylusDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000537 return stylusDevicesToKeep.find(pair.first) == stylusDevicesToKeep.end();
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900538 });
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000539 std::erase_if(mDrawingTabletPointersByDevice, [&drawingTabletDevicesToKeep](const auto& pair) {
540 return drawingTabletDevicesToKeep.find(pair.first) == drawingTabletDevicesToKeep.end();
541 });
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000542 std::erase_if(mMouseDevices, [&](DeviceId id) REQUIRES(mLock) {
543 return std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
544 [id](const auto& info) { return info.getId() == id; }) ==
545 mInputDeviceInfos.end();
546 });
Byoungho Jungda10dd32023-10-06 17:03:45 +0900547
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000548 onControllerAddedOrRemoved();
549
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000550 // Check if we need to notify the policy if there's a change on the pointer display ID.
551 return calculatePointerDisplayChangeToNotify();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900552}
553
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000554PointerChoreographer::PointerDisplayChange
555PointerChoreographer::calculatePointerDisplayChangeToNotify() {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900556 int32_t displayIdToNotify = ADISPLAY_ID_NONE;
557 FloatPoint cursorPosition = {0, 0};
558 if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
559 it != mMousePointersByDisplay.end()) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000560 const auto& pointerController = it->second;
561 // Use the displayId from the pointerController, because it accurately reflects whether
562 // the viewport has been added for that display. Otherwise, we would have to check if
563 // the viewport exists separately.
564 displayIdToNotify = pointerController->getDisplayId();
565 cursorPosition = pointerController->getPosition();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900566 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900567 if (mNotifiedPointerDisplayId == displayIdToNotify) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000568 return {};
Byoungho Jungda10dd32023-10-06 17:03:45 +0900569 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900570 mNotifiedPointerDisplayId = displayIdToNotify;
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000571 return {{displayIdToNotify, cursorPosition}};
Byoungho Jungda10dd32023-10-06 17:03:45 +0900572}
573
574void PointerChoreographer::setDefaultMouseDisplayId(int32_t displayId) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000575 PointerDisplayChange pointerDisplayChange;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900576
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000577 { // acquire lock
578 std::scoped_lock _l(mLock);
579
580 mDefaultMouseDisplayId = displayId;
581 pointerDisplayChange = updatePointerControllersLocked();
582 } // release lock
583
584 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900585}
586
587void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000588 PointerDisplayChange pointerDisplayChange;
589
590 { // acquire lock
591 std::scoped_lock _l(mLock);
592 for (const auto& viewport : viewports) {
593 const int32_t displayId = viewport.displayId;
594 if (const auto it = mMousePointersByDisplay.find(displayId);
595 it != mMousePointersByDisplay.end()) {
596 it->second->setDisplayViewport(viewport);
597 }
598 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
599 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
600 if (info && info->getAssociatedDisplayId() == displayId) {
601 stylusPointerController->setDisplayViewport(viewport);
602 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900603 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000604 for (const auto& [deviceId, drawingTabletController] : mDrawingTabletPointersByDevice) {
605 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
606 if (info && info->getAssociatedDisplayId() == displayId) {
607 drawingTabletController->setDisplayViewport(viewport);
608 }
609 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900610 }
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000611 mViewports = viewports;
612 pointerDisplayChange = calculatePointerDisplayChangeToNotify();
613 } // release lock
614
615 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900616}
617
618std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
619 int32_t associatedDisplayId) {
620 std::scoped_lock _l(mLock);
621 const int32_t resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
622 if (const auto viewport = findViewportByIdLocked(resolvedDisplayId); viewport) {
623 return *viewport;
624 }
625 return std::nullopt;
626}
627
628FloatPoint PointerChoreographer::getMouseCursorPosition(int32_t displayId) {
629 std::scoped_lock _l(mLock);
630 const int32_t resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
631 if (auto it = mMousePointersByDisplay.find(resolvedDisplayId);
632 it != mMousePointersByDisplay.end()) {
633 return it->second->getPosition();
634 }
635 return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000636}
637
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900638void PointerChoreographer::setShowTouchesEnabled(bool enabled) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000639 PointerDisplayChange pointerDisplayChange;
640
641 { // acquire lock
642 std::scoped_lock _l(mLock);
643 if (mShowTouchesEnabled == enabled) {
644 return;
645 }
646 mShowTouchesEnabled = enabled;
647 pointerDisplayChange = updatePointerControllersLocked();
648 } // release lock
649
650 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900651}
652
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900653void PointerChoreographer::setStylusPointerIconEnabled(bool enabled) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000654 PointerDisplayChange pointerDisplayChange;
655
656 { // acquire lock
657 std::scoped_lock _l(mLock);
658 if (mStylusPointerIconEnabled == enabled) {
659 return;
660 }
661 mStylusPointerIconEnabled = enabled;
662 pointerDisplayChange = updatePointerControllersLocked();
663 } // release lock
664
665 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900666}
667
Byoungho Jung99326452023-11-03 20:19:17 +0900668bool PointerChoreographer::setPointerIcon(
669 std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon, int32_t displayId,
670 DeviceId deviceId) {
671 std::scoped_lock _l(mLock);
672 if (deviceId < 0) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000673 LOG(WARNING) << "Invalid device id " << deviceId << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900674 return false;
675 }
676 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
677 if (!info) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000678 LOG(WARNING) << "No input device info found for id " << deviceId
679 << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900680 return false;
681 }
682 const uint32_t sources = info->getSources();
Byoungho Jung99326452023-11-03 20:19:17 +0900683
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000684 if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)) {
685 auto it = mDrawingTabletPointersByDevice.find(deviceId);
686 if (it != mDrawingTabletPointersByDevice.end()) {
687 setIconForController(icon, *it->second);
688 return true;
Byoungho Jung99326452023-11-03 20:19:17 +0900689 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000690 }
691 if (isFromSource(sources, AINPUT_SOURCE_STYLUS)) {
692 auto it = mStylusPointersByDevice.find(deviceId);
693 if (it != mStylusPointersByDevice.end()) {
694 setIconForController(icon, *it->second);
695 return true;
696 }
697 }
698 if (isFromSource(sources, AINPUT_SOURCE_MOUSE)) {
699 auto it = mMousePointersByDisplay.find(displayId);
700 if (it != mMousePointersByDisplay.end()) {
701 setIconForController(icon, *it->second);
702 return true;
Byoungho Jung99326452023-11-03 20:19:17 +0900703 } else {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000704 LOG(WARNING) << "No mouse pointer controller found for display " << displayId
705 << ", device " << deviceId << ".";
Byoungho Jung99326452023-11-03 20:19:17 +0900706 return false;
707 }
Byoungho Jung99326452023-11-03 20:19:17 +0900708 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000709 LOG(WARNING) << "Cannot set pointer icon for display " << displayId << ", device " << deviceId
710 << ".";
711 return false;
Byoungho Jung99326452023-11-03 20:19:17 +0900712}
713
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000714void PointerChoreographer::onWindowInfosChangedLocked(
715 const std::vector<android::gui::WindowInfo>& windowInfos) {
716 // Mark all spot controllers secure on displays containing secure windows and
717 // remove secure flag from others if required
718 std::unordered_set<int32_t> privacySensitiveDisplays;
719 std::unordered_set<int32_t> allDisplayIds;
720 for (const auto& windowInfo : windowInfos) {
721 allDisplayIds.insert(windowInfo.displayId);
722 if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
723 windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
724 privacySensitiveDisplays.insert(windowInfo.displayId);
725 }
726 }
727
728 for (auto& it : mTouchPointersByDevice) {
729 auto& pc = it.second;
730 for (int32_t displayId : allDisplayIds) {
731 pc->setSkipScreenshot(displayId,
732 privacySensitiveDisplays.find(displayId) !=
733 privacySensitiveDisplays.end());
734 }
735 }
736 // TODO (b/325252005): update skip screenshot flag for other types of pointer controllers
737}
738
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000739void PointerChoreographer::setPointerIconVisibility(int32_t displayId, bool visible) {
740 std::scoped_lock lock(mLock);
741 if (visible) {
742 mDisplaysWithPointersHidden.erase(displayId);
743 // We do not unfade the icons here, because we don't know when the last event happened.
744 return;
745 }
746
747 mDisplaysWithPointersHidden.emplace(displayId);
748
749 // Hide any icons that are currently visible on the display.
750 if (auto it = mMousePointersByDisplay.find(displayId); it != mMousePointersByDisplay.end()) {
751 const auto& [_, controller] = *it;
752 controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
753 }
754 for (const auto& [_, controller] : mStylusPointersByDevice) {
755 if (controller->getDisplayId() == displayId) {
756 controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
757 }
758 }
759}
760
Prabir Pradhan19767602023-11-03 16:53:31 +0000761PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
762 int32_t displayId) {
763 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
764 [this, displayId]() REQUIRES(mLock) {
765 auto pc = mPolicy.createPointerController(
766 PointerControllerInterface::ControllerType::MOUSE);
767 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
768 pc->setDisplayViewport(*viewport);
769 }
770 return pc;
771 };
772 return ConstructorDelegate(std::move(ctor));
773}
774
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900775PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
776 int32_t displayId) {
777 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
778 [this, displayId]() REQUIRES(mLock) {
779 auto pc = mPolicy.createPointerController(
780 PointerControllerInterface::ControllerType::STYLUS);
781 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
782 pc->setDisplayViewport(*viewport);
783 }
784 return pc;
785 };
786 return ConstructorDelegate(std::move(ctor));
787}
788
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000789void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfosChanged(
790 const gui::WindowInfosUpdate& windowInfosUpdate) {
791 std::scoped_lock _l(mListenerLock);
792 if (mPointerChoreographer != nullptr) {
793 mPointerChoreographer->onWindowInfosChanged(windowInfosUpdate.windowInfos);
794 }
795}
796
797void PointerChoreographer::PointerChoreographerDisplayInfoListener::
798 onPointerChoreographerDestroyed() {
799 std::scoped_lock _l(mListenerLock);
800 mPointerChoreographer = nullptr;
801}
802
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000803} // namespace android