Skip to content

Commit 18082bd

Browse files
committed
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
1 parent 3623fba commit 18082bd

File tree

10 files changed

+627
-3
lines changed

10 files changed

+627
-3
lines changed

CleanSpec.mk

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,13 @@
4747
# ************************************************
4848
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
4949
# ************************************************
50+
51+
$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib/libdynamic_sensor_ext.so)
52+
$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib64/libdynamic_sensor_ext.so)
53+
$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib/hw/sensors.dynamic_sensor_hal.so)
54+
$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib64/hw/sensors.dynamic_sensor_hal.so)
55+
56+
# ************************************************
57+
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
58+
# ************************************************
59+

modules/sensors/dynamic_sensor/Android.mk

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ include $(CLEAR_VARS)
3333
LOCAL_MODULE := libdynamic_sensor_ext
3434
LOCAL_MODULE_TAGS := optional
3535
LOCAL_MODULE_OWNER := google
36+
LOCAL_PROPRIETARY_MODULE := true
3637

3738
LOCAL_CFLAGS += $(COMMON_CFLAGS) -DLOG_TAG=\"DynamicSensorExt\"
3839

3940
LOCAL_SRC_FILES := \
41+
BaseDynamicSensorDaemon.cpp \
4042
BaseSensorObject.cpp \
43+
ConnectionDetector.cpp \
44+
DummyDynamicAccelDaemon.cpp \
4145
DynamicSensorManager.cpp \
4246
RingBuffer.cpp
4347

@@ -58,19 +62,23 @@ LOCAL_MODULE := sensors.dynamic_sensor_hal
5862
LOCAL_MODULE_RELATIVE_PATH := hw
5963
LOCAL_MODULE_TAGS := optional
6064
LOCAL_MODULE_OWNER := google
65+
LOCAL_PROPRIETARY_MODULE := true
6166

6267
LOCAL_CFLAGS += $(COMMON_CFLAGS) -DLOG_TAG=\"DynamicSensorHal\"
6368

6469
LOCAL_SRC_FILES := \
70+
BaseDynamicSensorDaemon.cpp \
6571
BaseSensorObject.cpp \
72+
ConnectionDetector.cpp \
73+
DummyDynamicAccelDaemon.cpp \
6674
DynamicSensorManager.cpp \
6775
RingBuffer.cpp \
6876
sensors.cpp
6977

7078
LOCAL_SHARED_LIBRARIES := \
7179
libcutils \
7280
libutils \
73-
liblog \
81+
liblog
7482

7583
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
7684

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (C) 2017 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "BaseDynamicSensorDaemon.h"
18+
#include "DynamicSensorManager.h"
19+
#include "utils/Log.h"
20+
21+
namespace android {
22+
namespace SensorHalExt {
23+
24+
bool BaseDynamicSensorDaemon::onConnectionChange(const std::string &deviceKey, bool connected) {
25+
bool ret = false;
26+
auto i = mDevices.find(deviceKey);
27+
if (connected) {
28+
if (i == mDevices.end()) {
29+
ALOGV("device %s is connected", deviceKey.c_str());
30+
BaseSensorObject* s = createSensor(deviceKey);
31+
if (s) {
32+
mDevices.emplace(deviceKey, sp<BaseSensorObject>(s));
33+
mManager.registerSensor(s);
34+
ALOGV("device %s is registered", deviceKey.c_str());
35+
ret = true;
36+
}
37+
} else {
38+
ALOGD("device %s already added and is connected again, ignore", deviceKey.c_str());
39+
}
40+
} else {
41+
ALOGV("device %s is disconnected", deviceKey.c_str());
42+
if (i != mDevices.end()) {
43+
mManager.unregisterSensor(i->second.get());
44+
mDevices.erase(i);
45+
ALOGV("device %s is unregistered", deviceKey.c_str());
46+
ret = true;
47+
} else {
48+
ALOGD("device not found in registry");
49+
}
50+
}
51+
52+
return ret;
53+
}
54+
} // namespace SensorHalExt
55+
} // namespace android
56+

