Change communication from dbus to socket to get list 58/166258/2
authorSeungha Son <seungha.son@samsung.com>
Thu, 28 Dec 2017 02:23:04 +0000 (11:23 +0900)
committerSeungha Son <seungha.son@samsung.com>
Tue, 9 Jan 2018 04:50:15 +0000 (04:50 +0000)
 Change the communication method from dbus to socket to get
 a very large number of notifications safely and quickly.

Related :
data-provider-master - https://review.tizen.org/gerrit/#/c/166259/

Signed-off-by: Seungha Son <seungha.son@samsung.com>
Change-Id: I8b3dc29d4f77b9874913b540f755bd4c42095e9d

CMakeLists.txt
include/notification_ipc.h
include/notification_list.h
include/notification_noti.h
packaging/notification.spec
src/notification_internal.c
src/notification_ipc.c
src/notification_ipc_socket.c [new file with mode: 0644]
src/notification_list.c
src/notification_noti.c

index 664f2456fa685291f2059fc860b4ccb3bc8e8feb..dc86dd8215f2900ce932a6e76aa29b7a04e0a8a8 100755 (executable)
@@ -22,6 +22,7 @@ SET(SRCS
        ./src/notification_list.c
        ./src/notification_status.c
        ./src/notification_ipc.c
+       ./src/notification_ipc_socket.c
        ./src/notification_setting.c
        ./src/notification_setting_service.c
        ./src/notification_internal.c
@@ -67,6 +68,7 @@ pkg_check_modules(pkgs REQUIRED
        libtzplatform-config
        glib-2.0
        gio-2.0
+       gio-unix-2.0
        iniparser
        security-manager
        libsmack
index 4b4ceb0e3db1f1d761a7175682475d78ebd017b1..0eeecf29d5cc822c12385c75304c42d65beac69c 100755 (executable)
@@ -69,8 +69,7 @@ int notification_ipc_update_system_setting(
 int notification_ipc_request_load_noti_by_tag(notification_h noti,
                const char *app_id, const char *tag, uid_t uid);
 int notification_ipc_request_load_noti_grouping_list(notification_type_e type,
-               int count,
-               notification_list_h *list, uid_t uid);
+               int count, int count_per_page, notification_list_h *list, uid_t uid);
 int notification_ipc_request_get_setting_array(
                notification_setting_h *setting_array, int *count, uid_t uid);
 int notification_ipc_request_get_setting_by_app_id(
@@ -99,6 +98,14 @@ int notification_ipc_send_event(notification_h noti, int event_type, int priv_id
 int notification_ipc_check_event_receiver(int priv_id, bool *available);
 void notification_ipc_reset_event_handler(int priv_id);
 int notification_ipc_request_get_all_count(notification_type_e type, int *count, uid_t uid);
+
+/* Functions related with socket */
+int notification_ipc_socket_pair(int *fd);
+int notification_ipc_socket_get_read_buf_size(int fd, unsigned int *size);
+int notification_ipc_socket_get_write_buf_size(int fd, unsigned int *size);
+int notification_ipc_socket_write(int fd, const char *buffer, unsigned int nbytes);
+int notification_ipc_socket_write_string(int fd, const char *buffer, unsigned int string_len);
+int notification_ipc_socket_read(int fd, char *buffer, unsigned int nbytes);
 #ifdef __cplusplus
 }
 #endif
index ef01d262f1942b96ae8f75164c549a7503c9abd0..bfaa64f72b7b8ccc173167b40417d5a4b753a6d3 100644 (file)
@@ -81,6 +81,31 @@ int notification_get_list_for_uid(notification_type_e type,
                int count,
                notification_list_h *list, uid_t uid);
 
+/**
+ * @internal
+ * @brief Gets the notification list associated with the partition into pages.
+ * @since_tizen 4.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in]  type            The notification type
+ * @param[in]  page_number     The page number of the value set \n
+ *                             It starts from @c 1.
+ * @param[in]  count_per_page  The desired maximum count of the data items per page
+ *                             The maximum value is 100, If the value is set more than 100, \n
+ *                             it is automatically set 100.
+ * @param[out] list            The notification list handle
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ *         otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE         Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @see #notification_list_h
+ */
+int notification_get_list_by_page(notification_type_e type,
+               int page_number, int count_per_page, notification_list_h *list);
+
+int notification_get_list_by_page_for_uid(notification_type_e type,
+               int page_number, int count_per_page, notification_list_h *list, uid_t uid);
 /**
  * @internal
  * @brief Returns the notification detail list handle of grouping data.
index fd0d662713b97db53904f64566f38e685a4466f0..171f3a940f548d577fd28f5a0c917e5af7100daf 100644 (file)
@@ -54,8 +54,10 @@ int notification_noti_get_count(notification_type_e type,
 int notification_noti_get_all_count(notification_type_e type, int *count, uid_t uid);
 
 int notification_noti_get_grouping_list(notification_type_e type,
-               int count,
+               int page_number,
+               int count_per_page,
                notification_list_h *list,
+               int *list_count,
                uid_t uid);
 
 int notification_noti_get_detail_list(const char *app_id,
index ef1139787eda9d3d6db137a3b6aec0be4b958e0b..0464ca03b3962db430cc763257fe7214694d4d71 100755 (executable)
@@ -18,6 +18,7 @@ BuildRequires: pkgconfig(capi-appfw-package-manager)
 BuildRequires: pkgconfig(pkgmgr-info)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(gio-unix-2.0)
 BuildRequires: pkgconfig(glib-2.0)
 BuildRequires: pkgconfig(iniparser)
 BuildRequires: pkgconfig(security-manager)
index ca829880b44d519d0b2918466b13c790b0f5ef3b..721a9642da962d7e7770cb06f984451e37738b70 100755 (executable)
@@ -648,7 +648,7 @@ int notification_get_grouping_list_for_uid(notification_type_e type, int count,
        if (list == NULL)
                return NOTIFICATION_ERROR_INVALID_PARAMETER;
 
-       ret = notification_noti_get_grouping_list(type, count, &get_list, uid);
+       ret = notification_noti_get_grouping_list(type, 1, count, &get_list, NULL, uid);
        if (ret != NOTIFICATION_ERROR_NONE)
                return ret;
 
index 78658e9fe5d7483c7260743e6fc17cf2eb2a875b..ea58942ed80704df4b7667ea70cb36d1e43d8095 100755 (executable)
@@ -30,6 +30,7 @@
 #include <notification_internal.h>
 
 #include <gio/gio.h>
+#include <gio/gunixfdlist.h>
 
 #define PROVIDER_BUS_NAME "org.tizen.data_provider_service"
 #define PROVIDER_OBJECT_PATH "/org/tizen/data_provider_service"
@@ -662,11 +663,9 @@ static int _dbus_signal_init()
        return ret;
 }
 
-static int _send_sync_noti(GVariant *body, GDBusMessage **reply, char *cmd)
+static GDBusMessage *__get_new_msg(GVariant *body, const char *cmd)
 {
-       int ret = NOTIFICATION_ERROR_NONE;
-       GError *err = NULL;
-       GDBusMessage *msg;
+       GDBusMessage *msg = NULL;
 
        msg = g_dbus_message_new_method_call(
                        PROVIDER_BUS_NAME,
@@ -678,13 +677,21 @@ static int _send_sync_noti(GVariant *body, GDBusMessage **reply, char *cmd)
                NOTIFICATION_ERR("Failed to alloc new method call");
                if (body)
                        g_variant_unref(body);
-               return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+               return NULL;
                /* LCOV_EXCL_STOP */
        }
 
        if (body != NULL)
                g_dbus_message_set_body(msg, body);
 
+       return msg;
+}
+
+static int __send_message(GDBusMessage *msg, GDBusMessage **reply, const char *cmd)
+{
+       int ret = NOTIFICATION_ERROR_NONE;
+       GError *g_err = NULL;
+
        *reply = g_dbus_connection_send_message_with_reply_sync(
                        _gdbus_conn,
                        msg,
@@ -692,38 +699,85 @@ static int _send_sync_noti(GVariant *body, GDBusMessage **reply, char *cmd)
                        -1,
                        NULL,
                        NULL,
-                       &err);
-
-       g_object_unref(msg);
+                       &g_err);
 
        if (!*reply) {
                /* LCOV_EXCL_START */
                ret = NOTIFICATION_ERROR_SERVICE_NOT_READY;
-               if (err != NULL) {
-                       NOTIFICATION_ERR("No reply. cmd[%s] err[%s]", cmd, err->message);
-                       if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
+               if (g_err != NULL) {
+                       NOTIFICATION_ERR("No reply. cmd[%s] err[%s]", cmd, g_err->message);
+                       if (g_err->code == G_DBUS_ERROR_ACCESS_DENIED)
                                ret = NOTIFICATION_ERROR_PERMISSION_DENIED;
-                       g_error_free(err);
+                       g_error_free(g_err);
                }
                return ret;
                /* LCOV_EXCL_STOP */
        }
 
-       if (g_dbus_message_to_gerror(*reply, &err)) {
-               if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
+       if (g_dbus_message_to_gerror(*reply, &g_err)) {
+               if (g_err->code == G_DBUS_ERROR_ACCESS_DENIED)
                        ret = NOTIFICATION_ERROR_PERMISSION_DENIED;
                else
-                       ret = err->code;
-
-               NOTIFICATION_ERR("Failed to send message[%s] err[%d]", cmd, ret);
-               g_error_free(err);
+                       ret = g_err->code;
+               g_error_free(g_err);
                return ret;
        }
 
-       NOTIFICATION_DBG("Success to send sync message");
+       NOTIFICATION_INFO("Success to send message[%s]", cmd);
        return NOTIFICATION_ERROR_NONE;
 }
 
+static int _send_sync_noti_with_fd(int fd, GVariant *body, GDBusMessage **reply, char *cmd)
+{
+       int ret = NOTIFICATION_ERROR_NONE;
+       GDBusMessage *msg = NULL;
+       GUnixFDList *fd_list = NULL;
+       GError *g_err = NULL;
+
+       fd_list = g_unix_fd_list_new();
+       g_unix_fd_list_append(fd_list, fd, &g_err);
+       if (g_err != NULL) {
+               NOTIFICATION_ERR("g_unix_fd_list_append [%s]", g_err->message);
+               g_object_unref(fd_list);
+               g_error_free(g_err);
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       msg = __get_new_msg(body, cmd);
+       if (msg == NULL) {
+               g_object_unref(fd_list);
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       g_dbus_message_set_unix_fd_list(msg, fd_list);
+
+       ret = __send_message(msg, reply, cmd);
+
+       g_object_unref(msg);
+       g_object_unref(fd_list);
+
+       NOTIFICATION_INFO("Done - send sync message with fd list [%d]", ret);
+       return ret;
+}
+
+static int _send_sync_noti(GVariant *body, GDBusMessage **reply, char *cmd)
+{
+       int ret = NOTIFICATION_ERROR_NONE;
+       GDBusMessage *msg = NULL;
+
+       msg = __get_new_msg(body, cmd);
+       if (msg == NULL)
+               return NOTIFICATION_ERROR_IO_ERROR;
+
+       ret = __send_message(msg, reply, cmd);
+
+       if (msg)
+               g_object_unref(msg);
+
+       NOTIFICATION_INFO("Done - send sync message [%d]", ret);
+       return ret;
+}
+
 static void _send_message_with_reply_async_cb(GDBusConnection *connection,
                GAsyncResult *res,
                gpointer user_data)
@@ -1165,17 +1219,90 @@ int notification_ipc_request_get_count(notification_type_e type,
 }
 /* LCOV_EXCL_STOP */
 
-int notification_ipc_request_load_noti_grouping_list(notification_type_e type, int count,
-               notification_list_h *list, uid_t uid)
+static int __receive_list_from_socket(int fd, notification_list_h *list, int list_count)
+{
+       int ret = NOTIFICATION_ERROR_NONE;
+       char *data = NULL;
+       unsigned int data_size = 0;
+       unsigned int buf_size = 0;
+       notification_h noti;
+       GVariant *noti_body;
+       GVariant *reply_body;
+
+       ret = notification_ipc_socket_get_read_buf_size(fd, &buf_size);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               NOTIFICATION_ERR("get read buf size");
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       data = (char *)calloc(buf_size, sizeof(char));
+       if (data == NULL) {
+               NOTIFICATION_ERR("OOM - socket buffer");
+               return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+       }
+
+       while (list_count > 0) {
+               ret = notification_ipc_socket_read(fd, (char *)&data_size, sizeof(data_size));
+               if (ret != NOTIFICATION_ERROR_NONE) {
+                       NOTIFICATION_ERR("socket read buf [%d]", ret);
+                       goto out;
+               }
+
+               if (data_size > buf_size) {
+                       buf_size = data_size;
+                       if (data)
+                               free(data);
+                       data = (char *)calloc(data_size, sizeof(char));
+                       if (data == NULL) {
+                               ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+                               NOTIFICATION_ERR("OOM - socket bulk buffer");
+                               goto out;
+                       }
+               }
+
+               ret = notification_ipc_socket_read(fd, data, data_size);
+               if (ret != NOTIFICATION_ERROR_NONE) {
+                       NOTIFICATION_ERR("socket read buf [%d]", ret);
+                       goto out;
+               }
+
+               noti = (notification_h)calloc(1, sizeof(struct _notification));
+               if (noti == NULL) {
+                       ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+                       NOTIFICATION_ERR("OOM - notification handle");
+                       goto out;
+               }
+
+               reply_body = g_variant_new_from_data(G_VARIANT_TYPE("(v)"),
+                               data, data_size, TRUE, NULL, NULL);
+               g_variant_get(reply_body, "(v)", &noti_body);
+               notification_ipc_make_noti_from_gvariant(noti, noti_body);
+               *list = notification_list_append(*list, noti);
+               g_variant_unref(noti_body);
+               g_variant_unref(reply_body);
+               list_count--;
+       }
+
+out:
+       if (ret != NOTIFICATION_ERROR_NONE)
+               notification_free_list(*list);
+       if (data)
+               free(data);
+
+       return ret;
+}
+
+int notification_ipc_request_load_noti_grouping_list(notification_type_e type,
+               int count, int count_per_page, notification_list_h *list, uid_t uid)
 {
+#define RCV_SOCK 0
+#define SND_SOCK 1
        int result;
+       int sockfd[2] = { 0, };
+       int list_count;
        GDBusMessage *reply = NULL;
        GVariant *body;
        GVariant *reply_body;
-       GVariant *iter_body;
-       GVariantIter *iter;
-       notification_h noti;
-       GVariant *noti_body;
 
        result = _dbus_init();
        if (result != NOTIFICATION_ERROR_NONE) {
@@ -1185,35 +1312,27 @@ int notification_ipc_request_load_noti_grouping_list(notification_type_e type, i
                /* LCOV_EXCL_STOP */
        }
 
-       body = g_variant_new("(iii)", type, count, uid);
-       result = _send_sync_noti(body, &reply, "load_noti_grouping_list");
+       result = notification_ipc_socket_pair(sockfd);
+       if (result != NOTIFICATION_ERROR_NONE)
+               return result;
+       NOTIFICATION_INFO("socket receive[%d] send[%d]", sockfd[RCV_SOCK], sockfd[SND_SOCK]);
 
+       body = g_variant_new("(iiii)", type, count, count_per_page, uid);
+       result = _send_sync_noti_with_fd(sockfd[SND_SOCK], body, &reply, "load_noti_grouping_list");
        if (result == NOTIFICATION_ERROR_NONE) {
                reply_body = g_dbus_message_get_body(reply);
-               g_variant_get(reply_body, "(a(v))", &iter);
-
-               while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
-                       noti = notification_create(NOTIFICATION_TYPE_NOTI);
-                       if (!noti) {
-                               /* LCOV_EXCL_START */
-                               result = NOTIFICATION_ERROR_OUT_OF_MEMORY;
-                               NOTIFICATION_ERR("failed to create a notification");
-                               notification_free_list(*list);
-                               break;
-                               /* LCOV_EXCL_STOP */
-                       }
-                       g_variant_get(iter_body, "(v)", &noti_body);
-                       notification_ipc_make_noti_from_gvariant(noti, noti_body);
-                       *list = notification_list_append(*list, noti);
-                       g_variant_unref(noti_body);
-               }
-               g_variant_iter_free(iter);
+               g_variant_get(reply_body, "(i)", &list_count);
+               result = __receive_list_from_socket(sockfd[RCV_SOCK], list, list_count);
        }
 
        if (reply)
                g_object_unref(reply);
+       if (sockfd[RCV_SOCK])
+               close(sockfd[RCV_SOCK]);
+       if (sockfd[SND_SOCK])
+               close(sockfd[SND_SOCK]);
 
-       NOTIFICATION_DBG("result[%d]", result);
+       NOTIFICATION_INFO("result [%d]", result);
        return result;
 }
 
diff --git a/src/notification_ipc_socket.c b/src/notification_ipc_socket.c
new file mode 100644 (file)
index 0000000..08fbb36
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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 <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "notification_ipc.h"
+#include "notification_debug.h"
+
+#define RCV_SOCK 0
+#define SND_SOCK 1
+
+#define MAX_RETRY_CNT 10
+#define WRITE_TIMEOUT 20 /* milliseconds*/
+
+EXPORT_API int notification_ipc_socket_pair(int *fd)
+{
+       int ret_fd[2];
+       int err;
+
+       if (fd == NULL)
+               return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+       errno = 0;
+       err = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, ret_fd);
+       if (err < 0) {
+               NOTIFICATION_ERR("socketpair [%d]", errno);
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       fd[RCV_SOCK] = ret_fd[RCV_SOCK];
+       fd[SND_SOCK] = ret_fd[SND_SOCK];
+
+       return NOTIFICATION_ERROR_NONE;
+}
+
+static int __get_socket_buffer_size(int fd, unsigned int *size, int optname)
+{
+       unsigned int ret_size = 0;
+       socklen_t len = sizeof(ret_size);
+
+       errno = 0;
+       if (getsockopt(fd, SOL_SOCKET, optname, &ret_size, &len) < 0) {
+               NOTIFICATION_ERR("read socket size [%d]", errno);
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       *size = ret_size;
+
+       return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_ipc_socket_get_read_buf_size(int fd, unsigned int *size)
+{
+       return __get_socket_buffer_size(fd, size, SO_RCVBUF);
+}
+
+EXPORT_API int notification_ipc_get_socket_write_buf_size(int fd, unsigned int *size)
+{
+       return __get_socket_buffer_size(fd, size, SO_SNDBUF);
+}
+
+
+EXPORT_API int notification_ipc_socket_write(int fd, const char *buffer, unsigned int nbytes)
+{
+       int retry_cnt = 0;
+       unsigned int left = nbytes;
+       ssize_t nb;
+       const struct timespec SLEEP_TIME = { 0, 20 * 1000 * 1000 };
+
+       while (left && (retry_cnt < MAX_RETRY_CNT)) {
+               errno = 0;
+               nb = write(fd, buffer, left);
+               if (nb == -1) {
+                       if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+                               NOTIFICATION_ERR("continue..");
+                               retry_cnt++;
+                               nanosleep(&SLEEP_TIME, 0);
+                               continue;
+                       }
+                       NOTIFICATION_ERR("error fd [%d] errno [%d]", fd, errno);
+                       return NOTIFICATION_ERROR_IO_ERROR;
+               }
+
+               left -= nb;
+               buffer += nb;
+               retry_cnt = 0;
+       }
+
+       if (left != 0) {
+               NOTIFICATION_ERR("error fd [%d], retry_cnt [%d]", fd, retry_cnt);
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_ipc_socket_write_string(int fd, const char *buffer, unsigned int string_len)
+{
+       int ret;
+
+       ret = notification_ipc_socket_write(fd, (char *)&string_len, sizeof(string_len));
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               NOTIFICATION_ERR("write string_len fail");
+               return ret;
+       }
+
+       if (string_len > 0) {
+               ret = notification_ipc_socket_write(fd, buffer, string_len);
+               if (ret != NOTIFICATION_ERROR_NONE) {
+                       NOTIFICATION_ERR("write string fail");
+                       return ret;
+               }
+       }
+
+       return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_ipc_socket_read(int fd, char *buffer, unsigned int nbytes)
+{
+       unsigned int left = nbytes;
+       ssize_t nb;
+       int retry_cnt = 0;
+       const struct timespec SLEEP_TIME = { 0, 20 * 1000 * 1000 };
+
+       while (left && (retry_cnt < MAX_RETRY_CNT)) {
+               errno = 0;
+               nb = read(fd, buffer, left);
+               if (nb == 0) {
+                       NOTIFICATION_ERR("read socket - EOF, fd close [%d]", fd);
+                       return NOTIFICATION_ERROR_IO_ERROR;
+               } else if (nb == -1) {
+                       if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+                               NOTIFICATION_ERR("errno [%d], sleep and retry", errno);
+                               retry_cnt++;
+                               nanosleep(&SLEEP_TIME, 0);
+                               continue;
+                       }
+                       NOTIFICATION_ERR("errno [%d] fd [%d]", errno, fd);
+                       return NOTIFICATION_ERROR_IO_ERROR;
+               }
+               left -= nb;
+               buffer += nb;
+               retry_cnt = 0;
+       }
+
+       if (left != 0) {
+               NOTIFICATION_ERR("error fd [%d] retry_cnt [%d]", fd, retry_cnt);
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       return NOTIFICATION_ERROR_NONE;
+}
index 30724cd2c3d3929306708beb879b39cff6bc3000..989c1682abff063f29961d70c7fcbd0a99439623 100755 (executable)
@@ -257,7 +257,7 @@ EXPORT_API int notification_get_list_for_uid(notification_type_e type,
        if (list == NULL)
                return NOTIFICATION_ERROR_INVALID_PARAMETER;
 
-       ret = notification_ipc_request_load_noti_grouping_list(type, count, &get_list, uid);
+       ret = notification_ipc_request_load_noti_grouping_list(type, 1, count, &get_list, uid);
        if (ret != NOTIFICATION_ERROR_NONE)
                return ret;
 
@@ -274,6 +274,52 @@ EXPORT_API int notification_get_list(notification_type_e type,
        return notification_get_list_for_uid(type, count, list, getuid());
 }
 
+EXPORT_API int notification_get_list_by_page_for_uid(notification_type_e type,
+               int page_number,
+               int count_per_page,
+               notification_list_h *list,
+               uid_t uid)
+{
+#define COUNT_PER_PAGE_MAX 100
+
+       int ret;
+       notification_list_h get_list = NULL;
+
+       if (list == NULL) {
+               NOTIFICATION_ERR("Invalid parameter - list is null");
+               return NOTIFICATION_ERROR_INVALID_PARAMETER;
+       }
+
+       if (page_number <= 0) {
+               NOTIFICATION_ERR("Invalid parameter - page_number [%d]", page_number);
+               return NOTIFICATION_ERROR_INVALID_PARAMETER;
+       }
+
+       if (count_per_page > COUNT_PER_PAGE_MAX) {
+               NOTIFICATION_WARN("count_per_page exceeds max value, max must be set %d",
+                               COUNT_PER_PAGE_MAX);
+               count_per_page = COUNT_PER_PAGE_MAX;
+       }
+
+       ret = notification_ipc_request_load_noti_grouping_list(type,
+                       page_number, count_per_page, &get_list, uid);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               NOTIFICATION_ERR("fail request load noti grouping list");
+               return ret;
+       }
+
+       *list = notification_list_get_head(get_list);
+
+       return ret;
+}
+
+EXPORT_API int notification_get_list_by_page(notification_type_e type,
+       int page_number, int count_per_page, notification_list_h *list)
+{
+       return notification_get_list_by_page_for_uid(type,
+                       page_number, count_per_page, list, getuid());
+}
+
 EXPORT_API int notification_get_detail_list_for_uid(const char *app_id,
                int group_id,
                int priv_id,
@@ -281,8 +327,8 @@ EXPORT_API int notification_get_detail_list_for_uid(const char *app_id,
                notification_list_h *list,
                uid_t uid)
 {
-       notification_list_h get_list = NULL;
        int ret = 0;
+       notification_list_h get_list = NULL;
 
        if (list == NULL || app_id == NULL)
                return NOTIFICATION_ERROR_INVALID_PARAMETER;
index 8706df612b38e9b64f39f0783ebf298f9160fae7..665342c50e138dc2ee148c9bf7fbfb443b96a8e5 100755 (executable)
@@ -616,7 +616,7 @@ err:
        return ret;
 }
 
-static int _get_notification_list(char *query_where, notification_list_h *list, int count)
+static int _get_notification_list(char *query_where, notification_list_h *list, int *list_count, int count)
 {
        int ret;
        int internal_count = 0;
@@ -664,9 +664,7 @@ static int _get_notification_list(char *query_where, notification_list_h *list,
                __notification_noti_populate_from_stmt(stmt, noti);
                if (noti != NULL) {
                        internal_count++;
-
                        get_list = notification_list_append(get_list, noti);
-
                        if (count != -1 && internal_count >= count) {
                                NOTIFICATION_INFO
                                ("internal count[%d] count[%d]",
@@ -683,8 +681,10 @@ err:
        if (db != NULL)
                notification_db_close(&db);
 
-       if (get_list != NULL)
+       if (get_list != NULL) {
                *list = notification_list_get_head(get_list);
+               *list_count = internal_count;
+       }
 
        return ret;
 }
@@ -1626,8 +1626,10 @@ out:
 }
 
 EXPORT_API int notification_noti_get_grouping_list(notification_type_e type,
-                                                       int count,
+                                                       int page_number,
+                                                       int count_per_page,
                                                        notification_list_h *list,
+                                                       int *list_count,
                                                        uid_t uid)
 {
        char *query = NULL;
@@ -1635,6 +1637,7 @@ EXPORT_API int notification_noti_get_grouping_list(notification_type_e type,
        char *query_where = NULL;
        int ret = NOTIFICATION_ERROR_NONE;
        int status;
+       int start_index;
 
        /* Check current sim status */
        ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
@@ -1668,8 +1671,18 @@ EXPORT_API int notification_noti_get_grouping_list(notification_type_e type,
                }
        }
 
-       query = sqlite3_mprintf("noti_list WHERE 1 > 0 %s %s "
-                       "ORDER BY rowid DESC, time DESC", query_where, query_uid);
+       if (count_per_page > 0) {
+               start_index = (page_number - 1) * count_per_page;
+               query = sqlite3_mprintf("noti_list WHERE 1 > 0 %s %s "
+                               "ORDER BY rowid DESC, time DESC LIMIT %d,%d",
+                               query_where, query_uid, start_index, count_per_page);
+       } else {
+               query = sqlite3_mprintf("noti_list WHERE 1 > 0 %s %s "
+                               "ORDER BY rowid DESC, time DESC",
+                               query_where, query_uid);
+               count_per_page = -1;
+       }
+
        if (query == NULL) {
                /* LCOV_EXCL_START */
                ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
@@ -1677,7 +1690,7 @@ EXPORT_API int notification_noti_get_grouping_list(notification_type_e type,
                /* LCOV_EXCL_STOP */
        }
 
-       ret = _get_notification_list(query, list, count);
+       ret = _get_notification_list(query, list, list_count, count_per_page);
 
 err:
        if (query_where)
@@ -1755,7 +1768,7 @@ EXPORT_API int notification_noti_get_detail_list(const char *app_id,
                /* LCOV_EXCL_STOP */
        }
 
-       ret = _get_notification_list(query, list, count);
+       ret = _get_notification_list(query, list, NULL, count);
 
 err:
        if (query_where)