Merge changes Ia4eb5378,I745031b8 into oc-dev
* changes:
Mark as vendor_available
Export headers as libhardware_headers
diff --git a/Android.bp b/Android.bp
index 1646bfe..739cb6d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,6 +15,7 @@
"liblog",
"libdl",
],
+ header_libs: ["libsystem_headers"],
cflags: ["-DQEMU_HARDWARE"],
export_include_dirs: ["include"],
vendor_available: true,
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b84e1b6..1c64bfc 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/hardware.c b/hardware.c
index 5394787..7e4debe 100644
--- a/hardware.c
+++ b/hardware.c
@@ -23,9 +23,11 @@
#include <pthread.h>
#include <errno.h>
#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
#define LOG_TAG "HAL"
-#include <utils/Log.h>
+#include <log/log.h>
/** Base path of the hal modules */
#if defined(__LP64__)
diff --git a/include/hardware/hwcomposer2.h b/include/hardware/hwcomposer2.h
index 35eedb0..d5a0d6f 100644
--- a/include/hardware/hwcomposer2.h
+++ b/include/hardware/hwcomposer2.h
@@ -94,6 +94,16 @@
* the client. This will prevent the client from applying the color
* transform during its composition step. */
HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM = 2,
+
+ /* Specifies that the present fence must not be used as an accurate
+ * representation of the actual present time of a frame.
+ * This capability must never be set by HWC2 devices.
+ * This capability may be set for HWC1 devices that use the
+ * HWC2On1Adapter where emulation of the present fence using the retire
+ * fence is not feasible.
+ * In the future, CTS tests will require present time to be reliable.
+ */
+ HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE = 3,
} hwc2_capability_t;
/* Possible composition types for a given layer */
@@ -335,6 +345,8 @@
case HWC2_CAPABILITY_SIDEBAND_STREAM: return "SidebandStream";
case HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM:
return "SkipClientColorTransform";
+ case HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE:
+ return "PresentFenceIsNotReliable";
default: return "Unknown";
}
}
@@ -551,6 +563,7 @@
Invalid = HWC2_CAPABILITY_INVALID,
SidebandStream = HWC2_CAPABILITY_SIDEBAND_STREAM,
SkipClientColorTransform = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM,
+ PresentFenceIsNotReliable = HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE,
};
TO_STRING(hwc2_capability_t, Capability, getCapabilityName)
diff --git a/include/hardware/sensors.h b/include/hardware/sensors.h
index 8c5fa16..92a8fd9 100644
--- a/include/hardware/sensors.h
+++ b/include/hardware/sensors.h
@@ -701,7 +701,7 @@
int sensor_handle, int channel_handle, const struct sensors_direct_cfg_t *config);
/*
- * Reserved for future use.
+ * Reserved for future use, must be zero.
*/
void (*reserved_procs[5])(void);
diff --git a/modules/consumerir/Android.bp b/modules/consumerir/Android.bp
index 2bbdc04..b139492 100644
--- a/modules/consumerir/Android.bp
+++ b/modules/consumerir/Android.bp
@@ -19,6 +19,5 @@
srcs: ["consumerir.c"],
shared_libs: [
"liblog",
- "libcutils",
],
}
diff --git a/modules/consumerir/consumerir.c b/modules/consumerir/consumerir.c
index b0ff940..2af6b89 100644
--- a/modules/consumerir/consumerir.c
+++ b/modules/consumerir/consumerir.c
@@ -18,7 +18,7 @@
#include <errno.h>
#include <malloc.h>
#include <string.h>
-#include <cutils/log.h>
+#include <log/log.h>
#include <hardware/hardware.h>
#include <hardware/consumerir.h>
diff --git a/modules/sensors/dynamic_sensor/Android.mk b/modules/sensors/dynamic_sensor/Android.mk
index 07bc5e8..38a658a 100644
--- a/modules/sensors/dynamic_sensor/Android.mk
+++ b/modules/sensors/dynamic_sensor/Android.mk
@@ -33,11 +33,15 @@
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_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_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 0000000..f5f642c
--- /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<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
+
diff --git a/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.h b/modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.h
index 29cf7a4..b698b7d 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 <utils/RefBase.h>
+#include <string>
+#include <unordered_map>
namespace android {
namespace SensorHalExt {
@@ -28,8 +32,13 @@
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
diff --git a/modules/sensors/dynamic_sensor/ConnectionDetector.cpp b/modules/sensors/dynamic_sensor/ConnectionDetector.cpp
new file mode 100644
index 0000000..6099493
--- /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 <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
diff --git a/modules/sensors/dynamic_sensor/ConnectionDetector.h b/modules/sensors/dynamic_sensor/ConnectionDetector.h
new file mode 100644
index 0000000..712d832
--- /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 <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
diff --git a/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp b/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp
new file mode 100644
index 0000000..1977967
--- /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
+
diff --git a/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.h b/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.h
new file mode 100644
index 0000000..0bffbee
--- /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 <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
+
diff --git a/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp b/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp
index d33650c..eb4903d 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 <utils/Log.h>
@@ -29,6 +30,7 @@
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 be42b67..2fd8708 100644
--- a/modules/sensors/dynamic_sensor/sensors.h
+++ b/modules/sensors/dynamic_sensor/sensors.h
@@ -75,7 +75,6 @@
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;