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 "ASensorEventQueue.h"
18 
19 #include "ALooper.h"
20 
21 #define LOG_TAG "libsensorndkbridge"
22 #include <android-base/logging.h>
23 #include <android/binder_auto_utils.h>
24 
25 using aidl::android::hardware::sensors::SensorInfo;
26 using android::BAD_VALUE;
27 using android::Mutex;
28 using android::OK;
29 
ASensorEventQueue(ALooper * looper,ALooper_callbackFunc callback,void * data)30 ASensorEventQueue::ASensorEventQueue(ALooper* looper, ALooper_callbackFunc callback, void* data)
31     : mLooper(looper),
32       mCallback(callback),
33       mData(data),
34       mRequestAdditionalInfo(false),
35       mValid(true) {}
36 
setImpl(const std::shared_ptr<IEventQueue> & queueImpl)37 void ASensorEventQueue::setImpl(const std::shared_ptr<IEventQueue>& queueImpl) {
38     mQueueImpl = queueImpl;
39 }
40 
registerSensor(ASensorRef sensor,int32_t samplingPeriodUs,int64_t maxBatchReportLatencyUs)41 int ASensorEventQueue::registerSensor(
42         ASensorRef sensor,
43         int32_t samplingPeriodUs,
44         int64_t maxBatchReportLatencyUs) {
45     ndk::ScopedAStatus ret =
46         mQueueImpl->enableSensor(reinterpret_cast<const SensorInfo*>(sensor)->sensorHandle,
47                                  samplingPeriodUs, maxBatchReportLatencyUs);
48 
49     if (!ret.isOk()) {
50         return BAD_VALUE;
51     }
52 
53     return OK;
54 }
55 
enableSensor(ASensorRef sensor)56 int ASensorEventQueue::enableSensor(ASensorRef sensor) {
57     static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
58 
59     return registerSensor(
60             sensor, SENSOR_DELAY_NORMAL, 0 /* maxBatchReportLatencyUs */);
61 }
62 
setEventRate(ASensorRef sensor,int32_t samplingPeriodUs)63 int ASensorEventQueue::setEventRate(
64         ASensorRef sensor, int32_t samplingPeriodUs) {
65     // Technically this is not supposed to enable the sensor but using this
66     // API without enabling the sensor first is a no-op, so...
67     return registerSensor(
68             sensor, samplingPeriodUs, 0 /* maxBatchReportLatencyUs */);
69 }
70 
requestAdditionalInfoEvents(bool enable)71 int ASensorEventQueue::requestAdditionalInfoEvents(bool enable) {
72     mRequestAdditionalInfo = enable;
73     return OK;
74 }
75 
disableSensor(ASensorRef sensor)76 int ASensorEventQueue::disableSensor(ASensorRef sensor) {
77     ndk::ScopedAStatus ret =
78         mQueueImpl->disableSensor(reinterpret_cast<const SensorInfo*>(sensor)->sensorHandle);
79 
80     return ret.isOk() ? OK : BAD_VALUE;
81 }
82 
getEvents(ASensorEvent * events,size_t count)83 ssize_t ASensorEventQueue::getEvents(ASensorEvent *events, size_t count) {
84     // XXX Should this block if there aren't any events in the queue?
85 
86     Mutex::Autolock autoLock(mLock);
87 
88     static_assert(
89             sizeof(ASensorEvent) == sizeof(sensors_event_t), "mismatched size");
90 
91     size_t copy = std::min(count, mQueue.size());
92     for (size_t i = 0; i < copy; ++i) {
93         reinterpret_cast<sensors_event_t *>(events)[i] = mQueue[i];
94     }
95     mQueue.erase(mQueue.begin(), mQueue.begin() + copy);
96 
97     LOG(VERBOSE) << "ASensorEventQueue::getEvents() returned " << copy << " events.";
98 
99     return copy;
100 }
101 
hasEvents() const102 int ASensorEventQueue::hasEvents() const {
103     return !mQueue.empty();
104 }
105 
onEvent(const Event & event)106 ndk::ScopedAStatus ASensorEventQueue::onEvent(const Event& event) {
107     LOG(VERBOSE) << "ASensorEventQueue::onEvent";
108 
109     if (static_cast<int32_t>(event.sensorType) != ASENSOR_TYPE_ADDITIONAL_INFO ||
110             mRequestAdditionalInfo.load()) {
111 
112         {
113             // Only lock the mutex in this block to avoid the following deadlock scenario:
114             //
115             // ASensorEventQueue::onEvent is called which grabs ASensorEventQueue::mLock followed
116             // by ALooper::mLock via ALooper::signalSensorEvents.
117             //
118             // Meanwhile
119             //
120             // ASensorEventQueue::dispatchCallback is invoked from ALooper::pollOnce which has
121             // has ALooper::mLock locked and the dispatched callback invokes
122             // ASensorEventQueue::getEvents which would try to grab ASensorEventQueue::mLock
123             // resulting in a deadlock.
124             Mutex::Autolock autoLock(mLock);
125             mQueue.emplace_back();
126             sensors_event_t* sensorEvent = &mQueue[mQueue.size() - 1];
127             android::hardware::sensors::implementation::convertToSensorEvent(event, sensorEvent);
128         }
129 
130         Mutex::Autolock autoLock(mValidLock);
131         if (mValid) {
132             mLooper->signalSensorEvents(this->ref<ASensorEventQueue>());
133         }
134     }
135 
136     return ndk::ScopedAStatus::ok();
137 }
138 
dispatchCallback()139 void ASensorEventQueue::dispatchCallback() {
140     if (mCallback != NULL) {
141         int res = (*mCallback)(-1 /* fd */, ALOOPER_EVENT_INPUT, mData);
142 
143         if (res == 0) {
144             mCallback = NULL;
145             mData = NULL;
146         }
147     }
148 }
149 
invalidate()150 void ASensorEventQueue::invalidate() {
151     {
152       // Only lock within this context to avoid locking while calling invalidateSensorQueue which
153       // also holds a lock. This is safe to do because mValid can't be made true after it's false
154       // so onEvent will never signal new sensor events after mValid is false.
155       Mutex::Autolock autoLock(mValidLock);
156       mValid = false;
157     }
158     mLooper->invalidateSensorQueue(this->ref<ASensorEventQueue>());
159     setImpl(nullptr);
160 }
161 
162