/* * 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