From ccf9ba4209e4fd281cadf7a764c724e508a04113 Mon Sep 17 00:00:00 2001 From: Boram Bae Date: Fri, 29 Nov 2019 13:35:56 +0900 Subject: [PATCH] Implement sensord_get_data_list * Add a command type CMD_LISTENER_GET_DATA_LIST * Add sensorctl tests * Now, you can use sensor_get_data_list instead of sensor_get_data Change-Id: I2c90e680a6b3f86076df5702f3b29d5ff7eec1bf Signed-off-by: Boram Bae --- include/sensor_internal.h | 11 ++ src/client-dummy/client_dummy.cpp | 5 + src/client/sensor_internal.cpp | 19 +++ src/client/sensor_listener.cpp | 51 ++++++- src/client/sensor_listener.h | 1 + src/sensorctl/testcase/sensor_listener.cpp | 50 +++++++ src/sensorctl/testcase/sensor_provider.cpp | 160 +++++++++++++++++++++ src/server/server_channel_handler.cpp | 46 ++++++ src/server/server_channel_handler.h | 1 + src/shared/command_types.h | 8 ++ 10 files changed, 349 insertions(+), 3 deletions(-) diff --git a/include/sensor_internal.h b/include/sensor_internal.h index 07638fd5..1fbfabeb 100644 --- a/include/sensor_internal.h +++ b/include/sensor_internal.h @@ -466,6 +466,17 @@ bool sensord_send_command(int handle, const char *command, int command_len); */ bool sensord_get_data(int handle, unsigned int data_id, sensor_data_t* sensor_data); +/** + * @brief get sensor data from a connected sensor + * + * @param[in] handle a handle represensting a connected context sensor. + * @param[in] data_id it specifies data to get + * @param[out] sensor_data the data list from connected sensor, the caller should explicitly free this list. + * @param[out] count the count of data contained in the list. + * @return true on success, otherwise false. + */ +bool sensord_get_data_list(int handle, unsigned int data_id, sensor_data_t** sensor_data, int* count); + /** * @brief flush sensor data from a connected sensor * diff --git a/src/client-dummy/client_dummy.cpp b/src/client-dummy/client_dummy.cpp index accc0430..8432ba21 100644 --- a/src/client-dummy/client_dummy.cpp +++ b/src/client-dummy/client_dummy.cpp @@ -233,6 +233,11 @@ API bool sensord_get_data(int handle, unsigned int data_id, sensor_data_t* senso return false; } +API bool sensord_get_data_list(int handle, unsigned int data_id, sensor_data_t** sensor_data, int* count) +{ + return false; +} + API bool sensord_flush(int handle) { return false; diff --git a/src/client/sensor_internal.cpp b/src/client/sensor_internal.cpp index 376059c6..950c28de 100644 --- a/src/client/sensor_internal.cpp +++ b/src/client/sensor_internal.cpp @@ -787,6 +787,25 @@ API bool sensord_get_data(int handle, unsigned int data_id, sensor_data_t* senso return true; } +API bool sensord_get_data_list(int handle, unsigned int data_id, sensor_data_t** sensor_data, int* count) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->get_sensor_data_list(sensor_data, count) < 0) { + _E("Failed to get sensor data from listener"); + return false; + } + + return true; +} + API bool sensord_flush(int handle) { sensor::sensor_listener *listener; diff --git a/src/client/sensor_listener.cpp b/src/client/sensor_listener.cpp index 6cea7d32..c979244e 100644 --- a/src/client/sensor_listener.cpp +++ b/src/client/sensor_listener.cpp @@ -532,7 +532,6 @@ int sensor_listener::get_attribute(int attribute, int* value) m_cmd_channel->read_sync(reply); if (reply.header()->err < 0) { - _D("reply.header()->err < 0"); return reply.header()->err; } if (reply.header()->length && reply.body()) { @@ -606,7 +605,6 @@ int sensor_listener::get_attribute(int attribute, char **value, int* len) m_cmd_channel->read_sync(reply); if (reply.header()->err < 0) { - _D("reply.header()->err < 0"); return reply.header()->err; } @@ -660,4 +658,51 @@ int sensor_listener::get_sensor_data(sensor_data_t *data) _D("Listener[%d] read sensor data", get_id()); return OP_SUCCESS; -} \ No newline at end of file +} + +int sensor_listener::get_sensor_data_list(sensor_data_t **data, int *count) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_get_data_list_t buf; + + retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server"); + + buf.listener_id = m_id; + msg.set_type(CMD_LISTENER_GET_DATA_LIST); + msg.enclose((char *)&buf, sizeof(buf)); + + m_cmd_channel->send_sync(&msg); + m_cmd_channel->read_sync(reply); + + if (reply.header()->err < 0) { + return reply.header()->err; + } + + size_t size = reply.size(); + cmd_listener_get_data_list_t* reply_buf = (cmd_listener_get_data_list_t *) new(std::nothrow) char[size]; + + retvm_if(!reply_buf, -ENOMEM, "Failed to allocate memory"); + + reply.disclose((char *)reply_buf); + + if (reply_buf->len <= 0) { + delete [] reply_buf; + return OP_ERROR; + } + + *count = reply_buf->data_count; + *data = (sensor_data_t*) malloc(reply_buf->len); + + if (!(*data)) { + _E("Memory allocation failed"); + delete [] reply_buf; + return -ENOMEM; + } + + memcpy(*data, reply_buf->data, reply_buf->len); + + _D("Listener[%d] read sensor data list", get_id()); + delete [] reply_buf; + return OP_SUCCESS; +} diff --git a/src/client/sensor_listener.h b/src/client/sensor_listener.h index 47cab206..581b2a11 100644 --- a/src/client/sensor_listener.h +++ b/src/client/sensor_listener.h @@ -75,6 +75,7 @@ public: int get_attribute(int attribute, char **value, int *len); void update_attribute(int attribute, const char *value, int len); int get_sensor_data(sensor_data_t *data); + int get_sensor_data_list(sensor_data_t **data, int *count); int flush(void); void restore(void); diff --git a/src/sensorctl/testcase/sensor_listener.cpp b/src/sensorctl/testcase/sensor_listener.cpp index c5adee27..6fc6bf45 100644 --- a/src/sensorctl/testcase/sensor_listener.cpp +++ b/src/sensorctl/testcase/sensor_listener.cpp @@ -427,6 +427,56 @@ TESTCASE(sensor_listener, get_attribute_string_2) return true; } +#define SENSOR_SHIFT_TYPE 16 +TESTCASE(sensor_listener, get_data_list) +{ + int err; + bool ret; + int handle; + sensor_t sensor; + sensor_type_t type; + + called = false; + + err = sensord_get_default_sensor(ACCELEROMETER_SENSOR, &sensor); + ASSERT_EQ(err, 0); + + handle = sensord_connect(sensor); + + sensord_get_type(sensor, &type); + ASSERT_EQ(err, 0); + + ret = sensord_start(handle, 0); + ASSERT_TRUE(ret); + + sensor_data_t* data_list = NULL; + int count = 0; + unsigned int data_id = type << SENSOR_SHIFT_TYPE | 0x1; + + ret = sensord_get_data_list(handle, data_id, &data_list, &count); + ASSERT_TRUE(ret); + ASSERT_EQ(count, 1); + + for (int i = 0 ; i < count; i++) { + _I("[%llu]", data_list[i].timestamp); + for (int j = 0; j < data_list[i].value_count; j++) + _I(" %f", data_list[i].values[j]); + _I("\n"); + } + free(data_list); + + ret = sensord_stop(handle); + ASSERT_TRUE(ret); + + ret = sensord_unregister_events(handle, 1); + ASSERT_TRUE(ret); + + ret = sensord_disconnect(handle); + ASSERT_TRUE(ret); + + return true; +} + void sensor_attribute_int_changed_callback(sensor_t sensor, int attribute, int value, void *data) { _I("[ATTRIBUTE INT CHANGED] attribute : %d, value : %d\n", attribute, value); diff --git a/src/sensorctl/testcase/sensor_provider.cpp b/src/sensorctl/testcase/sensor_provider.cpp index bcd5101d..d7ed1bbe 100644 --- a/src/sensorctl/testcase/sensor_provider.cpp +++ b/src/sensorctl/testcase/sensor_provider.cpp @@ -356,3 +356,163 @@ TESTCASE(skip_sensor_provider, mysensor_batch_with_listener_p_1) return true; } + +TESTCASE(skip_sensor_provider, mysensor_batch_events_once) +{ + int err = 0; + bool ret = false; + sensor_t sensor; + sensord_provider_h provider; + + err = sensord_create_provider(MYSENSOR_BATCH_URI, &provider); + ASSERT_EQ(err, 0); + + err = sensord_provider_set_name(provider, MYSENSOR_BATCH_NAME); + ASSERT_EQ(err, 0); + err = sensord_provider_set_vendor(provider, MYSENSOR_VENDOR); + ASSERT_EQ(err, 0); + err = sensord_provider_set_range(provider, 0.0f, 1.0f); + ASSERT_EQ(err, 0); + err = sensord_provider_set_resolution(provider, 0.01f); + ASSERT_EQ(err, 0); + + err = sensord_add_provider(provider); + ASSERT_EQ(err, 0); + + err = sensord_provider_set_start_cb(provider, start_cb, NULL); + ASSERT_EQ(err, 0); + err = sensord_provider_set_stop_cb(provider, stop_cb, NULL); + ASSERT_EQ(err, 0); + err = sensord_provider_set_interval_changed_cb(provider, interval_cb, NULL); + ASSERT_EQ(err, 0); + + err = sensord_get_default_sensor_by_uri(MYSENSOR_BATCH_URI, &sensor); + ASSERT_EQ(err, 0); + + int client_handle; + sensor_t client_sensor; + err = sensord_get_default_sensor_by_uri(MYSENSOR_BATCH_URI, &client_sensor); + ASSERT_EQ(err, 0); + client_handle = sensord_connect(client_sensor); + ASSERT_EQ(err, 0); + + ret = sensord_start(client_handle, 0); + ASSERT_TRUE(ret); + + sensor_data_t data[NUMBER_OF_EVENT]; + for (int i = 0 ; i < NUMBER_OF_EVENT; i++) { + data[i].accuracy = 3; + data[i].timestamp = sensor::utils::get_timestamp(); + data[i].value_count = 3; + data[i].values[0] = i; + data[i].values[1] = i; + data[i].values[2] = i; + } + err = sensord_provider_publish_events(provider, data, NUMBER_OF_EVENT); + ASSERT_EQ(err, 0); + + ret = sensord_stop(client_handle); + ASSERT_TRUE(ret); + ret = sensord_disconnect(client_handle); + ASSERT_TRUE(ret); + + mainloop::run(); + + err = sensord_remove_provider(provider); + ASSERT_EQ(err, 0); + err = sensord_destroy_provider(provider); + ASSERT_EQ(err, 0); + + return true; +} + +TESTCASE(skip_sensor_provider, mysensor_batch_p_without_publish) +{ + int err = 0; + sensor_t sensor; + sensord_provider_h provider; + + err = sensord_create_provider(MYSENSOR_BATCH_URI, &provider); + ASSERT_EQ(err, 0); + + err = sensord_provider_set_name(provider, MYSENSOR_BATCH_NAME); + ASSERT_EQ(err, 0); + err = sensord_provider_set_vendor(provider, MYSENSOR_VENDOR); + ASSERT_EQ(err, 0); + err = sensord_provider_set_range(provider, 0.0f, 1.0f); + ASSERT_EQ(err, 0); + err = sensord_provider_set_resolution(provider, 0.01f); + ASSERT_EQ(err, 0); + + err = sensord_add_provider(provider); + ASSERT_EQ(err, 0); + + err = sensord_provider_set_start_cb(provider, start_cb, NULL); + ASSERT_EQ(err, 0); + err = sensord_provider_set_stop_cb(provider, stop_cb, NULL); + ASSERT_EQ(err, 0); + err = sensord_provider_set_interval_changed_cb(provider, interval_cb, NULL); + ASSERT_EQ(err, 0); + + err = sensord_get_default_sensor_by_uri(MYSENSOR_BATCH_URI, &sensor); + ASSERT_EQ(err, 0); + + mainloop::run(); + + err = sensord_remove_provider(provider); + ASSERT_EQ(err, 0); + err = sensord_destroy_provider(provider); + ASSERT_EQ(err, 0); + + return true; +} + +#define SENSOR_SHIFT_TYPE 16 +TESTCASE(skip_sensor_provider, mysensor_get_data_list) +{ + int err; + bool ret; + int handle; + sensor_t sensor; + sensor_type_t type; + + called = false; + + err = sensord_get_default_sensor_by_uri(MYSENSOR_BATCH_URI, &sensor); + ASSERT_EQ(err, 0); + + handle = sensord_connect(sensor); + + sensord_get_type(sensor, &type); + ASSERT_EQ(err, 0); + + ret = sensord_start(handle, 0); + ASSERT_TRUE(ret); + + sensor_data_t* data_list = NULL; + int count = 0; + unsigned int data_id = type << SENSOR_SHIFT_TYPE | 0x1; + + ret = sensord_get_data_list(handle, data_id, &data_list, &count); + ASSERT_TRUE(ret); + ASSERT_EQ(count, NUMBER_OF_EVENT); + + for (int i = 0 ; i < count; i++) { + _I("[%llu]", data_list[i].timestamp); + for (int j = 0; j < data_list[i].value_count; j++) + _I(" %f", data_list[i].values[j]); + _I("\n"); + } + free(data_list); + + ret = sensord_stop(handle); + ASSERT_TRUE(ret); + + ret = sensord_unregister_events(handle, 1); + ASSERT_TRUE(ret); + + ret = sensord_disconnect(handle); + ASSERT_TRUE(ret); + + return true; +} \ No newline at end of file diff --git a/src/server/server_channel_handler.cpp b/src/server/server_channel_handler.cpp index c8c8d0be..69f15f46 100644 --- a/src/server/server_channel_handler.cpp +++ b/src/server/server_channel_handler.cpp @@ -99,6 +99,8 @@ void server_channel_handler::read(channel *ch, message &msg) err = listener_get_attr_int(ch, msg); break; case CMD_LISTENER_GET_ATTR_STR: err = listener_get_attr_str(ch, msg); break; + case CMD_LISTENER_GET_DATA_LIST: + err = listener_get_data_list(ch, msg); break; case CMD_PROVIDER_CONNECT: err = provider_connect(ch, msg); break; case CMD_PROVIDER_PUBLISH: @@ -410,6 +412,50 @@ int server_channel_handler::listener_get_data(channel *ch, message &msg) return OP_SUCCESS; } +int server_channel_handler::listener_get_data_list(ipc::channel *ch, ipc::message &msg) +{ + ipc::message reply; + cmd_listener_get_data_list_t buf; + sensor_data_t *data; + int len; + uint32_t id; + + msg.disclose((char *)&buf); + id = buf.listener_id; + + auto it = m_listeners.find(id); + retv_if(it == m_listeners.end(), -EINVAL); + retvm_if(!has_privileges(ch->get_fd(), m_listeners[id]->get_required_privileges()), + -EACCES, "Permission denied[%d, %s]", + id, m_listeners[id]->get_required_privileges().c_str()); + + int ret = m_listeners[id]->get_data(&data, &len); + retv_if(ret < 0, ret); + + size_t reply_size = sizeof(cmd_listener_get_data_list_t) + len; + cmd_listener_get_data_list_t* reply_buf = (cmd_listener_get_data_list_t *) malloc(reply_size); + if (!reply_buf) { + _E("Failed to allocate memory"); + free(data); + return -ENOMEM; + } + + memcpy(reply_buf->data, data, len); + reply_buf->len = len; + reply_buf->data_count = len / sizeof(sensor_data_t); + reply.enclose((const char *)reply_buf, reply_size); + reply.header()->err = OP_SUCCESS; + reply.header()->type = CMD_LISTENER_GET_DATA_LIST; + + ch->send_sync(&reply); + + free(data); + free(reply_buf); + + return OP_SUCCESS; + +} + int server_channel_handler::provider_connect(channel *ch, message &msg) { sensor_info info; diff --git a/src/server/server_channel_handler.h b/src/server/server_channel_handler.h index 6befe1c5..456c4d1d 100644 --- a/src/server/server_channel_handler.h +++ b/src/server/server_channel_handler.h @@ -58,6 +58,7 @@ private: int listener_get_data(ipc::channel *ch, ipc::message &msg); int listener_get_attr_int(ipc::channel *ch, ipc::message &msg); int listener_get_attr_str(ipc::channel *ch, ipc::message &msg); + int listener_get_data_list(ipc::channel *ch, ipc::message &msg); int provider_connect(ipc::channel *ch, ipc::message &msg); int provider_disconnect(ipc::channel *ch, ipc::message &msg); diff --git a/src/shared/command_types.h b/src/shared/command_types.h index 5d98e46d..7acf8780 100644 --- a/src/shared/command_types.h +++ b/src/shared/command_types.h @@ -48,6 +48,7 @@ enum cmd_type_e { CMD_LISTENER_GET_DATA, CMD_LISTENER_GET_ATTR_INT, CMD_LISTENER_GET_ATTR_STR, + CMD_LISTENER_GET_DATA_LIST, /* Provider */ CMD_PROVIDER_CONNECT = 0x300, @@ -100,6 +101,13 @@ typedef struct { sensor_data_t data; } cmd_listener_get_data_t; +typedef struct { + int listener_id; + int len; + int data_count; + sensor_data_t data[0]; +} cmd_listener_get_data_list_t; + typedef struct { char info[0]; } cmd_provider_connect_t; -- 2.34.1