/* * 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 #include #include 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) { mMetaSensorActive = enable; 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 lk(mLock); mPendingReport.erase(handle); } return operateSensor(handle, [=] (sp 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, [=] (sp 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) { if (mMetaSensorActive) { static const sensors_event_t event = { .sensor = mHandleRange.first, .type = SENSOR_TYPE_META_DATA, .meta_data.what = META_DATA_FLUSH_COMPLETE, .timestamp = TIMESTAMP_AUTO_FILL, // timestamp will be filled at dispatcher }; submitEvent(nullptr, event); } else { return -EINVAL; } return 0; } return operateSensor(handle, [] (sp s)->int {return s->flush();}); } int DynamicSensorManager::poll(sensors_event_t * data, int count) { assert(mCallback == nullptr); std::lock_guard lk(mFifoLock); return mFifo.read(data, count); } bool DynamicSensorManager::registerSensor(sp sensor) { std::lock_guard 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 sensor) { std::lock_guard 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 source, const sensors_event_t &e) { int handle; if (source == nullptr) { handle = mHandleRange.first; } else { std::lock_guard 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 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; } int DynamicSensorManager::operateSensor( int handle, OperateSensorFunc sensorFunc) { std::shared_future sensorOp; { std::lock_guard lock(mSensorOpQueueLock); // Invoke the function asynchronously. sensorOp = std::async( [this, handle = handle, sensorFunc = sensorFunc, sensorOpIndex = mNextSensorOpIndex] ()->int { return operateSensor(handle, sensorFunc, sensorOpIndex); }).share(); // Add sensor operation to the queue. mSensorOpQueue.push({mNextSensorOpIndex, sensorOp}); mNextSensorOpIndex++; } // Wait for the sensor operation to complete. if (sensorOp.wait_for(kSensorOpTimeout) != std::future_status::ready) { ALOGE("sensor operation timed out"); return TIMED_OUT; } return sensorOp.get(); } int DynamicSensorManager::operateSensor( int handle, OperateSensorFunc sensorFunc, uint64_t sensorOpIndex) { int rv = 0; // Wait until this sensor operation is at the head of the queue. while (1) { std::shared_future headSensorOp; { std::lock_guard lock(mSensorOpQueueLock); if (mSensorOpQueue.front().first == sensorOpIndex) { break; } headSensorOp = mSensorOpQueue.front().second; } headSensorOp.wait(); } // Perform sensor operation. sp sensor; { std::lock_guard lk(mLock); const auto i = mMap.find(handle); if (i == mMap.end()) { rv = BAD_VALUE; } if (rv == 0) { sensor = i->second.promote(); if (sensor == nullptr) { // sensor object is already gone rv = BAD_VALUE; } } } if (rv == 0) { rv = sensorFunc(sensor); } // Remove sensor operation from queue. When the operation's shared state is // destroyed, execution of this function ceases. Thus, if the state is // destroyed when the operation is removed from the queue, the lock will // never be released. To prevent that, the state is shared locally, so it // isn't destroyed until this function completes. std::shared_future sensorOp; { std::lock_guard lock(mSensorOpQueueLock); sensorOp = mSensorOpQueue.front().second; mSensorOpQueue.pop(); } return rv; } DynamicSensorManager::ConnectionReport::ConnectionReport( int handle, sp 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