Commit 1911f596 authored by Matt Reynolds's avatar Matt Reynolds Committed by Commit Bot

Add haptics to GamepadDataFetcher

A GamepadDataFetcher represents a host interface for receiving gamepad
state and communicating commands to a gamepad connected over a
particular host interface.

This CL modifies GamepadDataFetcher to support haptics commands.
Haptics commands received by GamepadService are routed to the fetcher
corresponding to the gamepad's host interface.

BUG=749295

Change-Id: I82629d34494871ed59c574a9846c0b4ff088f229
Reviewed-on: https://chromium-review.googlesource.com/739926
Commit-Queue: Matt Reynolds <mattreynolds@chromium.org>
Reviewed-by: default avatarBrandon Jones <bajones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#513009}
parent 42a9c385
...@@ -15,6 +15,22 @@ void GamepadDataFetcher::InitializeProvider(GamepadPadStateProvider* provider) { ...@@ -15,6 +15,22 @@ void GamepadDataFetcher::InitializeProvider(GamepadPadStateProvider* provider) {
OnAddedToProvider(); OnAddedToProvider();
} }
GamepadDataFetcherFactory::GamepadDataFetcherFactory() {} void GamepadDataFetcher::PlayEffect(
int source_id,
mojom::GamepadHapticEffectType type,
mojom::GamepadEffectParametersPtr params,
mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback) {
std::move(callback).Run(
mojom::GamepadHapticsResult::GamepadHapticsResultError);
}
void GamepadDataFetcher::ResetVibration(
int source_id,
mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback) {
std::move(callback).Run(
mojom::GamepadHapticsResult::GamepadHapticsResultError);
}
GamepadDataFetcherFactory::GamepadDataFetcherFactory() = default;
} // namespace device } // namespace device
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "device/gamepad/gamepad_data_fetcher_manager.h" #include "device/gamepad/gamepad_data_fetcher_manager.h"
#include "device/gamepad/gamepad_export.h" #include "device/gamepad/gamepad_export.h"
#include "device/gamepad/gamepad_pad_state_provider.h" #include "device/gamepad/gamepad_pad_state_provider.h"
#include "device/gamepad/public/cpp/gamepad.h"
#include "device/gamepad/public/interfaces/gamepad.mojom.h"
namespace device { namespace device {
...@@ -19,6 +21,14 @@ class DEVICE_GAMEPAD_EXPORT GamepadDataFetcher { ...@@ -19,6 +21,14 @@ class DEVICE_GAMEPAD_EXPORT GamepadDataFetcher {
virtual ~GamepadDataFetcher() {} virtual ~GamepadDataFetcher() {}
virtual void GetGamepadData(bool devices_changed_hint) = 0; virtual void GetGamepadData(bool devices_changed_hint) = 0;
virtual void PauseHint(bool paused) {} virtual void PauseHint(bool paused) {}
virtual void PlayEffect(
int source_id,
mojom::GamepadHapticEffectType,
mojom::GamepadEffectParametersPtr,
mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback);
virtual void ResetVibration(
int source_id,
mojom::GamepadHapticsManager::ResetVibrationActuatorCallback);
virtual GamepadSource source() = 0; virtual GamepadSource source() = 0;
GamepadPadStateProvider* provider() { return provider_; } GamepadPadStateProvider* provider() { return provider_; }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <utility> #include <utility>
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "device/gamepad/gamepad_service.h"
#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/bindings/strong_binding.h"
namespace device { namespace device {
...@@ -27,13 +28,15 @@ void GamepadHapticsManager::PlayVibrationEffectOnce( ...@@ -27,13 +28,15 @@ void GamepadHapticsManager::PlayVibrationEffectOnce(
mojom::GamepadHapticEffectType type, mojom::GamepadHapticEffectType type,
mojom::GamepadEffectParametersPtr params, mojom::GamepadEffectParametersPtr params,
PlayVibrationEffectOnceCallback callback) { PlayVibrationEffectOnceCallback callback) {
NOTIMPLEMENTED(); GamepadService::GetInstance()->PlayVibrationEffectOnce(
pad_index, type, std::move(params), std::move(callback));
} }
void GamepadHapticsManager::ResetVibrationActuator( void GamepadHapticsManager::ResetVibrationActuator(
int pad_index, int pad_index,
ResetVibrationActuatorCallback callback) { ResetVibrationActuatorCallback callback) {
NOTIMPLEMENTED(); GamepadService::GetInstance()->ResetVibrationActuator(pad_index,
std::move(callback));
} }
} // namespace device } // namespace device
...@@ -49,6 +49,17 @@ PadState* GamepadPadStateProvider::GetPadState(GamepadSource source, ...@@ -49,6 +49,17 @@ PadState* GamepadPadStateProvider::GetPadState(GamepadSource source,
return empty_slot; return empty_slot;
} }
PadState* GamepadPadStateProvider::GetConnectedPadState(int pad_index) {
if (pad_index < 0 || pad_index >= (int)Gamepads::kItemsLengthCap)
return nullptr;
PadState& pad_state = pad_states_.get()[pad_index];
if (pad_state.source == GAMEPAD_SOURCE_NONE)
return nullptr;
return &pad_state;
}
void GamepadPadStateProvider::ClearPadState(PadState& state) { void GamepadPadStateProvider::ClearPadState(PadState& state) {
memset(&state, 0, sizeof(PadState)); memset(&state, 0, sizeof(PadState));
} }
......
...@@ -83,6 +83,11 @@ class DEVICE_GAMEPAD_EXPORT GamepadPadStateProvider { ...@@ -83,6 +83,11 @@ class DEVICE_GAMEPAD_EXPORT GamepadPadStateProvider {
// If no slots are available will return NULL. // If no slots are available will return NULL.
PadState* GetPadState(GamepadSource source, int source_id); PadState* GetPadState(GamepadSource source, int source_id);
// Gets a PadState object for a connected gamepad by specifying its index in
// the pad_states_ array. Returns NULL if there is no connected gamepad at
// that index.
PadState* GetConnectedPadState(int pad_index);
protected: protected:
void ClearPadState(PadState& state); void ClearPadState(PadState& state);
......
...@@ -102,6 +102,49 @@ void GamepadProvider::GetCurrentGamepadData(Gamepads* data) { ...@@ -102,6 +102,49 @@ void GamepadProvider::GetCurrentGamepadData(Gamepads* data) {
*data = *pads; *data = *pads;
} }
void GamepadProvider::PlayVibrationEffectOnce(
int pad_index,
mojom::GamepadHapticEffectType type,
mojom::GamepadEffectParametersPtr params,
mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback) {
PadState* pad_state = GetConnectedPadState(pad_index);
if (!pad_state) {
std::move(callback).Run(
mojom::GamepadHapticsResult::GamepadHapticsResultError);
return;
}
GamepadDataFetcher* fetcher = GetSourceGamepadDataFetcher(pad_state->source);
if (!fetcher) {
std::move(callback).Run(
mojom::GamepadHapticsResult::GamepadHapticsResultNotSupported);
return;
}
fetcher->PlayEffect(pad_state->source_id, type, std::move(params),
std::move(callback));
}
void GamepadProvider::ResetVibrationActuator(
int pad_index,
mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback) {
PadState* pad_state = GetConnectedPadState(pad_index);
if (!pad_state) {
std::move(callback).Run(
mojom::GamepadHapticsResult::GamepadHapticsResultError);
return;
}
GamepadDataFetcher* fetcher = GetSourceGamepadDataFetcher(pad_state->source);
if (!fetcher) {
std::move(callback).Run(
mojom::GamepadHapticsResult::GamepadHapticsResultNotSupported);
return;
}
fetcher->ResetVibration(pad_state->source_id, std::move(callback));
}
void GamepadProvider::Pause() { void GamepadProvider::Pause() {
{ {
base::AutoLock lock(is_paused_lock_); base::AutoLock lock(is_paused_lock_);
...@@ -183,6 +226,19 @@ void GamepadProvider::RemoveSourceGamepadDataFetcher(GamepadSource source) { ...@@ -183,6 +226,19 @@ void GamepadProvider::RemoveSourceGamepadDataFetcher(GamepadSource source) {
base::Unretained(this), source)); base::Unretained(this), source));
} }
GamepadDataFetcher* GamepadProvider::GetSourceGamepadDataFetcher(
GamepadSource source) {
for (GamepadFetcherVector::iterator it = data_fetchers_.begin();
it != data_fetchers_.end();) {
if ((*it)->source() == source) {
return it->get();
} else {
++it;
}
}
return nullptr;
}
void GamepadProvider::DoAddGamepadDataFetcher( void GamepadProvider::DoAddGamepadDataFetcher(
std::unique_ptr<GamepadDataFetcher> fetcher) { std::unique_ptr<GamepadDataFetcher> fetcher) {
DCHECK(polling_thread_->task_runner()->BelongsToCurrentThread()); DCHECK(polling_thread_->task_runner()->BelongsToCurrentThread());
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "device/gamepad/gamepad_pad_state_provider.h" #include "device/gamepad/gamepad_pad_state_provider.h"
#include "device/gamepad/gamepad_shared_buffer.h" #include "device/gamepad/gamepad_shared_buffer.h"
#include "device/gamepad/public/cpp/gamepads.h" #include "device/gamepad/public/cpp/gamepads.h"
#include "device/gamepad/public/interfaces/gamepad.mojom.h"
#include "mojo/public/cpp/system/buffer.h" #include "mojo/public/cpp/system/buffer.h"
namespace base { namespace base {
...@@ -57,11 +58,18 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider ...@@ -57,11 +58,18 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider
// Returns a new mojo::ScopedSharedBufferHandle of the gamepad data. // Returns a new mojo::ScopedSharedBufferHandle of the gamepad data.
mojo::ScopedSharedBufferHandle GetSharedBufferHandle(); mojo::ScopedSharedBufferHandle GetSharedBufferHandle();
void AddGamepadDataFetcher(GamepadDataFetcher* fetcher);
void RemoveGamepadDataFetcher(GamepadDataFetcher* fetcher);
void GetCurrentGamepadData(Gamepads* data); void GetCurrentGamepadData(Gamepads* data);
void PlayVibrationEffectOnce(
int pad_index,
mojom::GamepadHapticEffectType,
mojom::GamepadEffectParametersPtr,
mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback);
void ResetVibrationActuator(
int pad_index,
mojom::GamepadHapticsManager::ResetVibrationActuatorCallback);
// Pause and resume the background polling thread. Can be called from any // Pause and resume the background polling thread. Can be called from any
// thread. // thread.
void Pause(); void Pause();
...@@ -90,6 +98,8 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider ...@@ -90,6 +98,8 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider
void DoAddGamepadDataFetcher(std::unique_ptr<GamepadDataFetcher> fetcher); void DoAddGamepadDataFetcher(std::unique_ptr<GamepadDataFetcher> fetcher);
void DoRemoveSourceGamepadDataFetcher(GamepadSource source); void DoRemoveSourceGamepadDataFetcher(GamepadSource source);
GamepadDataFetcher* GetSourceGamepadDataFetcher(GamepadSource source);
// Method for sending pause hints to the low-level data fetcher. Runs on // Method for sending pause hints to the low-level data fetcher. Runs on
// polling_thread_. // polling_thread_.
void SendPauseHint(bool paused); void SendPauseHint(bool paused);
...@@ -130,7 +140,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider ...@@ -130,7 +140,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider
base::Closure closure; base::Closure closure;
scoped_refptr<base::SingleThreadTaskRunner> task_runner; scoped_refptr<base::SingleThreadTaskRunner> task_runner;
}; };
typedef std::vector<ClosureAndThread> UserGestureObserverVector; using UserGestureObserverVector = std::vector<ClosureAndThread>;
UserGestureObserverVector user_gesture_observers_; UserGestureObserverVector user_gesture_observers_;
// Updated based on notification from SystemMonitor when the system devices // Updated based on notification from SystemMonitor when the system devices
...@@ -145,7 +155,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider ...@@ -145,7 +155,7 @@ class DEVICE_GAMEPAD_EXPORT GamepadProvider
bool sanitize_; bool sanitize_;
// Only used on the polling thread. // Only used on the polling thread.
typedef std::vector<std::unique_ptr<GamepadDataFetcher>> GamepadFetcherVector; using GamepadFetcherVector = std::vector<std::unique_ptr<GamepadDataFetcher>>;
GamepadFetcherVector data_fetchers_; GamepadFetcherVector data_fetchers_;
base::Lock shared_memory_lock_; base::Lock shared_memory_lock_;
......
...@@ -169,6 +169,37 @@ void GamepadService::OnGamepadDisconnected(int index, const Gamepad& pad) { ...@@ -169,6 +169,37 @@ void GamepadService::OnGamepadDisconnected(int index, const Gamepad& pad) {
} }
} }
void GamepadService::PlayVibrationEffectOnce(
int pad_index,
mojom::GamepadHapticEffectType type,
mojom::GamepadEffectParametersPtr params,
mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback) {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
if (!provider_) {
std::move(callback).Run(
mojom::GamepadHapticsResult::GamepadHapticsResultError);
return;
}
provider_->PlayVibrationEffectOnce(pad_index, type, std::move(params),
std::move(callback));
}
void GamepadService::ResetVibrationActuator(
int pad_index,
mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback) {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
if (!provider_) {
std::move(callback).Run(
mojom::GamepadHapticsResult::GamepadHapticsResultError);
return;
}
provider_->ResetVibrationActuator(pad_index, std::move(callback));
}
base::SharedMemoryHandle GamepadService::DuplicateSharedMemoryHandle() { base::SharedMemoryHandle GamepadService::DuplicateSharedMemoryHandle() {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
return provider_->DuplicateSharedMemoryHandle(); return provider_->DuplicateSharedMemoryHandle();
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "device/gamepad/gamepad_export.h" #include "device/gamepad/gamepad_export.h"
#include "device/gamepad/gamepad_provider.h" #include "device/gamepad/gamepad_provider.h"
#include "device/gamepad/public/interfaces/gamepad.mojom.h"
namespace { namespace {
class SingleThreadTaskRunner; class SingleThreadTaskRunner;
...@@ -84,6 +85,22 @@ class DEVICE_GAMEPAD_EXPORT GamepadService ...@@ -84,6 +85,22 @@ class DEVICE_GAMEPAD_EXPORT GamepadService
// Called on IO thread when a gamepad is disconnected. // Called on IO thread when a gamepad is disconnected.
void OnGamepadDisconnected(int index, const Gamepad& pad); void OnGamepadDisconnected(int index, const Gamepad& pad);
// Request playback of a haptic effect on the specified gamepad. Once effect
// playback is complete or is preempted by a different effect, the callback
// will be called.
void PlayVibrationEffectOnce(
int pad_index,
mojom::GamepadHapticEffectType,
mojom::GamepadEffectParametersPtr,
mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback);
// Resets the state of the vibration actuator on the specified gamepad. If any
// effects are currently being played, they are preempted and vibration is
// stopped.
void ResetVibrationActuator(
int pad_index,
mojom::GamepadHapticsManager::ResetVibrationActuatorCallback);
private: private:
friend struct base::DefaultSingletonTraits<GamepadService>; friend struct base::DefaultSingletonTraits<GamepadService>;
friend class GamepadServiceTestConstructor; friend class GamepadServiceTestConstructor;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment