| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "ALooper.h" |
| |
| #include "ASensorEventQueue.h" |
| |
| #define LOG_TAG "libsensorndkbridge" |
| #include <android/looper.h> |
| #include <android-base/logging.h> |
| |
| using android::Mutex; |
| using android::sp; |
| using android::wp; |
| |
| ALooper::ALooper() |
| : mAwoken(false) { |
| } |
| |
| void ALooper::signalSensorEvents(wp<ASensorEventQueue> queue) { |
| Mutex::Autolock autoLock(mLock); |
| mReadyQueues.insert(queue); |
| mCondition.signal(); |
| } |
| |
| void ALooper::wake() { |
| Mutex::Autolock autoLock(mLock); |
| mAwoken = true; |
| mCondition.signal(); |
| } |
| |
| int ALooper::pollOnce( |
| int timeoutMillis, int *outFd, int *outEvents, void **outData) { |
| if (outFd) { *outFd = 0; } |
| if (outEvents) { *outEvents = 0; } |
| if (outData) { *outData = NULL; } |
| |
| int64_t waitUntilNs; |
| if (timeoutMillis < 0) { |
| waitUntilNs = -1; |
| } else { |
| waitUntilNs = systemTime(SYSTEM_TIME_MONOTONIC) + timeoutMillis * 1000000LL; |
| } |
| |
| Mutex::Autolock autoLock(mLock); |
| int64_t nowNs; |
| while ((timeoutMillis < 0 |
| || (nowNs = systemTime(SYSTEM_TIME_MONOTONIC)) < waitUntilNs) |
| && mReadyQueues.empty() |
| && !mAwoken) { |
| if (timeoutMillis < 0) { |
| mCondition.wait(mLock); |
| } else { |
| mCondition.waitRelative(mLock, waitUntilNs - nowNs); |
| } |
| } |
| |
| int result = ALOOPER_POLL_TIMEOUT; |
| |
| if (!mReadyQueues.empty()) { |
| result = ALOOPER_POLL_CALLBACK; |
| |
| for (auto& queue : mReadyQueues) { |
| sp<ASensorEventQueue> promotedQueue = queue.promote(); |
| if (promotedQueue != nullptr) { |
| promotedQueue->dispatchCallback(); |
| } |
| } |
| |
| mReadyQueues.clear(); |
| } else if (mAwoken) { |
| result = ALOOPER_POLL_WAKE; |
| mAwoken = false; |
| } |
| |
| LOG(VERBOSE) << "pollOnce returning " << result; |
| |
| return result; |
| } |
| |
| void ALooper::invalidateSensorQueue(wp<ASensorEventQueue> queue) { |
| Mutex::Autolock autoLock(mLock); |
| mReadyQueues.erase(queue); |
| } |