1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef DEVICE_GAMEPAD_GAMEPAD_PROVIDER_H_
6 #define DEVICE_GAMEPAD_GAMEPAD_PROVIDER_H_
7 
8 #include <memory>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/callback_forward.h"
13 #include "base/macros.h"
14 #include "base/memory/read_only_shared_memory_region.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/synchronization/lock.h"
17 #include "base/system/system_monitor.h"
18 #include "base/time/time.h"
19 #include "device/gamepad/gamepad_export.h"
20 #include "device/gamepad/gamepad_pad_state_provider.h"
21 #include "device/gamepad/gamepad_shared_buffer.h"
22 #include "device/gamepad/public/cpp/gamepads.h"
23 #include "device/gamepad/public/mojom/gamepad.mojom.h"
24 #include "mojo/public/cpp/system/buffer.h"
25 
26 namespace base {
27 class SingleThreadTaskRunner;
28 class Thread;
29 }  // namespace base
30 
31 namespace device {
32 
33 class GamepadDataFetcher;
34 
35 class DEVICE_GAMEPAD_EXPORT GamepadConnectionChangeClient {
36  public:
37   virtual void OnGamepadConnectionChange(bool connected,
38                                          uint32_t index,
39                                          const Gamepad& pad) = 0;
40 };
41 
42 class DEVICE_GAMEPAD_EXPORT GamepadProvider
43     : public GamepadPadStateProvider,
44       public base::SystemMonitor::DevicesChangedObserver {
45  public:
46   explicit GamepadProvider(
47       GamepadConnectionChangeClient* connection_change_client);
48 
49   // Manually specifies the data fetcher and polling thread. The polling thread
50   // will be created normally if |polling_thread| is nullptr. Used for testing.
51   GamepadProvider(
52       GamepadConnectionChangeClient* connection_change_client,
53       std::unique_ptr<GamepadDataFetcher> fetcher,
54       std::unique_ptr<base::Thread> polling_thread);
55 
56   ~GamepadProvider() override;
57 
58   // Returns a duplicate of the shared memory region of the gamepad data.
59   base::ReadOnlySharedMemoryRegion DuplicateSharedMemoryRegion();
60 
61   void GetCurrentGamepadData(Gamepads* data);
62 
63   void PlayVibrationEffectOnce(
64       uint32_t pad_index,
65       mojom::GamepadHapticEffectType,
66       mojom::GamepadEffectParametersPtr,
67       mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback);
68 
69   void ResetVibrationActuator(
70       uint32_t pad_index,
71       mojom::GamepadHapticsManager::ResetVibrationActuatorCallback);
72 
73   // Pause and resume the background polling thread. Can be called from any
74   // thread.
75   void Pause();
76   void Resume();
77 
78   // Registers the given closure for calling when the user has interacted with
79   // the device. This callback will only be issued once.
80   void RegisterForUserGesture(base::OnceClosure closure);
81 
82   // base::SystemMonitor::DevicesChangedObserver implementation.
83   void OnDevicesChanged(base::SystemMonitor::DeviceType type) override;
84 
85   // Add a gamepad data fetcher. Takes ownership of |fetcher|.
86   void AddGamepadDataFetcher(std::unique_ptr<GamepadDataFetcher> fetcher);
87 
88   // Remove gamepad data fetchers with the given source.
89   void RemoveSourceGamepadDataFetcher(GamepadSource source);
90 
SetSanitizationEnabled(bool sanitize)91   void SetSanitizationEnabled(bool sanitize) { sanitize_ = sanitize; }
92 
93  private:
94   void Initialize(std::unique_ptr<GamepadDataFetcher> fetcher);
95 
96   // Method for setting up the platform-specific data fetcher. Takes ownership
97   // of |fetcher|.
98   void DoAddGamepadDataFetcher(std::unique_ptr<GamepadDataFetcher> fetcher);
99   void DoRemoveSourceGamepadDataFetcher(GamepadSource source);
100 
101   GamepadDataFetcher* GetSourceGamepadDataFetcher(GamepadSource source);
102 
103   // Method for sending pause hints to the low-level data fetcher. Runs on
104   // polling_thread_.
105   void SendPauseHint(bool paused);
106 
107   // Method for polling a GamepadDataFetcher. Runs on the polling_thread_.
108   void DoPoll();
109   void ScheduleDoPoll();
110 
111   void OnGamepadConnectionChange(bool connected,
112                                  uint32_t index,
113                                  const Gamepad& pad);
114 
115   // Checks the gamepad state to see if the user has interacted with it. Returns
116   // true if any user gesture observers were notified.
117   bool CheckForUserGesture();
118 
119   // GamepadPadStateProvider implementation.
120   void DisconnectUnrecognizedGamepad(GamepadSource source,
121                                      int source_id) override;
122 
123   void PlayEffectOnPollingThread(
124       uint32_t pad_index,
125       mojom::GamepadHapticEffectType,
126       mojom::GamepadEffectParametersPtr,
127       mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback,
128       scoped_refptr<base::SequencedTaskRunner>);
129 
130   void ResetVibrationOnPollingThread(
131       uint32_t pad_index,
132       mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback,
133       scoped_refptr<base::SequencedTaskRunner>);
134 
135   // The duration of the delay between iterations of DoPoll.
136   base::TimeDelta sampling_interval_delta_;
137 
138   // Keeps track of when the background thread is paused. Access to is_paused_
139   // must be guarded by is_paused_lock_.
140   base::Lock is_paused_lock_;
141   bool is_paused_ = true;
142 
143   // Keep track of when a polling task is schedlued, so as to prevent us from
144   // accidentally scheduling more than one at any time, when rapidly toggling
145   // |is_paused_|.
146   bool have_scheduled_do_poll_ = false;
147 
148   // Lists all observers registered for user gestures, and the thread which
149   // to issue the callbacks on. Since we always issue the callback on the
150   // thread which the registration happened, and this class lives on the I/O
151   // thread, the message loop proxies will normally just be the I/O thread.
152   // However, this will be the main thread for unit testing.
153   base::Lock user_gesture_lock_;
154   using ClosureAndThread =
155       std::pair<base::OnceClosure, scoped_refptr<base::SingleThreadTaskRunner>>;
156   using UserGestureObserverVector = std::vector<ClosureAndThread>;
157   UserGestureObserverVector user_gesture_observers_;
158 
159   // Updated based on notification from SystemMonitor when the system devices
160   // have been updated, and this notification is passed on to the data fetcher
161   // to enable it to avoid redundant (and possibly expensive) is-connected
162   // tests. Access to devices_changed_ must be guarded by
163   // devices_changed_lock_.
164   base::Lock devices_changed_lock_;
165   bool devices_changed_ = true;
166 
167   bool ever_had_user_gesture_ = false;
168   bool sanitize_ = true;
169 
170   // Only used on the polling thread.
171   using GamepadFetcherVector = std::vector<std::unique_ptr<GamepadDataFetcher>>;
172   GamepadFetcherVector data_fetchers_;
173 
174   base::Lock shared_memory_lock_;
175   std::unique_ptr<GamepadSharedBuffer> gamepad_shared_buffer_;
176 
177   // Polling is done on this background thread.
178   std::unique_ptr<base::Thread> polling_thread_;
179 
180   GamepadConnectionChangeClient* connection_change_client_;
181 
182   DISALLOW_COPY_AND_ASSIGN(GamepadProvider);
183 };
184 
185 }  // namespace device
186 
187 #endif  // DEVICE_GAMEPAD_GAMEPAD_PROVIDER_H_
188