Home | History | Annotate | Download | only in bubblelevel
      1 /*
      2  * Copyright (C) 2012 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 #define LOG_TAG "BubbleLevelImpl"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <utils/Log.h>
     21 #include <binder/IServiceManager.h>
     22 #include "BubbleLevelImpl.h"
     23 
     24 namespace android {
     25 
     26 static int sensor_callback(int fd, int events, void* data);
     27 
     28 #define BL_SENSOR_POLL_INTERVAL_MS 20
     29 #define BL_SENSOR_POLL_TIMEOUT_MS (BL_SENSOR_POLL_INTERVAL_MS * 5)
     30 #define BL_SENSOR_POLL_COUNT 10
     31 #define BL_SENSOR_LEVEL_THRESHOLD (2.0)
     32 
     33 BubbleLevelImpl::BubbleLevelImpl()
     34     : Thread(false),
     35       mState(BL_STATE_IDLE), mCmd(BL_CMD_NONE),
     36       mPollIntervalSec(BL_POLL_INTERVAL_DEFAULT_SEC), mPollCount(0), mLevelCount(0),
     37       mCallBack(NULL), mUserData(NULL),
     38       mNumSensors(0), mAccelerometer(NULL),
     39       mInitStatus(-ENODEV)
     40 {
     41     init();
     42 }
     43 
     44 int BubbleLevelImpl::init()
     45 {
     46     if (mInitStatus == 0) {
     47         return 0;
     48     }
     49 
     50     if (defaultServiceManager()->checkService(String16("sensorservice")) == 0) {
     51         ALOGW("CSTOR sensorservice not ready yet");
     52         return mInitStatus;
     53     }
     54 
     55     SensorManager& mgr(SensorManager::getInstance());
     56     Sensor const* const* sensorList;
     57 
     58     mNumSensors = mgr.getSensorList(&sensorList);
     59 
     60     if (mNumSensors <= 0) {
     61         ALOGE("CSTOR mNumSensors error %d", mNumSensors);
     62         goto exit;
     63     }
     64     mAccelerometer = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
     65     if (mAccelerometer == NULL) {
     66         ALOGE("CSTOR mAccelerometer error NULL");
     67         goto exit;
     68     }
     69 
     70     mSensorEventQueue = mgr.createEventQueue();
     71     if (mSensorEventQueue == 0) {
     72         ALOGE("createEventQueue returned 0");
     73         goto exit;
     74     }
     75 
     76     mLooper = new Looper(false);
     77     mLooper->addFd(mSensorEventQueue->getFd(), 0, ALOOPER_EVENT_INPUT, sensor_callback, this);
     78 
     79     mInitStatus = 0;
     80 
     81 exit:
     82     return mInitStatus;
     83 }
     84 
     85 BubbleLevelImpl::~BubbleLevelImpl()
     86 {
     87     {
     88         Mutex::Autolock _l(mStateLock);
     89         mCmd = BL_CMD_EXIT;
     90         mLooper->wake();
     91         mCond.broadcast();
     92     }
     93     requestExitAndWait();
     94 }
     95 
     96 void BubbleLevelImpl::onFirstRef()
     97 {
     98     if (mInitStatus == 0) {
     99         run("Acc Loop", ANDROID_PRIORITY_URGENT_AUDIO);
    100     }
    101 }
    102 
    103 bool BubbleLevelImpl::threadLoop() {
    104     bool isLevel;
    105 
    106     while(!exitPending()) {
    107         {
    108             Mutex::Autolock _l(mStateLock);
    109 
    110             isLevel = false;
    111 
    112             switch (mCmd) {
    113             case BL_CMD_POLL_ONCE:
    114             case BL_CMD_START_POLL:
    115                 if (mState == BL_STATE_IDLE) {
    116                     mSensorEventQueue->enableSensor(mAccelerometer);
    117                     mSensorEventQueue->setEventRate(mAccelerometer,
    118                                                     ms2ns(BL_SENSOR_POLL_INTERVAL_MS));
    119                     mPollCount = 0;
    120                     mLevelCount = 0;
    121                     if (mCmd == BL_CMD_START_POLL) {
    122                         mState = BL_STATE_POLLING;
    123                     } else {
    124                         mState = BL_STATE_POLLING_ONCE;
    125                     }
    126                 }
    127                 if ((mCmd == BL_CMD_START_POLL) && (mState == BL_STATE_POLLING_ONCE)) {
    128                     mState = BL_STATE_POLLING;
    129                 }
    130                 break;
    131             case BL_CMD_STOP_POLL:
    132                 if (mState == BL_STATE_POLLING ||
    133                         mState == BL_STATE_POLLING_ONCE ||
    134                         mState == BL_STATE_SLEEPING) {
    135                     mSensorEventQueue->disableSensor(mAccelerometer);
    136                     mState = BL_STATE_IDLE;
    137                 }
    138                 break;
    139             case BL_CMD_EXIT:
    140                 continue;
    141             case BL_CMD_NONE:
    142                 break;
    143             default:
    144                 ALOGE("unknown command: %d", mCmd);
    145             }
    146             mCmd = BL_CMD_NONE;
    147 
    148             switch (mState) {
    149             case BL_STATE_IDLE:
    150                 mCond.wait(mStateLock);
    151                 continue;
    152 
    153             case BL_STATE_POLLING:
    154             case BL_STATE_POLLING_ONCE:
    155                 if (mPollCount >= BL_SENSOR_POLL_COUNT) {
    156                     // majority vote
    157                     isLevel = (mLevelCount > (BL_SENSOR_POLL_COUNT / 2));
    158                     if (mState == BL_STATE_POLLING_ONCE) {
    159                         mCmd = BL_CMD_STOP_POLL;
    160                     }
    161                     mState = BL_STATE_SLEEPING;
    162                 }
    163                 break;
    164             case BL_STATE_SLEEPING:
    165                 mCond.waitRelative(mStateLock, seconds(mPollIntervalSec));
    166                 mPollCount = 0;
    167                 mLevelCount = 0;
    168                 mState = BL_STATE_POLLING;
    169                 break;
    170 
    171             default:
    172                 ALOGE("unknown state: %d", mState);
    173                 mState = BL_STATE_IDLE;
    174                 continue;
    175             }
    176         }
    177 
    178         if (mState == BL_STATE_SLEEPING) {
    179             Mutex::Autolock _l(mCallbackLock);
    180             if (mCallBack != NULL) {
    181                 mCallBack(isLevel, mUserData);
    182             }
    183             continue;
    184         }
    185         mLooper->pollOnce(BL_SENSOR_POLL_TIMEOUT_MS);
    186     }
    187     ALOGV("threadLoop EXIT");
    188     return false;
    189 }
    190 
    191 int BubbleLevelImpl::setCallback(BubbleLevel_CallBack_t callback, void *userData)
    192 {
    193     Mutex::Autolock _l(mCallbackLock);
    194     if (mInitStatus != 0) {
    195         return mInitStatus;
    196     }
    197     mCallBack = callback;
    198     mUserData = userData;
    199     return 0;
    200 }
    201 
    202 int BubbleLevelImpl::setPollInterval(unsigned int seconds)
    203 {
    204     if (seconds < BL_POLL_INTERVAL_MIN_SEC) {
    205         return -EINVAL;
    206     }
    207 
    208     Mutex::Autolock _l(mStateLock);
    209     if (mInitStatus != 0) {
    210         return mInitStatus;
    211     }
    212     mPollIntervalSec = seconds;
    213     return 0;
    214 }
    215 int BubbleLevelImpl::startPolling()
    216 {
    217     Mutex::Autolock _l(mStateLock);
    218     if (mInitStatus != 0) {
    219         return mInitStatus;
    220     }
    221     if (mCmd != BL_CMD_EXIT) {
    222         mCmd = BL_CMD_START_POLL;
    223         mCond.signal();
    224     }
    225     return 0;
    226 }
    227 
    228 int BubbleLevelImpl::stopPolling()
    229 {
    230     Mutex::Autolock _l(mStateLock);
    231     if (mInitStatus != 0) {
    232         return mInitStatus;
    233     }
    234     if (mCmd != BL_CMD_EXIT) {
    235         mCmd = BL_CMD_STOP_POLL;
    236         mCond.signal();
    237     }
    238     return 0;
    239 }
    240 
    241 int BubbleLevelImpl::pollOnce()
    242 {
    243     Mutex::Autolock _l(mStateLock);
    244     if (mInitStatus != 0) {
    245         return mInitStatus;
    246     }
    247     if (mCmd != BL_CMD_EXIT) {
    248         mCmd = BL_CMD_POLL_ONCE;
    249         mCond.signal();
    250     }
    251     return 0;
    252 }
    253 
    254 static int sensor_callback(int fd, int events, void* data)
    255 {
    256     sp<BubbleLevelImpl> bl = sp<BubbleLevelImpl>((BubbleLevelImpl *)data);
    257 
    258     bl->lockState();
    259     if (((bl->state() != BubbleLevelImpl::BL_STATE_POLLING) &&
    260             (bl->state() != BubbleLevelImpl::BL_STATE_POLLING_ONCE)) ||
    261             (bl->pollCount() >= BL_SENSOR_POLL_COUNT)) {
    262         bl->unlockState();
    263         return 1;
    264     }
    265     bl->unlockState();
    266 
    267     sp<SensorEventQueue> sensorEventQueue = bl->sensorEventQueue();
    268     size_t numSensors = bl->numSensors();
    269     bool isLevel = false;
    270     ASensorEvent sensorEvents[numSensors];
    271     ssize_t ret = sensorEventQueue->read(sensorEvents, numSensors);
    272     if (ret > 0) {
    273         for (int i = 0; i < ret; i++) {
    274             if (sensorEvents[i].type == Sensor::TYPE_ACCELEROMETER) {
    275                 ALOGV("sensor_callback() azimuth = %f pitch = %f roll = %f",
    276                       sensorEvents[i].vector.azimuth,
    277                       sensorEvents[i].vector.pitch,
    278                       sensorEvents[i].vector.roll);
    279 
    280                 if ((sensorEvents[i].vector.roll > 0.0) &&
    281                         (sensorEvents[i].vector.azimuth < BL_SENSOR_LEVEL_THRESHOLD) &&
    282                         (sensorEvents[i].vector.azimuth > -BL_SENSOR_LEVEL_THRESHOLD) &&
    283                         (sensorEvents[i].vector.pitch < BL_SENSOR_LEVEL_THRESHOLD) &&
    284                         (sensorEvents[i].vector.pitch > -BL_SENSOR_LEVEL_THRESHOLD)) {
    285                     isLevel = true;
    286                 }
    287                 break;
    288             }
    289         }
    290     }
    291 
    292     bl->lockState();
    293     bl->incPollCount();
    294     if (isLevel) {
    295         bl->incLevelCount();
    296     }
    297     bl->unlockState();
    298 
    299     return 1;
    300 }
    301 
    302 }; // namespace android
    303 
    304 extern "C" {
    305 
    306 static int bl_set_callback(const struct bubble_level *bubble_level,
    307                  BubbleLevel_CallBack_t callback, void *userData)
    308 {
    309     bubble_level_C_impl *bl = (bubble_level_C_impl *)bubble_level;
    310     return bl->bubble_level->setCallback(callback, userData);
    311 }
    312 
    313 static int bl_set_poll_interval(const struct bubble_level *bubble_level, unsigned int seconds)
    314 {
    315     bubble_level_C_impl *bl = (bubble_level_C_impl *)bubble_level;
    316     return bl->bubble_level->setPollInterval(seconds);
    317 }
    318 
    319 static int bl_start_polling(const struct bubble_level *bubble_level)
    320 {
    321     bubble_level_C_impl *bl = (bubble_level_C_impl *)bubble_level;
    322     return bl->bubble_level->startPolling();
    323 }
    324 
    325 static int bl_stop_polling(const struct bubble_level *bubble_level)
    326 {
    327     bubble_level_C_impl *bl = (bubble_level_C_impl *)bubble_level;
    328     return bl->bubble_level->stopPolling();
    329 }
    330 
    331 static int bl_poll_once(const struct bubble_level *bubble_level)
    332 {
    333     bubble_level_C_impl *bl = (bubble_level_C_impl *)bubble_level;
    334     return bl->bubble_level->pollOnce();
    335 }
    336 
    337 
    338 struct bubble_level *bubble_level_create()
    339 {
    340     bubble_level_C_impl *bl = new bubble_level_C_impl();
    341     bl->bubble_level = new android::BubbleLevelImpl();
    342     if (bl->bubble_level->initStatus() != 0) {
    343         bubble_level_release((struct bubble_level *)bl);
    344         return NULL;
    345     }
    346     bl->interface.set_callback = bl_set_callback;
    347     bl->interface.set_poll_interval = bl_set_poll_interval;
    348     bl->interface.start_polling = bl_start_polling;
    349     bl->interface.stop_polling = bl_stop_polling;
    350     bl->interface.poll_once = bl_poll_once;
    351 
    352     return (struct bubble_level *)bl;
    353 }
    354 
    355 void bubble_level_release(const struct bubble_level *bubble_level)
    356 {
    357     bubble_level_C_impl *bl = (bubble_level_C_impl *)bubble_level;
    358 
    359     if (bl == NULL)
    360         return;
    361 
    362     bl->bubble_level.clear();
    363     delete bubble_level;
    364 }
    365 
    366 };
    367