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/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"
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
);
38 class DataFetcherSharedMemoryBase::PollingThread
: public base::Thread
{
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; }
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
)
64 consumers_bitmask_(0),
68 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
71 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
72 ConsumerType consumer_type
, void* buffer
) {
74 if (!fetcher_
->Start(consumer_type
, buffer
))
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
) {
90 if (!fetcher_
->Stop(consumer_type
))
93 consumers_bitmask_
^= consumer_type
;
95 if (!consumers_bitmask_
)
96 timer_
.reset(); // will also stop the timer.
99 void DataFetcherSharedMemoryBase::PollingThread::DoPoll() {
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.
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
)
127 void* buffer
= GetSharedMemoryBuffer(consumer_type
);
131 if (GetType() != FETCHER_TYPE_DEFAULT
) {
132 if (!InitAndStartPollingThreadIfNecessary())
134 polling_thread_
->task_runner()->PostTask(
135 FROM_HERE
, base::Bind(&PollingThread::AddConsumer
,
136 base::Unretained(polling_thread_
.get()),
137 consumer_type
, buffer
));
139 if (!Start(consumer_type
, buffer
))
143 started_consumers_
|= consumer_type
;
148 bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
149 ConsumerType consumer_type
) {
150 if (!(started_consumers_
& consumer_type
))
153 if (GetType() != FETCHER_TYPE_DEFAULT
) {
154 polling_thread_
->task_runner()->PostTask(
156 base::Bind(&PollingThread::RemoveConsumer
,
157 base::Unretained(polling_thread_
.get()), consumer_type
));
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