Home | History | Annotate | Download | only in camera
      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 #include "SensorListener.h"
     25 
     26 #include <stdint.h>
     27 #include <math.h>
     28 #include <sys/types.h>
     29 
     30 namespace Ti {
     31 namespace Camera {
     32 
     33 /*** static declarations ***/
     34 static const float RADIANS_2_DEG = (float) (180 / M_PI);
     35 // measured values on device...might need tuning
     36 static const int DEGREES_90_THRESH = 50;
     37 static const int DEGREES_180_THRESH = 170;
     38 static const int DEGREES_270_THRESH = 250;
     39 
     40 static int sensor_events_listener(int fd, int events, void* data)
     41 {
     42     SensorListener* listener = (SensorListener*) data;
     43     ssize_t num_sensors;
     44     ASensorEvent sen_events[8];
     45     while ((num_sensors = listener->mSensorEventQueue->read(sen_events, 8)) > 0) {
     46         for (int i = 0; i < num_sensors; i++) {
     47             if (sen_events[i].type == android::Sensor::TYPE_ACCELEROMETER) {
     48                 float x = sen_events[i].vector.azimuth;
     49                 float y = sen_events[i].vector.pitch;
     50                 float z = sen_events[i].vector.roll;
     51                 float radius = 0;
     52                 int tilt = 0, orient = 0;
     53 
     54                 CAMHAL_LOGVA("ACCELEROMETER EVENT");
     55                 CAMHAL_LOGVB(" azimuth = %f pitch = %f roll = %f",
     56                              sen_events[i].vector.azimuth,
     57                              sen_events[i].vector.pitch,
     58                              sen_events[i].vector.roll);
     59                 // see http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates
     60                 // about conversion from cartesian to spherical for orientation calculations
     61                 radius = (float) sqrt(x * x + y * y + z * z);
     62                 tilt = (int) asinf(z / radius) * RADIANS_2_DEG;
     63                 orient = (int) atan2f(-x, y) * RADIANS_2_DEG;
     64 
     65                 if (orient < 0) {
     66                     orient += 360;
     67                 }
     68 
     69                 if (orient >= DEGREES_270_THRESH) {
     70                     orient = 270;
     71                 } else if (orient >= DEGREES_180_THRESH) {
     72                     orient = 180;
     73                 } else if (orient >= DEGREES_90_THRESH) {
     74                     orient = 90;
     75                 } else {
     76                     orient = 0;
     77                 }
     78                 listener->handleOrientation(orient, tilt);
     79                 CAMHAL_LOGVB(" tilt = %d orientation = %d", tilt, orient);
     80             } else if (sen_events[i].type == android::Sensor::TYPE_GYROSCOPE) {
     81                 CAMHAL_LOGVA("GYROSCOPE EVENT");
     82             }
     83         }
     84     }
     85 
     86     if (num_sensors < 0 && num_sensors != -EAGAIN) {
     87         CAMHAL_LOGEB("reading events failed: %s", strerror(-num_sensors));
     88     }
     89 
     90     return 1;
     91 }
     92 
     93 /****** public - member functions ******/
     94 SensorListener::SensorListener() {
     95     LOG_FUNCTION_NAME;
     96 
     97     sensorsEnabled = 0;
     98     mOrientationCb = NULL;
     99     mSensorEventQueue = NULL;
    100     mSensorLooperThread = NULL;
    101 
    102     LOG_FUNCTION_NAME_EXIT;
    103 }
    104 
    105 SensorListener::~SensorListener() {
    106     LOG_FUNCTION_NAME;
    107 
    108     CAMHAL_LOGDA("Kill looper thread");
    109     if (mSensorLooperThread.get()) {
    110         // 1. Request exit
    111         // 2. Wake up looper which should be polling for an event
    112         // 3. Wait for exit
    113         mSensorLooperThread->requestExit();
    114         mSensorLooperThread->wake();
    115         mSensorLooperThread->join();
    116         mSensorLooperThread.clear();
    117         mSensorLooperThread = NULL;
    118     }
    119 
    120     CAMHAL_LOGDA("Kill looper");
    121     if (mLooper.get()) {
    122         mLooper->removeFd(mSensorEventQueue->getFd());
    123         mLooper.clear();
    124         mLooper = NULL;
    125     }
    126     CAMHAL_LOGDA("SensorListener destroyed");
    127 
    128     LOG_FUNCTION_NAME_EXIT;
    129 }
    130 
    131 status_t SensorListener::initialize() {
    132     status_t ret = NO_ERROR;
    133     android::SensorManager& mgr(android::SensorManager::getInstance());
    134 
    135     LOG_FUNCTION_NAME;
    136 
    137     android::sp<android::Looper> mLooper;
    138 
    139     mSensorEventQueue = mgr.createEventQueue();
    140     if (mSensorEventQueue == NULL) {
    141         CAMHAL_LOGEA("createEventQueue returned NULL");
    142         ret = NO_INIT;
    143         goto out;
    144     }
    145 
    146     mLooper = new android::Looper(false);
    147     mLooper->addFd(mSensorEventQueue->getFd(), 0, ALOOPER_EVENT_INPUT, sensor_events_listener, this);
    148 
    149     if (mSensorLooperThread.get() == NULL)
    150             mSensorLooperThread = new SensorLooperThread(mLooper.get());
    151 
    152     if (mSensorLooperThread.get() == NULL) {
    153         CAMHAL_LOGEA("Couldn't create sensor looper thread");
    154         ret = NO_MEMORY;
    155         goto out;
    156     }
    157 
    158     ret = mSensorLooperThread->run("sensor looper thread", android::PRIORITY_URGENT_DISPLAY);
    159     if (ret == INVALID_OPERATION){
    160         CAMHAL_LOGDA("thread already running ?!?");
    161     } else if (ret != NO_ERROR) {
    162         CAMHAL_LOGEA("couldn't run thread");
    163         goto out;
    164     }
    165 
    166  out:
    167     LOG_FUNCTION_NAME_EXIT;
    168     return ret;
    169 }
    170 
    171 void SensorListener::setCallbacks(orientation_callback_t orientation_cb, void *cookie) {
    172     LOG_FUNCTION_NAME;
    173 
    174     if (orientation_cb) {
    175         mOrientationCb = orientation_cb;
    176     }
    177     mCbCookie = cookie;
    178 
    179     LOG_FUNCTION_NAME_EXIT;
    180 }
    181 
    182 void SensorListener::handleOrientation(uint32_t orientation, uint32_t tilt) {
    183     LOG_FUNCTION_NAME;
    184 
    185     android::AutoMutex lock(&mLock);
    186 
    187     if (mOrientationCb && (sensorsEnabled & SENSOR_ORIENTATION)) {
    188         mOrientationCb(orientation, tilt, mCbCookie);
    189     }
    190 
    191     LOG_FUNCTION_NAME_EXIT;
    192 }
    193 
    194 void SensorListener::enableSensor(sensor_type_t type) {
    195     android::Sensor const* sensor;
    196     android::SensorManager& mgr(android::SensorManager::getInstance());
    197 
    198     LOG_FUNCTION_NAME;
    199 
    200     android::AutoMutex lock(&mLock);
    201 
    202     if ((type & SENSOR_ORIENTATION) && !(sensorsEnabled & SENSOR_ORIENTATION)) {
    203         sensor = mgr.getDefaultSensor(android::Sensor::TYPE_ACCELEROMETER);
    204         if(sensor) {
    205             CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string());
    206             mSensorEventQueue->enableSensor(sensor);
    207             mSensorEventQueue->setEventRate(sensor, ms2ns(100));
    208             sensorsEnabled |= SENSOR_ORIENTATION;
    209         } else {
    210             CAMHAL_LOGDB("not enabling absent orientation sensor");
    211         }
    212     }
    213 
    214     LOG_FUNCTION_NAME_EXIT;
    215 }
    216 
    217 void SensorListener::disableSensor(sensor_type_t type) {
    218     android::Sensor const* sensor;
    219     android::SensorManager& mgr(android::SensorManager::getInstance());
    220 
    221     LOG_FUNCTION_NAME;
    222 
    223     android::AutoMutex lock(&mLock);
    224 
    225     if ((type & SENSOR_ORIENTATION) && (sensorsEnabled & SENSOR_ORIENTATION)) {
    226         sensor = mgr.getDefaultSensor(android::Sensor::TYPE_ACCELEROMETER);
    227         CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string());
    228         mSensorEventQueue->disableSensor(sensor);
    229         sensorsEnabled &= ~SENSOR_ORIENTATION;
    230     }
    231 
    232     LOG_FUNCTION_NAME_EXIT;
    233 }
    234 
    235 } // namespace Camera
    236 } // namespace Ti
    237