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