Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: device/gamepad/gamepad_provider.cc

Issue 2081583002: Migrating majority of gamepad from content/browser/ to device/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Final tweaks Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « device/gamepad/gamepad_provider.h ('k') | device/gamepad/gamepad_provider_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/gamepad/gamepad_provider.h" 5 #include "device/gamepad/gamepad_provider.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <string.h> 8 #include <string.h>
9 #include <cmath> 9 #include <cmath>
10 #include <set> 10 #include <set>
11 #include <utility> 11 #include <utility>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/single_thread_task_runner.h" 17 #include "base/single_thread_task_runner.h"
18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
19 #include "base/threading/thread.h" 19 #include "base/threading/thread.h"
20 #include "base/threading/thread_restrictions.h" 20 #include "base/threading/thread_restrictions.h"
21 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
22 #include "build/build_config.h" 22 #include "build/build_config.h"
23 #include "content/browser/gamepad/gamepad_data_fetcher.h" 23 #include "device/gamepad/gamepad_data_fetcher.h"
24 #include "content/browser/gamepad/gamepad_platform_data_fetcher.h" 24 #include "device/gamepad/gamepad_platform_data_fetcher.h"
25 #include "content/browser/gamepad/gamepad_service.h" 25 #include "device/gamepad/gamepad_user_gesture.h"
26 #include "content/common/gamepad_hardware_buffer.h"
27 #include "content/common/gamepad_messages.h"
28 #include "content/common/gamepad_user_gesture.h"
29 #include "content/public/browser/browser_thread.h"
30 26
31 using blink::WebGamepad; 27 using blink::WebGamepad;
32 using blink::WebGamepads; 28 using blink::WebGamepads;
33 29
34 namespace content { 30 namespace device {
35 31
36 GamepadProvider::ClosureAndThread::ClosureAndThread( 32 GamepadProvider::ClosureAndThread::ClosureAndThread(
37 const base::Closure& c, 33 const base::Closure& c,
38 const scoped_refptr<base::SingleThreadTaskRunner>& m) 34 const scoped_refptr<base::SingleThreadTaskRunner>& m)
39 : closure(c), task_runner(m) { 35 : closure(c), task_runner(m) {}
40 }
41 36
42 GamepadProvider::ClosureAndThread::ClosureAndThread( 37 GamepadProvider::ClosureAndThread::ClosureAndThread(
43 const ClosureAndThread& other) = default; 38 const ClosureAndThread& other) = default;
44 39
45 GamepadProvider::ClosureAndThread::~ClosureAndThread() { 40 GamepadProvider::ClosureAndThread::~ClosureAndThread() {}
46 }
47 41
48 GamepadProvider::GamepadProvider() 42 GamepadProvider::GamepadProvider(
43 std::unique_ptr<GamepadSharedBuffer> buffer,
44 GamepadConnectionChangeClient* connection_change_client)
49 : is_paused_(true), 45 : is_paused_(true),
50 have_scheduled_do_poll_(false), 46 have_scheduled_do_poll_(false),
51 devices_changed_(true), 47 devices_changed_(true),
52 ever_had_user_gesture_(false) { 48 ever_had_user_gesture_(false),
49 gamepad_shared_buffer_(std::move(buffer)),
50 connection_change_client_(connection_change_client) {
53 Initialize(std::unique_ptr<GamepadDataFetcher>()); 51 Initialize(std::unique_ptr<GamepadDataFetcher>());
54 } 52 }
55 53
56 GamepadProvider::GamepadProvider(std::unique_ptr<GamepadDataFetcher> fetcher) 54 GamepadProvider::GamepadProvider(
55 std::unique_ptr<GamepadSharedBuffer> buffer,
56 GamepadConnectionChangeClient* connection_change_client,
57 std::unique_ptr<GamepadDataFetcher> fetcher)
57 : is_paused_(true), 58 : is_paused_(true),
58 have_scheduled_do_poll_(false), 59 have_scheduled_do_poll_(false),
59 devices_changed_(true), 60 devices_changed_(true),
60 ever_had_user_gesture_(false) { 61 ever_had_user_gesture_(false),
62 gamepad_shared_buffer_(std::move(buffer)),
63 connection_change_client_(connection_change_client) {
61 Initialize(std::move(fetcher)); 64 Initialize(std::move(fetcher));
62 } 65 }
63 66
64 GamepadProvider::~GamepadProvider() { 67 GamepadProvider::~GamepadProvider() {
65 base::SystemMonitor* monitor = base::SystemMonitor::Get(); 68 base::SystemMonitor* monitor = base::SystemMonitor::Get();
66 if (monitor) 69 if (monitor)
67 monitor->RemoveDevicesChangedObserver(this); 70 monitor->RemoveDevicesChangedObserver(this);
68 71
69 // Use Stop() to join the polling thread, as there may be pending callbacks 72 // Use Stop() to join the polling thread, as there may be pending callbacks
70 // which dereference |polling_thread_|. 73 // which dereference |polling_thread_|.
71 polling_thread_->Stop(); 74 polling_thread_->Stop();
72 data_fetcher_.reset(); 75 data_fetcher_.reset();
73 } 76 }
74 77
75 base::SharedMemoryHandle GamepadProvider::GetSharedMemoryHandleForProcess( 78 base::SharedMemoryHandle GamepadProvider::GetSharedMemoryHandleForProcess(
76 base::ProcessHandle process) { 79 base::ProcessHandle process) {
77 base::SharedMemoryHandle renderer_handle; 80 base::SharedMemoryHandle renderer_handle;
78 gamepad_shared_memory_.ShareToProcess(process, &renderer_handle); 81 gamepad_shared_buffer_->shared_memory()->ShareToProcess(process,
82 &renderer_handle);
79 return renderer_handle; 83 return renderer_handle;
80 } 84 }
81 85
82 void GamepadProvider::GetCurrentGamepadData(WebGamepads* data) { 86 void GamepadProvider::GetCurrentGamepadData(WebGamepads* data) {
83 const WebGamepads& pads = SharedMemoryAsHardwareBuffer()->buffer; 87 const WebGamepads* pads = gamepad_shared_buffer_->buffer();
84 base::AutoLock lock(shared_memory_lock_); 88 base::AutoLock lock(shared_memory_lock_);
85 *data = pads; 89 *data = *pads;
86 } 90 }
87 91
88 void GamepadProvider::Pause() { 92 void GamepadProvider::Pause() {
89 { 93 {
90 base::AutoLock lock(is_paused_lock_); 94 base::AutoLock lock(is_paused_lock_);
91 is_paused_ = true; 95 is_paused_ = true;
92 } 96 }
93 base::MessageLoop* polling_loop = polling_thread_->message_loop(); 97 base::MessageLoop* polling_loop = polling_thread_->message_loop();
94 polling_loop->task_runner()->PostTask( 98 polling_loop->task_runner()->PostTask(
95 FROM_HERE, 99 FROM_HERE,
96 base::Bind(&GamepadProvider::SendPauseHint, Unretained(this), true)); 100 base::Bind(&GamepadProvider::SendPauseHint, Unretained(this), true));
97 } 101 }
98 102
99 void GamepadProvider::Resume() { 103 void GamepadProvider::Resume() {
100 { 104 {
101 base::AutoLock lock(is_paused_lock_); 105 base::AutoLock lock(is_paused_lock_);
102 if (!is_paused_) 106 if (!is_paused_)
103 return; 107 return;
104 is_paused_ = false; 108 is_paused_ = false;
105 } 109 }
106 110
107 base::MessageLoop* polling_loop = polling_thread_->message_loop(); 111 base::MessageLoop* polling_loop = polling_thread_->message_loop();
108 polling_loop->task_runner()->PostTask( 112 polling_loop->task_runner()->PostTask(
109 FROM_HERE, 113 FROM_HERE,
110 base::Bind(&GamepadProvider::SendPauseHint, Unretained(this), false)); 114 base::Bind(&GamepadProvider::SendPauseHint, Unretained(this), false));
111 polling_loop->task_runner()->PostTask( 115 polling_loop->task_runner()->PostTask(
112 FROM_HERE, 116 FROM_HERE,
113 base::Bind(&GamepadProvider::ScheduleDoPoll, Unretained(this))); 117 base::Bind(&GamepadProvider::ScheduleDoPoll, Unretained(this)));
114 } 118 }
115 119
116 void GamepadProvider::RegisterForUserGesture(const base::Closure& closure) { 120 void GamepadProvider::RegisterForUserGesture(const base::Closure& closure) {
117 base::AutoLock lock(user_gesture_lock_); 121 base::AutoLock lock(user_gesture_lock_);
118 user_gesture_observers_.push_back( 122 user_gesture_observers_.push_back(
119 ClosureAndThread(closure, base::ThreadTaskRunnerHandle::Get())); 123 ClosureAndThread(closure, base::ThreadTaskRunnerHandle::Get()));
120 } 124 }
121 125
122 void GamepadProvider::OnDevicesChanged(base::SystemMonitor::DeviceType type) { 126 void GamepadProvider::OnDevicesChanged(base::SystemMonitor::DeviceType type) {
123 base::AutoLock lock(devices_changed_lock_); 127 base::AutoLock lock(devices_changed_lock_);
124 devices_changed_ = true; 128 devices_changed_ = true;
125 } 129 }
126 130
127 void GamepadProvider::Initialize(std::unique_ptr<GamepadDataFetcher> fetcher) { 131 void GamepadProvider::Initialize(std::unique_ptr<GamepadDataFetcher> fetcher) {
128 size_t data_size = sizeof(GamepadHardwareBuffer);
129 base::SystemMonitor* monitor = base::SystemMonitor::Get(); 132 base::SystemMonitor* monitor = base::SystemMonitor::Get();
130 if (monitor) 133 if (monitor)
131 monitor->AddDevicesChangedObserver(this); 134 monitor->AddDevicesChangedObserver(this);
132 bool res = gamepad_shared_memory_.CreateAndMapAnonymous(data_size); 135
133 CHECK(res);
134 GamepadHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer();
135 memset(hwbuf, 0, sizeof(GamepadHardwareBuffer));
136 pad_states_.reset(new PadState[WebGamepads::itemsLengthCap]); 136 pad_states_.reset(new PadState[WebGamepads::itemsLengthCap]);
137 137
138 polling_thread_.reset(new base::Thread("Gamepad polling thread")); 138 polling_thread_.reset(new base::Thread("Gamepad polling thread"));
139 #if defined(OS_LINUX) 139 #if defined(OS_LINUX)
140 // On Linux, the data fetcher needs to watch file descriptors, so the message 140 // On Linux, the data fetcher needs to watch file descriptors, so the message
141 // loop needs to be a libevent loop. 141 // loop needs to be a libevent loop.
142 const base::MessageLoop::Type kMessageLoopType = base::MessageLoop::TYPE_IO; 142 const base::MessageLoop::Type kMessageLoopType = base::MessageLoop::TYPE_IO;
143 #elif defined(OS_ANDROID) 143 #elif defined(OS_ANDROID)
144 // On Android, keeping a message loop of default type. 144 // On Android, keeping a message loop of default type.
145 const base::MessageLoop::Type kMessageLoopType = 145 const base::MessageLoop::Type kMessageLoopType =
(...skipping 21 matching lines...) Expand all
167 data_fetcher_ = std::move(fetcher); 167 data_fetcher_ = std::move(fetcher);
168 } 168 }
169 169
170 void GamepadProvider::SendPauseHint(bool paused) { 170 void GamepadProvider::SendPauseHint(bool paused) {
171 DCHECK(base::MessageLoop::current() == polling_thread_->message_loop()); 171 DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
172 if (data_fetcher_) 172 if (data_fetcher_)
173 data_fetcher_->PauseHint(paused); 173 data_fetcher_->PauseHint(paused);
174 } 174 }
175 175
176 bool GamepadProvider::PadState::Match(const WebGamepad& pad) const { 176 bool GamepadProvider::PadState::Match(const WebGamepad& pad) const {
177 return connected_ == pad.connected && 177 return connected_ == pad.connected && axes_length_ == pad.axesLength &&
178 axes_length_ == pad.axesLength &&
179 buttons_length_ == pad.buttonsLength && 178 buttons_length_ == pad.buttonsLength &&
180 memcmp(id_, pad.id, sizeof(id_)) == 0 && 179 memcmp(id_, pad.id, sizeof(id_)) == 0 &&
181 memcmp(mapping_, pad.mapping, sizeof(mapping_)) == 0; 180 memcmp(mapping_, pad.mapping, sizeof(mapping_)) == 0;
182 } 181 }
183 182
184 void GamepadProvider::PadState::SetPad(const WebGamepad& pad) { 183 void GamepadProvider::PadState::SetPad(const WebGamepad& pad) {
185 connected_ = pad.connected; 184 connected_ = pad.connected;
186 axes_length_ = pad.axesLength; 185 axes_length_ = pad.axesLength;
187 buttons_length_ = pad.buttonsLength; 186 buttons_length_ = pad.buttonsLength;
188 memcpy(id_, pad.id, sizeof(id_)); 187 memcpy(id_, pad.id, sizeof(id_));
(...skipping 17 matching lines...) Expand all
206 memset(pad->axes, 0, sizeof(pad->axes)); 205 memset(pad->axes, 0, sizeof(pad->axes));
207 memset(pad->buttons, 0, sizeof(pad->buttons)); 206 memset(pad->buttons, 0, sizeof(pad->buttons));
208 } 207 }
209 208
210 void GamepadProvider::DoPoll() { 209 void GamepadProvider::DoPoll() {
211 DCHECK(base::MessageLoop::current() == polling_thread_->message_loop()); 210 DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
212 DCHECK(have_scheduled_do_poll_); 211 DCHECK(have_scheduled_do_poll_);
213 have_scheduled_do_poll_ = false; 212 have_scheduled_do_poll_ = false;
214 213
215 bool changed; 214 bool changed;
216 GamepadHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer();
217 215
218 ANNOTATE_BENIGN_RACE_SIZED( 216 ANNOTATE_BENIGN_RACE_SIZED(gamepad_shared_buffer_->buffer(),
219 &hwbuf->buffer, 217 sizeof(WebGamepads), "Racey reads are discarded");
220 sizeof(WebGamepads),
221 "Racey reads are discarded");
222 218
223 { 219 {
224 base::AutoLock lock(devices_changed_lock_); 220 base::AutoLock lock(devices_changed_lock_);
225 changed = devices_changed_; 221 changed = devices_changed_;
226 devices_changed_ = false; 222 devices_changed_ = false;
227 } 223 }
228 224
229 { 225 {
230 base::AutoLock lock(shared_memory_lock_); 226 base::AutoLock lock(shared_memory_lock_);
231 227
232 // Acquire the SeqLock. There is only ever one writer to this data. 228 // Acquire the SeqLock. There is only ever one writer to this data.
233 // See gamepad_hardware_buffer.h. 229 // See gamepad_hardware_buffer.h.
234 hwbuf->sequence.WriteBegin(); 230 gamepad_shared_buffer_->WriteBegin();
235 data_fetcher_->GetGamepadData(&hwbuf->buffer, changed); 231 data_fetcher_->GetGamepadData(gamepad_shared_buffer_->buffer(), changed);
236 hwbuf->sequence.WriteEnd(); 232 gamepad_shared_buffer_->WriteEnd();
237 } 233 }
238 234
239 if (ever_had_user_gesture_) { 235 if (ever_had_user_gesture_) {
240 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) { 236 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
241 WebGamepad& pad = hwbuf->buffer.items[i]; 237 WebGamepad& pad = gamepad_shared_buffer_->buffer()->items[i];
242 PadState& state = pad_states_.get()[i]; 238 PadState& state = pad_states_.get()[i];
243 if (pad.connected && !state.connected()) { 239 if (pad.connected && !state.connected()) {
244 OnGamepadConnectionChange(true, i, pad); 240 OnGamepadConnectionChange(true, i, pad);
245 } else if (!pad.connected && state.connected()) { 241 } else if (!pad.connected && state.connected()) {
246 OnGamepadConnectionChange(false, i, pad); 242 OnGamepadConnectionChange(false, i, pad);
247 } else if (pad.connected && state.connected() && !state.Match(pad)) { 243 } else if (pad.connected && state.connected() && !state.Match(pad)) {
248 WebGamepad old_pad; 244 WebGamepad old_pad;
249 state.AsWebGamepad(&old_pad); 245 state.AsWebGamepad(&old_pad);
250 OnGamepadConnectionChange(false, i, old_pad); 246 OnGamepadConnectionChange(false, i, old_pad);
251 OnGamepadConnectionChange(true, i, pad); 247 OnGamepadConnectionChange(true, i, pad);
(...skipping 17 matching lines...) Expand all
269 if (is_paused_) 265 if (is_paused_)
270 return; 266 return;
271 } 267 }
272 268
273 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 269 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
274 FROM_HERE, base::Bind(&GamepadProvider::DoPoll, Unretained(this)), 270 FROM_HERE, base::Bind(&GamepadProvider::DoPoll, Unretained(this)),
275 base::TimeDelta::FromMilliseconds(kDesiredSamplingIntervalMs)); 271 base::TimeDelta::FromMilliseconds(kDesiredSamplingIntervalMs));
276 have_scheduled_do_poll_ = true; 272 have_scheduled_do_poll_ = true;
277 } 273 }
278 274
279 void GamepadProvider::OnGamepadConnectionChange( 275 void GamepadProvider::OnGamepadConnectionChange(bool connected,
280 bool connected, int index, const WebGamepad& pad) { 276 int index,
277 const WebGamepad& pad) {
281 PadState& state = pad_states_.get()[index]; 278 PadState& state = pad_states_.get()[index];
282 if (connected) 279 if (connected)
283 state.SetPad(pad); 280 state.SetPad(pad);
284 else 281 else
285 state.SetDisconnected(); 282 state.SetDisconnected();
286 283
287 BrowserThread::PostTask( 284 if (connection_change_client_)
288 BrowserThread::IO, 285 connection_change_client_->OnGamepadConnectionChange(connected, index, pad);
289 FROM_HERE,
290 base::Bind(&GamepadProvider::DispatchGamepadConnectionChange,
291 base::Unretained(this),
292 connected,
293 index,
294 pad));
295 }
296
297 void GamepadProvider::DispatchGamepadConnectionChange(
298 bool connected, int index, const WebGamepad& pad) {
299 if (connected)
300 GamepadService::GetInstance()->OnGamepadConnected(index, pad);
301 else
302 GamepadService::GetInstance()->OnGamepadDisconnected(index, pad);
303 }
304
305 GamepadHardwareBuffer* GamepadProvider::SharedMemoryAsHardwareBuffer() {
306 void* mem = gamepad_shared_memory_.memory();
307 CHECK(mem);
308 return static_cast<GamepadHardwareBuffer*>(mem);
309 } 286 }
310 287
311 void GamepadProvider::CheckForUserGesture() { 288 void GamepadProvider::CheckForUserGesture() {
312 base::AutoLock lock(user_gesture_lock_); 289 base::AutoLock lock(user_gesture_lock_);
313 if (user_gesture_observers_.empty() && ever_had_user_gesture_) 290 if (user_gesture_observers_.empty() && ever_had_user_gesture_)
314 return; 291 return;
315 292
316 bool had_gesture_before = ever_had_user_gesture_; 293 bool had_gesture_before = ever_had_user_gesture_;
317 const WebGamepads& pads = SharedMemoryAsHardwareBuffer()->buffer; 294 const WebGamepads* pads = gamepad_shared_buffer_->buffer();
318 if (GamepadsHaveUserGesture(pads)) { 295 if (GamepadsHaveUserGesture(*pads)) {
319 ever_had_user_gesture_ = true; 296 ever_had_user_gesture_ = true;
320 for (size_t i = 0; i < user_gesture_observers_.size(); i++) { 297 for (size_t i = 0; i < user_gesture_observers_.size(); i++) {
321 user_gesture_observers_[i].task_runner->PostTask( 298 user_gesture_observers_[i].task_runner->PostTask(
322 FROM_HERE, user_gesture_observers_[i].closure); 299 FROM_HERE, user_gesture_observers_[i].closure);
323 } 300 }
324 user_gesture_observers_.clear(); 301 user_gesture_observers_.clear();
325 } 302 }
326 if (!had_gesture_before && ever_had_user_gesture_) { 303 if (!had_gesture_before && ever_had_user_gesture_) {
327 // Initialize pad_states_ for the first time. 304 // Initialize pad_states_ for the first time.
328 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { 305 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
329 pad_states_.get()[i].SetPad(pads.items[i]); 306 pad_states_.get()[i].SetPad(pads->items[i]);
330 } 307 }
331 } 308 }
332 } 309 }
333 310
334 } // namespace content 311 } // namespace device
OLDNEW
« no previous file with comments | « device/gamepad/gamepad_provider.h ('k') | device/gamepad/gamepad_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698