/*
* 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 "ASensorEventQueue.h"
#include "ALooper.h"
#define LOG_TAG "libsensorndkbridge"
#include <android-base/logging.h>
using android::sp;
using android::frameworks::sensorservice::V1_0::Result;
using android::hardware::sensors::V1_0::SensorInfo;
using android::OK;
using android::BAD_VALUE;
using android::Mutex;
using android::hardware::Return;
ASensorEventQueue::ASensorEventQueue(
ALooper *looper, int ident, ALooper_callbackFunc callback, void *data)
: mLooper(looper),
mIdent(ident),
mCallback(callback),
mData(data) {
}
void ASensorEventQueue::setImpl(const sp<IEventQueue> &queueImpl) {
mQueueImpl = queueImpl;
}
int ASensorEventQueue::registerSensor(
ASensorRef sensor,
int32_t samplingPeriodUs,
int64_t maxBatchReportLatencyUs) {
Return<Result> ret = mQueueImpl->enableSensor(
reinterpret_cast<const SensorInfo *>(sensor)->sensorHandle,
samplingPeriodUs,
maxBatchReportLatencyUs);
if (!ret.isOk()) {
return BAD_VALUE;
}
return OK;
}
int ASensorEventQueue::enableSensor(ASensorRef sensor) {
static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
return registerSensor(
sensor, SENSOR_DELAY_NORMAL, 0 /* maxBatchReportLatencyUs */);
}
int ASensorEventQueue::setEventRate(
ASensorRef sensor, int32_t samplingPeriodUs) {
// Technically this is not supposed to enable the sensor but using this
// API without enabling the sensor first is a no-op, so...
return registerSensor(
sensor, samplingPeriodUs, 0 /* maxBatchReportLatencyUs */);
}
int ASensorEventQueue::disableSensor(ASensorRef sensor) {
Return<Result> ret = mQueueImpl->disableSensor(
reinterpret_cast<const SensorInfo *>(sensor)->sensorHandle);
return ret.isOk() ? OK : BAD_VALUE;
}
ssize_t ASensorEventQueue::getEvents(ASensorEvent *events, size_t count) {
// XXX Should this block if there aren't any events in the queue?
Mutex::Autolock autoLock(mLock);
static_assert(
sizeof(ASensorEvent) == sizeof(sensors_event_t), "mismatched size");
size_t copy = std::min(count, mQueue.size());
for (size_t i = 0; i < copy; ++i) {
reinterpret_cast<sensors_event_t *>(events)[i] = mQueue[i];
}
mQueue.erase(mQueue.begin(), mQueue.begin() + copy);
LOG(VERBOSE) << "ASensorEventQueue::getEvents() returned " << copy << " events.";
return copy;
}
int ASensorEventQueue::hasEvents() const {
return mQueue.empty();
}
Return<void> ASensorEventQueue::onEvent(const Event &event) {
LOG(VERBOSE) << "ASensorEventQueue::onEvent";
{
Mutex::Autolock autoLock(mLock);
mQueue.emplace_back();
sensors_event_t *sensorEvent = &mQueue[mQueue.size() - 1];
android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
event, sensorEvent);
}
mLooper->signalSensorEvents(this);
return android::hardware::Void();
}
void ASensorEventQueue::dispatchCallback() {
if (mCallback != NULL) {
int res = (*mCallback)(-1 /* fd */, ALOOPER_EVENT_INPUT, mData);
if (res == 0) {
mCallback = NULL;
mData = NULL;
}
}
}
void ASensorEventQueue::invalidate() {
mLooper->invalidateSensorQueue(this);
setImpl(nullptr);
}