Change communication from dbus to socket to get list 31/165331/14
authorSeungha Son <seungha.son@samsung.com>
Thu, 28 Dec 2017 02:23:04 +0000 (11:23 +0900)
committerSeungha Son <seungha.son@samsung.com>
Mon, 8 Jan 2018 06:26:28 +0000 (15:26 +0900)
 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/165334/

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 d4b4966..b92dfa5 100755 (executable)
@@ -31,6 +31,7 @@ pkg_check_modules(pkgs REQUIRED
        libtzplatform-config
        glib-2.0
        gio-2.0
+       gio-unix-2.0
        iniparser
        security-manager
        libsmack
index 4b4ceb0..0eeecf2 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 ef01d26..bfaa64f 100644 (file)
@@ -83,6 +83,31 @@ int notification_get_list_for_uid(notification_type_e type,
 
 /**
  * @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.
  * @details If count is equal to c -1, all notifications are returned.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
index a12eb86..77a81ea 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 69cb6f6..387c9f9 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 c7da4d8..45d655b 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 91f5069..fe0ce76 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"
@@ -651,11 +652,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,
@@ -667,13 +666,21 @@ static int _send_sync_noti(GVariant *body, GDBusMessage **reply, char *cmd)
                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,
@@ -681,38 +688,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) {
-                       ERR("No reply. cmd[%s] err[%s]", cmd, err->message);
-                       if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
+               if (g_err != NULL) {
+                       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;
-
-               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;
        }
 
-       DBG("Success to send sync message");
+       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) {
+               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);
+
+       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);
+
+       INFO("Done - send sync message [%d]", ret);
+       return ret;
+}
+
 static void _send_message_with_reply_async_cb(GDBusConnection *connection,
                GAsyncResult *res,
                gpointer user_data)
@@ -1154,17 +1208,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) {
+               ERR("get read buf size");
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       data = (char *)calloc(buf_size, sizeof(char));
+       if (data == NULL) {
+               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) {
+                       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;
+                               ERR("OOM - socket bulk buffer");
+                               goto out;
+                       }
+               }
+
+               ret = notification_ipc_socket_read(fd, data, data_size);
+               if (ret != NOTIFICATION_ERROR_NONE) {
+                       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;
+                       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) {
@@ -1174,35 +1301,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;
+       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;
-                               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]);
 
-       DBG("result[%d]", result);
+       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..fa44356
--- /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) {
+               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) {
+               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) {
+                               ERR("continue..");
+                               retry_cnt++;
+                               nanosleep(&SLEEP_TIME, 0);
+                               continue;
+                       }
+                       ERR("error fd [%d] errno [%d]", fd, errno);
+                       return NOTIFICATION_ERROR_IO_ERROR;
+               }
+
+               left -= nb;
+               buffer += nb;
+               retry_cnt = 0;
+       }
+
+       if (left != 0) {
+               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) {
+               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) {
+                       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) {
+                       ERR("read socket - EOF, fd close [%d]", fd);
+                       return NOTIFICATION_ERROR_IO_ERROR;
+               } else if (nb == -1) {
+                       if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+                               ERR("errno [%d], sleep and retry", errno);
+                               retry_cnt++;
+                               nanosleep(&SLEEP_TIME, 0);
+                               continue;
+                       }
+                       ERR("errno [%d] fd [%d]", errno, fd);
+                       return NOTIFICATION_ERROR_IO_ERROR;
+               }
+               left -= nb;
+               buffer += nb;
+               retry_cnt = 0;
+       }
+
+       if (left != 0) {
+               ERR("error fd [%d] retry_cnt [%d]", fd, retry_cnt);
+               return NOTIFICATION_ERROR_IO_ERROR;
+       }
+
+       return NOTIFICATION_ERROR_NONE;
+}
index 61d5555..18d14b2 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) {
+               ERR("Invalid parameter - list is null");
+               return NOTIFICATION_ERROR_INVALID_PARAMETER;
+       }
+
+       if (page_number <= 0) {
+               ERR("Invalid parameter - page_number [%d]", page_number);
+               return NOTIFICATION_ERROR_INVALID_PARAMETER;
+       }
+
+       if (count_per_page > COUNT_PER_PAGE_MAX) {
+               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) {
+               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 1c8a6ed..4a3b473 100755 (executable)
@@ -618,7 +618,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;
@@ -666,9 +666,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) {
                                INFO("internal count[%d] count[%d]",
                                internal_count, count);
@@ -684,8 +682,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;
 }
@@ -1627,8 +1627,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;
@@ -1636,6 +1638,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);
@@ -1669,8 +1672,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;
@@ -1678,7 +1691,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)
@@ -1756,7 +1769,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)