From: Seungha Son Date: Thu, 28 Dec 2017 02:23:04 +0000 (+0900) Subject: Change communication from dbus to socket to get list X-Git-Tag: submit/tizen_4.0/20180109.060519~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=95c0da70ebc50f4bcc49b52c1e5ee239065d7a85;p=platform%2Fcore%2Fapi%2Fnotification.git Change communication from dbus to socket to get list 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 Change-Id: I8b3dc29d4f77b9874913b540f755bd4c42095e9d --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 664f2456..dc86dd82 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/include/notification_ipc.h b/include/notification_ipc.h index 4b4ceb0e..0eeecf29 100755 --- a/include/notification_ipc.h +++ b/include/notification_ipc.h @@ -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 diff --git a/include/notification_list.h b/include/notification_list.h index ef01d262..bfaa64f7 100644 --- a/include/notification_list.h +++ b/include/notification_list.h @@ -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. diff --git a/include/notification_noti.h b/include/notification_noti.h index fd0d6627..171f3a94 100644 --- a/include/notification_noti.h +++ b/include/notification_noti.h @@ -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, diff --git a/packaging/notification.spec b/packaging/notification.spec index ef113978..0464ca03 100755 --- a/packaging/notification.spec +++ b/packaging/notification.spec @@ -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) diff --git a/src/notification_internal.c b/src/notification_internal.c index ca829880..721a9642 100755 --- a/src/notification_internal.c +++ b/src/notification_internal.c @@ -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; diff --git a/src/notification_ipc.c b/src/notification_ipc.c index 78658e9f..ea58942e 100755 --- a/src/notification_ipc.c +++ b/src/notification_ipc.c @@ -30,6 +30,7 @@ #include #include +#include #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)", ¬i_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)", ¬i_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 index 00000000..08fbb368 --- /dev/null +++ b/src/notification_ipc_socket.c @@ -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 +#include +#include + +#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; +} diff --git a/src/notification_list.c b/src/notification_list.c index 30724cd2..989c1682 100755 --- a/src/notification_list.c +++ b/src/notification_list.c @@ -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; diff --git a/src/notification_noti.c b/src/notification_noti.c index 8706df61..665342c5 100755 --- a/src/notification_noti.c +++ b/src/notification_noti.c @@ -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)