Merge "Dynamic sensor manager -- implementation of basic sensor daemon" into oc-dev am: 7c371eb532
am: 2fa64e81e1
Change-Id: Id846a254e47ab6c465a909e083d5c22dab29bfef
This commit is contained in:
commit
c6fccf3fd4
10 changed files with 627 additions and 3 deletions
10
CleanSpec.mk
10
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
|
||||
# ************************************************
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
56
modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.cpp
Normal file
56
modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.cpp
Normal file
|
@ -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<BaseSensorObject>(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
|
||||
|
|
@ -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 <utils/RefBase.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
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<std::string, sp<BaseSensorObject> > mDevices;
|
||||
};
|
||||
|
||||
} // namespace SensorHalExt
|
||||
|
|
215
modules/sensors/dynamic_sensor/ConnectionDetector.cpp
Normal file
215
modules/sensors/dynamic_sensor/ConnectionDetector.cpp
Normal file
|
@ -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 <utils/Log.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
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
|
81
modules/sensors/dynamic_sensor/ConnectionDetector.h
Normal file
81
modules/sensors/dynamic_sensor/ConnectionDetector.h
Normal file
|
@ -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 <utils/Thread.h>
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
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
|
171
modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp
Normal file
171
modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp
Normal file
|
@ -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
|
||||
|
73
modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.h
Normal file
73
modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.h
Normal file
|
@ -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 <hardware/sensors.h>
|
||||
#include <utils/Thread.h>
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
|
||||
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<ConnectionDetector> mFileDetector;
|
||||
sp<ConnectionDetector> mSocketDetector;
|
||||
};
|
||||
} // namespace SensorHalExt
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_SENSORHAL_EXT_DYNAMIC_SENSOR_DAEMON_H
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "BaseDynamicSensorDaemon.h"
|
||||
#include "BaseSensorObject.h"
|
||||
#include "DummyDynamicAccelDaemon.h"
|
||||
#include "DynamicSensorManager.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue