Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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> |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 21 | #include <binder/IServiceManager.h> |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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 |
Eric Laurent | 4634eff | 2012-11-28 17:48:51 -0800 | [diff] [blame] | 31 | #define BL_SENSOR_LEVEL_THRESHOLD (2.0) |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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), |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 38 | mNumSensors(0), mAccelerometer(NULL), |
| 39 | mInitStatus(-ENODEV) |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 40 | { |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 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 | |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 62 | goto exit; |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 63 | } |
| 64 | mAccelerometer = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER); |
| 65 | if (mAccelerometer == NULL) { |
| 66 | ALOGE("CSTOR mAccelerometer error NULL"); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 67 | goto exit; |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | mSensorEventQueue = mgr.createEventQueue(); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 71 | if (mSensorEventQueue == 0) { |
| 72 | ALOGE("createEventQueue returned 0"); |
| 73 | goto exit; |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | mLooper = new Looper(false); |
| 77 | mLooper->addFd(mSensorEventQueue->getFd(), 0, ALOOPER_EVENT_INPUT, sensor_callback, this); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 78 | |
| 79 | mInitStatus = 0; |
| 80 | |
| 81 | exit: |
| 82 | return mInitStatus; |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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 | { |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 98 | if (mInitStatus == 0) { |
| 99 | run("Acc Loop", ANDROID_PRIORITY_URGENT_AUDIO); |
| 100 | } |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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)); |
Eric Laurent | d23b2fb | 2012-10-23 19:29:41 -0700 | [diff] [blame] | 158 | if (mState == BL_STATE_POLLING_ONCE) { |
| 159 | mCmd = BL_CMD_STOP_POLL; |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 160 | } |
Eric Laurent | d23b2fb | 2012-10-23 19:29:41 -0700 | [diff] [blame] | 161 | mState = BL_STATE_SLEEPING; |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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 | |
Eric Laurent | d23b2fb | 2012-10-23 19:29:41 -0700 | [diff] [blame] | 178 | if (mState == BL_STATE_SLEEPING) { |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 194 | if (mInitStatus != 0) { |
| 195 | return mInitStatus; |
| 196 | } |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 209 | if (mInitStatus != 0) { |
| 210 | return mInitStatus; |
| 211 | } |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 212 | mPollIntervalSec = seconds; |
| 213 | return 0; |
| 214 | } |
| 215 | int BubbleLevelImpl::startPolling() |
| 216 | { |
| 217 | Mutex::Autolock _l(mStateLock); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 218 | if (mInitStatus != 0) { |
| 219 | return mInitStatus; |
| 220 | } |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 231 | if (mInitStatus != 0) { |
| 232 | return mInitStatus; |
| 233 | } |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 244 | if (mInitStatus != 0) { |
| 245 | return mInitStatus; |
| 246 | } |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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) && |
Eric Laurent | 4634eff | 2012-11-28 17:48:51 -0800 | [diff] [blame] | 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)) { |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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(); |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 342 | if (bl->bubble_level->initStatus() != 0) { |
| 343 | bubble_level_release((struct bubble_level *)bl); |
| 344 | return NULL; |
| 345 | } |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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 | |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 352 | return (struct bubble_level *)bl; |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 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 | |
Eric Laurent | 23e77a8 | 2012-11-02 14:37:38 -0700 | [diff] [blame] | 359 | if (bl == NULL) |
| 360 | return; |
| 361 | |
Eric Laurent | bec6aef | 2012-10-16 10:06:15 -0700 | [diff] [blame] | 362 | bl->bubble_level.clear(); |
| 363 | delete bubble_level; |
| 364 | } |
| 365 | |
| 366 | }; |