From 141a78d2459788d2f51f4a99c5acd9a11258e2c7 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Tue, 4 Apr 2017 21:30:31 +0900 Subject: [PATCH 01/16] sensord: ipc: add ipc_client class - ipc_client class is a helper for client. - ipc_client class that makes it easy to connect a channel to use for clients. - it creates and connects socket/channel/channel event_handler. Change-Id: If75a4ab542d3623a785ccf8bccbd66628b9646db Signed-off-by: kibak.yoon --- src/shared/channel_event_handler.cpp | 92 ++++++++++++++++++++++++++++++++++++ src/shared/channel_event_handler.h | 52 ++++++++++++++++++++ src/shared/ipc_client.cpp | 92 ++++++++++++++++++++++++++++++++++++ src/shared/ipc_client.h | 49 +++++++++++++++++++ 4 files changed, 285 insertions(+) create mode 100644 src/shared/channel_event_handler.cpp create mode 100644 src/shared/channel_event_handler.h create mode 100644 src/shared/ipc_client.cpp create mode 100644 src/shared/ipc_client.h diff --git a/src/shared/channel_event_handler.cpp b/src/shared/channel_event_handler.cpp new file mode 100644 index 0000000..9045a88 --- /dev/null +++ b/src/shared/channel_event_handler.cpp @@ -0,0 +1,92 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "channel_event_handler.h" + +#include "channel.h" +#include "channel_handler.h" +#include "sensor_log.h" + +using namespace ipc; + +channel_event_handler::channel_event_handler(channel *ch, channel_handler *handler) +: m_ch(ch) +, m_handler(handler) +{ +} + +channel_event_handler::~channel_event_handler() +{ + m_ch = NULL; + m_handler = NULL; +} + +bool channel_event_handler::handle(int fd, event_condition condition) +{ + message msg; + + if (!m_ch || !m_ch->is_connected()) + return false; + + if (condition & (EVENT_HUP)) { + m_ch->disconnect(); + delete m_ch; + m_ch = NULL; + return false; + } + + if (!m_ch->read_sync(msg)) { + m_ch->disconnect(); + delete m_ch; + m_ch = NULL; + return false; + } + + return true; +} + +void channel_event_handler::connected(channel *ch) +{ + if (m_handler) + m_handler->connected(ch); +} + +void channel_event_handler::disconnected(channel *ch) +{ + if (m_handler) + m_handler->disconnected(ch); +} + +void channel_event_handler::read(channel *ch, message &msg) +{ + if (m_handler) + m_handler->read(ch, msg); +} + +void channel_event_handler::read_complete(channel *ch) +{ + if (m_handler) + m_handler->read_complete(ch); +} + +void channel_event_handler::error_caught(channel *ch, int error) +{ + if (m_handler) + m_handler->error_caught(ch, error); +} diff --git a/src/shared/channel_event_handler.h b/src/shared/channel_event_handler.h new file mode 100644 index 0000000..252c7ee --- /dev/null +++ b/src/shared/channel_event_handler.h @@ -0,0 +1,52 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __CHANNEL_EVENT_HANDLER_H__ +#define __CHANNEL_EVENT_HANDLER_H__ + +#include + +#include "event_handler.h" +#include "channel_handler.h" + +namespace ipc { + +class channel; + +class channel_event_handler : public event_handler, public channel_handler { +public: + channel_event_handler(channel *ch, channel_handler *handler); + virtual ~channel_event_handler(); + + bool handle(int fd, event_condition condition); + + void connected(channel *ch); + void disconnected(channel *ch); + void read(channel *ch, message &msg); + void read_complete(channel *ch); + void error_caught(channel *ch, int error); + +private: + channel *m_ch; + channel_handler *m_handler; +}; + +} + +#endif /* __CHANNEL_EVENT_HANDLER_H__ */ diff --git a/src/shared/ipc_client.cpp b/src/shared/ipc_client.cpp new file mode 100644 index 0000000..71fdde4 --- /dev/null +++ b/src/shared/ipc_client.cpp @@ -0,0 +1,92 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "ipc_client.h" + +#include "sensor_log.h" +#include "stream_socket.h" +#include "event_handler.h" +#include "channel_event_handler.h" + +using namespace ipc; + +ipc_client::ipc_client(const std::string &path) +{ + m_path = path; +} + +ipc_client::~ipc_client() +{ +} + +bool ipc_client::set_option(int option, int value) +{ + return true; +} + +bool ipc_client::set_option(const std::string &option, int value) +{ + return true; +} + +channel *ipc_client::connect(channel_handler *handler) +{ + return connect(handler, NULL); +} + +channel *ipc_client::connect(channel_handler *handler, event_loop *loop) +{ + socket *sock; + channel *ch; + channel_event_handler *ev_handler; + + sock = new(std::nothrow) stream_socket(); + retvm_if(!sock, NULL, "Failed to allocate memory"); + + if (!sock->create(m_path)) { + delete sock; + return NULL; + } + + ch = new(std::nothrow) channel(sock); + if (!ch) { + delete sock; + _E("Failed to allocate memory"); + return NULL; + } + + ev_handler = new(std::nothrow) channel_event_handler(ch, handler); + if (!ev_handler) { + delete ch; + delete sock; + _E("Faield to allocate memory"); + return NULL; + } + + ch->connect(ev_handler, loop); + + if (loop) { + uint64_t id = loop->add_event(sock->get_fd(), + (EVENT_IN | EVENT_HUP | EVENT_NVAL), ev_handler); + ch->set_event_id(id); + } + + _I("Connected"); + return ch; +} diff --git a/src/shared/ipc_client.h b/src/shared/ipc_client.h new file mode 100644 index 0000000..8f52678 --- /dev/null +++ b/src/shared/ipc_client.h @@ -0,0 +1,49 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __IPC_CLIENT_H__ +#define __IPC_CLIENT_H__ + +#include + +#include "channel.h" +#include "channel_handler.h" +#include "event_loop.h" + +namespace ipc { + +class ipc_client { +public: + ipc_client(const std::string &path); + ~ipc_client(); + + bool set_option(int option, int value); + bool set_option(const std::string &option, int value); + + /* call channel->disconnect() after you have used it */ + channel *connect(channel_handler *handler); + channel *connect(channel_handler *handler, event_loop *loop); + +private: + std::string m_path; +}; + +} + +#endif /* __IPC_CLIENT_H__ */ -- 2.7.4 From 94b08af3a6ff275818e9e6104dc556d93d95e36a Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 09:57:43 +0900 Subject: [PATCH 02/16] sensord: ipc: add ipc_server class - ipc_server class is a helper for server - ipc_server class that makes it easy to bind/listen/accept a channel to use for server. - it creates and bind/accepts socket/channel/channel_event_handler Change-Id: If79e27a6babcf73126b56f65e750176a9ddd5c78 Signed-off-by: kibak.yoon --- src/shared/accept_event_handler.cpp | 47 +++++++++++++++ src/shared/accept_event_handler.h | 42 ++++++++++++++ src/shared/ipc_server.cpp | 111 ++++++++++++++++++++++++++++++++++++ src/shared/ipc_server.h | 59 +++++++++++++++++++ 4 files changed, 259 insertions(+) create mode 100644 src/shared/accept_event_handler.cpp create mode 100644 src/shared/accept_event_handler.h create mode 100644 src/shared/ipc_server.cpp create mode 100644 src/shared/ipc_server.h diff --git a/src/shared/accept_event_handler.cpp b/src/shared/accept_event_handler.cpp new file mode 100644 index 0000000..527d967 --- /dev/null +++ b/src/shared/accept_event_handler.cpp @@ -0,0 +1,47 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "accept_event_handler.h" + +#include "sensor_log.h" +#include "ipc_server.h" + +using namespace ipc; + +accept_event_handler::accept_event_handler(ipc_server *server) +: m_server(server) +{ +} + +bool accept_event_handler::handle(int fd, event_condition condition) +{ + retv_if((condition & (EVENT_HUP)), false); + + stream_socket *cli_sock = new(std::nothrow) stream_socket(); + retvm_if(!cli_sock, false, "Failed to allocate memory"); + + m_server->accept(*cli_sock); + + channel *_ch = new(std::nothrow) channel(cli_sock); + retvm_if(!_ch, false, "Failed to allocate memory"); + + m_server->register_channel(cli_sock->get_fd(), _ch); + + return true; +} diff --git a/src/shared/accept_event_handler.h b/src/shared/accept_event_handler.h new file mode 100644 index 0000000..814f560 --- /dev/null +++ b/src/shared/accept_event_handler.h @@ -0,0 +1,42 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __ACCEPT_EVENT_HANDLER__ +#define __ACCEPT_EVENT_HANDLER__ + +#include "event_handler.h" + +namespace ipc { + +class ipc_server; + +class accept_event_handler : public event_handler +{ +public: + accept_event_handler(ipc_server *server); + + bool handle(int fd, event_condition condition); + +private: + ipc_server *m_server; +}; + +} + +#endif /* __ACCEPT_EVENT_HANDLER__ */ diff --git a/src/shared/ipc_server.cpp b/src/shared/ipc_server.cpp new file mode 100644 index 0000000..9723a98 --- /dev/null +++ b/src/shared/ipc_server.cpp @@ -0,0 +1,111 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "ipc_server.h" + +#include "channel.h" +#include "sensor_log.h" +#include "event_loop.h" +#include "channel_event_handler.h" +#include "accept_event_handler.h" + +using namespace ipc; + +#define MAX_CONNECTIONS 1000 + +ipc_server::ipc_server(const std::string &path) +{ + m_accept_sock.create(path); +} + +ipc_server::~ipc_server() +{ +} + +bool ipc_server::set_option(int option, int value) +{ + /* TODO */ + return true; +} + +bool ipc_server::set_option(const std::string &option, int value) +{ + /* TODO */ + return true; +} + +void ipc_server::accept(ipc::socket &cli_sock) +{ + m_accept_sock.accept(cli_sock); + + _I("Accepted[%d]", cli_sock.get_fd()); +} + +bool ipc_server::bind(channel_handler *handler, event_loop *loop) +{ + m_handler = handler; + m_event_loop = loop; + + m_accept_sock.bind(); + m_accept_sock.listen(MAX_CONNECTIONS); + + register_acceptor(); + + _I("Bound[%d]", m_accept_sock.get_fd()); + return true; +} + +void ipc_server::register_channel(int fd, channel *ch) +{ + channel_event_handler *ev_handler = new(std::nothrow) channel_event_handler(ch, m_handler); + retm_if(!ev_handler, "Failed to allocate memory"); + + ch->bind(ev_handler, m_event_loop); + uint64_t id = m_event_loop->add_event(fd, + (event_condition)(EVENT_IN | EVENT_HUP | EVENT_NVAL), ev_handler); + + if (id == 0) + delete ev_handler; +} + +void ipc_server::register_acceptor(void) +{ + int fd = m_accept_sock.get_fd(); + + m_accept_handler = new(std::nothrow) accept_event_handler(this); + retm_if(!m_accept_handler, "Failed to allocate memory"); + + uint64_t id = m_event_loop->add_event(fd, + (event_condition)(EVENT_IN | EVENT_HUP | EVENT_NVAL), m_accept_handler); + + if (id == 0) { + delete m_accept_handler; + m_accept_handler = NULL; + } +} + +bool ipc_server::close(void) +{ + m_accept_sock.close(); + + m_handler = NULL; + + _I("Closed"); + return true; +} diff --git a/src/shared/ipc_server.h b/src/shared/ipc_server.h new file mode 100644 index 0000000..7e033d0 --- /dev/null +++ b/src/shared/ipc_server.h @@ -0,0 +1,59 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __IPC_SERVER_H__ +#define __IPC_SERVER_H__ + +#include + +#include "stream_socket.h" +#include "channel.h" +#include "channel_handler.h" +#include "accept_event_handler.h" +#include "event_loop.h" + +namespace ipc { + +class ipc_server { +public: + ipc_server(const std::string &path); + ~ipc_server(); + + bool set_option(int option, int value); + bool set_option(const std::string &option, int value); + + bool bind(channel_handler *handler, event_loop *loop); + bool close(void); + + /* TODO: only accept_handler should use these functions */ + void accept(ipc::socket &cli_sock); + void register_channel(int fd, channel *ch); + void register_acceptor(void); + +private: + stream_socket m_accept_sock; + + event_loop *m_event_loop; + channel_handler *m_handler; + accept_event_handler *m_accept_handler; +}; + +} + +#endif /* __IPC_SERVER_H__ */ -- 2.7.4 From 4552f30d4227b2a14477b19246b1faacd0036ba2 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 10:19:13 +0900 Subject: [PATCH 03/16] sensord: remove build warnings in ipc-utils - warning: control reaches end of non-void function [-Wreturn-type] - warning: ignoring return value [-Wunused-result] Change-Id: Id172b9e32bfe45543b16dc9a0726bc1cc0c11441 Signed-off-by: kibak.yoon --- src/shared/event_loop.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/shared/event_loop.cpp b/src/shared/event_loop.cpp index 9bd596a..73854b5 100644 --- a/src/shared/event_loop.cpp +++ b/src/shared/event_loop.cpp @@ -230,6 +230,8 @@ bool event_loop::run(int timeout) _I("Started"); g_main_loop_run(m_mainloop); + + return true; } void event_loop::stop(void) @@ -237,8 +239,11 @@ void event_loop::stop(void) ret_if(!is_running() || m_terminating.load()); uint64_t term = 1; + ssize_t size; m_terminating.store(true); - write(m_term_fd, &term, sizeof(uint64_t)); + size = write(m_term_fd, &term, sizeof(uint64_t)); + + retm_if(size != sizeof(ssize_t), "Failed to write[%d]", m_term_fd); } void event_loop::terminate(void) -- 2.7.4 From 1626d4fcda3c62ab1c76edef565660cbb3730be4 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 10:29:52 +0900 Subject: [PATCH 04/16] sensord: ipc: add unit testcases - test a connection between ipc_client and ipc_server - test 2 clients - test 100 clients - test 1 client with 2 channels - test 30 clients with large message - test 3 normal client and 1 client with small recv buffer - test 3 normal client and 1 client witch sleeps 10 seconds Change-Id: I33b2e782872b51d42fc4a68b84bd5d6fe758964f Signed-off-by: kibak.yoon --- src/sensorctl/testcase/unit_ipc.cpp | 524 ++++++++++++++++++++++++++++++++++++ 1 file changed, 524 insertions(+) create mode 100644 src/sensorctl/testcase/unit_ipc.cpp diff --git a/src/sensorctl/testcase/unit_ipc.cpp b/src/sensorctl/testcase/unit_ipc.cpp new file mode 100644 index 0000000..4528562 --- /dev/null +++ b/src/sensorctl/testcase/unit_ipc.cpp @@ -0,0 +1,524 @@ +/* + * sensorctl + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 +#include +#include + +#include "shared/channel.h" +#include "shared/channel_handler.h" +#include "shared/ipc_client.h" +#include "shared/ipc_server.h" + +#include "log.h" +#include "test_bench.h" + +using namespace ipc; + +#define MAX_BUF_SIZE 4096 +#define TEST_PATH "/run/.sensord_test.socket" + +typedef bool (*process_func_t)(const char *msg, int size, int count); + +static pid_t run_process(process_func_t func, const char *msg, int size, int count) +{ + pid_t pid = fork(); + if (pid < 0) + return -1; + + if (pid == 0) { + if (!func(msg, size, count)) + _E("Failed to run process\n"); + exit(0); + } + + return pid; +} + +class test_echo_server_handler : public channel_handler +{ +public: + void connected(channel *ch) {} + void disconnected(channel *ch) {} + void read(channel *ch, message &msg) + { + char buf[MAX_BUF_SIZE]; + + message *reply = new(std::nothrow) message(); + RETM_IF(!reply, "Failed to allocate memory"); + + msg.disclose(buf); + reply->enclose(buf, MAX_BUF_SIZE); + + ch->send(reply); + } + void read_complete(channel *ch) {} + void error_caught(channel *ch, int error) {} +}; + +/* IPC Echo Server */ +static bool run_ipc_server_echo(const char *str, int size, int count) +{ + event_loop eloop; + + ipc_server server(TEST_PATH); + test_echo_server_handler handler; + + server.set_option("max_connection", 10); + server.set_option(SO_TYPE, SOCK_STREAM); + server.bind(&handler, &eloop); + + eloop.run(18000); + server.close(); + + return true; +} + +class test_client_handler_30_1M : public channel_handler +{ +public: + void connected(channel *ch) {} + void disconnected(channel *ch) {} + void read(channel *ch, message &msg) {} + void read_complete(channel *ch) {} + void error_caught(channel *ch, int error) {} +}; + +/* IPC Client Sleep Test(4096Kb * 1024) */ +static bool run_ipc_client_sleep_10s(const char *str, int size, int count) +{ + ipc_client client(TEST_PATH); + test_client_handler_30_1M client_handler; + + channel *ch = client.connect(&client_handler, NULL); + ASSERT_NE(ch, 0); + + message msg; + message reply; + char buf[MAX_BUF_SIZE] = {'1', '1', '1',}; + + msg.enclose(buf, MAX_BUF_SIZE); + + usleep(10000); + ch->send_sync(&msg); + + /* Test */ + sleep(1); + + ch->read_sync(reply); + reply.disclose(buf); + + int ret = strncmp(buf, "111", 3); + ASSERT_EQ(ret, 0); + ASSERT_EQ(reply.size(), MAX_BUF_SIZE); + + ch->disconnect(); + delete ch; + + return true; +} + +/* IPC Client With Small Buffer Test(4096Kb * 1024) */ +static bool run_ipc_client_small_buffer(const char *str, int size, int count) +{ + ipc_client client(TEST_PATH); + test_client_handler_30_1M client_handler; + + channel *ch = client.connect(&client_handler, NULL); + ASSERT_NE(ch, 0); + + int ret; + message msg; + message reply; + char buf[MAX_BUF_SIZE] = {'1', '1', '1',}; + + msg.enclose(buf, MAX_BUF_SIZE); + + usleep(10000); + + int buf_size; + ch->get_option(SO_RCVBUF, buf_size); + _I("Before: Buffer size : %d\n", buf_size); + + ch->set_option(SO_RCVBUF, buf_size/2048); + ch->get_option(SO_RCVBUF, buf_size); + _I("After: Buffer size : %d\n", buf_size); + + for (int i = 0; i < 1024; ++i) { + ch->send_sync(&msg); + ch->read_sync(reply); + } + + reply.disclose(buf); + + ret = strncmp(buf, "111", 3); + ASSERT_EQ(ret, 0); + ASSERT_EQ(reply.size(), MAX_BUF_SIZE); + + ch->disconnect(); + delete ch; + + return true; +} + +/* IPC Client Test(4K * 256) */ +static bool run_ipc_client_1M(const char *str, int size, int count) +{ + ipc_client client(TEST_PATH); + test_client_handler_30_1M client_handler; + + channel *ch = client.connect(&client_handler, NULL); + ASSERT_NE(ch, 0); + + int ret; + message msg; + message reply; + char buf[MAX_BUF_SIZE] = {'1', '1', '1',}; + + msg.enclose(buf, MAX_BUF_SIZE); + + usleep(10000); + + for (int i = 0; i < 256; ++i) { + ch->send_sync(&msg); + ch->read_sync(reply); + } + + reply.disclose(buf); + + ret = strncmp(buf, "111", 3); + ASSERT_EQ(ret, 0); + ASSERT_EQ(reply.size(), MAX_BUF_SIZE); + + ch->disconnect(); + delete ch; + + return true; +} + +/* IPC Server Test(Not Echo) */ +class test_server_handler : public channel_handler +{ +public: + void connected(channel *ch) {} + void disconnected(channel *ch) {} + void read(channel *ch, message &msg) + { + char buf[MAX_BUF_SIZE]; + msg.disclose(buf); + + message *reply = new(std::nothrow) message(); + if (!reply) return; + + reply->enclose("TEXTTEXTTEXTTEXT", 16); + ch->send(reply); + } + void read_complete(channel *ch) {} + void error_caught(channel *ch, int error) {} +}; + +static bool run_ipc_server(const char *str, int size, int count) +{ + event_loop eloop; + + ipc_server server(TEST_PATH); + test_server_handler handler; + + server.set_option("max_connection", 10); + server.set_option(SO_TYPE, SOCK_STREAM); + server.bind(&handler, &eloop); + + /* run main loop for 5 seconds */ + eloop.run(5000); + + server.close(); + + return true; +} + +/* IPC Client Test(Not Echo) */ +class test_client_handler : public channel_handler +{ +public: + void connected(channel *ch) {} + void disconnected(channel *ch) {} + void read(channel *ch, message &msg) {} + void read_complete(channel *ch) {} + void error_caught(channel *ch, int error) {} +}; + +static bool run_ipc_client_2_channel_message(const char *str, int size, int count) +{ + ipc_client client(TEST_PATH); + test_client_handler client_handler; + channel *ch[2]; + int ret; + message msg; + message reply; + char buf[MAX_BUF_SIZE]; + + ch[0] = client.connect(&client_handler, NULL); + ASSERT_NE(ch[0], 0); + + msg.enclose("TESTTESTTEST", 12); + ch[0]->send_sync(&msg); + usleep(100000); + ch[0]->read_sync(reply); + reply.disclose(buf); + ret = strncmp(buf, "TEXTTEXTTEXTTEXT", 16); + ASSERT_EQ(ret, 0); + + ch[1] = client.connect(&client_handler, NULL); + ASSERT_NE(ch[1], 0); + + msg.enclose("TESTTESTTEST", 12); + ch[1]->send_sync(&msg); + usleep(100000); + ch[1]->read_sync(reply); + reply.disclose(buf); + ret = strncmp(buf, "TEXTTEXTTEXTTEXT", 16); + ASSERT_EQ(ret, 0); + + ch[0]->disconnect(); + ch[1]->disconnect(); + delete ch[0]; + delete ch[1]; + + return true; +} + +static bool run_ipc_client_2_channel(const char *str, int size, int count) +{ + ipc_client client(TEST_PATH); + test_client_handler client_handler; + channel *ch[2]; + + ch[0] = client.connect(&client_handler, NULL); + ASSERT_NE(ch[0], 0); + ch[1] = client.connect(&client_handler, NULL); + ASSERT_NE(ch[1], 0); + ASSERT_NE(ch[1], ch[0]); + + ch[0]->disconnect(); + ch[1]->disconnect(); + delete ch[0]; + delete ch[1]; + + return true; +} + +static bool run_ipc_client(const char *str, int size, int count) +{ + ipc_client client(TEST_PATH); + test_client_handler client_handler; + + channel *ch = client.connect(&client_handler, NULL); + ASSERT_NE(ch, 0); + + int ret; + message msg; + message reply; + char buf[MAX_BUF_SIZE]; + + msg.enclose("TESTTESTTEST", 12); + ch->send_sync(&msg); + + usleep(100000); + + ch->read_sync(reply); + reply.disclose(buf); + + ret = strncmp(buf, "TEXTTEXTTEXTTEXT", 16); + ASSERT_EQ(ret, 0); + + ch->disconnect(); + delete ch; + + return true; +} + +/** + * @brief Test 3 client + 1 client which sleeps 10 seconds + */ +TESTCASE(sensor_ipc_client_sleep_1s, sleep_1s_p) +{ + pid_t pid = run_process(run_ipc_server_echo, NULL, 0, 0); + EXPECT_GE(pid, 0); + + usleep(100000); + + for (int i = 0; i < 3; ++i) { + pid = run_process(run_ipc_client_1M, NULL, 0, 0); + EXPECT_GE(pid, 0); + } + + bool ret = run_ipc_client_sleep_10s(NULL, 0, 0); + ASSERT_TRUE(ret); + + usleep(100000); + + return true; +} + +/** + * @brief Test 3 client + 1 client which has small recv buffer + */ +TESTCASE(sensor_ipc_client_small_2240, ipc_client_small_2240_p) +{ + pid_t pid = run_process(run_ipc_server_echo, NULL, 0, 0); + EXPECT_GE(pid, 0); + + usleep(100000); + + for (int i = 0; i < 3; ++i) { + pid = run_process(run_ipc_client_1M, NULL, 0, 0); + EXPECT_GE(pid, 0); + } + + bool ret = run_ipc_client_small_buffer(NULL, 0, 0); + ASSERT_TRUE(ret); + + usleep(100000); + + return true; +} + +/** + * @brief Test 30 ipc_client with 1M message + */ +TESTCASE(sensor_ipc_30_client_1M, ipc_client_p_30_1M) +{ + pid_t pid = run_process(run_ipc_server_echo, NULL, 0, 0); + EXPECT_GE(pid, 0); + + usleep(100000); + + for (int i = 0; i < 30; ++i) { + pid = run_process(run_ipc_client_1M, NULL, 0, 0); + EXPECT_GE(pid, 0); + } + + bool ret = run_ipc_client_1M(NULL, 0, 0); + ASSERT_TRUE(ret); + + usleep(100000); + + return true; +} + +/** + * @brief Test 2 channel of 1 client with message + */ +TESTCASE(sensor_ipc_client_2_channel_message, 2_channel_message_p) +{ + pid_t pid = run_process(run_ipc_server, NULL, 0, 0); + EXPECT_GE(pid, 0); + + usleep(100000); + + bool ret = run_ipc_client_2_channel_message(NULL, 0, 0); + ASSERT_TRUE(ret); + + usleep(100000); + + return true; +} + +/** + * @brief Test 2 channel of 1 client + */ +TESTCASE(sensor_ipc_client_2_channel, 2_channel_p) +{ + pid_t pid = run_process(run_ipc_server, NULL, 0, 0); + EXPECT_GE(pid, 0); + + usleep(100000); + + bool ret = run_ipc_client_2_channel(NULL, 0, 0); + ASSERT_TRUE(ret); + + usleep(100000); + + return true; +} + +/** + * @brief Test 100 ipc_client + */ +TESTCASE(sensor_ipc_100_client, ipc_client_p_100) +{ + pid_t pid = run_process(run_ipc_server, NULL, 0, 0); + EXPECT_GE(pid, 0); + + usleep(100000); + + for (int i = 0; i < 99; ++i) { + pid = run_process(run_ipc_client, NULL, 0, 0); + EXPECT_GE(pid, 0); + } + + bool ret = run_ipc_client(NULL, 0, 0); + ASSERT_TRUE(ret); + + usleep(100000); + + return true; +} + +/** + * @brief Test 2 ipc_client + */ +TESTCASE(sensor_ipc_2_client, ipc_client_p_2) +{ + pid_t pid = run_process(run_ipc_server, NULL, 0, 0); + EXPECT_GE(pid, 0); + + usleep(100000); + + pid = run_process(run_ipc_client, NULL, 0, 0); + EXPECT_GE(pid, 0); + + bool ret = run_ipc_client(NULL, 0, 0); + ASSERT_TRUE(ret); + + usleep(100000); + + return true; +} + +/** + * @brief Test ipc_client/ipc_server class + * @details 1. connect/disconnect + * 2. send "TEST" message from client to server + * 3. check that message in server handler + */ +TESTCASE(sensor_ipc_client_0, ipc_client_p_0) +{ + pid_t pid = run_process(run_ipc_server, NULL, 0, 0); + EXPECT_GE(pid, 0); + + usleep(100000); + + bool ret = run_ipc_client(NULL, 0, 0); + ASSERT_TRUE(ret); + + usleep(100000); + + return true; +} -- 2.7.4 From a718244c631c79952680c6f80de925e3c7c4153c Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 10:50:34 +0900 Subject: [PATCH 05/16] sensord: add util functions to sensor:utils namepsace - change sensor_type_t to uri - get timestamp - get client name Change-Id: I3aabf426176306b31a61c4da987281f19664ac62 Signed-off-by: kibak.yoon --- src/shared/sensor_utils.cpp | 201 ++++++++++++++++++++++++++++++++++++++++++++ src/shared/sensor_utils.h | 40 +++++++++ 2 files changed, 241 insertions(+) create mode 100644 src/shared/sensor_utils.cpp create mode 100644 src/shared/sensor_utils.h diff --git a/src/shared/sensor_utils.cpp b/src/shared/sensor_utils.cpp new file mode 100644 index 0000000..2b2781f --- /dev/null +++ b/src/shared/sensor_utils.cpp @@ -0,0 +1,201 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "sensor_utils.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PATH_MAX 256 + +/* TODO: move and define string type to sensor_type.h */ +static std::map types = { + {UNKNOWN_SENSOR, "http://tizen.org/sensor/unknown"}, + {ALL_SENSOR, "http://tizen.org/sensor/all"}, + {ACCELEROMETER_SENSOR, "http://tizen.org/sensor/accelerometer"}, + {GRAVITY_SENSOR, "http://tizen.org/sensor/gravity"}, + {LINEAR_ACCEL_SENSOR, "http://tizen.org/sensor/linear_accel"}, + {GEOMAGNETIC_SENSOR, "http://tizen.org/sensor/geomagnetic"}, + {ROTATION_VECTOR_SENSOR, "http://tizen.org/sensor/rotation_vector"}, + {ORIENTATION_SENSOR, "http://tizen.org/sensor/orientation"}, + {GYROSCOPE_SENSOR, "http://tizen.org/sensor/gyroscope"}, + {LIGHT_SENSOR, "http://tizen.org/sensor/light"}, + {PROXIMITY_SENSOR, "http://tizen.org/sensor/proximity"}, + {PRESSURE_SENSOR, "http://tizen.org/sensor/pressure"}, + {ULTRAVIOLET_SENSOR, "http://tizen.org/sensor/ultraviolet"}, + {TEMPERATURE_SENSOR, "http://tizen.org/sensor/temperature"}, + {HUMIDITY_SENSOR, "http://tizen.org/sensor/humidity"}, + {HRM_SENSOR, "http://tizen.org/sensor/heart_rate_monitor"}, + {HRM_LED_GREEN_SENSOR, "http://tizen.org/sensor/hrm.led_green"}, + {HRM_LED_IR_SENSOR, "http://tizen.org/sensor/hrm.led_ir"}, + {HRM_LED_RED_SENSOR, "http://tizen.org/sensor/hrm.led_red"}, + {GYROSCOPE_UNCAL_SENSOR, "http://tizen.org/sensor/gyroscope.uncalibrated"}, + {GEOMAGNETIC_UNCAL_SENSOR, "http://tizen.org/sensor/geomagnetic.uncalibrated"}, + {GYROSCOPE_RV_SENSOR, "http://tizen.org/sensor/rotation_vector.gyroscope"}, + {GEOMAGNETIC_RV_SENSOR, "http://tizen.org/sensor/rotation_vector.geomagnetic"}, + + {HUMAN_PEDOMETER_SENSOR, "http://tizen.org/sensor/human_pedometer"}, + {HUMAN_SLEEP_MONITOR_SENSOR, "http://tizen.org/sensor/human_sleep_monitor"}, + {HUMAN_SLEEP_DETECTOR_SENSOR, "http://tizen.org/sensor/human_sleep_detector"}, + {HUMAN_STRESS_MONITOR_SENSOR, "http://tizen.org/sensor/human_stress_monitor"}, + + {EXERCISE_WALKING_SENSOR, "http://tizen.org/sensor/exercise.walking"}, + {EXERCISE_RUNNING_SENSOR, "http://tizen.org/sensor/exercise.running"}, + {EXERCISE_HIKING_SENSOR, "http://tizen.org/sensor/exercise.hiking"}, + {EXERCISE_CYCLING_SENSOR, "http://tizen.org/sensor/exercise.cycling"}, + {EXERCISE_ELLIPTICAL_SENSOR, "http://tizen.org/sensor/exercise.elliptical"}, + {EXERCISE_INDOOR_CYCLING_SENSOR, "http://tizen.org/sensor/exercise.indoor_cycling"}, + {EXERCISE_ROWING_SENSOR, "http://tizen.org/sensor/exercise.rowing"}, + {EXERCISE_STEPPER_SENSOR, "http://tizen.org/sensor/exercise.stepper"}, + + {EXTERNAL_EXERCISE_SENSOR, "http://tizen.org/sensor/external_exercise"}, + + {FUSION_SENSOR, "http://tizen.org/sensor/fusion"}, + {AUTO_ROTATION_SENSOR, "http://tizen.org/sensor/auto_rotation"}, + {AUTO_BRIGHTNESS_SENSOR, "http://tizen.org/sensor/auto_brightness"}, + + {GESTURE_MOVEMENT_SENSOR, "http://tizen.org/sensor/gesture_movement"}, + {GESTURE_WRIST_UP_SENSOR, "http://tizen.org/sensor/gesture_wrist_up"}, + {GESTURE_WRIST_DOWN_SENSOR, "http://tizen.org/sensor/gesture_wrist_down"}, + {GESTURE_MOVEMENT_STATE_SENSOR, "http://tizen.org/sensor/gesture_movement_state"}, + {GESTURE_FACE_DOWN_SENSOR, "http://tizen.org/sensor/gesture_face_down"}, + + {ACTIVITY_TRACKER_SENSOR, "http://tizen.org/sensor/activity_tracker"}, + {ACTIVITY_LEVEL_MONITOR_SENSOR, "http://tizen.org/sensor/activity_level_monitor"}, + {GPS_BATCH_SENSOR, "http://tizen.org/sensor/gps_batch"}, + + {HRM_CTRL_SENSOR, "http://tizen.org/sensor/hrm_ctrl"}, + + {WEAR_STATUS_SENSOR, "http://tizen.org/sensor/wear_status"}, + {WEAR_ON_MONITOR_SENSOR, "http://tizen.org/sensor/wear_on_monitor"}, + {NO_MOVE_DETECTOR_SENSOR, "http://tizen.org/sensor/no_move_detector"}, + {RESTING_HR_SENSOR, "http://tizen.org/sensor/resting_hr"}, + {STEP_LEVEL_MONITOR_SENSOR, "http://tizen.org/sensor/step_level_monitor"}, + {EXERCISE_STANDALONE_SENSOR, "http://tizen.org/sensor/exercise_standalone"}, + {EXERCISE_HR_SENSOR, "http://tizen.org/sensor/exercise_hr"}, + {WORKOUT_SENSOR, "http://tizen.org/sensor/workout"}, + {CYCLE_MONITOR_SENSOR, "http://tizen.org/sensor/cycle_monitor"}, + {STAIR_TRACKER_SENSOR, "http://tizen.org/sensor/stair_tracker"}, + {PRESSURE_INDICATOR_SENSOR, "http://tizen.org/sensor/pressure_indicator"}, + {PRESSURE_ALERT_SENSOR, "http://tizen.org/sensor/pressure_alert"}, + {HR_CALORIE_SENSOR, "http://tizen.org/sensor/hr_calorie"}, + + {CONTEXT_SENSOR, "http://tizen.org/sensor/context"}, + {MOTION_SENSOR, "http://tizen.org/sensor/motion"}, + {PIR_SENSOR, "http://tizen.org/sensor/pir"}, + {PIR_LONG_SENSOR, "http://tizen.org/sensor/pir_long"}, + {DUST_SENSOR, "http://tizen.org/sensor/dust"}, + {THERMOMETER_SENSOR, "http://tizen.org/sensor/thermometer"}, + {PEDOMETER_SENSOR, "http://tizen.org/sensor/pedometer"}, + {FLAT_SENSOR, "http://tizen.org/sensor/flat"}, + {HRM_RAW_SENSOR, "http://tizen.org/sensor/hrm_raw"}, + {TILT_SENSOR, "http://tizen.org/sensor/tilt"}, + {RV_RAW_SENSOR, "http://tizen.org/sensor/rv_raw"}, + {GSR_SENSOR, "http://tizen.org/sensor/gsr"}, + {SIMSENSE_SENSOR, "http://tizen.org/sensor/simsense"}, + {PPG_SENSOR, "http://tizen.org/sensor/ppg"}, +}; + +const char *sensor::utils::get_uri(sensor_type_t type) +{ + auto it = types.find(type); + if (it == types.end()) + return "Unknown Type"; + return it->second; +} + +unsigned long long sensor::utils::get_timestamp(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return ((unsigned long long)(t.tv_sec)*1000000000LL + t.tv_nsec) / 1000; +} + +unsigned long long sensor::utils::get_timestamp(timeval *t) +{ + if (!t) + return 0; + + return ((unsigned long long)(t->tv_sec)*1000000LL +t->tv_usec); +} + +#ifdef _DEBUG +bool sensor::utils::get_proc_name(pid_t pid, char *process_name) +{ + FILE *fp; + char buf[NAME_MAX]; + char filename[PATH_MAX]; + + sprintf(filename, "/proc/%d/stat", pid); + fp = fopen(filename, "r"); + + if (fp == NULL) + return false; + + if (fscanf(fp, "%*s (%[^)]", buf) < 1) { + fclose(fp); + return false; + } + + strncpy(process_name, buf, NAME_MAX-1); + process_name[NAME_MAX-1] = '\0'; + fclose(fp); + + return true; +} +#else +bool sensor::utils::get_proc_name(pid_t pid, char *process_name) +{ + char buf[NAME_MAX]; + + if (snprintf(buf, sizeof(buf), "%d process", pid) < 1) { + return false; + } + + strncpy(process_name, buf, NAME_MAX-1); + process_name[NAME_MAX-1] = '\0'; + + return true; +} +#endif + +const char* sensor::utils::get_client_name(void) +{ + const int pid_string_size = 10; + static pid_t pid = -1; + static char client_name[NAME_MAX + pid_string_size]; + + char proc_name[NAME_MAX]; + + if (pid == -1) + { + pid = getpid(); + get_proc_name(pid, proc_name); + snprintf(client_name, sizeof(client_name), "%s(%d)", proc_name, pid); + } + + return client_name; +} diff --git a/src/shared/sensor_utils.h b/src/shared/sensor_utils.h new file mode 100644 index 0000000..c6ab64d --- /dev/null +++ b/src/shared/sensor_utils.h @@ -0,0 +1,40 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __SENSOR_UTILS_H__ +#define __SENSOR_UTILS_H__ + +#include +#include + +namespace sensor { + +namespace utils { + const char *get_uri(sensor_type_t type); + + unsigned long long get_timestamp(void); + unsigned long long get_timestamp(timeval *t); + + const char* get_client_name(void); + bool get_proc_name(pid_t pid, char *process_name); +} + +} + +#endif /* __SENSOR_UTILS_H__ */ -- 2.7.4 From 850ec974bbe07d4785a1ff002132544b1c145fcb Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 12:21:11 +0900 Subject: [PATCH 06/16] sensord: clean up sensor_info class to support URI as name - sensor_info class has sensor information and can support serialize/deserialize information between client and server. - URI(type and name) is supported - TODO-LIST - some information is redundant or requires a clear distinction Change-Id: I3f40376f37cccbb003d865b7558b5fc55a3b141f Signed-off-by: kibak.yoon --- include/sensor_types.h | 3 + src/shared/sensor_info.cpp | 213 ++++++++++++++++++++++++++------------------- src/shared/sensor_info.h | 59 ++++++++----- 3 files changed, 160 insertions(+), 115 deletions(-) diff --git a/include/sensor_types.h b/include/sensor_types.h index 5062062..5266450 100644 --- a/include/sensor_types.h +++ b/include/sensor_types.h @@ -57,6 +57,9 @@ extern "C" #define MICROSECONDS(tv) ((tv.tv_sec * 1000000ll) + tv.tv_usec) +#define SENSOR_UNKNOWN_TYPE "http://tizen.org/sensor/unknown" +#define SENSOR_UNKNOWN_NAME "Unknown" + typedef int64_t sensor_id_t; typedef void *sensor_t; diff --git a/src/shared/sensor_info.cpp b/src/shared/sensor_info.cpp index 2a2ca83..f634c50 100644 --- a/src/shared/sensor_info.cpp +++ b/src/shared/sensor_info.cpp @@ -1,7 +1,7 @@ /* * sensord * - * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,38 +17,93 @@ * */ -#include +#include "sensor_info.h" + +#include #include #include -#include #include -using std::vector; -using std::string; +#include "sensor_utils.h" + +using namespace sensor; + +sensor_info::sensor_info() +: m_type(UNKNOWN_SENSOR) +, m_type_uri(SENSOR_UNKNOWN_TYPE) +, m_uri(SENSOR_UNKNOWN_NAME) +, m_model(SENSOR_UNKNOWN_NAME) +, m_vendor(SENSOR_UNKNOWN_NAME) +, m_min_range(0) +, m_max_range(0) +, m_resolution(0) +, m_min_interval(0) +, m_max_batch_count(0) +, m_wakeup_supported(false) +, m_permission(SENSOR_PERMISSION_STANDARD) /* TODO: change it to string */ +{ +} + +sensor_info::sensor_info(const sensor_info &info) +: m_type(info.m_type) +, m_type_uri(info.m_type_uri) +, m_uri(info.m_uri) +, m_model(info.m_model) +, m_vendor(info.m_vendor) +, m_min_range(info.m_min_range) +, m_max_range(info.m_max_range) +, m_resolution(info.m_resolution) +, m_min_interval(info.m_min_interval) +, m_max_batch_count(info.m_max_batch_count) +, m_wakeup_supported(info.m_wakeup_supported) +, m_permission(SENSOR_PERMISSION_STANDARD) +{ +} + +sensor_info::sensor_info(const sensor_info_t &info) +{ + /* TODO: HAL should change name from single name to URI */ + const char *type_uri = sensor::utils::get_uri((sensor_type_t)info.type); + std::string name(type_uri); + name.append("/").append(info.name); + + set_type((sensor_type_t)info.type); + set_type_uri(type_uri); + set_uri(name.c_str()); + set_model(info.model_name); + set_vendor(info.vendor); + set_min_range(info.min_range); + set_max_range(info.max_range); + set_resolution(info.resolution); + set_min_interval(info.min_interval); + set_max_batch_count(info.max_batch_count); + set_wakeup_supported(info.wakeup_supported); + set_permission(SENSOR_PERMISSION_STANDARD); +} sensor_type_t sensor_info::get_type(void) { return m_type; } -sensor_id_t sensor_info::get_id(void) +std::string &sensor_info::get_type_uri(void) { - return m_id; + return m_type_uri; } -sensor_privilege_t sensor_info::get_privilege(void) +std::string &sensor_info::get_uri(void) { - return m_privilege; + return m_uri; } -const char* sensor_info::get_name(void) +std::string &sensor_info::get_model(void) { - return m_name.c_str(); + return m_model; } -const char* sensor_info::get_vendor(void) +std::string &sensor_info::get_vendor(void) { - return m_vendor.c_str(); + return m_vendor; } float sensor_info::get_min_range(void) @@ -71,32 +126,19 @@ int sensor_info::get_min_interval(void) return m_min_interval; } -int sensor_info::get_fifo_count(void) -{ - return m_fifo_count; -} - int sensor_info::get_max_batch_count(void) { return m_max_batch_count; } -unsigned int sensor_info::get_supported_event(void) -{ - return m_supported_event; -} - -bool sensor_info::is_supported_event(unsigned int event) +bool sensor_info::is_wakeup_supported(void) { - if (event != m_supported_event) - return false; - - return true; + return m_wakeup_supported; } -bool sensor_info::is_wakeup_supported(void) +sensor_permission_t sensor_info::get_permission(void) { - return m_wakeup_supported; + return m_permission; } void sensor_info::set_type(sensor_type_t type) @@ -104,19 +146,19 @@ void sensor_info::set_type(sensor_type_t type) m_type = type; } -void sensor_info::set_id(sensor_id_t id) +void sensor_info::set_type_uri(const char *type_uri) { - m_id = id; + m_type_uri = type_uri; } -void sensor_info::set_privilege(sensor_privilege_t privilege) +void sensor_info::set_uri(const char *name) { - m_privilege = privilege; + m_uri = name; } -void sensor_info::set_name(const char *name) +void sensor_info::set_model(const char *model) { - m_name = name; + m_model = model; } void sensor_info::set_vendor(const char *vendor) @@ -144,109 +186,98 @@ void sensor_info::set_min_interval(int min_interval) m_min_interval = min_interval; } -void sensor_info::set_fifo_count(int fifo_count) -{ - m_fifo_count = fifo_count; -} - void sensor_info::set_max_batch_count(int max_batch_count) { m_max_batch_count = max_batch_count; } -void sensor_info::set_supported_event(unsigned int event) +void sensor_info::set_wakeup_supported(bool supported) { - m_supported_event = event; + m_wakeup_supported = supported; } -void sensor_info::set_wakeup_supported(bool supported) +void sensor_info::set_permission(sensor_permission_t permission) { - m_wakeup_supported = supported; + m_permission = permission; } -void sensor_info::get_raw_data(raw_data_t &data) +void sensor_info::serialize(raw_data_t &data) { - put(data, (int) m_type); - put(data, m_id); - put(data, (int) m_privilege); - put(data, m_name); + put(data, m_type); + put(data, m_type_uri); + put(data, m_uri); + put(data, m_model); put(data, m_vendor); put(data, m_min_range); put(data, m_max_range); put(data, m_resolution); put(data, m_min_interval); - put(data, m_fifo_count); put(data, m_max_batch_count); - put(data, m_supported_event); put(data, m_wakeup_supported); + put(data, (int)m_permission); } -void sensor_info::set_raw_data(const char *data, int data_len) +void sensor_info::deserialize(const char *data, int data_len) { + int permission; + int type; + raw_data_t raw_data(&data[0], &data[data_len]); + auto it = raw_data.begin(); + it = get(it, type); + m_type = (sensor_type_t)type; + + it = get(it, m_type_uri); + it = get(it, m_uri); + it = get(it, m_model); + it = get(it, m_vendor); + it = get(it, m_min_range); + it = get(it, m_max_range); + it = get(it, m_resolution); + it = get(it, m_min_interval); + it = get(it, m_max_batch_count); + it = get(it, m_wakeup_supported); - auto it_r_data = raw_data.begin(); - - int type, privilege; - int64_t id; - - it_r_data = get(it_r_data, type); - m_type = (sensor_type_t) type; - it_r_data = get(it_r_data, id); - m_id = (sensor_id_t) id; - it_r_data = get(it_r_data, privilege); - m_privilege = (sensor_privilege_t) privilege; - it_r_data = get(it_r_data, m_name); - it_r_data = get(it_r_data, m_vendor); - it_r_data = get(it_r_data, m_min_range); - it_r_data = get(it_r_data, m_max_range); - it_r_data = get(it_r_data, m_resolution); - it_r_data = get(it_r_data, m_min_interval); - it_r_data = get(it_r_data, m_fifo_count); - it_r_data = get(it_r_data, m_max_batch_count); - it_r_data = get(it_r_data, m_supported_event); - it_r_data = get(it_r_data, m_wakeup_supported); + it = get(it, permission); + m_permission = (sensor_permission_t)permission; } void sensor_info::show(void) { - _I("Type = %d", m_type); - _I("ID = %#llx", (int64_t)m_id); - _I("Privilege = %d", (int)m_privilege); - _I("Name = %s", m_name.c_str()); + _I("Type = %s", m_type_uri.c_str()); + _I("Name = %s", m_uri.c_str()); + _I("Model = %s", m_model.c_str()); _I("Vendor = %s", m_vendor.c_str()); _I("Min_range = %f", m_min_range); _I("Max_range = %f", m_max_range); _I("Resolution = %f", m_resolution); _I("Min_interval = %d", m_min_interval); - _I("Fifo_count = %d", m_fifo_count); _I("Max_batch_count = %d", m_max_batch_count); - _I("Supported_event = %#x", m_supported_event); _I("Wakeup_supported = %d", m_wakeup_supported); + _I("Privilege = %d", (int)m_permission); } void sensor_info::clear(void) { m_type = UNKNOWN_SENSOR; - m_id = -1; - m_privilege = SENSOR_PRIVILEGE_PUBLIC; - m_name.clear(); + m_type_uri.clear(); + m_uri.clear(); + m_model.clear(); m_vendor.clear(); m_min_range = 0.0f; m_max_range = 0.0f; m_resolution = 0.0f; m_min_interval = 0; - m_fifo_count = 0; m_max_batch_count = 0; - m_supported_event = 0; m_wakeup_supported = false; + m_permission = SENSOR_PERMISSION_STANDARD; } void sensor_info::put(raw_data_t &data, int value) { char buffer[sizeof(value)]; - int *temp = (int *)buffer; + int *temp = reinterpret_cast(buffer); *temp = value; copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); @@ -256,7 +287,7 @@ void sensor_info::put(raw_data_t &data, unsigned int value) { char buffer[sizeof(value)]; - unsigned int *temp = (unsigned int *)buffer; + unsigned int *temp = reinterpret_cast(buffer); *temp = value; copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); @@ -266,7 +297,7 @@ void sensor_info::put(raw_data_t &data, int64_t value) { char buffer[sizeof(value)]; - int64_t *temp = (int64_t *) buffer; + int64_t *temp = reinterpret_cast(buffer); *temp = value; copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); @@ -276,13 +307,13 @@ void sensor_info::put(raw_data_t &data, float value) { char buffer[sizeof(value)]; - float *temp = (float *) buffer; + float *temp = reinterpret_cast(buffer); *temp = value; copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); } -void sensor_info::put(raw_data_t &data, string &value) +void sensor_info::put(raw_data_t &data, std::string &value) { put(data, (int) value.size()); @@ -327,7 +358,7 @@ raw_data_iterator sensor_info::get(raw_data_iterator it, float &value) return it + sizeof(value); } -raw_data_iterator sensor_info::get(raw_data_iterator it, string &value) +raw_data_iterator sensor_info::get(raw_data_iterator it, std::string &value) { int len; diff --git a/src/shared/sensor_info.h b/src/shared/sensor_info.h index 8a50d64..4fbabe8 100644 --- a/src/shared/sensor_info.h +++ b/src/shared/sensor_info.h @@ -1,7 +1,7 @@ /* * sensord * - * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,68 +17,76 @@ * */ -#ifndef _SENSOR_INFO_H_ -#define _SENSOR_INFO_H_ +#ifndef __SENSOR_INFO_H__ +#define __SENSOR_INFO_H__ #include -#include #include #include +#include +#include + +namespace sensor { typedef std::vector raw_data_t; typedef raw_data_t::iterator raw_data_iterator; +/* TODO: builder */ class sensor_info { public: + sensor_info(); + sensor_info(const sensor_info &info); + sensor_info(const sensor_info_t &info); + + /* TODO: it would be better to get_type() returns type(URI) */ sensor_type_t get_type(void); - sensor_id_t get_id(void); - sensor_privilege_t get_privilege(void); - const char* get_name(void); - const char* get_vendor(void); + std::string &get_type_uri(void); + std::string &get_uri(void); + std::string &get_model(void); + std::string & get_vendor(void); float get_min_range(void); float get_max_range(void); float get_resolution(void); int get_min_interval(void); - int get_fifo_count(void); int get_max_batch_count(void); - unsigned int get_supported_event(void); - bool is_supported_event(unsigned int event); bool is_wakeup_supported(void); + sensor_permission_t get_permission(void); + /* TODO: it would be better to get_type() returns type(URI) */ void set_type(sensor_type_t type); - void set_id(sensor_id_t id); - void set_privilege(sensor_privilege_t privilege); - void set_name(const char *name); + void set_type_uri(const char *type_uri); + void set_uri(const char *name); + void set_model(const char *name); void set_vendor(const char *vendor); void set_min_range(float min_range); void set_max_range(float max_range); void set_resolution(float resolution); void set_min_interval(int min_interval); - void set_fifo_count(int fifo_count); void set_max_batch_count(int max_batch_count); - void set_supported_event(unsigned int event); void set_wakeup_supported(bool supported); + void set_permission(sensor_permission_t permission); void clear(void); - void get_raw_data(raw_data_t &data); - void set_raw_data(const char *data, int data_len); + void serialize(raw_data_t &data); + void deserialize(const char *data, int data_len); void show(void); + private: sensor_type_t m_type; - sensor_id_t m_id; - sensor_privilege_t m_privilege; - std::string m_name; + std::string m_type_uri; + std::string m_uri; + std::string m_model; std::string m_vendor; float m_min_range; float m_max_range; float m_resolution; int m_min_interval; - int m_fifo_count; int m_max_batch_count; - unsigned int m_supported_event; bool m_wakeup_supported; + sensor_permission_t m_permission; + /* TODO: use template */ void put(raw_data_t &data, int value); void put(raw_data_t &data, unsigned int value); void put(raw_data_t &data, int64_t value); @@ -86,6 +94,7 @@ private: void put(raw_data_t &data, std::string &value); void put(raw_data_t &data, bool value); + /* TODO: use template */ raw_data_iterator get(raw_data_iterator it, int &value); raw_data_iterator get(raw_data_iterator it, unsigned int &value); raw_data_iterator get(raw_data_iterator it, int64_t &value); @@ -94,4 +103,6 @@ private: raw_data_iterator get(raw_data_iterator it, bool &value); }; -#endif /* _SENSOR_INFO_H_ */ +} + +#endif /* __SENSOR_INFO_H__ */ -- 2.7.4 From c5b5c233520c5c4246ca257dd4a7fe3a5b0472c6 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 13:06:01 +0900 Subject: [PATCH 07/16] sensord: api: add skeleton code of internal apis - sensor_manager can stores and manages all of sensors. - sensor_listener can listen sensor event and modify sensor configuation (interval, option, batch_latency, attributes and so on) - rename client.cpp to sensor_internal.cpp Change-Id: I15b74b777ba70d9c7b7d7a2c597fabf91f259b2c Signed-off-by: kibak.yoon --- src/client/{client.cpp => sensor_internal.cpp} | 0 src/client/sensor_listener.cpp | 201 +++++++++++++++++++++++++ src/client/sensor_listener.h | 95 ++++++++++++ src/client/sensor_manager.cpp | 148 ++++++++++++++++++ src/client/sensor_manager.h | 82 ++++++++++ 5 files changed, 526 insertions(+) rename src/client/{client.cpp => sensor_internal.cpp} (100%) create mode 100644 src/client/sensor_listener.cpp create mode 100644 src/client/sensor_listener.h create mode 100644 src/client/sensor_manager.cpp create mode 100644 src/client/sensor_manager.h diff --git a/src/client/client.cpp b/src/client/sensor_internal.cpp similarity index 100% rename from src/client/client.cpp rename to src/client/sensor_internal.cpp diff --git a/src/client/sensor_listener.cpp b/src/client/sensor_listener.cpp new file mode 100644 index 0000000..83145ef --- /dev/null +++ b/src/client/sensor_listener.cpp @@ -0,0 +1,201 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "sensor_listener.h" + +#include +#include +#include +#include +#include + +using namespace sensor; + +class listener_handler : public ipc::channel_handler +{ +public: + listener_handler(sensor_listener *listener) + : m_listener(listener) + {} + void connected(ipc::channel *ch) {} + void disconnected(ipc::channel *ch) {} + void read(ipc::channel *ch, ipc::message &msg) {} + void read_complete(ipc::channel *ch) {} + void error_caught(ipc::channel *ch, int error) {} + +private: + sensor_listener *m_listener; +}; + +sensor_listener::sensor_listener(sensor_t sensor) +: m_id(0) +, m_sensor(reinterpret_cast(sensor)) +, m_client(NULL) +, m_channel(NULL) +, m_handler(NULL) +, m_evt_handler(NULL) +, m_acc_handler(NULL) +, m_connected(false) +, m_started(false) +{ + init(); +} + +sensor_listener::~sensor_listener() +{ + deinit(); +} + +bool sensor_listener::init(void) +{ + return true; +} + +void sensor_listener::deinit(void) +{ +} + +int sensor_listener::get_id(void) +{ + return m_id; +} + +sensor_t sensor_listener::get_sensor(void) +{ + return static_cast(m_sensor); +} + +void sensor_listener::restore(void) +{ + _D("Restored listener[%d]", get_id()); +} + +bool sensor_listener::connect(void) +{ + _I("Listener ID[%d]", get_id()); + + return true; +} + +void sensor_listener::disconnect(void) +{ + _I("Disconnected[%d]", get_id()); +} + +bool sensor_listener::is_connected(void) +{ + return m_connected.load(); +} + +ipc::channel_handler *sensor_listener::get_event_handler(void) +{ + return m_evt_handler; +} + +void sensor_listener::set_event_handler(ipc::channel_handler *handler) +{ + m_evt_handler = handler; +} + +void sensor_listener::unset_event_handler(void) +{ + delete m_evt_handler; + m_evt_handler = NULL; +} + +ipc::channel_handler *sensor_listener::get_accuracy_handler(void) +{ + return m_acc_handler; +} + +void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler) +{ + m_acc_handler = handler; +} + +void sensor_listener::unset_accuracy_handler(void) +{ + m_acc_handler = NULL; +} + +int sensor_listener::start(void) +{ + return OP_ERROR; +} + +int sensor_listener::stop(void) +{ + return OP_ERROR; +} + +int sensor_listener::get_interval(void) +{ + return OP_ERROR; +} + +int sensor_listener::get_max_batch_latency(void) +{ + return OP_ERROR; +} + +int sensor_listener::get_pause_policy(void) +{ + return OP_ERROR; +} + +int sensor_listener::get_passive_mode(void) +{ + return OP_ERROR; +} + +int sensor_listener::set_interval(unsigned int interval) +{ + return OP_ERROR; +} + +int sensor_listener::set_max_batch_latency(unsigned int max_batch_latency) +{ + return OP_ERROR; +} + +int sensor_listener::set_passive_mode(bool passive) +{ + return OP_ERROR; +} + +int sensor_listener::flush(void) +{ + return OP_ERROR; +} + +int sensor_listener::set_attribute(int attribute, int value) +{ + return OP_ERROR; +} + +int sensor_listener::set_attribute(int attribute, const char *value, int len) +{ + return OP_ERROR; +} + +int sensor_listener::get_sensor_data(sensor_data_t *data) +{ + return OP_ERROR; +} + diff --git a/src/client/sensor_listener.h b/src/client/sensor_listener.h new file mode 100644 index 0000000..ea30092 --- /dev/null +++ b/src/client/sensor_listener.h @@ -0,0 +1,95 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __SENSOR_LISTENER_H__ +#define __SENSOR_LISTENER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sensor { + +class sensor_listener { +public: + sensor_listener(sensor_t sensor); + virtual ~sensor_listener(); + + int get_id(void); + sensor_t get_sensor(void); + + ipc::channel_handler *get_event_handler(void); + ipc::channel_handler *get_accuracy_handler(void); + + /* TODO: modify the listener so that it can register multiple handlers(1:n) */ + void set_event_handler(ipc::channel_handler *handler); + void set_accuracy_handler(ipc::channel_handler *handler); + + void unset_event_handler(void); + void unset_accuracy_handler(void); + + int start(void); + int stop(void); + + int get_interval(void); + int get_max_batch_latency(void); + int get_pause_policy(void); + int get_passive_mode(void); + + int set_interval(unsigned int interval); + int set_max_batch_latency(unsigned int max_batch_latency); + int set_passive_mode(bool passive); + int set_attribute(int attribute, int value); + int set_attribute(int attribute, const char *value, int len); + + int get_sensor_data(sensor_data_t *data); + int flush(void); + + void restore(void); + +private: + bool init(void); + void deinit(void); + + bool connect(void); + void disconnect(void); + bool is_connected(void); + + int m_id; + sensor_info *m_sensor; + + ipc::ipc_client *m_client; + ipc::channel *m_channel; + ipc::channel_handler *m_handler; + ipc::channel_handler *m_evt_handler; + ipc::channel_handler *m_acc_handler; + ipc::event_loop m_loop; + std::atomic m_connected; + std::atomic m_started; + std::map m_attributes; +}; + +} + +#endif /* __SENSOR_LISTENER_H__ */ diff --git a/src/client/sensor_manager.cpp b/src/client/sensor_manager.cpp new file mode 100644 index 0000000..3a4742b --- /dev/null +++ b/src/client/sensor_manager.cpp @@ -0,0 +1,148 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "sensor_manager.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace sensor; + +class manager_handler : public ipc::channel_handler +{ +public: + manager_handler(sensor_manager *manager) + : m_manager(manager) + {} + void connected(ipc::channel *ch) {} + void disconnected(ipc::channel *ch) {} + void read(ipc::channel *ch, ipc::message &msg) {} + void read_complete(ipc::channel *ch) {} + void error_caught(ipc::channel *ch, int error) {} + +private: + sensor_manager *m_manager; +}; + +sensor_manager::sensor_manager() +: m_client(NULL) +, m_handler(NULL) +, m_channel(NULL) +, m_connected(false) +{ + init(); +} + +sensor_manager::~sensor_manager() +{ + deinit(); +} + +int sensor_manager::get_sensor(sensor_type_t type, sensor_t *sensor) +{ + return OP_ERROR; +} + +int sensor_manager::get_sensors(sensor_type_t type, sensor_t **list, int *count) +{ + return OP_ERROR; +} + +int sensor_manager::get_sensor(const char *uri, sensor_t *sensor) +{ + return OP_ERROR; +} + +int sensor_manager::get_sensors(const char *uri, sensor_t **list, int *count) +{ + return OP_ERROR; +} + +bool sensor_manager::is_supported(sensor_t sensor) +{ + return false; +} + +bool sensor_manager::is_supported(const char *uri) +{ + return false; +} + +bool sensor_manager::init(void) +{ + return true; +} + +void sensor_manager::deinit(void) +{ +} + +bool sensor_manager::connect_channel(void) +{ + _D("Connected"); + return true; +} + +bool sensor_manager::connect(void) +{ + return false; +} + +void sensor_manager::disconnect(void) +{ + _D("Disconnected"); +} + +bool sensor_manager::is_connected(void) +{ + return m_connected.load(); +} + +void sensor_manager::restore(void) +{ + _D("Restored manager"); +} + +void sensor_manager::decode_sensors(const char *buf, std::vector &infos) +{ + int count = 0; + _D("Sensor count : %d", count); +} + +bool sensor_manager::get_sensors_internal(void) +{ + return true; +} + +sensor_info *sensor_manager::get_info(const char *uri) +{ + return NULL; +} + +std::vector sensor_manager::get_infos(const char *uri) +{ + std::vector infos; + return infos; +} + diff --git a/src/client/sensor_manager.h b/src/client/sensor_manager.h new file mode 100644 index 0000000..35ae863 --- /dev/null +++ b/src/client/sensor_manager.h @@ -0,0 +1,82 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __SENSOR_MANAGER_H__ +#define __SENSOR_MANAGER_H__ + +#include +#include +#include +#include +#include +#include + +#include "sensor_internal.h" + +namespace sensor { + +class sensor_manager { +public: + sensor_manager(); + virtual ~sensor_manager(); + + bool connect(void); + void disconnect(void); + + int get_sensor(sensor_type_t type, sensor_t *sensor); + int get_sensors(sensor_type_t type, sensor_t **list, int *count); + int get_sensor(const char *uri, sensor_t *sensor); + int get_sensors(const char *uri, sensor_t **list, int *count); + + bool is_supported(sensor_t sensor); + bool is_supported(const char *uri); + + void restore(void); + + /* TODO: register sensor_provider by using manager */ + /* int register_sensor(sensor_provider *provider); */ + /* int unregister_sensor(const char *uri) */ + +private: + typedef std::vector sensor_infos_t; + + bool init(void); + void deinit(void); + + bool connect_channel(void); + bool is_connected(void); + + void decode_sensors(const char *buf, std::vector &infos); + bool get_sensors_internal(void); + + sensor_info *get_info(const char *uri); + std::vector get_infos(const char *uri); + + ipc::ipc_client *m_client; + ipc::channel_handler *m_handler; + ipc::channel *m_channel; + ipc::event_loop m_loop; + std::atomic m_connected; + + sensor_infos_t m_infos; +}; + +} + +#endif /* __SENSOR_MANAGER_H__ */ -- 2.7.4 From f192807171708e30d467c3a11cea4855f6bcd947 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 13:50:49 +0900 Subject: [PATCH 08/16] sensor: api: implement internal api using classes - check invalid parameters. - call proper operations/functions. Change-Id: I61b9813a3f77cfd116a8ea72ee417f4cb7356640 Signed-off-by: kibak.yoon --- src/client/sensor_internal.cpp | 532 +++++++++++++++++++++++++++++------------ 1 file changed, 373 insertions(+), 159 deletions(-) diff --git a/src/client/sensor_internal.cpp b/src/client/sensor_internal.cpp index 0864b14..f9b2698 100644 --- a/src/client/sensor_internal.cpp +++ b/src/client/sensor_internal.cpp @@ -17,184 +17,270 @@ * */ -#include "sensor_internal.h" -#include +#include +#include +#include + +#include +#include +#include #include +#include + +#define CONVERT_OPTION_PAUSE_POLICY(option) ((option) ^ 0b11) + +using namespace sensor; + +class sensor_event_handler : public ipc::channel_handler +{ +public: + sensor_event_handler(sensor_t sensor, sensor_cb_t cb, void *user_data) + : m_sensor(reinterpret_cast(sensor)) + , m_cb(cb) + , m_user_data(user_data) + {} + + void connected(ipc::channel *ch) {} + void disconnected(ipc::channel *ch) {} + void read(ipc::channel *ch, ipc::message &msg) + { + int event_type; + sensor_data_t *data; + + data = reinterpret_cast(msg.body()); + event_type = CONVERT_TYPE_EVENT(m_sensor->get_type()); + + m_cb(m_sensor, event_type, data, m_user_data); + } + + void read_complete(ipc::channel *ch) {} + void error_caught(ipc::channel *ch, int error) {} + +private: + sensor_info *m_sensor; + sensor_cb_t m_cb; + void *m_user_data; +}; + +class sensor_accuracy_handler : public ipc::channel_handler +{ +public: + sensor_accuracy_handler(sensor_t sensor, sensor_accuracy_changed_cb_t cb, void *user_data) + : m_sensor(reinterpret_cast(sensor)) + , m_cb(cb) + , m_user_data(user_data) + {} + + void connected(ipc::channel *ch) {} + void disconnected(ipc::channel *ch) {} + void read(ipc::channel *ch, ipc::message &msg) + { + sensor_data_t *data; + data = reinterpret_cast(msg.body()); + + m_cb(m_sensor, data->timestamp, data->accuracy, m_user_data); + } + + void read_complete(ipc::channel *ch) {} + void error_caught(ipc::channel *ch, int error) {} + +private: + sensor_info *m_sensor; + sensor_accuracy_changed_cb_t m_cb; + void *m_user_data; +}; + +static sensor::sensor_manager manager; +static std::unordered_map listeners; /* * TO-DO-LIST: - * 1. restore session - * 1.1 close socket - * 1.2 listener : start, interval, batch latency, attributes - * 2. power save option / lcd vconf : move to server - * 3. clean up data - * 4. thread-safe : ipc_client - * 5. client-id - * 6. cmd_hello - * 7. stop : unset interval, batch - * 8. get sensor list + * 1. power save option / lcd vconf : move to server + * 2. thread-safe : ipc_client */ API int sensord_get_sensors(sensor_type_t type, sensor_t **list, int *count) { - /* - * 1. get sensor list() - * 2. if sensor list is empty, return -ENODATA - * 3. if id is -EACCESS, return -EACCESS (except ALL_SENSOR) - * 4. list : memory allocation - * 5. return list, count - */ + int ret = OP_ERROR; + + retvm_if((!list || !count), -EINVAL, + "Invalid parameter[%#x, %#x]", list, count); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + ret = manager.get_sensors(type, list, count); + retv_if(ret < 0, ret); return OP_SUCCESS; } API int sensord_get_default_sensor(sensor_type_t type, sensor_t *sensor) { - /* - * 1. get sensor list() - * 2. if there is no sensor, return -ENODATA - * 3. if id is -EACCESS, return -EACCESS - * 4. if SENSOR_ALL, ??? - * 5. return sensor - */ + int ret = OP_ERROR; + + retvm_if(!sensor, -EPERM, "Invalid parameter[%#x]", sensor); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + ret = manager.get_sensor(type, sensor); + retv_if(ret < 0, ret); return OP_SUCCESS; } API bool sensord_get_type(sensor_t sensor, sensor_type_t *type) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + retvm_if(!type, false, "Invalid parameter[%#x]", type); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); + + *type = static_cast(sensor)->get_type(); return true; } API const char* sensord_get_name(sensor_t sensor) { - /* - * 1. if there is no sensor, return NULL - */ + retvm_if(!manager.connect(), NULL, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), NULL, + "Invalid sensor[%#x]", sensor); - return NULL; + return static_cast(sensor)->get_uri().c_str(); } API const char* sensord_get_vendor(sensor_t sensor) { - /* - * 1. if there is no sensor, return NULL - */ + retvm_if(!manager.connect(), NULL, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), NULL, + "Invalid sensor[%#x]", sensor); - return NULL; + return static_cast(sensor)->get_vendor().c_str(); } API bool sensord_get_privilege(sensor_t sensor, sensor_privilege_t *privilege) { - /* - * 1. check parameter - * 2. if there is no sensor, return false + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!privilege, false, "Invalid parameter[%#x]", privilege); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); + + /* TODO: + * sensor_permission_t perm = static_cast(sensor)->get_permission(); + * *privilege = static_cast(perm); */ + *privilege = SENSOR_PRIVILEGE_PUBLIC; return true; } API bool sensord_get_min_range(sensor_t sensor, float *min_range) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!min_range, false, "Invalid parameter[%#x]", min_range); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); + + *min_range = static_cast(sensor)->get_min_range(); return true; } API bool sensord_get_max_range(sensor_t sensor, float *max_range) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + retvm_if(!max_range, false, "Invalid parameter[%#x]", max_range); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); + + *max_range = static_cast(sensor)->get_max_range(); return true; } API bool sensord_get_resolution(sensor_t sensor, float *resolution) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + retvm_if(!resolution, false, "Invalid parameter[%#x]", resolution); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); + + *resolution = static_cast(sensor)->get_resolution(); return true; } API bool sensord_get_min_interval(sensor_t sensor, int *min_interval) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + retvm_if(!min_interval, false, "Invalid parameter[%#x]", min_interval); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); + + *min_interval = static_cast(sensor)->get_min_interval(); return true; } API bool sensord_get_fifo_count(sensor_t sensor, int *fifo_count) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + retvm_if(!fifo_count, false, "Invalid parameter[%#x]", fifo_count); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); + + *fifo_count = 0; return true; } API bool sensord_get_max_batch_count(sensor_t sensor, int *max_batch_count) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + retvm_if(!max_batch_count, false, "Invalid parameter[%#x]", max_batch_count); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); + + *max_batch_count = static_cast(sensor)->get_max_batch_count(); return true; } API bool sensord_is_wakeup_supported(sensor_t sensor) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%#x]", sensor); - return true; + return static_cast(sensor)->is_wakeup_supported(); } API int sensord_connect(sensor_t sensor) { - /* - * 1. check parameter - * 2. if there is no sensor, return -EPERM - * 3. sensor is already registered(sensor), it doesn't need to connect server - * 4. create integer handle for only this client - * 5. if it is first connection(client), get client id from server - * 6. if it is first connection(client), start sensor event listener - * 7. sensor initialization : stop, pause_all - * 8. if it is first connection(client), send cmd hello - * 9. if cmd hello is failed and it is first connection(client) stop listener, remove id - */ + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), -EINVAL, + "Invalid sensor[%#x]", sensor); - return 0; + sensor::sensor_listener *listener; + + listener = new(std::nothrow) sensor::sensor_listener(sensor); + retvm_if(!listener, -ENOMEM, "Failed to allocate memory"); + + listeners[listener->get_id()] = listener; + + return listener->get_id(); } API bool sensord_disconnect(int handle) { - /* - * 1. check parameter(check handle???) - * 2. check state of this handle - * 3. if it is on passive mode, unregister event and unset interval/latency - * 4. if it is not stop, stop it - * 5. if there is no active sensor(client), reset id & byebye and stop listener - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + retvm_if(!listener, false, "Invalid handle[%d]", handle); + + delete listener; + listeners.erase(handle); return true; } @@ -202,148 +288,270 @@ API bool sensord_disconnect(int handle) API bool sensord_register_event(int handle, unsigned int event_type, unsigned int interval, unsigned int max_batch_latency, sensor_cb_t cb, void *user_data) { - /* - * 1. check parameter - * 2. if interval is 0, default interval - * ** if cb is null, how to handle it? - * ** event type is deprecated - */ + sensor::sensor_listener *listener; + int prev_interval; + int prev_max_batch_latency; + sensor_event_handler *handler; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + prev_interval = listener->get_interval(); + prev_max_batch_latency = listener->get_max_batch_latency(); + + if (listener->set_interval(interval) < 0) { + _E("Failed to set interval"); + return false; + } + + if (listener->set_max_batch_latency(max_batch_latency) < 0) { + listener->set_interval(prev_interval); + _E("Failed to set max_batch_latency"); + return false; + } + + handler = new(std::nothrow) sensor_event_handler(listener->get_sensor(), cb, user_data); + if (!handler) { + listener->set_max_batch_latency(prev_max_batch_latency); + listener->set_interval(prev_interval); + _E("Failed to allocate memory"); + return false; + } + + listener->set_event_handler(handler); return true; } API bool sensord_unregister_event(int handle, unsigned int event_type) { - /* - * 1. check parameter - * 2. check previous interval, latency, cb, user_data - * 3. if passive mode is true, set false - * 4. if ret is false, register event - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + listener->unset_event_handler(); return true; } API bool sensord_register_accuracy_cb(int handle, sensor_accuracy_changed_cb_t cb, void *user_data) { - /* - * 1. check parameter - */ + sensor::sensor_listener *listener; + sensor_accuracy_handler *handler; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + handler = new(std::nothrow) sensor_accuracy_handler(listener->get_sensor(), cb, user_data); + retvm_if(!handler, false, "Failed to allocate memory"); + + listener->set_accuracy_handler(handler); return true; } API bool sensord_unregister_accuracy_cb(int handle) { - /* - * 1. check parameter - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + listener->unset_accuracy_handler(); return true; } API bool sensord_start(int handle, int option) { - /* - * 1. check parameter - * 2. pause = CONVERT_OPTION_PAUSE_POLICY(option) - * 3. start listener - */ + sensor::sensor_listener *listener; + int prev_pause; + int pause; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + pause = CONVERT_OPTION_PAUSE_POLICY(option); + prev_pause = listener->get_pause_policy(); + + if (listener->set_attribute(SENSORD_ATTRIBUTE_PAUSE_POLICY, pause) < 0) { + _E("Failed to set pause policy[%d]", pause); + return false; + } + + if (listener->start() < 0) { + listener->set_attribute(SENSORD_ATTRIBUTE_PAUSE_POLICY, prev_pause); + _E("Failed to start listener"); + return false; + } return true; } API bool sensord_stop(int handle) { - /* - * 1. check parameter - * 2. check sensor state, id - * 2.1. if sensor is already stopped, return true - * 3. stop listener - */ + int ret; + sensor::sensor_listener *listener; - return true; + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + ret = listener->stop(); + + if (ret == -EAGAIN || ret == OP_SUCCESS) + return true; + + return false; } API bool sensord_change_event_interval(int handle, unsigned int event_type, unsigned int interval) { - /* - * 1. check parameter - * 2. if interval is 0, default interval - * 3. if previous interval is lower than interval, return true - * 4. change interval - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_interval(interval) < 0) { + _E("Failed to set interval to listener"); + return false; + } return true; } API bool sensord_change_event_max_batch_latency(int handle, unsigned int event_type, unsigned int max_batch_latency) { - /* - * 1. check parameter - * 2. if previous interval is lower than interval, return true - * 3. change batch latency - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_max_batch_latency(max_batch_latency) < 0) { + _E("Failed to set max_batch_latency to listener"); + return false; + } return true; } API bool sensord_set_option(int handle, int option) { - /* - * change option, always-on/power save option/lcd off/default - */ + sensor::sensor_listener *listener; + int pause; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + pause = CONVERT_OPTION_PAUSE_POLICY(option); + + if (listener->set_attribute(SENSORD_ATTRIBUTE_PAUSE_POLICY, pause) < 0) { + _E("Failed to set option[%d(%d)] to listener", option, pause); + return false; + } return true; } API int sensord_set_attribute_int(int handle, int attribute, int value) { - /* - * 1. if ATTRIBUTE_PAUSE_POLICY - * 2. if ATTRIBUTE_AXIS_ORIENTATION - * 3. else attribute - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), -EINVAL, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_attribute(attribute, value) < 0) { + _E("Failed to set attribute[%d, %d]", attribute, value); + return -EIO; + } return OP_SUCCESS; } API int sensord_set_attribute_str(int handle, int attribute, const char *value, int len) { - /* - * 1. check parameter - * 2. if client id is invalid, return -EPERM - * 3. if there is other problems, return -EPERM - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), -EINVAL, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_attribute(attribute, value, len) < 0) { + _E("Failed to set attribute[%d, %s]", attribute, value); + return -EIO; + } return OP_SUCCESS; } API bool sensord_get_data(int handle, unsigned int data_id, sensor_data_t* sensor_data) { - /* - * 1. check parameter - * 2. check sensor state(is it really needed?) - * 3. get data - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->get_sensor_data(sensor_data) < 0) { + _E("Failed to get sensor data from listener"); + return false; + } return true; } API bool sensord_flush(int handle) { - /* - * 1. check parameter - * 2. check sensor state(is it really needed?) - * 3. flush sensor - */ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->flush() < 0) { + _E("Failed to flush sensor"); + return false; + } return true; } API bool sensord_set_passive_mode(int handle, bool passive) { - /* set passive mode*/ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_passive_mode(passive) < 0) { + _E("Failed to set passive mode"); + return false; + } return true; } @@ -387,7 +595,12 @@ API bool sensord_external_post(int handle, unsigned long long timestamp, const f /* deperecated */ API sensor_t sensord_get_sensor(sensor_type_t type) { - return NULL; + sensor_t sensor; + + if (sensord_get_default_sensor(type, &sensor) < 0) + return NULL; + + return sensor; } /* deprecated */ @@ -417,10 +630,11 @@ API bool sensord_get_supported_event_types(sensor_t sensor, unsigned int **event /* deprecated(BUT it is used in C-API....) */ API bool sensord_is_supported_event_type(sensor_t sensor, unsigned int event_type, bool *supported) { - /* - * 1. check parameter - * 2. if there is no sensor, return false - */ + if (!manager.is_supported(sensor)) + *supported = false; + else + *supported = true; + return true; } -- 2.7.4 From c5fe24434065b980e9cccd728454d06b8ae04fd5 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 14:42:25 +0900 Subject: [PATCH 09/16] sensord: implement sensor_manager class for clients - sensor_manager provides: - store sensor information and manages all sensor handles - check whether the sensor is supported or not - [TBD]listen an event that the application sensor is connected or disconnected Change-Id: Icd38a74058170162bbfa8c7df6d1bdcc41d80e2d Signed-off-by: kibak.yoon --- include/sensor_types.h | 2 + src/client/sensor_manager.cpp | 163 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 158 insertions(+), 7 deletions(-) diff --git a/include/sensor_types.h b/include/sensor_types.h index 5266450..2253a29 100644 --- a/include/sensor_types.h +++ b/include/sensor_types.h @@ -60,6 +60,8 @@ extern "C" #define SENSOR_UNKNOWN_TYPE "http://tizen.org/sensor/unknown" #define SENSOR_UNKNOWN_NAME "Unknown" +#define SENSOR_URI_PERMISSION_DENIED "http://tizen.org/sensor/EACCES" + typedef int64_t sensor_id_t; typedef void *sensor_t; diff --git a/src/client/sensor_manager.cpp b/src/client/sensor_manager.cpp index 3a4742b..9a93cb5 100644 --- a/src/client/sensor_manager.cpp +++ b/src/client/sensor_manager.cpp @@ -36,8 +36,18 @@ public: : m_manager(manager) {} void connected(ipc::channel *ch) {} - void disconnected(ipc::channel *ch) {} - void read(ipc::channel *ch, ipc::message &msg) {} + void disconnected(ipc::channel *ch) + { + /* If channel->disconnect() is not explicitly called, it will be restored */ + m_manager->restore(); + } + + void read(ipc::channel *ch, ipc::message &msg) + { + /* TODO: if dynamic sensor is loaded, + * it will be called with the sensor information */ + } + void read_complete(ipc::channel *ch) {} void error_caught(ipc::channel *ch, int error) {} @@ -61,56 +71,134 @@ sensor_manager::~sensor_manager() int sensor_manager::get_sensor(sensor_type_t type, sensor_t *sensor) { - return OP_ERROR; + return get_sensor(utils::get_uri(type), sensor); } int sensor_manager::get_sensors(sensor_type_t type, sensor_t **list, int *count) { - return OP_ERROR; + return get_sensors(utils::get_uri(type), list, count); } int sensor_manager::get_sensor(const char *uri, sensor_t *sensor) { - return OP_ERROR; + sensor_info *info; + + info = get_info(uri); + if (!info) { + *sensor = NULL; + return -ENODATA; + } + + if (info->get_uri() == SENSOR_URI_PERMISSION_DENIED) + return -EACCES; + + *sensor = (sensor_t)info; + return OP_SUCCESS; } int sensor_manager::get_sensors(const char *uri, sensor_t **list, int *count) { - return OP_ERROR; + std::vector infos; + int size; + + infos = get_infos(uri); + size = infos.size(); + + if (size == 0) { + *count = 0; + return -ENODATA; + } + + if (infos[0]->get_uri() == SENSOR_URI_PERMISSION_DENIED) + return -EACCES; + + *list = (sensor_t *)malloc(sizeof(sensor_info *) * size); + retvm_if(!*list, -ENOMEM, "Failed to allocate memory"); + + for (int i = 0; i < size; ++i) + *(*list + i) = infos[i]; + + *count = size; + return OP_SUCCESS; } bool sensor_manager::is_supported(sensor_t sensor) { + retvm_if(!sensor, false, "Invalid parameter[%#x]", sensor); + + for (auto it = m_infos.begin(); it != m_infos.end(); ++it) { + if (&*it == sensor) + return true; + } + return false; } bool sensor_manager::is_supported(const char *uri) { + for (auto it = m_infos.begin(); it != m_infos.end(); ++it) { + if ((*it).get_uri() == uri) + return true; + } + return false; } bool sensor_manager::init(void) { + m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH); + retvm_if(!m_client, false, "Failed to allocate memory"); + + m_handler = new(std::nothrow) manager_handler(this); + if (!m_handler) { + delete m_client; + m_client = NULL; + return false; + } + return true; } void sensor_manager::deinit(void) { + disconnect(); + + delete m_handler; + m_handler = NULL; + + delete m_client; + m_client = NULL; } bool sensor_manager::connect_channel(void) { + m_channel = m_client->connect(m_handler, &m_loop); + retvm_if(!m_channel, false, "Failed to connect to server"); + + m_connected.store(true); + _D("Connected"); return true; } bool sensor_manager::connect(void) { - return false; + retv_if(is_connected(), true); + retv_if(!connect_channel(), false); + + return get_sensors_internal(); } void sensor_manager::disconnect(void) { + ret_if(!is_connected()); + + m_connected.store(false); + m_channel->disconnect(); + + delete m_channel; + m_channel = NULL; + _D("Disconnected"); } @@ -121,28 +209,89 @@ bool sensor_manager::is_connected(void) void sensor_manager::restore(void) { + ret_if(!is_connected()); + + m_connected.store(false); + retm_if(!connect_channel(), "Failed to restore manager"); + _D("Restored manager"); } void sensor_manager::decode_sensors(const char *buf, std::vector &infos) { int count = 0; + sensor_info info; + const size_t *size; + const char *data; + cmd_manager_sensor_list_t *raw; + + raw = (cmd_manager_sensor_list_t *)buf; + count = raw->sensor_cnt; + size = (const size_t *)raw->data; + data = (const char *)raw->data + sizeof(size_t); + + for (int i = 0; i < count; ++i) { + info.clear(); + info.deserialize(data, size[0]); + infos.push_back(info); + + size = (const size_t *)((const char *)data + size[0]); + data = (const char *)size + sizeof(size_t); + } + _D("Sensor count : %d", count); } bool sensor_manager::get_sensors_internal(void) { + retvm_if(!is_connected(), false, "Failed to get sensors"); + + bool ret; + ipc::message msg; + ipc::message reply; + char buf[MAX_BUF_SIZE]; + + msg.set_type(CMD_MANAGER_SENSOR_LIST); + + ret = m_channel->send_sync(&msg); + retvm_if(!ret, false, "Failed to send message"); + + ret = m_channel->read_sync(reply); + retvm_if(!ret, false, "Failed to receive message"); + + reply.disclose(buf); + + decode_sensors(buf, m_infos); + return true; } sensor_info *sensor_manager::get_info(const char *uri) { + if (strncmp(uri, utils::get_uri(ALL_SENSOR), 27) == 0) + return &m_infos[0]; + + for (auto it = m_infos.begin(); it != m_infos.end(); ++it) { + if ((*it).get_uri() == uri) + return &*it; + } + return NULL; } std::vector sensor_manager::get_infos(const char *uri) { std::vector infos; + bool all = false; + + if (strncmp(uri, utils::get_uri(ALL_SENSOR), 27) == 0) + all = true; + + for (auto it = m_infos.begin(); it != m_infos.end(); ++it) { + if (all || (*it).get_type_uri() == uri) + infos.push_back(&*it); + } + return infos; } -- 2.7.4 From d1e1914574deef5df62b3a3c38f11c1658e79ae9 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 15:33:47 +0900 Subject: [PATCH 10/16] sensord: implement sensor_listener class for clients - sensor_listener provides: - controls for sensor actions such as start and stop. - controls for changing sensor settings - listening for sensor events from server Change-Id: I7216b282cc3429d0864b4343d65ff192951b1038 Signed-off-by: kibak.yoon --- src/client/sensor_listener.cpp | 238 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 222 insertions(+), 16 deletions(-) diff --git a/src/client/sensor_listener.cpp b/src/client/sensor_listener.cpp index 83145ef..da9dbe8 100644 --- a/src/client/sensor_listener.cpp +++ b/src/client/sensor_listener.cpp @@ -34,8 +34,25 @@ public: : m_listener(listener) {} void connected(ipc::channel *ch) {} - void disconnected(ipc::channel *ch) {} - void read(ipc::channel *ch, ipc::message &msg) {} + void disconnected(ipc::channel *ch) + { + /* If channel->disconnect() is not explicitly called, + * listener will be restored */ + m_listener->restore(); + } + + void read(ipc::channel *ch, ipc::message &msg) + { + switch (msg.header()->type) { + case CMD_LISTENER_EVENT: + if (m_listener->get_event_handler()) + m_listener->get_event_handler()->read(ch, msg); + case CMD_LISTENER_ACC_EVENT: + if (m_listener->get_accuracy_handler()) + m_listener->get_accuracy_handler()->read(ch, msg); + } + } + void read_complete(ipc::channel *ch) {} void error_caught(ipc::channel *ch, int error) {} @@ -64,11 +81,37 @@ sensor_listener::~sensor_listener() bool sensor_listener::init(void) { + m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH); + retvm_if(!m_client, false, "Failed to allocate memory"); + + m_handler = new(std::nothrow) listener_handler(this); + if (!m_handler) { + delete m_client; + return false; + } + + if (!connect()) { + delete m_handler; + delete m_client; + m_handler = NULL; + m_client = NULL; + return false; + } + return true; } void sensor_listener::deinit(void) { + disconnect(); + + delete m_handler; + m_handler = NULL; + + delete m_client; + m_client = NULL; + + m_attributes.clear(); } int sensor_listener::get_id(void) @@ -83,18 +126,66 @@ sensor_t sensor_listener::get_sensor(void) void sensor_listener::restore(void) { + ret_if(!is_connected()); + retm_if(!connect(), "Failed to restore listener"); + + /* Restore attributes/status */ + if (m_started.load()) + start(); + + auto interval = m_attributes.find(SENSORD_ATTRIBUTE_INTERVAL); + if (interval != m_attributes.end()) + set_interval(m_attributes[SENSORD_ATTRIBUTE_INTERVAL]); + + auto latency = m_attributes.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY); + if (latency != m_attributes.end()) + set_max_batch_latency(m_attributes[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY]); + _D("Restored listener[%d]", get_id()); } bool sensor_listener::connect(void) { - _I("Listener ID[%d]", get_id()); + m_channel = m_client->connect(m_handler, &m_loop); + retvm_if(!m_channel, false, "Failed to connect to server"); + + ipc::message msg; + ipc::message reply; + cmd_listener_connect_t buf = {0, }; + + memcpy(buf.sensor, m_sensor->get_uri().c_str(), m_sensor->get_uri().size()); + msg.set_type(CMD_LISTENER_CONNECT); + msg.enclose((const char *)&buf, sizeof(buf)); + m_channel->send_sync(&msg); + + m_channel->read_sync(reply); + reply.disclose((char *)&buf); + + m_id = buf.listener_id; + m_connected.store(true); + + _D("Listener ID[%d]", get_id()); return true; } void sensor_listener::disconnect(void) { + ret_if(!is_connected()); + m_connected.store(false); + + ipc::message msg; + ipc::message reply; + + msg.set_type(CMD_LISTENER_DISCONNECT); + m_channel->send_sync(&msg); + + m_channel->read_sync(reply); + m_channel->disconnect(); + + delete m_channel; + m_channel = NULL; + _I("Disconnected[%d]", get_id()); } @@ -131,71 +222,186 @@ void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler) void sensor_listener::unset_accuracy_handler(void) { + delete m_acc_handler; m_acc_handler = NULL; } int sensor_listener::start(void) { - return OP_ERROR; + ipc::message msg; + ipc::message reply; + cmd_listener_start_t buf; + + retvm_if(!m_channel, -EINVAL, "Failed to connect to server"); + + buf.listener_id = m_id; + msg.set_type(CMD_LISTENER_START); + msg.enclose((char *)&buf, sizeof(buf)); + + m_channel->send_sync(&msg); + m_channel->read_sync(reply); + + if (reply.header()->err < 0) + return reply.header()->err; + + m_started.store(true); + + return OP_SUCCESS; } int sensor_listener::stop(void) { - return OP_ERROR; + ipc::message msg; + ipc::message reply; + cmd_listener_stop_t buf; + + retvm_if(!m_channel, -EINVAL, "Failed to connect to server"); + retvm_if(!m_started.load(), -EAGAIN, "Already stopped"); + + buf.listener_id = m_id; + msg.set_type(CMD_LISTENER_STOP); + msg.enclose((char *)&buf, sizeof(buf)); + + m_channel->send_sync(&msg); + m_channel->read_sync(reply); + + if (reply.header()->err < 0) + return reply.header()->err; + + m_started.store(false); + + return OP_SUCCESS; } int sensor_listener::get_interval(void) { - return OP_ERROR; + auto it = m_attributes.find(SENSORD_ATTRIBUTE_INTERVAL); + retv_if(it == m_attributes.end(), -1); + + return m_attributes[SENSORD_ATTRIBUTE_INTERVAL]; } int sensor_listener::get_max_batch_latency(void) { - return OP_ERROR; + auto it = m_attributes.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY); + retv_if(it == m_attributes.end(), -1); + + return m_attributes[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY]; } int sensor_listener::get_pause_policy(void) { - return OP_ERROR; + auto it = m_attributes.find(SENSORD_ATTRIBUTE_PAUSE_POLICY); + retv_if(it == m_attributes.end(), -1); + + return m_attributes[SENSORD_ATTRIBUTE_PAUSE_POLICY]; } int sensor_listener::get_passive_mode(void) { - return OP_ERROR; + auto it = m_attributes.find(SENSORD_ATTRIBUTE_PASSIVE_MODE); + retv_if(it == m_attributes.end(), -1); + + return m_attributes[SENSORD_ATTRIBUTE_PASSIVE_MODE]; } int sensor_listener::set_interval(unsigned int interval) { - return OP_ERROR; + int _interval; + + /* TODO: move this logic to server */ + if (interval == 0) + _interval = DEFAULT_INTERVAL; + else if (interval < (unsigned int)m_sensor->get_min_interval()) + _interval = m_sensor->get_min_interval(); + else + _interval = interval; + + return set_attribute(SENSORD_ATTRIBUTE_INTERVAL, _interval); } int sensor_listener::set_max_batch_latency(unsigned int max_batch_latency) { - return OP_ERROR; + return set_attribute(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY, max_batch_latency); } int sensor_listener::set_passive_mode(bool passive) { - return OP_ERROR; + return set_attribute(SENSORD_ATTRIBUTE_PASSIVE_MODE, passive); } int sensor_listener::flush(void) { - return OP_ERROR; + return set_attribute(SENSORD_ATTRIBUTE_FLUSH, 1); } int sensor_listener::set_attribute(int attribute, int value) { - return OP_ERROR; + ipc::message msg; + ipc::message reply; + cmd_listener_attr_int_t buf; + + retvm_if(!m_channel, false, "Failed to connect to server"); + + buf.listener_id = m_id; + buf.attribute = attribute; + buf.value = value; + msg.set_type(CMD_LISTENER_ATTR_INT); + msg.enclose((char *)&buf, sizeof(buf)); + + m_channel->send_sync(&msg); + m_channel->read_sync(reply); + + if (reply.header()->err < 0) + return reply.header()->err; + + m_attributes[attribute] = value; + + return OP_SUCCESS; } int sensor_listener::set_attribute(int attribute, const char *value, int len) { - return OP_ERROR; + ipc::message msg; + ipc::message reply; + cmd_listener_attr_str_t buf; + + retvm_if(!m_channel, false, "Failed to connect to server"); + + msg.set_type(CMD_LISTENER_ATTR_STR); + buf.listener_id = m_id; + buf.attribute = attribute; + memcpy(buf.value, value, len); + buf.len = len; + + msg.enclose((char *)&buf, sizeof(buf) + len); + + m_channel->send_sync(&msg); + m_channel->read_sync(reply); + + return reply.header()->err; } int sensor_listener::get_sensor_data(sensor_data_t *data) { - return OP_ERROR; + ipc::message msg; + ipc::message reply; + cmd_listener_get_data_t buf; + + retvm_if(!m_channel, false, "Failed to connect to server"); + + buf.listener_id = m_id; + msg.set_type(CMD_LISTENER_GET_DATA); + msg.enclose((char *)&buf, sizeof(buf)); + m_channel->send_sync(&msg); + + m_channel->read_sync(reply); + /* TODO */ + /* + reply.disclose((char *)&buf); + memcpy(data, buf.data, sizeof(buf.len)); + */ + + return OP_SUCCESS; } -- 2.7.4 From 665a5cf24e0fceae5c50f2fd9a8f5b6123020dd3 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 16:15:30 +0900 Subject: [PATCH 11/16] sensord: move dbus_listener from client to server - dbus_listener is a helper class for listening dbus signal. - it will listen AXIS_ORIENTATED policy from other framework. Change-Id: I1705d87ebd0ab0a231f7bfccba28ba217ead9b70 Signed-off-by: kibak.yoon --- src/server/dbus_listener.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++ src/server/dbus_listener.h | 45 +++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 src/server/dbus_listener.cpp create mode 100644 src/server/dbus_listener.h diff --git a/src/server/dbus_listener.cpp b/src/server/dbus_listener.cpp new file mode 100644 index 0000000..c417586 --- /dev/null +++ b/src/server/dbus_listener.cpp @@ -0,0 +1,134 @@ +/* + * sensord + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * + * 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 +#include "dbus_listener.h" + +#define HANDLE_GERROR(Err) \ + do { \ + if ((Err)) { \ + _E("GError: %s", Err->message); \ + g_error_free(Err); \ + Err = NULL; \ + } \ + } while (0) + +#define ROTATION_DBUS_DEST "org.tizen.system.coord" +#define ROTATION_DBUS_OBJ_PATH "/Org/Tizen/System/Coord/Rotation" +#define ROTATION_DBUS_IFACE "org.tizen.system.coord.rotation" +#define ROTATION_DBUS_SIGNAL "Changed" +#define ROTATION_DBUS_METHOD "Degree" + +static void rotation_signal_cb(GDBusConnection *conn, const gchar *sender, + const gchar *obj_path, const gchar *iface, const gchar *signal_name, + GVariant *param, gpointer user_data) +{ + gint state; + g_variant_get(param, "(i)", &state); + //sensor_event_listener::get_instance().set_display_rotation(state); +} + +static void rotation_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + GDBusConnection *conn = G_DBUS_CONNECTION(source_object); + GVariant *result = g_dbus_connection_call_finish(conn, res, &error); + HANDLE_GERROR(error); + ret_if(result == NULL); + + gint state; + g_variant_get(result, "(i)", &state); + g_variant_unref(result); + //sensor_event_listener::get_instance().set_display_rotation(state); +} + +dbus_listener::dbus_listener() +: m_connection(NULL) +{ +#ifndef GLIB_VERSION_2_36 + g_type_init(); +#endif +} + +dbus_listener::~dbus_listener() +{ + disconnect(); +} + +void dbus_listener::init(void) +{ + static dbus_listener listener; + static bool done = false; + ret_if(done); + listener.connect(); + done = true; +} + +void dbus_listener::connect(void) +{ + GError *gerr = NULL; + + gchar *addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &gerr); + HANDLE_GERROR(gerr); + retm_if(addr == NULL, "Getting address failed"); + + g_dbus_connection_new_for_address(addr, + (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, NULL, on_connection_ready, this); + g_free(addr); +} + +void dbus_listener::on_connection_ready(GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + GError *gerr = NULL; + dbus_listener *listener = static_cast(user_data); + + GDBusConnection *conn = g_dbus_connection_new_finish(res, &gerr); + HANDLE_GERROR(gerr); + + retm_if(conn == NULL, "Connection failed"); + _D("Dbus connection established: %s", g_dbus_connection_get_unique_name(conn)); + + listener->m_connection = conn; + listener->get_current_state(); + listener->subscribe(); +} + +void dbus_listener::disconnect(void) +{ + ret_if(!m_connection); + g_dbus_connection_close_sync(m_connection, NULL, NULL); + g_object_unref(m_connection); +} + +void dbus_listener::subscribe(void) +{ + /* Diplay rotation */ + g_dbus_connection_signal_subscribe(m_connection, + ROTATION_DBUS_DEST, ROTATION_DBUS_IFACE, ROTATION_DBUS_SIGNAL, ROTATION_DBUS_OBJ_PATH, + NULL, G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback)rotation_signal_cb, NULL, NULL); +} + +void dbus_listener::get_current_state(void) +{ + /* Display rotation */ + g_dbus_connection_call(m_connection, + ROTATION_DBUS_DEST, ROTATION_DBUS_OBJ_PATH, ROTATION_DBUS_IFACE, ROTATION_DBUS_METHOD, + NULL, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, (GAsyncReadyCallback)rotation_read_cb, NULL); +} diff --git a/src/server/dbus_listener.h b/src/server/dbus_listener.h new file mode 100644 index 0000000..6b045f3 --- /dev/null +++ b/src/server/dbus_listener.h @@ -0,0 +1,45 @@ +/* + * sensord + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * + * 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 _DBUS_LISTENER_H_ +#define _DBUS_LISTENER_H_ + +#include +#include + +class dbus_listener { +public: + static void init(void); + +private: + GDBusConnection *m_connection; + + dbus_listener(); + ~dbus_listener(); + + void connect(void); + void disconnect(void); + + void subscribe(void); + void get_current_state(void); + + static void on_connection_ready(GObject *source_object, GAsyncResult *res, gpointer user_data); +}; + +#endif /* _DBUS_LISTENER_H_ */ -- 2.7.4 From 25258ab1eb05bea3075a697b0009e4937d525e36 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 16:20:26 +0900 Subject: [PATCH 12/16] sensord: add permission_checker for checking privileges - permission_checker provides two way to check privilege: - by string - by sensor_permission_t(enum) - [TBD] in the future, we will only check privilege with string. - [TBD] since there is a direct dependency on cynara, it will be separated. Change-Id: Ic7ddac594bebb669a9643992ef7f52f1c36dcdfb Signed-off-by: kibak.yoon --- src/server/permission_checker.cpp | 101 ++++++++++++++++++++++++++++++++++++-- src/server/permission_checker.h | 25 +++++++--- 2 files changed, 115 insertions(+), 11 deletions(-) diff --git a/src/server/permission_checker.cpp b/src/server/permission_checker.cpp index 20b03ec..644ce61 100644 --- a/src/server/permission_checker.cpp +++ b/src/server/permission_checker.cpp @@ -1,7 +1,7 @@ /* * sensord * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,22 +17,113 @@ * */ -#include +#include "permission_checker.h" + #include #include #include +#include +#include #define CACHE_SIZE 16 -static bool check_privilege_by_sockfd(int sock_fd, const char *priv, const char *access) +using namespace sensor; + +static cynara *cynara_env = NULL; +static std::unordered_map permissions; + +permission_checker::permission_checker() +{ + init_cynara(); +} + +permission_checker::~permission_checker() +{ + deinit_cynara(); +} + +void permission_checker::init(void) +{ + /* if needed, add privilege to permissions */ + permissions[SENSOR_PERMISSION_HEALTH_INFO] = "http://tizen.org/privilege/healthinfo"; +} + +void permission_checker::init_cynara(void) +{ + int err; + cynara_configuration *conf; + + err = cynara_configuration_create(&conf); + retm_if(err != CYNARA_API_SUCCESS, "Failed to create cynara configuration"); + + err = cynara_configuration_set_cache_size(conf, CACHE_SIZE); + if (err != CYNARA_API_SUCCESS) { + _E("Failed to set cynara cache"); + cynara_configuration_destroy(conf); + return; + } + + err = cynara_initialize(&cynara_env, conf); + cynara_configuration_destroy(conf); + + if (err != CYNARA_API_SUCCESS) { + _E("Failed to initialize cynara"); + cynara_env = NULL; + return; + } + + _I("Initialized"); +} + +void permission_checker::deinit_cynara(void) +{ + if (cynara_env) { + cynara_finish(cynara_env); + cynara_env = NULL; + } + + _I("Deinitialized"); +} + +bool permission_checker::has_permission_cynara(int sock_fd, std::string &perm) { + retvm_if(cynara_env == NULL, false, "Cynara not initialized"); + + int pid = -1; + char *client = NULL; + char *session = NULL; + char *user = NULL; + + retvm_if(cynara_creds_socket_get_pid(sock_fd, &pid) != CYNARA_API_SUCCESS, + false, "Failed to get pid"); + + if (cynara_creds_socket_get_client(sock_fd, + CLIENT_METHOD_DEFAULT, &client) != CYNARA_API_SUCCESS || + cynara_creds_socket_get_user(sock_fd, + USER_METHOD_DEFAULT, &user) != CYNARA_API_SUCCESS || + (session = cynara_session_from_pid(pid)) == NULL) { + _E("Failed to get client information"); + free(client); + free(user); + free(session); + return false; + } + return true; } -permission_checker::permission_checker() +bool permission_checker::has_permission(int sock_fd, std::string &perm) { + retv_if(perm.empty(), true); + + return has_permission_cynara(sock_fd, perm); } -permission_checker::~permission_checker() +/* TODO: remove sensor_permission_t and this function */ +bool permission_checker::has_permission(int sock_fd, sensor_permission_t perm) { + auto it = permissions.find(perm); + retv_if(it == permissions.end(), true); + + return has_permission(sock_fd, permissions[perm]); } diff --git a/src/server/permission_checker.h b/src/server/permission_checker.h index 01cc8b4..b307dc0 100644 --- a/src/server/permission_checker.h +++ b/src/server/permission_checker.h @@ -1,7 +1,7 @@ /* * sensord * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,16 +17,29 @@ * */ -#ifndef _PERMISSION_CHECKER_H_ -#define _PERMISSION_CHECKER_H_ +#ifndef __PERMISSION_CHECKER_H__ +#define __PERMISSION_CHECKER_H__ +#include #include -#include -#include + +namespace sensor { class permission_checker { +public: permission_checker(); ~permission_checker(); + + void init(void); + + void init_cynara(void); + void deinit_cynara(void); + bool has_permission_cynara(int sock_fd, std::string &perm); + + bool has_permission(int sock_fd, std::string &perm); + bool has_permission(int sock_fd, sensor_permission_t perm); }; -#endif /* _PERMISSION_CHECKER_H_ */ +} + +#endif /* __PERMISSION_CHECKER_H__ */ -- 2.7.4 From 84993de67f4119d47b66014fc70f316e507e2027 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 17:04:32 +0900 Subject: [PATCH 13/16] sensord: add handlers to main for new failures - if new(memory allocation) is failed, on_new_failed will be called. - this patch refers to https://review.tizen.org/gerrit/#/c/123204/ Change-Id: I1817e376fb256992266a78d078cdc15ad00b6a58 Signed-off-by: kibak.yoon --- src/server/main.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/server/main.cpp b/src/server/main.cpp index 2ce210c..90b6cf4 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -17,10 +17,58 @@ * */ -/* TODO: create conf file for calibration paths */ -#define CAL_NODE_PATH "/sys/class/sensors/ssp_sensor/set_cal_data" +#include +#include +#include +#include +#include + +#include "server.h" + +#define NEW_FAIL_LIMIT 3 + +using namespace sensor; + +static void on_signal(int signum) +{ + _W("Received SIGNAL(%d : %s)", signum, strsignal(signum)); + server::stop(); +} + +static void on_new_failed(void) +{ + static unsigned fail_count = 0; + _E("Failed to allocate memory"); + + fail_count += 1; + if (fail_count >= NEW_FAIL_LIMIT) { + raise(SIGTERM); + return; + } + + usleep(100000); +} int main(int argc, char *argv[]) { + _I("Started"); + std::signal(SIGINT, on_signal); + std::signal(SIGHUP, on_signal); + std::signal(SIGTERM, on_signal); + std::signal(SIGQUIT, on_signal); + std::signal(SIGABRT, on_signal); + std::signal(SIGCHLD, SIG_IGN); + std::signal(SIGPIPE, SIG_IGN); + + std::set_new_handler(on_new_failed); + + init_dbus(); + + server::run(); + + fini_dbus(); + + _I("Stopped"); + return 0; } -- 2.7.4 From d8513d84462bbfb573fc2e104917d12f481f884d Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 18:26:20 +0900 Subject: [PATCH 14/16] sensord: add the basic implementation of the server-side - server provides: - controls for the event_loop which manages all I/O events. - server has: - event_loop - sensor_manager - server_channel_handler * it is singleton class. Change-Id: I6d7266f3ec68a4f576428bf4d7c2e91b699a4064 Signed-off-by: kibak.yoon --- src/server/sensor_loader.h | 10 +-- src/server/sensor_manager.cpp | 49 ++++++++++++ src/server/sensor_manager.h | 48 ++++++++++++ src/server/server.cpp | 102 ++++++++++++++++++++++++- src/server/server.h | 41 +++++++++-- src/server/server_channel_handler.cpp | 135 ++++++++++++++++++++++++++++++++++ src/server/server_channel_handler.h | 65 ++++++++++++++++ 7 files changed, 437 insertions(+), 13 deletions(-) create mode 100644 src/server/sensor_manager.cpp create mode 100644 src/server/sensor_manager.h create mode 100644 src/server/server_channel_handler.cpp create mode 100644 src/server/server_channel_handler.h diff --git a/src/server/sensor_loader.h b/src/server/sensor_loader.h index 22efa62..ab9b9b0 100644 --- a/src/server/sensor_loader.h +++ b/src/server/sensor_loader.h @@ -1,7 +1,7 @@ /* * sensord * - * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,13 +17,13 @@ * */ -#ifndef _SENSOR_LOADER_H_ -#define _SENSOR_LOADER_H_ +#ifndef __SENSOR_LOADER_H__ +#define __SENSOR_LOADER_H__ class sensor_loader { -private: +public: sensor_loader(); virtual ~sensor_loader(); }; -#endif /* _SENSOR_LOADER_H_ */ +#endif /* __SENSOR_LOADER_H__ */ diff --git a/src/server/sensor_manager.cpp b/src/server/sensor_manager.cpp new file mode 100644 index 0000000..6944e86 --- /dev/null +++ b/src/server/sensor_manager.cpp @@ -0,0 +1,49 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "sensor_manager.h" + +#include +#include +#include +#include +#include +#include + +using namespace sensor; + +sensor_manager::sensor_manager(ipc::event_loop *loop) +: m_loop(loop) +{ +} + +sensor_manager::~sensor_manager() +{ +} + +bool sensor_manager::init(void) +{ + return true; +} + +bool sensor_manager::deinit(void) +{ + return true; +} + diff --git a/src/server/sensor_manager.h b/src/server/sensor_manager.h new file mode 100644 index 0000000..31236af --- /dev/null +++ b/src/server/sensor_manager.h @@ -0,0 +1,48 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __SENSOR_MANAGER_H__ +#define __SENSOR_MANAGER_H__ + +#include +#include +#include + +#include "event_loop.h" + +#include "sensor_loader.h" + +namespace sensor { + +class sensor_manager { +public: + sensor_manager(ipc::event_loop *loop); + ~sensor_manager(); + + bool init(void); + bool deinit(void); + +private: + ipc::event_loop *m_loop; + sensor_loader m_loader; +}; + +} + +#endif /* __SENSOR_MANAGER_H__ */ diff --git a/src/server/server.cpp b/src/server/server.cpp index 0c1e624..fee9abf 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -1,7 +1,7 @@ /* * sensord * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,26 @@ #include "server.h" +#include +#include +#include +#include +#include + +#include "sensor_manager.h" +#include "server_channel_handler.h" + +#define TIMEOUT_TERM 10 + +using namespace sensor; + +ipc::event_loop server::m_loop; +std::atomic server::is_running(false); + server::server() +: m_server(NULL) +, m_manager(NULL) +, m_handler(NULL) { } @@ -27,8 +46,87 @@ server::~server() { } -server& server::get_instance(void) +server &server::instance(void) { static server inst; return inst; } + +void server::run(void) +{ + _I("Starting.."); + + retm_if(is_running.load(), "Server is running"); + retm_if(!instance().init(), "Failed to initialize server"); + + m_loop.run(); +} + +void server::stop(void) +{ + _I("Stopping.."); + + retm_if(!is_running.load(), "Server is not running"); + + m_loop.stop(); + instance().deinit(); +} + +bool server::init(void) +{ + m_server = new(std::nothrow) ipc::ipc_server(SENSOR_CHANNEL_PATH); + retvm_if(!m_server, false, "Failed to allocate memory"); + + m_manager = new(std::nothrow) sensor_manager(&m_loop); + retvm_if(!m_manager, false, "Failed to allocate memory"); + + m_handler = new(std::nothrow) server_channel_handler(m_manager); + retvm_if(!m_handler, false, "Failed to allocate memory"); + + init_server(); + init_termination(); + + is_running.store(true); + sd_notify(0, "READY=1"); + + return true; +} + +void server::deinit(void) +{ + m_manager->deinit(); + m_server->close(); + + delete m_server; + m_server = NULL; + + delete m_manager; + m_manager = NULL; + + delete m_handler; + m_handler = NULL; + + is_running.store(false); +} + +void server::init_server(void) +{ + m_manager->init(); + + /* TODO: setting socket option */ + m_server->set_option("max_connection", 1000); + m_server->set_option(SO_TYPE, SOCK_STREAM); + m_server->bind(m_handler, &m_loop); +} + +static gboolean terminate(gpointer data) +{ + /* TODO: if there is no sensor, sensord will be terminated */ + + return FALSE; +} + +void server::init_termination(void) +{ + g_timeout_add_seconds(TIMEOUT_TERM, terminate, m_manager); +} diff --git a/src/server/server.h b/src/server/server.h index 017f461..b8bb2f6 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -1,7 +1,7 @@ /* * sensord * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,15 +17,44 @@ * */ -#ifndef _SERVER_H_ -#define _SERVER_H_ +#ifndef __SERVER_H__ +#define __SERVER_H__ + +#include +#include +#include +#include +#include +#include + +namespace sensor { class server { public: + static void run(void); + static void stop(void); + +private: + static server &instance(void); + + static ipc::event_loop m_loop; + static std::atomic is_running; + server(); - virtual ~server(); + ~server(); + + bool init(void); + void deinit(void); - static server& get_instance(void); + void init_calibration(void); + void init_server(void); + void init_termination(void); + + ipc::ipc_server *m_server; + sensor_manager *m_manager; + server_channel_handler *m_handler; }; -#endif /* _SERVER_H_ */ +} + +#endif /* __SERVER_H__ */ diff --git a/src/server/server_channel_handler.cpp b/src/server/server_channel_handler.cpp new file mode 100644 index 0000000..afcfa4e --- /dev/null +++ b/src/server/server_channel_handler.cpp @@ -0,0 +1,135 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 "server_channel_handler.h" + +#include +#include +#include + +using namespace sensor; +using namespace ipc; + +server_channel_handler::server_channel_handler(sensor_manager *manager) +: m_manager(manager) +{ +} + +server_channel_handler::~server_channel_handler() +{ +} + +void server_channel_handler::connected(channel *ch) +{ +} + +void server_channel_handler::disconnected(channel *ch) +{ +} + +void server_channel_handler::read(channel *ch, message &msg) +{ + int err = -EINVAL; + + switch (msg.type()) { + case CMD_MANAGER_SENSOR_LIST: + err = manager_get_sensor_list(ch, msg); break; + case CMD_LISTENER_CONNECT: + err = listener_connect(ch, msg); break; + case CMD_LISTENER_DISCONNECT: + err = listener_disconnect(ch, msg); break; + case CMD_LISTENER_START: + err = listener_start(ch, msg); break; + case CMD_LISTENER_STOP: + err = listener_stop(ch, msg); break; + case CMD_LISTENER_ATTR_INT: + err = listener_attr_int(ch, msg); break; + case CMD_LISTENER_ATTR_STR: + err = listener_attr_str(ch, msg); break; + case CMD_LISTENER_GET_DATA: + err = listener_get_data(ch, msg); break; + case CMD_PROVIDER_CONNECT: + err = provider_connect(ch, msg); break; + case CMD_PROVIDER_DISCONNECT: + err = provider_disconnect(ch, msg); break; + case CMD_PROVIDER_POST: + err = provider_post(ch, msg); break; + default: break; + } + + if (err != 0) { + message reply(err); + ch->send_sync(&reply); + } +} + +int server_channel_handler::manager_get_sensor_list(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::listener_connect(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::listener_disconnect(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::listener_start(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::listener_stop(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::listener_attr_int(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::listener_attr_str(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::listener_get_data(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::provider_connect(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::provider_disconnect(channel *ch, message &msg) +{ + return OP_ERROR; +} + +int server_channel_handler::provider_post(channel *ch, message &msg) +{ + return OP_ERROR; +} diff --git a/src/server/server_channel_handler.h b/src/server/server_channel_handler.h new file mode 100644 index 0000000..76ea4a3 --- /dev/null +++ b/src/server/server_channel_handler.h @@ -0,0 +1,65 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __SERVER_CHANNEL_HANDLER_H__ +#define __SERVER_CHANNEL_HANDLER_H__ + +#include +#include +#include +#include + +#include "sensor_manager.h" + +namespace sensor { + +/* TODO: this class seems to be able to split */ +class server_channel_handler : public ipc::channel_handler +{ +public: + server_channel_handler(sensor_manager *manager); + ~server_channel_handler(); + + void connected(ipc::channel *ch); + void disconnected(ipc::channel *ch); + void read(ipc::channel *ch, ipc::message &msg); + void read_complete(ipc::channel *ch) {} + void error_caught(ipc::channel *ch, int error) {} + +private: + int manager_get_sensor_list(ipc::channel *ch, ipc::message &msg); + + int listener_connect(ipc::channel *ch, ipc::message &msg); + int listener_disconnect(ipc::channel *ch, ipc::message &msg); + int listener_start(ipc::channel *ch, ipc::message &msg); + int listener_stop(ipc::channel *ch, ipc::message &msg); + int listener_attr_int(ipc::channel *ch, ipc::message &msg); + int listener_attr_str(ipc::channel *ch, ipc::message &msg); + int listener_get_data(ipc::channel *ch, ipc::message &msg); + + int provider_connect(ipc::channel *ch, ipc::message &msg); + int provider_disconnect(ipc::channel *ch, ipc::message &msg); + int provider_post(ipc::channel *ch, ipc::message &msg); + + sensor_manager *m_manager; +}; + +} + +#endif /* __SERVER_CHANNEL_HANDLER_H__ */ -- 2.7.4 From 98bc10f25673e914b73f571e5c0bc984f10b8624 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 5 Apr 2017 19:54:34 +0900 Subject: [PATCH 15/16] sensord: add sensor_publisher and sensor_observer interfaces - observer pattern Change-Id: I7c0f859a48faca21f1cf51fede816cc84c9b016e Signed-off-by: kibak.yoon --- src/server/sensor_observer.h | 37 +++++++++++++++++++++++++++++++++++++ src/server/sensor_publisher.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/server/sensor_observer.h create mode 100644 src/server/sensor_publisher.h diff --git a/src/server/sensor_observer.h b/src/server/sensor_observer.h new file mode 100644 index 0000000..ee04c20 --- /dev/null +++ b/src/server/sensor_observer.h @@ -0,0 +1,37 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __SENSOR_OBSERVER_H__ +#define __SENSOR_OBSERVER_H__ + +#include + +namespace sensor { + +class sensor_observer { +public: + virtual ~sensor_observer() {} + + /* for performance, use message */ + virtual int update(const char *uri, ipc::message *msg) = 0; +}; + +} + +#endif /* __SENSOR_OBSERVER_H__ */ diff --git a/src/server/sensor_publisher.h b/src/server/sensor_publisher.h new file mode 100644 index 0000000..58bb996 --- /dev/null +++ b/src/server/sensor_publisher.h @@ -0,0 +1,41 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __SENSOR_PUBLISHER_H__ +#define __SENSOR_PUBLISHER_H__ + +#include + +namespace sensor { + +class sensor_observer; + +class sensor_publisher { +public: + virtual ~sensor_publisher() {} + + virtual bool has_observer(sensor_observer *ob) = 0; + virtual void add_observer(sensor_observer *ob) = 0; + virtual void remove_observer(sensor_observer *ob) = 0; + virtual int notify(const char *type, sensor_data_t *data, int len) = 0; +}; + +} + +#endif /* __SENSOR_PUBLISHER_H__ */ -- 2.7.4 From bed2c7f2284884c7672193c6a028e6463b9693de Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 6 Apr 2017 16:45:06 +0900 Subject: [PATCH 16/16] sensord: implement sensor_handler class - sensor_handler has: - a common logic of publisher - sensor control interface Change-Id: Ifbc32db62b96996d01041f6b7855b07ae07115b0 Signed-off-by: kibak.yoon --- src/server/sensor_handler.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++ src/server/sensor_handler.h | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 src/server/sensor_handler.cpp create mode 100644 src/server/sensor_handler.h diff --git a/src/server/sensor_handler.cpp b/src/server/sensor_handler.cpp new file mode 100644 index 0000000..e567c22 --- /dev/null +++ b/src/server/sensor_handler.cpp @@ -0,0 +1,70 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 +#include +#include "sensor_handler.h" + +using namespace sensor; + +bool sensor_handler::has_observer(sensor_observer *ob) +{ + for (auto it = m_observers.begin(); it != m_observers.end(); ++it) { + if ((*it) == ob) + return true; + } + + return false; +} + +void sensor_handler::add_observer(sensor_observer *ob) +{ + ret_if(has_observer(ob)); + + m_observers.push_back(ob); +} + +void sensor_handler::remove_observer(sensor_observer *ob) +{ + m_observers.remove(ob); +} + +int sensor_handler::notify(const char *uri, sensor_data_t *data, int len) +{ + if (observer_count() == 0) + return OP_ERROR; + + ipc::message *msg; + + msg = new(std::nothrow) ipc::message((char *)data, len); + retvm_if(!msg, OP_ERROR, "Failed to allocate memory"); + + for (auto it = m_observers.begin(); it != m_observers.end(); ++it) + (*it)->update(uri, msg); + + if (msg->ref_count() == 0) + msg->unref(); + + return OP_SUCCESS; +} + +uint32_t sensor_handler::observer_count(void) +{ + return m_observers.size(); +} diff --git a/src/server/sensor_handler.h b/src/server/sensor_handler.h new file mode 100644 index 0000000..68672ab --- /dev/null +++ b/src/server/sensor_handler.h @@ -0,0 +1,60 @@ +/* + * sensord + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __SENSOR_HANDLER_H__ +#define __SENSOR_HANDLER_H__ + +#include +#include +#include +#include +#include + +namespace sensor { + +class sensor_handler : public sensor_publisher { +public: + virtual ~sensor_handler() {} + + /* publisher */ + bool has_observer(sensor_observer *ob); + void add_observer(sensor_observer *ob); + void remove_observer(sensor_observer *ob); + int notify(const char *type, sensor_data_t *data, int len); + uint32_t observer_count(void); + + virtual const sensor_info &get_sensor_info(void) = 0; + + virtual int start(sensor_observer *ob) = 0; + virtual int stop(sensor_observer *ob) = 0; + + virtual int set_interval(sensor_observer *ob, int32_t interval) = 0; + virtual int set_batch_latency(sensor_observer *ob, int32_t latency) = 0; + virtual int set_attribute(sensor_observer *ob, int32_t attr, int32_t value) = 0; + virtual int set_attribute(sensor_observer *ob, int32_t attr, const char *value, int len) = 0; + virtual int get_data(sensor_data_t **data, int *len) = 0; + virtual int flush(void) = 0; + +private: + std::list m_observers; +}; + +} + +#endif /* __SENSOR_HANDLER_H__ */ -- 2.7.4