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"
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"
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
);
33 class DataFetcherSharedMemoryBase::PollingThread
: public base::Thread
{
35 PollingThread(const char* name
, DataFetcherSharedMemoryBase
* fetcher
);
36 virtual ~PollingThread();
38 void AddConsumer(ConsumerType consumer_type
, void* buffer
);
39 void RemoveConsumer(ConsumerType consumer_type
);
41 unsigned GetConsumersBitmask() const { return consumers_bitmask_
; }
42 bool IsTimerRunning() const { return timer_
? timer_
->IsRunning() : false; }
47 unsigned consumers_bitmask_
;
48 DataFetcherSharedMemoryBase
* fetcher_
;
49 scoped_ptr
<base::RepeatingTimer
<PollingThread
> > timer_
;
51 DISALLOW_COPY_AND_ASSIGN(PollingThread
);
54 // --- PollingThread methods
56 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
57 const char* name
, DataFetcherSharedMemoryBase
* fetcher
)
59 consumers_bitmask_(0),
63 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
66 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
67 ConsumerType consumer_type
, void* buffer
) {
69 if (!fetcher_
->Start(consumer_type
, buffer
))
72 consumers_bitmask_
|= consumer_type
;
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
);
82 void DataFetcherSharedMemoryBase::PollingThread::RemoveConsumer(
83 ConsumerType consumer_type
) {
85 if (!fetcher_
->Stop(consumer_type
))
88 consumers_bitmask_
^= consumer_type
;
90 if (!consumers_bitmask_
)
91 timer_
.reset(); // will also stop the timer.
94 void DataFetcherSharedMemoryBase::PollingThread::DoPoll() {
96 DCHECK(consumers_bitmask_
);
97 fetcher_
->Fetch(consumers_bitmask_
);
100 // --- end of PollingThread methods
102 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
103 : started_consumers_(0) {
106 DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
107 StopFetchingDeviceData(CONSUMER_TYPE_MOTION
);
108 StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION
);
110 // make sure polling thread stops asap.
112 polling_thread_
->Stop();
114 STLDeleteContainerPairSecondPointers(shared_memory_map_
.begin(),
115 shared_memory_map_
.end());
118 bool DataFetcherSharedMemoryBase::StartFetchingDeviceData(
119 ConsumerType consumer_type
) {
120 if (started_consumers_
& consumer_type
)
123 void* buffer
= GetSharedMemoryBuffer(consumer_type
);
127 if (GetType() != FETCHER_TYPE_DEFAULT
) {
128 if (!InitAndStartPollingThreadIfNecessary())
130 polling_thread_
->message_loop()->PostTask(
132 base::Bind(&PollingThread::AddConsumer
,
133 base::Unretained(polling_thread_
.get()),
134 consumer_type
, buffer
));
136 if (!Start(consumer_type
, buffer
))
140 started_consumers_
|= consumer_type
;
145 bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
146 ConsumerType consumer_type
) {
147 if (!(started_consumers_
& consumer_type
))
150 if (GetType() != FETCHER_TYPE_DEFAULT
) {
151 polling_thread_
->message_loop()->PostTask(
153 base::Bind(&PollingThread::RemoveConsumer
,
154 base::Unretained(polling_thread_
.get()),
157 if (!Stop(consumer_type
))
161 started_consumers_
^= consumer_type
;
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();
173 base::SharedMemoryHandle renderer_handle
;
174 it
->second
->ShareToProcess(process
, &renderer_handle
);
175 return renderer_handle
;
178 bool DataFetcherSharedMemoryBase::InitAndStartPollingThreadIfNecessary() {
182 polling_thread_
.reset(
183 new PollingThread("Inertial Device Sensor poller", this));
185 if (!polling_thread_
->Start()) {
186 LOG(ERROR
) << "Failed to start inertial sensor data polling thread";
192 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask
) {
196 DataFetcherSharedMemoryBase::FetcherType
197 DataFetcherSharedMemoryBase::GetType() const {
198 return FETCHER_TYPE_DEFAULT
;
201 base::TimeDelta
DataFetcherSharedMemoryBase::GetInterval() const {
202 return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis
);
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())
211 size_t buffer_size
= GetConsumerSharedMemoryBufferSize(consumer_type
);
212 if (buffer_size
== 0)
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
;
224 LOG(ERROR
) << "Failed to initialize shared memory";
228 void* DataFetcherSharedMemoryBase::GetSharedMemoryBuffer(
229 ConsumerType consumer_type
) {
230 if (base::SharedMemory
* shared_memory
= GetSharedMemory(consumer_type
))
231 return shared_memory
->memory();
235 base::MessageLoop
* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
236 return polling_thread_
? polling_thread_
->message_loop() : NULL
;
239 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
240 return polling_thread_
? polling_thread_
->IsTimerRunning() : false;
244 } // namespace content