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