gamepad_service.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. #include "device/gamepad/gamepad_service.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/check_op.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/memory/singleton.h"
  10. #include "base/threading/thread.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. #include "device/gamepad/gamepad_consumer.h"
  13. #include "device/gamepad/gamepad_data_fetcher.h"
  14. #include "device/gamepad/gamepad_data_fetcher_manager.h"
  15. #include "device/gamepad/gamepad_provider.h"
  16. namespace device {
  17. namespace {
  18. GamepadService* g_gamepad_service = nullptr;
  19. } // namespace
  20. GamepadService::GamepadService() {
  21. SetInstance(this);
  22. }
  23. GamepadService::GamepadService(std::unique_ptr<GamepadDataFetcher> fetcher)
  24. : provider_(std::make_unique<GamepadProvider>(
  25. /*connection_change_client=*/this,
  26. std::move(fetcher),
  27. /*polling_thread=*/nullptr)) {
  28. SetInstance(this);
  29. }
  30. GamepadService::~GamepadService() = default;
  31. void GamepadService::SetInstance(GamepadService* instance) {
  32. // Unit tests can create multiple instances but only one should exist at any
  33. // given time so |g_gamepad_service| should only go from nullptr to
  34. // non-nullptr and vice versa.
  35. CHECK(!!instance != !!g_gamepad_service);
  36. if (g_gamepad_service)
  37. delete g_gamepad_service;
  38. g_gamepad_service = instance;
  39. }
  40. GamepadService* GamepadService::GetInstance() {
  41. if (!g_gamepad_service)
  42. g_gamepad_service = new GamepadService;
  43. return g_gamepad_service;
  44. }
  45. void GamepadService::StartUp(
  46. GamepadDataFetcher::HidManagerBinder hid_manager_binder) {
  47. GamepadDataFetcher::SetHidManagerBinder(std::move(hid_manager_binder));
  48. // Ensures GamepadDataFetcherManager is created on UI thread. Otherwise,
  49. // GamepadPlatformDataFetcherLinux::Factory would be created with the
  50. // wrong thread for its |dbus_runner_|.
  51. GamepadDataFetcherManager::GetInstance();
  52. }
  53. bool GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
  54. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  55. if (!provider_) {
  56. provider_ = std::make_unique<GamepadProvider>(
  57. /*connection_change_client=*/this);
  58. }
  59. std::pair<ConsumerSet::iterator, bool> insert_result =
  60. consumers_.insert(consumer);
  61. const ConsumerInfo& info = *insert_result.first;
  62. if (info.is_active)
  63. return false;
  64. info.is_active = true;
  65. if (info.did_observe_user_gesture) {
  66. auto consumer_state_it = inactive_consumer_state_.find(consumer);
  67. if (consumer_state_it != inactive_consumer_state_.end()) {
  68. const std::vector<bool>& old_connected_state = consumer_state_it->second;
  69. Gamepads gamepads;
  70. provider_->GetCurrentGamepadData(&gamepads);
  71. for (size_t i = 0; i < Gamepads::kItemsLengthCap; ++i) {
  72. const Gamepad& gamepad = gamepads.items[i];
  73. if (gamepad.connected) {
  74. info.consumer->OnGamepadConnected(i, gamepad);
  75. } else if (old_connected_state[i] && !gamepad.connected) {
  76. info.consumer->OnGamepadDisconnected(i, gamepad);
  77. }
  78. }
  79. inactive_consumer_state_.erase(consumer_state_it);
  80. }
  81. } else if (!gesture_callback_pending_) {
  82. gesture_callback_pending_ = true;
  83. provider_->RegisterForUserGesture(
  84. base::BindOnce(&GamepadService::OnUserGesture, base::Unretained(this)));
  85. }
  86. if (num_active_consumers_++ == 0)
  87. provider_->Resume();
  88. return true;
  89. }
  90. bool GamepadService::ConsumerBecameInactive(GamepadConsumer* consumer) {
  91. DCHECK(provider_);
  92. auto consumer_it = consumers_.find(consumer);
  93. if (consumer_it == consumers_.end())
  94. return false;
  95. const ConsumerInfo& info = *consumer_it;
  96. if (!info.is_active)
  97. return false;
  98. DCHECK_GT(num_active_consumers_, 0);
  99. info.is_active = false;
  100. if (--num_active_consumers_ == 0)
  101. provider_->Pause();
  102. // Save the current state of connected gamepads.
  103. if (info.did_observe_user_gesture) {
  104. Gamepads gamepads;
  105. provider_->GetCurrentGamepadData(&gamepads);
  106. std::vector<bool> connected_state(Gamepads::kItemsLengthCap);
  107. for (size_t i = 0; i < Gamepads::kItemsLengthCap; ++i)
  108. connected_state[i] = gamepads.items[i].connected;
  109. inactive_consumer_state_[consumer] = connected_state;
  110. }
  111. return true;
  112. }
  113. bool GamepadService::RemoveConsumer(GamepadConsumer* consumer) {
  114. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  115. auto it = consumers_.find(consumer);
  116. if (it == consumers_.end())
  117. return false;
  118. if (it->is_active && --num_active_consumers_ == 0)
  119. provider_->Pause();
  120. DCHECK_GE(num_active_consumers_, 0);
  121. consumers_.erase(it);
  122. inactive_consumer_state_.erase(consumer);
  123. return true;
  124. }
  125. void GamepadService::RegisterForUserGesture(base::OnceClosure closure) {
  126. DCHECK(consumers_.size() > 0);
  127. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  128. provider_->RegisterForUserGesture(std::move(closure));
  129. }
  130. void GamepadService::Terminate() {
  131. provider_.reset();
  132. }
  133. void GamepadService::OnGamepadConnectionChange(bool connected,
  134. uint32_t index,
  135. const Gamepad& pad) {
  136. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  137. if (connected) {
  138. OnGamepadConnected(index, pad);
  139. } else {
  140. OnGamepadDisconnected(index, pad);
  141. }
  142. }
  143. void GamepadService::OnGamepadChange(mojom::GamepadChangesPtr changes) {
  144. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  145. for (auto& it : consumers_) {
  146. if (it.did_observe_user_gesture && it.is_active)
  147. it.consumer->OnGamepadChanged(*changes);
  148. }
  149. }
  150. void GamepadService::OnGamepadConnected(uint32_t index, const Gamepad& pad) {
  151. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  152. for (auto it = consumers_.begin(); it != consumers_.end(); ++it) {
  153. if (it->did_observe_user_gesture && it->is_active)
  154. it->consumer->OnGamepadConnected(index, pad);
  155. }
  156. }
  157. void GamepadService::OnGamepadDisconnected(uint32_t index, const Gamepad& pad) {
  158. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  159. for (auto it = consumers_.begin(); it != consumers_.end(); ++it) {
  160. if (it->did_observe_user_gesture && it->is_active)
  161. it->consumer->OnGamepadDisconnected(index, pad);
  162. }
  163. }
  164. void GamepadService::PlayVibrationEffectOnce(
  165. uint32_t pad_index,
  166. mojom::GamepadHapticEffectType type,
  167. mojom::GamepadEffectParametersPtr params,
  168. mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback) {
  169. if (!provider_) {
  170. std::move(callback).Run(
  171. mojom::GamepadHapticsResult::GamepadHapticsResultError);
  172. return;
  173. }
  174. provider_->PlayVibrationEffectOnce(pad_index, type, std::move(params),
  175. std::move(callback));
  176. }
  177. void GamepadService::ResetVibrationActuator(
  178. uint32_t pad_index,
  179. mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback) {
  180. if (!provider_) {
  181. std::move(callback).Run(
  182. mojom::GamepadHapticsResult::GamepadHapticsResultError);
  183. return;
  184. }
  185. provider_->ResetVibrationActuator(pad_index, std::move(callback));
  186. }
  187. base::ReadOnlySharedMemoryRegion GamepadService::DuplicateSharedMemoryRegion() {
  188. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  189. return provider_->DuplicateSharedMemoryRegion();
  190. }
  191. void GamepadService::OnUserGesture() {
  192. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  193. gesture_callback_pending_ = false;
  194. if (!provider_ || num_active_consumers_ == 0)
  195. return;
  196. for (auto it = consumers_.begin(); it != consumers_.end(); ++it) {
  197. if (!it->did_observe_user_gesture && it->is_active) {
  198. const ConsumerInfo& info = *it;
  199. info.did_observe_user_gesture = true;
  200. Gamepads gamepads;
  201. provider_->GetCurrentGamepadData(&gamepads);
  202. for (size_t i = 0; i < Gamepads::kItemsLengthCap; ++i) {
  203. const Gamepad& pad = gamepads.items[i];
  204. if (pad.connected)
  205. info.consumer->OnGamepadConnected(i, pad);
  206. }
  207. }
  208. }
  209. }
  210. void GamepadService::SetSanitizationEnabled(bool sanitize) {
  211. provider_->SetSanitizationEnabled(sanitize);
  212. }
  213. } // namespace device