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 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