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 CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
6#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
7
8#include <utility>
9#include <vector>
10
11#include "base/callback_forward.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/shared_memory.h"
15#include "base/memory/weak_ptr.h"
16#include "base/message_loop/message_loop_proxy.h"
17#include "base/synchronization/lock.h"
18#include "base/system_monitor/system_monitor.h"
19#include "content/common/content_export.h"
20
21namespace base {
22class MessageLoopProxy;
23class Thread;
24}
25
26namespace content {
27
28class GamepadDataFetcher;
29struct GamepadHardwareBuffer;
30
31class CONTENT_EXPORT GamepadProvider :
32  public base::SystemMonitor::DevicesChangedObserver {
33 public:
34  GamepadProvider();
35
36  // Manually specifies the data fetcher. Used for testing.
37  explicit GamepadProvider(scoped_ptr<GamepadDataFetcher> fetcher);
38
39  virtual ~GamepadProvider();
40
41  // Returns the shared memory handle of the gamepad data duplicated into the
42  // given process.
43  base::SharedMemoryHandle GetSharedMemoryHandleForProcess(
44      base::ProcessHandle renderer_process);
45
46  // Pause and resume the background polling thread. Can be called from any
47  // thread.
48  void Pause();
49  void Resume();
50
51  // Registers the given closure for calling when the user has interacted with
52  // the device. This callback will only be issued once.
53  void RegisterForUserGesture(const base::Closure& closure);
54
55  // base::SystemMonitor::DevicesChangedObserver implementation.
56  virtual void OnDevicesChanged(base::SystemMonitor::DeviceType type) OVERRIDE;
57
58 private:
59  void Initialize(scoped_ptr<GamepadDataFetcher> fetcher);
60
61  // Method for setting up the platform-specific data fetcher. Takes ownership
62  // of |fetcher|.
63  void DoInitializePollingThread(scoped_ptr<GamepadDataFetcher> fetcher);
64
65  // Method for sending pause hints to the low-level data fetcher. Runs on
66  // polling_thread_.
67  void SendPauseHint(bool paused);
68
69  // Method for polling a GamepadDataFetcher. Runs on the polling_thread_.
70  void DoPoll();
71  void ScheduleDoPoll();
72
73  GamepadHardwareBuffer* SharedMemoryAsHardwareBuffer();
74
75  // Checks the gamepad state to see if the user has interacted with it.
76  void CheckForUserGesture();
77
78  enum { kDesiredSamplingIntervalMs = 16 };
79
80  // Keeps track of when the background thread is paused. Access to is_paused_
81  // must be guarded by is_paused_lock_.
82  base::Lock is_paused_lock_;
83  bool is_paused_;
84
85  // Keep track of when a polling task is schedlued, so as to prevent us from
86  // accidentally scheduling more than one at any time, when rapidly toggling
87  // |is_paused_|.
88  bool have_scheduled_do_poll_;
89
90  // Lists all observers registered for user gestures, and the thread which
91  // to issue the callbacks on. Since we always issue the callback on the
92  // thread which the registration happened, and this class lives on the I/O
93  // thread, the message loop proxies will normally just be the I/O thread.
94  // However, this will be the main thread for unit testing.
95  base::Lock user_gesture_lock_;
96  struct ClosureAndThread {
97    ClosureAndThread(const base::Closure& c,
98                     const scoped_refptr<base::MessageLoopProxy>& m);
99    ~ClosureAndThread();
100
101    base::Closure closure;
102    scoped_refptr<base::MessageLoopProxy> message_loop;
103  };
104  typedef std::vector<ClosureAndThread> UserGestureObserverVector;
105  UserGestureObserverVector user_gesture_observers_;
106
107  // Updated based on notification from SystemMonitor when the system devices
108  // have been updated, and this notification is passed on to the data fetcher
109  // to enable it to avoid redundant (and possibly expensive) is-connected
110  // tests. Access to devices_changed_ must be guarded by
111  // devices_changed_lock_.
112  base::Lock devices_changed_lock_;
113  bool devices_changed_;
114
115  // When polling_thread_ is running, members below are only to be used
116  // from that thread.
117  scoped_ptr<GamepadDataFetcher> data_fetcher_;
118  base::SharedMemory gamepad_shared_memory_;
119
120  // Polling is done on this background thread.
121  scoped_ptr<base::Thread> polling_thread_;
122
123  static GamepadProvider* instance_;
124
125  DISALLOW_COPY_AND_ASSIGN(GamepadProvider);
126};
127
128}  // namespace content
129
130#endif  // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
131