blob: c45b0a115abfb6af2c17e01e81ea3da9ed3504ff [file] [log] [blame]
Eric Laurentbec6aef2012-10-16 10:06:15 -07001/*
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 Laurent23e77a82012-11-02 14:37:38 -070021#include <binder/IServiceManager.h>
Eric Laurentbec6aef2012-10-16 10:06:15 -070022#include "BubbleLevelImpl.h"
23
24namespace android {
25
26static 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 Laurent4634eff2012-11-28 17:48:51 -080031#define BL_SENSOR_LEVEL_THRESHOLD (2.0)
Eric Laurentbec6aef2012-10-16 10:06:15 -070032
33BubbleLevelImpl::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 Laurent23e77a82012-11-02 14:37:38 -070038 mNumSensors(0), mAccelerometer(NULL),
39 mInitStatus(-ENODEV)
Eric Laurentbec6aef2012-10-16 10:06:15 -070040{
Eric Laurent23e77a82012-11-02 14:37:38 -070041 init();
42}
43
44int 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 Laurentbec6aef2012-10-16 10:06:15 -070055 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 Laurent23e77a82012-11-02 14:37:38 -070062 goto exit;
Eric Laurentbec6aef2012-10-16 10:06:15 -070063 }
64 mAccelerometer = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
65 if (mAccelerometer == NULL) {
66 ALOGE("CSTOR mAccelerometer error NULL");
Eric Laurent23e77a82012-11-02 14:37:38 -070067 goto exit;
Eric Laurentbec6aef2012-10-16 10:06:15 -070068 }
69
70 mSensorEventQueue = mgr.createEventQueue();
Eric Laurent23e77a82012-11-02 14:37:38 -070071 if (mSensorEventQueue == 0) {
72 ALOGE("createEventQueue returned 0");
73 goto exit;
Eric Laurentbec6aef2012-10-16 10:06:15 -070074 }
75
76 mLooper = new Looper(false);
77 mLooper->addFd(mSensorEventQueue->getFd(), 0, ALOOPER_EVENT_INPUT, sensor_callback, this);
Eric Laurent23e77a82012-11-02 14:37:38 -070078
79 mInitStatus = 0;
80
81exit:
82 return mInitStatus;
Eric Laurentbec6aef2012-10-16 10:06:15 -070083}
84
85BubbleLevelImpl::~BubbleLevelImpl()
86{
87 {
88 Mutex::Autolock _l(mStateLock);
89 mCmd = BL_CMD_EXIT;
90 mLooper->wake();
91 mCond.broadcast();
92 }
93 requestExitAndWait();
94}
95
96void BubbleLevelImpl::onFirstRef()
97{
Eric Laurent23e77a82012-11-02 14:37:38 -070098 if (mInitStatus == 0) {
99 run("Acc Loop", ANDROID_PRIORITY_URGENT_AUDIO);
100 }
Eric Laurentbec6aef2012-10-16 10:06:15 -0700101}
102
103bool 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 Laurentd23b2fb2012-10-23 19:29:41 -0700158 if (mState == BL_STATE_POLLING_ONCE) {
159 mCmd = BL_CMD_STOP_POLL;
Eric Laurentbec6aef2012-10-16 10:06:15 -0700160 }
Eric Laurentd23b2fb2012-10-23 19:29:41 -0700161 mState = BL_STATE_SLEEPING;
Eric Laurentbec6aef2012-10-16 10:06:15 -0700162 }
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 Laurentd23b2fb2012-10-23 19:29:41 -0700178 if (mState == BL_STATE_SLEEPING) {
Eric Laurentbec6aef2012-10-16 10:06:15 -0700179 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
191int BubbleLevelImpl::setCallback(BubbleLevel_CallBack_t callback, void *userData)
192{
193 Mutex::Autolock _l(mCallbackLock);
Eric Laurent23e77a82012-11-02 14:37:38 -0700194 if (mInitStatus != 0) {
195 return mInitStatus;
196 }
Eric Laurentbec6aef2012-10-16 10:06:15 -0700197 mCallBack = callback;
198 mUserData = userData;
199 return 0;
200}
201
202int 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 Laurent23e77a82012-11-02 14:37:38 -0700209 if (mInitStatus != 0) {
210 return mInitStatus;
211 }
Eric Laurentbec6aef2012-10-16 10:06:15 -0700212 mPollIntervalSec = seconds;
213 return 0;
214}
215int BubbleLevelImpl::startPolling()
216{
217 Mutex::Autolock _l(mStateLock);
Eric Laurent23e77a82012-11-02 14:37:38 -0700218 if (mInitStatus != 0) {
219 return mInitStatus;
220 }
Eric Laurentbec6aef2012-10-16 10:06:15 -0700221 if (mCmd != BL_CMD_EXIT) {
222 mCmd = BL_CMD_START_POLL;
223 mCond.signal();
224 }
225 return 0;
226}
227
228int BubbleLevelImpl::stopPolling()
229{
230 Mutex::Autolock _l(mStateLock);
Eric Laurent23e77a82012-11-02 14:37:38 -0700231 if (mInitStatus != 0) {
232 return mInitStatus;
233 }
Eric Laurentbec6aef2012-10-16 10:06:15 -0700234 if (mCmd != BL_CMD_EXIT) {
235 mCmd = BL_CMD_STOP_POLL;
236 mCond.signal();
237 }
238 return 0;
239}
240
241int BubbleLevelImpl::pollOnce()
242{
243 Mutex::Autolock _l(mStateLock);
Eric Laurent23e77a82012-11-02 14:37:38 -0700244 if (mInitStatus != 0) {
245 return mInitStatus;
246 }
Eric Laurentbec6aef2012-10-16 10:06:15 -0700247 if (mCmd != BL_CMD_EXIT) {
248 mCmd = BL_CMD_POLL_ONCE;
249 mCond.signal();
250 }
251 return 0;
252}
253
254static 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 Laurent4634eff2012-11-28 17:48:51 -0800281 (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 Laurentbec6aef2012-10-16 10:06:15 -0700285 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
304extern "C" {
305
306static 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
313static 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
319static 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
325static 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
331static 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
338struct 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 Laurent23e77a82012-11-02 14:37:38 -0700342 if (bl->bubble_level->initStatus() != 0) {
343 bubble_level_release((struct bubble_level *)bl);
344 return NULL;
345 }
Eric Laurentbec6aef2012-10-16 10:06:15 -0700346 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 Laurent23e77a82012-11-02 14:37:38 -0700352 return (struct bubble_level *)bl;
Eric Laurentbec6aef2012-10-16 10:06:15 -0700353}
354
355void bubble_level_release(const struct bubble_level *bubble_level)
356{
357 bubble_level_C_impl *bl = (bubble_level_C_impl *)bubble_level;
358
Eric Laurent23e77a82012-11-02 14:37:38 -0700359 if (bl == NULL)
360 return;
361
Eric Laurentbec6aef2012-10-16 10:06:15 -0700362 bl->bubble_level.clear();
363 delete bubble_level;
364}
365
366};