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