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 =
54             systemTime(SYSTEM_TIME_MONOTONIC) + timeoutMillis * 1000000ll;
55     }
56 
57     Mutex::Autolock autoLock(mLock);
58     int64_t nowNs;
59     while ((timeoutMillis < 0
60                 || (nowNs = systemTime(SYSTEM_TIME_MONOTONIC)) < waitUntilNs)
61             && mReadyQueues.empty()
62             && !mAwoken) {
63         if (timeoutMillis < 0) {
64             mCondition.wait(mLock);
65         } else {
66             mCondition.waitRelative(mLock, waitUntilNs - nowNs);
67         }
68     }
69 
70     int result = ALOOPER_POLL_TIMEOUT;
71 
72     if (!mReadyQueues.empty()) {
73         result = ALOOPER_POLL_CALLBACK;
74 
75         for (auto queue : mReadyQueues) {
76             queue->dispatchCallback();
77         }
78 
79         mReadyQueues.clear();
80     } else if (mAwoken) {
81         result = ALOOPER_POLL_WAKE;
82         mAwoken = false;
83     }
84 
85     LOG(VERBOSE) << "pollOnce returning " << result;
86 
87     return result;
88 }
89 
invalidateSensorQueue(ASensorEventQueue * queue)90 void ALooper::invalidateSensorQueue(ASensorEventQueue *queue) {
91     Mutex::Autolock autoLock(mLock);
92     mReadyQueues.erase(queue);
93 }
94 
95