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 "athena/screen/public/screen_manager.h" | |
6 #include "athena/system/orientation_controller.h" | |
7 #include "base/bind.h" | |
8 #include "base/file_util.h" | |
9 #include "base/files/file_path_watcher.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/task_runner.h" | |
12 | |
13 namespace athena { | |
14 | |
15 namespace { | |
16 | |
17 // Path of the socket which the sensor daemon creates. | |
18 const char kSocketPath[] = "/dev/sensors/orientation"; | |
19 | |
20 // Threshold after which to rotate in a given direction. | |
21 const int kGravityThreshold = 6.0f; | |
22 | |
23 // Minimum delay before triggering another orientation change. | |
24 const int kOrientationChangeDelayNS = 500000000; | |
25 | |
26 enum { | |
27 SENSOR_ACCELEROMETER, | |
28 SENSOR_LIGHT, | |
29 SENSOR_PROXIMITY | |
30 }; | |
31 | |
32 // A sensor event from the device. | |
33 struct DeviceSensorEvent { | |
34 // The type of event from the enum above. | |
35 int32_t type; | |
36 | |
37 // The time in nanoseconds at which the event happened. | |
38 int64_t timestamp; | |
39 | |
40 union { | |
41 // Accelerometer X,Y,Z values in SI units (m/s^2) including gravity. | |
42 // The orientation is described at | |
43 // http://www.html5rocks.com/en/tutorials/device/orientation/. | |
44 float data[3]; | |
45 | |
46 // Ambient (room) temperature in degrees Celcius. | |
47 float temperature; | |
48 | |
49 // Proximity sensor distance in centimeters. | |
50 float distance; | |
51 | |
52 // Ambient light level in SI lux units. | |
53 float light; | |
54 }; | |
55 }; | |
56 | |
57 } // namespace | |
58 | |
59 OrientationController::OrientationController() | |
60 : DeviceSocketListener(kSocketPath, sizeof(DeviceSensorEvent)), | |
61 last_orientation_change_time_(0), | |
62 weak_factory_(this) { | |
63 CHECK(base::MessageLoop::current()); | |
oshima
2014/08/11 21:30:17
base::MessageLoopForUI::current() ?
flackr
2014/08/13 15:52:36
Done.
| |
64 ui_task_runner_ = base::MessageLoop::current()->task_runner(); | |
65 base::FilePath socket_path(kSocketPath); | |
66 if (base::PathExists(socket_path)) { | |
67 StartListening(); | |
68 } else { | |
69 // Watch for socket to be created if it doesn't already exist. | |
70 watcher_.reset(new base::FilePathWatcher); | |
71 watcher_->Watch(socket_path, false, | |
72 base::Bind(&OrientationController::OnFilePathChanged, | |
73 weak_factory_.GetWeakPtr())); | |
oshima
2014/08/11 21:30:17
Looks like FilePathWacher::Watch has to be called
flackr
2014/08/13 15:52:36
Done.
| |
74 } | |
75 } | |
76 | |
77 OrientationController::~OrientationController() { | |
78 } | |
79 | |
80 void OrientationController::OnDataAvailableOnIO(const void* data) { | |
81 const DeviceSensorEvent* event = | |
82 static_cast<const DeviceSensorEvent*>(data); | |
83 if (event->type != SENSOR_ACCELEROMETER) | |
84 return; | |
85 | |
86 float gravity_x = event->data[0]; | |
87 float gravity_y = event->data[1]; | |
88 gfx::Display::Rotation rotation; | |
89 if (gravity_x < -kGravityThreshold) { | |
90 rotation = gfx::Display::ROTATE_270; | |
91 } else if (gravity_x > kGravityThreshold) { | |
92 rotation = gfx::Display::ROTATE_90; | |
93 } else if (gravity_y < -kGravityThreshold) { | |
94 rotation = gfx::Display::ROTATE_180; | |
95 } else if (gravity_y > kGravityThreshold) { | |
96 rotation = gfx::Display::ROTATE_0; | |
97 } else { | |
98 // No rotation as gravity threshold was not hit. | |
99 return; | |
100 } | |
101 | |
102 if (rotation == current_rotation_ || | |
103 event->timestamp - last_orientation_change_time_ < | |
104 kOrientationChangeDelayNS) { | |
105 return; | |
106 } | |
107 | |
108 last_orientation_change_time_ = event->timestamp; | |
109 current_rotation_ = rotation; | |
110 | |
111 // TODO(flackr): Avoid callbacks using unretained pointers. This could | |
112 // technically call RotateOnUI after OrientationController has destructed. We | |
113 // should instead use callbacks with weak pointers similar to | |
114 // chromeos/accelerometer/accelerometer_reader.cc. | |
115 ui_task_runner_->PostTask(FROM_HERE, | |
116 base::Bind(&OrientationController::RotateOnUI, | |
117 base::Unretained(this), rotation)); | |
118 } | |
119 | |
120 void OrientationController::RotateOnUI(gfx::Display::Rotation rotation) { | |
121 ScreenManager::Get()->SetRotation(rotation); | |
122 } | |
123 | |
124 void OrientationController::OnFilePathChanged(const base::FilePath& path, | |
125 bool error) { | |
126 if (error) | |
127 return; | |
128 | |
129 StartListening(); | |
130 watcher_.reset(); | |
131 } | |
132 | |
133 } // namespace athena | |
OLD | NEW |