modules/sensors/dynamic_sensor/BaseDynamicSensorDaemon.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717
#ifndef ANDROID_SENSORHAL_EXT_BASE_DYNAMIC_SENSOR_DAEMON_H
1818
#define ANDROID_SENSORHAL_EXT_BASE_DYNAMIC_SENSOR_DAEMON_H
1919

20+
#include "BaseSensorObject.h"
21+
2022
#include <utils/RefBase.h>
23+
#include <string>
24+
#include <unordered_map>
2125

2226
namespace android {
2327
namespace SensorHalExt {
@@ -28,8 +32,13 @@ class BaseDynamicSensorDaemon : public RefBase {
2832
public:
2933
BaseDynamicSensorDaemon(DynamicSensorManager& manager) : mManager(manager) {}
3034
virtual ~BaseDynamicSensorDaemon() = default;
35+
36+
virtual bool onConnectionChange(const std::string &deviceKey, bool connected);
3137
protected:
32-
DynamicSensorManager& mManager;
38+
virtual BaseSensorObject * createSensor(const std::string &deviceKey) = 0;
39+
40+
DynamicSensorManager &mManager;
41+
std::unordered_map<std::string, sp<BaseSensorObject> > mDevices;
3342
};
3443

3544
} // namespace SensorHalExt
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/*
2+
* Copyright (C) 2017 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "ConnectionDetector.h"
18+
19+
#include <utils/Log.h>
20+
21+
#include <dirent.h>
22+
#include <fcntl.h>
23+
#include <netinet/in.h>
24+
#include <sys/inotify.h>
25+
#include <sys/socket.h>
26+
27+
#include <sstream>
28+
29+
namespace android {
30+
namespace SensorHalExt {
31+
32+
// SocketConnectionDetector functions
33+
SocketConnectionDetector::SocketConnectionDetector(BaseDynamicSensorDaemon *d, int port)
34+
: ConnectionDetector(d) {
35+
// initialize socket that accept connection to localhost:port
36+
mListenFd = ::socket(AF_INET, SOCK_STREAM, 0);
37+
if (mListenFd < 0) {
38+
ALOGE("Cannot open socket");
39+
return;
40+
}
41+
42+
struct sockaddr_in serverAddress = {
43+
.sin_family = AF_INET,
44+
.sin_port = htons(port),
45+
.sin_addr = {
46+
.s_addr = htonl(INADDR_LOOPBACK)
47+
}
48+
};
49+
50+
::bind(mListenFd, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
51+
if (::listen(mListenFd, 0) != NO_ERROR) {
52+
ALOGE("Cannot listen to port %d", port);
53+
mListenFd = -1;
54+
return;
55+
}
56+
57+
std::ostringstream s;
58+
s << "socket:" << port;
59+
mDevice = s.str();
60+
61+
run("ddad_socket");
62+
}
63+
64+
SocketConnectionDetector::~SocketConnectionDetector() {
65+
if (mListenFd >= 0) {
66+
requestExitAndWait();
67+
}
68+
}
69+
70+
int SocketConnectionDetector::waitForConnection() {
71+
return ::accept(mListenFd, nullptr, nullptr);
72+
}
73+
74+
void SocketConnectionDetector::waitForDisconnection(int connFd) {
75+
char buffer[16];
76+
while (::read(connFd, buffer, sizeof(buffer)) > 0) {
77+
// discard data but response something to denote thread alive
78+
::write(connFd, ".", 1);
79+
}
80+
// read failure means disconnection
81+
::close(connFd);
82+
}
83+
84+
bool SocketConnectionDetector::threadLoop() {
85+
while (!Thread::exitPending()) {
86+
// block waiting for connection
87+
int connFd = waitForConnection();
88+
89+
if (connFd < 0) {
90+
break;
91+
}
92+
93+
ALOGV("Received connection, register dynamic accel sensor");
94+
mDaemon->onConnectionChange(mDevice, true);
95+
96+
waitForDisconnection(connFd);
97+
ALOGV("Connection break, unregister dynamic accel sensor");
98+
mDaemon->onConnectionChange(mDevice, false);
99+
}
100+
mDaemon->onConnectionChange(mDevice, false);
101+
ALOGD("SocketConnectionDetector thread exited");
102+
return false;
103+
}
104+
105+
// FileConnectionDetector functions
106+
FileConnectionDetector::FileConnectionDetector (
107+
BaseDynamicSensorDaemon *d, const std::string &path, const std::string &regex)
108+
: ConnectionDetector(d), mPath(path), mRegex(regex) {
109+
mInotifyFd = ::inotify_init1(IN_NONBLOCK);
110+
if (mInotifyFd < 0) {
111+
ALOGE("Cannot init inotify");
112+
return;
113+
}
114+
115+
int wd = ::inotify_add_watch(mInotifyFd, path.c_str(), IN_CREATE | IN_DELETE | IN_MOVED_FROM);
116+
if (wd < 0) {
117+
::close(mInotifyFd);
118+
mInotifyFd = -1;
119+
ALOGE("Cannot setup watch on dir %s", path.c_str());
120+
return;
121+
}
122+
123+
mPollFd.fd = wd;
124+
mPollFd.events = POLLIN;
125+
126+
run("ddad_file");
127+
}
128+
129+
FileConnectionDetector::~FileConnectionDetector() {
130+
if (mInotifyFd) {
131+
requestExitAndWait();
132+
::close(mInotifyFd);
133+
}
134+
}
135+
136+
bool FileConnectionDetector::matches(const std::string &name) const {
137+
return std::regex_match(name, mRegex);
138+
}
139+
140+
std::string FileConnectionDetector::getFullName(const std::string name) const {
141+
return mPath + name;
142+
}
143+
144+
void FileConnectionDetector::processExistingFiles() const {
145+
auto dirp = ::opendir(mPath.c_str());
146+
struct dirent *dp;
147+
while ((dp = ::readdir(dirp)) != NULL) {
148+
const std::string name(dp->d_name);
149+
if (matches(name)) {
150+
mDaemon->onConnectionChange(getFullName(name), true /*connected*/);
151+
}
152+
}
153+
::closedir(dirp);
154+
}
155+
156+
bool FileConnectionDetector::threadLoop() {
157+
struct {
158+
struct inotify_event e;
159+
uint8_t padding[NAME_MAX + 1];
160+
} ev;
161+
162+
processExistingFiles();
163+
164+
while (!Thread::exitPending()) {
165+
int pollNum = ::poll(&mPollFd, 1, -1);
166+
if (pollNum == -1) {
167+
if (errno == EINTR)
168+
continue;
169+
ALOGE("inotify poll error: %s", ::strerror(errno));
170+
}
171+
172+
if (pollNum > 0) {
173+
if (! (mPollFd.revents & POLLIN)) {
174+
continue;
175+
}
176+
177+
/* Inotify events are available */
178+
while (true) {
179+
/* Read some events. */
180+
ssize_t len = ::read(mInotifyFd, &ev, sizeof ev);
181+
if (len == -1 && errno != EAGAIN) {
182+
ALOGE("read error: %s", ::strerror(errno));
183+
requestExit();
184+
break;
185+
}
186+
187+
/* If the nonblocking read() found no events to read, then
188+
it returns -1 with errno set to EAGAIN. In that case,
189+
we exit the loop. */
190+
if (len <= 0) {
191+
break;
192+
}
193+
194+
if (ev.e.len && !(ev.e.mask & IN_ISDIR)) {
195+
const std::string name(ev.e.name);
196+
ALOGV("device %s state changed", name.c_str());
197+
if (matches(name)) {
198+
if (ev.e.mask & IN_CREATE) {
199+
mDaemon->onConnectionChange(getFullName(name), true /* connected*/);
200+
}
201+
202+
if (ev.e.mask & IN_DELETE || ev.e.mask & IN_MOVED_FROM) {
203+
mDaemon->onConnectionChange(getFullName(name), false /* connected*/);
204+
}
205+
}
206+
}
207+
}
208+
}
209+
}
210+
211+
ALOGD("FileConnectionDetection thread exited");
212+
return false;
213+
}
214+
} // namespace SensorHalExt
215+
} // namespace android

0 commit comments

Comments
 (0)