blob: b6340524e0047641186816cb1430394f83bb6568 [file] [log] [blame]
/*
* 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 "BaseDynamicSensorDaemon.h"
#include "BaseSensorObject.h"
#include "DummyDynamicAccelDaemon.h"
#include "HidRawSensorDaemon.h"
#include "DynamicSensorManager.h"
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <cassert>
namespace android {
namespace SensorHalExt {
DynamicSensorManager* DynamicSensorManager::createInstance(
int handleBase, int handleCount, SensorEventCallback *callback) {
auto m = new DynamicSensorManager(handleBase, handleBase + handleCount - 1, callback);
m->mDaemonVector.push_back(new DummyDynamicAccelDaemon(*m));
m->mDaemonVector.push_back(new HidRawSensorDaemon(*m));
return m;
}
DynamicSensorManager::DynamicSensorManager(
int handleBase, int handleMax, SensorEventCallback* callback) :
mHandleRange(handleBase, handleMax),
mCallback(callback),
mFifo(callback ? 0 : kFifoSize),
mNextHandle(handleBase+1) {
assert(handleBase > 0 && handleMax > handleBase + 1); // handleBase is reserved
mMetaSensor = (const sensor_t) {
"Dynamic Sensor Manager",
"Google",
1, // version
handleBase, // handle
SENSOR_TYPE_DYNAMIC_SENSOR_META,
1, // maxRange
1, // resolution
1e-6f, // power, very small number instead of 0
// to avoid sigularity in app
(int32_t)(1000), // minDelay
0, // fifoReservedEventCount
0, // fifoMaxEventCount
SENSOR_STRING_TYPE_DYNAMIC_SENSOR_META,
"", // requiredPermission
(long)(1000), // maxDelay
SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP,
{ NULL, NULL }
};
}
DynamicSensorManager::~DynamicSensorManager() {
// free all daemons first
mDaemonVector.clear();
}
bool DynamicSensorManager::owns(int handle) const {
return handle >= mHandleRange.first && handle < mHandleRange.second;
}
int DynamicSensorManager::activate(int handle, bool enable) {
if (handle == mHandleRange.first) {
// ignored
return 0;
}
// in case there is a pending report, now it is time to remove it as it is no longer necessary.
{
std::lock_guard<std::mutex> lk(mLock);
mPendingReport.erase(handle);
}
return operateSensor(handle,
[&enable] (sp<BaseSensorObject> s)->int {
return s->enable(enable);
});
}
int DynamicSensorManager::batch(int handle, nsecs_t sample_period, nsecs_t batch_period) {
if (handle == mHandleRange.first) {
// ignored
return 0;
}
return operateSensor(handle,
[&sample_period, &batch_period] (sp<BaseSensorObject> s)->int {
return s->batch(sample_period, batch_period);
});
}
int DynamicSensorManager::setDelay(int handle, nsecs_t sample_period) {
return batch(handle, sample_period, 0);
}
int DynamicSensorManager::flush(int handle) {
if (handle == mHandleRange.first) {
// submit a flush complete here
static const sensors_event_t event = {
.type = SENSOR_TYPE_META_DATA,
.sensor = mHandleRange.first,
.timestamp = TIMESTAMP_AUTO_FILL, // timestamp will be filled at dispatcher
};
submitEvent(nullptr, event);
return 0;
}
return operateSensor(handle, [] (sp<BaseSensorObject> s)->int {return s->flush();});
}
int DynamicSensorManager::poll(sensors_event_t * data, int count) {
assert(mCallback == nullptr);
std::lock_guard<std::mutex> lk(mFifoLock);
return mFifo.read(data, count);
}
bool DynamicSensorManager::registerSensor(sp<BaseSensorObject> sensor) {
std::lock_guard<std::mutex> lk(mLock);
if (mReverseMap.find(sensor.get()) != mReverseMap.end()) {
ALOGE("trying to add the same sensor twice, ignore");
return false;
}
int handle = getNextAvailableHandle();
if (handle < 0) {
ALOGE("Running out of handle, quit.");
return false;
}
// these emplace will always be successful
mMap.emplace(handle, sensor);
mReverseMap.emplace(sensor.get(), handle);
sensor->setEventCallback(this);
auto entry = mPendingReport.emplace(
std::piecewise_construct,
std::forward_as_tuple(handle),
std::forward_as_tuple(handle, sensor));
if (entry.second) {
submitEvent(nullptr, entry.first->second.generateConnectionEvent(mHandleRange.first));
}
return entry.second;
}
void DynamicSensorManager::unregisterSensor(sp<BaseSensorObject> sensor) {
std::lock_guard<std::mutex> lk(mLock);
auto i = mReverseMap.find(sensor.get());
if (i == mReverseMap.end()) {
ALOGE("cannot remove a non-exist sensor");
return;
}
int handle = i->second;
mReverseMap.erase(i);
mMap.erase(handle);
// will not clean up mPendingReport here, it will be cleaned up when at first activate call.
// sensorservice is guranteed to call activate upon arrival of dynamic sensor meta connection
// event.
// send disconnection event
sensors_event_t event;
ConnectionReport::fillDisconnectionEvent(&event, mHandleRange.first, handle);
submitEvent(nullptr, event);
}
int DynamicSensorManager::submitEvent(sp<BaseSensorObject> source, const sensors_event_t &e) {
int handle;
if (source == nullptr) {
handle = mHandleRange.first;
} else {
std::lock_guard<std::mutex> lk(mLock);
auto i = mReverseMap.find(source.get());
if (i == mReverseMap.end()) {
ALOGE("cannot submit event for sensor that has not been registered");
return NAME_NOT_FOUND;
}
handle = i->second;
}
// making a copy of events, prepare for editing
sensors_event_t event = e;
event.version = sizeof(event);
// special case of flush complete
if (event.type == SENSOR_TYPE_META_DATA) {
event.sensor = 0;
event.meta_data.sensor = handle;
} else {
event.sensor = handle;
}
// set timestamp if it is default value
if (event.timestamp == TIMESTAMP_AUTO_FILL) {
event.timestamp = elapsedRealtimeNano();
}
if (mCallback) {
// extention mode, calling callback directly
int ret;
ret = mCallback->submitEvent(nullptr, event);
if (ret < 0) {
ALOGE("DynamicSensorManager callback failed, ret: %d", ret);
}
} else {
// standalone mode, add event to internal buffer for poll() to pick up
std::lock_guard<std::mutex> lk(mFifoLock);
if (mFifo.write(&event, 1) < 0) {
ALOGE("DynamicSensorManager fifo full");
}
}
return 0;
}
int DynamicSensorManager::getNextAvailableHandle() {
if (mNextHandle == mHandleRange.second) {
return -1;
}
return mNextHandle++;
}
const sensor_t& DynamicSensorManager::getDynamicMetaSensor() const {
return mMetaSensor;
}
DynamicSensorManager::ConnectionReport::ConnectionReport(
int handle, sp<BaseSensorObject> sensor) :
mSensor(*(sensor->getSensor())),
mName(mSensor.name),
mVendor(mSensor.vendor),
mPermission(mSensor.requiredPermission),
mStringType(mSensor.stringType),
mGenerated(false) {
mSensor.name = mName.c_str();
mSensor.vendor = mVendor.c_str();
mSensor.requiredPermission = mPermission.c_str();
mSensor.stringType = mStringType.c_str();
mSensor.handle = handle;
memset(&mEvent, 0, sizeof(mEvent));
mEvent.version = sizeof(mEvent);
sensor->getUuid(mUuid);
ALOGV("Connection report init: name = %s, handle = %d", mSensor.name, mSensor.handle);
}
DynamicSensorManager::ConnectionReport::~ConnectionReport() {
ALOGV("Connection report dtor: name = %s, handle = %d", mSensor.name, mSensor.handle);
}
const sensors_event_t& DynamicSensorManager::ConnectionReport::
generateConnectionEvent(int metaHandle) {
if (!mGenerated) {
mEvent.sensor = metaHandle;
mEvent.type = SENSOR_TYPE_DYNAMIC_SENSOR_META;
mEvent.timestamp = elapsedRealtimeNano();
mEvent.dynamic_sensor_meta =
(dynamic_sensor_meta_event_t) {true, mSensor.handle, &mSensor, {0}};
memcpy(&mEvent.dynamic_sensor_meta.uuid, &mUuid, sizeof(mEvent.dynamic_sensor_meta.uuid));
mGenerated = true;
}
return mEvent;
}
void DynamicSensorManager::ConnectionReport::
fillDisconnectionEvent(sensors_event_t* event, int metaHandle, int handle) {
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor = metaHandle;
event->type = SENSOR_TYPE_DYNAMIC_SENSOR_META;
event->timestamp = elapsedRealtimeNano();
event->dynamic_sensor_meta.connected = false;
event->dynamic_sensor_meta.handle = handle;
}
} // namespace SensorHalExt
} // namespace android