/* * Copyright (C) 2015 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. */ #define LOG_TAG "sensors" #define LOG_NDEBUG 1 #include <utils/Log.h> #include "hubconnection.h" #include "sensorlist.h" #include "sensors.h" #include <cutils/ashmem.h> #include <errno.h> #include <math.h> #include <media/stagefright/foundation/ADebug.h> #include <string.h> #include <sys/mman.h> #include <stdlib.h> #ifdef DYNAMIC_SENSOR_EXT_ENABLED #include <DynamicSensorManager.h> #include <SensorEventCallback.h> #endif using namespace android; //////////////////////////////////////////////////////////////////////////////// SensorContext::SensorContext(const struct hw_module_t *module) : mSensorList(kSensorList, kSensorList + kSensorCount), mHubConnection(HubConnection::getInstance()) { memset(&device, 0, sizeof(device)); device.common.tag = HARDWARE_DEVICE_TAG; device.common.version = SENSORS_DEVICE_API_VERSION_1_4; device.common.module = const_cast<hw_module_t *>(module); device.common.close = CloseWrapper; device.activate = ActivateWrapper; device.setDelay = SetDelayWrapper; device.poll = PollWrapper; device.batch = BatchWrapper; device.flush = FlushWrapper; device.inject_sensor_data = InjectSensorDataWrapper; mHubConnection->setRawScale(kScaleAccel, kScaleMag); if (mHubConnection->isDirectReportSupported()) { device.register_direct_channel = RegisterDirectChannelWrapper; device.config_direct_report = ConfigDirectReportWrapper; } mOperationHandler.emplace_back(new HubConnectionOperation(mHubConnection)); initializeHalExtension(); } int SensorContext::close() { ALOGV("close"); delete this; return 0; } int SensorContext::activate(int handle, int enabled) { ALOGV("activate"); for (auto &h : mOperationHandler) { if (h->owns(handle)) { return h->activate(handle, enabled); } } return INVALID_OPERATION; } int SensorContext::setDelay(int handle, int64_t delayNs) { ALOGV("setDelay"); for (auto &h: mOperationHandler) { if (h->owns(handle)) { return h->setDelay(handle, delayNs); } } return INVALID_OPERATION; } int SensorContext::poll(sensors_event_t *data, int count) { ALOGV("poll"); // Release wakelock if held and no more events in ring buffer mHubConnection->releaseWakeLockIfAppropriate(); ssize_t n = mHubConnection->read(data, count); if (n < 0) { return -1; } // If we have wake events in the queue, determine how many we're sending // up this round and decrement that count now so that when we get called back, // we'll have an accurate count of how many wake events are STILL in the HAL queue // to be able to determine whether we can release our wakelock if held. if (mHubConnection->getWakeEventCount() != 0) { for (ssize_t i = 0; i < n; i++) { if (mHubConnection->isWakeEvent(data[i].sensor)) { ssize_t count = mHubConnection->decrementWakeEventCount(); if (count == 0) { break; } } } } return n; } int SensorContext::batch( int handle, int64_t sampling_period_ns, int64_t max_report_latency_ns) { ALOGV("batch"); for (auto &h : mOperationHandler) { if (h->owns(handle)) { return h->batch(handle, sampling_period_ns, max_report_latency_ns); } } return INVALID_OPERATION; } int SensorContext::flush(int handle) { ALOGV("flush"); for (auto &h : mOperationHandler) { if (h->owns(handle)) { return h->flush(handle); } } return INVALID_OPERATION; } int SensorContext::register_direct_channel( const struct sensors_direct_mem_t *mem, int32_t channel_handle) { if (mem) { //add return mHubConnection->addDirectChannel(mem); } else { //remove mHubConnection->removeDirectChannel(channel_handle); return NO_ERROR; } } int SensorContext::config_direct_report( int32_t sensor_handle, int32_t channel_handle, const struct sensors_direct_cfg_t * config) { int rate_level = config->rate_level; return mHubConnection->configDirectReport(sensor_handle, channel_handle, rate_level); } // static int SensorContext::CloseWrapper(struct hw_device_t *dev) { return reinterpret_cast<SensorContext *>(dev)->close(); } // static int SensorContext::ActivateWrapper( struct sensors_poll_device_t *dev, int handle, int enabled) { return reinterpret_cast<SensorContext *>(dev)->activate(handle, enabled); } // static int SensorContext::SetDelayWrapper( struct sensors_poll_device_t *dev, int handle, int64_t delayNs) { return reinterpret_cast<SensorContext *>(dev)->setDelay(handle, delayNs); } // static int SensorContext::PollWrapper( struct sensors_poll_device_t *dev, sensors_event_t *data, int count) { return reinterpret_cast<SensorContext *>(dev)->poll(data, count); } // static int SensorContext::BatchWrapper( struct sensors_poll_device_1 *dev, int handle, int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns) { (void) flags; return reinterpret_cast<SensorContext *>(dev)->batch( handle, sampling_period_ns, max_report_latency_ns); } // static int SensorContext::FlushWrapper(struct sensors_poll_device_1 *dev, int handle) { return reinterpret_cast<SensorContext *>(dev)->flush(handle); } // static int SensorContext::RegisterDirectChannelWrapper(struct sensors_poll_device_1 *dev, const struct sensors_direct_mem_t* mem, int channel_handle) { return reinterpret_cast<SensorContext *>(dev)->register_direct_channel( mem, channel_handle); } // static int SensorContext::ConfigDirectReportWrapper(struct sensors_poll_device_1 *dev, int sensor_handle, int channel_handle, const sensors_direct_cfg_t * config) { return reinterpret_cast<SensorContext *>(dev)->config_direct_report( sensor_handle, channel_handle, config); } int SensorContext::inject_sensor_data(const sensors_event_t *event) { ALOGV("inject_sensor_data"); // only support set operation parameter, which will have handle == 0 if (event == nullptr || event->type != SENSOR_TYPE_ADDITIONAL_INFO) { return -EINVAL; } if (event->sensor != SENSORS_HANDLE_BASE - 1) { return -ENOSYS; } if (event->additional_info.type == AINFO_BEGIN || event->additional_info.type == AINFO_END) { return 0; } mHubConnection->setOperationParameter(event->additional_info); return 0; } // static int SensorContext::InjectSensorDataWrapper(struct sensors_poll_device_1 *dev, const struct sensors_event_t *event) { return reinterpret_cast<SensorContext *>(dev)->inject_sensor_data(event); } bool SensorContext::getHubAlive() { return (mHubConnection->initCheck() == OK && mHubConnection->getAliveCheck() == OK); } size_t SensorContext::getSensorList(sensor_t const **list) { ALOGE("sensor p = %p, n = %zu", mSensorList.data(), mSensorList.size()); *list = mSensorList.data(); return mSensorList.size(); } // HubConnectionOperation functions SensorContext::HubConnectionOperation::HubConnectionOperation(sp<HubConnection> hubConnection) : mHubConnection(hubConnection) { for (size_t i = 0; i < kSensorCount; i++) { mHandles.emplace(kSensorList[i].handle); } } bool SensorContext::HubConnectionOperation::owns(int handle) { return mHandles.find(handle) != mHandles.end(); } int SensorContext::HubConnectionOperation::activate(int handle, int enabled) { mHubConnection->queueActivate(handle, enabled); return 0; } int SensorContext::HubConnectionOperation::setDelay(int handle, int64_t delayNs) { // clamp sample rate based on minDelay and maxDelay defined in kSensorList int64_t delayNsClamped = delayNs; for (size_t i = 0; i < kSensorCount; i++) { sensor_t sensor = kSensorList[i]; if (sensor.handle != handle) { continue; } if ((sensor.flags & REPORTING_MODE_MASK) == SENSOR_FLAG_CONTINUOUS_MODE) { if ((delayNs/1000) < sensor.minDelay) { delayNsClamped = sensor.minDelay * 1000; } else if ((delayNs/1000) > sensor.maxDelay) { delayNsClamped = sensor.maxDelay * 1000; } } break; } mHubConnection->queueSetDelay(handle, delayNsClamped); return 0; } int SensorContext::HubConnectionOperation::batch( int handle, int64_t sampling_period_ns, int64_t max_report_latency_ns) { // clamp sample rate based on minDelay and maxDelay defined in kSensorList int64_t sampling_period_ns_clamped = sampling_period_ns; for (size_t i = 0; i < kSensorCount; i++) { sensor_t sensor = kSensorList[i]; if (sensor.handle != handle) { continue; } if ((sensor.flags & REPORTING_MODE_MASK) == SENSOR_FLAG_CONTINUOUS_MODE) { if ((sampling_period_ns/1000) < sensor.minDelay) { sampling_period_ns_clamped = sensor.minDelay * 1000; } else if ((sampling_period_ns/1000) > sensor.maxDelay) { sampling_period_ns_clamped = sensor.maxDelay * 1000; } } break; } mHubConnection->queueBatch(handle, sampling_period_ns_clamped, max_report_latency_ns); return 0; } int SensorContext::HubConnectionOperation::flush(int handle) { mHubConnection->queueFlush(handle); return 0; } #ifdef DYNAMIC_SENSOR_EXT_ENABLED namespace { // adaptor class class Callback : public SensorEventCallback { public: Callback(sp<HubConnection> hubConnection) : mHubConnection(hubConnection) {} virtual int submitEvent(sp<BaseSensorObject> source, const sensors_event_t &e) override; private: sp<HubConnection> mHubConnection; }; int Callback::submitEvent(sp<BaseSensorObject> source, const sensors_event_t &e) { (void) source; // irrelavent in this context return (mHubConnection->write(&e, 1) == 1) ? 0 : -ENOSPC; } } // anonymous namespace SensorContext::DynamicSensorManagerOperation::DynamicSensorManagerOperation(DynamicSensorManager* manager) : mDynamicSensorManager(manager) { } bool SensorContext::DynamicSensorManagerOperation::owns(int handle) { return mDynamicSensorManager->owns(handle); } int SensorContext::DynamicSensorManagerOperation::activate(int handle, int enabled) { return mDynamicSensorManager->activate(handle, enabled); } int SensorContext::DynamicSensorManagerOperation::setDelay(int handle, int64_t delayNs) { return mDynamicSensorManager->setDelay(handle, delayNs); } int SensorContext::DynamicSensorManagerOperation::batch(int handle, int64_t sampling_period_ns, int64_t max_report_latency_ns) { return mDynamicSensorManager->batch(handle, sampling_period_ns, max_report_latency_ns); } int SensorContext::DynamicSensorManagerOperation::flush(int handle) { return mDynamicSensorManager->flush(handle); } #endif void SensorContext::initializeHalExtension() { #ifdef DYNAMIC_SENSOR_EXT_ENABLED // initialize callback and dynamic sensor manager mEventCallback.reset(new Callback(mHubConnection)); DynamicSensorManager* manager = DynamicSensorManager::createInstance( kDynamicHandleBase, kMaxDynamicHandleCount, mEventCallback.get()); // add meta sensor to list mSensorList.push_back(manager->getDynamicMetaSensor()); // register operation mOperationHandler.emplace_back(new DynamicSensorManagerOperation(manager)); #endif } //////////////////////////////////////////////////////////////////////////////// static bool gHubAlive; static sensor_t const *sensor_list; static int n_sensor; static int open_sensors( const struct hw_module_t *module, const char *, struct hw_device_t **dev) { ALOGV("open_sensors"); SensorContext *ctx = new SensorContext(module); n_sensor = ctx->getSensorList(&sensor_list); gHubAlive = ctx->getHubAlive(); *dev = &ctx->device.common; return 0; } static struct hw_module_methods_t sensors_module_methods = { .open = open_sensors }; static int get_sensors_list( struct sensors_module_t *, struct sensor_t const **list) { ALOGV("get_sensors_list"); if (gHubAlive && sensor_list != nullptr) { *list = sensor_list; return n_sensor; } else { *list = {}; return 0; } } static int set_operation_mode(unsigned int mode) { ALOGV("set_operation_mode"); // This is no-op because there is no sensor in the hal that system can // inject events. Only operation parameter injection is implemented, which // works in both data injection and normal mode. (void) mode; return 0; } struct sensors_module_t HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = SENSORS_HARDWARE_MODULE_ID, .name = "Google Sensor module", .author = "Google", .methods = &sensors_module_methods, .dso = NULL, .reserved = {0}, }, .get_sensors_list = get_sensors_list, .set_operation_mode = set_operation_mode, };