diff options
author | Peng Xu <pengxu@google.com> | 2017-01-20 14:24:39 -0800 |
---|---|---|
committer | Peng Xu <pengxu@google.com> | 2017-04-07 20:54:18 +0000 |
commit | 18082bd61fffd120100ea93fd94538492b39d7bd (patch) | |
tree | eb6ac172af752398b7f8a715195ef58e0ffc43a6 /modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp | |
parent | 3623fbace2d01c89411b00d930372831eb9e9957 (diff) |
Dynamic sensor manager -- implementation of basic sensor daemon
Library to handle dynamic sensor connection. There are two way to use
this: as hal extension or standalone hal module.
In hal extension mode: add libdynamic_sensor_ext in dependency of hal,
instantiate DynamicSensorManager with appropriate parameters. Then
for all sensor requests, if the handle is owned by dynamic sensor
manager, forward the request.
In standalone mode, add sensor.dynamic_sensor_hal into device make
file. Usually, this also means multihal is necessary. Add
sensor.dynamic_sensor_hal into multihal configuration file.
A dummy sensor module is included for testing.
Test: tested with cts dynamics sensor related test and demo app.
also verified sensor basic operation with sensor logger.
Change-Id: I16612935fc21b06c173aca875401ece37c6bde01
Diffstat (limited to 'modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp')
-rw-r--r-- | modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp b/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp new file mode 100644 index 00000000..19779678 --- /dev/null +++ b/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp @@ -0,0 +1,171 @@ +/* + * 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 "BaseSensorObject.h" +#include "ConnectionDetector.h" +#include "DummyDynamicAccelDaemon.h" +#include "DynamicSensorManager.h" + +#include <cutils/properties.h> +#include <utils/Log.h> +#include <utils/SystemClock.h> +#include <utils/misc.h> + +#include <sys/socket.h> +#include <netinet/in.h> +#include <algorithm> //std::max + +#define SYSPROP_PREFIX "dynamic_sensor.dummy" +#define FILE_NAME_BASE "dummy_accel_file" +#define FILE_NAME_REGEX ("^" FILE_NAME_BASE "[0-9]$") + +namespace android { +namespace SensorHalExt { + +DummyDynamicAccelDaemon::DummyDynamicAccelDaemon(DynamicSensorManager& manager) + : BaseDynamicSensorDaemon(manager) { + char property[PROPERTY_VALUE_MAX+1]; + + property_get(SYSPROP_PREFIX ".file", property, ""); + if (strcmp(property, "") != 0) { + mFileDetector = new FileConnectionDetector( + this, std::string(property), std::string(FILE_NAME_REGEX)); + } + + property_get(SYSPROP_PREFIX ".socket", property, ""); + if (strcmp(property, "") != 0) { + mSocketDetector = new SocketConnectionDetector(this, atoi(property)); + } +} + +BaseSensorObject * DummyDynamicAccelDaemon::createSensor(const std::string &deviceKey) { + if (deviceKey.compare(0, 1, "/") == 0) { + // file detector result, deviceKey is file absolute path + size_t start = std::max(static_cast<size_t>(0), + deviceKey.length() - (::strlen(FILE_NAME_BASE) + 1)); + return new DummySensor(deviceKey.substr(start)); + + } else if (deviceKey.compare(0, ::strlen("socket:"), "socket:") == 0) { + return new DummySensor(deviceKey); + } else { + // unknown deviceKey + return nullptr; + } +} + +DummyDynamicAccelDaemon::DummySensor::DummySensor(const std::string &name) : mRunState(false) { + mSensorName = "Dummy Accel - " + name; + mSensor = (struct sensor_t) { + mSensorName.c_str(), + "DemoSense, Inc.", + 1, // version + -1, // handle, dummy number here + SENSOR_TYPE_ACCELEROMETER, + 9.8 * 8.0f, // maxRange + 9.8 * 8.0f / 32768.0f, // resolution + 0.5f, // power + (int32_t)(1.0E6f / 50), // minDelay + 0, // fifoReservedEventCount + 0, // fifoMaxEventCount + SENSOR_STRING_TYPE_ACCELEROMETER, + "", // requiredPermission + (long)(1.0E6f / 50), // maxDelay + SENSOR_FLAG_CONTINUOUS_MODE, + { NULL, NULL } + }; + mRunLock.lock(); + run("DummySensor"); +} + +DummyDynamicAccelDaemon::DummySensor::~DummySensor() { + requestExitAndWait(); + // unlock mRunLock so thread can be unblocked + mRunLock.unlock(); +} + +const sensor_t* DummyDynamicAccelDaemon::DummySensor::getSensor() const { + return &mSensor; +} + +void DummyDynamicAccelDaemon::DummySensor::getUuid(uint8_t* uuid) const { + // at maximum, there will be always one instance, so we can hardcode + size_t hash = std::hash<std::string>()(mSensorName); + memset(uuid, 'x', 16); + memcpy(uuid, &hash, sizeof(hash)); +} + +int DummyDynamicAccelDaemon::DummySensor::enable(bool enable) { + std::lock_guard<std::mutex> lk(mLock); + if (mRunState != enable) { + if (enable) { + mRunLock.unlock(); + } else { + mRunLock.lock(); + } + mRunState = enable; + } + return 0; +} + +int DummyDynamicAccelDaemon::DummySensor::batch(nsecs_t, nsecs_t) { + return 0; +} + +void DummyDynamicAccelDaemon::DummySensor::waitUntilNextSample() { + // block when disabled (mRunLock locked) + mRunLock.lock(); + mRunLock.unlock(); + + if (!Thread::exitPending()) { + // sleep 20 ms (50Hz) + usleep(20000); + } +} + +bool DummyDynamicAccelDaemon::DummySensor::threadLoop() { + // designated intialization will leave the unspecified fields zeroed + sensors_event_t event = { + .version = sizeof(event), + .sensor = -1, + .type = SENSOR_TYPE_ACCELEROMETER, + }; + + int64_t startTimeNs = elapsedRealtimeNano(); + + ALOGI("Dynamic Dummy Accel started for sensor %s", mSensorName.c_str()); + while (!Thread::exitPending()) { + waitUntilNextSample(); + + if (Thread::exitPending()) { + break; + } + int64_t nowTimeNs = elapsedRealtimeNano(); + float t = (nowTimeNs - startTimeNs) / 1e9f; + + event.data[0] = 2 * ::sin(3 * M_PI * t); + event.data[1] = 3 * ::cos(3 * M_PI * t); + event.data[2] = 1.5 * ::sin(6 * M_PI * t); + event.timestamp = nowTimeNs; + generateEvent(event); + } + + ALOGI("Dynamic Dummy Accel thread ended for sensor %s", mSensorName.c_str()); + return false; +} + +} // namespace SensorHalExt +} // namespace android + |