summaryrefslogtreecommitdiffstats
path: root/chromium/content/browser/gamepad/gamepad_provider.h
blob: 5f10f137a14ed8311b94a25d7242fa9596ef227f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// 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 CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_

#include <utility>
#include <vector>

#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/synchronization/lock.h"
#include "base/system_monitor/system_monitor.h"
#include "content/common/content_export.h"

namespace base {
class MessageLoopProxy;
class Thread;
}

namespace content {

class GamepadDataFetcher;
struct GamepadHardwareBuffer;

class CONTENT_EXPORT GamepadProvider :
  public base::SystemMonitor::DevicesChangedObserver {
 public:
  GamepadProvider();

  // Manually specifies the data fetcher. Used for testing.
  explicit GamepadProvider(scoped_ptr<GamepadDataFetcher> fetcher);

  virtual ~GamepadProvider();

  // Returns the shared memory handle of the gamepad data duplicated into the
  // given process.
  base::SharedMemoryHandle GetSharedMemoryHandleForProcess(
      base::ProcessHandle renderer_process);

  // 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(const base::Closure& closure);

  // base::SystemMonitor::DevicesChangedObserver implementation.
  virtual void OnDevicesChanged(base::SystemMonitor::DeviceType type) OVERRIDE;

 private:
  void Initialize(scoped_ptr<GamepadDataFetcher> fetcher);

  // Method for setting up the platform-specific data fetcher. Takes ownership
  // of |fetcher|.
  void DoInitializePollingThread(scoped_ptr<GamepadDataFetcher> fetcher);

  // 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();

  GamepadHardwareBuffer* SharedMemoryAsHardwareBuffer();

  // Checks the gamepad state to see if the user has interacted with it.
  void CheckForUserGesture();

  enum { kDesiredSamplingIntervalMs = 16 };

  // 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_;

  // 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_;

  // 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_;
  struct ClosureAndThread {
    ClosureAndThread(const base::Closure& c,
                     const scoped_refptr<base::MessageLoopProxy>& m);
    ~ClosureAndThread();

    base::Closure closure;
    scoped_refptr<base::MessageLoopProxy> message_loop;
  };
  typedef std::vector<ClosureAndThread> UserGestureObserverVector;
  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_;

  // When polling_thread_ is running, members below are only to be used
  // from that thread.
  scoped_ptr<GamepadDataFetcher> data_fetcher_;
  base::SharedMemory gamepad_shared_memory_;

  // Polling is done on this background thread.
  scoped_ptr<base::Thread> polling_thread_;

  static GamepadProvider* instance_;

  DISALLOW_COPY_AND_ASSIGN(GamepadProvider);
};

}  // namespace content

#endif  // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_