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

Unified Diff: athena/system/orientation_controller.cc

Issue 431183003: Rotate screen in response to accelerator or device orientation sensors. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add dependencies on ipc and content. Created 6 years, 4 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: athena/system/orientation_controller.cc
diff --git a/athena/system/orientation_controller.cc b/athena/system/orientation_controller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..671215bf8b9ecb4155950794c73ccc3866807727
--- /dev/null
+++ b/athena/system/orientation_controller.cc
@@ -0,0 +1,143 @@
+// Copyright 2014 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 "athena/screen/public/screen_manager.h"
+#include "athena/system/orientation_controller.h"
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/file_path_watcher.h"
+#include "base/message_loop/message_loop.h"
+#include "base/task_runner.h"
+
+namespace athena {
+
+namespace {
+
+// Path of the socket which the sensor daemon creates.
+const char kSocketPath[] = "/dev/sensors/orientation";
+
+// Threshold after which to rotate in a given direction.
+const int kGravityThreshold = 6.0f;
+
+// Minimum delay before triggering another orientation change.
+const int kOrientationChangeDelayNS = 500000000;
+
+enum SensorType {
+ SENSOR_ACCELEROMETER,
+ SENSOR_LIGHT,
+ SENSOR_PROXIMITY
+};
+
+// A sensor event from the device.
+struct DeviceSensorEvent {
+ // The type of event from the SensorType enum above.
+ int32_t type;
+
+ // The time in nanoseconds at which the event happened.
+ int64_t timestamp;
+
+ union {
+ // Accelerometer X,Y,Z values in SI units (m/s^2) including gravity.
+ // The orientation is described at
+ // http://www.html5rocks.com/en/tutorials/device/orientation/.
+ float data[3];
+
+ // Ambient (room) temperature in degrees Celcius.
+ float temperature;
+
+ // Proximity sensor distance in centimeters.
+ float distance;
+
+ // Ambient light level in SI lux units.
+ float light;
+ };
+};
+
+} // namespace
+
+OrientationController::OrientationController(
+ scoped_refptr<base::TaskRunner> io_task_runner)
+ : DeviceSocketListener(kSocketPath, sizeof(DeviceSensorEvent)),
+ last_orientation_change_time_(0),
+ weak_factory_(this) {
+ CHECK(base::MessageLoopForUI::current());
+ ui_task_runner_ = base::MessageLoopForUI::current()->task_runner();
+ io_task_runner->PostTask(FROM_HERE, base::Bind(
+ &OrientationController::WatchForSocketPathOnIO,
+ make_scoped_refptr<OrientationController>(this)));
+}
+
+OrientationController::~OrientationController() {
+}
+
+void OrientationController::WatchForSocketPathOnIO() {
+ CHECK(base::MessageLoopForIO::current());
+ if (base::PathExists(base::FilePath(kSocketPath))) {
+ ui_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&OrientationController::StartListening,
+ make_scoped_refptr<OrientationController>(this)));
+ } else {
+ watcher_.reset(new base::FilePathWatcher);
+ watcher_->Watch(
+ base::FilePath(kSocketPath), false,
+ base::Bind(&OrientationController::OnFilePathChangedOnIO,
+ make_scoped_refptr<OrientationController>(this)));
+ }
+}
+
+void OrientationController::OnFilePathChangedOnIO(const base::FilePath& path,
+ bool error) {
+ watcher_.reset();
+ if (error)
+ return;
+
+ ui_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&OrientationController::StartListening,
+ make_scoped_refptr<OrientationController>(this)));
+}
+
+void OrientationController::OnDataAvailableOnIO(const void* data) {
+ const DeviceSensorEvent* event =
+ static_cast<const DeviceSensorEvent*>(data);
+ if (event->type != SENSOR_ACCELEROMETER)
+ return;
+
+ float gravity_x = event->data[0];
+ float gravity_y = event->data[1];
+ gfx::Display::Rotation rotation;
+ if (gravity_x < -kGravityThreshold) {
+ rotation = gfx::Display::ROTATE_270;
+ } else if (gravity_x > kGravityThreshold) {
+ rotation = gfx::Display::ROTATE_90;
+ } else if (gravity_y < -kGravityThreshold) {
+ rotation = gfx::Display::ROTATE_180;
+ } else if (gravity_y > kGravityThreshold) {
+ rotation = gfx::Display::ROTATE_0;
+ } else {
+ // No rotation as gravity threshold was not hit.
+ return;
+ }
+
+ if (rotation == current_rotation_ ||
+ event->timestamp - last_orientation_change_time_ <
+ kOrientationChangeDelayNS) {
+ return;
+ }
+
+ last_orientation_change_time_ = event->timestamp;
+ current_rotation_ = rotation;
+ ui_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&OrientationController::RotateOnUI,
+ make_scoped_refptr<OrientationController>(this), rotation));
+}
+
+void OrientationController::RotateOnUI(gfx::Display::Rotation rotation) {
+ ScreenManager* screen_manager = ScreenManager::Get();
+ // Since this is called from the IO thread, the screen manager may no longer
+ // exist.
+ if (screen_manager)
+ screen_manager->SetRotation(rotation);
+}
+
+} // namespace athena

Powered by Google App Engine
This is Rietveld 408576698