1 /*
2  * Copyright (C) 2017 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 #include "ALooper.h"
18 
19 #include "ASensorEventQueue.h"
20 
21 #define LOG_TAG "libsensorndkbridge"
22 #include <android/looper.h>
23 #include <android-base/logging.h>
24 
25 using android::Mutex;
26 
ALooper()27 ALooper::ALooper()
28     : mAwoken(false) {
29 }
30 
signalSensorEvents(ASensorEventQueue * queue)31 void ALooper::signalSensorEvents(ASensorEventQueue *queue) {
32     Mutex::Autolock autoLock(mLock);
33     mReadyQueues.insert(queue);
34     mCondition.signal();
35 }
36 
wake()37 void ALooper::wake() {
38     Mutex::Autolock autoLock(mLock);
39     mAwoken = true;
40     mCondition.signal();
41 }
42 
pollOnce(int timeoutMillis,int * outFd,int * outEvents,void ** outData)43 int ALooper::pollOnce(
44         int timeoutMillis, int *outFd, int *outEvents, void **outData) {
45     if (outFd) { *outFd = 0; }
46     if (outEvents) { *outEvents = 0; }
47     if (outData) { *outData = NULL; }
48 
49     int64_t waitUntilNs;
50     if (timeoutMillis < 0) {
51         waitUntilNs = -1;
52     } else {
53         waitUntilNs = systemTime(SYSTEM_TIME_MONOTONIC) + timeoutMillis * 1000000LL;
54     }
55 
56     Mutex::Autolock autoLock(mLock);
57     int64_t nowNs;
58     while ((timeoutMillis < 0
59                 || (nowNs = systemTime(SYSTEM_TIME_MONOTONIC)) < waitUntilNs)
60             && mReadyQueues.empty()
61             && !mAwoken) {
62         if (timeoutMillis < 0) {
63             mCondition.wait(mLock);
64         } else {
65             mCondition.waitRelative(mLock, waitUntilNs - nowNs);
66         }
67     }
68 
69     int result = ALOOPER_POLL_TIMEOUT;
70 
71     if (!mReadyQueues.empty()) {
72         result = ALOOPER_POLL_CALLBACK;
73 
74         for (auto queue : mReadyQueues) {
75             queue->dispatchCallback();
76         }
77 
78         mReadyQueues.clear();
79     } else if (mAwoken) {
80         result = ALOOPER_POLL_WAKE;
81         mAwoken = false;
82     }
83 
84     LOG(VERBOSE) << "pollOnce returning " << result;
85 
86     return result;
87 }
88 
invalidateSensorQueue(ASensorEventQueue * queue)89 void ALooper::invalidateSensorQueue(ASensorEventQueue *queue) {
90     Mutex::Autolock autoLock(mLock);
91     mReadyQueues.erase(queue);
92 }
93 
94