| OLD | NEW |
| (Empty) |
| 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 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 ~PollingThread() override; | |
| 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::Shutdown() { | |
| 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::FromMicroseconds(kInertialSensorIntervalMicroseconds); | |
| 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 nullptr; | |
| 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 nullptr; | |
| 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 nullptr; | |
| 241 } | |
| 242 | |
| 243 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const { | |
| 244 return polling_thread_ ? polling_thread_->message_loop() : nullptr; | |
| 245 } | |
| 246 | |
| 247 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const { | |
| 248 return polling_thread_ ? polling_thread_->IsTimerRunning() : false; | |
| 249 } | |
| 250 | |
| 251 } // namespace content | |
| OLD | NEW |