blob: d6c6f938d40a4cabbdca450f90faa6bee986a3be [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
Linnan Li13bf76a2024-05-05 19:18:02 +080070inline void notifyPointerDisplayChange(
71 std::optional<std::tuple<ui::LogicalDisplayId, FloatPoint>> change,
72 PointerChoreographerPolicyInterface& policy) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +000073 if (!change) {
74 return;
75 }
76 const auto& [displayId, cursorPosition] = *change;
77 policy.notifyPointerDisplayIdChanged(displayId, cursorPosition);
78}
79
Prabir Pradhan4c977a42024-03-15 16:47:37 +000080void setIconForController(const std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle>& icon,
81 PointerControllerInterface& controller) {
82 if (std::holds_alternative<std::unique_ptr<SpriteIcon>>(icon)) {
83 if (std::get<std::unique_ptr<SpriteIcon>>(icon) == nullptr) {
84 LOG(FATAL) << "SpriteIcon should not be null";
85 }
86 controller.setCustomPointerIcon(*std::get<std::unique_ptr<SpriteIcon>>(icon));
87 } else {
88 controller.updatePointerIcon(std::get<PointerIconStyle>(icon));
89 }
90}
91
Byoungho Jungda10dd32023-10-06 17:03:45 +090092} // namespace
93
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000094// --- PointerChoreographer ---
95
96PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
97 PointerChoreographerPolicyInterface& policy)
Prabir Pradhan5a51a222024-03-05 03:54:00 +000098 : mTouchControllerConstructor([this]() {
Prabir Pradhan16788792023-11-08 21:07:21 +000099 return mPolicy.createPointerController(
100 PointerControllerInterface::ControllerType::TOUCH);
101 }),
102 mNextListener(listener),
Byoungho Jungda10dd32023-10-06 17:03:45 +0900103 mPolicy(policy),
Linnan Li13bf76a2024-05-05 19:18:02 +0800104 mDefaultMouseDisplayId(ui::ADISPLAY_ID_DEFAULT),
105 mNotifiedPointerDisplayId(ui::ADISPLAY_ID_NONE),
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900106 mShowTouchesEnabled(false),
107 mStylusPointerIconEnabled(false) {}
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000108
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000109PointerChoreographer::~PointerChoreographer() {
110 std::scoped_lock _l(mLock);
111 if (mWindowInfoListener == nullptr) {
112 return;
113 }
114 mWindowInfoListener->onPointerChoreographerDestroyed();
115}
116
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000117void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000118 PointerDisplayChange pointerDisplayChange;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900119
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000120 { // acquire lock
121 std::scoped_lock _l(mLock);
122
123 mInputDeviceInfos = args.inputDeviceInfos;
124 pointerDisplayChange = updatePointerControllersLocked();
125 } // release lock
126
127 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000128 mNextListener.notify(args);
129}
130
131void PointerChoreographer::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
132 mNextListener.notify(args);
133}
134
135void PointerChoreographer::notifyKey(const NotifyKeyArgs& args) {
136 mNextListener.notify(args);
137}
138
139void PointerChoreographer::notifyMotion(const NotifyMotionArgs& args) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900140 NotifyMotionArgs newArgs = processMotion(args);
141
142 mNextListener.notify(newArgs);
143}
144
145NotifyMotionArgs PointerChoreographer::processMotion(const NotifyMotionArgs& args) {
146 std::scoped_lock _l(mLock);
147
148 if (isFromMouse(args)) {
149 return processMouseEventLocked(args);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900150 } else if (isFromTouchpad(args)) {
151 return processTouchpadEventLocked(args);
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000152 } else if (isFromDrawingTablet(args)) {
153 processDrawingTabletEventLocked(args);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900154 } else if (mStylusPointerIconEnabled && isStylusHoverEvent(args)) {
155 processStylusHoverEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900156 } else if (isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN)) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900157 processTouchscreenAndStylusEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900158 }
159 return args;
160}
161
162NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotionArgs& args) {
163 if (args.getPointerCount() != 1) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000164 LOG(FATAL) << "Only mouse events with a single pointer are currently supported: "
165 << args.dump();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900166 }
167
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000168 mMouseDevices.emplace(args.deviceId);
Prabir Pradhan990d8712024-03-05 00:31:36 +0000169 auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
Nergi Rahardie0a4cfe2024-03-11 13:18:59 +0900170 NotifyMotionArgs newArgs(args);
171 newArgs.displayId = displayId;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900172
Nergi Rahardie0a4cfe2024-03-11 13:18:59 +0900173 if (MotionEvent::isValidCursorPosition(args.xCursorPosition, args.yCursorPosition)) {
174 // This is an absolute mouse device that knows about the location of the cursor on the
175 // display, so set the cursor position to the specified location.
176 const auto [x, y] = pc.getPosition();
177 const float deltaX = args.xCursorPosition - x;
178 const float deltaY = args.yCursorPosition - y;
179 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
180 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
181 pc.setPosition(args.xCursorPosition, args.yCursorPosition);
182 } else {
183 // This is a relative mouse, so move the cursor by the specified amount.
184 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
185 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
186 pc.move(deltaX, deltaY);
187 const auto [x, y] = pc.getPosition();
188 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
189 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
190 newArgs.xCursorPosition = x;
191 newArgs.yCursorPosition = y;
192 }
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000193 if (canUnfadeOnDisplay(displayId)) {
194 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
195 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900196 return newArgs;
197}
198
Byoungho Jungee6268f2023-10-30 17:27:26 +0900199NotifyMotionArgs PointerChoreographer::processTouchpadEventLocked(const NotifyMotionArgs& args) {
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000200 mMouseDevices.emplace(args.deviceId);
Prabir Pradhan990d8712024-03-05 00:31:36 +0000201 auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900202
203 NotifyMotionArgs newArgs(args);
204 newArgs.displayId = displayId;
205 if (args.getPointerCount() == 1 && args.classification == MotionClassification::NONE) {
206 // This is a movement of the mouse pointer.
207 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
208 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
209 pc.move(deltaX, deltaY);
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000210 if (canUnfadeOnDisplay(displayId)) {
211 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
212 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900213
214 const auto [x, y] = pc.getPosition();
215 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
216 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
217 newArgs.xCursorPosition = x;
218 newArgs.yCursorPosition = y;
219 } else {
220 // This is a trackpad gesture with fake finger(s) that should not move the mouse pointer.
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000221 if (canUnfadeOnDisplay(displayId)) {
222 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
223 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900224
225 const auto [x, y] = pc.getPosition();
226 for (uint32_t i = 0; i < newArgs.getPointerCount(); i++) {
227 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X,
228 args.pointerCoords[i].getX() + x);
229 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y,
230 args.pointerCoords[i].getY() + y);
231 }
232 newArgs.xCursorPosition = x;
233 newArgs.yCursorPosition = y;
234 }
235 return newArgs;
236}
237
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000238void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800239 if (args.displayId == ui::ADISPLAY_ID_NONE) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000240 return;
241 }
242
243 if (args.getPointerCount() != 1) {
244 LOG(WARNING) << "Only drawing tablet events with a single pointer are currently supported: "
245 << args.dump();
246 }
247
248 // Use a mouse pointer controller for drawing tablets, or create one if it doesn't exist.
249 auto [it, _] = mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
250 getMouseControllerConstructor(
251 args.displayId));
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000252 // TODO (b/325252005): Add handing for drawing tablets mouse pointer controller
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000253
254 PointerControllerInterface& pc = *it->second;
255
256 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
257 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
258 pc.setPosition(x, y);
259 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
260 // TODO(b/315815559): Do not fade and reset the icon if the hover exit will be followed
261 // immediately by a DOWN event.
262 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
263 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
264 } else if (canUnfadeOnDisplay(args.displayId)) {
265 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
266 }
267}
268
Byoungho Jungda10dd32023-10-06 17:03:45 +0900269/**
270 * When screen is touched, fade the mouse pointer on that display. We only call fade for
271 * ACTION_DOWN events.This would allow both mouse and touch to be used at the same time if the
272 * mouse device keeps moving and unfades the cursor.
273 * For touch events, we do not need to populate the cursor position.
274 */
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900275void PointerChoreographer::processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800276 if (!args.displayId.isValid()) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900277 return;
278 }
279
Byoungho Jungda10dd32023-10-06 17:03:45 +0900280 if (const auto it = mMousePointersByDisplay.find(args.displayId);
281 it != mMousePointersByDisplay.end() && args.action == AMOTION_EVENT_ACTION_DOWN) {
282 it->second->fade(PointerControllerInterface::Transition::GRADUAL);
283 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900284
285 if (!mShowTouchesEnabled) {
286 return;
287 }
288
289 // Get the touch pointer controller for the device, or create one if it doesn't exist.
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000290 auto [it, controllerAdded] =
291 mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
292 if (controllerAdded) {
293 onControllerAddedOrRemoved();
294 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900295
296 PointerControllerInterface& pc = *it->second;
297
298 const PointerCoords* coords = args.pointerCoords.data();
299 const int32_t maskedAction = MotionEvent::getActionMasked(args.action);
300 const uint8_t actionIndex = MotionEvent::getActionIndex(args.action);
301 std::array<uint32_t, MAX_POINTER_ID + 1> idToIndex;
302 BitSet32 idBits;
303 if (maskedAction != AMOTION_EVENT_ACTION_UP && maskedAction != AMOTION_EVENT_ACTION_CANCEL) {
304 for (size_t i = 0; i < args.getPointerCount(); i++) {
305 if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP && actionIndex == i) {
306 continue;
307 }
308 uint32_t id = args.pointerProperties[i].id;
309 idToIndex[id] = i;
310 idBits.markBit(id);
311 }
312 }
313 // The PointerController already handles setting spots per-display, so
314 // we do not need to manually manage display changes for touch spots for now.
315 pc.setSpots(coords, idToIndex.cbegin(), idBits, args.displayId);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000316}
317
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900318void PointerChoreographer::processStylusHoverEventLocked(const NotifyMotionArgs& args) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800319 if (!args.displayId.isValid()) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900320 return;
321 }
322
323 if (args.getPointerCount() != 1) {
324 LOG(WARNING) << "Only stylus hover events with a single pointer are currently supported: "
325 << args.dump();
326 }
327
328 // Get the stylus pointer controller for the device, or create one if it doesn't exist.
329 auto [it, _] =
330 mStylusPointersByDevice.try_emplace(args.deviceId,
331 getStylusControllerConstructor(args.displayId));
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000332 // TODO (b/325252005): Add handing for stylus pointer controller
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900333
334 PointerControllerInterface& pc = *it->second;
335
336 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
337 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
338 pc.setPosition(x, y);
339 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000340 // TODO(b/315815559): Do not fade and reset the icon if the hover exit will be followed
341 // immediately by a DOWN event.
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900342 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
Prabir Pradhan4b36db92024-01-03 20:56:57 +0000343 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000344 } else if (canUnfadeOnDisplay(args.displayId)) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900345 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
346 }
347}
348
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000349void PointerChoreographer::notifySwitch(const NotifySwitchArgs& args) {
350 mNextListener.notify(args);
351}
352
353void PointerChoreographer::notifySensor(const NotifySensorArgs& args) {
354 mNextListener.notify(args);
355}
356
357void PointerChoreographer::notifyVibratorState(const NotifyVibratorStateArgs& args) {
358 mNextListener.notify(args);
359}
360
361void PointerChoreographer::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900362 processDeviceReset(args);
363
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000364 mNextListener.notify(args);
365}
366
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900367void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) {
368 std::scoped_lock _l(mLock);
Prabir Pradhan16788792023-11-08 21:07:21 +0000369 mTouchPointersByDevice.erase(args.deviceId);
370 mStylusPointersByDevice.erase(args.deviceId);
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000371 mDrawingTabletPointersByDevice.erase(args.deviceId);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000372 onControllerAddedOrRemoved();
373}
374
375void PointerChoreographer::onControllerAddedOrRemoved() {
376 if (!HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS) {
377 return;
378 }
379 bool requireListener = !mTouchPointersByDevice.empty();
380 // TODO (b/325252005): Update for other types of pointer controllers
381
382 if (requireListener && mWindowInfoListener == nullptr) {
383 mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this);
384 auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
385 std::vector<android::gui::DisplayInfo>{});
386#if defined(__ANDROID__)
387 SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener,
388 &initialInfo);
389#endif
390 onWindowInfosChangedLocked(initialInfo.first);
391 } else if (!requireListener && mWindowInfoListener != nullptr) {
392#if defined(__ANDROID__)
393 SurfaceComposerClient::getDefault()->removeWindowInfosListener(mWindowInfoListener);
394#endif
395 mWindowInfoListener = nullptr;
396 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900397}
398
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000399void PointerChoreographer::notifyPointerCaptureChanged(
400 const NotifyPointerCaptureChangedArgs& args) {
Hiroki Sato25040232024-02-22 17:21:22 +0900401 if (args.request.isEnable()) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900402 std::scoped_lock _l(mLock);
403 for (const auto& [_, mousePointerController] : mMousePointersByDisplay) {
404 mousePointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
405 }
406 }
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000407 mNextListener.notify(args);
408}
409
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000410void PointerChoreographer::onWindowInfosChanged(
411 const std::vector<android::gui::WindowInfo>& windowInfos) {
412 std::scoped_lock _l(mLock);
413 onWindowInfosChangedLocked(windowInfos);
414}
415
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000416void PointerChoreographer::dump(std::string& dump) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900417 std::scoped_lock _l(mLock);
418
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000419 dump += "PointerChoreographer:\n";
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900420 dump += StringPrintf("show touches: %s\n", mShowTouchesEnabled ? "true" : "false");
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900421 dump += StringPrintf("stylus pointer icon enabled: %s\n",
422 mStylusPointerIconEnabled ? "true" : "false");
Byoungho Jungda10dd32023-10-06 17:03:45 +0900423
424 dump += INDENT "MousePointerControllers:\n";
425 for (const auto& [displayId, mousePointerController] : mMousePointersByDisplay) {
426 std::string pointerControllerDump = addLinePrefix(mousePointerController->dump(), INDENT);
Linnan Li13bf76a2024-05-05 19:18:02 +0800427 dump += INDENT + displayId.toString() + " : " + pointerControllerDump;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900428 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900429 dump += INDENT "TouchPointerControllers:\n";
430 for (const auto& [deviceId, touchPointerController] : mTouchPointersByDevice) {
431 std::string pointerControllerDump = addLinePrefix(touchPointerController->dump(), INDENT);
432 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
433 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900434 dump += INDENT "StylusPointerControllers:\n";
435 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
436 std::string pointerControllerDump = addLinePrefix(stylusPointerController->dump(), INDENT);
437 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
438 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000439 dump += INDENT "DrawingTabletControllers:\n";
440 for (const auto& [deviceId, drawingTabletController] : mDrawingTabletPointersByDevice) {
441 std::string pointerControllerDump = addLinePrefix(drawingTabletController->dump(), INDENT);
442 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
443 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900444 dump += "\n";
445}
446
Linnan Li13bf76a2024-05-05 19:18:02 +0800447const DisplayViewport* PointerChoreographer::findViewportByIdLocked(
448 ui::LogicalDisplayId displayId) const {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900449 for (auto& viewport : mViewports) {
450 if (viewport.displayId == displayId) {
451 return &viewport;
452 }
453 }
454 return nullptr;
455}
456
Linnan Li13bf76a2024-05-05 19:18:02 +0800457ui::LogicalDisplayId PointerChoreographer::getTargetMouseDisplayLocked(
458 ui::LogicalDisplayId associatedDisplayId) const {
459 return associatedDisplayId.isValid() ? associatedDisplayId : mDefaultMouseDisplayId;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900460}
461
Linnan Li13bf76a2024-05-05 19:18:02 +0800462std::pair<ui::LogicalDisplayId, PointerControllerInterface&>
463PointerChoreographer::ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) {
464 const ui::LogicalDisplayId displayId = getTargetMouseDisplayLocked(associatedDisplayId);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900465
Prabir Pradhan990d8712024-03-05 00:31:36 +0000466 auto it = mMousePointersByDisplay.find(displayId);
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000467 if (it == mMousePointersByDisplay.end()) {
468 it = mMousePointersByDisplay.emplace(displayId, getMouseControllerConstructor(displayId))
469 .first;
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000470 // TODO (b/325252005): Add handing for mouse pointer controller
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000471 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900472
473 return {displayId, *it->second};
474}
475
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900476InputDeviceInfo* PointerChoreographer::findInputDeviceLocked(DeviceId deviceId) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000477 auto it = std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
478 [deviceId](const auto& info) { return info.getId() == deviceId; });
479 return it != mInputDeviceInfos.end() ? &(*it) : nullptr;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900480}
481
Linnan Li13bf76a2024-05-05 19:18:02 +0800482bool PointerChoreographer::canUnfadeOnDisplay(ui::LogicalDisplayId displayId) {
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000483 return mDisplaysWithPointersHidden.find(displayId) == mDisplaysWithPointersHidden.end();
484}
485
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000486PointerChoreographer::PointerDisplayChange PointerChoreographer::updatePointerControllersLocked() {
Linnan Li13bf76a2024-05-05 19:18:02 +0800487 std::set<ui::LogicalDisplayId /*displayId*/> mouseDisplaysToKeep;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900488 std::set<DeviceId> touchDevicesToKeep;
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900489 std::set<DeviceId> stylusDevicesToKeep;
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000490 std::set<DeviceId> drawingTabletDevicesToKeep;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900491
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000492 // Mark the displayIds or deviceIds of PointerControllers currently needed, and create
493 // new PointerControllers if necessary.
Byoungho Jungda10dd32023-10-06 17:03:45 +0900494 for (const auto& info : mInputDeviceInfos) {
Linnan Li48f80da2024-04-22 18:38:16 +0000495 if (!info.isEnabled()) {
496 // If device is disabled, we should not keep it, and should not show pointer for
497 // disabled mouse device.
498 continue;
499 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900500 const uint32_t sources = info.getSources();
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000501 const bool isKnownMouse = mMouseDevices.count(info.getId()) != 0;
502
503 if (isMouseOrTouchpad(sources) || isKnownMouse) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800504 const ui::LogicalDisplayId displayId =
505 getTargetMouseDisplayLocked(info.getAssociatedDisplayId());
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000506 mouseDisplaysToKeep.insert(displayId);
507 // For mice, show the cursor immediately when the device is first connected or
508 // when it moves to a new display.
509 auto [mousePointerIt, isNewMousePointer] =
510 mMousePointersByDisplay.try_emplace(displayId,
511 getMouseControllerConstructor(displayId));
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000512 // TODO (b/325252005): Add handing for mouse pointer controller
513
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000514 mMouseDevices.emplace(info.getId());
515 if ((!isKnownMouse || isNewMousePointer) && canUnfadeOnDisplay(displayId)) {
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000516 mousePointerIt->second->unfade(PointerControllerInterface::Transition::IMMEDIATE);
517 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900518 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900519 if (isFromSource(sources, AINPUT_SOURCE_TOUCHSCREEN) && mShowTouchesEnabled &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800520 info.getAssociatedDisplayId().isValid()) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900521 touchDevicesToKeep.insert(info.getId());
522 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900523 if (isFromSource(sources, AINPUT_SOURCE_STYLUS) && mStylusPointerIconEnabled &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800524 info.getAssociatedDisplayId().isValid()) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900525 stylusDevicesToKeep.insert(info.getId());
526 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000527 if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE) &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800528 info.getAssociatedDisplayId().isValid()) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000529 drawingTabletDevicesToKeep.insert(info.getId());
530 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900531 }
532
533 // Remove PointerControllers no longer needed.
Prabir Pradhan19767602023-11-03 16:53:31 +0000534 std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000535 return mouseDisplaysToKeep.find(pair.first) == mouseDisplaysToKeep.end();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900536 });
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900537 std::erase_if(mTouchPointersByDevice, [&touchDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000538 return touchDevicesToKeep.find(pair.first) == touchDevicesToKeep.end();
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900539 });
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900540 std::erase_if(mStylusPointersByDevice, [&stylusDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000541 return stylusDevicesToKeep.find(pair.first) == stylusDevicesToKeep.end();
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900542 });
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000543 std::erase_if(mDrawingTabletPointersByDevice, [&drawingTabletDevicesToKeep](const auto& pair) {
544 return drawingTabletDevicesToKeep.find(pair.first) == drawingTabletDevicesToKeep.end();
545 });
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000546 std::erase_if(mMouseDevices, [&](DeviceId id) REQUIRES(mLock) {
547 return std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
548 [id](const auto& info) { return info.getId() == id; }) ==
549 mInputDeviceInfos.end();
550 });
Byoungho Jungda10dd32023-10-06 17:03:45 +0900551
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000552 onControllerAddedOrRemoved();
553
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000554 // Check if we need to notify the policy if there's a change on the pointer display ID.
555 return calculatePointerDisplayChangeToNotify();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900556}
557
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000558PointerChoreographer::PointerDisplayChange
559PointerChoreographer::calculatePointerDisplayChangeToNotify() {
Linnan Li13bf76a2024-05-05 19:18:02 +0800560 ui::LogicalDisplayId displayIdToNotify = ui::ADISPLAY_ID_NONE;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900561 FloatPoint cursorPosition = {0, 0};
562 if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
563 it != mMousePointersByDisplay.end()) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000564 const auto& pointerController = it->second;
565 // Use the displayId from the pointerController, because it accurately reflects whether
566 // the viewport has been added for that display. Otherwise, we would have to check if
567 // the viewport exists separately.
568 displayIdToNotify = pointerController->getDisplayId();
569 cursorPosition = pointerController->getPosition();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900570 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900571 if (mNotifiedPointerDisplayId == displayIdToNotify) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000572 return {};
Byoungho Jungda10dd32023-10-06 17:03:45 +0900573 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900574 mNotifiedPointerDisplayId = displayIdToNotify;
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000575 return {{displayIdToNotify, cursorPosition}};
Byoungho Jungda10dd32023-10-06 17:03:45 +0900576}
577
Linnan Li13bf76a2024-05-05 19:18:02 +0800578void PointerChoreographer::setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000579 PointerDisplayChange pointerDisplayChange;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900580
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000581 { // acquire lock
582 std::scoped_lock _l(mLock);
583
584 mDefaultMouseDisplayId = displayId;
585 pointerDisplayChange = updatePointerControllersLocked();
586 } // release lock
587
588 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900589}
590
591void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000592 PointerDisplayChange pointerDisplayChange;
593
594 { // acquire lock
595 std::scoped_lock _l(mLock);
596 for (const auto& viewport : viewports) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800597 const ui::LogicalDisplayId displayId = viewport.displayId;
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000598 if (const auto it = mMousePointersByDisplay.find(displayId);
599 it != mMousePointersByDisplay.end()) {
600 it->second->setDisplayViewport(viewport);
601 }
602 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
603 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
604 if (info && info->getAssociatedDisplayId() == displayId) {
605 stylusPointerController->setDisplayViewport(viewport);
606 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900607 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000608 for (const auto& [deviceId, drawingTabletController] : mDrawingTabletPointersByDevice) {
609 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
610 if (info && info->getAssociatedDisplayId() == displayId) {
611 drawingTabletController->setDisplayViewport(viewport);
612 }
613 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900614 }
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000615 mViewports = viewports;
616 pointerDisplayChange = calculatePointerDisplayChangeToNotify();
617 } // release lock
618
619 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900620}
621
622std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
Linnan Li13bf76a2024-05-05 19:18:02 +0800623 ui::LogicalDisplayId associatedDisplayId) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900624 std::scoped_lock _l(mLock);
Linnan Li13bf76a2024-05-05 19:18:02 +0800625 const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900626 if (const auto viewport = findViewportByIdLocked(resolvedDisplayId); viewport) {
627 return *viewport;
628 }
629 return std::nullopt;
630}
631
Linnan Li13bf76a2024-05-05 19:18:02 +0800632FloatPoint PointerChoreographer::getMouseCursorPosition(ui::LogicalDisplayId displayId) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900633 std::scoped_lock _l(mLock);
Linnan Li13bf76a2024-05-05 19:18:02 +0800634 const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900635 if (auto it = mMousePointersByDisplay.find(resolvedDisplayId);
636 it != mMousePointersByDisplay.end()) {
637 return it->second->getPosition();
638 }
639 return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000640}
641
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900642void PointerChoreographer::setShowTouchesEnabled(bool enabled) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000643 PointerDisplayChange pointerDisplayChange;
644
645 { // acquire lock
646 std::scoped_lock _l(mLock);
647 if (mShowTouchesEnabled == enabled) {
648 return;
649 }
650 mShowTouchesEnabled = enabled;
651 pointerDisplayChange = updatePointerControllersLocked();
652 } // release lock
653
654 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900655}
656
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900657void PointerChoreographer::setStylusPointerIconEnabled(bool enabled) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000658 PointerDisplayChange pointerDisplayChange;
659
660 { // acquire lock
661 std::scoped_lock _l(mLock);
662 if (mStylusPointerIconEnabled == enabled) {
663 return;
664 }
665 mStylusPointerIconEnabled = enabled;
666 pointerDisplayChange = updatePointerControllersLocked();
667 } // release lock
668
669 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900670}
671
Byoungho Jung99326452023-11-03 20:19:17 +0900672bool PointerChoreographer::setPointerIcon(
Linnan Li13bf76a2024-05-05 19:18:02 +0800673 std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
674 ui::LogicalDisplayId displayId, DeviceId deviceId) {
Byoungho Jung99326452023-11-03 20:19:17 +0900675 std::scoped_lock _l(mLock);
676 if (deviceId < 0) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000677 LOG(WARNING) << "Invalid device id " << deviceId << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900678 return false;
679 }
680 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
681 if (!info) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000682 LOG(WARNING) << "No input device info found for id " << deviceId
683 << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900684 return false;
685 }
686 const uint32_t sources = info->getSources();
Byoungho Jung99326452023-11-03 20:19:17 +0900687
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000688 if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)) {
689 auto it = mDrawingTabletPointersByDevice.find(deviceId);
690 if (it != mDrawingTabletPointersByDevice.end()) {
691 setIconForController(icon, *it->second);
692 return true;
Byoungho Jung99326452023-11-03 20:19:17 +0900693 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000694 }
695 if (isFromSource(sources, AINPUT_SOURCE_STYLUS)) {
696 auto it = mStylusPointersByDevice.find(deviceId);
697 if (it != mStylusPointersByDevice.end()) {
698 setIconForController(icon, *it->second);
699 return true;
700 }
701 }
702 if (isFromSource(sources, AINPUT_SOURCE_MOUSE)) {
703 auto it = mMousePointersByDisplay.find(displayId);
704 if (it != mMousePointersByDisplay.end()) {
705 setIconForController(icon, *it->second);
706 return true;
Byoungho Jung99326452023-11-03 20:19:17 +0900707 } else {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000708 LOG(WARNING) << "No mouse pointer controller found for display " << displayId
709 << ", device " << deviceId << ".";
Byoungho Jung99326452023-11-03 20:19:17 +0900710 return false;
711 }
Byoungho Jung99326452023-11-03 20:19:17 +0900712 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000713 LOG(WARNING) << "Cannot set pointer icon for display " << displayId << ", device " << deviceId
714 << ".";
715 return false;
Byoungho Jung99326452023-11-03 20:19:17 +0900716}
717
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000718void PointerChoreographer::onWindowInfosChangedLocked(
719 const std::vector<android::gui::WindowInfo>& windowInfos) {
720 // Mark all spot controllers secure on displays containing secure windows and
721 // remove secure flag from others if required
Linnan Li13bf76a2024-05-05 19:18:02 +0800722 std::unordered_set<ui::LogicalDisplayId> privacySensitiveDisplays;
723 std::unordered_set<ui::LogicalDisplayId> allDisplayIds;
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000724 for (const auto& windowInfo : windowInfos) {
725 allDisplayIds.insert(windowInfo.displayId);
726 if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
727 windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
728 privacySensitiveDisplays.insert(windowInfo.displayId);
729 }
730 }
731
732 for (auto& it : mTouchPointersByDevice) {
733 auto& pc = it.second;
Linnan Li13bf76a2024-05-05 19:18:02 +0800734 for (ui::LogicalDisplayId displayId : allDisplayIds) {
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000735 pc->setSkipScreenshot(displayId,
736 privacySensitiveDisplays.find(displayId) !=
737 privacySensitiveDisplays.end());
738 }
739 }
740 // TODO (b/325252005): update skip screenshot flag for other types of pointer controllers
741}
742
Linnan Li13bf76a2024-05-05 19:18:02 +0800743void PointerChoreographer::setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) {
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000744 std::scoped_lock lock(mLock);
745 if (visible) {
746 mDisplaysWithPointersHidden.erase(displayId);
747 // We do not unfade the icons here, because we don't know when the last event happened.
748 return;
749 }
750
751 mDisplaysWithPointersHidden.emplace(displayId);
752
753 // Hide any icons that are currently visible on the display.
754 if (auto it = mMousePointersByDisplay.find(displayId); it != mMousePointersByDisplay.end()) {
755 const auto& [_, controller] = *it;
756 controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
757 }
758 for (const auto& [_, controller] : mStylusPointersByDevice) {
759 if (controller->getDisplayId() == displayId) {
760 controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
761 }
762 }
763}
764
Prabir Pradhan19767602023-11-03 16:53:31 +0000765PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
Linnan Li13bf76a2024-05-05 19:18:02 +0800766 ui::LogicalDisplayId displayId) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000767 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
768 [this, displayId]() REQUIRES(mLock) {
769 auto pc = mPolicy.createPointerController(
770 PointerControllerInterface::ControllerType::MOUSE);
771 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
772 pc->setDisplayViewport(*viewport);
773 }
774 return pc;
775 };
776 return ConstructorDelegate(std::move(ctor));
777}
778
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900779PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
Linnan Li13bf76a2024-05-05 19:18:02 +0800780 ui::LogicalDisplayId displayId) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900781 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
782 [this, displayId]() REQUIRES(mLock) {
783 auto pc = mPolicy.createPointerController(
784 PointerControllerInterface::ControllerType::STYLUS);
785 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
786 pc->setDisplayViewport(*viewport);
787 }
788 return pc;
789 };
790 return ConstructorDelegate(std::move(ctor));
791}
792
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000793void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfosChanged(
794 const gui::WindowInfosUpdate& windowInfosUpdate) {
795 std::scoped_lock _l(mListenerLock);
796 if (mPointerChoreographer != nullptr) {
797 mPointerChoreographer->onWindowInfosChanged(windowInfosUpdate.windowInfos);
798 }
799}
800
801void PointerChoreographer::PointerChoreographerDisplayInfoListener::
802 onPointerChoreographerDestroyed() {
803 std::scoped_lock _l(mListenerLock);
804 mPointerChoreographer = nullptr;
805}
806
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000807} // namespace android