• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type)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 
GetConsumersBitmask() const41   unsigned GetConsumersBitmask() const { return consumers_bitmask_; }
IsTimerRunning() const42   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 
PollingThread(const char * name,DataFetcherSharedMemoryBase * fetcher)56 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
57     const char* name, DataFetcherSharedMemoryBase* fetcher)
58     : base::Thread(name),
59       consumers_bitmask_(0),
60       fetcher_(fetcher) {
61 }
62 
~PollingThread()63 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
64 }
65 
AddConsumer(ConsumerType consumer_type,void * buffer)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 
RemoveConsumer(ConsumerType consumer_type)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 
DoPoll()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 
DataFetcherSharedMemoryBase()102 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
103     : started_consumers_(0) {
104 }
105 
~DataFetcherSharedMemoryBase()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 
StartFetchingDeviceData(ConsumerType consumer_type)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 
StopFetchingDeviceData(ConsumerType consumer_type)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
GetSharedMemoryHandleForProcess(ConsumerType consumer_type,base::ProcessHandle process)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 
InitAndStartPollingThreadIfNecessary()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 
Fetch(unsigned consumer_bitmask)192 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
193   NOTIMPLEMENTED();
194 }
195 
196 DataFetcherSharedMemoryBase::FetcherType
GetType() const197 DataFetcherSharedMemoryBase::GetType() const {
198   return FETCHER_TYPE_DEFAULT;
199 }
200 
GetInterval() const201 base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
202   return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis);
203 }
204 
GetSharedMemory(ConsumerType consumer_type)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 
GetSharedMemoryBuffer(ConsumerType consumer_type)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 
GetPollingMessageLoop() const235 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
236   return polling_thread_ ? polling_thread_->message_loop() : NULL;
237 }
238 
IsPollingTimerRunningForTesting() const239 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
240   return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
241 }
242 
243 
244 }  // namespace content
245