Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1774)

Unified Diff: content/browser/sensors/provider_impl.cc

Issue 7273073: Animated Rotation (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/sensors/provider_impl.cc
diff --git a/content/browser/sensors/provider_impl.cc b/content/browser/sensors/provider_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2777fb5e1802aae38dbae93358eac1e9305f1aa0
--- /dev/null
+++ b/content/browser/sensors/provider_impl.cc
@@ -0,0 +1,198 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "content/browser/sensors/provider_impl.h"
+
+#include <vector>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+// TODO: The thread safety varies from tolerable (normal operation) to
+// non-existent (delete). Need to fix that.
+
+namespace sensors {
+
+class ConnectionImpl : public Connection {
+ public:
+ ConnectionImpl(ProviderImpl* provider, Listener* listener)
+ : provider_(provider), listener_(listener),
+ listener_proxy_(base::MessageLoopProxy::CreateForCurrentThread()) {
+ }
+
+ virtual void Start(Channel channel, const std::string& data) {
+ provider_->ConnectionStarted(this, channel, data);
+ }
+
+ virtual void Stop(Channel channel) {
+ provider_->ConnectionStopped(this, channel);
+ }
+
+ virtual void Close() {
+ provider_->ConnectionClosed(this);
+ listener_ = NULL;
+ }
+
+ virtual void FireSensorChanged(Channel channel, const std::string& data) {
+ if (!listener_proxy_->BelongsToCurrentThread()) {
+ listener_proxy_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &ConnectionImpl::FireSensorChanged, channel, data));
+ return;
+ }
+
+ if (listener_)
+ listener_->SensorChanged(channel, data);
+ }
+
+ private:
+ ProviderImpl* provider_;
+ Listener* listener_;
+ scoped_refptr<base::MessageLoopProxy> listener_proxy_;
+};
+
+ProviderImpl* ProviderImpl::GetInstance() {
+ return Singleton<ProviderImpl>::get();
+}
+
+ProviderImpl::ProviderImpl()
+ : device_fd_(-1),
+ device_buf_end_(0) {
+ base::Thread* thread = new base::Thread("sensor provider");
+ thread->Start();
+
+ device_proxy_ = thread->message_loop_proxy();
+
+ device_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ProviderImpl::DeviceStart));
+}
+
+ProviderImpl::~ProviderImpl() {
+ DCHECK(device_fd_ == -1);
+}
+
+Connection* ProviderImpl::Open(Listener* listener) {
+ ConnectionImpl* conn = new ConnectionImpl(this, listener);
+ connections_.AddObserver(conn);
+ return conn;
+}
+
+void ProviderImpl::FireSensorChanged(Channel channel, const std::string& data) {
+ FOR_EACH_OBSERVER(ConnectionImpl, connections_, FireSensorChanged(channel, data));
+}
+
+void ProviderImpl::DeviceStart() {
+ DCHECK(device_proxy_->BelongsToCurrentThread());
+
+ static const char* kDeviceEventPath = "/dev/device0:event0";
+ static const char* kEnableEventPath =
+ "/sys/bus/iio/devices/device0:event0/tilt_change_en";
Jói 2011/06/30 19:50:50 This seems device-dependent, or at least POSIX-spe
+
+ int ret;
+
+ int fd = open(kDeviceEventPath, O_RDONLY, 0);
+ if (fd < 0) {
+ LOG(ERROR) << "Failed to open accelerometer: " << strerror(errno);
+ LOG(ERROR) << "Orientation will be unavailable until Chrome is restarted.";
+ return;
+ }
+
+ ret = file_util::WriteFile(FilePath(kEnableEventPath), "1\n", 2);
+ if (ret < 0) {
+ LOG(ERROR) << "Failed to enable accelerometer: " << strerror(errno);
+ LOG(ERROR) << "Orientation will be unavailable until Chrome is restarted.";
+ return;
+ }
+
+ device_fd_ = fd;
+ device_proxy_->PostDelayedTask(FROM_HERE,
+ NewRunnableMethod(this, &ProviderImpl::DeviceRead), 1000);
+}
+
+struct iio_event {
+ uint32 code;
+ uint32 unused;
+ uint64 time;
+};
+
+void ProviderImpl::DeviceRead() {
+ DCHECK(device_proxy_->BelongsToCurrentThread());
+
+ if (!DoDeviceRead()) {
+ LOG(ERROR) << "Orientation will be unavailable until Chrome is restarted.";
+ return;
+ }
+
+ device_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ProviderImpl::DeviceRead));
+}
+
+bool ProviderImpl::DoDeviceRead() {
+ DCHECK(device_proxy_->BelongsToCurrentThread());
+ DCHECK(device_fd_ != -1);
+
+ ssize_t rv = read(device_fd_, device_buf_ + device_buf_end_,
+ sizeof(device_buf_) - device_buf_end_);
+ if (rv < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return true; // Do not have any data to read
+
+ LOG(ERROR) << "Failed to read accelerometer events: " << strerror(errno);
+ return false;
+ }
+ device_buf_end_ += rv;
+
+ if (device_buf_end_ < kIIOMessageSize)
+ return true; // Do not have a complete message yet
+
+ device_buf_end_ = 0;
+
+ struct iio_event* event = reinterpret_cast<struct iio_event*>(device_buf_);
+
+ // HACK: These orientations are rearranged from their definitions in the
+ // accelerometer driver so that the development devices report their
+ // orientation correctly. This will eventually be configured in the
+ // sensor manager, and the data received by Chrome will be correct.
+ ScreenOrientationChange change;
+ switch (event->code >> 8) {
+ case 0: change.upward = ScreenOrientationChange::TOP; break;
+ case 1: change.upward = ScreenOrientationChange::BOTTOM; break;
+ case 2: change.upward = ScreenOrientationChange::RIGHT; break;
+ case 3: change.upward = ScreenOrientationChange::LEFT; break;
+ case 4: change.upward = ScreenOrientationChange::FRONT; break;
+ case 5: change.upward = ScreenOrientationChange::BACK; break;
+ default: return true; // drop unknown orientation
+ }
+
+ std::string data(reinterpret_cast<const char*>(&change), sizeof(change));
+ FireSensorChanged(kScreenOrientationChannel, data);
+ return true;
+}
+
+void ProviderImpl::DeviceStop() {
+ DCHECK(device_proxy_->BelongsToCurrentThread());
+
+ close(device_fd_);
+ device_fd_ = -1;
+}
+
+void ProviderImpl::ConnectionClosed(ConnectionImpl* conn) {
+ connections_.RemoveObserver(conn);
+}
+
+void ProviderImpl::ConnectionStarted(ConnectionImpl* conn,
+ Channel channel, const std::string& data) {
+
+ connections_.AddObserver(conn);
+}
+
+void ProviderImpl::ConnectionStopped(ConnectionImpl* conn, Channel channel) {
+ connections_.RemoveObserver(conn);
+}
+
+} // namespace sensors

Powered by Google App Engine
This is Rietveld 408576698