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_motion_hardware_buffer.h"
     13 #include "content/common/device_sensors/device_orientation_hardware_buffer.h"
     14 
     15 namespace content {
     16 
     17 namespace {
     18 
     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 
     41   unsigned GetConsumersBitmask() const { return consumers_bitmask_; }
     42   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 
     56 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
     57     const char* name, DataFetcherSharedMemoryBase* fetcher)
     58     : base::Thread(name),
     59       consumers_bitmask_(0),
     60       fetcher_(fetcher) {
     61 }
     62 
     63 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
     64 }
     65 
     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 
     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 
     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 
    102 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
    103     : started_consumers_(0) {
    104 }
    105 
    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 
    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 
    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
    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 
    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 
    192 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
    193   NOTIMPLEMENTED();
    194 }
    195 
    196 DataFetcherSharedMemoryBase::FetcherType
    197 DataFetcherSharedMemoryBase::GetType() const {
    198   return FETCHER_TYPE_DEFAULT;
    199 }
    200 
    201 base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
    202   return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis);
    203 }
    204 
    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 
    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 
    235 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
    236   return polling_thread_ ? polling_thread_->message_loop() : NULL;
    237 }
    238 
    239 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
    240   return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
    241 }
    242 
    243 
    244 }  // namespace content
    245