1 /*
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 
23 #include <android-base/thread_annotations.h>
24 #include <gui/WindowInfosListener.h>
25 #include <type_traits>
26 #include <unordered_set>
27 
28 namespace android {
29 
30 struct SpriteIcon;
31 
32 /**
33  * A helper class that wraps a factory method that acts as a constructor for the type returned
34  * by the factory method.
35  */
36 template <typename Factory>
37 struct ConstructorDelegate {
ConstructorDelegateConstructorDelegate38     constexpr ConstructorDelegate(Factory&& factory) : mFactory(std::move(factory)) {}
39 
40     using ConstructedType = std::invoke_result_t<const Factory&>;
ConstructedTypeConstructorDelegate41     constexpr operator ConstructedType() const { return mFactory(); }
42 
43     Factory mFactory;
44 };
45 
46 /**
47  * 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  */
52 class PointerChoreographerInterface : public InputListenerInterface {
53 public:
54     /**
55      * Set the display that pointers, like the mouse cursor and drawing tablets,
56      * should be drawn on.
57      */
58     virtual void setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) = 0;
59     virtual void setDisplayViewports(const std::vector<DisplayViewport>& viewports) = 0;
60     virtual std::optional<DisplayViewport> getViewportForPointerDevice(
61             ui::LogicalDisplayId associatedDisplayId = ui::LogicalDisplayId::INVALID) = 0;
62     virtual FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId) = 0;
63     virtual void setShowTouchesEnabled(bool enabled) = 0;
64     virtual void setStylusPointerIconEnabled(bool enabled) = 0;
65     /**
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      */
70     virtual bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
71                                 ui::LogicalDisplayId displayId, DeviceId deviceId) = 0;
72     /**
73      * Set whether pointer icons for mice, touchpads, and styluses should be visible on the
74      * given display.
75      */
76     virtual void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) = 0;
77 
78     /**
79      * Used by Dispatcher to notify changes in the current focused display.
80      */
81     virtual void setFocusedDisplay(ui::LogicalDisplayId displayId) = 0;
82 
83     /**
84      * 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 
89 class PointerChoreographer : public PointerChoreographerInterface {
90 public:
91     explicit PointerChoreographer(InputListenerInterface& listener,
92                                   PointerChoreographerPolicyInterface&);
93     ~PointerChoreographer() override;
94 
95     void setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) override;
96     void setDisplayViewports(const std::vector<DisplayViewport>& viewports) override;
97     std::optional<DisplayViewport> getViewportForPointerDevice(
98             ui::LogicalDisplayId associatedDisplayId) override;
99     FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId) override;
100     void setShowTouchesEnabled(bool enabled) override;
101     void setStylusPointerIconEnabled(bool enabled) override;
102     bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
103                         ui::LogicalDisplayId displayId, DeviceId deviceId) override;
104     void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) override;
105     void setFocusedDisplay(ui::LogicalDisplayId displayId) override;
106 
107     void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
108     void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
109     void notifyKey(const NotifyKeyArgs& args) override;
110     void notifyMotion(const NotifyMotionArgs& args) override;
111     void notifySwitch(const NotifySwitchArgs& args) override;
112     void notifySensor(const NotifySensorArgs& args) override;
113     void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
114     void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
115     void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
116 
117     void dump(std::string& dump) override;
118 
119 private:
120     using PointerDisplayChange = std::optional<
121             std::tuple<ui::LogicalDisplayId /*displayId*/, FloatPoint /*cursorPosition*/>>;
122     [[nodiscard]] PointerDisplayChange updatePointerControllersLocked() REQUIRES(mLock);
123     [[nodiscard]] PointerDisplayChange calculatePointerDisplayChangeToNotify() REQUIRES(mLock);
124     const DisplayViewport* findViewportByIdLocked(ui::LogicalDisplayId displayId) const
125             REQUIRES(mLock);
126     ui::LogicalDisplayId getTargetMouseDisplayLocked(ui::LogicalDisplayId associatedDisplayId) const
127             REQUIRES(mLock);
128     std::pair<ui::LogicalDisplayId /*displayId*/, PointerControllerInterface&>
129     ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) REQUIRES(mLock);
130     InputDeviceInfo* findInputDeviceLocked(DeviceId deviceId) REQUIRES(mLock);
131     bool canUnfadeOnDisplay(ui::LogicalDisplayId displayId) REQUIRES(mLock);
132 
133     void fadeMouseCursorOnKeyPress(const NotifyKeyArgs& args);
134     NotifyMotionArgs processMotion(const NotifyMotionArgs& args);
135     NotifyMotionArgs processMouseEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
136     NotifyMotionArgs processTouchpadEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
137     void processDrawingTabletEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
138     void processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
139     void processStylusHoverEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
140     void processDeviceReset(const NotifyDeviceResetArgs& args);
141     void onControllerAddedOrRemovedLocked() REQUIRES(mLock);
142     void onPrivacySensitiveDisplaysChangedLocked(
143             const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays)
144             REQUIRES(mLock);
145     void onPrivacySensitiveDisplaysChanged(
146             const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays);
147 
148     /* This listener keeps tracks of visible privacy sensitive displays and updates the
149      * choreographer if there are any changes.
150      *
151      * Listener uses mListenerLock to guard all private data as choreographer and SurfaceComposer
152      * both can call into the listener. To prevent deadlocks Choreographer can call listener with
153      * its lock held, but listener must not call choreographer with its lock.
154      */
155     class PointerChoreographerDisplayInfoListener : public gui::WindowInfosListener {
156     public:
PointerChoreographerDisplayInfoListener(PointerChoreographer * pc)157         explicit PointerChoreographerDisplayInfoListener(PointerChoreographer* pc)
158               : mPointerChoreographer(pc){};
159         void onWindowInfosChanged(const gui::WindowInfosUpdate&) override;
160         void setInitialDisplayInfos(const std::vector<gui::WindowInfo>& windowInfos);
161         std::unordered_set<ui::LogicalDisplayId /*displayId*/> getPrivacySensitiveDisplays();
162         void onPointerChoreographerDestroyed();
163 
164     private:
165         std::mutex mListenerLock;
166         PointerChoreographer* mPointerChoreographer GUARDED_BY(mListenerLock);
167         std::unordered_set<ui::LogicalDisplayId /*displayId*/> mPrivacySensitiveDisplays
168                 GUARDED_BY(mListenerLock);
169     };
170     sp<PointerChoreographerDisplayInfoListener> mWindowInfoListener GUARDED_BY(mLock);
171 
172     using ControllerConstructor =
173             ConstructorDelegate<std::function<std::shared_ptr<PointerControllerInterface>()>>;
174     ControllerConstructor mTouchControllerConstructor GUARDED_BY(mLock);
175     ControllerConstructor getMouseControllerConstructor(ui::LogicalDisplayId displayId)
176             REQUIRES(mLock);
177     ControllerConstructor getStylusControllerConstructor(ui::LogicalDisplayId displayId)
178             REQUIRES(mLock);
179 
180     std::mutex mLock;
181 
182     InputListenerInterface& mNextListener;
183     PointerChoreographerPolicyInterface& mPolicy;
184 
185     std::map<ui::LogicalDisplayId, std::shared_ptr<PointerControllerInterface>>
186             mMousePointersByDisplay GUARDED_BY(mLock);
187     std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mTouchPointersByDevice
188             GUARDED_BY(mLock);
189     std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mStylusPointersByDevice
190             GUARDED_BY(mLock);
191     std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mDrawingTabletPointersByDevice
192             GUARDED_BY(mLock);
193 
194     ui::LogicalDisplayId mDefaultMouseDisplayId GUARDED_BY(mLock);
195     ui::LogicalDisplayId mNotifiedPointerDisplayId GUARDED_BY(mLock);
196     std::vector<InputDeviceInfo> mInputDeviceInfos GUARDED_BY(mLock);
197     std::set<DeviceId> mMouseDevices GUARDED_BY(mLock);
198     std::vector<DisplayViewport> mViewports GUARDED_BY(mLock);
199     bool mShowTouchesEnabled GUARDED_BY(mLock);
200     bool mStylusPointerIconEnabled GUARDED_BY(mLock);
201     std::set<ui::LogicalDisplayId /*displayId*/> mDisplaysWithPointersHidden;
202     ui::LogicalDisplayId mCurrentFocusedDisplay GUARDED_BY(mLock);
203 
204 protected:
205     using WindowListenerRegisterConsumer = std::function<std::vector<gui::WindowInfo>(
206             const sp<android::gui::WindowInfosListener>&)>;
207     using WindowListenerUnregisterConsumer =
208             std::function<void(const sp<android::gui::WindowInfosListener>&)>;
209     explicit PointerChoreographer(InputListenerInterface& listener,
210                                   PointerChoreographerPolicyInterface&,
211                                   const WindowListenerRegisterConsumer& registerListener,
212                                   const WindowListenerUnregisterConsumer& unregisterListener);
213 
214 private:
215     const WindowListenerRegisterConsumer mRegisterListener;
216     const WindowListenerUnregisterConsumer mUnregisterListener;
217 };
218 
219 } // namespace android
220