Index: content/browser/device_orientation/device_motion_provider.cc |
diff --git a/content/browser/device_orientation/device_motion_provider.cc b/content/browser/device_orientation/device_motion_provider.cc |
index 84f65cabd1108b6da4bec2a79ff06275a13788a1..e88d5af83f4173e97fe97aaa3077ac828de702c9 100644 |
--- a/content/browser/device_orientation/device_motion_provider.cc |
+++ b/content/browser/device_orientation/device_motion_provider.cc |
@@ -4,14 +4,95 @@ |
#include "content/browser/device_orientation/device_motion_provider.h" |
+#include "base/bind.h" |
#include "base/logging.h" |
+#include "base/threading/thread.h" |
+#include "base/timer/timer.h" |
#include "content/browser/device_orientation/data_fetcher_shared_memory.h" |
#include "content/common/device_motion_hardware_buffer.h" |
namespace content { |
+namespace { |
+const int kPeriodInMilliseconds = 100; |
+} |
+ |
+class DeviceMotionProvider::PollingThread : public base::Thread { |
+ public: |
+ explicit PollingThread(const char* name); |
+ virtual ~PollingThread(); |
+ |
+ void StartPolling(DataFetcherSharedMemory* fetcher, |
+ DeviceMotionHardwareBuffer* buffer); |
+ void StopPolling(); |
+ |
+ private: |
+ void DoPoll(); |
+ |
+ scoped_ptr<base::RepeatingTimer<PollingThread> > timer_; |
+ DataFetcherSharedMemory* fetcher_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PollingThread); |
+}; |
+ |
+// ---- PollingThread methods |
+ |
+DeviceMotionProvider::PollingThread::PollingThread(const char* name) |
+ : base::Thread(name) { |
+} |
+ |
+DeviceMotionProvider::PollingThread::~PollingThread() { |
+} |
+ |
+void DeviceMotionProvider::PollingThread::StartPolling( |
+ DataFetcherSharedMemory* fetcher, DeviceMotionHardwareBuffer* buffer) { |
+ DCHECK(base::MessageLoop::current() == message_loop()); |
+ DCHECK(!timer_); |
+ |
+ fetcher_ = fetcher; |
+ fetcher_->StartFetchingDeviceMotionData(buffer); |
+ timer_.reset(new base::RepeatingTimer<PollingThread>()); |
+ timer_->Start(FROM_HERE, |
+ base::TimeDelta::FromMilliseconds(kPeriodInMilliseconds), |
+ this, &PollingThread::DoPoll); |
+} |
+ |
+void DeviceMotionProvider::PollingThread::StopPolling() { |
+ DCHECK(base::MessageLoop::current() == message_loop()); |
+ DCHECK(fetcher_); |
+ // this will also stop the timer before killing it. |
+ timer_.reset(); |
+ fetcher_->StopFetchingDeviceMotionData(); |
+} |
+ |
+void DeviceMotionProvider::PollingThread::DoPoll() { |
+ DCHECK(base::MessageLoop::current() == message_loop()); |
+ fetcher_->FetchDeviceMotionDataIntoBuffer(); |
+} |
+ |
+// ---- end PollingThread methods |
+ |
DeviceMotionProvider::DeviceMotionProvider() |
: is_started_(false) { |
+ Initialize(); |
+} |
+ |
+DeviceMotionProvider::DeviceMotionProvider( |
+ scoped_ptr<DataFetcherSharedMemory> fetcher) |
+ : is_started_(false) { |
+ data_fetcher_ = fetcher.Pass(); |
+ Initialize(); |
+} |
+ |
+DeviceMotionProvider::~DeviceMotionProvider() { |
+ StopFetchingDeviceMotionData(); |
+ // make sure polling thread stops before data_fetcher_ gets deleted. |
+ if (polling_thread_) |
+ polling_thread_->Stop(); |
+ data_fetcher_.reset(); |
+} |
+ |
+void DeviceMotionProvider::Initialize() { |
size_t data_size = sizeof(DeviceMotionHardwareBuffer); |
bool res = device_motion_shared_memory_.CreateAndMapAnonymous(data_size); |
// TODO(timvolodine): consider not crashing the browser if the check fails. |
@@ -20,9 +101,6 @@ DeviceMotionProvider::DeviceMotionProvider() |
memset(hwbuf, 0, sizeof(DeviceMotionHardwareBuffer)); |
} |
-DeviceMotionProvider::~DeviceMotionProvider() { |
-} |
- |
base::SharedMemoryHandle DeviceMotionProvider::GetSharedMemoryHandleForProcess( |
base::ProcessHandle process) { |
base::SharedMemoryHandle renderer_handle; |
@@ -33,20 +111,59 @@ base::SharedMemoryHandle DeviceMotionProvider::GetSharedMemoryHandleForProcess( |
void DeviceMotionProvider::StartFetchingDeviceMotionData() { |
if (is_started_) |
return; |
+ |
if (!data_fetcher_) |
data_fetcher_.reset(new DataFetcherSharedMemory); |
- data_fetcher_->StartFetchingDeviceMotionData(SharedMemoryAsHardwareBuffer()); |
+ |
+ if (data_fetcher_->NeedsPolling()) { |
+ if (!polling_thread_) |
+ CreateAndStartPollingThread(); |
+ |
+ polling_thread_->message_loop()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&PollingThread::StartPolling, |
+ base::Unretained(polling_thread_.get()), |
+ data_fetcher_.get(), |
+ SharedMemoryAsHardwareBuffer())); |
+ } else { |
+ data_fetcher_->StartFetchingDeviceMotionData( |
+ SharedMemoryAsHardwareBuffer()); |
+ } |
+ |
is_started_ = true; |
} |
+void DeviceMotionProvider::CreateAndStartPollingThread() { |
+ polling_thread_.reset( |
+ new PollingThread("Device Motion poller")); |
+ |
+ if (!polling_thread_->Start()) { |
+ LOG(ERROR) << "Failed to start Device Motion data polling thread"; |
+ return; |
+ } |
+} |
+ |
void DeviceMotionProvider::StopFetchingDeviceMotionData() { |
- if (data_fetcher_) |
+ if (!is_started_) |
+ return; |
+ |
+ DCHECK(data_fetcher_); |
+ |
+ if (data_fetcher_->NeedsPolling()) { |
+ DCHECK(polling_thread_); |
+ polling_thread_->message_loop()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&PollingThread::StopPolling, |
+ base::Unretained(polling_thread_.get()))); |
+ } else { |
data_fetcher_->StopFetchingDeviceMotionData(); |
+ } |
+ |
is_started_ = false; |
} |
-DeviceMotionHardwareBuffer* DeviceMotionProvider:: |
- SharedMemoryAsHardwareBuffer() { |
+DeviceMotionHardwareBuffer* |
+DeviceMotionProvider::SharedMemoryAsHardwareBuffer() { |
void* mem = device_motion_shared_memory_.memory(); |
CHECK(mem); |
return static_cast<DeviceMotionHardwareBuffer*>(mem); |