Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / device_sensors / data_fetcher_shared_memory_base.cc
blobac86c6f8c69613e67b92b2385110ae491eeff8fa
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.
5 #include "content/browser/device_sensors/data_fetcher_shared_memory_base.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/stl_util.h"
12 #include "base/threading/thread.h"
13 #include "base/timer/timer.h"
14 #include "content/common/device_sensors/device_light_hardware_buffer.h"
15 #include "content/common/device_sensors/device_motion_hardware_buffer.h"
16 #include "content/common/device_sensors/device_orientation_hardware_buffer.h"
18 namespace content {
20 namespace {
22 size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type) {
23 switch (consumer_type) {
24 case CONSUMER_TYPE_MOTION:
25 return sizeof(DeviceMotionHardwareBuffer);
26 case CONSUMER_TYPE_ORIENTATION:
27 return sizeof(DeviceOrientationHardwareBuffer);
28 case CONSUMER_TYPE_LIGHT:
29 return sizeof(DeviceLightHardwareBuffer);
30 default:
31 NOTREACHED();
33 return 0;
36 } // namespace
38 class DataFetcherSharedMemoryBase::PollingThread : public base::Thread {
39 public:
40 PollingThread(const char* name, DataFetcherSharedMemoryBase* fetcher);
41 ~PollingThread() override;
43 void AddConsumer(ConsumerType consumer_type, void* buffer);
44 void RemoveConsumer(ConsumerType consumer_type);
46 unsigned GetConsumersBitmask() const { return consumers_bitmask_; }
47 bool IsTimerRunning() const { return timer_ ? timer_->IsRunning() : false; }
49 private:
50 void DoPoll();
52 unsigned consumers_bitmask_;
53 DataFetcherSharedMemoryBase* fetcher_;
54 scoped_ptr<base::RepeatingTimer<PollingThread> > timer_;
56 DISALLOW_COPY_AND_ASSIGN(PollingThread);
59 // --- PollingThread methods
61 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
62 const char* name, DataFetcherSharedMemoryBase* fetcher)
63 : base::Thread(name),
64 consumers_bitmask_(0),
65 fetcher_(fetcher) {
68 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
71 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
72 ConsumerType consumer_type, void* buffer) {
73 DCHECK(fetcher_);
74 if (!fetcher_->Start(consumer_type, buffer))
75 return;
77 consumers_bitmask_ |= consumer_type;
79 if (!timer_ && fetcher_->GetType() == FETCHER_TYPE_POLLING_CALLBACK) {
80 timer_.reset(new base::RepeatingTimer<PollingThread>());
81 timer_->Start(FROM_HERE,
82 fetcher_->GetInterval(),
83 this, &PollingThread::DoPoll);
87 void DataFetcherSharedMemoryBase::PollingThread::RemoveConsumer(
88 ConsumerType consumer_type) {
89 DCHECK(fetcher_);
90 if (!fetcher_->Stop(consumer_type))
91 return;
93 consumers_bitmask_ ^= consumer_type;
95 if (!consumers_bitmask_)
96 timer_.reset(); // will also stop the timer.
99 void DataFetcherSharedMemoryBase::PollingThread::DoPoll() {
100 DCHECK(fetcher_);
101 DCHECK(consumers_bitmask_);
102 fetcher_->Fetch(consumers_bitmask_);
105 // --- end of PollingThread methods
107 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
108 : started_consumers_(0) {
111 DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
112 DCHECK_EQ(0u, started_consumers_);
114 // make sure polling thread stops asap.
115 if (polling_thread_)
116 polling_thread_->Stop();
118 STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(),
119 shared_memory_map_.end());
122 bool DataFetcherSharedMemoryBase::StartFetchingDeviceData(
123 ConsumerType consumer_type) {
124 if (started_consumers_ & consumer_type)
125 return true;
127 void* buffer = GetSharedMemoryBuffer(consumer_type);
128 if (!buffer)
129 return false;
131 if (GetType() != FETCHER_TYPE_DEFAULT) {
132 if (!InitAndStartPollingThreadIfNecessary())
133 return false;
134 polling_thread_->task_runner()->PostTask(
135 FROM_HERE, base::Bind(&PollingThread::AddConsumer,
136 base::Unretained(polling_thread_.get()),
137 consumer_type, buffer));
138 } else {
139 if (!Start(consumer_type, buffer))
140 return false;
143 started_consumers_ |= consumer_type;
145 return true;
148 bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
149 ConsumerType consumer_type) {
150 if (!(started_consumers_ & consumer_type))
151 return true;
153 if (GetType() != FETCHER_TYPE_DEFAULT) {
154 polling_thread_->task_runner()->PostTask(
155 FROM_HERE,
156 base::Bind(&PollingThread::RemoveConsumer,
157 base::Unretained(polling_thread_.get()), consumer_type));
158 } else {
159 if (!Stop(consumer_type))
160 return false;
163 started_consumers_ ^= consumer_type;
165 return true;
168 void DataFetcherSharedMemoryBase::Shutdown() {
169 StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
170 StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
171 StopFetchingDeviceData(CONSUMER_TYPE_LIGHT);
174 base::SharedMemoryHandle
175 DataFetcherSharedMemoryBase::GetSharedMemoryHandleForProcess(
176 ConsumerType consumer_type, base::ProcessHandle process) {
177 SharedMemoryMap::const_iterator it = shared_memory_map_.find(consumer_type);
178 if (it == shared_memory_map_.end())
179 return base::SharedMemory::NULLHandle();
181 base::SharedMemoryHandle renderer_handle;
182 it->second->ShareToProcess(process, &renderer_handle);
183 return renderer_handle;
186 bool DataFetcherSharedMemoryBase::InitAndStartPollingThreadIfNecessary() {
187 if (polling_thread_)
188 return true;
190 polling_thread_.reset(
191 new PollingThread("Inertial Device Sensor poller", this));
193 if (!polling_thread_->Start()) {
194 LOG(ERROR) << "Failed to start inertial sensor data polling thread";
195 return false;
197 return true;
200 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
201 NOTIMPLEMENTED();
204 DataFetcherSharedMemoryBase::FetcherType
205 DataFetcherSharedMemoryBase::GetType() const {
206 return FETCHER_TYPE_DEFAULT;
209 base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
210 return base::TimeDelta::FromMicroseconds(kInertialSensorIntervalMicroseconds);
213 base::SharedMemory* DataFetcherSharedMemoryBase::GetSharedMemory(
214 ConsumerType consumer_type) {
215 SharedMemoryMap::const_iterator it = shared_memory_map_.find(consumer_type);
216 if (it != shared_memory_map_.end())
217 return it->second;
219 size_t buffer_size = GetConsumerSharedMemoryBufferSize(consumer_type);
220 if (buffer_size == 0)
221 return nullptr;
223 scoped_ptr<base::SharedMemory> new_shared_mem(new base::SharedMemory);
224 if (new_shared_mem->CreateAndMapAnonymous(buffer_size)) {
225 if (void* mem = new_shared_mem->memory()) {
226 memset(mem, 0, buffer_size);
227 base::SharedMemory* shared_mem = new_shared_mem.release();
228 shared_memory_map_[consumer_type] = shared_mem;
229 return shared_mem;
232 LOG(ERROR) << "Failed to initialize shared memory";
233 return nullptr;
236 void* DataFetcherSharedMemoryBase::GetSharedMemoryBuffer(
237 ConsumerType consumer_type) {
238 if (base::SharedMemory* shared_memory = GetSharedMemory(consumer_type))
239 return shared_memory->memory();
240 return nullptr;
243 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
244 return polling_thread_ ? polling_thread_->message_loop() : nullptr;
247 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
248 return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
251 } // namespace content