Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / device_sensors / data_fetcher_shared_memory_base.cc
1 // Copyright 2014 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 #include "content/browser/device_sensors/data_fetcher_shared_memory_base.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/stl_util.h"
10 #include "base/threading/thread.h"
11 #include "base/timer/timer.h"
12 #include "content/common/device_sensors/device_motion_hardware_buffer.h"
13 #include "content/common/device_sensors/device_orientation_hardware_buffer.h"
14
15 namespace content {
16
17 namespace {
18
19 static size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type) {
20   switch (consumer_type) {
21     case CONSUMER_TYPE_MOTION:
22       return sizeof(DeviceMotionHardwareBuffer);
23     case CONSUMER_TYPE_ORIENTATION:
24       return sizeof(DeviceOrientationHardwareBuffer);
25     default:
26       NOTREACHED();
27   }
28   return 0;
29 }
30
31 }  // namespace
32
33 class DataFetcherSharedMemoryBase::PollingThread : public base::Thread {
34  public:
35   PollingThread(const char* name, DataFetcherSharedMemoryBase* fetcher);
36   virtual ~PollingThread();
37
38   void AddConsumer(ConsumerType consumer_type, void* buffer);
39   void RemoveConsumer(ConsumerType consumer_type);
40
41   unsigned GetConsumersBitmask() const { return consumers_bitmask_; }
42   bool IsTimerRunning() const { return timer_ ? timer_->IsRunning() : false; }
43
44  private:
45   void DoPoll();
46
47   unsigned consumers_bitmask_;
48   DataFetcherSharedMemoryBase* fetcher_;
49   scoped_ptr<base::RepeatingTimer<PollingThread> > timer_;
50
51   DISALLOW_COPY_AND_ASSIGN(PollingThread);
52 };
53
54 // --- PollingThread methods
55
56 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
57     const char* name, DataFetcherSharedMemoryBase* fetcher)
58     : base::Thread(name),
59       consumers_bitmask_(0),
60       fetcher_(fetcher) {
61 }
62
63 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
64 }
65
66 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
67     ConsumerType consumer_type, void* buffer) {
68   DCHECK(fetcher_);
69   if (!fetcher_->Start(consumer_type, buffer))
70     return;
71
72   consumers_bitmask_ |= consumer_type;
73
74   if (!timer_ && fetcher_->GetType() == FETCHER_TYPE_POLLING_CALLBACK) {
75     timer_.reset(new base::RepeatingTimer<PollingThread>());
76     timer_->Start(FROM_HERE,
77                   fetcher_->GetInterval(),
78                   this, &PollingThread::DoPoll);
79   }
80 }
81
82 void DataFetcherSharedMemoryBase::PollingThread::RemoveConsumer(
83     ConsumerType consumer_type) {
84   DCHECK(fetcher_);
85   if (!fetcher_->Stop(consumer_type))
86     return;
87
88   consumers_bitmask_ ^= consumer_type;
89
90   if (!consumers_bitmask_)
91     timer_.reset();  // will also stop the timer.
92 }
93
94 void DataFetcherSharedMemoryBase::PollingThread::DoPoll() {
95   DCHECK(fetcher_);
96   DCHECK(consumers_bitmask_);
97   fetcher_->Fetch(consumers_bitmask_);
98 }
99
100 // --- end of PollingThread methods
101
102 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
103     : started_consumers_(0) {
104 }
105
106 DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
107   StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
108   StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
109
110   // make sure polling thread stops asap.
111   if (polling_thread_)
112     polling_thread_->Stop();
113
114   STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(),
115       shared_memory_map_.end());
116 }
117
118 bool DataFetcherSharedMemoryBase::StartFetchingDeviceData(
119     ConsumerType consumer_type) {
120   if (started_consumers_ & consumer_type)
121     return true;
122
123   void* buffer = GetSharedMemoryBuffer(consumer_type);
124   if (!buffer)
125     return false;
126
127   if (GetType() != FETCHER_TYPE_DEFAULT) {
128     if (!InitAndStartPollingThreadIfNecessary())
129       return false;
130     polling_thread_->message_loop()->PostTask(
131         FROM_HERE,
132         base::Bind(&PollingThread::AddConsumer,
133                    base::Unretained(polling_thread_.get()),
134                    consumer_type, buffer));
135   } else {
136     if (!Start(consumer_type, buffer))
137       return false;
138   }
139
140   started_consumers_ |= consumer_type;
141
142   return true;
143 }
144
145 bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
146     ConsumerType consumer_type) {
147   if (!(started_consumers_ & consumer_type))
148     return true;
149
150   if (GetType() != FETCHER_TYPE_DEFAULT) {
151     polling_thread_->message_loop()->PostTask(
152         FROM_HERE,
153         base::Bind(&PollingThread::RemoveConsumer,
154                    base::Unretained(polling_thread_.get()),
155                    consumer_type));
156   } else {
157     if (!Stop(consumer_type))
158       return false;
159   }
160
161   started_consumers_ ^= consumer_type;
162
163   return true;
164 }
165
166 base::SharedMemoryHandle
167 DataFetcherSharedMemoryBase::GetSharedMemoryHandleForProcess(
168     ConsumerType consumer_type, base::ProcessHandle process) {
169   SharedMemoryMap::const_iterator it = shared_memory_map_.find(consumer_type);
170   if (it == shared_memory_map_.end())
171     return base::SharedMemory::NULLHandle();
172
173   base::SharedMemoryHandle renderer_handle;
174   it->second->ShareToProcess(process, &renderer_handle);
175   return renderer_handle;
176 }
177
178 bool DataFetcherSharedMemoryBase::InitAndStartPollingThreadIfNecessary() {
179   if (polling_thread_)
180     return true;
181
182   polling_thread_.reset(
183       new PollingThread("Inertial Device Sensor poller", this));
184
185   if (!polling_thread_->Start()) {
186       LOG(ERROR) << "Failed to start inertial sensor data polling thread";
187       return false;
188   }
189   return true;
190 }
191
192 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
193   NOTIMPLEMENTED();
194 }
195
196 DataFetcherSharedMemoryBase::FetcherType
197 DataFetcherSharedMemoryBase::GetType() const {
198   return FETCHER_TYPE_DEFAULT;
199 }
200
201 base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
202   return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis);
203 }
204
205 base::SharedMemory* DataFetcherSharedMemoryBase::GetSharedMemory(
206     ConsumerType consumer_type) {
207   SharedMemoryMap::const_iterator it = shared_memory_map_.find(consumer_type);
208   if (it != shared_memory_map_.end())
209     return it->second;
210
211   size_t buffer_size = GetConsumerSharedMemoryBufferSize(consumer_type);
212   if (buffer_size == 0)
213     return NULL;
214
215   scoped_ptr<base::SharedMemory> new_shared_mem(new base::SharedMemory);
216   if (new_shared_mem->CreateAndMapAnonymous(buffer_size)) {
217     if (void* mem = new_shared_mem->memory()) {
218       memset(mem, 0, buffer_size);
219       base::SharedMemory* shared_mem = new_shared_mem.release();
220       shared_memory_map_[consumer_type] = shared_mem;
221       return shared_mem;
222     }
223   }
224   LOG(ERROR) << "Failed to initialize shared memory";
225   return NULL;
226 }
227
228 void* DataFetcherSharedMemoryBase::GetSharedMemoryBuffer(
229     ConsumerType consumer_type) {
230   if (base::SharedMemory* shared_memory = GetSharedMemory(consumer_type))
231     return shared_memory->memory();
232   return NULL;
233 }
234
235 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
236   return polling_thread_ ? polling_thread_->message_loop() : NULL;
237 }
238
239 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
240   return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
241 }
242
243
244 }  // namespace content