• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) Texas Instruments - http://www.ti.com/
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 "CameraHAL"
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 
sensor_events_listener(int fd,int events,void * data)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 ******/
SensorListener()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 
~SensorListener()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 
initialize()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 
setCallbacks(orientation_callback_t orientation_cb,void * cookie)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 
handleOrientation(uint32_t orientation,uint32_t tilt)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 
enableSensor(sensor_type_t type)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 
disableSensor(sensor_type_t type)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