Home | History | Annotate | Download | only in device_sensors
      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_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"
     15 
     16 namespace content {
     17 
     18 namespace {
     19 
     20 static 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);
     28     default:
     29       NOTREACHED();
     30   }
     31   return 0;
     32 }
     33 
     34 }  // namespace
     35 
     36 class DataFetcherSharedMemoryBase::PollingThread : public base::Thread {
     37  public:
     38   PollingThread(const char* name, DataFetcherSharedMemoryBase* fetcher);
     39   virtual ~PollingThread();
     40 
     41   void AddConsumer(ConsumerType consumer_type, void* buffer);
     42   void RemoveConsumer(ConsumerType consumer_type);
     43 
     44   unsigned GetConsumersBitmask() const { return consumers_bitmask_; }
     45   bool IsTimerRunning() const { return timer_ ? timer_->IsRunning() : false; }
     46 
     47  private:
     48   void DoPoll();
     49 
     50   unsigned consumers_bitmask_;
     51   DataFetcherSharedMemoryBase* fetcher_;
     52   scoped_ptr<base::RepeatingTimer<PollingThread> > timer_;
     53 
     54   DISALLOW_COPY_AND_ASSIGN(PollingThread);
     55 };
     56 
     57 // --- PollingThread methods
     58 
     59 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
     60     const char* name, DataFetcherSharedMemoryBase* fetcher)
     61     : base::Thread(name),
     62       consumers_bitmask_(0),
     63       fetcher_(fetcher) {
     64 }
     65 
     66 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
     67 }
     68 
     69 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
     70     ConsumerType consumer_type, void* buffer) {
     71   DCHECK(fetcher_);
     72   if (!fetcher_->Start(consumer_type, buffer))
     73     return;
     74 
     75   consumers_bitmask_ |= consumer_type;
     76 
     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);
     82   }
     83 }
     84 
     85 void DataFetcherSharedMemoryBase::PollingThread::RemoveConsumer(
     86     ConsumerType consumer_type) {
     87   DCHECK(fetcher_);
     88   if (!fetcher_->Stop(consumer_type))
     89     return;
     90 
     91   consumers_bitmask_ ^= consumer_type;
     92 
     93   if (!consumers_bitmask_)
     94     timer_.reset();  // will also stop the timer.
     95 }
     96 
     97 void DataFetcherSharedMemoryBase::PollingThread::DoPoll() {
     98   DCHECK(fetcher_);
     99   DCHECK(consumers_bitmask_);
    100   fetcher_->Fetch(consumers_bitmask_);
    101 }
    102 
    103 // --- end of PollingThread methods
    104 
    105 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
    106     : started_consumers_(0) {
    107 }
    108 
    109 DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
    110   DCHECK_EQ(0u, started_consumers_);
    111 
    112   // make sure polling thread stops asap.
    113   if (polling_thread_)
    114     polling_thread_->Stop();
    115 
    116   STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(),
    117       shared_memory_map_.end());
    118 }
    119 
    120 bool DataFetcherSharedMemoryBase::StartFetchingDeviceData(
    121     ConsumerType consumer_type) {
    122   if (started_consumers_ & consumer_type)
    123     return true;
    124 
    125   void* buffer = GetSharedMemoryBuffer(consumer_type);
    126   if (!buffer)
    127     return false;
    128 
    129   if (GetType() != FETCHER_TYPE_DEFAULT) {
    130     if (!InitAndStartPollingThreadIfNecessary())
    131       return false;
    132     polling_thread_->message_loop()->PostTask(
    133         FROM_HERE,
    134         base::Bind(&PollingThread::AddConsumer,
    135                    base::Unretained(polling_thread_.get()),
    136                    consumer_type, buffer));
    137   } else {
    138     if (!Start(consumer_type, buffer))
    139       return false;
    140   }
    141 
    142   started_consumers_ |= consumer_type;
    143 
    144   return true;
    145 }
    146 
    147 bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
    148     ConsumerType consumer_type) {
    149   if (!(started_consumers_ & consumer_type))
    150     return true;
    151 
    152   if (GetType() != FETCHER_TYPE_DEFAULT) {
    153     polling_thread_->message_loop()->PostTask(
    154         FROM_HERE,
    155         base::Bind(&PollingThread::RemoveConsumer,
    156                    base::Unretained(polling_thread_.get()),
    157                    consumer_type));
    158   } else {
    159     if (!Stop(consumer_type))
    160       return false;
    161   }
    162 
    163   started_consumers_ ^= consumer_type;
    164 
    165   return true;
    166 }
    167 
    168 void DataFetcherSharedMemoryBase::StopFetchingAllDeviceData() {
    169   StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
    170   StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
    171   StopFetchingDeviceData(CONSUMER_TYPE_LIGHT);
    172 }
    173 
    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();
    180 
    181   base::SharedMemoryHandle renderer_handle;
    182   it->second->ShareToProcess(process, &renderer_handle);
    183   return renderer_handle;
    184 }
    185 
    186 bool DataFetcherSharedMemoryBase::InitAndStartPollingThreadIfNecessary() {
    187   if (polling_thread_)
    188     return true;
    189 
    190   polling_thread_.reset(
    191       new PollingThread("Inertial Device Sensor poller", this));
    192 
    193   if (!polling_thread_->Start()) {
    194       LOG(ERROR) << "Failed to start inertial sensor data polling thread";
    195       return false;
    196   }
    197   return true;
    198 }
    199 
    200 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
    201   NOTIMPLEMENTED();
    202 }
    203 
    204 DataFetcherSharedMemoryBase::FetcherType
    205 DataFetcherSharedMemoryBase::GetType() const {
    206   return FETCHER_TYPE_DEFAULT;
    207 }
    208 
    209 base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
    210   return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis);
    211 }
    212 
    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;
    218 
    219   size_t buffer_size = GetConsumerSharedMemoryBufferSize(consumer_type);
    220   if (buffer_size == 0)
    221     return NULL;
    222 
    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;
    230     }
    231   }
    232   LOG(ERROR) << "Failed to initialize shared memory";
    233   return NULL;
    234 }
    235 
    236 void* DataFetcherSharedMemoryBase::GetSharedMemoryBuffer(
    237     ConsumerType consumer_type) {
    238   if (base::SharedMemory* shared_memory = GetSharedMemory(consumer_type))
    239     return shared_memory->memory();
    240   return NULL;
    241 }
    242 
    243 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
    244   return polling_thread_ ? polling_thread_->message_loop() : NULL;
    245 }
    246 
    247 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
    248   return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
    249 }
    250 
    251 }  // namespace content
    252