blob: 7d3a2df550b0f34f12c541b0d7c3b045213fc675 [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
Byoungho Jungda10dd32023-10-06 17:03:45 +090033namespace {
Prabir Pradhan5a51a222024-03-05 03:54:00 +000034
Byoungho Jungda10dd32023-10-06 17:03:45 +090035bool isFromMouse(const NotifyMotionArgs& args) {
36 return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
37 args.pointerProperties[0].toolType == ToolType::MOUSE;
38}
39
Byoungho Jungee6268f2023-10-30 17:27:26 +090040bool isFromTouchpad(const NotifyMotionArgs& args) {
41 return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
42 args.pointerProperties[0].toolType == ToolType::FINGER;
43}
44
Prabir Pradhan4c977a42024-03-15 16:47:37 +000045bool isFromDrawingTablet(const NotifyMotionArgs& args) {
46 return isFromSource(args.source, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS) &&
47 isStylusToolType(args.pointerProperties[0].toolType);
48}
49
Byoungho Jungd6fe27b2023-10-27 20:49:38 +090050bool isHoverAction(int32_t action) {
51 return action == AMOTION_EVENT_ACTION_HOVER_ENTER ||
52 action == AMOTION_EVENT_ACTION_HOVER_MOVE || action == AMOTION_EVENT_ACTION_HOVER_EXIT;
53}
54
55bool isStylusHoverEvent(const NotifyMotionArgs& args) {
56 return isStylusEvent(args.source, args.pointerProperties) && isHoverAction(args.action);
57}
Prabir Pradhan5a51a222024-03-05 03:54:00 +000058
Prabir Pradhan4c977a42024-03-15 16:47:37 +000059bool isMouseOrTouchpad(uint32_t sources) {
60 // Check if this is a mouse or touchpad, but not a drawing tablet.
61 return isFromSource(sources, AINPUT_SOURCE_MOUSE_RELATIVE) ||
62 (isFromSource(sources, AINPUT_SOURCE_MOUSE) &&
63 !isFromSource(sources, AINPUT_SOURCE_STYLUS));
64}
65
Linnan Li13bf76a2024-05-05 19:18:02 +080066inline void notifyPointerDisplayChange(
67 std::optional<std::tuple<ui::LogicalDisplayId, FloatPoint>> change,
68 PointerChoreographerPolicyInterface& policy) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +000069 if (!change) {
70 return;
71 }
72 const auto& [displayId, cursorPosition] = *change;
73 policy.notifyPointerDisplayIdChanged(displayId, cursorPosition);
74}
75
Prabir Pradhan4c977a42024-03-15 16:47:37 +000076void setIconForController(const std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle>& icon,
77 PointerControllerInterface& controller) {
78 if (std::holds_alternative<std::unique_ptr<SpriteIcon>>(icon)) {
79 if (std::get<std::unique_ptr<SpriteIcon>>(icon) == nullptr) {
80 LOG(FATAL) << "SpriteIcon should not be null";
81 }
82 controller.setCustomPointerIcon(*std::get<std::unique_ptr<SpriteIcon>>(icon));
83 } else {
84 controller.updatePointerIcon(std::get<PointerIconStyle>(icon));
85 }
86}
87
Arpit Singh420d0742024-04-04 11:54:20 +000088// filters and returns a set of privacy sensitive displays that are currently visible.
89std::unordered_set<ui::LogicalDisplayId> getPrivacySensitiveDisplaysFromWindowInfos(
90 const std::vector<gui::WindowInfo>& windowInfos) {
91 std::unordered_set<ui::LogicalDisplayId> privacySensitiveDisplays;
92 for (const auto& windowInfo : windowInfos) {
93 if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
94 windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
95 privacySensitiveDisplays.insert(windowInfo.displayId);
96 }
97 }
98 return privacySensitiveDisplays;
99}
100
Byoungho Jungda10dd32023-10-06 17:03:45 +0900101} // namespace
102
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000103// --- PointerChoreographer ---
104
Arpit Singhbd49b282024-05-23 18:02:54 +0000105PointerChoreographer::PointerChoreographer(InputListenerInterface& inputListener,
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000106 PointerChoreographerPolicyInterface& policy)
Arpit Singhbd49b282024-05-23 18:02:54 +0000107 : PointerChoreographer(
108 inputListener, policy,
109 [](const sp<android::gui::WindowInfosListener>& listener) {
110 auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
111 std::vector<android::gui::DisplayInfo>{});
112#if defined(__ANDROID__)
113 SurfaceComposerClient::getDefault()->addWindowInfosListener(listener,
114 &initialInfo);
115#endif
116 return initialInfo.first;
117 },
118 [](const sp<android::gui::WindowInfosListener>& listener) {
119#if defined(__ANDROID__)
120 SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener);
121#endif
122 }) {
123}
124
125PointerChoreographer::PointerChoreographer(
126 android::InputListenerInterface& listener,
127 android::PointerChoreographerPolicyInterface& policy,
128 const android::PointerChoreographer::WindowListenerRegisterConsumer& registerListener,
129 const android::PointerChoreographer::WindowListenerUnregisterConsumer& unregisterListener)
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000130 : mTouchControllerConstructor([this]() {
Prabir Pradhan16788792023-11-08 21:07:21 +0000131 return mPolicy.createPointerController(
132 PointerControllerInterface::ControllerType::TOUCH);
133 }),
134 mNextListener(listener),
Byoungho Jungda10dd32023-10-06 17:03:45 +0900135 mPolicy(policy),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700136 mDefaultMouseDisplayId(ui::LogicalDisplayId::DEFAULT),
137 mNotifiedPointerDisplayId(ui::LogicalDisplayId::INVALID),
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900138 mShowTouchesEnabled(false),
Arpit Singhbd49b282024-05-23 18:02:54 +0000139 mStylusPointerIconEnabled(false),
140 mRegisterListener(registerListener),
141 mUnregisterListener(unregisterListener) {}
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000142
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000143PointerChoreographer::~PointerChoreographer() {
144 std::scoped_lock _l(mLock);
145 if (mWindowInfoListener == nullptr) {
146 return;
147 }
148 mWindowInfoListener->onPointerChoreographerDestroyed();
Arpit Singhbd49b282024-05-23 18:02:54 +0000149 mUnregisterListener(mWindowInfoListener);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000150}
151
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000152void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000153 PointerDisplayChange pointerDisplayChange;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900154
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000155 { // acquire lock
156 std::scoped_lock _l(mLock);
157
158 mInputDeviceInfos = args.inputDeviceInfos;
159 pointerDisplayChange = updatePointerControllersLocked();
160 } // release lock
161
162 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000163 mNextListener.notify(args);
164}
165
166void PointerChoreographer::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
167 mNextListener.notify(args);
168}
169
170void PointerChoreographer::notifyKey(const NotifyKeyArgs& args) {
171 mNextListener.notify(args);
172}
173
174void PointerChoreographer::notifyMotion(const NotifyMotionArgs& args) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900175 NotifyMotionArgs newArgs = processMotion(args);
176
177 mNextListener.notify(newArgs);
178}
179
180NotifyMotionArgs PointerChoreographer::processMotion(const NotifyMotionArgs& args) {
181 std::scoped_lock _l(mLock);
182
183 if (isFromMouse(args)) {
184 return processMouseEventLocked(args);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900185 } else if (isFromTouchpad(args)) {
186 return processTouchpadEventLocked(args);
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000187 } else if (isFromDrawingTablet(args)) {
188 processDrawingTabletEventLocked(args);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900189 } else if (mStylusPointerIconEnabled && isStylusHoverEvent(args)) {
190 processStylusHoverEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900191 } else if (isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN)) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900192 processTouchscreenAndStylusEventLocked(args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900193 }
194 return args;
195}
196
197NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotionArgs& args) {
198 if (args.getPointerCount() != 1) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000199 LOG(FATAL) << "Only mouse events with a single pointer are currently supported: "
200 << args.dump();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900201 }
202
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000203 mMouseDevices.emplace(args.deviceId);
Prabir Pradhan990d8712024-03-05 00:31:36 +0000204 auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
Nergi Rahardie0a4cfe2024-03-11 13:18:59 +0900205 NotifyMotionArgs newArgs(args);
206 newArgs.displayId = displayId;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900207
Nergi Rahardie0a4cfe2024-03-11 13:18:59 +0900208 if (MotionEvent::isValidCursorPosition(args.xCursorPosition, args.yCursorPosition)) {
209 // This is an absolute mouse device that knows about the location of the cursor on the
210 // display, so set the cursor position to the specified location.
211 const auto [x, y] = pc.getPosition();
212 const float deltaX = args.xCursorPosition - x;
213 const float deltaY = args.yCursorPosition - y;
214 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
215 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
216 pc.setPosition(args.xCursorPosition, args.yCursorPosition);
217 } else {
218 // This is a relative mouse, so move the cursor by the specified amount.
219 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
220 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
221 pc.move(deltaX, deltaY);
222 const auto [x, y] = pc.getPosition();
223 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
224 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
225 newArgs.xCursorPosition = x;
226 newArgs.yCursorPosition = y;
227 }
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000228 if (canUnfadeOnDisplay(displayId)) {
229 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
230 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900231 return newArgs;
232}
233
Byoungho Jungee6268f2023-10-30 17:27:26 +0900234NotifyMotionArgs PointerChoreographer::processTouchpadEventLocked(const NotifyMotionArgs& args) {
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000235 mMouseDevices.emplace(args.deviceId);
Prabir Pradhan990d8712024-03-05 00:31:36 +0000236 auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900237
238 NotifyMotionArgs newArgs(args);
239 newArgs.displayId = displayId;
240 if (args.getPointerCount() == 1 && args.classification == MotionClassification::NONE) {
241 // This is a movement of the mouse pointer.
242 const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
243 const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
244 pc.move(deltaX, deltaY);
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000245 if (canUnfadeOnDisplay(displayId)) {
246 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
247 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900248
249 const auto [x, y] = pc.getPosition();
250 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
251 newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
252 newArgs.xCursorPosition = x;
253 newArgs.yCursorPosition = y;
254 } else {
255 // This is a trackpad gesture with fake finger(s) that should not move the mouse pointer.
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000256 if (canUnfadeOnDisplay(displayId)) {
257 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
258 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900259
260 const auto [x, y] = pc.getPosition();
261 for (uint32_t i = 0; i < newArgs.getPointerCount(); i++) {
262 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X,
263 args.pointerCoords[i].getX() + x);
264 newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y,
265 args.pointerCoords[i].getY() + y);
266 }
267 newArgs.xCursorPosition = x;
268 newArgs.yCursorPosition = y;
269 }
270 return newArgs;
271}
272
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000273void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700274 if (args.displayId == ui::LogicalDisplayId::INVALID) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000275 return;
276 }
277
278 if (args.getPointerCount() != 1) {
279 LOG(WARNING) << "Only drawing tablet events with a single pointer are currently supported: "
280 << args.dump();
281 }
282
283 // Use a mouse pointer controller for drawing tablets, or create one if it doesn't exist.
Arpit Singh420d0742024-04-04 11:54:20 +0000284 auto [it, controllerAdded] =
285 mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
286 getMouseControllerConstructor(
287 args.displayId));
288 if (controllerAdded) {
289 onControllerAddedOrRemovedLocked();
290 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000291
292 PointerControllerInterface& pc = *it->second;
293
294 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
295 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
296 pc.setPosition(x, y);
297 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
298 // TODO(b/315815559): Do not fade and reset the icon if the hover exit will be followed
299 // immediately by a DOWN event.
300 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
301 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
302 } else if (canUnfadeOnDisplay(args.displayId)) {
303 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
304 }
305}
306
Byoungho Jungda10dd32023-10-06 17:03:45 +0900307/**
308 * When screen is touched, fade the mouse pointer on that display. We only call fade for
309 * ACTION_DOWN events.This would allow both mouse and touch to be used at the same time if the
310 * mouse device keeps moving and unfades the cursor.
311 * For touch events, we do not need to populate the cursor position.
312 */
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900313void PointerChoreographer::processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800314 if (!args.displayId.isValid()) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900315 return;
316 }
317
Byoungho Jungda10dd32023-10-06 17:03:45 +0900318 if (const auto it = mMousePointersByDisplay.find(args.displayId);
319 it != mMousePointersByDisplay.end() && args.action == AMOTION_EVENT_ACTION_DOWN) {
320 it->second->fade(PointerControllerInterface::Transition::GRADUAL);
321 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900322
323 if (!mShowTouchesEnabled) {
324 return;
325 }
326
327 // Get the touch pointer controller for the device, or create one if it doesn't exist.
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000328 auto [it, controllerAdded] =
329 mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
330 if (controllerAdded) {
Arpit Singh420d0742024-04-04 11:54:20 +0000331 onControllerAddedOrRemovedLocked();
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000332 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900333
334 PointerControllerInterface& pc = *it->second;
335
336 const PointerCoords* coords = args.pointerCoords.data();
337 const int32_t maskedAction = MotionEvent::getActionMasked(args.action);
338 const uint8_t actionIndex = MotionEvent::getActionIndex(args.action);
339 std::array<uint32_t, MAX_POINTER_ID + 1> idToIndex;
340 BitSet32 idBits;
341 if (maskedAction != AMOTION_EVENT_ACTION_UP && maskedAction != AMOTION_EVENT_ACTION_CANCEL) {
342 for (size_t i = 0; i < args.getPointerCount(); i++) {
343 if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP && actionIndex == i) {
344 continue;
345 }
346 uint32_t id = args.pointerProperties[i].id;
347 idToIndex[id] = i;
348 idBits.markBit(id);
349 }
350 }
351 // The PointerController already handles setting spots per-display, so
352 // we do not need to manually manage display changes for touch spots for now.
353 pc.setSpots(coords, idToIndex.cbegin(), idBits, args.displayId);
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000354}
355
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900356void PointerChoreographer::processStylusHoverEventLocked(const NotifyMotionArgs& args) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800357 if (!args.displayId.isValid()) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900358 return;
359 }
360
361 if (args.getPointerCount() != 1) {
362 LOG(WARNING) << "Only stylus hover events with a single pointer are currently supported: "
363 << args.dump();
364 }
365
366 // Get the stylus pointer controller for the device, or create one if it doesn't exist.
Arpit Singh420d0742024-04-04 11:54:20 +0000367 auto [it, controllerAdded] =
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900368 mStylusPointersByDevice.try_emplace(args.deviceId,
369 getStylusControllerConstructor(args.displayId));
Arpit Singh420d0742024-04-04 11:54:20 +0000370 if (controllerAdded) {
371 onControllerAddedOrRemovedLocked();
372 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900373
374 PointerControllerInterface& pc = *it->second;
375
376 const float x = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
377 const float y = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
378 pc.setPosition(x, y);
379 if (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000380 // TODO(b/315815559): Do not fade and reset the icon if the hover exit will be followed
381 // immediately by a DOWN event.
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900382 pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
Prabir Pradhan4b36db92024-01-03 20:56:57 +0000383 pc.updatePointerIcon(PointerIconStyle::TYPE_NOT_SPECIFIED);
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000384 } else if (canUnfadeOnDisplay(args.displayId)) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900385 pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
386 }
387}
388
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000389void PointerChoreographer::notifySwitch(const NotifySwitchArgs& args) {
390 mNextListener.notify(args);
391}
392
393void PointerChoreographer::notifySensor(const NotifySensorArgs& args) {
394 mNextListener.notify(args);
395}
396
397void PointerChoreographer::notifyVibratorState(const NotifyVibratorStateArgs& args) {
398 mNextListener.notify(args);
399}
400
401void PointerChoreographer::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900402 processDeviceReset(args);
403
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000404 mNextListener.notify(args);
405}
406
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900407void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) {
408 std::scoped_lock _l(mLock);
Prabir Pradhan16788792023-11-08 21:07:21 +0000409 mTouchPointersByDevice.erase(args.deviceId);
410 mStylusPointersByDevice.erase(args.deviceId);
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000411 mDrawingTabletPointersByDevice.erase(args.deviceId);
Arpit Singh420d0742024-04-04 11:54:20 +0000412 onControllerAddedOrRemovedLocked();
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000413}
414
Arpit Singh420d0742024-04-04 11:54:20 +0000415void PointerChoreographer::onControllerAddedOrRemovedLocked() {
Arpit Singhbd49b282024-05-23 18:02:54 +0000416 if (!com::android::input::flags::hide_pointer_indicators_for_secure_windows()) {
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000417 return;
418 }
Arpit Singh420d0742024-04-04 11:54:20 +0000419 bool requireListener = !mTouchPointersByDevice.empty() || !mMousePointersByDisplay.empty() ||
420 !mDrawingTabletPointersByDevice.empty() || !mStylusPointersByDevice.empty();
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000421
422 if (requireListener && mWindowInfoListener == nullptr) {
423 mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this);
Arpit Singhbd49b282024-05-23 18:02:54 +0000424 mWindowInfoListener->setInitialDisplayInfos(mRegisterListener(mWindowInfoListener));
Arpit Singh420d0742024-04-04 11:54:20 +0000425 onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000426 } else if (!requireListener && mWindowInfoListener != nullptr) {
Arpit Singhbd49b282024-05-23 18:02:54 +0000427 mUnregisterListener(mWindowInfoListener);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000428 mWindowInfoListener = nullptr;
Arpit Singh420d0742024-04-04 11:54:20 +0000429 } else if (requireListener && mWindowInfoListener != nullptr) {
430 // controller may have been added to an existing privacy sensitive display, we need to
431 // update all controllers again
432 onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
433 }
434}
435
436void PointerChoreographer::onPrivacySensitiveDisplaysChangedLocked(
437 const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
438 for (auto& [_, pc] : mTouchPointersByDevice) {
439 pc->clearSkipScreenshotFlags();
440 for (auto displayId : privacySensitiveDisplays) {
441 pc->setSkipScreenshotFlagForDisplay(displayId);
442 }
443 }
444
445 for (auto& [displayId, pc] : mMousePointersByDisplay) {
446 if (privacySensitiveDisplays.find(displayId) != privacySensitiveDisplays.end()) {
447 pc->setSkipScreenshotFlagForDisplay(displayId);
448 } else {
449 pc->clearSkipScreenshotFlags();
450 }
451 }
452
453 for (auto* pointerControllerByDevice :
454 {&mDrawingTabletPointersByDevice, &mStylusPointersByDevice}) {
455 for (auto& [_, pc] : *pointerControllerByDevice) {
456 auto displayId = pc->getDisplayId();
457 if (privacySensitiveDisplays.find(displayId) != privacySensitiveDisplays.end()) {
458 pc->setSkipScreenshotFlagForDisplay(displayId);
459 } else {
460 pc->clearSkipScreenshotFlags();
461 }
462 }
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000463 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900464}
465
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000466void PointerChoreographer::notifyPointerCaptureChanged(
467 const NotifyPointerCaptureChangedArgs& args) {
Hiroki Sato25040232024-02-22 17:21:22 +0900468 if (args.request.isEnable()) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900469 std::scoped_lock _l(mLock);
470 for (const auto& [_, mousePointerController] : mMousePointersByDisplay) {
471 mousePointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
472 }
473 }
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000474 mNextListener.notify(args);
475}
476
Arpit Singh420d0742024-04-04 11:54:20 +0000477void PointerChoreographer::onPrivacySensitiveDisplaysChanged(
478 const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000479 std::scoped_lock _l(mLock);
Arpit Singh420d0742024-04-04 11:54:20 +0000480 onPrivacySensitiveDisplaysChangedLocked(privacySensitiveDisplays);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000481}
482
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000483void PointerChoreographer::dump(std::string& dump) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900484 std::scoped_lock _l(mLock);
485
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000486 dump += "PointerChoreographer:\n";
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900487 dump += StringPrintf("show touches: %s\n", mShowTouchesEnabled ? "true" : "false");
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900488 dump += StringPrintf("stylus pointer icon enabled: %s\n",
489 mStylusPointerIconEnabled ? "true" : "false");
Byoungho Jungda10dd32023-10-06 17:03:45 +0900490
491 dump += INDENT "MousePointerControllers:\n";
492 for (const auto& [displayId, mousePointerController] : mMousePointersByDisplay) {
493 std::string pointerControllerDump = addLinePrefix(mousePointerController->dump(), INDENT);
Linnan Li13bf76a2024-05-05 19:18:02 +0800494 dump += INDENT + displayId.toString() + " : " + pointerControllerDump;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900495 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900496 dump += INDENT "TouchPointerControllers:\n";
497 for (const auto& [deviceId, touchPointerController] : mTouchPointersByDevice) {
498 std::string pointerControllerDump = addLinePrefix(touchPointerController->dump(), INDENT);
499 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
500 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900501 dump += INDENT "StylusPointerControllers:\n";
502 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
503 std::string pointerControllerDump = addLinePrefix(stylusPointerController->dump(), INDENT);
504 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
505 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000506 dump += INDENT "DrawingTabletControllers:\n";
507 for (const auto& [deviceId, drawingTabletController] : mDrawingTabletPointersByDevice) {
508 std::string pointerControllerDump = addLinePrefix(drawingTabletController->dump(), INDENT);
509 dump += INDENT + std::to_string(deviceId) + " : " + pointerControllerDump;
510 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900511 dump += "\n";
512}
513
Linnan Li13bf76a2024-05-05 19:18:02 +0800514const DisplayViewport* PointerChoreographer::findViewportByIdLocked(
515 ui::LogicalDisplayId displayId) const {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900516 for (auto& viewport : mViewports) {
517 if (viewport.displayId == displayId) {
518 return &viewport;
519 }
520 }
521 return nullptr;
522}
523
Linnan Li13bf76a2024-05-05 19:18:02 +0800524ui::LogicalDisplayId PointerChoreographer::getTargetMouseDisplayLocked(
525 ui::LogicalDisplayId associatedDisplayId) const {
526 return associatedDisplayId.isValid() ? associatedDisplayId : mDefaultMouseDisplayId;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900527}
528
Linnan Li13bf76a2024-05-05 19:18:02 +0800529std::pair<ui::LogicalDisplayId, PointerControllerInterface&>
530PointerChoreographer::ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) {
531 const ui::LogicalDisplayId displayId = getTargetMouseDisplayLocked(associatedDisplayId);
Byoungho Jungee6268f2023-10-30 17:27:26 +0900532
Prabir Pradhan990d8712024-03-05 00:31:36 +0000533 auto it = mMousePointersByDisplay.find(displayId);
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000534 if (it == mMousePointersByDisplay.end()) {
535 it = mMousePointersByDisplay.emplace(displayId, getMouseControllerConstructor(displayId))
536 .first;
Arpit Singh420d0742024-04-04 11:54:20 +0000537 onControllerAddedOrRemovedLocked();
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000538 }
Byoungho Jungee6268f2023-10-30 17:27:26 +0900539
540 return {displayId, *it->second};
541}
542
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900543InputDeviceInfo* PointerChoreographer::findInputDeviceLocked(DeviceId deviceId) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000544 auto it = std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
545 [deviceId](const auto& info) { return info.getId() == deviceId; });
546 return it != mInputDeviceInfos.end() ? &(*it) : nullptr;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900547}
548
Linnan Li13bf76a2024-05-05 19:18:02 +0800549bool PointerChoreographer::canUnfadeOnDisplay(ui::LogicalDisplayId displayId) {
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000550 return mDisplaysWithPointersHidden.find(displayId) == mDisplaysWithPointersHidden.end();
551}
552
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000553PointerChoreographer::PointerDisplayChange PointerChoreographer::updatePointerControllersLocked() {
Linnan Li13bf76a2024-05-05 19:18:02 +0800554 std::set<ui::LogicalDisplayId /*displayId*/> mouseDisplaysToKeep;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900555 std::set<DeviceId> touchDevicesToKeep;
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900556 std::set<DeviceId> stylusDevicesToKeep;
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000557 std::set<DeviceId> drawingTabletDevicesToKeep;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900558
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000559 // Mark the displayIds or deviceIds of PointerControllers currently needed, and create
560 // new PointerControllers if necessary.
Byoungho Jungda10dd32023-10-06 17:03:45 +0900561 for (const auto& info : mInputDeviceInfos) {
Linnan Li48f80da2024-04-22 18:38:16 +0000562 if (!info.isEnabled()) {
563 // If device is disabled, we should not keep it, and should not show pointer for
564 // disabled mouse device.
565 continue;
566 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900567 const uint32_t sources = info.getSources();
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000568 const bool isKnownMouse = mMouseDevices.count(info.getId()) != 0;
569
570 if (isMouseOrTouchpad(sources) || isKnownMouse) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800571 const ui::LogicalDisplayId displayId =
572 getTargetMouseDisplayLocked(info.getAssociatedDisplayId());
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000573 mouseDisplaysToKeep.insert(displayId);
574 // For mice, show the cursor immediately when the device is first connected or
575 // when it moves to a new display.
576 auto [mousePointerIt, isNewMousePointer] =
577 mMousePointersByDisplay.try_emplace(displayId,
578 getMouseControllerConstructor(displayId));
Arpit Singh420d0742024-04-04 11:54:20 +0000579 if (isNewMousePointer) {
580 onControllerAddedOrRemovedLocked();
581 }
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000582
Prabir Pradhan5a31d3c2024-03-29 20:23:22 +0000583 mMouseDevices.emplace(info.getId());
584 if ((!isKnownMouse || isNewMousePointer) && canUnfadeOnDisplay(displayId)) {
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000585 mousePointerIt->second->unfade(PointerControllerInterface::Transition::IMMEDIATE);
586 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900587 }
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900588 if (isFromSource(sources, AINPUT_SOURCE_TOUCHSCREEN) && mShowTouchesEnabled &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800589 info.getAssociatedDisplayId().isValid()) {
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900590 touchDevicesToKeep.insert(info.getId());
591 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900592 if (isFromSource(sources, AINPUT_SOURCE_STYLUS) && mStylusPointerIconEnabled &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800593 info.getAssociatedDisplayId().isValid()) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900594 stylusDevicesToKeep.insert(info.getId());
595 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000596 if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE) &&
Linnan Li13bf76a2024-05-05 19:18:02 +0800597 info.getAssociatedDisplayId().isValid()) {
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000598 drawingTabletDevicesToKeep.insert(info.getId());
599 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900600 }
601
602 // Remove PointerControllers no longer needed.
Prabir Pradhan19767602023-11-03 16:53:31 +0000603 std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000604 return mouseDisplaysToKeep.find(pair.first) == mouseDisplaysToKeep.end();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900605 });
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900606 std::erase_if(mTouchPointersByDevice, [&touchDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000607 return touchDevicesToKeep.find(pair.first) == touchDevicesToKeep.end();
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900608 });
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900609 std::erase_if(mStylusPointersByDevice, [&stylusDevicesToKeep](const auto& pair) {
Prabir Pradhan16788792023-11-08 21:07:21 +0000610 return stylusDevicesToKeep.find(pair.first) == stylusDevicesToKeep.end();
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900611 });
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000612 std::erase_if(mDrawingTabletPointersByDevice, [&drawingTabletDevicesToKeep](const auto& pair) {
613 return drawingTabletDevicesToKeep.find(pair.first) == drawingTabletDevicesToKeep.end();
614 });
Prabir Pradhan6506f6f2023-12-11 20:48:39 +0000615 std::erase_if(mMouseDevices, [&](DeviceId id) REQUIRES(mLock) {
616 return std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
617 [id](const auto& info) { return info.getId() == id; }) ==
618 mInputDeviceInfos.end();
619 });
Byoungho Jungda10dd32023-10-06 17:03:45 +0900620
Arpit Singh420d0742024-04-04 11:54:20 +0000621 onControllerAddedOrRemovedLocked();
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000622
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000623 // Check if we need to notify the policy if there's a change on the pointer display ID.
624 return calculatePointerDisplayChangeToNotify();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900625}
626
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000627PointerChoreographer::PointerDisplayChange
628PointerChoreographer::calculatePointerDisplayChangeToNotify() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700629 ui::LogicalDisplayId displayIdToNotify = ui::LogicalDisplayId::INVALID;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900630 FloatPoint cursorPosition = {0, 0};
631 if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
632 it != mMousePointersByDisplay.end()) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000633 const auto& pointerController = it->second;
634 // Use the displayId from the pointerController, because it accurately reflects whether
635 // the viewport has been added for that display. Otherwise, we would have to check if
636 // the viewport exists separately.
637 displayIdToNotify = pointerController->getDisplayId();
638 cursorPosition = pointerController->getPosition();
Byoungho Jungda10dd32023-10-06 17:03:45 +0900639 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900640 if (mNotifiedPointerDisplayId == displayIdToNotify) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000641 return {};
Byoungho Jungda10dd32023-10-06 17:03:45 +0900642 }
Byoungho Jungda10dd32023-10-06 17:03:45 +0900643 mNotifiedPointerDisplayId = displayIdToNotify;
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000644 return {{displayIdToNotify, cursorPosition}};
Byoungho Jungda10dd32023-10-06 17:03:45 +0900645}
646
Linnan Li13bf76a2024-05-05 19:18:02 +0800647void PointerChoreographer::setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000648 PointerDisplayChange pointerDisplayChange;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900649
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000650 { // acquire lock
651 std::scoped_lock _l(mLock);
652
653 mDefaultMouseDisplayId = displayId;
654 pointerDisplayChange = updatePointerControllersLocked();
655 } // release lock
656
657 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900658}
659
660void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000661 PointerDisplayChange pointerDisplayChange;
662
663 { // acquire lock
664 std::scoped_lock _l(mLock);
665 for (const auto& viewport : viewports) {
Linnan Li13bf76a2024-05-05 19:18:02 +0800666 const ui::LogicalDisplayId displayId = viewport.displayId;
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000667 if (const auto it = mMousePointersByDisplay.find(displayId);
668 it != mMousePointersByDisplay.end()) {
669 it->second->setDisplayViewport(viewport);
670 }
671 for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
672 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
673 if (info && info->getAssociatedDisplayId() == displayId) {
674 stylusPointerController->setDisplayViewport(viewport);
675 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900676 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000677 for (const auto& [deviceId, drawingTabletController] : mDrawingTabletPointersByDevice) {
678 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
679 if (info && info->getAssociatedDisplayId() == displayId) {
680 drawingTabletController->setDisplayViewport(viewport);
681 }
682 }
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900683 }
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000684 mViewports = viewports;
685 pointerDisplayChange = calculatePointerDisplayChangeToNotify();
686 } // release lock
687
688 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900689}
690
691std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
Linnan Li13bf76a2024-05-05 19:18:02 +0800692 ui::LogicalDisplayId associatedDisplayId) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900693 std::scoped_lock _l(mLock);
Linnan Li13bf76a2024-05-05 19:18:02 +0800694 const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900695 if (const auto viewport = findViewportByIdLocked(resolvedDisplayId); viewport) {
696 return *viewport;
697 }
698 return std::nullopt;
699}
700
Linnan Li13bf76a2024-05-05 19:18:02 +0800701FloatPoint PointerChoreographer::getMouseCursorPosition(ui::LogicalDisplayId displayId) {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900702 std::scoped_lock _l(mLock);
Linnan Li13bf76a2024-05-05 19:18:02 +0800703 const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900704 if (auto it = mMousePointersByDisplay.find(resolvedDisplayId);
705 it != mMousePointersByDisplay.end()) {
706 return it->second->getPosition();
707 }
708 return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000709}
710
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900711void PointerChoreographer::setShowTouchesEnabled(bool enabled) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000712 PointerDisplayChange pointerDisplayChange;
713
714 { // acquire lock
715 std::scoped_lock _l(mLock);
716 if (mShowTouchesEnabled == enabled) {
717 return;
718 }
719 mShowTouchesEnabled = enabled;
720 pointerDisplayChange = updatePointerControllersLocked();
721 } // release lock
722
723 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900724}
725
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900726void PointerChoreographer::setStylusPointerIconEnabled(bool enabled) {
Prabir Pradhan5a51a222024-03-05 03:54:00 +0000727 PointerDisplayChange pointerDisplayChange;
728
729 { // acquire lock
730 std::scoped_lock _l(mLock);
731 if (mStylusPointerIconEnabled == enabled) {
732 return;
733 }
734 mStylusPointerIconEnabled = enabled;
735 pointerDisplayChange = updatePointerControllersLocked();
736 } // release lock
737
738 notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900739}
740
Byoungho Jung99326452023-11-03 20:19:17 +0900741bool PointerChoreographer::setPointerIcon(
Linnan Li13bf76a2024-05-05 19:18:02 +0800742 std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
743 ui::LogicalDisplayId displayId, DeviceId deviceId) {
Byoungho Jung99326452023-11-03 20:19:17 +0900744 std::scoped_lock _l(mLock);
745 if (deviceId < 0) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000746 LOG(WARNING) << "Invalid device id " << deviceId << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900747 return false;
748 }
749 const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
750 if (!info) {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000751 LOG(WARNING) << "No input device info found for id " << deviceId
752 << ". Cannot set pointer icon.";
Byoungho Jung99326452023-11-03 20:19:17 +0900753 return false;
754 }
755 const uint32_t sources = info->getSources();
Byoungho Jung99326452023-11-03 20:19:17 +0900756
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000757 if (isFromSource(sources, AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)) {
758 auto it = mDrawingTabletPointersByDevice.find(deviceId);
759 if (it != mDrawingTabletPointersByDevice.end()) {
760 setIconForController(icon, *it->second);
761 return true;
Byoungho Jung99326452023-11-03 20:19:17 +0900762 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000763 }
764 if (isFromSource(sources, AINPUT_SOURCE_STYLUS)) {
765 auto it = mStylusPointersByDevice.find(deviceId);
766 if (it != mStylusPointersByDevice.end()) {
767 setIconForController(icon, *it->second);
768 return true;
769 }
770 }
771 if (isFromSource(sources, AINPUT_SOURCE_MOUSE)) {
772 auto it = mMousePointersByDisplay.find(displayId);
773 if (it != mMousePointersByDisplay.end()) {
774 setIconForController(icon, *it->second);
775 return true;
Byoungho Jung99326452023-11-03 20:19:17 +0900776 } else {
Prabir Pradhan521f4fc2023-12-04 19:09:59 +0000777 LOG(WARNING) << "No mouse pointer controller found for display " << displayId
778 << ", device " << deviceId << ".";
Byoungho Jung99326452023-11-03 20:19:17 +0900779 return false;
780 }
Byoungho Jung99326452023-11-03 20:19:17 +0900781 }
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000782 LOG(WARNING) << "Cannot set pointer icon for display " << displayId << ", device " << deviceId
783 << ".";
784 return false;
Byoungho Jung99326452023-11-03 20:19:17 +0900785}
786
Linnan Li13bf76a2024-05-05 19:18:02 +0800787void PointerChoreographer::setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) {
Prabir Pradhan502ddbd2024-01-19 02:22:38 +0000788 std::scoped_lock lock(mLock);
789 if (visible) {
790 mDisplaysWithPointersHidden.erase(displayId);
791 // We do not unfade the icons here, because we don't know when the last event happened.
792 return;
793 }
794
795 mDisplaysWithPointersHidden.emplace(displayId);
796
797 // Hide any icons that are currently visible on the display.
798 if (auto it = mMousePointersByDisplay.find(displayId); it != mMousePointersByDisplay.end()) {
799 const auto& [_, controller] = *it;
800 controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
801 }
802 for (const auto& [_, controller] : mStylusPointersByDevice) {
803 if (controller->getDisplayId() == displayId) {
804 controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
805 }
806 }
807}
808
Prabir Pradhan19767602023-11-03 16:53:31 +0000809PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
Linnan Li13bf76a2024-05-05 19:18:02 +0800810 ui::LogicalDisplayId displayId) {
Prabir Pradhan19767602023-11-03 16:53:31 +0000811 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
812 [this, displayId]() REQUIRES(mLock) {
813 auto pc = mPolicy.createPointerController(
814 PointerControllerInterface::ControllerType::MOUSE);
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
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900823PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
Linnan Li13bf76a2024-05-05 19:18:02 +0800824 ui::LogicalDisplayId displayId) {
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900825 std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
826 [this, displayId]() REQUIRES(mLock) {
827 auto pc = mPolicy.createPointerController(
828 PointerControllerInterface::ControllerType::STYLUS);
829 if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
830 pc->setDisplayViewport(*viewport);
831 }
832 return pc;
833 };
834 return ConstructorDelegate(std::move(ctor));
835}
836
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000837void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfosChanged(
838 const gui::WindowInfosUpdate& windowInfosUpdate) {
839 std::scoped_lock _l(mListenerLock);
Arpit Singh420d0742024-04-04 11:54:20 +0000840 if (mPointerChoreographer == nullptr) {
841 return;
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000842 }
Arpit Singh420d0742024-04-04 11:54:20 +0000843 auto newPrivacySensitiveDisplays =
844 getPrivacySensitiveDisplaysFromWindowInfos(windowInfosUpdate.windowInfos);
845 if (newPrivacySensitiveDisplays != mPrivacySensitiveDisplays) {
846 mPrivacySensitiveDisplays = std::move(newPrivacySensitiveDisplays);
847 mPointerChoreographer->onPrivacySensitiveDisplaysChanged(mPrivacySensitiveDisplays);
848 }
849}
850
851void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfos(
852 const std::vector<gui::WindowInfo>& windowInfos) {
853 std::scoped_lock _l(mListenerLock);
854 mPrivacySensitiveDisplays = getPrivacySensitiveDisplaysFromWindowInfos(windowInfos);
855}
856
857std::unordered_set<ui::LogicalDisplayId /*displayId*/>
858PointerChoreographer::PointerChoreographerDisplayInfoListener::getPrivacySensitiveDisplays() {
859 std::scoped_lock _l(mListenerLock);
860 return mPrivacySensitiveDisplays;
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000861}
862
863void PointerChoreographer::PointerChoreographerDisplayInfoListener::
864 onPointerChoreographerDestroyed() {
865 std::scoped_lock _l(mListenerLock);
866 mPointerChoreographer = nullptr;
867}
868
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000869} // namespace android