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 
BubbleLevelImpl()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 
init()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 
~BubbleLevelImpl()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 
onFirstRef()96 void BubbleLevelImpl::onFirstRef()
97 {
98     if (mInitStatus == 0) {
99         run("Acc Loop", ANDROID_PRIORITY_URGENT_AUDIO);
100     }
101 }
102 
threadLoop()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 
setCallback(BubbleLevel_CallBack_t callback,void * userData)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 
setPollInterval(unsigned int seconds)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 }
startPolling()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 
stopPolling()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 
pollOnce()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 
sensor_callback(int fd,int events,void * data)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 
bl_set_callback(const struct bubble_level * bubble_level,BubbleLevel_CallBack_t callback,void * userData)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 
bl_set_poll_interval(const struct bubble_level * bubble_level,unsigned int seconds)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 
bl_start_polling(const struct bubble_level * bubble_level)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 
bl_stop_polling(const struct bubble_level * bubble_level)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 
bl_poll_once(const struct bubble_level * bubble_level)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 
bubble_level_create()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 
bubble_level_release(const struct bubble_level * bubble_level)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