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

Side by Side 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, 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "base/file_util.h"
6 #include "base/logging.h"
7 #include "base/memory/singleton.h"
8 #include "base/string_util.h"
9 #include "base/stringprintf.h"
10 #include "content/browser/sensors/provider_impl.h"
11
12 #include <vector>
13
14 #include <fcntl.h>
15 #include <unistd.h>
16
17 // TODO: The thread safety varies from tolerable (normal operation) to
18 // non-existent (delete). Need to fix that.
19
20 namespace sensors {
21
22 class ConnectionImpl : public Connection {
23 public:
24 ConnectionImpl(ProviderImpl* provider, Listener* listener)
25 : provider_(provider), listener_(listener),
26 listener_proxy_(base::MessageLoopProxy::CreateForCurrentThread()) {
27 }
28
29 virtual void Start(Channel channel, const std::string& data) {
30 provider_->ConnectionStarted(this, channel, data);
31 }
32
33 virtual void Stop(Channel channel) {
34 provider_->ConnectionStopped(this, channel);
35 }
36
37 virtual void Close() {
38 provider_->ConnectionClosed(this);
39 listener_ = NULL;
40 }
41
42 virtual void FireSensorChanged(Channel channel, const std::string& data) {
43 if (!listener_proxy_->BelongsToCurrentThread()) {
44 listener_proxy_->PostTask(FROM_HERE, NewRunnableMethod(
45 this, &ConnectionImpl::FireSensorChanged, channel, data));
46 return;
47 }
48
49 if (listener_)
50 listener_->SensorChanged(channel, data);
51 }
52
53 private:
54 ProviderImpl* provider_;
55 Listener* listener_;
56 scoped_refptr<base::MessageLoopProxy> listener_proxy_;
57 };
58
59 ProviderImpl* ProviderImpl::GetInstance() {
60 return Singleton<ProviderImpl>::get();
61 }
62
63 ProviderImpl::ProviderImpl()
64 : device_fd_(-1),
65 device_buf_end_(0) {
66 base::Thread* thread = new base::Thread("sensor provider");
67 thread->Start();
68
69 device_proxy_ = thread->message_loop_proxy();
70
71 device_proxy_->PostTask(FROM_HERE,
72 NewRunnableMethod(this, &ProviderImpl::DeviceStart));
73 }
74
75 ProviderImpl::~ProviderImpl() {
76 DCHECK(device_fd_ == -1);
77 }
78
79 Connection* ProviderImpl::Open(Listener* listener) {
80 ConnectionImpl* conn = new ConnectionImpl(this, listener);
81 connections_.AddObserver(conn);
82 return conn;
83 }
84
85 void ProviderImpl::FireSensorChanged(Channel channel, const std::string& data) {
86 FOR_EACH_OBSERVER(ConnectionImpl, connections_, FireSensorChanged(channel, dat a));
87 }
88
89 void ProviderImpl::DeviceStart() {
90 DCHECK(device_proxy_->BelongsToCurrentThread());
91
92 static const char* kDeviceEventPath = "/dev/device0:event0";
93 static const char* kEnableEventPath =
94 "/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
95
96 int ret;
97
98 int fd = open(kDeviceEventPath, O_RDONLY, 0);
99 if (fd < 0) {
100 LOG(ERROR) << "Failed to open accelerometer: " << strerror(errno);
101 LOG(ERROR) << "Orientation will be unavailable until Chrome is restarted.";
102 return;
103 }
104
105 ret = file_util::WriteFile(FilePath(kEnableEventPath), "1\n", 2);
106 if (ret < 0) {
107 LOG(ERROR) << "Failed to enable accelerometer: " << strerror(errno);
108 LOG(ERROR) << "Orientation will be unavailable until Chrome is restarted.";
109 return;
110 }
111
112 device_fd_ = fd;
113 device_proxy_->PostDelayedTask(FROM_HERE,
114 NewRunnableMethod(this, &ProviderImpl::DeviceRead), 1000);
115 }
116
117 struct iio_event {
118 uint32 code;
119 uint32 unused;
120 uint64 time;
121 };
122
123 void ProviderImpl::DeviceRead() {
124 DCHECK(device_proxy_->BelongsToCurrentThread());
125
126 if (!DoDeviceRead()) {
127 LOG(ERROR) << "Orientation will be unavailable until Chrome is restarted.";
128 return;
129 }
130
131 device_proxy_->PostTask(FROM_HERE,
132 NewRunnableMethod(this, &ProviderImpl::DeviceRead));
133 }
134
135 bool ProviderImpl::DoDeviceRead() {
136 DCHECK(device_proxy_->BelongsToCurrentThread());
137 DCHECK(device_fd_ != -1);
138
139 ssize_t rv = read(device_fd_, device_buf_ + device_buf_end_,
140 sizeof(device_buf_) - device_buf_end_);
141 if (rv < 0) {
142 if (errno == EAGAIN || errno == EWOULDBLOCK)
143 return true; // Do not have any data to read
144
145 LOG(ERROR) << "Failed to read accelerometer events: " << strerror(errno);
146 return false;
147 }
148 device_buf_end_ += rv;
149
150 if (device_buf_end_ < kIIOMessageSize)
151 return true; // Do not have a complete message yet
152
153 device_buf_end_ = 0;
154
155 struct iio_event* event = reinterpret_cast<struct iio_event*>(device_buf_);
156
157 // HACK: These orientations are rearranged from their definitions in the
158 // accelerometer driver so that the development devices report their
159 // orientation correctly. This will eventually be configured in the
160 // sensor manager, and the data received by Chrome will be correct.
161 ScreenOrientationChange change;
162 switch (event->code >> 8) {
163 case 0: change.upward = ScreenOrientationChange::TOP; break;
164 case 1: change.upward = ScreenOrientationChange::BOTTOM; break;
165 case 2: change.upward = ScreenOrientationChange::RIGHT; break;
166 case 3: change.upward = ScreenOrientationChange::LEFT; break;
167 case 4: change.upward = ScreenOrientationChange::FRONT; break;
168 case 5: change.upward = ScreenOrientationChange::BACK; break;
169 default: return true; // drop unknown orientation
170 }
171
172 std::string data(reinterpret_cast<const char*>(&change), sizeof(change));
173 FireSensorChanged(kScreenOrientationChannel, data);
174 return true;
175 }
176
177 void ProviderImpl::DeviceStop() {
178 DCHECK(device_proxy_->BelongsToCurrentThread());
179
180 close(device_fd_);
181 device_fd_ = -1;
182 }
183
184 void ProviderImpl::ConnectionClosed(ConnectionImpl* conn) {
185 connections_.RemoveObserver(conn);
186 }
187
188 void ProviderImpl::ConnectionStarted(ConnectionImpl* conn,
189 Channel channel, const std::string& data) {
190
191 connections_.AddObserver(conn);
192 }
193
194 void ProviderImpl::ConnectionStopped(ConnectionImpl* conn, Channel channel) {
195 connections_.RemoveObserver(conn);
196 }
197
198 } // namespace sensors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698