blob: 4ca7323bfc23cbf2ed952e5a19dbfac29a490c98 [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#pragma once
18
19#include "InputListener.h"
20#include "NotifyArgs.h"
21#include "PointerChoreographerPolicyInterface.h"
22
Byoungho Jungda10dd32023-10-06 17:03:45 +090023#include <android-base/thread_annotations.h>
Arpit Singh4b6ad2d2024-04-04 11:54:20 +000024#include <gui/WindowInfosListener.h>
Prabir Pradhan19767602023-11-03 16:53:31 +000025#include <type_traits>
Arpit Singh420d0742024-04-04 11:54:20 +000026#include <unordered_set>
Byoungho Jungda10dd32023-10-06 17:03:45 +090027
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000028namespace android {
29
Byoungho Jung99326452023-11-03 20:19:17 +090030struct SpriteIcon;
31
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000032/**
Prabir Pradhan19767602023-11-03 16:53:31 +000033 * A helper class that wraps a factory method that acts as a constructor for the type returned
34 * by the factory method.
35 */
36template <typename Factory>
37struct ConstructorDelegate {
38 constexpr ConstructorDelegate(Factory&& factory) : mFactory(std::move(factory)) {}
39
40 using ConstructedType = std::invoke_result_t<const Factory&>;
41 constexpr operator ConstructedType() const { return mFactory(); }
42
43 Factory mFactory;
44};
45
46/**
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000047 * PointerChoreographer manages the icons shown by the system for input interactions.
48 * This includes showing the mouse cursor, stylus hover icons, and touch spots.
49 * It is responsible for accumulating the location of the mouse cursor, and populating
50 * the cursor position for incoming events, if necessary.
51 */
52class PointerChoreographerInterface : public InputListenerInterface {
53public:
54 /**
Byoungho Jungda10dd32023-10-06 17:03:45 +090055 * Set the display that pointers, like the mouse cursor and drawing tablets,
56 * should be drawn on.
57 */
Linnan Li13bf76a2024-05-05 19:18:02 +080058 virtual void setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) = 0;
Byoungho Jungda10dd32023-10-06 17:03:45 +090059 virtual void setDisplayViewports(const std::vector<DisplayViewport>& viewports) = 0;
60 virtual std::optional<DisplayViewport> getViewportForPointerDevice(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070061 ui::LogicalDisplayId associatedDisplayId = ui::LogicalDisplayId::INVALID) = 0;
Linnan Li13bf76a2024-05-05 19:18:02 +080062 virtual FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId) = 0;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +090063 virtual void setShowTouchesEnabled(bool enabled) = 0;
Byoungho Jungd6fe27b2023-10-27 20:49:38 +090064 virtual void setStylusPointerIconEnabled(bool enabled) = 0;
Prabir Pradhan521f4fc2023-12-04 19:09:59 +000065 /**
66 * Set the icon that is shown for the given pointer. The request may fail in some cases, such
67 * as if the device or display was removed, or if the cursor was moved to a different display.
68 * Returns true if the icon was changed successfully, false otherwise.
69 */
Byoungho Jung99326452023-11-03 20:19:17 +090070 virtual bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
Linnan Li13bf76a2024-05-05 19:18:02 +080071 ui::LogicalDisplayId displayId, DeviceId deviceId) = 0;
Prabir Pradhan502ddbd2024-01-19 02:22:38 +000072 /**
73 * Set whether pointer icons for mice, touchpads, and styluses should be visible on the
74 * given display.
75 */
Linnan Li13bf76a2024-05-05 19:18:02 +080076 virtual void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) = 0;
Byoungho Jung99326452023-11-03 20:19:17 +090077
Byoungho Jungda10dd32023-10-06 17:03:45 +090078 /**
Arpit Singhb65e2bd2024-06-03 09:48:16 +000079 * Used by Dispatcher to notify changes in the current focused display.
80 */
81 virtual void setFocusedDisplay(ui::LogicalDisplayId displayId) = 0;
82
83 /**
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000084 * This method may be called on any thread (usually by the input manager on a binder thread).
85 */
86 virtual void dump(std::string& dump) = 0;
87};
88
89class PointerChoreographer : public PointerChoreographerInterface {
90public:
91 explicit PointerChoreographer(InputListenerInterface& listener,
92 PointerChoreographerPolicyInterface&);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +000093 ~PointerChoreographer() override;
Prabir Pradhanb56e92c2023-06-09 23:40:37 +000094
Linnan Li13bf76a2024-05-05 19:18:02 +080095 void setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) override;
Byoungho Jungda10dd32023-10-06 17:03:45 +090096 void setDisplayViewports(const std::vector<DisplayViewport>& viewports) override;
97 std::optional<DisplayViewport> getViewportForPointerDevice(
Linnan Li13bf76a2024-05-05 19:18:02 +080098 ui::LogicalDisplayId associatedDisplayId) override;
99 FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId) override;
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900100 void setShowTouchesEnabled(bool enabled) override;
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900101 void setStylusPointerIconEnabled(bool enabled) override;
Byoungho Jung99326452023-11-03 20:19:17 +0900102 bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
Linnan Li13bf76a2024-05-05 19:18:02 +0800103 ui::LogicalDisplayId displayId, DeviceId deviceId) override;
104 void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) override;
Arpit Singhb65e2bd2024-06-03 09:48:16 +0000105 void setFocusedDisplay(ui::LogicalDisplayId displayId) override;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900106
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000107 void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000108 void notifyKey(const NotifyKeyArgs& args) override;
109 void notifyMotion(const NotifyMotionArgs& args) override;
110 void notifySwitch(const NotifySwitchArgs& args) override;
111 void notifySensor(const NotifySensorArgs& args) override;
112 void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
113 void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
114 void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
115
Arpit Singhe33845c2024-10-25 20:59:24 +0000116 // TODO(b/362719483) remove these when real topology is available
Arpit Singhf0169ab2024-11-18 20:44:35 +0000117 enum class DisplayPosition {
118 RIGHT,
119 TOP,
120 LEFT,
121 BOTTOM,
Arpit Singhe33845c2024-10-25 20:59:24 +0000122 ftl_last = BOTTOM,
123 };
124
125 struct AdjacentDisplay {
126 ui::LogicalDisplayId displayId;
127 DisplayPosition position;
128 float offsetPx;
129 };
130 void setDisplayTopology(
131 const std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>>&
132 displayTopology);
133
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000134 void dump(std::string& dump) override;
135
136private:
Linnan Li13bf76a2024-05-05 19:18:02 +0800137 using PointerDisplayChange = std::optional<
138 std::tuple<ui::LogicalDisplayId /*displayId*/, FloatPoint /*cursorPosition*/>>;
Arpit Singh7918c822024-11-20 11:28:44 +0000139
140 // PointerChoreographer's DisplayInfoListener can outlive the PointerChoreographer because when
141 // the listener is registered and called from display thread, a strong pointer to the listener
142 // (which can extend its lifecycle) is given away.
143 // If we use two locks it can also cause deadlocks due to race in acquiring them between the
144 // display and reader thread.
145 // To avoid these problems we use DisplayInfoListener's lock in PointerChoreographer.
146 std::mutex& getLock() const;
147
148 [[nodiscard]] PointerDisplayChange updatePointerControllersLocked() REQUIRES(getLock());
149 [[nodiscard]] PointerDisplayChange calculatePointerDisplayChangeToNotify() REQUIRES(getLock());
Linnan Li13bf76a2024-05-05 19:18:02 +0800150 const DisplayViewport* findViewportByIdLocked(ui::LogicalDisplayId displayId) const
Arpit Singh7918c822024-11-20 11:28:44 +0000151 REQUIRES(getLock());
Linnan Li13bf76a2024-05-05 19:18:02 +0800152 ui::LogicalDisplayId getTargetMouseDisplayLocked(ui::LogicalDisplayId associatedDisplayId) const
Arpit Singh7918c822024-11-20 11:28:44 +0000153 REQUIRES(getLock());
Linnan Li13bf76a2024-05-05 19:18:02 +0800154 std::pair<ui::LogicalDisplayId /*displayId*/, PointerControllerInterface&>
Arpit Singh7918c822024-11-20 11:28:44 +0000155 ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) REQUIRES(getLock());
156 InputDeviceInfo* findInputDeviceLocked(DeviceId deviceId) REQUIRES(getLock());
157 bool canUnfadeOnDisplay(ui::LogicalDisplayId displayId) REQUIRES(getLock());
Byoungho Jungda10dd32023-10-06 17:03:45 +0900158
Arpit Singhb65e2bd2024-06-03 09:48:16 +0000159 void fadeMouseCursorOnKeyPress(const NotifyKeyArgs& args);
Byoungho Jungda10dd32023-10-06 17:03:45 +0900160 NotifyMotionArgs processMotion(const NotifyMotionArgs& args);
Arpit Singh7918c822024-11-20 11:28:44 +0000161 NotifyMotionArgs processMouseEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
162 NotifyMotionArgs processTouchpadEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
163 void processDrawingTabletEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
164 void processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
165 void processStylusHoverEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
Arpit Singh5cd74972024-11-25 11:17:42 +0000166 void processPointerDeviceMotionEventLocked(NotifyMotionArgs& newArgs,
167 PointerControllerInterface& pc) REQUIRES(getLock());
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900168 void processDeviceReset(const NotifyDeviceResetArgs& args);
Arpit Singh7918c822024-11-20 11:28:44 +0000169 void onControllerAddedOrRemovedLocked() REQUIRES(getLock());
Arpit Singh420d0742024-04-04 11:54:20 +0000170 void onPrivacySensitiveDisplaysChangedLocked(
171 const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays)
Arpit Singh7918c822024-11-20 11:28:44 +0000172 REQUIRES(getLock());
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000173
Arpit Singhe33845c2024-10-25 20:59:24 +0000174 void handleUnconsumedDeltaLocked(PointerControllerInterface& pc,
175 const FloatPoint& unconsumedDelta) REQUIRES(getLock());
176
177 void populateFakeDisplayTopologyLocked(const std::vector<gui::DisplayInfo>& displayInfos)
178 REQUIRES(getLock());
179
Arpit Singhf0169ab2024-11-18 20:44:35 +0000180 std::optional<std::pair<const DisplayViewport*, float /*offset*/>> findDestinationDisplayLocked(
181 const ui::LogicalDisplayId sourceDisplayId, const DisplayPosition sourceBoundary,
182 float cursorOffset) const REQUIRES(getLock());
183
184 static vec2 calculateDestinationPosition(const DisplayViewport& destinationViewport,
185 float pointerOffset, DisplayPosition sourceBoundary);
Arpit Singhe33845c2024-10-25 20:59:24 +0000186
187 std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>> mTopology
188 GUARDED_BY(getLock());
189
Arpit Singh420d0742024-04-04 11:54:20 +0000190 /* This listener keeps tracks of visible privacy sensitive displays and updates the
191 * choreographer if there are any changes.
192 *
193 * Listener uses mListenerLock to guard all private data as choreographer and SurfaceComposer
194 * both can call into the listener. To prevent deadlocks Choreographer can call listener with
195 * its lock held, but listener must not call choreographer with its lock.
196 */
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000197 class PointerChoreographerDisplayInfoListener : public gui::WindowInfosListener {
198 public:
199 explicit PointerChoreographerDisplayInfoListener(PointerChoreographer* pc)
200 : mPointerChoreographer(pc){};
201 void onWindowInfosChanged(const gui::WindowInfosUpdate&) override;
Arpit Singh7918c822024-11-20 11:28:44 +0000202 void setInitialDisplayInfosLocked(const std::vector<gui::WindowInfo>& windowInfos)
203 REQUIRES(mLock);
204 std::unordered_set<ui::LogicalDisplayId> getPrivacySensitiveDisplaysLocked()
205 REQUIRES(mLock);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000206 void onPointerChoreographerDestroyed();
207
Arpit Singh7918c822024-11-20 11:28:44 +0000208 // This lock is also used by PointerChoreographer. See PointerChoreographer::getLock().
209 std::mutex mLock;
210
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000211 private:
Arpit Singh7918c822024-11-20 11:28:44 +0000212 PointerChoreographer* mPointerChoreographer GUARDED_BY(mLock);
Arpit Singh420d0742024-04-04 11:54:20 +0000213 std::unordered_set<ui::LogicalDisplayId /*displayId*/> mPrivacySensitiveDisplays
Arpit Singh7918c822024-11-20 11:28:44 +0000214 GUARDED_BY(mLock);
Arpit Singh4b6ad2d2024-04-04 11:54:20 +0000215 };
Byoungho Jungda10dd32023-10-06 17:03:45 +0900216
Prabir Pradhan19767602023-11-03 16:53:31 +0000217 using ControllerConstructor =
218 ConstructorDelegate<std::function<std::shared_ptr<PointerControllerInterface>()>>;
Arpit Singh7918c822024-11-20 11:28:44 +0000219 ControllerConstructor mTouchControllerConstructor GUARDED_BY(getLock());
Linnan Li13bf76a2024-05-05 19:18:02 +0800220 ControllerConstructor getMouseControllerConstructor(ui::LogicalDisplayId displayId)
Arpit Singh7918c822024-11-20 11:28:44 +0000221 REQUIRES(getLock());
Linnan Li13bf76a2024-05-05 19:18:02 +0800222 ControllerConstructor getStylusControllerConstructor(ui::LogicalDisplayId displayId)
Arpit Singh7918c822024-11-20 11:28:44 +0000223 REQUIRES(getLock());
Byoungho Jungda10dd32023-10-06 17:03:45 +0900224
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000225 InputListenerInterface& mNextListener;
Byoungho Jungda10dd32023-10-06 17:03:45 +0900226 PointerChoreographerPolicyInterface& mPolicy;
227
Linnan Li13bf76a2024-05-05 19:18:02 +0800228 std::map<ui::LogicalDisplayId, std::shared_ptr<PointerControllerInterface>>
Arpit Singh7918c822024-11-20 11:28:44 +0000229 mMousePointersByDisplay GUARDED_BY(getLock());
Byoungho Jung6f5b16b2023-10-27 18:22:07 +0900230 std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mTouchPointersByDevice
Arpit Singh7918c822024-11-20 11:28:44 +0000231 GUARDED_BY(getLock());
Byoungho Jungd6fe27b2023-10-27 20:49:38 +0900232 std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mStylusPointersByDevice
Arpit Singh7918c822024-11-20 11:28:44 +0000233 GUARDED_BY(getLock());
Prabir Pradhan4c977a42024-03-15 16:47:37 +0000234 std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mDrawingTabletPointersByDevice
Arpit Singh7918c822024-11-20 11:28:44 +0000235 GUARDED_BY(getLock());
Byoungho Jungda10dd32023-10-06 17:03:45 +0900236
Arpit Singh7918c822024-11-20 11:28:44 +0000237 ui::LogicalDisplayId mDefaultMouseDisplayId GUARDED_BY(getLock());
238 ui::LogicalDisplayId mNotifiedPointerDisplayId GUARDED_BY(getLock());
239 std::vector<InputDeviceInfo> mInputDeviceInfos GUARDED_BY(getLock());
240 std::set<DeviceId> mMouseDevices GUARDED_BY(getLock());
241 std::vector<DisplayViewport> mViewports GUARDED_BY(getLock());
242 bool mShowTouchesEnabled GUARDED_BY(getLock());
243 bool mStylusPointerIconEnabled GUARDED_BY(getLock());
Linnan Li13bf76a2024-05-05 19:18:02 +0800244 std::set<ui::LogicalDisplayId /*displayId*/> mDisplaysWithPointersHidden;
Arpit Singh7918c822024-11-20 11:28:44 +0000245 ui::LogicalDisplayId mCurrentFocusedDisplay GUARDED_BY(getLock());
Arpit Singhbd49b282024-05-23 18:02:54 +0000246
247protected:
248 using WindowListenerRegisterConsumer = std::function<std::vector<gui::WindowInfo>(
249 const sp<android::gui::WindowInfosListener>&)>;
250 using WindowListenerUnregisterConsumer =
251 std::function<void(const sp<android::gui::WindowInfosListener>&)>;
252 explicit PointerChoreographer(InputListenerInterface& listener,
253 PointerChoreographerPolicyInterface&,
254 const WindowListenerRegisterConsumer& registerListener,
255 const WindowListenerUnregisterConsumer& unregisterListener);
256
257private:
Arpit Singh7918c822024-11-20 11:28:44 +0000258 // WindowInfoListener object should always exist while PointerChoreographer exists, because we
259 // need to use the lock from it. But we don't always need to register the listener.
260 bool mIsWindowInfoListenerRegistered GUARDED_BY(getLock());
261 const sp<PointerChoreographerDisplayInfoListener> mWindowInfoListener;
Arpit Singhbd49b282024-05-23 18:02:54 +0000262 const WindowListenerRegisterConsumer mRegisterListener;
263 const WindowListenerUnregisterConsumer mUnregisterListener;
Prabir Pradhanb56e92c2023-06-09 23:40:37 +0000264};
265
266} // namespace android