Implement sensord_get_data_list 14/218914/1
authorBoram Bae <boram21.bae@samsung.com>
Fri, 29 Nov 2019 04:35:56 +0000 (13:35 +0900)
committerBoram Bae <boram21.bae@samsung.com>
Fri, 29 Nov 2019 04:35:56 +0000 (13:35 +0900)
* 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 <boram21.bae@samsung.com>
include/sensor_internal.h
src/client-dummy/client_dummy.cpp
src/client/sensor_internal.cpp
src/client/sensor_listener.cpp
src/client/sensor_listener.h
src/sensorctl/testcase/sensor_listener.cpp
src/sensorctl/testcase/sensor_provider.cpp
src/server/server_channel_handler.cpp
src/server/server_channel_handler.h
src/shared/command_types.h

index 07638fd57c4f8408b6da36e2528348b47e65a705..1fbfabeb0e6a4dea30b303101108553320ae5d31 100644 (file)
@@ -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
  *
index accc043049be28e28949df0742c878951aacf4a2..8432ba21784148f5b735ce938f6ca2016c2bc1b3 100644 (file)
@@ -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;
index 376059c6ea960ed6104026f1d0c975fdf3548e31..950c28dead67a74bb6d05d66fce87fe17a0066ba 100644 (file)
@@ -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;
index 6cea7d328c3be16e7d545f232480671727733ee1..c979244e48a980ad4cefaebe099578d2812c0fbd 100644 (file)
@@ -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;
+}
index 47cab206c3160bbbe1930917fcda97e1dad3364e..581b2a1152e3f2217651183dbee1dacee47def65 100644 (file)
@@ -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);
index c5adee272919d87bfd64ecdda0b78a045baf78b7..6fc6bf45ee415d5c55524c71fc1f41f6b6655f60 100644 (file)
@@ -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);
index bcd5101d8446f00b4a3bd94a48e281831dacbaa5..d7ed1bbea844299fd6cc875d30f0efe7debbcb09 100644 (file)
@@ -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
index c8c8d0bec68e242f8382ae171ea91ae5642b50c8..69f15f4619fbf0fa5528069c6faed5bfc25e869a 100644 (file)
@@ -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;
index 6befe1c549e57a3520a07263c2cfb66ca0c15aae..456c4d1d8d7b15a8ab3037e3c5a75666c5631d15 100644 (file)
@@ -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);
index 5d98e46d7603576c19cce1e2d02bac7f7ce8a207..7acf878029d487949eec1d56133b03d0ddfa04e6 100644 (file)
@@ -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;