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(const std::shared_ptr<ASensorEventQueue> & queue)31 void ALooper::signalSensorEvents(const std::shared_ptr<ASensorEventQueue>& queue) {
32     Mutex::Autolock autoLock(mLock);
33     mReadyQueues.push_back(std::weak_ptr<ASensorEventQueue>(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             std::shared_ptr<ASensorEventQueue> promotedQueue = queue.lock();
76             if (promotedQueue != nullptr) {
77                 promotedQueue->dispatchCallback();
78             }
79         }
80 
81         mReadyQueues.clear();
82     } else if (mAwoken) {
83         result = ALOOPER_POLL_WAKE;
84         mAwoken = false;
85     }
86 
87     LOG(VERBOSE) << "pollOnce returning " << result;
88 
89     return result;
90 }
91 
invalidateSensorQueue(const std::shared_ptr<ASensorEventQueue> & queue)92 void ALooper::invalidateSensorQueue(const std::shared_ptr<ASensorEventQueue>& queue) {
93     Mutex::Autolock autoLock(mLock);
94 
95     mReadyQueues.erase(std::remove_if(mReadyQueues.begin(), mReadyQueues.end(),
96                                       [&](const std::weak_ptr<ASensorEventQueue>& ptr) {
97                                           std::shared_ptr<ASensorEventQueue> in = ptr.lock();
98                                           return (in == nullptr) || (in == queue);
99                                       }),
100                        mReadyQueues.end());
101 }
102