blob: adcb7b81754a907242c658f48cd1d238bb90c9d3
1 | /* |
2 | * Copyright (C) 2011 The Android Open Source Project |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | /** |
18 | * @file SensorListener.cpp |
19 | * |
20 | * This file listens and propogates sensor events to CameraHal. |
21 | * |
22 | */ |
23 | |
24 | #define LOG_TAG "CameraHALSensorLstenner" |
25 | |
26 | #include "SensorListener.h" |
27 | #include "CameraHal.h" |
28 | |
29 | #include <stdint.h> |
30 | #include <math.h> |
31 | #include <sys/types.h> |
32 | |
33 | namespace android { |
34 | |
35 | /*** static declarations ***/ |
36 | static const float RADIANS_2_DEG = (float) (180 / M_PI); |
37 | // measured values on device...might need tuning |
38 | static const int DEGREES_90_THRESH = 50; |
39 | static const int DEGREES_180_THRESH = 170; |
40 | static const int DEGREES_270_THRESH = 250; |
41 | |
42 | static int sensor_events_listener(int fd, int events, void* data) |
43 | { |
44 | SensorListener* listener = (SensorListener*) data; |
45 | ssize_t num_sensors; |
46 | ASensorEvent sen_events[8]; |
47 | while ((num_sensors = listener->mSensorEventQueue->read(sen_events, 8)) > 0) { |
48 | for (int i = 0; i < num_sensors; i++) { |
49 | if (sen_events[i].type == Sensor::TYPE_ACCELEROMETER) { |
50 | float x = sen_events[i].vector.azimuth; |
51 | float y = sen_events[i].vector.pitch; |
52 | float z = sen_events[i].vector.roll; |
53 | float radius = 0; |
54 | int tilt = 0, orient = 0; |
55 | |
56 | /*CAMHAL_LOGVA("ACCELEROMETER EVENT"); |
57 | CAMHAL_LOGVB(" azimuth = %f pitch = %f roll = %f", |
58 | sen_events[i].vector.azimuth, |
59 | sen_events[i].vector.pitch, |
60 | sen_events[i].vector.roll);*/ |
61 | // see http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates |
62 | // about conversion from cartesian to spherical for orientation calculations |
63 | radius = (float) sqrt(x * x + y * y + z * z); |
64 | tilt = (int) asinf(z / radius) * RADIANS_2_DEG; |
65 | orient = (int) atan2f(-x, y) * RADIANS_2_DEG; |
66 | |
67 | if (orient < 0) { |
68 | orient += 360; |
69 | } |
70 | |
71 | if (orient >= DEGREES_270_THRESH) { |
72 | orient = 270; |
73 | } else if (orient >= DEGREES_180_THRESH) { |
74 | orient = 180; |
75 | } else if (orient >= DEGREES_90_THRESH) { |
76 | orient = 90; |
77 | } else { |
78 | orient = 0; |
79 | } |
80 | listener->handleOrientation(orient, tilt); |
81 | //CAMHAL_LOGVB(" tilt = %d orientation = %d", tilt, orient); |
82 | } else if (sen_events[i].type == Sensor::TYPE_GYROSCOPE) { |
83 | CAMHAL_LOGVA("GYROSCOPE EVENT"); |
84 | } |
85 | } |
86 | } |
87 | |
88 | if (num_sensors < 0 && num_sensors != -EAGAIN) { |
89 | CAMHAL_LOGEB("reading events failed: %s", strerror(-num_sensors)); |
90 | } |
91 | |
92 | return 1; |
93 | } |
94 | |
95 | /****** public - member functions ******/ |
96 | SensorListener::SensorListener() { |
97 | LOG_FUNCTION_NAME; |
98 | |
99 | sensorsEnabled = 0; |
100 | mOrientationCb = NULL; |
101 | mSensorEventQueue = NULL; |
102 | mSensorLooperThread = NULL; |
103 | |
104 | LOG_FUNCTION_NAME_EXIT; |
105 | } |
106 | |
107 | SensorListener::~SensorListener() { |
108 | LOG_FUNCTION_NAME; |
109 | |
110 | CAMHAL_LOGDA("Kill looper thread"); |
111 | if (mSensorLooperThread.get()) { |
112 | // 1. Request exit |
113 | // 2. Wake up looper which should be polling for an event |
114 | // 3. Wait for exit |
115 | mSensorLooperThread->requestExit(); |
116 | mSensorLooperThread->wake(); |
117 | mSensorLooperThread->join(); |
118 | mSensorLooperThread.clear(); |
119 | mSensorLooperThread = NULL; |
120 | } |
121 | |
122 | CAMHAL_LOGDA("Kill looper"); |
123 | if (mLooper.get()) { |
124 | mLooper->removeFd(mSensorEventQueue->getFd()); |
125 | mLooper.clear(); |
126 | mLooper = NULL; |
127 | } |
128 | CAMHAL_LOGDA("SensorListener destroyed"); |
129 | |
130 | LOG_FUNCTION_NAME_EXIT; |
131 | } |
132 | |
133 | status_t SensorListener::initialize() { |
134 | status_t ret = NO_ERROR; |
135 | SensorManager& mgr(SensorManager::getInstance()); |
136 | |
137 | LOG_FUNCTION_NAME; |
138 | |
139 | sp<Looper> mLooper; |
140 | |
141 | mSensorEventQueue = mgr.createEventQueue(); |
142 | if (mSensorEventQueue == NULL) { |
143 | CAMHAL_LOGEA("createEventQueue returned NULL"); |
144 | ret = NO_INIT; |
145 | goto out; |
146 | } |
147 | |
148 | mLooper = new Looper(false); |
149 | mLooper->addFd(mSensorEventQueue->getFd(), 0, ALOOPER_EVENT_INPUT, sensor_events_listener, this); |
150 | |
151 | if (mSensorLooperThread.get() == NULL) |
152 | mSensorLooperThread = new SensorLooperThread(mLooper.get()); |
153 | |
154 | if (mSensorLooperThread.get() == NULL) { |
155 | CAMHAL_LOGEA("Couldn't create sensor looper thread"); |
156 | ret = NO_MEMORY; |
157 | goto out; |
158 | } |
159 | |
160 | ret = mSensorLooperThread->run("sensor looper thread", PRIORITY_URGENT_DISPLAY); |
161 | if (ret == INVALID_OPERATION){ |
162 | CAMHAL_LOGDA("thread already running ?!?"); |
163 | } else if (ret != NO_ERROR) { |
164 | CAMHAL_LOGEA("couldn't run thread"); |
165 | goto out; |
166 | } |
167 | |
168 | out: |
169 | LOG_FUNCTION_NAME_EXIT; |
170 | return ret; |
171 | } |
172 | |
173 | void SensorListener::setCallbacks(orientation_callback_t orientation_cb, void *cookie) { |
174 | LOG_FUNCTION_NAME; |
175 | |
176 | if (orientation_cb) { |
177 | mOrientationCb = orientation_cb; |
178 | } |
179 | mCbCookie = cookie; |
180 | |
181 | LOG_FUNCTION_NAME_EXIT; |
182 | } |
183 | |
184 | void SensorListener::handleOrientation(uint32_t orientation, uint32_t tilt) { |
185 | LOG_FUNCTION_NAME; |
186 | |
187 | Mutex::Autolock lock(&mLock); |
188 | |
189 | if (mOrientationCb && (sensorsEnabled & SENSOR_ORIENTATION)) { |
190 | mOrientationCb(orientation, tilt, mCbCookie); |
191 | } |
192 | |
193 | LOG_FUNCTION_NAME_EXIT; |
194 | } |
195 | |
196 | void SensorListener::enableSensor(sensor_type_t type) { |
197 | Sensor const* sensor; |
198 | SensorManager& mgr(SensorManager::getInstance()); |
199 | |
200 | LOG_FUNCTION_NAME; |
201 | |
202 | Mutex::Autolock lock(&mLock); |
203 | |
204 | if ((type & SENSOR_ORIENTATION) && !(sensorsEnabled & SENSOR_ORIENTATION)) { |
205 | sensor = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER); |
206 | CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string()); |
207 | mSensorEventQueue->enableSensor(sensor); |
208 | mSensorEventQueue->setEventRate(sensor, ms2ns(100)); |
209 | sensorsEnabled |= SENSOR_ORIENTATION; |
210 | } |
211 | |
212 | LOG_FUNCTION_NAME_EXIT; |
213 | } |
214 | |
215 | void SensorListener::disableSensor(sensor_type_t type) { |
216 | Sensor const* sensor; |
217 | SensorManager& mgr(SensorManager::getInstance()); |
218 | |
219 | LOG_FUNCTION_NAME; |
220 | |
221 | Mutex::Autolock lock(&mLock); |
222 | |
223 | if ((type & SENSOR_ORIENTATION) && (sensorsEnabled & SENSOR_ORIENTATION)) { |
224 | sensor = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER); |
225 | CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string()); |
226 | mSensorEventQueue->disableSensor(sensor); |
227 | sensorsEnabled &= ~SENSOR_ORIENTATION; |
228 | } |
229 | |
230 | LOG_FUNCTION_NAME_EXIT; |
231 | } |
232 | |
233 | } // namespace android |
234 |