| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef DEVICE_GAMEPAD_GAMEPAD_PROVIDER_H_ |
| #define DEVICE_GAMEPAD_GAMEPAD_PROVIDER_H_ |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/callback_forward.h" |
| #include "base/macros.h" |
| #include "base/memory/read_only_shared_memory_region.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/synchronization/lock.h" |
| #include "base/system/system_monitor.h" |
| #include "base/time/time.h" |
| #include "device/gamepad/gamepad_export.h" |
| #include "device/gamepad/gamepad_pad_state_provider.h" |
| #include "device/gamepad/gamepad_shared_buffer.h" |
| #include "device/gamepad/public/cpp/gamepads.h" |
| #include "device/gamepad/public/mojom/gamepad.mojom.h" |
| #include "mojo/public/cpp/system/buffer.h" |
| |
| namespace base { |
| class SingleThreadTaskRunner; |
| class Thread; |
| } // namespace base |
| |
| namespace device { |
| |
| class GamepadDataFetcher; |
| |
| class DEVICE_GAMEPAD_EXPORT GamepadConnectionChangeClient { |
| public: |
| virtual void OnGamepadConnectionChange(bool connected, |
| uint32_t index, |
| const Gamepad& pad) = 0; |
| }; |
| |
| class DEVICE_GAMEPAD_EXPORT GamepadProvider |
| : public GamepadPadStateProvider, |
| public base::SystemMonitor::DevicesChangedObserver { |
| public: |
| explicit GamepadProvider( |
| GamepadConnectionChangeClient* connection_change_client); |
| |
| // Manually specifies the data fetcher and polling thread. The polling thread |
| // will be created normally if |polling_thread| is nullptr. Used for testing. |
| GamepadProvider( |
| GamepadConnectionChangeClient* connection_change_client, |
| std::unique_ptr<GamepadDataFetcher> fetcher, |
| std::unique_ptr<base::Thread> polling_thread); |
| |
| ~GamepadProvider() override; |
| |
| // Returns a duplicate of the shared memory region of the gamepad data. |
| base::ReadOnlySharedMemoryRegion DuplicateSharedMemoryRegion(); |
| |
| void GetCurrentGamepadData(Gamepads* data); |
| |
| void PlayVibrationEffectOnce( |
| uint32_t pad_index, |
| mojom::GamepadHapticEffectType, |
| mojom::GamepadEffectParametersPtr, |
| mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback); |
| |
| void ResetVibrationActuator( |
| uint32_t pad_index, |
| mojom::GamepadHapticsManager::ResetVibrationActuatorCallback); |
| |
| // Pause and resume the background polling thread. Can be called from any |
| // thread. |
| void Pause(); |
| void Resume(); |
| |
| // Registers the given closure for calling when the user has interacted with |
| // the device. This callback will only be issued once. |
| void RegisterForUserGesture(base::OnceClosure closure); |
| |
| // base::SystemMonitor::DevicesChangedObserver implementation. |
| void OnDevicesChanged(base::SystemMonitor::DeviceType type) override; |
| |
| // Add a gamepad data fetcher. Takes ownership of |fetcher|. |
| void AddGamepadDataFetcher(std::unique_ptr<GamepadDataFetcher> fetcher); |
| |
| // Remove gamepad data fetchers with the given source. |
| void RemoveSourceGamepadDataFetcher(GamepadSource source); |
| |
| void SetSanitizationEnabled(bool sanitize) { sanitize_ = sanitize; } |
| |
| private: |
| void Initialize(std::unique_ptr<GamepadDataFetcher> fetcher); |
| |
| // Method for setting up the platform-specific data fetcher. Takes ownership |
| // of |fetcher|. |
| void DoAddGamepadDataFetcher(std::unique_ptr<GamepadDataFetcher> fetcher); |
| void DoRemoveSourceGamepadDataFetcher(GamepadSource source); |
| |
| GamepadDataFetcher* GetSourceGamepadDataFetcher(GamepadSource source); |
| |
| // Method for sending pause hints to the low-level data fetcher. Runs on |
| // polling_thread_. |
| void SendPauseHint(bool paused); |
| |
| // Method for polling a GamepadDataFetcher. Runs on the polling_thread_. |
| void DoPoll(); |
| void ScheduleDoPoll(); |
| |
| void OnGamepadConnectionChange(bool connected, |
| uint32_t index, |
| const Gamepad& pad); |
| |
| // Checks the gamepad state to see if the user has interacted with it. Returns |
| // true if any user gesture observers were notified. |
| bool CheckForUserGesture(); |
| |
| // GamepadPadStateProvider implementation. |
| void DisconnectUnrecognizedGamepad(GamepadSource source, |
| int source_id) override; |
| |
| void PlayEffectOnPollingThread( |
| uint32_t pad_index, |
| mojom::GamepadHapticEffectType, |
| mojom::GamepadEffectParametersPtr, |
| mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback, |
| scoped_refptr<base::SequencedTaskRunner>); |
| |
| void ResetVibrationOnPollingThread( |
| uint32_t pad_index, |
| mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback, |
| scoped_refptr<base::SequencedTaskRunner>); |
| |
| // The duration of the delay between iterations of DoPoll. |
| base::TimeDelta sampling_interval_delta_; |
| |
| // Keeps track of when the background thread is paused. Access to is_paused_ |
| // must be guarded by is_paused_lock_. |
| base::Lock is_paused_lock_; |
| bool is_paused_ = true; |
| |
| // Keep track of when a polling task is schedlued, so as to prevent us from |
| // accidentally scheduling more than one at any time, when rapidly toggling |
| // |is_paused_|. |
| bool have_scheduled_do_poll_ = false; |
| |
| // Lists all observers registered for user gestures, and the thread which |
| // to issue the callbacks on. Since we always issue the callback on the |
| // thread which the registration happened, and this class lives on the I/O |
| // thread, the message loop proxies will normally just be the I/O thread. |
| // However, this will be the main thread for unit testing. |
| base::Lock user_gesture_lock_; |
| using ClosureAndThread = |
| std::pair<base::OnceClosure, scoped_refptr<base::SingleThreadTaskRunner>>; |
| using UserGestureObserverVector = std::vector<ClosureAndThread>; |
| UserGestureObserverVector user_gesture_observers_; |
| |
| // Updated based on notification from SystemMonitor when the system devices |
| // have been updated, and this notification is passed on to the data fetcher |
| // to enable it to avoid redundant (and possibly expensive) is-connected |
| // tests. Access to devices_changed_ must be guarded by |
| // devices_changed_lock_. |
| base::Lock devices_changed_lock_; |
| bool devices_changed_ = true; |
| |
| bool ever_had_user_gesture_ = false; |
| bool sanitize_ = true; |
| |
| // Only used on the polling thread. |
| using GamepadFetcherVector = std::vector<std::unique_ptr<GamepadDataFetcher>>; |
| GamepadFetcherVector data_fetchers_; |
| |
| base::Lock shared_memory_lock_; |
| std::unique_ptr<GamepadSharedBuffer> gamepad_shared_buffer_; |
| |
| // Polling is done on this background thread. |
| std::unique_ptr<base::Thread> polling_thread_; |
| |
| GamepadConnectionChangeClient* connection_change_client_; |
| |
| DISALLOW_COPY_AND_ASSIGN(GamepadProvider); |
| }; |
| |
| } // namespace device |
| |
| #endif // DEVICE_GAMEPAD_GAMEPAD_PROVIDER_H_ |