From 18082bd61fffd120100ea93fd94538492b39d7bd Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Fri, 20 Jan 2017 14:24:39 -0800 Subject: [PATCH] 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 --- CleanSpec.mk | 10 + modules/sensors/dynamic_sensor/Android.mk | 10 +- .../BaseDynamicSensorDaemon.cpp | 56 +++++ .../dynamic_sensor/BaseDynamicSensorDaemon.h | 11 +- .../dynamic_sensor/ConnectionDetector.cpp | 215 ++++++++++++++++++ .../dynamic_sensor/ConnectionDetector.h | 81 +++++++ .../DummyDynamicAccelDaemon.cpp | 171 ++++++++++++++ .../dynamic_sensor/DummyDynamicAccelDaemon.h | 73 ++++++ .../dynamic_sensor/DynamicSensorManager.cpp | 2 + modules/sensors/dynamic_sensor/sensors.h | 1 - 10 files changed, 627 insertions(+), 3 deletions(-) create mode 100644 modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.cpp create mode 100644 modules/sensors/dynamic_sensor/ConnectionDetector.cpp create mode 100644 modules/sensors/dynamic_sensor/ConnectionDetector.h create mode 100644 modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp create mode 100644 modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.h diff --git a/CleanSpec.mk b/CleanSpec.mk index b84e1b65..1c64bfc4 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -47,3 +47,13 @@ # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ + +$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib/libdynamic_sensor_ext.so) +$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib64/libdynamic_sensor_ext.so) +$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib/hw/sensors.dynamic_sensor_hal.so) +$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib64/hw/sensors.dynamic_sensor_hal.so) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + diff --git a/modules/sensors/dynamic_sensor/Android.mk b/modules/sensors/dynamic_sensor/Android.mk index 07bc5e8c..38a658aa 100644 --- a/modules/sensors/dynamic_sensor/Android.mk +++ b/modules/sensors/dynamic_sensor/Android.mk @@ -33,11 +33,15 @@ include $(CLEAR_VARS) LOCAL_MODULE := libdynamic_sensor_ext LOCAL_MODULE_TAGS := optional LOCAL_MODULE_OWNER := google +LOCAL_PROPRIETARY_MODULE := true LOCAL_CFLAGS += $(COMMON_CFLAGS) -DLOG_TAG=\"DynamicSensorExt\" LOCAL_SRC_FILES := \ + BaseDynamicSensorDaemon.cpp \ BaseSensorObject.cpp \ + ConnectionDetector.cpp \ + DummyDynamicAccelDaemon.cpp \ DynamicSensorManager.cpp \ RingBuffer.cpp @@ -58,11 +62,15 @@ LOCAL_MODULE := sensors.dynamic_sensor_hal LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_MODULE_TAGS := optional LOCAL_MODULE_OWNER := google +LOCAL_PROPRIETARY_MODULE := true LOCAL_CFLAGS += $(COMMON_CFLAGS) -DLOG_TAG=\"DynamicSensorHal\" LOCAL_SRC_FILES := \ + BaseDynamicSensorDaemon.cpp \ BaseSensorObject.cpp \ + ConnectionDetector.cpp \ + DummyDynamicAccelDaemon.cpp \ DynamicSensorManager.cpp \ RingBuffer.cpp \ sensors.cpp @@ -70,7 +78,7 @@ LOCAL_SRC_FILES := \ LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ - liblog \ + liblog LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) diff --git a/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.cpp b/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.cpp new file mode 100644 index 00000000..f5f642ce --- /dev/null +++ b/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.cpp @@ -0,0 +1,56 @@ +/* + * 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 "DynamicSensorManager.h" +#include "utils/Log.h" + +namespace android { +namespace SensorHalExt { + +bool BaseDynamicSensorDaemon::onConnectionChange(const std::string &deviceKey, bool connected) { + bool ret = false; + auto i = mDevices.find(deviceKey); + if (connected) { + if (i == mDevices.end()) { + ALOGV("device %s is connected", deviceKey.c_str()); + BaseSensorObject* s = createSensor(deviceKey); + if (s) { + mDevices.emplace(deviceKey, sp(s)); + mManager.registerSensor(s); + ALOGV("device %s is registered", deviceKey.c_str()); + ret = true; + } + } else { + ALOGD("device %s already added and is connected again, ignore", deviceKey.c_str()); + } + } else { + ALOGV("device %s is disconnected", deviceKey.c_str()); + if (i != mDevices.end()) { + mManager.unregisterSensor(i->second.get()); + mDevices.erase(i); + ALOGV("device %s is unregistered", deviceKey.c_str()); + ret = true; + } else { + ALOGD("device not found in registry"); + } + } + + return ret; +} +} // namespace SensorHalExt +} // namespace android + diff --git a/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.h b/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.h index 29cf7a47..b698b7d5 100644 --- a/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.h +++ b/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.h @@ -17,7 +17,11 @@ #ifndef ANDROID_SENSORHAL_EXT_BASE_DYNAMIC_SENSOR_DAEMON_H #define ANDROID_SENSORHAL_EXT_BASE_DYNAMIC_SENSOR_DAEMON_H +#include "BaseSensorObject.h" + #include +#include +#include namespace android { namespace SensorHalExt { @@ -28,8 +32,13 @@ class BaseDynamicSensorDaemon : public RefBase { public: BaseDynamicSensorDaemon(DynamicSensorManager& manager) : mManager(manager) {} virtual ~BaseDynamicSensorDaemon() = default; + + virtual bool onConnectionChange(const std::string &deviceKey, bool connected); protected: - DynamicSensorManager& mManager; + virtual BaseSensorObject * createSensor(const std::string &deviceKey) = 0; + + DynamicSensorManager &mManager; + std::unordered_map > mDevices; }; } // namespace SensorHalExt diff --git a/modules/sensors/dynamic_sensor/ConnectionDetector.cpp b/modules/sensors/dynamic_sensor/ConnectionDetector.cpp new file mode 100644 index 00000000..60994930 --- /dev/null +++ b/modules/sensors/dynamic_sensor/ConnectionDetector.cpp @@ -0,0 +1,215 @@ +/* + * 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 "ConnectionDetector.h" + +#include + +#include +#include +#include +#include +#include + +#include + +namespace android { +namespace SensorHalExt { + +// SocketConnectionDetector functions +SocketConnectionDetector::SocketConnectionDetector(BaseDynamicSensorDaemon *d, int port) + : ConnectionDetector(d) { + // initialize socket that accept connection to localhost:port + mListenFd = ::socket(AF_INET, SOCK_STREAM, 0); + if (mListenFd < 0) { + ALOGE("Cannot open socket"); + return; + } + + struct sockaddr_in serverAddress = { + .sin_family = AF_INET, + .sin_port = htons(port), + .sin_addr = { + .s_addr = htonl(INADDR_LOOPBACK) + } + }; + + ::bind(mListenFd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)); + if (::listen(mListenFd, 0) != NO_ERROR) { + ALOGE("Cannot listen to port %d", port); + mListenFd = -1; + return; + } + + std::ostringstream s; + s << "socket:" << port; + mDevice = s.str(); + + run("ddad_socket"); +} + +SocketConnectionDetector::~SocketConnectionDetector() { + if (mListenFd >= 0) { + requestExitAndWait(); + } +} + +int SocketConnectionDetector::waitForConnection() { + return ::accept(mListenFd, nullptr, nullptr); +} + +void SocketConnectionDetector::waitForDisconnection(int connFd) { + char buffer[16]; + while (::read(connFd, buffer, sizeof(buffer)) > 0) { + // discard data but response something to denote thread alive + ::write(connFd, ".", 1); + } + // read failure means disconnection + ::close(connFd); +} + +bool SocketConnectionDetector::threadLoop() { + while (!Thread::exitPending()) { + // block waiting for connection + int connFd = waitForConnection(); + + if (connFd < 0) { + break; + } + + ALOGV("Received connection, register dynamic accel sensor"); + mDaemon->onConnectionChange(mDevice, true); + + waitForDisconnection(connFd); + ALOGV("Connection break, unregister dynamic accel sensor"); + mDaemon->onConnectionChange(mDevice, false); + } + mDaemon->onConnectionChange(mDevice, false); + ALOGD("SocketConnectionDetector thread exited"); + return false; +} + +// FileConnectionDetector functions +FileConnectionDetector::FileConnectionDetector ( + BaseDynamicSensorDaemon *d, const std::string &path, const std::string ®ex) + : ConnectionDetector(d), mPath(path), mRegex(regex) { + mInotifyFd = ::inotify_init1(IN_NONBLOCK); + if (mInotifyFd < 0) { + ALOGE("Cannot init inotify"); + return; + } + + int wd = ::inotify_add_watch(mInotifyFd, path.c_str(), IN_CREATE | IN_DELETE | IN_MOVED_FROM); + if (wd < 0) { + ::close(mInotifyFd); + mInotifyFd = -1; + ALOGE("Cannot setup watch on dir %s", path.c_str()); + return; + } + + mPollFd.fd = wd; + mPollFd.events = POLLIN; + + run("ddad_file"); +} + +FileConnectionDetector::~FileConnectionDetector() { + if (mInotifyFd) { + requestExitAndWait(); + ::close(mInotifyFd); + } +} + +bool FileConnectionDetector::matches(const std::string &name) const { + return std::regex_match(name, mRegex); +} + +std::string FileConnectionDetector::getFullName(const std::string name) const { + return mPath + name; +} + +void FileConnectionDetector::processExistingFiles() const { + auto dirp = ::opendir(mPath.c_str()); + struct dirent *dp; + while ((dp = ::readdir(dirp)) != NULL) { + const std::string name(dp->d_name); + if (matches(name)) { + mDaemon->onConnectionChange(getFullName(name), true /*connected*/); + } + } + ::closedir(dirp); +} + +bool FileConnectionDetector::threadLoop() { + struct { + struct inotify_event e; + uint8_t padding[NAME_MAX + 1]; + } ev; + + processExistingFiles(); + + while (!Thread::exitPending()) { + int pollNum = ::poll(&mPollFd, 1, -1); + if (pollNum == -1) { + if (errno == EINTR) + continue; + ALOGE("inotify poll error: %s", ::strerror(errno)); + } + + if (pollNum > 0) { + if (! (mPollFd.revents & POLLIN)) { + continue; + } + + /* Inotify events are available */ + while (true) { + /* Read some events. */ + ssize_t len = ::read(mInotifyFd, &ev, sizeof ev); + if (len == -1 && errno != EAGAIN) { + ALOGE("read error: %s", ::strerror(errno)); + requestExit(); + break; + } + + /* If the nonblocking read() found no events to read, then + it returns -1 with errno set to EAGAIN. In that case, + we exit the loop. */ + if (len <= 0) { + break; + } + + if (ev.e.len && !(ev.e.mask & IN_ISDIR)) { + const std::string name(ev.e.name); + ALOGV("device %s state changed", name.c_str()); + if (matches(name)) { + if (ev.e.mask & IN_CREATE) { + mDaemon->onConnectionChange(getFullName(name), true /* connected*/); + } + + if (ev.e.mask & IN_DELETE || ev.e.mask & IN_MOVED_FROM) { + mDaemon->onConnectionChange(getFullName(name), false /* connected*/); + } + } + } + } + } + } + + ALOGD("FileConnectionDetection thread exited"); + return false; +} +} // namespace SensorHalExt +} // namespace android diff --git a/modules/sensors/dynamic_sensor/ConnectionDetector.h b/modules/sensors/dynamic_sensor/ConnectionDetector.h new file mode 100644 index 00000000..712d832f --- /dev/null +++ b/modules/sensors/dynamic_sensor/ConnectionDetector.h @@ -0,0 +1,81 @@ +/* + * 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. + */ + +#ifndef ANDROID_SENSORHAL_EXT_CONNECTION_DETECTOR_H +#define ANDROID_SENSORHAL_EXT_CONNECTION_DETECTOR_H + +#include "BaseDynamicSensorDaemon.h" +#include + +#include + +#include + +namespace android { +namespace SensorHalExt { + +// Abstraction of connection detector: an entity that calls +// BaseDynamicSensorDaemon::onConnectionChange() when necessary. +class ConnectionDetector : virtual public RefBase { +public: + ConnectionDetector(BaseDynamicSensorDaemon *d) : mDaemon(d) { } + virtual ~ConnectionDetector() = default; +protected: + BaseDynamicSensorDaemon* mDaemon; +}; + +// Open a socket that listen to localhost:port and notify sensor daemon of connection and +// disconnection event when socket is connected or disconnected, respectively. Only one concurrent +// client is accepted. +class SocketConnectionDetector : public ConnectionDetector, public Thread { +public: + SocketConnectionDetector(BaseDynamicSensorDaemon *d, int port); + virtual ~SocketConnectionDetector(); +private: + // implement virtual of Thread + virtual bool threadLoop(); + int waitForConnection(); + static void waitForDisconnection(int connFd); + + int mListenFd; + std::string mDevice; +}; + +// Detect file change under path and notify sensor daemon of connection and disconnection event when +// file is created in or removed from the directory, respectively. +class FileConnectionDetector : public ConnectionDetector, public Thread { +public: + FileConnectionDetector( + BaseDynamicSensorDaemon *d, const std::string &path, const std::string ®ex); + virtual ~FileConnectionDetector(); +private: + // implement virtual of Thread + virtual bool threadLoop(); + + bool matches(const std::string &name) const; + void processExistingFiles() const; + std::string getFullName(const std::string name) const; + + std::string mPath; + std::regex mRegex; + int mInotifyFd; + struct pollfd mPollFd; +}; + +} // namespace SensorHalExt +} // namespace android + +#endif // ANDROID_SENSORHAL_EXT_DYNAMIC_SENSOR_DAEMON_H 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 +#include +#include +#include + +#include +#include +#include //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(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()(mSensorName); + memset(uuid, 'x', 16); + memcpy(uuid, &hash, sizeof(hash)); +} + +int DummyDynamicAccelDaemon::DummySensor::enable(bool enable) { + std::lock_guard 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 + diff --git a/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.h b/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.h new file mode 100644 index 00000000..0bffbee3 --- /dev/null +++ b/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.h @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#ifndef ANDROID_SENSORHAL_EXT_DUMMY_DYNAMIC_ACCEL_DAEMON_H +#define ANDROID_SENSORHAL_EXT_DUMMY_DYNAMIC_ACCEL_DAEMON_H + +#include "BaseDynamicSensorDaemon.h" +#include "BaseSensorObject.h" + +#include +#include +#include +#include + +namespace android { +namespace SensorHalExt { + +class ConnectionDetector; + +/** + * This daemon simulates dynamic sensor connection without the need of actually connect peripheral + * to Android. It is for debugging and testing. It can handle one concurrent connections at maximum. + */ +class DummyDynamicAccelDaemon : public BaseDynamicSensorDaemon { +public: + DummyDynamicAccelDaemon(DynamicSensorManager& manager); + virtual ~DummyDynamicAccelDaemon() = default; +private: + class DummySensor : public BaseSensorObject, public Thread { + public: + DummySensor(const std::string &name); + ~DummySensor(); + virtual const sensor_t* getSensor() const; + virtual void getUuid(uint8_t* uuid) const; + virtual int enable(bool enable); + virtual int batch(nsecs_t sample_period, nsecs_t batch_period); + private: + // implement Thread function + virtual bool threadLoop() override; + + void waitUntilNextSample(); + + sensor_t mSensor; + std::string mSensorName; + + std::mutex mLock; + std::mutex mRunLock; + bool mRunState; + }; + // implement BaseDynamicSensorDaemon function + BaseSensorObject * createSensor(const std::string &deviceKey) override; + + sp mFileDetector; + sp mSocketDetector; +}; +} // namespace SensorHalExt +} // namespace android + +#endif // ANDROID_SENSORHAL_EXT_DYNAMIC_SENSOR_DAEMON_H + diff --git a/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp b/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp index d33650cc..eb4903d2 100644 --- a/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp +++ b/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp @@ -16,6 +16,7 @@ #include "BaseDynamicSensorDaemon.h" #include "BaseSensorObject.h" +#include "DummyDynamicAccelDaemon.h" #include "DynamicSensorManager.h" #include @@ -29,6 +30,7 @@ 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)); return m; } diff --git a/modules/sensors/dynamic_sensor/sensors.h b/modules/sensors/dynamic_sensor/sensors.h index be42b67f..2fd8708d 100644 --- a/modules/sensors/dynamic_sensor/sensors.h +++ b/modules/sensors/dynamic_sensor/sensors.h @@ -75,7 +75,6 @@ private: static int FlushWrapper(struct sensors_poll_device_1 *dev, int handle); - // default ~16 million handles for dynamic sensor use, can be overriden by system property static constexpr int32_t kDynamicHandleBase = 0x10000; static constexpr int32_t kDynamicHandleEnd = 0x1000000; static constexpr int32_t kMaxDynamicHandleCount = kDynamicHandleEnd - kDynamicHandleBase;