blob: 02453ef7a0090c748eb9e9d1136ed5b63d2ee6cb [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
Arpit Singh420d0742024-04-04 11:54:20 +000092// filters and returns a set of privacy sensitive displays that are currently visible.
93std::unordered_set<ui::LogicalDisplayId> getPrivacySensitiveDisplaysFromWindowInfos(
94 const std::vector<gui::WindowInfo>& windowInfos) {
95 std::unordered_set<ui::LogicalDisplayId> privacySensitiveDisplays;
96 for (const auto& windowInfo : windowInfos) {
97 if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
98 windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
99 privacySensitiveDisplays.insert(windowInfo.displayId);
100 }
101 }
102 return privacySensitiveDisplays;
103}
104
Byoungho Jungda10dd32023-10-06 17:03:45 +0900105} // namespace
106
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000107// --- PointerChoreographer ---
108
109PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
110 PointerChoreographerPolicyInterface& policy)
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000111 : mTouchControllerConstructor([this]() {
Prabir Pradhan16788792023-11-08 21:07:21 +0000112 return mPolicy.createPointerController(
113 PointerControllerInterface::ControllerType::TOUCH);
114 }),
115 mNextListener(listener),
Byoungho Jungda10dd32023-10-06 17:03:45 +0900116 mPolicy(policy),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700117 mDefaultMouseDisplayId(ui::LogicalDisplayId::DEFAULT),
118 mNotifiedPointerDisplayId(ui::LogicalDisplayId::INVALID),
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900119 mShowTouchesEnabled(false),
120 mStylusPointerIconEnabled(false) {}
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000121
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000122PointerChoreographer::~PointerChoreographer() {
123 std::scoped_lock _l(mLock);
124 if (mWindowInfoListener == nullptr) {
125 return;
126 }
127 mWindowInfoListener->onPointerChoreographerDestroyed();
128}
129
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000130void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000131 PointerDisplayChange pointerDisplayChange;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900132
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000133 { // acquire lock
134 std::scoped_lock _l(mLock);
135
136 mInputDeviceInfos = args.inputDeviceInfos;
137 pointerDisplayChange = updatePointerControllersLocked();
138 } // release lock
139
140 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000141 mNextListener.notify(args);
142}
143
144void PointerChoreographer::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
145 mNextListener.notify(args);
146}
147
148void PointerChoreographer::notifyKey(const NotifyKeyArgs& args) {
149 mNextListener.notify(args);
150}
151
152void PointerChoreographer::notifyMotion(const NotifyMotionArgs& args) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900153 NotifyMotionArgs newArgs = processMotion(args);
154
155 mNextListener.notify(newArgs);
156}
157
158NotifyMotionArgs PointerChoreographer::processMotion(const NotifyMotionArgs& args) {
159 std::scoped_lock _l(mLock);
160
161 if (isFromMouse(args)) {
162 return processMouseEventLocked(args);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900163 } else if (isFromTouchpad(args)) {
164 return processTouchpadEventLocked(args);
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000165 } else if (isFromDrawingTablet(args)) {
166 processDrawingTabletEventLocked(args);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900167 } else if (mStylusPointerIconEnabled && isStylusHoverEvent(args)) {
168 processStylusHoverEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900169 } else if (isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN)) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900170 processTouchscreenAndStylusEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900171 }
172 return args;
173}
174
175NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotionArgs& args) {
176 if (args.getPointerCount() != 1) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000177 LOG(FATAL) << "Only mouse events with a single pointer are currently supported: "
178 << args.dump();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900179 }
180
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000181 mMouseDevices.emplace(args.deviceId);
Prabir Pradhan990d8712024-03-05 00:31:36 +0000182 auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
Nergi Rahardie0a4cfe2024-03-11 13:18:59 +0900183 NotifyMotionArgs newArgs(args);
184 newArgs.displayId = displayId;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900185
Nergi Rahardie0a4cfe2024-03-11 13:18:59 +0900186 if (MotionEvent::isValidCursorPosition(args.xCursorPosition, args.yCursorPosition)) {
187 // This is an absolute mouse device that knows about the location of the cursor on the
188 // display, so set the cursor position to the specified location.
189 const auto [x, y] = pc.getPosition();
190 const float deltaX = args.xCursorPosition - x;
191 const float deltaY = args.yCursorPosition - y;
192 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
193 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
194 pc.setPosition(args.xCursorPosition, args.yCursorPosition);
195 } else {
196 // This is a relative mouse, so move the cursor by the specified amount.
197 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
198 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
199 pc.move(deltaX, deltaY);
200 const auto [x, y] = pc.getPosition();
201 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
202 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
203 newArgs.xCursorPosition = x;
204 newArgs.yCursorPosition = y;
205 }
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000206 if (canUnfadeOnDisplay(displayId)) {
207 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
208 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900209 return newArgs;
210}
211
Byoungho Jungee6268f2023-10-30 17:27:26 +0900212NotifyMotionArgs PointerChoreographer::processTouchpadEventLocked(const NotifyMotionArgs& args) {
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000213 mMouseDevices.emplace(args.deviceId);
Prabir Pradhan990d8712024-03-05 00:31:36 +0000214 auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900215
216 NotifyMotionArgs newArgs(args);
217 newArgs.displayId = displayId;
218 if (args.getPointerCount() == 1 && args.classification == MotionClassification::NONE) {
219 // This is a movement of the mouse pointer.
220 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
221 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
222 pc.move(deltaX, deltaY);
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000223 if (canUnfadeOnDisplay(displayId)) {
224 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
225 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900226
227 const auto [x, y] = pc.getPosition();
228 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
229 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
230 newArgs.xCursorPosition = x;
231 newArgs.yCursorPosition = y;
232 } else {
233 // This is a trackpad gesture with fake finger(s) that should not move the mouse pointer.
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000234 if (canUnfadeOnDisplay(displayId)) {
235 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
236 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900237
238 const auto [x, y] = pc.getPosition();
239 for (uint32_t i = 0; i < newArgs.getPointerCount(); i++) {
240 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X,
241 args.pointerCoords[i].getX() + x);
242 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y,
243 args.pointerCoords[i].getY() + y);
244 }
245 newArgs.xCursorPosition = x;
246 newArgs.yCursorPosition = y;
247 }
248 return newArgs;
249}
250
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000251void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700252 if (args.displayId == ui::LogicalDisplayId::INVALID) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000253 return;
254 }
255
256 if (args.getPointerCount() != 1) {
257 LOG(WARNING) << "Only drawing tablet events with a single pointer are currently supported: "
258 << args.dump();
259 }
260
261 // Use a mouse pointer controller for drawing tablets, or create one if it doesn't exist.
Arpit Singh420d0742024-04-04 11:54:20 +0000262 auto [it, controllerAdded] =
263 mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
264 getMouseControllerConstructor(
265 args.displayId));
266 if (controllerAdded) {
267 onControllerAddedOrRemovedLocked();
268 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000269
270 PointerControllerInterface& pc = *it->second;
271
272 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
273 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
274 pc.setPosition(x, y);
275 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
276 // TODO(b/315815559): Do not fade and reset the icon if the hover exit will be followed
277 // immediately by a DOWN event.
278 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
279 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
280 } else if (canUnfadeOnDisplay(args.displayId)) {
281 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
282 }
283}
284
Byoungho Jungda10dd32023-10-06 17:03:45 +0900285/**
286 * When screen is touched, fade the mouse pointer on that display. We only call fade for
287 * ACTION_DOWN events.This would allow both mouse and touch to be used at the same time if the
288 * mouse device keeps moving and unfades the cursor.
289 * For touch events, we do not need to populate the cursor position.
290 */
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900291void PointerChoreographer::processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800292 if (!args.displayId.isValid()) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900293 return;
294 }
295
Byoungho Jungda10dd32023-10-06 17:03:45 +0900296 if (const auto it = mMousePointersByDisplay.find(args.displayId);
297 it != mMousePointersByDisplay.end() && args.action == AMOTION_EVENT_ACTION_DOWN) {
298 it->second->fade(PointerControllerInterface::Transition::GRADUAL);
299 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900300
301 if (!mShowTouchesEnabled) {
302 return;
303 }
304
305 // Get the touch pointer controller for the device, or create one if it doesn't exist.
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000306 auto [it, controllerAdded] =
307 mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
308 if (controllerAdded) {
Arpit Singh420d0742024-04-04 11:54:20 +0000309 onControllerAddedOrRemovedLocked();
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000310 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900311
312 PointerControllerInterface& pc = *it->second;
313
314 const PointerCoords* coords = args.pointerCoords.data();
315 const int32_t maskedAction = MotionEvent::getActionMasked(args.action);
316 const uint8_t actionIndex = MotionEvent::getActionIndex(args.action);
317 std::array<uint32_t, MAX_POINTER_ID + 1> idToIndex;
318 BitSet32 idBits;
319 if (maskedAction != AMOTION_EVENT_ACTION_UP && maskedAction != AMOTION_EVENT_ACTION_CANCEL) {
320 for (size_t i = 0; i < args.getPointerCount(); i++) {
321 if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP && actionIndex == i) {
322 continue;
323 }
324 uint32_t id = args.pointerProperties[i].id;
325 idToIndex[id] = i;
326 idBits.markBit(id);
327 }
328 }
329 // The PointerController already handles setting spots per-display, so
330 // we do not need to manually manage display changes for touch spots for now.
331 pc.setSpots(coords, idToIndex.cbegin(), idBits, args.displayId);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000332}
333
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900334void PointerChoreographer::processStylusHoverEventLocked(const NotifyMotionArgs& args) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800335 if (!args.displayId.isValid()) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900336 return;
337 }
338
339 if (args.getPointerCount() != 1) {
340 LOG(WARNING) << "Only stylus hover events with a single pointer are currently supported: "
341 << args.dump();
342 }
343
344 // Get the stylus pointer controller for the device, or create one if it doesn't exist.
Arpit Singh420d0742024-04-04 11:54:20 +0000345 auto [it, controllerAdded] =
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900346 mStylusPointersByDevice.try_emplace(args.deviceId,
347 getStylusControllerConstructor(args.displayId));
Arpit Singh420d0742024-04-04 11:54:20 +0000348 if (controllerAdded) {
349 onControllerAddedOrRemovedLocked();
350 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900351
352 PointerControllerInterface& pc = *it->second;
353
354 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
355 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
356 pc.setPosition(x, y);
357 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000358 // TODO(b/315815559): Do not fade and reset the icon if the hover exit will be followed
359 // immediately by a DOWN event.
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900360 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
Prabir Pradhan4b36db92024-01-03 20:56:57 +0000361 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000362 } else if (canUnfadeOnDisplay(args.displayId)) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900363 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
364 }
365}
366
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000367void PointerChoreographer::notifySwitch(const NotifySwitchArgs& args) {
368 mNextListener.notify(args);
369}
370
371void PointerChoreographer::notifySensor(const NotifySensorArgs& args) {
372 mNextListener.notify(args);
373}
374
375void PointerChoreographer::notifyVibratorState(const NotifyVibratorStateArgs& args) {
376 mNextListener.notify(args);
377}
378
379void PointerChoreographer::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900380 processDeviceReset(args);
381
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000382 mNextListener.notify(args);
383}
384
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900385void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) {
386 std::scoped_lock _l(mLock);
Prabir Pradhan16788792023-11-08 21:07:21 +0000387 mTouchPointersByDevice.erase(args.deviceId);
388 mStylusPointersByDevice.erase(args.deviceId);
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000389 mDrawingTabletPointersByDevice.erase(args.deviceId);
Arpit Singh420d0742024-04-04 11:54:20 +0000390 onControllerAddedOrRemovedLocked();
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000391}
392
Arpit Singh420d0742024-04-04 11:54:20 +0000393void PointerChoreographer::onControllerAddedOrRemovedLocked() {
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000394 if (!HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS) {
395 return;
396 }
Arpit Singh420d0742024-04-04 11:54:20 +0000397 bool requireListener = !mTouchPointersByDevice.empty() || !mMousePointersByDisplay.empty() ||
398 !mDrawingTabletPointersByDevice.empty() || !mStylusPointersByDevice.empty();
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000399
400 if (requireListener && mWindowInfoListener == nullptr) {
401 mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this);
402 auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
403 std::vector<android::gui::DisplayInfo>{});
404#if defined(__ANDROID__)
405 SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener,
406 &initialInfo);
407#endif
Arpit Singh420d0742024-04-04 11:54:20 +0000408 mWindowInfoListener->setInitialDisplayInfos(initialInfo.first);
409 onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000410 } else if (!requireListener && mWindowInfoListener != nullptr) {
411#if defined(__ANDROID__)
412 SurfaceComposerClient::getDefault()->removeWindowInfosListener(mWindowInfoListener);
413#endif
414 mWindowInfoListener = nullptr;
Arpit Singh420d0742024-04-04 11:54:20 +0000415 } else if (requireListener && mWindowInfoListener != nullptr) {
416 // controller may have been added to an existing privacy sensitive display, we need to
417 // update all controllers again
418 onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
419 }
420}
421
422void PointerChoreographer::onPrivacySensitiveDisplaysChangedLocked(
423 const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
424 for (auto& [_, pc] : mTouchPointersByDevice) {
425 pc->clearSkipScreenshotFlags();
426 for (auto displayId : privacySensitiveDisplays) {
427 pc->setSkipScreenshotFlagForDisplay(displayId);
428 }
429 }
430
431 for (auto& [displayId, pc] : mMousePointersByDisplay) {
432 if (privacySensitiveDisplays.find(displayId) != privacySensitiveDisplays.end()) {
433 pc->setSkipScreenshotFlagForDisplay(displayId);
434 } else {
435 pc->clearSkipScreenshotFlags();
436 }
437 }
438
439 for (auto* pointerControllerByDevice :
440 {&mDrawingTabletPointersByDevice, &mStylusPointersByDevice}) {
441 for (auto& [_, pc] : *pointerControllerByDevice) {
442 auto displayId = pc->getDisplayId();
443 if (privacySensitiveDisplays.find(displayId) != privacySensitiveDisplays.end()) {
444 pc->setSkipScreenshotFlagForDisplay(displayId);
445 } else {
446 pc->clearSkipScreenshotFlags();
447 }
448 }
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000449 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900450}
451
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000452void PointerChoreographer::notifyPointerCaptureChanged(
453 const NotifyPointerCaptureChangedArgs& args) {
Hiroki Sato25040232024-02-22 17:21:22 +0900454 if (args.request.isEnable()) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900455 std::scoped_lock _l(mLock);
456 for (const auto& [_, mousePointerController] : mMousePointersByDisplay) {
457 mousePointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
458 }
459 }
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000460 mNextListener.notify(args);
461}
462
Arpit Singh420d0742024-04-04 11:54:20 +0000463void PointerChoreographer::onPrivacySensitiveDisplaysChanged(
464 const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000465 std::scoped_lock _l(mLock);
Arpit Singh420d0742024-04-04 11:54:20 +0000466 onPrivacySensitiveDisplaysChangedLocked(privacySensitiveDisplays);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000467}
468
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000469void PointerChoreographer::dump(std::string& dump) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900470 std::scoped_lock _l(mLock);
471
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000472 dump += "PointerChoreographer:\n";
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900473 dump += StringPrintf("show touches: %s\n", mShowTouchesEnabled ? "true" : "false");
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900474 dump += StringPrintf("stylus pointer icon enabled: %s\n",
475 mStylusPointerIconEnabled ? "true" : "false");
Byoungho Jungda10dd32023-10-06 17:03:45 +0900476
477 dump += INDENT "MousePointerControllers:\n";
478 for (const auto& [displayId, mousePointerController] : mMousePointersByDisplay) {
479 std::string pointerControllerDump = addLinePrefix(mousePointerController->dump(), INDENT);
Linnan Li13bf76a2024-05-05 19:18:02 +0800480 dump += INDENT + displayId.toString() + " : " + pointerControllerDump;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900481 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900482 dump += INDENT "TouchPointerControllers:\n";
483 for (const auto& [deviceId, touchPointerController] : mTouchPointersByDevice) {
484 std::string pointerControllerDump = addLinePrefix(touchPointerController->dump(), INDENT);
485 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
486 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900487 dump += INDENT "StylusPointerControllers:\n";
488 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
489 std::string pointerControllerDump = addLinePrefix(stylusPointerController->dump(), INDENT);
490 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
491 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000492 dump += INDENT "DrawingTabletControllers:\n";
493 for (const auto& [deviceId, drawingTabletController] : mDrawingTabletPointersByDevice) {
494 std::string pointerControllerDump = addLinePrefix(drawingTabletController->dump(), INDENT);
495 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
496 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900497 dump += "\n";
498}
499
Linnan Li13bf76a2024-05-05 19:18:02 +0800500const DisplayViewport* PointerChoreographer::findViewportByIdLocked(
501 ui::LogicalDisplayId displayId) const {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900502 for (auto& viewport : mViewports) {
503 if (viewport.displayId == displayId) {
504 return &viewport;
505 }
506 }
507 return nullptr;
508}
509
Linnan Li13bf76a2024-05-05 19:18:02 +0800510ui::LogicalDisplayId PointerChoreographer::getTargetMouseDisplayLocked(
511 ui::LogicalDisplayId associatedDisplayId) const {
512 return associatedDisplayId.isValid() ? associatedDisplayId : mDefaultMouseDisplayId;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900513}
514
Linnan Li13bf76a2024-05-05 19:18:02 +0800515std::pair<ui::LogicalDisplayId, PointerControllerInterface&>
516PointerChoreographer::ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) {
517 const ui::LogicalDisplayId displayId = getTargetMouseDisplayLocked(associatedDisplayId);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900518
Prabir Pradhan990d8712024-03-05 00:31:36 +0000519 auto it = mMousePointersByDisplay.find(displayId);
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000520 if (it == mMousePointersByDisplay.end()) {
521 it = mMousePointersByDisplay.emplace(displayId, getMouseControllerConstructor(displayId))
522 .first;
Arpit Singh420d0742024-04-04 11:54:20 +0000523 onControllerAddedOrRemovedLocked();
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000524 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900525
526 return {displayId, *it->second};
527}
528
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900529InputDeviceInfo* PointerChoreographer::findInputDeviceLocked(DeviceId deviceId) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000530 auto it = std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
531 [deviceId](const auto& info) { return info.getId() == deviceId; });
532 return it != mInputDeviceInfos.end() ? &(*it) : nullptr;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900533}
534
Linnan Li13bf76a2024-05-05 19:18:02 +0800535bool PointerChoreographer::canUnfadeOnDisplay(ui::LogicalDisplayId displayId) {
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000536 return mDisplaysWithPointersHidden.find(displayId) == mDisplaysWithPointersHidden.end();
537}
538
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000539PointerChoreographer::PointerDisplayChange PointerChoreographer::updatePointerControllersLocked() {
Linnan Li13bf76a2024-05-05 19:18:02 +0800540 std::set<ui::LogicalDisplayId /*displayId*/> mouseDisplaysToKeep;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900541 std::set<DeviceId> touchDevicesToKeep;
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900542 std::set<DeviceId> stylusDevicesToKeep;
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000543 std::set<DeviceId> drawingTabletDevicesToKeep;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900544
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000545 // Mark the displayIds or deviceIds of PointerControllers currently needed, and create
546 // new PointerControllers if necessary.
Byoungho Jungda10dd32023-10-06 17:03:45 +0900547 for (const auto& info : mInputDeviceInfos) {
Linnan Li48f80da2024-04-22 18:38:16 +0000548 if (!info.isEnabled()) {
549 // If device is disabled, we should not keep it, and should not show pointer for
550 // disabled mouse device.
551 continue;
552 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900553 const uint32_t sources = info.getSources();
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000554 const bool isKnownMouse = mMouseDevices.count(info.getId()) != 0;
555
556 if (isMouseOrTouchpad(sources) || isKnownMouse) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800557 const ui::LogicalDisplayId displayId =
558 getTargetMouseDisplayLocked(info.getAssociatedDisplayId());
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000559 mouseDisplaysToKeep.insert(displayId);
560 // For mice, show the cursor immediately when the device is first connected or
561 // when it moves to a new display.
562 auto [mousePointerIt, isNewMousePointer] =
563 mMousePointersByDisplay.try_emplace(displayId,
564 getMouseControllerConstructor(displayId));
Arpit Singh420d0742024-04-04 11:54:20 +0000565 if (isNewMousePointer) {
566 onControllerAddedOrRemovedLocked();
567 }
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000568
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000569 mMouseDevices.emplace(info.getId());
570 if ((!isKnownMouse || isNewMousePointer) && canUnfadeOnDisplay(displayId)) {
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000571 mousePointerIt->second->unfade(PointerControllerInterface::Transition::IMMEDIATE);
572 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900573 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900574 if (isFromSource(sources, AINPUT_SOURCE_TOUCHSCREEN) && mShowTouchesEnabled &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800575 info.getAssociatedDisplayId().isValid()) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900576 touchDevicesToKeep.insert(info.getId());
577 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900578 if (isFromSource(sources, AINPUT_SOURCE_STYLUS) && mStylusPointerIconEnabled &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800579 info.getAssociatedDisplayId().isValid()) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900580 stylusDevicesToKeep.insert(info.getId());
581 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000582 if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE) &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800583 info.getAssociatedDisplayId().isValid()) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000584 drawingTabletDevicesToKeep.insert(info.getId());
585 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900586 }
587
588 // Remove PointerControllers no longer needed.
Prabir Pradhan19767602023-11-03 16:53:31 +0000589 std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000590 return mouseDisplaysToKeep.find(pair.first) == mouseDisplaysToKeep.end();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900591 });
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900592 std::erase_if(mTouchPointersByDevice, [&touchDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000593 return touchDevicesToKeep.find(pair.first) == touchDevicesToKeep.end();
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900594 });
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900595 std::erase_if(mStylusPointersByDevice, [&stylusDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000596 return stylusDevicesToKeep.find(pair.first) == stylusDevicesToKeep.end();
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900597 });
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000598 std::erase_if(mDrawingTabletPointersByDevice, [&drawingTabletDevicesToKeep](const auto& pair) {
599 return drawingTabletDevicesToKeep.find(pair.first) == drawingTabletDevicesToKeep.end();
600 });
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000601 std::erase_if(mMouseDevices, [&](DeviceId id) REQUIRES(mLock) {
602 return std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
603 [id](const auto& info) { return info.getId() == id; }) ==
604 mInputDeviceInfos.end();
605 });
Byoungho Jungda10dd32023-10-06 17:03:45 +0900606
Arpit Singh420d0742024-04-04 11:54:20 +0000607 onControllerAddedOrRemovedLocked();
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000608
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000609 // Check if we need to notify the policy if there's a change on the pointer display ID.
610 return calculatePointerDisplayChangeToNotify();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900611}
612
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000613PointerChoreographer::PointerDisplayChange
614PointerChoreographer::calculatePointerDisplayChangeToNotify() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700615 ui::LogicalDisplayId displayIdToNotify = ui::LogicalDisplayId::INVALID;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900616 FloatPoint cursorPosition = {0, 0};
617 if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
618 it != mMousePointersByDisplay.end()) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000619 const auto& pointerController = it->second;
620 // Use the displayId from the pointerController, because it accurately reflects whether
621 // the viewport has been added for that display. Otherwise, we would have to check if
622 // the viewport exists separately.
623 displayIdToNotify = pointerController->getDisplayId();
624 cursorPosition = pointerController->getPosition();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900625 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900626 if (mNotifiedPointerDisplayId == displayIdToNotify) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000627 return {};
Byoungho Jungda10dd32023-10-06 17:03:45 +0900628 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900629 mNotifiedPointerDisplayId = displayIdToNotify;
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000630 return {{displayIdToNotify, cursorPosition}};
Byoungho Jungda10dd32023-10-06 17:03:45 +0900631}
632
Linnan Li13bf76a2024-05-05 19:18:02 +0800633void PointerChoreographer::setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000634 PointerDisplayChange pointerDisplayChange;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900635
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000636 { // acquire lock
637 std::scoped_lock _l(mLock);
638
639 mDefaultMouseDisplayId = displayId;
640 pointerDisplayChange = updatePointerControllersLocked();
641 } // release lock
642
643 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900644}
645
646void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000647 PointerDisplayChange pointerDisplayChange;
648
649 { // acquire lock
650 std::scoped_lock _l(mLock);
651 for (const auto& viewport : viewports) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800652 const ui::LogicalDisplayId displayId = viewport.displayId;
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000653 if (const auto it = mMousePointersByDisplay.find(displayId);
654 it != mMousePointersByDisplay.end()) {
655 it->second->setDisplayViewport(viewport);
656 }
657 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
658 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
659 if (info && info->getAssociatedDisplayId() == displayId) {
660 stylusPointerController->setDisplayViewport(viewport);
661 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900662 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000663 for (const auto& [deviceId, drawingTabletController] : mDrawingTabletPointersByDevice) {
664 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
665 if (info && info->getAssociatedDisplayId() == displayId) {
666 drawingTabletController->setDisplayViewport(viewport);
667 }
668 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900669 }
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000670 mViewports = viewports;
671 pointerDisplayChange = calculatePointerDisplayChangeToNotify();
672 } // release lock
673
674 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900675}
676
677std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
Linnan Li13bf76a2024-05-05 19:18:02 +0800678 ui::LogicalDisplayId associatedDisplayId) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900679 std::scoped_lock _l(mLock);
Linnan Li13bf76a2024-05-05 19:18:02 +0800680 const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900681 if (const auto viewport = findViewportByIdLocked(resolvedDisplayId); viewport) {
682 return *viewport;
683 }
684 return std::nullopt;
685}
686
Linnan Li13bf76a2024-05-05 19:18:02 +0800687FloatPoint PointerChoreographer::getMouseCursorPosition(ui::LogicalDisplayId displayId) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900688 std::scoped_lock _l(mLock);
Linnan Li13bf76a2024-05-05 19:18:02 +0800689 const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900690 if (auto it = mMousePointersByDisplay.find(resolvedDisplayId);
691 it != mMousePointersByDisplay.end()) {
692 return it->second->getPosition();
693 }
694 return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000695}
696
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900697void PointerChoreographer::setShowTouchesEnabled(bool enabled) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000698 PointerDisplayChange pointerDisplayChange;
699
700 { // acquire lock
701 std::scoped_lock _l(mLock);
702 if (mShowTouchesEnabled == enabled) {
703 return;
704 }
705 mShowTouchesEnabled = enabled;
706 pointerDisplayChange = updatePointerControllersLocked();
707 } // release lock
708
709 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900710}
711
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900712void PointerChoreographer::setStylusPointerIconEnabled(bool enabled) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000713 PointerDisplayChange pointerDisplayChange;
714
715 { // acquire lock
716 std::scoped_lock _l(mLock);
717 if (mStylusPointerIconEnabled == enabled) {
718 return;
719 }
720 mStylusPointerIconEnabled = enabled;
721 pointerDisplayChange = updatePointerControllersLocked();
722 } // release lock
723
724 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900725}
726
Byoungho Jung99326452023-11-03 20:19:17 +0900727bool PointerChoreographer::setPointerIcon(
Linnan Li13bf76a2024-05-05 19:18:02 +0800728 std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
729 ui::LogicalDisplayId displayId, DeviceId deviceId) {
Byoungho Jung99326452023-11-03 20:19:17 +0900730 std::scoped_lock _l(mLock);
731 if (deviceId < 0) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000732 LOG(WARNING) << "Invalid device id " << deviceId << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900733 return false;
734 }
735 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
736 if (!info) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000737 LOG(WARNING) << "No input device info found for id " << deviceId
738 << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900739 return false;
740 }
741 const uint32_t sources = info->getSources();
Byoungho Jung99326452023-11-03 20:19:17 +0900742
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000743 if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)) {
744 auto it = mDrawingTabletPointersByDevice.find(deviceId);
745 if (it != mDrawingTabletPointersByDevice.end()) {
746 setIconForController(icon, *it->second);
747 return true;
Byoungho Jung99326452023-11-03 20:19:17 +0900748 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000749 }
750 if (isFromSource(sources, AINPUT_SOURCE_STYLUS)) {
751 auto it = mStylusPointersByDevice.find(deviceId);
752 if (it != mStylusPointersByDevice.end()) {
753 setIconForController(icon, *it->second);
754 return true;
755 }
756 }
757 if (isFromSource(sources, AINPUT_SOURCE_MOUSE)) {
758 auto it = mMousePointersByDisplay.find(displayId);
759 if (it != mMousePointersByDisplay.end()) {
760 setIconForController(icon, *it->second);
761 return true;
Byoungho Jung99326452023-11-03 20:19:17 +0900762 } else {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000763 LOG(WARNING) << "No mouse pointer controller found for display " << displayId
764 << ", device " << deviceId << ".";
Byoungho Jung99326452023-11-03 20:19:17 +0900765 return false;
766 }
Byoungho Jung99326452023-11-03 20:19:17 +0900767 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000768 LOG(WARNING) << "Cannot set pointer icon for display " << displayId << ", device " << deviceId
769 << ".";
770 return false;
Byoungho Jung99326452023-11-03 20:19:17 +0900771}
772
Linnan Li13bf76a2024-05-05 19:18:02 +0800773void PointerChoreographer::setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) {
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000774 std::scoped_lock lock(mLock);
775 if (visible) {
776 mDisplaysWithPointersHidden.erase(displayId);
777 // We do not unfade the icons here, because we don't know when the last event happened.
778 return;
779 }
780
781 mDisplaysWithPointersHidden.emplace(displayId);
782
783 // Hide any icons that are currently visible on the display.
784 if (auto it = mMousePointersByDisplay.find(displayId); it != mMousePointersByDisplay.end()) {
785 const auto& [_, controller] = *it;
786 controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
787 }
788 for (const auto& [_, controller] : mStylusPointersByDevice) {
789 if (controller->getDisplayId() == displayId) {
790 controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
791 }
792 }
793}
794
Prabir Pradhan19767602023-11-03 16:53:31 +0000795PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
Linnan Li13bf76a2024-05-05 19:18:02 +0800796 ui::LogicalDisplayId displayId) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000797 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
798 [this, displayId]() REQUIRES(mLock) {
799 auto pc = mPolicy.createPointerController(
800 PointerControllerInterface::ControllerType::MOUSE);
801 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
802 pc->setDisplayViewport(*viewport);
803 }
804 return pc;
805 };
806 return ConstructorDelegate(std::move(ctor));
807}
808
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900809PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
Linnan Li13bf76a2024-05-05 19:18:02 +0800810 ui::LogicalDisplayId displayId) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900811 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
812 [this, displayId]() REQUIRES(mLock) {
813 auto pc = mPolicy.createPointerController(
814 PointerControllerInterface::ControllerType::STYLUS);
815 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
816 pc->setDisplayViewport(*viewport);
817 }
818 return pc;
819 };
820 return ConstructorDelegate(std::move(ctor));
821}
822
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000823void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfosChanged(
824 const gui::WindowInfosUpdate& windowInfosUpdate) {
825 std::scoped_lock _l(mListenerLock);
Arpit Singh420d0742024-04-04 11:54:20 +0000826 if (mPointerChoreographer == nullptr) {
827 return;
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000828 }
Arpit Singh420d0742024-04-04 11:54:20 +0000829 auto newPrivacySensitiveDisplays =
830 getPrivacySensitiveDisplaysFromWindowInfos(windowInfosUpdate.windowInfos);
831 if (newPrivacySensitiveDisplays != mPrivacySensitiveDisplays) {
832 mPrivacySensitiveDisplays = std::move(newPrivacySensitiveDisplays);
833 mPointerChoreographer->onPrivacySensitiveDisplaysChanged(mPrivacySensitiveDisplays);
834 }
835}
836
837void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfos(
838 const std::vector<gui::WindowInfo>& windowInfos) {
839 std::scoped_lock _l(mListenerLock);
840 mPrivacySensitiveDisplays = getPrivacySensitiveDisplaysFromWindowInfos(windowInfos);
841}
842
843std::unordered_set<ui::LogicalDisplayId /*displayId*/>
844PointerChoreographer::PointerChoreographerDisplayInfoListener::getPrivacySensitiveDisplays() {
845 std::scoped_lock _l(mListenerLock);
846 return mPrivacySensitiveDisplays;
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000847}
848
849void PointerChoreographer::PointerChoreographerDisplayInfoListener::
850 onPointerChoreographerDestroyed() {
851 std::scoped_lock _l(mListenerLock);
852 mPointerChoreographer = nullptr;
853}
854
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000855} // namespace android