diff options
Diffstat (limited to 'modules/sensors/dynamic_sensor/DynamicSensorManager.cpp')
-rw-r--r-- | modules/sensors/dynamic_sensor/DynamicSensorManager.cpp | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp b/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp new file mode 100644 index 00000000..d33650cc --- /dev/null +++ b/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp @@ -0,0 +1,283 @@ +/* + * 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 "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); + 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) { + // TODO: 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 |