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_light_hardware_buffer.h"
13 #include "content/common/device_sensors/device_motion_hardware_buffer.h"
14 #include "content/common/device_sensors/device_orientation_hardware_buffer.h"
20 size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type
) {
21 switch (consumer_type
) {
22 case CONSUMER_TYPE_MOTION
:
23 return sizeof(DeviceMotionHardwareBuffer
);
24 case CONSUMER_TYPE_ORIENTATION
:
25 return sizeof(DeviceOrientationHardwareBuffer
);
26 case CONSUMER_TYPE_LIGHT
:
27 return sizeof(DeviceLightHardwareBuffer
);
36 class DataFetcherSharedMemoryBase::PollingThread
: public base::Thread
{
38 PollingThread(const char* name
, DataFetcherSharedMemoryBase
* fetcher
);
39 ~PollingThread() override
;
41 void AddConsumer(ConsumerType consumer_type
, void* buffer
);
42 void RemoveConsumer(ConsumerType consumer_type
);
44 unsigned GetConsumersBitmask() const { return consumers_bitmask_
; }
45 bool IsTimerRunning() const { return timer_
? timer_
->IsRunning() : false; }
50 unsigned consumers_bitmask_
;
51 DataFetcherSharedMemoryBase
* fetcher_
;
52 scoped_ptr
<base::RepeatingTimer
<PollingThread
> > timer_
;
54 DISALLOW_COPY_AND_ASSIGN(PollingThread
);
57 // --- PollingThread methods
59 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
60 const char* name
, DataFetcherSharedMemoryBase
* fetcher
)
62 consumers_bitmask_(0),
66 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
69 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
70 ConsumerType consumer_type
, void* buffer
) {
72 if (!fetcher_
->Start(consumer_type
, buffer
))
75 consumers_bitmask_
|= consumer_type
;
77 if (!timer_
&& fetcher_
->GetType() == FETCHER_TYPE_POLLING_CALLBACK
) {
78 timer_
.reset(new base::RepeatingTimer
<PollingThread
>());
79 timer_
->Start(FROM_HERE
,
80 fetcher_
->GetInterval(),
81 this, &PollingThread::DoPoll
);
85 void DataFetcherSharedMemoryBase::PollingThread::RemoveConsumer(
86 ConsumerType consumer_type
) {
88 if (!fetcher_
->Stop(consumer_type
))
91 consumers_bitmask_
^= consumer_type
;
93 if (!consumers_bitmask_
)
94 timer_
.reset(); // will also stop the timer.
97 void DataFetcherSharedMemoryBase::PollingThread::DoPoll() {
99 DCHECK(consumers_bitmask_
);
100 fetcher_
->Fetch(consumers_bitmask_
);
103 // --- end of PollingThread methods
105 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
106 : started_consumers_(0) {
109 DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
110 DCHECK_EQ(0u, started_consumers_
);
112 // make sure polling thread stops asap.
114 polling_thread_
->Stop();
116 STLDeleteContainerPairSecondPointers(shared_memory_map_
.begin(),
117 shared_memory_map_
.end());
120 bool DataFetcherSharedMemoryBase::StartFetchingDeviceData(
121 ConsumerType consumer_type
) {
122 if (started_consumers_
& consumer_type
)
125 void* buffer
= GetSharedMemoryBuffer(consumer_type
);
129 if (GetType() != FETCHER_TYPE_DEFAULT
) {
130 if (!InitAndStartPollingThreadIfNecessary())
132 polling_thread_
->message_loop()->PostTask(
134 base::Bind(&PollingThread::AddConsumer
,
135 base::Unretained(polling_thread_
.get()),
136 consumer_type
, buffer
));
138 if (!Start(consumer_type
, buffer
))
142 started_consumers_
|= consumer_type
;
147 bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
148 ConsumerType consumer_type
) {
149 if (!(started_consumers_
& consumer_type
))
152 if (GetType() != FETCHER_TYPE_DEFAULT
) {
153 polling_thread_
->message_loop()->PostTask(
155 base::Bind(&PollingThread::RemoveConsumer
,
156 base::Unretained(polling_thread_
.get()),
159 if (!Stop(consumer_type
))
163 started_consumers_
^= consumer_type
;
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() {
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";
200 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask
) {
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())
219 size_t buffer_size
= GetConsumerSharedMemoryBufferSize(consumer_type
);
220 if (buffer_size
== 0)
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
;
232 LOG(ERROR
) << "Failed to initialize shared memory";
236 void* DataFetcherSharedMemoryBase::GetSharedMemoryBuffer(
237 ConsumerType consumer_type
) {
238 if (base::SharedMemory
* shared_memory
= GetSharedMemory(consumer_type
))
239 return shared_memory
->memory();
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