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