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