summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjusung son <jusung07.son@samsung.com>2019-03-29 14:39:55 +0900
committerjusung son <jusung07.son@samsung.com>2019-03-29 14:39:55 +0900
commit8cf6ca98110b621a6f5c33bb58bc1fd68af721d8 (patch)
tree3ff2da72787fd61e9adca1cb8b5892d870f892b5
parent727ebe6820e16937c07f77ad92d9c467afaa8430 (diff)
parent18d51ef8a88e1ace447813be77134bafc71cdb07 (diff)
downloadnotification-feature/noti_ex.tar.gz
notification-feature/noti_ex.tar.bz2
notification-feature/noti_ex.zip
Merge branch 'tizen' into feature/noti_exfeature/noti_ex
Conflicts: AUTHORS CMakeLists.txt LICENSE packaging/notification.spec
-rwxr-xr-xAUTHORS2
-rwxr-xr-xCMakeLists.txt72
-rw-r--r--doc/notification_doc.h55
-rw-r--r--notification-ex.manifest5
-rw-r--r--notification-ex/CMakeLists.txt47
-rw-r--r--notification-ex/abstract_action.cc85
-rw-r--r--notification-ex/abstract_action.h63
-rw-r--r--notification-ex/abstract_action_implementation.h47
-rw-r--r--notification-ex/abstract_item.cc451
-rw-r--r--notification-ex/abstract_item.h277
-rw-r--r--notification-ex/abstract_item_implementation.h72
-rw-r--r--notification-ex/action_inflator.cc42
-rw-r--r--notification-ex/action_inflator.h38
-rw-r--r--notification-ex/app_control_action.cc147
-rw-r--r--notification-ex/app_control_action.h50
-rw-r--r--notification-ex/app_control_action_implementation.h43
-rw-r--r--notification-ex/button_item.cc80
-rw-r--r--notification-ex/button_item.h51
-rw-r--r--notification-ex/button_item_implementation.h46
-rw-r--r--notification-ex/chat_message_item.cc158
-rw-r--r--notification-ex/chat_message_item.h66
-rw-r--r--notification-ex/chat_message_item_implementation.h52
-rw-r--r--notification-ex/checkbox_item.cc85
-rw-r--r--notification-ex/checkbox_item.h49
-rw-r--r--notification-ex/checkbox_item_implementation.h45
-rw-r--r--notification-ex/common.h42
-rw-r--r--notification-ex/db_manager.cc774
-rw-r--r--notification-ex/db_manager.h67
-rw-r--r--notification-ex/dbus_connection_manager.cc119
-rw-r--r--notification-ex/dbus_connection_manager.h48
-rw-r--r--notification-ex/dbus_event_listener.cc218
-rw-r--r--notification-ex/dbus_event_listener.h42
-rw-r--r--notification-ex/dbus_event_listener_implementation.h63
-rw-r--r--notification-ex/dbus_sender.cc155
-rw-r--r--notification-ex/dbus_sender.h45
-rw-r--r--notification-ex/dbus_sender_implementation.h46
-rw-r--r--notification-ex/default_action_factory.cc54
-rw-r--r--notification-ex/default_action_factory.h36
-rw-r--r--notification-ex/default_item_factory.cc83
-rw-r--r--notification-ex/default_item_factory.h36
-rw-r--r--notification-ex/entry_item.cc93
-rw-r--r--notification-ex/entry_item.h54
-rw-r--r--notification-ex/entry_item_implementation.h46
-rw-r--r--notification-ex/event_info.cc156
-rw-r--r--notification-ex/event_info_implementation.h54
-rw-r--r--notification-ex/event_info_internal.h60
-rw-r--r--notification-ex/event_listener_interface.h42
-rw-r--r--notification-ex/event_observer_interface.h40
-rw-r--r--notification-ex/event_sender_interface.h40
-rw-r--r--notification-ex/ex_bundle.h230
-rw-r--r--notification-ex/ex_util.cc105
-rw-r--r--notification-ex/ex_util.h33
-rw-r--r--notification-ex/exception.h89
-rw-r--r--notification-ex/factory_manager.cc67
-rw-r--r--notification-ex/factory_manager.h50
-rw-r--r--notification-ex/group_item.cc167
-rw-r--r--notification-ex/group_item.h58
-rw-r--r--notification-ex/group_item_implementation.h49
-rw-r--r--notification-ex/iaction_factory.h38
-rw-r--r--notification-ex/icon_item.cc54
-rw-r--r--notification-ex/icon_item.h45
-rw-r--r--notification-ex/icon_item_implementation.h44
-rw-r--r--notification-ex/icon_text_item.cc94
-rw-r--r--notification-ex/icon_text_item.h54
-rw-r--r--notification-ex/icon_text_item_implementation.h46
-rw-r--r--notification-ex/ievent_info.h49
-rw-r--r--notification-ex/ievent_info_internal.h36
-rw-r--r--notification-ex/iitem_factory.h38
-rw-r--r--notification-ex/iitem_info.h37
-rw-r--r--notification-ex/iitem_info_internal.h43
-rw-r--r--notification-ex/image_item.cc81
-rw-r--r--notification-ex/image_item.h50
-rw-r--r--notification-ex/image_item_implementation.h44
-rw-r--r--notification-ex/input_selector_item.cc90
-rw-r--r--notification-ex/input_selector_item.h53
-rw-r--r--notification-ex/input_selector_item_implementation.h46
-rw-r--r--notification-ex/item_inflator.cc42
-rw-r--r--notification-ex/item_inflator.h37
-rw-r--r--notification-ex/item_info.cc90
-rw-r--r--notification-ex/item_info_internal.h49
-rw-r--r--notification-ex/manager.cc218
-rw-r--r--notification-ex/manager.h71
-rw-r--r--notification-ex/manager_implementation.h48
-rw-r--r--notification-ex/mock_listener.h40
-rw-r--r--notification-ex/mock_sender.h38
-rw-r--r--notification-ex/notification-ex.pc.in11
-rw-r--r--notification-ex/null_item.cc62
-rw-r--r--notification-ex/null_item.h44
-rw-r--r--notification-ex/progress_item.cc105
-rw-r--r--notification-ex/progress_item.h56
-rw-r--r--notification-ex/progress_item_implementation.h51
-rw-r--r--notification-ex/reporter.cc165
-rw-r--r--notification-ex/reporter.h67
-rw-r--r--notification-ex/reporter_implementation.h47
-rw-r--r--notification-ex/text_item.cc90
-rw-r--r--notification-ex/text_item.h53
-rw-r--r--notification-ex/text_item_implementation.h46
-rw-r--r--notification-ex/time_item.cc104
-rw-r--r--notification-ex/time_item.h54
-rw-r--r--notification-ex/time_item_implementation.h46
-rw-r--r--notification-ex/visibility_action.cc128
-rw-r--r--notification-ex/visibility_action.h47
-rw-r--r--notification-ex/visibility_action_implementation.h53
-rw-r--r--notification.manifest5
-rw-r--r--notification/11_notification-add.post1
-rw-r--r--notification/CMakeLists.txt68
-rw-r--r--notification/include/notification.h1865
-rw-r--r--notification/include/notification_db.h37
-rw-r--r--notification/include/notification_debug.h75
-rw-r--r--notification/include/notification_error.h62
-rw-r--r--notification/include/notification_group.h49
-rw-r--r--notification/include/notification_internal.h1506
-rw-r--r--notification/include/notification_ipc.h114
-rw-r--r--notification/include/notification_list.h454
-rw-r--r--notification/include/notification_noti.h93
-rw-r--r--notification/include/notification_ongoing.h130
-rw-r--r--notification/include/notification_ongoing_flag.h83
-rw-r--r--notification/include/notification_private.h187
-rw-r--r--notification/include/notification_setting.h259
-rw-r--r--notification/include/notification_setting_internal.h1493
-rw-r--r--notification/include/notification_setting_service.h54
-rw-r--r--notification/include/notification_shared_file.h38
-rw-r--r--notification/include/notification_status.h60
-rw-r--r--notification/include/notification_status_internal.h105
-rw-r--r--notification/include/notification_text_domain.h95
-rw-r--r--notification/include/notification_type.h403
-rw-r--r--notification/include/notification_type_internal.h84
-rw-r--r--notification/include/notification_viewer.h24
-rw-r--r--notification/notification.pc.in11
-rw-r--r--notification/src/notification.c2035
-rw-r--r--notification/src/notification_db.c229
-rw-r--r--notification/src/notification_db_query.h359
-rw-r--r--notification/src/notification_error.c60
-rw-r--r--notification/src/notification_group.c181
-rw-r--r--notification/src/notification_init.c84
-rw-r--r--notification/src/notification_internal.c2133
-rw-r--r--notification/src/notification_ipc.c2726
-rw-r--r--notification/src/notification_ipc_socket.c173
-rw-r--r--notification/src/notification_list.c376
-rw-r--r--notification/src/notification_noti.c2299
-rw-r--r--notification/src/notification_ongoing.c273
-rw-r--r--notification/src/notification_setting.c1125
-rw-r--r--notification/src/notification_setting_service.c931
-rw-r--r--notification/src/notification_shared_file.c1185
-rw-r--r--notification/src/notification_status.c197
-rw-r--r--notification/src/notification_viewer.c113
-rw-r--r--notification/test-app/CMakeLists.txt44
-rw-r--r--notification/test-app/main.c911
-rwxr-xr-xpackaging/notification.spec209
-rw-r--r--scripts/505.notification_upgrade.sh234
-rw-r--r--unittest/CMakeLists.txt42
-rw-r--r--unittest/mock/app_common.h42
-rw-r--r--unittest/mock/fff.h6493
-rw-r--r--unittest/mock/mock.cc10
-rw-r--r--unittest/mock/mock.h22
-rw-r--r--unittest/src/test_abstract_item.cc220
-rw-r--r--unittest/src/test_app_control_action.cc92
-rw-r--r--unittest/src/test_bundle.cc120
-rw-r--r--unittest/src/test_button_item.cc48
-rw-r--r--unittest/src/test_chat_message_item.cc74
-rw-r--r--unittest/src/test_checkbox_item.cc64
-rw-r--r--unittest/src/test_entry_item.cc73
-rw-r--r--unittest/src/test_event_info.cc39
-rw-r--r--unittest/src/test_group_item.cc109
-rw-r--r--unittest/src/test_icon_item.cc61
-rw-r--r--unittest/src/test_icon_text_item.cc63
-rw-r--r--unittest/src/test_image_item.cc62
-rw-r--r--unittest/src/test_input_selector_item.cc47
-rw-r--r--unittest/src/test_main.cc37
-rw-r--r--unittest/src/test_progress_item.cc38
-rw-r--r--unittest/src/test_text_item.cc77
-rw-r--r--unittest/src/test_time_item.cc63
-rw-r--r--unittest/src/test_visibility_action.cc82
173 files changed, 39239 insertions, 164 deletions
diff --git a/AUTHORS b/AUTHORS
index de95323..fa6ae31 100755
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,4 @@
Seungtaek Chung <seungtaek.chung@samsung.com>
Mi-Ju Lee <miju52.lee@samsung.com>
Xi zhichan <zhichan.xi@samsung.com>
-Youngsub Ko <ys4610.ko@samsung.com>
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1f80c2f..90ed25c 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,67 +1,11 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(notification C)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
-SET(PREFIX ${CMAKE_INSTALL_PREFIX})
-SET(EXEC_PREFIX "\${prefix}")
-SET(LIBDIR "\${prefix}/lib")
-SET(INCLUDEDIR "\${prefix}/include/${PROJECT_NAME}")
-SET(ICONDIR "${PREFIX}/share/${PROJECT_NAME}")
-SET(DBDIR "/opt/dbspace")
-SET(DBFILE ".notification.db")
-SET(MAJOR_VER 0)
-SET(VERSION ${MAJOR_VER}.1.0)
+ENABLE_TESTING()
+SET(NOTIFICATION_UNIT_TESTS notification-ex_unittests)
+ADD_TEST(NAME ${NOTIFICATION_UNIT_TESTS} COMMAND ${NOTIFICATION_UNIT_TESTS})
-SET(SRCS ./src/notification.c
- ./src/notification_noti.c
- ./src/notification_ongoing.c
- ./src/notification_group.c
- ./src/notification_db.c
- ./src/notification_list.c)
-SET(HEADERS ./include/notification.h
- ./include/notification_error.h
- ./include/notification_type.h
- ./include/notification_list.h)
-
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
-
-INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED
- sqlite3
- db-util
- vconf
- bundle
- dlog
- ail
- aul
- appsvc
- dbus-1
- dbus-glib-1
-)
-
-FOREACH(flag ${pkgs_CFLAGS})
- SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
-ENDFOREACH(flag)
-
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -g -Wall")
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
-
-SET(CMAKE_SKIP_BUILD_RPATH TRUE)
-
-ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
-ADD_DEFINITIONS("-DICONDIR=\"${ICONDIR}\"")
-ADD_DEFINITIONS("-DDBDIR=\"${DBDIR}\"")
-ADD_DEFINITIONS("-DDBFILE=\"${DBFILE}\"")
-
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
-SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${MAJOR_VER})
-SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
-
-CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
-
-INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries)
-INSTALL(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig)
-FOREACH(hfile ${HEADERS})
- INSTALL(FILES ${CMAKE_SOURCE_DIR}/${hfile} DESTINATION include/${PROJECT_NAME})
-ENDFOREACH(hfile)
+ADD_SUBDIRECTORY(notification)
+ADD_SUBDIRECTORY(notification-ex)
+ADD_SUBDIRECTORY(unittest)
+ADD_DEPENDENCIES(notification-ex_unittests notification-ex)
diff --git a/doc/notification_doc.h b/doc/notification_doc.h
new file mode 100644
index 0000000..83ae4dd
--- /dev/null
+++ b/doc/notification_doc.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2000 - 2016 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.
+ */
+
+
+/**
+ * @ingroup CAPI_APPLICATION_FRAMEWORK
+ * @defgroup NOTIFICATION_MODULE Notification
+ * @brief Notification APIs.
+ * @section NOTIFICATION_MODULE_HEADER Required Header
+ * \#include <notification.h>
+ *
+ * @section NOTIFICATION_MODULE_OVERVIEW Overview
+ * A notification is a message that is displayed on the notification area or the ongoing area.
+ * It is created to notify information to the user through the application.
+ * This API provides functions for creating, inserting and updating notification.
+ */
+
+
+/**
+ * @internal
+ * @ingroup NOTIFICATION_MODULE
+ * @defgroup NOTIFICATION_LIST Notification List
+ * @brief Linked list of notification data.
+ * @section NOTIFICATION_LIST_MODULE_HEADER Required Header
+ * \#include <notification.h>
+ *
+ * @section NOTIFICATION_LIST_MODULE_OVERVIEW Overview
+ * It provides functions for handling notification list.
+ *
+ */
+
+
+/**
+ * @ingroup NOTIFICATION_MODULE
+ * @defgroup NOTIFICATION_STATUS Notification Status
+ * @brief APIs displaying plain text message on the indicator area.
+ * @section NOTIFICATION_STATUS_MODULE_HEADER Required Header
+ * \#include <notification.h>
+ *
+ * @section NOTIFICATION_STATUS_MODULE_OVERVIEW Overview
+ * Notification status APIs.
+ */
diff --git a/notification-ex.manifest b/notification-ex.manifest
new file mode 100644
index 0000000..6c61ae0
--- /dev/null
+++ b/notification-ex.manifest
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
diff --git a/notification-ex/CMakeLists.txt b/notification-ex/CMakeLists.txt
new file mode 100644
index 0000000..ea587cc
--- /dev/null
+++ b/notification-ex/CMakeLists.txt
@@ -0,0 +1,47 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(notification-ex CXX)
+
+SET(PREFIX "${CMAKE_INSTALL_PREFIX}")
+SET(EXEC_PREFIX "\${prefix}")
+SET(PROJECT_NAME "${PROJECT_NAME}")
+SET(LIBDIR ${LIB_INSTALL_DIR})
+SET(INCLUDEDIR "\${prefix}/include/${PROJECT_NAME}")
+SET(VERSION_MAJOR 1)
+SET(VERSION "${VERSION_MAJOR}.0.0")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(notification-ex REQUIRED
+ glib-2.0
+ bundle
+ dlog
+ capi-appfw-app-control
+ capi-appfw-app-common
+ aul
+ uuid
+)
+
+FOREACH(flag ${notification-ex_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline -std=c++11")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../)
+
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
+ADD_LIBRARY (${PROJECT_NAME} SHARED ${SOURCES})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${notification-ex_LDFLAGS} "-lpthread")
+
+CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
+SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PROJECT_NAME}.pc")
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION include/${PROJECT_NAME}
+ FILES_MATCHING PATTERN "*.h")
diff --git a/notification-ex/abstract_action.cc b/notification-ex/abstract_action.cc
new file mode 100644
index 0000000..e37ee52
--- /dev/null
+++ b/notification-ex/abstract_action.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include "notification-ex/abstract_action.h"
+#include "notification-ex/abstract_action_implementation.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define ABSTRACT_ACTION_TYPE_KEY "__ABSTRACT_ACTION_TYPE_KEY__"
+#define ABSTRACT_ACTION_IS_LOCAL_KEY "__ABSTRACT_ACTION_IS_LOCAL_KEY__"
+#define ABSTRACT_ACTION_EXTRA_KEY "__ABSTRACT_ACTION_EXTRA_KEY__"
+
+namespace notification {
+namespace item {
+AbstractAction::AbstractAction(bool isLocal)
+ : impl_(new Impl(this, isLocal)) {
+}
+
+AbstractAction::AbstractAction(bool isLocal, std::string extra)
+ : impl_(new Impl(this, isLocal, extra)) {
+}
+
+AbstractAction::Impl::Impl(AbstractAction* parent, bool isLocal)
+ : parent_(parent) , isLocal_(isLocal) {
+ LOGI("Action created");
+}
+
+AbstractAction::Impl::Impl(AbstractAction* parent, bool isLocal,
+ std::string extra) : parent_(parent) , isLocal_(isLocal), extra_(extra) {
+ LOGI("Action created");
+}
+
+AbstractAction::~AbstractAction() = default;
+AbstractAction::Impl::~Impl() = default;
+
+int AbstractAction::GetType(Bundle b) {
+ return std::stoi(b.GetString(ABSTRACT_ACTION_TYPE_KEY));
+}
+
+Bundle AbstractAction::Serialize() const {
+ Bundle b;
+
+ b.Add(ABSTRACT_ACTION_TYPE_KEY, std::to_string(GetType()));
+ b.Add(ABSTRACT_ACTION_IS_LOCAL_KEY, std::to_string(impl_->isLocal_));
+ if (!impl_->extra_.empty())
+ b.Add(ABSTRACT_ACTION_EXTRA_KEY ,impl_->extra_);
+ return b;
+}
+
+void AbstractAction::Deserialize(Bundle b) {
+ impl_->isLocal_ = std::stoi(b.GetString(ABSTRACT_ACTION_IS_LOCAL_KEY));
+ impl_->extra_ = b.GetString(ABSTRACT_ACTION_EXTRA_KEY);
+}
+
+bool AbstractAction::IsLocal() const {
+ return impl_->isLocal_;
+}
+
+void AbstractAction::Execute(std::shared_ptr<AbstractItem> item) {
+}
+
+std::string AbstractAction::GetExtra() const {
+ return impl_->extra_;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/abstract_action.h b/notification-ex/abstract_action.h
new file mode 100644
index 0000000..0e001b8
--- /dev/null
+++ b/notification-ex/abstract_action.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ABSTRACT_ACTION_H_
+#define NOTIFICATION_EX_ABSTRACT_ACTION_H_
+
+#include <memory>
+#include <string>
+
+#include "notification-ex/ex_bundle.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+namespace item {
+
+class AbstractItem;
+class EXPORT_API AbstractAction {
+ public:
+ enum Type {
+ NullObject,
+ AppControl,
+ Visibility,
+ Custom = 100
+ };
+
+ public:
+ AbstractAction(bool isLocal);
+ AbstractAction(bool isLocal, std::string extra);
+ virtual ~AbstractAction();
+
+ virtual int GetType() const = 0;
+ static int GetType(Bundle b);
+ virtual Bundle Serialize() const = 0;
+ virtual void Deserialize(Bundle b) = 0;
+ virtual bool IsLocal() const = 0;
+ virtual void Execute(std::shared_ptr<AbstractItem> item) = 0;
+ virtual std::string GetExtra() const = 0;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_ABSTRACT_ACTION_H_
diff --git a/notification-ex/abstract_action_implementation.h b/notification-ex/abstract_action_implementation.h
new file mode 100644
index 0000000..cb60c45
--- /dev/null
+++ b/notification-ex/abstract_action_implementation.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ABSTRACT_ACTION_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_ABSTRACT_ACTION_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+
+#include "notification-ex/abstract_action.h"
+
+namespace notification {
+namespace item {
+
+class AbstractAction::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class AbstractAction;
+ Impl(AbstractAction* parent, bool isLocal);
+ Impl(AbstractAction* parent, bool isLocal, std::string extra);
+
+ private:
+ AbstractAction* parent_;
+
+ bool isLocal_ = true;
+ std::string extra_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_ABSTRACT_ACTION_IMPLEMENTATION_H_
diff --git a/notification-ex/abstract_item.cc b/notification-ex/abstract_item.cc
new file mode 100644
index 0000000..8cc2c7d
--- /dev/null
+++ b/notification-ex/abstract_item.cc
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <uuid/uuid.h>
+#include <unistd.h>
+
+#include <memory>
+#include <algorithm>
+
+#include "notification-ex/exception.h"
+#include "notification-ex/abstract_item.h"
+#include "notification-ex/abstract_item_implementation.h"
+#include "notification-ex/item_info_internal.h"
+#include "notification-ex/ex_util.h"
+#include "notification-ex/action_inflator.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define ABSTRACT_ITEM_TYPE_KEY "__ABSTRACT_ITEM_TYPE_KEY__"
+#define ABSTRACT_ITEM_ID_KEY "__ABSTRACT_ITEM_ID_KEY__"
+#define ABSTRACT_ITEM_UID_KEY "__ABSTRACT_ITEM_UID_KEY__"
+#define ABSTRACT_ITEM_TIME_KEY "__ABSTRACT_ITEM_TIME_KEY__"
+#define ABSTRACT_ITEM_SENDER_APPID_KEY "__ABSTRACT_ITEM_SENDER_APPID_KEY__"
+#define ABSTRACT_ITEM_CHANNEL_KEY "__ABSTRACT_ITEM_CHANNEL_KEY__"
+#define ABSTRACT_ITEM_VERSION_KEY "__ABSTRACT_ITEM_VERSION_KEY__"
+#define ABSTRACT_ITEM_HIDE_TIME_KEY "__ABSTRACT_ITEM_HIDE_TIME_KEY__"
+#define ABSTRACT_ITEM_DELETE_TIME_KEY "__ABSTRACT_ITEM_DELETE_TIME_KEY__"
+#define ABSTRACT_ITEM_CAN_RECEIVE_KEY "__ABSTRACT_ITEM_CAN_RECEIVE_KEY__"
+#define ABSTRACT_ITEM_SOUND_PATH_KEY "__ABSTRACT_ITEM_SOUND_PATH_KEY__"
+#define ABSTRACT_ITEM_VIBRATION_PATH_KEY "__ABSTRACT_ITEM_VIBRATION_PATH_KEY__"
+#define ABSTRACT_ITEM_POLICY_KEY "__ABSTRACT_ITEM_POLICY_KEY__"
+#define ABSTRACT_ITEM_RECEIVER_GROUP_KEY "__ABSTRACT_ITEM_RECEIVER_GROUP_KEY__"
+#define ABSTRACT_ITEM_VISIBLE_KEY "__ABSTRACT_ITEM_VISIBLE_KEY__"
+#define ABSTRACT_ITEM_ENABLE_KEY "__ABSTRACT_ITEM_ENABLE_KEY__"
+#define ABSTRACT_ITEM_STYLE_IS_EXIST_KEY "__ABSTRACT_ITEM_STYLE_IS_EXIST_KEY__"
+#define ABSTRACT_ITEM_STYLE_PADDING_TOP_KEY "__ABSTRACT_ITEM_STYLE_PADDING_TOP_KEY__"
+#define ABSTRACT_ITEM_STYLE_PADDING_LEFT_KEY "__ABSTRACT_ITEM_STYLE_PADDING_LEFT_KEY__"
+#define ABSTRACT_ITEM_STYLE_PADDING_RIGHT_KEY "__ABSTRACT_ITEM_STYLE_PADDING_RIGHT_KEY__"
+#define ABSTRACT_ITEM_STYLE_PADDING_BOTTOM_KEY "__ABSTRACT_ITEM_STYLE_PADDING_BOTTOM_KEY__"
+#define ABSTRACT_ITEM_STYLE_COLOR_A_KEY "__ABSTRACT_ITEM_STYLE_COLOR_A_KEY__"
+#define ABSTRACT_ITEM_STYLE_COLOR_R_KEY "__ABSTRACT_ITEM_STYLE_COLOR_R_KEY__"
+#define ABSTRACT_ITEM_STYLE_COLOR_G_KEY "__ABSTRACT_ITEM_STYLE_COLOR_G_KEY__"
+#define ABSTRACT_ITEM_STYLE_COLOR_B_KEY "__ABSTRACT_ITEM_STYLE_COLOR_B_KEY__"
+#define ABSTRACT_ITEM_STYLE_GEOMETRY_X_KEY "__ABSTRACT_ITEM_STYLE_GEOMETRY_X_KEY__"
+#define ABSTRACT_ITEM_STYLE_GEOMETRY_Y_KEY "__ABSTRACT_ITEM_STYLE_GEOMETRY_Y_KEY__"
+#define ABSTRACT_ITEM_STYLE_GEOMETRY_WIDTH_KEY "__ABSTRACT_ITEM_STYLE_GEOMETRY_WIDTH_KEY__"
+#define ABSTRACT_ITEM_STYLE_GEOMETRY_HEIGHT_KEY "__ABSTRACT_ITEM_STYLE_GEOMETRY_HEIGHT_KEY__"
+#define ABSTRACT_ITEM_LED_ON_PERIOD_KEY "__ABSTRACT_ITEM_LED_ON_PERIOD_KEY__"
+#define ABSTRACT_ITEM_LED_OFF_PERIOD_KEY "__ABSTRACT_ITEM_LED_OFF_PERIOD_KEY__"
+#define ABSTRACT_ITEM_LED_COLOR_A_KEY "__ABSTRACT_ITEM_LED_COLOR_A_KEY__"
+#define ABSTRACT_ITEM_LED_COLOR_R_KEY "__ABSTRACT_ITEM_LED_COLOR_R_KEY__"
+#define ABSTRACT_ITEM_LED_COLOR_G_KEY "__ABSTRACT_ITEM_LED_COLOR_G_KEY__"
+#define ABSTRACT_ITEM_LED_COLOR_B_KEY "__ABSTRACT_ITEM_LED_COLOR_B_KEY__"
+#define ABSTRACT_ITEM_LED_IS_EXIST_KEY "__ABSTRACT_ITEM_LED_IS_EXIST_KEY__"
+#define ABSTRACT_ITEM_ACTION_KEY "__ABSTRACT_ITEM_ACTION_KEY__"
+#define ABSTRACT_ITEM_HIDE_VIEWER_KEY "__ABSTRACT_ITEM_HIDE_VIEWER_KEY__"
+#define ABSTRACT_ITEM_TRUE "TRUE"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+const string ReceiverGroup::Panel = "tizen.org/receiver/panel";
+const string ReceiverGroup::Ticker = "tizen.org/receiver/ticker";
+const string ReceiverGroup::LockScreen = "tizen.org/receiver/lockscreen";
+const string ReceiverGroup::Indicator = "tizen.org/receiver/indicator";
+const string ReceiverGroup::Popup = "tizen.org/receiver/popup";
+
+string AbstractItem::Impl::GenerateItemId() {
+ char uuid[37];
+ uuid_t u;
+ uuid_generate(u);
+ uuid_unparse(u, uuid);
+ string id = util::GetAppId();
+ return string(uuid) + ":" + id;
+}
+
+AbstractItem::AbstractItem(std::shared_ptr<AbstractAction> action)
+ : impl_(new Impl(this, action)) {
+}
+
+AbstractItem::AbstractItem(std::string id,
+ std::shared_ptr<AbstractAction> action)
+ : impl_(new Impl(this, id, action)) {
+}
+
+AbstractItem::Impl::Impl(AbstractItem* parent, string id,
+ std::shared_ptr<AbstractAction> action)
+ : id_(id), action_(action), parent_(parent),
+ info_(std::make_shared<ItemInfo>(this)) {
+ if (id_.empty())
+ id_ = GenerateItemId();
+ sender_appid_ = util::GetAppId();
+ LOGI("AbstractItem created (%s)", id_.c_str());
+}
+
+AbstractItem::Impl::Impl(AbstractItem* parent,
+ std::shared_ptr<AbstractAction> action)
+ : action_(action), parent_(parent),
+ info_(std::make_shared<ItemInfo>(this)) {
+ LOGI("AbstractItem created");
+
+ id_ = GenerateItemId();
+ sender_appid_ = util::GetAppId();
+ LOGI("AbstractItem created (%s)", id_.c_str());
+}
+
+AbstractItem::~AbstractItem() = default;
+
+Bundle AbstractItem::Serialize() const {
+ Bundle b;
+ struct tm* timeinfo;
+ char buf[80] = {0,};
+
+ if (impl_->uid_ == 0)
+ impl_->uid_ = getuid();
+
+ if (!impl_->channel_.empty())
+ b.Add(ABSTRACT_ITEM_CHANNEL_KEY, impl_->channel_);
+
+ b.Add(ABSTRACT_ITEM_ID_KEY, impl_->id_);
+ b.Add(ABSTRACT_ITEM_SENDER_APPID_KEY, GetSenderAppId().c_str());
+ b.Add(ABSTRACT_ITEM_TYPE_KEY, to_string(GetType()));
+ b.Add(ABSTRACT_ITEM_VERSION_KEY, to_string(impl_->version_));
+ b.Add(ABSTRACT_ITEM_HIDE_TIME_KEY, to_string(impl_->hide_time_));
+ b.Add(ABSTRACT_ITEM_DELETE_TIME_KEY, to_string(impl_->delete_time_));
+ b.Add(ABSTRACT_ITEM_UID_KEY, to_string(impl_->uid_));
+
+ timeinfo = localtime(&impl_->time_);
+ strftime (buf, sizeof(buf), "%s", timeinfo);
+ b.Add(ABSTRACT_ITEM_TIME_KEY, string(buf));
+
+ if (!impl_->can_receive_.empty())
+ b.Add(ABSTRACT_ITEM_CAN_RECEIVE_KEY, impl_->can_receive_);
+
+ if (!impl_->sound_path_.empty())
+ b.Add(ABSTRACT_ITEM_SOUND_PATH_KEY, impl_->sound_path_);
+
+ if (!impl_->vibration_path_.empty())
+ b.Add(ABSTRACT_ITEM_VIBRATION_PATH_KEY, impl_->vibration_path_);
+
+ b.Add(ABSTRACT_ITEM_VISIBLE_KEY, to_string((int)impl_->visible_));
+ b.Add(ABSTRACT_ITEM_ENABLE_KEY, to_string((int)impl_->enable_));
+ b.Add(ABSTRACT_ITEM_POLICY_KEY, to_string((int)impl_->policy_));
+
+ if (impl_->receiver_group_list_.size() != 0) {
+ vector<string> arr;
+
+ for (auto& i : impl_->receiver_group_list_) {
+ string receiver = i;
+
+ arr.push_back(receiver);
+ }
+ b.Add(ABSTRACT_ITEM_RECEIVER_GROUP_KEY, arr);
+ }
+
+ if (impl_->style_ != nullptr) {
+ Padding padding = impl_->style_->GetPadding();
+ b.Add(ABSTRACT_ITEM_STYLE_PADDING_LEFT_KEY, to_string(padding.GetLeft()));
+ b.Add(ABSTRACT_ITEM_STYLE_PADDING_TOP_KEY, to_string(padding.GetTop()));
+ b.Add(ABSTRACT_ITEM_STYLE_PADDING_RIGHT_KEY, to_string(padding.GetRight()));
+ b.Add(ABSTRACT_ITEM_STYLE_PADDING_BOTTOM_KEY, to_string(padding.GetBottom()));
+
+ Color color = impl_->style_->GetColor();
+ b.Add(ABSTRACT_ITEM_STYLE_COLOR_A_KEY,
+ to_string(static_cast<int>(color.GetAVal())));
+ b.Add(ABSTRACT_ITEM_STYLE_COLOR_R_KEY,
+ to_string(static_cast<int>(color.GetRVal())));
+ b.Add(ABSTRACT_ITEM_STYLE_COLOR_G_KEY,
+ to_string(static_cast<int>(color.GetGVal())));
+ b.Add(ABSTRACT_ITEM_STYLE_COLOR_B_KEY,
+ to_string(static_cast<int>(color.GetBVal())));
+
+ Geometry geometry = impl_->style_->GetGeometry();
+ b.Add(ABSTRACT_ITEM_STYLE_GEOMETRY_X_KEY, to_string(geometry.GetX()));
+ b.Add(ABSTRACT_ITEM_STYLE_GEOMETRY_Y_KEY, to_string(geometry.GetY()));
+ b.Add(ABSTRACT_ITEM_STYLE_GEOMETRY_WIDTH_KEY, to_string(geometry.GetWidth()));
+ b.Add(ABSTRACT_ITEM_STYLE_GEOMETRY_HEIGHT_KEY, to_string(geometry.GetHeight()));
+
+ b.Add(ABSTRACT_ITEM_STYLE_IS_EXIST_KEY, ABSTRACT_ITEM_TRUE);
+ }
+
+ if (impl_->led_ != nullptr) {
+ b.Add(ABSTRACT_ITEM_LED_ON_PERIOD_KEY, to_string(impl_->led_->GetOnPeriod()));
+ b.Add(ABSTRACT_ITEM_LED_OFF_PERIOD_KEY, to_string(impl_->led_->GetOffPeriod()));
+ b.Add(ABSTRACT_ITEM_LED_COLOR_A_KEY,
+ to_string(static_cast<int>(impl_->led_->GetColor().GetAVal())));
+ b.Add(ABSTRACT_ITEM_LED_COLOR_R_KEY,
+ to_string(static_cast<int>(impl_->led_->GetColor().GetRVal())));
+ b.Add(ABSTRACT_ITEM_LED_COLOR_G_KEY,
+ to_string(static_cast<int>(impl_->led_->GetColor().GetGVal())));
+ b.Add(ABSTRACT_ITEM_LED_COLOR_B_KEY,
+ to_string(static_cast<int>(impl_->led_->GetColor().GetBVal())));
+ b.Add(ABSTRACT_ITEM_LED_IS_EXIST_KEY, ABSTRACT_ITEM_TRUE);
+ }
+
+ if (impl_->action_ != nullptr) {
+ b.Add(ABSTRACT_ITEM_ACTION_KEY,
+ reinterpret_cast<char*>(impl_->action_->Serialize().ToRaw().first.get()));
+ }
+
+ if (impl_->hide_viewer_list_.size() != 0) {
+ vector<string> arr;
+
+ for (auto& i : impl_->hide_viewer_list_) {
+ string viewer = i;
+
+ arr.push_back(viewer);
+ }
+ b.Add(ABSTRACT_ITEM_HIDE_VIEWER_KEY, arr);
+ }
+
+ return b;
+}
+
+void AbstractItem::Deserialize(Bundle b) {
+ string time_s;
+ struct tm timeinfo;
+
+ string type_str = b.GetString(ABSTRACT_ITEM_TYPE_KEY);
+ if (type_str.empty())
+ THROW(NOTIFICATION_ERROR_IO_ERROR);
+
+ impl_->id_ = b.GetString(ABSTRACT_ITEM_ID_KEY);
+ impl_->sender_appid_ = b.GetString(ABSTRACT_ITEM_SENDER_APPID_KEY);
+ impl_->channel_ = b.GetString(ABSTRACT_ITEM_CHANNEL_KEY);
+ impl_->version_ = stoi(b.GetString(ABSTRACT_ITEM_VERSION_KEY));
+ impl_->hide_time_ = stoi(b.GetString(ABSTRACT_ITEM_HIDE_TIME_KEY));
+ impl_->delete_time_ = stoi(b.GetString(ABSTRACT_ITEM_DELETE_TIME_KEY));
+ impl_->can_receive_ = b.GetString(ABSTRACT_ITEM_CAN_RECEIVE_KEY);
+ impl_->sound_path_ = b.GetString(ABSTRACT_ITEM_SOUND_PATH_KEY);
+ impl_->vibration_path_ = b.GetString(ABSTRACT_ITEM_VIBRATION_PATH_KEY);
+ impl_->uid_ = stoi(b.GetString(ABSTRACT_ITEM_UID_KEY));
+
+ time_s = b.GetString(ABSTRACT_ITEM_TIME_KEY);
+ strptime(time_s.c_str(), "%s", &timeinfo);
+ impl_->time_ = mktime(&timeinfo);
+
+ string policy_str = b.GetString(ABSTRACT_ITEM_POLICY_KEY);
+
+ impl_->policy_ = static_cast<Policy>(stoi(policy_str));
+
+ impl_->visible_ = (bool)stoi(b.GetString(ABSTRACT_ITEM_VISIBLE_KEY));
+
+ impl_->enable_ = (bool)stoi(b.GetString(ABSTRACT_ITEM_ENABLE_KEY));
+
+ vector<string> receiver_group = b.GetStringArray(ABSTRACT_ITEM_RECEIVER_GROUP_KEY);
+ if (receiver_group.size() != 0) {
+ for (string str : receiver_group) {
+ impl_->receiver_group_list_.push_back(str);
+ }
+ }
+
+ if (!b.GetString(ABSTRACT_ITEM_STYLE_IS_EXIST_KEY).compare(ABSTRACT_ITEM_TRUE)) {
+ Padding padding(stoi(b.GetString(ABSTRACT_ITEM_STYLE_PADDING_LEFT_KEY)),
+ stoi(b.GetString(ABSTRACT_ITEM_STYLE_PADDING_TOP_KEY)),
+ stoi(b.GetString(ABSTRACT_ITEM_STYLE_PADDING_RIGHT_KEY)),
+ stoi(b.GetString(ABSTRACT_ITEM_STYLE_PADDING_BOTTOM_KEY)));
+
+ Color color(
+ static_cast<unsigned char>(stoi(b.GetString(ABSTRACT_ITEM_STYLE_COLOR_A_KEY))),
+ static_cast<unsigned char>(stoi(b.GetString(ABSTRACT_ITEM_STYLE_COLOR_R_KEY))),
+ static_cast<unsigned char>(stoi(b.GetString(ABSTRACT_ITEM_STYLE_COLOR_G_KEY))),
+ static_cast<unsigned char>(stoi(b.GetString(ABSTRACT_ITEM_STYLE_COLOR_B_KEY))));
+
+ Geometry geometry(stoi(b.GetString(ABSTRACT_ITEM_STYLE_GEOMETRY_X_KEY)),
+ stoi(b.GetString(ABSTRACT_ITEM_STYLE_GEOMETRY_Y_KEY)),
+ stoi(b.GetString(ABSTRACT_ITEM_STYLE_GEOMETRY_WIDTH_KEY)),
+ stoi(b.GetString(ABSTRACT_ITEM_STYLE_GEOMETRY_HEIGHT_KEY)));
+
+ impl_->style_ = make_shared<Style>(color, padding, geometry);
+ }
+
+ if (!b.GetString(ABSTRACT_ITEM_LED_IS_EXIST_KEY).compare(ABSTRACT_ITEM_TRUE)) {
+ Color color(
+ static_cast<unsigned char>(stoi(b.GetString(ABSTRACT_ITEM_LED_COLOR_A_KEY))),
+ static_cast<unsigned char>(stoi(b.GetString(ABSTRACT_ITEM_LED_COLOR_R_KEY))),
+ static_cast<unsigned char>(stoi(b.GetString(ABSTRACT_ITEM_LED_COLOR_G_KEY))),
+ static_cast<unsigned char>(stoi(b.GetString(ABSTRACT_ITEM_LED_COLOR_B_KEY))));
+
+ impl_->led_ = make_shared<LEDInfo>(color);
+ impl_->led_->SetOnPeriod(stoi(b.GetString(ABSTRACT_ITEM_LED_ON_PERIOD_KEY)));
+ impl_->led_->SetOffPeriod(stoi(b.GetString(ABSTRACT_ITEM_LED_OFF_PERIOD_KEY)));
+ }
+
+ string action_str = b.GetString(ABSTRACT_ITEM_ACTION_KEY);
+ if (!action_str.empty())
+ impl_->action_ = ActionInflator::Create(Bundle(action_str));
+
+ vector<string> hide_viewer = b.GetStringArray(ABSTRACT_ITEM_HIDE_VIEWER_KEY);
+ if (hide_viewer.size() != 0) {
+ for (string str : hide_viewer) {
+ impl_->hide_viewer_list_.push_back(str);
+ }
+ }
+}
+
+string AbstractItem::GetId() const {
+ return impl_->id_;
+}
+
+std::list<std::string> AbstractItem::GetSharedPath() const {
+ return {};
+}
+
+shared_ptr<AbstractAction> AbstractItem::GetAction() const {
+ return impl_->action_;
+}
+
+void AbstractItem::SetAction(std::shared_ptr<AbstractAction> action) {
+ impl_->action_ = action;
+}
+
+shared_ptr<Style> AbstractItem::GetStyle() const {
+ return impl_->style_;
+}
+
+void AbstractItem::SetStyle(shared_ptr<Style> style) {
+ impl_->style_ = style;
+}
+
+void AbstractItem::SetLEDInfo(std::shared_ptr<LEDInfo> led) {
+ impl_->led_ = led;
+}
+
+std::shared_ptr<LEDInfo> AbstractItem::GetLEDInfo() const {
+ return impl_->led_;
+}
+
+int AbstractItem::GetType(Bundle b) {
+ string type_str = b.GetString(ABSTRACT_ITEM_TYPE_KEY);
+ if (type_str.empty())
+ THROW(NOTIFICATION_ERROR_IO_ERROR);
+ return strtol(type_str.c_str(), NULL, 10);
+}
+
+void AbstractItem::SetVisible(bool visible) {
+ impl_->visible_ = visible;
+}
+
+bool AbstractItem::GetVisible() const {
+ return impl_->visible_;
+}
+
+void AbstractItem::SetEnable(bool enable) {
+ impl_->enable_ = enable;
+}
+
+bool AbstractItem::GetEnable() const {
+ return impl_->enable_;
+}
+
+void AbstractItem::AddReceiver(std::string receiver_group) {
+ impl_->receiver_group_list_.push_back(receiver_group);
+}
+
+void AbstractItem::RemoveReceiver(std::string receiver_group) {
+ impl_->receiver_group_list_.remove(receiver_group);
+}
+
+list<string> AbstractItem::GetReceiverList() {
+ return impl_->receiver_group_list_;
+}
+
+bool AbstractItem::CanReceive(std::string id) const {
+ if (impl_->receiver_group_list_.size() != 0 && !id.empty()) {
+ list<string>::iterator iter =
+ std::find(impl_->receiver_group_list_.begin(),
+ impl_->receiver_group_list_.end(), id);
+
+ if (iter != impl_->receiver_group_list_.end())
+ return false;
+ }
+
+ if (impl_->hide_viewer_list_.size() == 0)
+ return true;
+
+ string app_id = util::GetAppId();
+ list<string>::iterator iter =
+ std::find(impl_->hide_viewer_list_.begin(),
+ impl_->hide_viewer_list_.end(), app_id);
+
+ if (iter != impl_->hide_viewer_list_.end())
+ return false;
+
+ return true;
+}
+
+void AbstractItem::SetPolicy(int policy) {
+ impl_->policy_ = policy;
+}
+
+int AbstractItem::GetPolicy() const {
+ return impl_->policy_;
+}
+
+std::shared_ptr<IItemInfo> AbstractItem::GetInfo() const {
+ return impl_->info_;
+}
+
+string AbstractItem::GetChannel() const {
+ return impl_->channel_;
+}
+
+void AbstractItem::SetChannel(string channel) {
+ impl_->channel_ = channel;
+}
+
+void AbstractItem::SetSoundPath(std::string path) {
+ impl_->sound_path_ = path;
+}
+
+void AbstractItem::SetVibrationPath(std::string path) {
+ impl_->vibration_path_ = path;
+}
+
+std::string AbstractItem::GetSoundPath() const {
+ return impl_->sound_path_;
+}
+
+std::string AbstractItem::GetVibrationPath() const {
+ return impl_->vibration_path_;
+}
+
+std::string AbstractItem::GetSenderAppId() const {
+ return impl_->sender_appid_;
+}
+
+void AbstractItem::SetSenderAppId(std::string sender_appid) {
+ impl_->sender_appid_ = sender_appid;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/abstract_item.h b/notification-ex/abstract_item.h
new file mode 100644
index 0000000..f1186fd
--- /dev/null
+++ b/notification-ex/abstract_item.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ABSTRACT_ITEM_H_
+#define NOTIFICATION_EX_ABSTRACT_ITEM_H_
+
+#include <time.h>
+
+#include <memory>
+#include <string>
+#include <list>
+
+#include "notification-ex/abstract_action.h"
+#include "notification-ex/ex_bundle.h"
+#include "notification-ex/iitem_info.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+namespace item {
+
+class EXPORT_API ReceiverGroup {
+ public:
+ static const std::string Panel;
+ static const std::string Ticker;
+ static const std::string LockScreen;
+ static const std::string Indicator;
+ static const std::string Popup;
+};
+
+class EXPORT_API Color {
+ public:
+ Color() {
+ a_ = 0;
+ r_ = 0;
+ g_ = 0;
+ b_ = 0;
+ }
+ Color(unsigned char a, unsigned char r, unsigned char g, unsigned char b)
+ : a_(a), r_(r), g_(g), b_(b) {
+ }
+ virtual ~Color() = default;
+
+ unsigned char GetAVal() const {
+ return a_;
+ }
+ unsigned char GetRVal() const {
+ return r_;
+ }
+ unsigned char GetGVal() const {
+ return g_;
+ }
+ unsigned char GetBVal() const {
+ return b_;
+ }
+
+ private:
+ unsigned char a_;
+ unsigned char r_;
+ unsigned char g_;
+ unsigned char b_;
+}; // class Color
+
+class EXPORT_API Padding {
+ public:
+ Padding() {
+ left_ = 0;
+ top_ = 0;
+ right_ = 0;
+ bottom_ = 0;
+ }
+ Padding(int left, int top, int right, int bottom)
+ : left_(left), top_(top), right_(right), bottom_(bottom) {
+ }
+ virtual ~Padding() = default;
+
+ int GetLeft() const {
+ return left_;
+ }
+ int GetTop() const {
+ return top_;
+ }
+ int GetRight() const {
+ return right_;
+ }
+ int GetBottom() const {
+ return bottom_;
+ }
+
+ private:
+ int left_;
+ int top_;
+ int right_;
+ int bottom_;
+}; // class Padding
+
+class EXPORT_API Geometry {
+ public:
+ Geometry() {
+ x_ = 0;
+ y_ = 0;
+ w_ = 0;
+ h_ = 0;
+ }
+ Geometry(int x, int y, int w, int h) : x_(x), y_(y), w_(w), h_(h) {
+ }
+ virtual ~Geometry() = default;
+
+ int GetX() const {
+ return x_;
+ }
+ int GetY() const {
+ return y_;
+ }
+ int GetWidth() const {
+ return w_;
+ }
+ int GetHeight() const {
+ return h_;
+ }
+
+ private:
+ int x_;
+ int y_;
+ int w_;
+ int h_;
+}; // class Geometry
+
+class EXPORT_API Style {
+ public:
+ Style() {
+ }
+ Style(Color color, Padding padding, Geometry geometry)
+ : color_(color), padding_(padding), geometry_(geometry) {
+ }
+ virtual ~Style() = default;
+
+ Padding GetPadding() const {
+ return padding_;
+ }
+ Color GetColor() const {
+ return color_;
+ }
+ Geometry GetGeometry() const {
+ return geometry_;
+ }
+
+ private:
+ Color color_;
+ Padding padding_;
+ Geometry geometry_;
+}; // class Style
+
+class EXPORT_API LEDInfo {
+ public:
+ LEDInfo() {
+ Color(0, 0, 0, 0);
+ }
+ explicit LEDInfo(Color color)
+ : color_(color) {
+ }
+ virtual ~LEDInfo() = default;
+
+ void SetOnPeriod(int ms) {
+ on_period_ = ms;
+ }
+ int GetOnPeriod() const {
+ return on_period_;
+ }
+ void SetOffPeriod(int ms) {
+ off_period_ = ms;
+ }
+ int GetOffPeriod() const {
+ return off_period_;
+ }
+
+ Color GetColor() const {
+ return color_;
+ }
+
+ private:
+ Color color_;
+ int on_period_ = 0;
+ int off_period_ = 0;
+}; // clss LEDInfo
+
+class EXPORT_API AbstractItem {
+ public:
+ enum Type {
+ NullObject,
+ Text,
+ Image,
+ Icon,
+ Button,
+ ChatMessage,
+ CheckBox,
+ IconText,
+ InputSelector,
+ Group,
+ Entry,
+ Progress,
+ Time,
+ Custom = 100
+ };
+
+ enum Policy {
+ None = 0,
+ OnBootClear = 1 << 0,
+ SimMode = 1 << 1,
+ };
+
+ public:
+ AbstractItem(
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ AbstractItem(std::string id,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~AbstractItem() = 0;
+ virtual Bundle Serialize() const = 0;
+ virtual void Deserialize(Bundle b) = 0;
+ virtual AbstractItem& FindByID(std::string id) = 0;
+ virtual int GetType() const = 0;
+ static int GetType(Bundle b);
+ virtual std::list<std::string> GetSharedPath() const;
+ std::string GetId() const;
+ void SetId(std::string id);
+ std::shared_ptr<AbstractAction> GetAction() const;
+ void SetAction(std::shared_ptr<AbstractAction> action);
+ std::shared_ptr<Style> GetStyle() const;
+ void SetStyle(std::shared_ptr<Style> style);
+ void SetVisible(bool visible);
+ bool GetVisible() const;
+ void SetEnable(bool enable);
+ bool GetEnable() const;
+ void AddReceiver(std::string receiver_group);
+ void RemoveReceiver(std::string receiver_group);
+ std::list<std::string> GetReceiverList();
+ bool CanReceive(std::string id) const;
+ void SetPolicy(int policy);
+ int GetPolicy() const;
+ std::string GetChannel() const;
+ void SetChannel(std::string channel);
+ void SetLEDInfo(std::shared_ptr<LEDInfo> led);
+ std::shared_ptr<LEDInfo> GetLEDInfo() const;
+ void SetSoundPath(std::string path);
+ void SetVibrationPath(std::string path);
+ std::string GetSoundPath() const;
+ std::string GetVibrationPath() const;
+ std::shared_ptr<IItemInfo> GetInfo() const;
+ std::string GetSenderAppId() const;
+ void SetSenderAppId(std::string sender_appid);
+ std::string GetTag();
+ void SetTag();
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class AbstractItem
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_ABSTRACT_ITEM_H_
diff --git a/notification-ex/abstract_item_implementation.h b/notification-ex/abstract_item_implementation.h
new file mode 100644
index 0000000..af62938
--- /dev/null
+++ b/notification-ex/abstract_item_implementation.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ABSTRACT_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_ABSTRACT_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class AbstractItem::Impl {
+ public:
+ class ItemInfo;
+ virtual ~Impl() = default;
+
+ private:
+ Impl(AbstractItem* parent);
+ Impl(AbstractItem* parent,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ Impl(AbstractItem* parent, std::string id,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+
+ private:
+ friend class AbstractItem;
+ std::string GenerateItemId();
+ std::string channel_;
+ std::string id_;
+ std::shared_ptr<LEDInfo> led_ = nullptr;
+ int policy_ = None;
+ std::shared_ptr<Style> style_ = nullptr;
+ bool visible_ = true;
+ bool enable_ = true;
+ int version_ = 1;
+ int hide_time_ = 0;
+ int delete_time_ = 0;
+ std::list<std::string> receiver_group_list_;
+ std::string can_receive_;
+ std::shared_ptr<AbstractAction> action_;
+ AbstractItem* parent_;
+ std::string sound_path_;
+ std::string vibration_path_;
+ std::string sender_appid_;
+ std::shared_ptr<IItemInfo> info_;
+ std::list<std::string> hide_viewer_list_;
+ std::string tag_;
+ time_t time_ = 0;
+ int uid_ = 0;
+ int request_id_ = 0;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_ABSTRACT_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/action_inflator.cc b/notification-ex/action_inflator.cc
new file mode 100644
index 0000000..c757e46
--- /dev/null
+++ b/notification-ex/action_inflator.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/action_inflator.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+namespace notification {
+namespace item {
+
+std::shared_ptr<AbstractAction> ActionInflator::Create(Bundle b) {
+ std::shared_ptr<AbstractAction> action =
+ FactoryManager::GetInst().CreateAction(AbstractAction::GetType(b));
+ action.get()->Deserialize(b);
+ return action;
+}
+
+} // namespace item
+} // namespace notification
+
diff --git a/notification-ex/action_inflator.h b/notification-ex/action_inflator.h
new file mode 100644
index 0000000..65329b9
--- /dev/null
+++ b/notification-ex/action_inflator.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ACTION_INFLATOR_H_
+#define NOTIFICATION_EX_ACTION_INFLATOR_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_action.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API ActionInflator {
+ public:
+ static std::shared_ptr<AbstractAction> Create(Bundle b);
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_ACTION_INFLATOR_H_
+
diff --git a/notification-ex/app_control_action.cc b/notification-ex/app_control_action.cc
new file mode 100644
index 0000000..d58c8d7
--- /dev/null
+++ b/notification-ex/app_control_action.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <app_control_internal.h>
+
+#include "notification-ex/app_control_action.h"
+#include "notification-ex/app_control_action_implementation.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define APPCONTROL_ACTION_KEY "__APPCONTROL_ACTION_KEY__"
+
+namespace notification {
+namespace item {
+
+AppControlAction::AppControlAction(app_control_h app_control)
+ : AbstractAction(true), impl_(new Impl(this)) {
+ app_control_h control_;
+ app_control_clone(&control_, app_control);
+ impl_->control_ = control_;
+}
+
+AppControlAction::AppControlAction(app_control_h app_control, std::string extra)
+ : AbstractAction(true, extra), impl_(new Impl(this)) {
+ app_control_h control_;
+ app_control_clone(&control_, app_control);
+ impl_->control_ = control_;
+}
+
+AppControlAction::Impl::Impl(AppControlAction* parent)
+ : parent_(parent) {
+ LOGI("AppControlAction created");
+}
+
+AppControlAction::~AppControlAction() = default;
+AppControlAction::Impl::~Impl() {
+ if (control_)
+ app_control_destroy(control_);
+}
+
+int AppControlAction::GetType() const {
+ return AbstractAction::AppControl;
+}
+
+Bundle AppControlAction::Serialize() const {
+ Bundle b;
+ bundle* control_b = NULL;
+ bundle_raw* control_raw;
+ int len = 0;
+
+ app_control_export_as_bundle(impl_->control_, &control_b);
+ if (control_b == NULL) {
+ LOGE("failed to get bundle from app_control");
+ return nullptr;
+ }
+
+ bundle_encode(control_b, &control_raw, &len);
+ if (len <= 0) {
+ LOGE("bundle encode failed");
+ return nullptr;
+ }
+
+ b = AbstractAction::Serialize();
+ b.Add(APPCONTROL_ACTION_KEY,
+ std::string(reinterpret_cast<const char*>(control_raw)));
+
+ bundle_free(control_b);
+ free(control_raw);
+ return b;
+}
+
+void AppControlAction::Deserialize(Bundle b) {
+ app_control_h app_control = nullptr;
+ bundle* b_ = nullptr;
+ std::string control_str;
+
+ AbstractAction::Deserialize(b);
+
+ control_str = b.GetString(APPCONTROL_ACTION_KEY);
+
+ b_ = bundle_decode((bundle_raw*)control_str.c_str(), control_str.length());
+ if (b_ == nullptr) {
+ LOGE("bundle_decode failed");
+ return;
+ }
+
+ app_control_create(&app_control);
+ if (app_control == nullptr) {
+ LOGE("failed to create app_control");
+ return;
+ }
+
+ app_control_import_from_bundle(app_control, b_);
+ if (app_control == nullptr) {
+ LOGE("failed to make app_control from bundle");
+ return;
+ }
+
+ impl_->control_ = app_control;
+}
+
+bool AppControlAction::IsLocal() const {
+ return AbstractAction::IsLocal();
+}
+
+void AppControlAction::Execute(std::shared_ptr<AbstractItem> item) {
+ app_control_send_launch_request(impl_->control_, NULL, NULL);
+}
+
+std::string AppControlAction::GetExtra() const {
+ return AbstractAction::GetExtra();
+}
+
+void AppControlAction::SetAppControl(app_control_h app_control) {
+ if (impl_->control_ != nullptr)
+ app_control_destroy(impl_->control_);
+
+ app_control_h control_;
+ app_control_clone(&control_, app_control);
+
+ impl_->control_ = control_;
+}
+
+app_control_h AppControlAction::GetAppControl() const {
+ return impl_->control_;
+}
+
+} //namespace item
+} //namespace notification
diff --git a/notification-ex/app_control_action.h b/notification-ex/app_control_action.h
new file mode 100644
index 0000000..875e27f
--- /dev/null
+++ b/notification-ex/app_control_action.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_APP_CONTROL_ACTION_H_
+#define NOTIFICATION_EX_APP_CONTROL_ACTION_H_
+
+#include <app_control.h>
+
+#include "notification-ex/abstract_action.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API AppControlAction : public AbstractAction {
+ public:
+ AppControlAction(app_control_h app_control);
+ AppControlAction(app_control_h app_control, std::string extra);
+ virtual ~AppControlAction();
+
+ int GetType() const override;
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ bool IsLocal() const override;
+ void Execute(std::shared_ptr<AbstractItem> item) override;
+ std::string GetExtra() const override;
+ void SetAppControl(app_control_h app_control);
+ app_control_h GetAppControl() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_APP_CONTROL_ACTION_H_
diff --git a/notification-ex/app_control_action_implementation.h b/notification-ex/app_control_action_implementation.h
new file mode 100644
index 0000000..36c25b5
--- /dev/null
+++ b/notification-ex/app_control_action_implementation.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_APP_CONTROL_ACTION_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_APP_CONTROL_ACTION_IMPLEMENTATION_H_
+
+#include "notification-ex/app_control_action.h"
+
+namespace notification {
+namespace item {
+
+class AppControlAction::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class AppControlAction;
+ Impl(AppControlAction* parent);
+
+ private:
+ AppControlAction* parent_;
+
+ app_control_h control_ = nullptr;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_APP_CONTROL_ACTION_IMPLEMENTATION_H_
+
diff --git a/notification-ex/button_item.cc b/notification-ex/button_item.cc
new file mode 100644
index 0000000..0c862ab
--- /dev/null
+++ b/notification-ex/button_item.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/button_item.h"
+#include "notification-ex/button_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define BUTTON_TITLE_KEY "__BUTTON_TITLE_KEY__"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+ButtonItem::ButtonItem(string title, std::shared_ptr<AbstractAction> action)
+ : AbstractItem(action), impl_(new Impl(this, title)) {
+}
+
+ButtonItem::ButtonItem(string id, string title,
+ std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action), impl_(new Impl(this, title)) {
+}
+
+ButtonItem::~ButtonItem() = default;
+ButtonItem::Impl::~Impl() = default;
+
+ButtonItem::Impl::Impl(ButtonItem* parent, string title)
+ : title_(title), parent_(parent) {
+ LOGI("ButtonItem impl created");
+}
+
+int ButtonItem::GetType() const {
+ return AbstractItem::Button;
+}
+
+Bundle ButtonItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+ b.Add(BUTTON_TITLE_KEY, impl_->title_);
+ return b;
+}
+
+void ButtonItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+ impl_->title_ = b.GetString(BUTTON_TITLE_KEY);
+}
+
+AbstractItem& ButtonItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+std::string ButtonItem::GetTitle() const {
+ return impl_->title_;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/button_item.h b/notification-ex/button_item.h
new file mode 100644
index 0000000..6cfd30d
--- /dev/null
+++ b/notification-ex/button_item.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_BUTTON_ITEM_H_
+#define NOTIFICATION_EX_BUTTON_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API ButtonItem : public AbstractItem {
+ public:
+ ButtonItem(std::string id, std::string title,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ ButtonItem(std::string title,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~ButtonItem();
+
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ int GetType() const override;
+ std::string GetTitle() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class ButtonItem
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_BUTTON_ITEM_H_
diff --git a/notification-ex/button_item_implementation.h b/notification-ex/button_item_implementation.h
new file mode 100644
index 0000000..bab5b46
--- /dev/null
+++ b/notification-ex/button_item_implementation.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_BUTTON_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_BUTTON_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/button_item.h"
+
+namespace notification {
+namespace item {
+
+class ButtonItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ Impl(ButtonItem* parent, std::string title);
+
+ private:
+ friend class ButtonItem;
+
+ std::string title_;
+ ButtonItem* parent_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_BUTTON_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/chat_message_item.cc b/notification-ex/chat_message_item.cc
new file mode 100644
index 0000000..11e5c4f
--- /dev/null
+++ b/notification-ex/chat_message_item.cc
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include "notification-ex/chat_message_item.h"
+#include "notification-ex/chat_message_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define CHATMESSAGE_NAME_KEY "__CHATMESSAGE_NAME_KEY__"
+#define CHATMESSAGE_TEXT_KEY "__CHATMESSAGE_TEXT_KEY__"
+#define CHATMESSAGE_IMAGE_KEY "__CHATMESSAGE_IMAGE_KEY__"
+#define CHATMESSAGE_TIME_KEY "__CHATMESSAGE_TIME_KEY__"
+#define CHATMESSAGE_TYPE_KEY "__CHATMESSAGE_TYPE_KEY__"
+
+namespace notification {
+namespace item {
+
+ChatMessageItem::ChatMessageItem(std::string id,
+ std::shared_ptr<TextItem> name, std::shared_ptr<TextItem> text,
+ std::shared_ptr<ImageItem> image, std::shared_ptr<TimeItem> time,
+ Type type, std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action),
+ impl_(new Impl(this, name, text, image, time, type)) {
+}
+
+ChatMessageItem::Impl::Impl(ChatMessageItem* parent,
+ std::shared_ptr<TextItem> name, std::shared_ptr<TextItem> text,
+ std::shared_ptr<ImageItem> image, std::shared_ptr<TimeItem> time, Type type)
+ : parent_(parent), name_(name), text_(text), image_(image), time_(time),
+ type_(type) {
+ LOGI("ChatMessageItem impl created");
+}
+
+int ChatMessageItem::GetType() const {
+ return AbstractItem::ChatMessage;
+}
+
+std::list<std::string> ChatMessageItem::GetSharedPath() const {
+ std::list<std::string> ret;
+
+ auto name = impl_->name_->GetSharedPath();
+ auto text = impl_->text_->GetSharedPath();
+ auto image = impl_->image_->GetSharedPath();
+ auto time = impl_->time_->GetSharedPath();
+
+ for (auto& i : name) {
+ ret.push_back(std::move(i));
+ }
+
+ for (auto& i : text) {
+ ret.push_back(std::move(i));
+ }
+
+ for (auto& i : image) {
+ ret.push_back(std::move(i));
+ }
+
+ for (auto& i : time) {
+ ret.push_back(std::move(i));
+ }
+
+ return ret;
+}
+
+Bundle ChatMessageItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+
+ b.Add(CHATMESSAGE_NAME_KEY,
+ reinterpret_cast<char*>(impl_->name_->Serialize().ToRaw().first.get()));
+ b.Add(CHATMESSAGE_TEXT_KEY,
+ reinterpret_cast<char*>(impl_->text_->Serialize().ToRaw().first.get()));
+ b.Add(CHATMESSAGE_IMAGE_KEY,
+ reinterpret_cast<char*>(impl_->image_->Serialize().ToRaw().first.get()));
+ b.Add(CHATMESSAGE_TIME_KEY,
+ reinterpret_cast<char*>(impl_->time_->Serialize().ToRaw().first.get()));
+ b.Add(CHATMESSAGE_TYPE_KEY, std::to_string((int)impl_->type_));
+ return b;
+}
+
+void ChatMessageItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+
+ std::shared_ptr<AbstractItem> name =
+ FactoryManager::GetInst().CreateItem(AbstractItem::Text);
+ name.get()->Deserialize(Bundle(b.GetString(CHATMESSAGE_NAME_KEY)));
+ impl_->name_ = std::static_pointer_cast<TextItem>(name);
+
+ std::shared_ptr<AbstractItem> text =
+ FactoryManager::GetInst().CreateItem(AbstractItem::Text);
+ text.get()->Deserialize(Bundle(b.GetString(CHATMESSAGE_TEXT_KEY)));
+ impl_->text_ = std::static_pointer_cast<TextItem>(text);
+
+ std::shared_ptr<AbstractItem> image =
+ FactoryManager::GetInst().CreateItem(AbstractItem::Image);
+ image.get()->Deserialize(Bundle(b.GetString(CHATMESSAGE_IMAGE_KEY)));
+ impl_->image_ = std::static_pointer_cast<ImageItem>(image);
+
+ std::shared_ptr<AbstractItem> time =
+ FactoryManager::GetInst().CreateItem(AbstractItem::Time);
+ time.get()->Deserialize(Bundle(b.GetString(CHATMESSAGE_TIME_KEY)));
+ impl_->time_ = std::static_pointer_cast<TimeItem>(time);
+
+ impl_->type_ = static_cast<Type>(std::stoi(b.GetString(CHATMESSAGE_TYPE_KEY)));
+}
+
+AbstractItem& ChatMessageItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+TextItem& ChatMessageItem::GetNameItem() const {
+ return *(impl_->name_);
+}
+
+TextItem& ChatMessageItem::GetTextItem() const {
+ return *(impl_->text_);
+}
+
+ImageItem& ChatMessageItem::GetImageItem() const {
+ return *(impl_->image_);
+}
+
+TimeItem& ChatMessageItem::GetTimeItem() const {
+ return *(impl_->time_);
+}
+
+ChatMessageItem::Type ChatMessageItem::GetMessageType() const {
+ return impl_->type_;
+}
+
+ChatMessageItem::~ChatMessageItem() = default;
+ChatMessageItem::Impl::~Impl() = default;
+
+} // namespace item
+} // namespace notification_ex
diff --git a/notification-ex/chat_message_item.h b/notification-ex/chat_message_item.h
new file mode 100644
index 0000000..ca4a2aa
--- /dev/null
+++ b/notification-ex/chat_message_item.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_CHAT_MESSAGE_ITEM_H_
+#define NOTIFICATION_EX_CHAT_MESSAGE_ITEM_H_
+
+#include <time.h>
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+#include "notification-ex/text_item.h"
+#include "notification-ex/image_item.h"
+#include "notification-ex/time_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API ChatMessageItem : public AbstractItem {
+ public:
+ enum Type {
+ user,
+ sender,
+ };
+
+ public:
+ ChatMessageItem(std::string id, std::shared_ptr<TextItem> name,
+ std::shared_ptr<TextItem> text, std::shared_ptr<ImageItem> image,
+ std::shared_ptr<TimeItem> time, Type type,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~ChatMessageItem();
+ int GetType() const override;
+
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ std::list<std::string> GetSharedPath() const override;
+ TextItem& GetNameItem() const;
+ TextItem& GetTextItem() const;
+ ImageItem& GetImageItem() const;
+ TimeItem& GetTimeItem() const;
+ Type GetMessageType() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class ChatMessageItem
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_CHAT_MESSAGE_ITEM_H_
diff --git a/notification-ex/chat_message_item_implementation.h b/notification-ex/chat_message_item_implementation.h
new file mode 100644
index 0000000..58084ca
--- /dev/null
+++ b/notification-ex/chat_message_item_implementation.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_CHAT_MESSAGE_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_CHAT_MESSAGE_ITEM_IMPLEMENTATION_H_
+
+#include <time.h>
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/chat_message_item.h"
+
+namespace notification {
+namespace item {
+
+class ChatMessageItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class ChatMessageItem;
+ Impl(ChatMessageItem* parent, std::shared_ptr<TextItem> name,
+ std::shared_ptr<TextItem> text, std::shared_ptr<ImageItem> image,
+ std::shared_ptr<TimeItem> time, Type type);
+
+ private:
+ ChatMessageItem* parent_;
+ std::shared_ptr<TextItem> name_;
+ std::shared_ptr<TextItem> text_;
+ std::shared_ptr<ImageItem> image_;
+ std::shared_ptr<TimeItem> time_;
+ Type type_;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_CHAT_MESSAGE_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/checkbox_item.cc b/notification-ex/checkbox_item.cc
new file mode 100644
index 0000000..ed5e99a
--- /dev/null
+++ b/notification-ex/checkbox_item.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include "notification-ex/checkbox_item.h"
+#include "notification-ex/checkbox_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define CHECKBOX_TITLE_KEY "__CHECKBOX_TITLE_KEY__"
+#define CHECKBOX_CHECKED_KEY "__CHECKBOX_CHECKED_KEY__"
+
+namespace notification {
+namespace item {
+
+CheckBoxItem::CheckBoxItem(std::string id, std::string title, bool checked,
+ std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action), impl_(new Impl(this, title, checked)) {
+}
+
+CheckBoxItem::Impl::Impl(CheckBoxItem* parent, std::string title, bool checked)
+ : parent_(parent), title_(title), checked_(checked) {
+ LOGI("CheckBoxItem impl created");
+}
+
+int CheckBoxItem::GetType() const {
+ return AbstractItem::CheckBox;
+}
+
+Bundle CheckBoxItem::Serialize() const {
+ Bundle b;
+
+ b = AbstractItem::Serialize();
+ b.Add(CHECKBOX_TITLE_KEY, impl_->title_);
+ b.Add(CHECKBOX_CHECKED_KEY, std::to_string(impl_->checked_));
+
+ return b;
+}
+
+void CheckBoxItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+
+ impl_->title_ = b.GetString(CHECKBOX_TITLE_KEY);
+ impl_->checked_ = std::stoi(b.GetString(CHECKBOX_CHECKED_KEY));
+}
+
+AbstractItem& CheckBoxItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+std::string CheckBoxItem::GetTitle(void) const {
+ return impl_->title_;
+}
+
+bool CheckBoxItem::IsChecked(void) const {
+ return impl_->checked_;
+}
+
+CheckBoxItem::~CheckBoxItem() = default;
+CheckBoxItem::Impl::~Impl() = default;
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/checkbox_item.h b/notification-ex/checkbox_item.h
new file mode 100644
index 0000000..c71fdf5
--- /dev/null
+++ b/notification-ex/checkbox_item.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_CHECKBOX_ITEM_H_
+#define NOTIFICATION_EX_CHECKBOX_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API CheckBoxItem : public AbstractItem {
+ public:
+ CheckBoxItem(std::string id, std::string title, bool checked = false,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~CheckBoxItem();
+
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ int GetType() const override;
+ std::string GetTitle() const;
+ bool IsChecked() const;
+
+private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class CheckBoxItem
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_CHECKBOX_ITEM_H_
diff --git a/notification-ex/checkbox_item_implementation.h b/notification-ex/checkbox_item_implementation.h
new file mode 100644
index 0000000..1435fb6
--- /dev/null
+++ b/notification-ex/checkbox_item_implementation.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_CHECKBOX_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_CHECKBOX_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/checkbox_item.h"
+
+namespace notification {
+namespace item {
+
+class CheckBoxItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class CheckBoxItem;
+ Impl(CheckBoxItem* parent, std::string title, bool checked);
+
+ private:
+ CheckBoxItem* parent_;
+ std::string title_;
+ bool checked_;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_CHECKBOX_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/common.h b/notification-ex/common.h
new file mode 100644
index 0000000..4422823
--- /dev/null
+++ b/notification-ex/common.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_COMMON_H_
+#define NOTIFICATION_EX_COMMON_H_
+
+#include <tizen.h>
+
+namespace notification {
+
+enum NotificationError {
+ NOTIFICATION_ERROR_NONE = TIZEN_ERROR_NONE, /**< Success */
+ NOTIFICATION_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ NOTIFICATION_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+ NOTIFICATION_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< I/O error */
+ NOTIFICATION_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+ NOTIFICATION_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Function not implemented (@b Since: @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif) */
+ NOTIFICATION_ERROR_FROM_DB = TIZEN_ERROR_NOTIFICATION | 0x01, /**< Error from DB query */
+ NOTIFICATION_ERROR_ALREADY_EXIST_ID = TIZEN_ERROR_NOTIFICATION | 0x02, /**< Already exist private ID */
+ NOTIFICATION_ERROR_FROM_DBUS = TIZEN_ERROR_NOTIFICATION | 0x03, /**< Error from DBus */
+ NOTIFICATION_ERROR_NOT_EXIST_ID = TIZEN_ERROR_NOTIFICATION | 0x04, /**< Not exist private ID */
+ NOTIFICATION_ERROR_SERVICE_NOT_READY = TIZEN_ERROR_NOTIFICATION | 0x05, /**< No response from notification service */
+ NOTIFICATION_ERROR_MAX_EXCEEDED = TIZEN_ERROR_NOTIFICATION | 0x06, /**< Max notification count exceeded (@b Since: 3.0) */
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_COMMON_H_
+
diff --git a/notification-ex/db_manager.cc b/notification-ex/db_manager.cc
new file mode 100644
index 0000000..10991fe
--- /dev/null
+++ b/notification-ex/db_manager.cc
@@ -0,0 +1,774 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <unistd.h>
+#include <sqlite3.h>
+#include <vconf.h>
+#include <pkgmgr-info.h>
+#include <tzplatform_config.h>
+#include <string.h>
+#include <list>
+#include <map>
+
+#include "notification-ex/common.h"
+#include "notification-ex/db_manager.h"
+#include "notification-ex/item_inflator.h"
+#include "notification-ex/iitem_info_internal.h"
+#include "notification-ex/ex_util.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "NOTIFICATION_EX"
+
+#define CREATE_NOTIFICATION_TABLE \
+ "PRAGMA journal_mode = PERSIST;\n" \
+ "PRAGMA synchronous = FULL;\n" \
+ "PRAGMA foreign_keys = ON;\n" \
+ "CREATE TABLE IF NOT EXISTS noti_ex_list (\n" \
+ " root_id TEXT NOT NULL,\n" \
+ " app_id TEXT NOT NULL,\n" \
+ " uid INTEGER,\n" \
+ " priv_id INTEGER,\n" \
+ " pkg_id TEXT,\n" \
+ " policy INTEGER,\n" \
+ " data TEXT NOT NULL,\n" \
+ " insert_time INTEGER,\n" \
+ " hide_list TEXT,\n" \
+ " PRIMARY KEY (root_id, app_id, uid));\n" \
+ "CREATE TABLE IF NOT EXISTS receiver_list (\n" \
+ " root_id TEXT NOT NULL,\n" \
+ " app_id TEXT NOT NULL,\n" \
+ " uid INTEGER,\n" \
+ " receiver_group TEXT NOT NULL,\n" \
+ " FOREIGN KEY (root_id, app_id, uid)\n" \
+ " REFERENCES noti_ex_list(root_id, app_id, uid) ON DELETE CASCADE);\n"
+
+#define DBPATH tzplatform_mkpath(TZ_SYS_DB, ".notification.db")
+#define NOTI_LIMIT 100
+
+using namespace std;
+using namespace notification::item;
+
+namespace notification {
+
+DBManager::DBManager() = default;
+DBManager::~DBManager() = default;
+
+sqlite3* DBManager::OpenDB() {
+ int ret;
+ sqlite3* db;
+
+ ret = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, nullptr);
+ if (ret != SQLITE_OK) {
+ LOGE("open db(%s) error: %d", DBPATH, ret);
+ return nullptr;
+ }
+
+ return db;
+}
+
+void DBManager::CloseDB(sqlite3* db) {
+ int ret = SQLITE_OK;
+
+ if (db)
+ ret = sqlite3_close_v2(db);
+
+ if (ret != SQLITE_OK)
+ LOGE("close db error");
+}
+
+int DBManager::ExecuteQuery(sqlite3* db, const char* query, int* num_changes) {
+ int ret = NOTIFICATION_ERROR_NONE;
+ sqlite3_stmt *stmt;
+
+ if (db == nullptr || query == nullptr)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ LOGE("Sqlite3 err[%d][%s]", ret, sqlite3_errmsg(db));
+ return NOTIFICATION_ERROR_FROM_DB;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE) {
+ if (num_changes != nullptr)
+ *num_changes = sqlite3_changes(db);
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ /* LCOV_EXCL_START */
+ LOGE("Sqlite err[%d][%s]", ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+int DBManager::ExecuteQuery(const char* query, int* num_changes) {
+ int ret;
+
+ if (query == nullptr)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ sqlite3* db = OpenDB();
+ if (db == nullptr)
+ return NOTIFICATION_ERROR_FROM_DB;
+
+ ret = ExecuteQuery(db, query, num_changes);
+ CloseDB(db);
+
+ return ret;
+}
+
+int DBManager::CheckDBIntegrity(void* user_data, int argc,
+ char** argv, char** notUsed) {
+ bool* is_db_corrupted = static_cast<bool*>(user_data);
+
+ if (std::string(argv[0]).compare("ok")) {
+ LOGE("db integrity result : %s", argv[0]);
+ *is_db_corrupted = true;
+ return -1;
+ }
+
+ LOGI("db integrity result : %s", argv[0]);
+ return 0;
+}
+
+int DBManager::RecoverCorruptedDB(sqlite3* db) {
+ int ret = NOTIFICATION_ERROR_NONE;
+ char* errmsg = nullptr;
+
+ LOGI("DB is corrupted, start to recover corrupted db");
+ if (db)
+ sqlite3_close(db);
+ unlink(DBPATH);
+
+ ret = sqlite3_open_v2(DBPATH, &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr);
+ if (ret != SQLITE_OK) {
+ LOGE("Failed to open db[%d]", ret);
+ unlink(DBPATH);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, nullptr, nullptr, &errmsg);
+ if (ret != SQLITE_OK) {
+ LOGE("Failed to exec query[%d][%s]", ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+out:
+ if (errmsg)
+ sqlite3_free(errmsg);
+
+ return ret;
+}
+
+int DBManager::InitializeDB() {
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ sqlite3* db;
+ char *errmsg = nullptr;
+ bool is_db_corrupted = false;
+
+ sql_ret = sqlite3_open_v2(DBPATH, &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr);
+ if (sql_ret != SQLITE_OK) {
+ LOGE("Failed to open db[%d]", ret);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, nullptr, nullptr, &errmsg);
+ if (sql_ret != SQLITE_OK) {
+ LOGE("Failed to exec sqlite[%d][%s]", ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, NULL);
+ if (sql_ret != SQLITE_OK) {
+ LOGE("Failed to exec sqlite[%d][%s]", ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
+ CheckDBIntegrity, &is_db_corrupted, &errmsg);
+ if (sql_ret != SQLITE_OK || is_db_corrupted) {
+ LOGE("Failed to exec query[%d][%s]", sql_ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+out:
+ if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
+ ret = RecoverCorruptedDB(db);
+ if (errmsg)
+ sqlite3_free(errmsg);
+ if (db)
+ sqlite3_close(db);
+
+ return ret;
+}
+
+void DBManager::InitializeData() {
+ char* query;
+
+ query = sqlite3_mprintf("DELETE FROM noti_ex_list WHERE policy & %d",
+ static_cast<int>(item::AbstractItem::Policy::OnBootClear));
+ if (!query) {
+ LOGE("OOM - sql query");
+ return;
+ }
+
+ ExecuteQuery(query, nullptr);
+ sqlite3_free(query);
+}
+
+void DBManager::CheckLimit(shared_ptr<item::AbstractItem> addedItem, sqlite3* db) {
+ int ret, count;
+ char* query;
+ sqlite3_stmt* stmt = nullptr;
+ sqlite3_stmt* delete_stmt = nullptr;
+ int uid = static_pointer_cast<IItemInfoInternal>(addedItem->GetInfo())->GetUid();
+
+ ret = GetCount(addedItem->GetSenderAppId(), uid, &count);
+ if (ret != NOTIFICATION_ERROR_NONE || count <= NOTI_LIMIT)
+ return;
+
+ query = sqlite3_mprintf("SELECT root_id FROM noti_ex_list WHERE uid = %d"
+ " AND app_id = %Q ORDER BY insert_time ASC",
+ uid, addedItem->GetSenderAppId().c_str());
+ if (query == nullptr) {
+ LOGE("OOM - sql query");
+ return;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, nullptr);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ LOGE("sqlite3_prepare_v2 Failed [%d][%s]", ret, sqlite3_errmsg(db));
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ count -= NOTI_LIMIT;
+
+ sqlite3_free(query);
+ query = sqlite3_mprintf("DELETE FROM noti_ex_list"
+ " WHERE root_id = ? AND app_id = %Q AND uid = %d",
+ addedItem->GetSenderAppId().c_str(), uid);
+ if (query == nullptr) {
+ LOGE("OOM - sql query");
+ return;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &delete_stmt, nullptr);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ LOGE("sqlite3_prepare_v2 Failed [%d][%s]", ret, sqlite3_errmsg(db));
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW && count > 0) {
+ ret = sqlite3_bind_text(delete_stmt, 1,
+ reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)),
+ -1, SQLITE_TRANSIENT);
+ if (ret != SQLITE_OK) {
+ LOGE("sqlite3_bind_int() error: %d(%s)", ret, sqlite3_errmsg(db));
+ goto out;
+ }
+
+ ret = sqlite3_step(delete_stmt);
+ if (ret != SQLITE_DONE) {
+ LOGE("step error: %d(%s)", ret, sqlite3_errmsg(db));
+ goto out;
+ }
+
+ ret = sqlite3_reset(delete_stmt);
+ if (ret != SQLITE_OK) {
+ LOGE("sqlite3_reset() error: %d", ret);
+ goto out;
+ }
+
+ sqlite3_clear_bindings(delete_stmt);
+
+ count--;
+ }
+
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (delete_stmt)
+ sqlite3_finalize(delete_stmt);
+ if (query)
+ sqlite3_free(query);
+}
+
+int DBManager::UpdateReceiverList
+ (shared_ptr<item::AbstractItem> updatedItem, sqlite3* db) {
+ int ret;
+ char* query;
+ int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
+
+ query = sqlite3_mprintf("DELETE FROM receiver_list"
+ " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
+ updatedItem->GetId().c_str(), updatedItem->GetSenderAppId().c_str(),
+ uid);
+ if (!query) {
+ LOGE("OOM - sql query");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = ExecuteQuery(db, query, nullptr);
+ sqlite3_free(query);
+
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ for (auto& i : updatedItem->GetReceiverList()) {
+ query = sqlite3_mprintf("INSERT INTO receiver_list"
+ " (root_id, app_id, uid, receiver_group)"
+ " VALUES (%Q, %Q, %d, %Q)",
+ updatedItem->GetId().c_str(),
+ updatedItem->GetSenderAppId().c_str(),
+ uid,
+ i.c_str());
+
+ if (!query) {
+ LOGE("OOM - sql query");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = ExecuteQuery(db, query, nullptr);
+ sqlite3_free(query);
+
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+ }
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int DBManager::InsertNotification(list<shared_ptr<item::AbstractItem>> addedItem) {
+ int ret, count;
+ char* query;
+ sqlite3* db = OpenDB();
+
+ if (db == nullptr)
+ return NOTIFICATION_ERROR_FROM_DB;
+
+ if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
+ LOGE("begin transaction error : %s", sqlite3_errmsg(db));
+ CloseDB(db);
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ for (auto& i : addedItem) {
+ int uid = static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetUid();
+ ret = GetCount(i->GetId(), i->GetSenderAppId(), uid, &count);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ break;
+
+ if (count > 0) {
+ LOGE("already exist id :[%s] appid[%s]",
+ i->GetId().c_str(), i->GetSenderAppId().c_str());
+ ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+ break;
+ }
+
+ Bundle b = i->Serialize();
+ query = sqlite3_mprintf("INSERT INTO noti_ex_list"
+ " (root_id, app_id, uid, priv_id, pkg_id, policy, data, insert_time)"
+ " VALUES (%Q, %Q, %d, %d, %Q, %d, %Q, %d)",
+ i->GetId().c_str(),
+ i->GetSenderAppId().c_str(),
+ uid,
+ util::GetQuarkFromString(i->GetId() + to_string(uid)),
+ GetPkgId(i->GetSenderAppId(),uid).c_str(),
+ static_cast<int>(i->GetPolicy()),
+ reinterpret_cast<char*>(b.ToRaw().first.get()),
+ static_pointer_cast<IItemInfo>(i->GetInfo())->GetTime());
+
+ if (!query) {
+ LOGE("OOM - sql query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ ret = ExecuteQuery(db, query, nullptr);
+ sqlite3_free(query);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ break;
+
+ ret = UpdateReceiverList(i, db);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ break;
+ }
+
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ CheckLimit(*(addedItem.begin()), db);
+ if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
+ LOGE("end transaction error : %s", sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+ } else {
+ if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
+ LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
+ }
+
+ CloseDB(db);
+ return ret;
+}
+
+map<string, string> DBManager::GetHideMap() {
+ map<string, string> hide_map;
+ char* query;
+ sqlite3_stmt* stmt;
+ sqlite3* db;
+ int ret;
+ string key;
+
+ query = sqlite3_mprintf("SELECT root_id, app_id, uid, hide_list FROM noti_ex_list"
+ " WHERE hide_list IS NOT NULL");
+ if (!query) {
+ LOGE("OOM - sql query");
+ return hide_map;
+ }
+
+ db = OpenDB();
+ if (db == nullptr) {
+ sqlite3_free(query);
+ return hide_map;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
+ if (ret != SQLITE_OK) {
+ LOGE("Failed to sqlite3_prepare [%d][%s]", ret, sqlite3_errmsg(db));
+ CloseDB(db);
+ sqlite3_free(query);
+ return hide_map;
+ }
+ sqlite3_free(query);
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ key = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))) \
+ + string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1))) \
+ + string(to_string(sqlite3_column_int(stmt, 2)));
+ hide_map[key] = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)));
+ }
+
+ sqlite3_finalize(stmt);
+ CloseDB(db);
+ return hide_map;
+}
+
+int DBManager::GetCount(const string& app_id, int uid, int* count) {
+ return GetCount(string(), app_id, uid, count);
+}
+
+int DBManager::GetCount(const string& root_id, const string& app_id,
+ int uid, int* count) {
+ int ret;
+ char* query;
+ sqlite3_stmt *stmt;
+ sqlite3* db;
+
+ if (root_id.empty()) {
+ query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
+ " WHERE app_id = %Q AND uid = %d", app_id.c_str(), uid);
+ } else {
+ query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
+ " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
+ root_id.c_str(), app_id.c_str(), uid);
+ }
+ if (!query) {
+ LOGE("OOM - sql query");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ db = OpenDB();
+ if (db == nullptr) {
+ sqlite3_free(query);
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
+ if (ret != SQLITE_OK) {
+ LOGE("Failed to sqlite3_prepare [%d][%s]", ret, sqlite3_errmsg(db));
+ sqlite3_free(query);
+ CloseDB(db);
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+ sqlite3_free(query);
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ *count = sqlite3_column_int(stmt, 0);
+ else
+ *count = 0;
+
+ sqlite3_finalize(stmt);
+ CloseDB(db);
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int DBManager::UpdateHideList(shared_ptr<item::AbstractItem> updatedItem,
+ const string& hide_list) {
+ int ret;
+ char* query;
+
+ query = sqlite3_mprintf("UPDATE noti_ex_list SET hide_list = %Q"
+ " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
+ hide_list.c_str(), updatedItem->GetId().c_str(),
+ updatedItem->GetSenderAppId().c_str(),
+ static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid());
+ if (!query) {
+ LOGE("OOM - sql query");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = ExecuteQuery(query, nullptr);
+ sqlite3_free(query);
+
+ return ret;
+}
+
+int DBManager::UpdateNotification(shared_ptr<item::AbstractItem> updatedItem) {
+ int count, ret;
+ char* query;
+ int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
+
+ ret = GetCount(updatedItem->GetId(), updatedItem->GetSenderAppId(), uid, &count);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ if (count <= 0)
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+ sqlite3* db = OpenDB();
+ if (db == nullptr)
+ return NOTIFICATION_ERROR_FROM_DB;
+
+ Bundle b = updatedItem->Serialize();
+ query = sqlite3_mprintf("UPDATE noti_ex_list SET"
+ " priv_id = %d, pkg_id = %Q, policy = %d, data = %Q, insert_time = %d"
+ " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
+ util::GetQuarkFromString(updatedItem->GetId() + to_string(uid)),
+ GetPkgId(updatedItem->GetSenderAppId(), uid).c_str(),
+ static_cast<int>(updatedItem->GetPolicy()),
+ reinterpret_cast<char*>(b.ToRaw().first.get()),
+ static_pointer_cast<IItemInfo>(updatedItem->GetInfo())->GetTime(),
+ updatedItem->GetId().c_str(),
+ updatedItem->GetSenderAppId().c_str(),
+ uid);
+
+ if (!query) {
+ LOGE("OOM - sql query");
+ CloseDB(db);
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
+ LOGE("begin transaction error : %s", sqlite3_errmsg(db));
+ sqlite3_free(query);
+ CloseDB(db);
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ ret = ExecuteQuery(db, query, nullptr);
+ sqlite3_free(query);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ ret = UpdateReceiverList(updatedItem, db);
+
+out:
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
+ LOGE("end transaction error : %s", sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+ } else {
+ if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
+ LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
+ }
+
+ CloseDB(db);
+ return ret;
+}
+
+list<shared_ptr<item::AbstractItem>> DBManager::ExecuteGetList(char* query) {
+ sqlite3_stmt *stmt;
+ sqlite3* db;
+ int ret;
+ list<shared_ptr<item::AbstractItem>> item_list;
+
+ if (!query) {
+ LOGE("Invalid parameter");
+ return item_list;
+ }
+
+ db = OpenDB();
+ if (db == nullptr)
+ return item_list;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
+ if (ret != SQLITE_OK) {
+ LOGE("Failed to sqlite3_prepare [%d][%s]", ret, sqlite3_errmsg(db));
+ CloseDB(db);
+ return item_list;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ LOGE("[%s]", sqlite3_column_text(stmt, 0));
+
+ Bundle serialized(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
+ shared_ptr<item::AbstractItem> gen_item = item::ItemInflator::Create(serialized);
+ item_list.emplace_back(gen_item);
+ }
+
+ sqlite3_finalize(stmt);
+ CloseDB(db);
+ return item_list;
+}
+
+list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(string app_id, int uid) {
+ char* query;
+ list<shared_ptr<item::AbstractItem>> item_list;
+
+ query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
+ " WHERE uid = %d AND app_id = %Q ORDER BY insert_time DESC",
+ uid, app_id.c_str());
+ if (!query) {
+ LOGE("OOM - sql query");
+ return item_list;
+ }
+
+ item_list = ExecuteGetList(query);
+ sqlite3_free(query);
+
+ return item_list;
+}
+
+list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList
+ (string app_id, string root_id, int uid) {
+ char* query;
+ list<shared_ptr<item::AbstractItem>> item_list;
+
+ query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
+ " WHERE uid = %d AND app_id = %Q AND root_id = %Q",
+ uid, app_id.c_str(), root_id.c_str());
+
+ if (!query) {
+ LOGE("OOM - sql query");
+ return item_list;
+ }
+
+ item_list = ExecuteGetList(query);
+ sqlite3_free(query);
+
+ return item_list;
+}
+
+list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(int uid) {
+ int ret, sim_mode;
+ char* query;
+ list<shared_ptr<item::AbstractItem>> item_list;
+
+ /* Check current sim status */
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &sim_mode);
+ if (ret < 0) {
+ sim_mode = VCONFKEY_TELEPHONY_SIM_INSERTED;
+ LOGI("vconf_get_int");
+ }
+
+ if (sim_mode == VCONFKEY_TELEPHONY_SIM_INSERTED) {
+ query = sqlite3_mprintf("SELECT data FROM noti_ex_list WHERE uid = %d"
+ " ORDER BY insert_time DESC", uid);
+ } else {
+ query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
+ " WHERE uid = %d AND (policy & %d) != 0 ORDER BY insert_time DESC",
+ uid, static_cast<int>(item::AbstractItem::Policy::SimMode));
+ }
+
+ if (!query) {
+ LOGE("OOM - sql query");
+ return item_list;
+ }
+
+ item_list = ExecuteGetList(query);
+ sqlite3_free(query);
+
+ return item_list;
+}
+
+int DBManager::DeleteNotification(shared_ptr<item::AbstractItem> deletedItem) {
+ int ret;
+ char* query;
+ int uid = static_pointer_cast<IItemInfoInternal>(deletedItem->GetInfo())->GetUid();
+
+ query = sqlite3_mprintf("DELETE FROM noti_ex_list"
+ " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
+ deletedItem->GetId().c_str(), deletedItem->GetSenderAppId().c_str(),
+ uid);
+ if (!query) {
+ LOGE("OOM - sql query");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = ExecuteQuery(query, nullptr);
+ sqlite3_free(query);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ query = sqlite3_mprintf("DELETE FROM receiver_list"
+ " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
+ deletedItem->GetId().c_str(), deletedItem->GetSenderAppId().c_str(),
+ uid);
+ if (!query) {
+ LOGE("OOM - sql query");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = ExecuteQuery(query, nullptr);
+ sqlite3_free(query);
+
+ return ret;
+}
+
+string DBManager::GetPkgId(const string& app_id, int uid) {
+ pkgmgrinfo_pkginfo_h handle;
+ char *buf = nullptr;
+ string pkgid;
+
+ if (pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), uid, &handle) == PMINFO_R_OK) {
+ if (pkgmgrinfo_appinfo_get_pkgid(handle, &buf) == PMINFO_R_OK) {
+ if (buf)
+ pkgid = string(buf);
+ }
+ pkgmgrinfo_appinfo_destroy_appinfo(handle);
+ }
+ return pkgid;
+}
+} // namespace notification
diff --git a/notification-ex/db_manager.h b/notification-ex/db_manager.h
new file mode 100644
index 0000000..23f6346
--- /dev/null
+++ b/notification-ex/db_manager.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_DB_MANAGER_H_
+#define NOTIFICATION_EX_DB_MANAGER_H_
+
+#include <sqlite3.h>
+
+#include <string>
+#include <memory>
+#include <map>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API DBManager {
+ public:
+ static int InitializeDB();
+ static void InitializeData();
+ static int InsertNotification(std::list<std::shared_ptr<item::AbstractItem>> addedItem);
+ static std::map<std::string, std::string> GetHideMap();
+ static int UpdateHideList(std::shared_ptr<item::AbstractItem> updatedItem, const std::string& hide_list);
+ static int UpdateNotification(std::shared_ptr<item::AbstractItem> updatedItem);
+ static int GetCount(const std::string& root_id, const std::string& app_id, int uid, int* count);
+ static int GetCount(const std::string& app_id, int uid, int* count);
+ static int DeleteNotification(std::shared_ptr<item::AbstractItem> deletedItem);
+ static std::list<std::shared_ptr<item::AbstractItem>> GetNotificationList(int uid);
+ static std::list<std::shared_ptr<item::AbstractItem>> GetNotificationList(std::string app_id, int uid);
+ static std::list<std::shared_ptr<item::AbstractItem>> GetNotificationList(std::string app_id, std::string root_id, int uid);
+
+ private:
+ DBManager(); /* LCOV_EXCL_LINE */
+ ~DBManager(); /* LCOV_EXCL_LINE */
+ static sqlite3* OpenDB();
+ static void CloseDB(sqlite3* db);
+ static int CheckDBIntegrity(void* user_data, int argc, char** argv, char** notUsed);
+ static int RecoverCorruptedDB(sqlite3* db);
+ static int ExecuteQuery(const char* query, int* num_changes);
+ static int ExecuteQuery(sqlite3* db, const char* query, int* num_changes);
+ static std::string GetPkgId(const std::string& app_id, int uid);
+ static void CheckLimit(std::shared_ptr<item::AbstractItem> addedItem, sqlite3* db);
+ static int UpdateReceiverList(std::shared_ptr<item::AbstractItem> updatedItem, sqlite3* db);
+ static std::list<std::shared_ptr<item::AbstractItem>> ExecuteGetList(char* query);
+
+};
+} // namespace notification
+
+#endif // NOTIFICATION_EX_DB_MANAGER_H_ \ No newline at end of file
diff --git a/notification-ex/dbus_connection_manager.cc b/notification-ex/dbus_connection_manager.cc
new file mode 100644
index 0000000..2cf9297
--- /dev/null
+++ b/notification-ex/dbus_connection_manager.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <glib.h>
+
+#include "notification-ex/exception.h"
+#include "notification-ex/dbus_connection_manager.h"
+#include "notification-ex/ex_util.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+#define NOTIFICATION_EX_BUS_NAME_PREFIX "org.tizen.notification_ex._"
+#define NOTIFICATION_EX_INTERFACE "org.tizen.notification_ex"
+#define DATA_PROVIDER_MASTER_ID "data-provider-master"
+
+using namespace std;
+namespace notification {
+
+DBusConnectionManager::DBusConnectionManager() = default;
+DBusConnectionManager::~DBusConnectionManager() = default;
+
+DBusConnectionManager& DBusConnectionManager::GetInst() {
+ static DBusConnectionManager w_inst;
+ int ret;
+ if (w_inst.connection_ == nullptr) {
+ ret = w_inst.Init();
+ if (ret != NOTIFICATION_ERROR_NONE)
+ THROW(ret);
+ }
+ return w_inst;
+}
+
+bool DBusConnectionManager::IsDataProviderMaster() const {
+ return is_DPM_;
+}
+
+bool DBusConnectionManager::IsDataProviderMaster(string appid) const {
+ if (appid == DATA_PROVIDER_MASTER_ID)
+ return true;
+ return false;
+}
+
+string DBusConnectionManager::GetDataProviderMasterName() const {
+ return GetBusName(DATA_PROVIDER_MASTER_ID);
+}
+
+string DBusConnectionManager::GetInterfaceName() const {
+ return NOTIFICATION_EX_INTERFACE;
+}
+
+GDBusConnection* DBusConnectionManager::GetConnection() {
+ return connection_;
+}
+
+std::string DBusConnectionManager::GetBusName(string appid) const {
+ if (appid.empty())
+ return "";
+
+ if (IsDataProviderMaster(appid))
+ return string(NOTIFICATION_EX_BUS_NAME_PREFIX) + DATA_PROVIDER_MASTER_ID;
+
+ char* encoded_str = g_compute_checksum_for_string(G_CHECKSUM_MD5,
+ appid.c_str(), -1);
+ if (encoded_str == NULL)
+ return "";
+
+ return string(NOTIFICATION_EX_BUS_NAME_PREFIX) + encoded_str;
+}
+
+int DBusConnectionManager::Init() {
+ GError* error = nullptr;
+ connection_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (connection_ == NULL) {
+ if (error != NULL) {
+ LOGE("Failed to get dbus [%s]", error->message);
+ g_error_free(error);
+ }
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ string appid = util::GetAppId();
+ if (appid.empty())
+ return NOTIFICATION_ERROR_IO_ERROR;
+
+ if (IsDataProviderMaster(appid))
+ is_DPM_ = true;
+
+ string encoded_name = GetBusName(appid);
+ LOGI("own name %s", encoded_name.c_str());
+ int owner_id = g_bus_own_name_on_connection(connection_, encoded_name.c_str(),
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL, NULL, NULL, NULL);
+ if (!owner_id) {
+ g_object_unref(connection_);
+ LOGE("g_bus_own_name_on_connection, error");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+ return NOTIFICATION_ERROR_NONE;
+}
+
+} // namespace notification
diff --git a/notification-ex/dbus_connection_manager.h b/notification-ex/dbus_connection_manager.h
new file mode 100644
index 0000000..9b37f09
--- /dev/null
+++ b/notification-ex/dbus_connection_manager.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_DBUS_MANAGER_H_
+#define NOTIFICATION_EX_DBUS_MANAGER_H_
+
+#include <gio/gio.h>
+
+#include <string>
+
+#include "notification-ex/ex_bundle.h"
+
+namespace notification {
+
+class EXPORT_API DBusConnectionManager {
+ public:
+ static DBusConnectionManager& GetInst();
+ GDBusConnection* GetConnection();
+ bool IsDataProviderMaster(std::string appid) const;
+ std::string GetDataProviderMasterName() const;
+ std::string GetInterfaceName() const;
+ std::string GetBusName(std::string appid) const;
+
+ private:
+ bool IsDataProviderMaster() const;
+ DBusConnectionManager();
+ ~DBusConnectionManager();
+ int Init();
+ GDBusConnection* connection_ = nullptr;
+ bool is_DPM_ = false;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_DBUS_MANAGER_H_
diff --git a/notification-ex/dbus_event_listener.cc b/notification-ex/dbus_event_listener.cc
new file mode 100644
index 0000000..c5f048b
--- /dev/null
+++ b/notification-ex/dbus_event_listener.cc
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <glib.h>
+#include <unistd.h>
+
+#include "notification-ex/dbus_connection_manager.h"
+#include "notification-ex/dbus_event_listener.h"
+#include "notification-ex/dbus_event_listener_implementation.h"
+#include "notification-ex/exception.h"
+#include "notification-ex/ex_util.h"
+#include "notification-ex/event_info_internal.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define MAX_PACKAGE_STR_SIZE 512
+
+using namespace std;
+namespace notification {
+
+DBusEventListener::DBusEventListener(string path)
+ : impl_(new Impl(this, path)) {
+ LOGW("Created (%s)", path.c_str());
+}
+
+DBusEventListener::~DBusEventListener() {
+ LOGW("Destroyed");
+}
+
+DBusEventListener::Impl::~Impl() = default;
+
+DBusEventListener::Impl::Impl(DBusEventListener* parent, string path)
+ : subscribe_id_(0), registration_id_(0), path_(path), parent_(parent) {
+ LOGI("ButtonItem impl created");
+}
+
+void DBusEventListener::Impl::SignalCb(GDBusConnection* connection,
+ const gchar* sender_name,
+ const gchar* object_path,
+ const gchar* interface_name,
+ const gchar* signal_name,
+ GVariant* parameters,
+ void* user_data) {
+ DBusEventListener::Impl* dl = static_cast<DBusEventListener::Impl*>(user_data);
+ char* appid = nullptr;
+ GVariantIter *iter = nullptr;
+ char* event_info_raw = nullptr;
+ g_variant_get(parameters, "(ssa(s))", &appid, &event_info_raw, &iter);
+
+ LOGI("signal callback!! (%s)", appid);
+ string sender_appid = string(appid);
+ string cur_appid = util::GetAppId();
+ if (sender_appid == cur_appid)
+ return;
+ if ((!DBusConnectionManager::GetInst().IsDataProviderMaster(cur_appid)
+ && !DBusConnectionManager::GetInst().IsDataProviderMaster(sender_appid))
+ || (cur_appid == sender_appid))
+ return;
+
+ LOGE("%s : %s", cur_appid.c_str(), sender_appid.c_str());
+
+ char* raw = nullptr;
+ list<Bundle> ret_list;
+ while (g_variant_iter_loop(iter, "(s)", &raw) && raw != nullptr) {
+ Bundle ret(raw);
+ ret_list.emplace_back(ret);
+ }
+
+ Bundle b(event_info_raw);
+ EventInfo info(b);
+ dl->parent_->NotifyObserver(info, ret_list);
+}
+
+void DBusEventListener::Impl::OnMethodCall(
+ GDBusConnection *conn, const gchar *sender, const gchar *object_path,
+ const gchar *iface_name, const gchar *method_name,
+ GVariant *parameters, GDBusMethodInvocation *invocation,
+ gpointer user_data) {
+ LOGI("method_name[%s] sender[%s]", method_name, sender);
+ DBusEventListener::Impl* dl = static_cast<DBusEventListener::Impl*>(user_data);
+ GVariant *reply_body = NULL;
+ if (g_strcmp0(method_name, "Get") == 0) {
+ char* appid = NULL;
+ char* serialized = NULL;
+ g_variant_get(parameters, "(&s&s)", &appid, &serialized);
+
+ Bundle b(serialized);
+ EventInfo info(b);
+ list<Bundle> result = dl->parent_->NotifyObserver(info);
+ GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
+ for (auto& i : result) {
+ g_variant_builder_add(builder, "(s)",
+ reinterpret_cast<char*>(i.ToRaw().first.get()));
+ }
+ reply_body = g_variant_new("(a(s))", builder);
+ g_variant_builder_unref(builder);
+ }
+ g_dbus_method_invocation_return_value(invocation, reply_body);
+}
+
+int DBusEventListener::Impl::RegisterGDBusInterface() {
+ static const GDBusInterfaceVTable interface_vtable = {
+ OnMethodCall,
+ nullptr,
+ nullptr
+ };
+ static gchar introspection_xml[] =
+ " <node>"
+ " <interface name='org.tizen.notification_ex'>"
+ " <method name='Get'>"
+ " <arg type='s' name='appid' direction='in'/>"
+ " <arg type='s' name='serialized' direction='in'/>"
+ " <arg type='a(s)' name='noti_arr' direction='out'/>"
+ " </method>"
+ " </interface>"
+ " </node>";
+ GError *error = NULL;
+ GDBusNodeInfo *introspection_data =
+ g_dbus_node_info_new_for_xml(introspection_xml, &error);
+ if (!introspection_data) {
+ LOGE("g_dbus_node_info_new_for_xml is failed.");
+ if (error != NULL) {
+ LOGE("g_dbus_node_info_new_for_xml err [%s]", error->message);
+ g_error_free(error);
+ }
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ registration_id_ = g_dbus_connection_register_object(
+ DBusConnectionManager::GetInst().GetConnection(),
+ path_.c_str(), introspection_data->interfaces[0],
+ &interface_vtable, this, NULL, NULL);
+ g_dbus_node_info_unref(introspection_data);
+ if (registration_id_ == 0) {
+ LOGE("register object fail");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ LOGI("RegisterGDBusInterface success");
+ return NOTIFICATION_ERROR_NONE;
+}
+
+void DBusEventListener::Impl::UnRegisterGDBusInterface() {
+ g_dbus_connection_unregister_object(
+ DBusConnectionManager::GetInst().GetConnection(),
+ registration_id_);
+}
+
+bool DBusEventListener::Impl::SubscribeSignal() {
+ subscribe_id_ = g_dbus_connection_signal_subscribe(
+ DBusConnectionManager::GetInst().GetConnection(),
+ NULL,
+ DBusConnectionManager::GetInst().GetInterfaceName().c_str(),
+ NULL,
+ path_.c_str(),
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ SignalCb,
+ this,
+ NULL);
+ return subscribe_id_ > 0;
+}
+
+void DBusEventListener::Impl::UnSubscribeSignal() {
+ g_dbus_connection_signal_unsubscribe(
+ DBusConnectionManager::GetInst().GetConnection(), subscribe_id_);
+ subscribe_id_ = 0;
+}
+
+void DBusEventListener::RegisterObserver(IEventObserver* observer) {
+ if (impl_->subscribe_id_ == 0) {
+ impl_->SubscribeSignal();
+ } else {
+ impl_->UnSubscribeSignal();
+ impl_->SubscribeSignal();
+ }
+
+ if (impl_->registration_id_ == 0) {
+ impl_->RegisterGDBusInterface();
+ } else {
+ impl_->UnRegisterGDBusInterface();
+ impl_->RegisterGDBusInterface();
+ }
+ impl_->observer_ = observer;
+}
+
+void DBusEventListener::UnRegisterObserver(IEventObserver* observer) {
+ impl_->UnSubscribeSignal();
+ impl_->observer_ = NULL;
+}
+
+void DBusEventListener::NotifyObserver(
+ const IEventInfo& info, list<Bundle> serialized) {
+ impl_->observer_->OnEvent(info, serialized);
+}
+
+list<Bundle> DBusEventListener::NotifyObserver(const IEventInfo& info) {
+ return impl_->observer_->OnRequest(info);
+}
+
+} // namespace notification
diff --git a/notification-ex/dbus_event_listener.h b/notification-ex/dbus_event_listener.h
new file mode 100644
index 0000000..15b1fde
--- /dev/null
+++ b/notification-ex/dbus_event_listener.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_DBUS_LISTENER_H_
+#define NOTIFICATION_EX_DBUS_LISTENER_H_
+
+#include "notification-ex/event_listener_interface.h"
+
+namespace notification {
+
+class EXPORT_API DBusEventListener : public IEventListener {
+ public:
+ DBusEventListener(std::string path);
+ ~DBusEventListener();
+
+ void RegisterObserver(IEventObserver* observer) override;
+ void UnRegisterObserver(IEventObserver* observer) override;
+ void NotifyObserver(
+ const IEventInfo& info, std::list<Bundle> serialized) override;
+ std::list<Bundle> NotifyObserver(const IEventInfo& info) override;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_DBUS_LISTENER_H_
diff --git a/notification-ex/dbus_event_listener_implementation.h b/notification-ex/dbus_event_listener_implementation.h
new file mode 100644
index 0000000..be2f58b
--- /dev/null
+++ b/notification-ex/dbus_event_listener_implementation.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_DBUS_EVENT_LISTENER_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_DBUS_EVENT_LISTENER_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/dbus_event_listener.h"
+
+namespace notification {
+
+class DBusEventListener::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class DBusEventListener;
+ Impl(DBusEventListener* parent, std::string path);
+
+ private:
+ void UnRegisterGDBusInterface();
+ int RegisterGDBusInterface();
+ static void OnMethodCall(
+ GDBusConnection *conn, const gchar *sender, const gchar *object_path,
+ const gchar *iface_name, const gchar *method_name,
+ GVariant *parameters, GDBusMethodInvocation *invocation,
+ gpointer user_data);
+
+ static GDBusInterfaceVTable InterfaceVtable;
+ static void SignalCb(GDBusConnection* connection,
+ const gchar* sender_name,
+ const gchar* object_path,
+ const gchar* interface_name,
+ const gchar* signal_name,
+ GVariant* parameters,
+ void* user_data);
+ bool SubscribeSignal();
+ void UnSubscribeSignal();
+ IEventObserver* observer_ = nullptr;
+ int subscribe_id_;
+ int registration_id_;
+ std::string path_;
+ DBusEventListener* parent_;
+};
+
+} // namespace notification
+#endif // NOTIFICATION_EX_DBUS_EVENT_LISTENER_IMPLEMENTATION_H_
diff --git a/notification-ex/dbus_sender.cc b/notification-ex/dbus_sender.cc
new file mode 100644
index 0000000..2195235
--- /dev/null
+++ b/notification-ex/dbus_sender.cc
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <glib.h>
+#include <unistd.h>
+
+#include <list>
+
+#include "notification-ex/dbus_connection_manager.h"
+#include "notification-ex/dbus_sender.h"
+#include "notification-ex/dbus_sender_implementation.h"
+#include "notification-ex/event_info_internal.h"
+#include "notification-ex/ex_util.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define MAX_PACKAGE_STR_SIZE 512
+
+using namespace std;
+namespace notification {
+
+DBusSender::DBusSender(string path) : impl_(new Impl(this, path)) {
+ LOGW("Created (%s)", path.c_str());
+}
+
+DBusSender::Impl::~Impl() = default;
+
+DBusSender::Impl::Impl(DBusSender* parent, string path)
+ : path_(path), parent_(parent) {
+ LOGI("ButtonItem impl created");
+}
+
+DBusSender::~DBusSender() {
+ LOGW("Destroyed");
+}
+
+bool DBusSender::Impl::EmitSignal(string bus_name, string signal_name,
+ GVariant* data) {
+ GError* err = NULL;
+ gboolean result = TRUE;
+
+ result = g_dbus_connection_emit_signal(
+ DBusConnectionManager::GetInst().GetConnection(),
+ bus_name.empty() ? NULL : bus_name.c_str(),
+ path_.c_str(),
+ DBusConnectionManager::GetInst().GetInterfaceName().c_str(),
+ signal_name.c_str(), data, &err);
+ if (result == FALSE) {
+ LOGE("g_dbus_connection_emit_signal() is failed");
+ if (err != NULL) {
+ LOGE("g_dbus_connection_emit_signal() err : %s",
+ err->message);
+ g_error_free(err);
+ }
+ } else {
+ LOGI("Successfully emit signal to %s, %s, %s",
+ bus_name.c_str(), path_.c_str(), signal_name.c_str());
+ }
+ return result;
+}
+
+string DBusSender::Impl::GetBusName(string appid, string dest_appid) const {
+ if (!DBusConnectionManager::GetInst().IsDataProviderMaster(appid))
+ return DBusConnectionManager::GetInst().GetDataProviderMasterName();
+
+ return DBusConnectionManager::GetInst().GetBusName(dest_appid);
+}
+
+void DBusSender::Notify(const IEventInfo& info, list<Bundle> serialized,
+ string dest_appid) {
+ string signal_name = EventInfo::GetString(info.GetEventType());
+ string appid = util::GetAppId();
+
+ GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
+ for (auto& i : serialized) {
+ g_variant_builder_add(builder, "(s)",
+ reinterpret_cast<char*>(i.ToRaw().first.get()));
+ }
+
+ GVariant* data = g_variant_new("(ssa(s))",
+ appid.c_str(),
+ reinterpret_cast<char*>(info.Serialize().ToRaw().first.get()), builder);
+ string bus_name = impl_->GetBusName(appid, dest_appid);
+ LOGI("bus name %s, %s", dest_appid.c_str(), bus_name.c_str());
+ impl_->EmitSignal(bus_name, signal_name, data);
+ g_variant_builder_unref(builder);
+}
+
+GDBusMessage* DBusSender::Impl::MethodCall(string appid, string method_name,
+ Bundle serialized) {
+ GError* err = nullptr;
+ GDBusMessage* msg = g_dbus_message_new_method_call(
+ DBusConnectionManager::GetInst().GetDataProviderMasterName().c_str(),
+ path_.c_str(),
+ DBusConnectionManager::GetInst().GetInterfaceName().c_str(),
+ method_name.c_str());
+ if (!msg) {
+ LOGE("Can't allocate new method call");
+ return nullptr;
+ }
+
+ g_dbus_message_set_body(msg,
+ g_variant_new("(ss)",
+ appid.c_str(),
+ reinterpret_cast<char*>(serialized.ToRaw().first.get())
+ )
+ );
+
+ LOGI("send message !! (%s) (%s) (%s)",
+ path_.c_str(), method_name.c_str(), appid.c_str());
+ GDBusMessage* reply = g_dbus_connection_send_message_with_reply_sync(
+ DBusConnectionManager::GetInst().GetConnection(), msg,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
+
+ return reply;
+}
+
+std::list<Bundle> DBusSender::Request(const IEventInfo& info) {
+ string appid = util::GetAppId();
+ string method_name = EventInfo::GetString(info.GetEventType());
+ Bundle serialized = info.Serialize();
+
+ GDBusMessage* reply = impl_->MethodCall(appid, method_name, serialized);
+ GVariant *reply_body = g_dbus_message_get_body(reply);
+
+ GVariantIter *iter = nullptr;
+ list<Bundle> ret_list;
+ g_variant_get(reply_body, "(a(s))", &iter);
+ char* raw = nullptr;
+ while (g_variant_iter_loop(iter, "(s)", &raw) && raw != nullptr) {
+ Bundle ret(raw);
+ ret_list.emplace_back(ret);
+ }
+
+ return ret_list;
+}
+
+} // namespace notification
diff --git a/notification-ex/dbus_sender.h b/notification-ex/dbus_sender.h
new file mode 100644
index 0000000..c6bf298
--- /dev/null
+++ b/notification-ex/dbus_sender.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_DBUS_SENDER_H_
+#define NOTIFICATION_EX_DBUS_SENDER_H_
+
+#include "notification-ex/ex_bundle.h"
+#include "notification-ex/event_sender_interface.h"
+#include "notification-ex/ievent_info.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API DBusSender : public IEventSender {
+ public:
+ DBusSender(std::string path);
+ virtual ~DBusSender();
+ void Notify(const IEventInfo& info, std::list<Bundle> serialized,
+ std::string dest_appid = "") override;
+ std::list<Bundle> Request(const IEventInfo& info) override;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_DBUS_SENDER_H_
diff --git a/notification-ex/dbus_sender_implementation.h b/notification-ex/dbus_sender_implementation.h
new file mode 100644
index 0000000..1ce5e5f
--- /dev/null
+++ b/notification-ex/dbus_sender_implementation.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_DBUS_SENDER_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_DBUS_SENDER_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/dbus_sender.h"
+
+namespace notification {
+
+class DBusSender::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class DBusSender;
+ Impl(DBusSender* parent, std::string path);
+
+ private:
+ std::string GetBusName(
+ std::string appid, std::string dest_appid) const;
+ bool EmitSignal(std::string bus_name, std::string signal_name, GVariant* data);
+ GDBusMessage* MethodCall(std::string appid, std::string method_name, Bundle serialized);
+ std::string path_;
+ DBusSender* parent_;
+};
+
+} // namespace notification
+#endif // NOTIFICATION_EX_DBUS_SENDER_IMPLEMENTATION_H_ \ No newline at end of file
diff --git a/notification-ex/default_action_factory.cc b/notification-ex/default_action_factory.cc
new file mode 100644
index 0000000..89f7689
--- /dev/null
+++ b/notification-ex/default_action_factory.cc
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/app_control_action.h"
+#include "notification-ex/visibility_action.h"
+#include "notification-ex/default_action_factory.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+unique_ptr<AbstractAction> DefaultActionFactory::CreateAction(int type) {
+ switch (type) {
+ case AbstractAction::NullObject :
+ THROW(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ case AbstractAction::AppControl :
+ app_control_h control;
+ app_control_create(&control);
+ return unique_ptr<AbstractAction>(new AppControlAction(control));
+ case AbstractAction::Visibility :
+ return unique_ptr<AbstractAction>(new VisibilityAction());
+ case AbstractAction::Custom :
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/default_action_factory.h b/notification-ex/default_action_factory.h
new file mode 100644
index 0000000..a1ecde5
--- /dev/null
+++ b/notification-ex/default_action_factory.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_DEFAULT_ACTION_FACTORY_H_
+#define NOTIFICATION_EX_DEFAULT_ACTION_FACTORY_H_
+
+#include <memory>
+
+#include "notification-ex/iaction_factory.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API DefaultActionFactory : public IActionFactory {
+ public:
+ virtual ~DefaultActionFactory() = default;
+ std::unique_ptr<AbstractAction> CreateAction(int type) override;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_DEFAULT_ACTION_FACTORY_H_
diff --git a/notification-ex/default_item_factory.cc b/notification-ex/default_item_factory.cc
new file mode 100644
index 0000000..13e43d7
--- /dev/null
+++ b/notification-ex/default_item_factory.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/default_item_factory.h"
+#include "notification-ex/button_item.h"
+#include "notification-ex/group_item.h"
+#include "notification-ex/entry_item.h"
+#include "notification-ex/text_item.h"
+#include "notification-ex/exception.h"
+#include "notification-ex/input_selector_item.h"
+#include "notification-ex/progress_item.h"
+#include "notification-ex/icon_item.h"
+#include "notification-ex/icon_text_item.h"
+#include "notification-ex/image_item.h"
+#include "notification-ex/checkbox_item.h"
+#include "notification-ex/chat_message_item.h"
+#include "notification-ex/time_item.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+unique_ptr<AbstractItem> DefaultItemFactory::CreateItem(int type) {
+ switch (type) {
+ case AbstractItem::NullObject :
+ THROW(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ case AbstractItem::Text :
+ return unique_ptr<AbstractItem>(new TextItem("",""));
+ case AbstractItem::Icon :
+ return unique_ptr<AbstractItem>(new IconItem(""));
+ case AbstractItem::Image :
+ return unique_ptr<AbstractItem>(new ImageItem(""));
+ case AbstractItem::Button :
+ return unique_ptr<AbstractItem>(new ButtonItem(""));
+ case AbstractItem::ChatMessage :
+ return unique_ptr<AbstractItem>(new ChatMessageItem("",
+ nullptr, nullptr, nullptr, nullptr, ChatMessageItem::Type::user));
+ case AbstractItem::CheckBox :
+ return unique_ptr<AbstractItem>(new CheckBoxItem("", ""));
+ case AbstractItem::IconText :
+ return unique_ptr<AbstractItem>(new IconTextItem("", nullptr, nullptr));
+ case AbstractItem::InputSelector :
+ return unique_ptr<AbstractItem>(new InputSelectorItem());
+ case AbstractItem::Group :
+ return unique_ptr<AbstractItem>(new GroupItem());
+ case AbstractItem::Entry :
+ return unique_ptr<AbstractItem>(new EntryItem(""));
+ case AbstractItem::Progress :
+ return unique_ptr<AbstractItem>(new ProgressItem(0.0, 0.0, 0.0));
+ case AbstractItem::Time :
+ return unique_ptr<AbstractItem>(new TimeItem());
+ case AbstractItem::Custom :
+ return unique_ptr<AbstractItem>(new ButtonItem(""));
+ }
+
+ return nullptr;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/default_item_factory.h b/notification-ex/default_item_factory.h
new file mode 100644
index 0000000..a9b0786
--- /dev/null
+++ b/notification-ex/default_item_factory.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_DEFAULT_ITEM_FACTORY_H_
+#define NOTIFICATION_EX_DEFAULT_ITEM_FACTORY_H_
+
+#include <memory>
+
+#include "notification-ex/iitem_factory.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API DefaultItemFactory : public IItemFactory {
+ public:
+ virtual ~DefaultItemFactory() = default;
+ std::unique_ptr<AbstractItem> CreateItem(int type) override;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_DEFAULT_ITEM_FACTORY_H_
diff --git a/notification-ex/entry_item.cc b/notification-ex/entry_item.cc
new file mode 100644
index 0000000..9b0bdc6
--- /dev/null
+++ b/notification-ex/entry_item.cc
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/entry_item.h"
+#include "notification-ex/entry_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define ENTRY_TEXT_KEY "__ENTRY_TEXT_KEY__"
+#define ENTRY_LIMIT_KEY "__ENTRY_LIMIT_KEY__"
+
+namespace notification {
+namespace item {
+
+EntryItem::EntryItem(std::shared_ptr<AbstractAction> action)
+ : AbstractItem(action), impl_(new Impl(this)) {
+}
+
+EntryItem::EntryItem(std::string id, std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action), impl_(new Impl(this)) {
+}
+
+EntryItem::Impl::Impl(EntryItem* parent)
+ : parent_(parent) {
+ LOGI("EntryItem created");
+}
+
+EntryItem::~EntryItem() = default;
+EntryItem::Impl::~Impl() = default;
+
+int EntryItem::GetType() const {
+ return AbstractItem::Entry;
+}
+
+Bundle EntryItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+
+ if (!impl_->text_.empty())
+ b.Add(ENTRY_TEXT_KEY, impl_->text_);
+
+ b.Add(ENTRY_LIMIT_KEY, std::to_string(impl_->limit_));
+
+ return b;
+}
+
+void EntryItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+ impl_->text_ = b.GetString(ENTRY_TEXT_KEY);
+ impl_->limit_ = std::stoi(b.GetString(ENTRY_LIMIT_KEY));
+}
+
+AbstractItem& EntryItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+std::string EntryItem::GetText() const {
+ return impl_->text_;
+}
+
+void EntryItem::SetText(std::string text) {
+ impl_->text_ = text;
+}
+
+int EntryItem::GetTextLimit() const {
+ return impl_->limit_;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/entry_item.h b/notification-ex/entry_item.h
new file mode 100644
index 0000000..e22af08
--- /dev/null
+++ b/notification-ex/entry_item.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ENTRY_ITEM_H_
+#define NOTIFICATION_EX_ENTRY_ITEM_H_
+
+#include <memory>
+#include <string>
+
+#include "notification-ex/abstract_item.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+namespace item {
+
+class EXPORT_API EntryItem : public AbstractItem {
+ public:
+ EntryItem(std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ EntryItem(std::string id,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~EntryItem();
+
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ int GetType() const override;
+ std::string GetText() const;
+ void SetText(std::string text);
+ int GetTextLimit() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class EntryItem
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_ENTRY_ITEM_H_ \ No newline at end of file
diff --git a/notification-ex/entry_item_implementation.h b/notification-ex/entry_item_implementation.h
new file mode 100644
index 0000000..4af69cc
--- /dev/null
+++ b/notification-ex/entry_item_implementation.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ENTRY_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_ENTRY_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+
+#include "notification-ex/entry_item.h"
+
+namespace notification {
+namespace item {
+
+class EntryItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ Impl(EntryItem* parent);
+
+ private:
+ friend class EntryItem;
+
+ EntryItem* parent_;
+ std::string text_;
+ int limit_ = 160;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_ENTRY_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/event_info.cc b/notification-ex/event_info.cc
new file mode 100644
index 0000000..c220603
--- /dev/null
+++ b/notification-ex/event_info.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include "notification-ex/event_info_internal.h"
+#include "notification-ex/event_info_implementation.h"
+#include "notification-ex/ex_util.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define NOTIFICATION_EX_EVENT_TYPE_KEY "__NOTIFICATION_EX_EVENT_TYPE_KEY__"
+#define NOTIFICATION_EX_EVENT_OWNER_KEY "__NOTIFICATION_EX_EVENT_OWNER_KEY__"
+#define NOTIFICATION_EX_EVENT_CHANNEL_KEY "__NOTIFICATION_EX_EVENT_CHANNEL_KEY__"
+#define NOTIFICATION_EX_EVENT_ITEM_ID_KEY "__NOTIFICATION_EX_EVENT_ITEM_ID_KEY__"
+#define NOTIFICATION_EX_EVENT_TAG_KEY "__NOTIFICATION_EX_EVENT_TAG_KEY__"
+#define NOTIFICATION_EX_EVENT_UID_KEY "__NOTIFICATION_EX_EVENT_UID_KEY__"
+#define NOTIFICATION_EX_EVENT_REQUEST_ID_KEY "__NOTIFICATION_EX_EVENT_REQUEST_ID_KEY__"
+#define NOTIFICATION_EX_EVENT_ERROR_KEY "__NOTIFICATION_EX_EVENT_ERROR_KEY__"
+
+using namespace std;
+namespace notification {
+
+EventInfo::EventInfo(int type, std::string owner, std::string channel,
+ std::string item_id, std::string tag)
+ : impl_(new Impl(this, type, owner, channel, item_id, tag)) {
+}
+EventInfo::~EventInfo() = default;
+EventInfo::Impl::~Impl() = default;
+
+EventInfo::Impl::Impl(EventInfo* parent,
+ int type, std::string owner, std::string channel,
+ std::string item_id, std::string tag)
+ : type_(type), owner_(owner), channel_(channel),
+ item_id_(item_id), tag_(tag), parent_(parent) {
+ uid_ = getuid();
+ request_id_ = util::GetRequestId();
+ error_ = NOTIFICATION_ERROR_NONE;
+ LOGI("EventInfo impl created");
+}
+
+EventInfo::EventInfo(Bundle serialized)
+ : impl_(new Impl(this, EventInfo::Post, "", "", "", "")) {
+ string event_str = serialized.GetString(NOTIFICATION_EX_EVENT_TYPE_KEY);
+ impl_->type_ = (int)strtol(event_str.c_str(), NULL, 10);
+ impl_->owner_ = serialized.GetString(NOTIFICATION_EX_EVENT_OWNER_KEY);
+ impl_->channel_ = serialized.GetString(NOTIFICATION_EX_EVENT_CHANNEL_KEY);
+ impl_->item_id_ = serialized.GetString(NOTIFICATION_EX_EVENT_ITEM_ID_KEY);
+ impl_->tag_ = serialized.GetString(NOTIFICATION_EX_EVENT_TAG_KEY);
+ string uid_str = serialized.GetString(NOTIFICATION_EX_EVENT_UID_KEY);
+ impl_->uid_ = (uid_t)strtol(uid_str.c_str(), NULL, 10);
+ string request_id_str =
+ serialized.GetString(NOTIFICATION_EX_EVENT_REQUEST_ID_KEY);
+ impl_->request_id_ = (int)strtol(request_id_str.c_str(), NULL, 10);
+ string error_str =
+ serialized.GetString(NOTIFICATION_EX_EVENT_ERROR_KEY);
+ impl_->error_ = (NotificationError)strtol(error_str.c_str(), NULL, 10);
+}
+
+string EventInfo::GetString(int type) {
+ switch(type) {
+ case Post:
+ return "Post";
+ case Update:
+ return "Update";
+ case Delete:
+ return "Delete";
+ case Get:
+ return "Get";
+ case Error:
+ return "Error";
+ default:
+ return "Custom" + std::to_string(Custom);
+ }
+}
+
+Bundle EventInfo::Serialize() const {
+ Bundle serialized;
+ serialized.Add(NOTIFICATION_EX_EVENT_TYPE_KEY, to_string((int)impl_->type_));
+ serialized.Add(NOTIFICATION_EX_EVENT_OWNER_KEY, impl_->owner_);
+ serialized.Add(NOTIFICATION_EX_EVENT_CHANNEL_KEY, impl_->channel_);
+ serialized.Add(NOTIFICATION_EX_EVENT_ITEM_ID_KEY, impl_->item_id_);
+ serialized.Add(NOTIFICATION_EX_EVENT_TAG_KEY, impl_->tag_);
+ serialized.Add(NOTIFICATION_EX_EVENT_UID_KEY, to_string((int)impl_->uid_));
+ serialized.Add(
+ NOTIFICATION_EX_EVENT_REQUEST_ID_KEY, to_string(impl_->request_id_));
+ serialized.Add(
+ NOTIFICATION_EX_EVENT_ERROR_KEY, to_string(impl_->error_));
+
+ return serialized;
+}
+
+int EventInfo::GetEventType() const {
+ return impl_->type_;
+}
+
+void EventInfo::SetEventType(int type) {
+ impl_->type_ = type;
+}
+
+string EventInfo::GetOwner() const {
+ return impl_->owner_;
+}
+
+string EventInfo::GetChannel() const {
+ return impl_->channel_;
+}
+
+string EventInfo::GetItemId() const {
+ return impl_->item_id_;
+}
+
+string EventInfo::GetTag() const {
+ return impl_->tag_;
+}
+
+uid_t EventInfo::GetUid() const {
+ return impl_->uid_;
+}
+
+void EventInfo::SetUid(uid_t uid) {
+ impl_->uid_ = uid;
+}
+
+int EventInfo::GetRequestId() const {
+ return impl_->request_id_;
+}
+
+NotificationError EventInfo::GetError() const {
+ return impl_->error_;
+}
+
+void EventInfo::SetError(NotificationError error) {
+ impl_->error_ = error;
+}
+
+} // namespace notification
diff --git a/notification-ex/event_info_implementation.h b/notification-ex/event_info_implementation.h
new file mode 100644
index 0000000..d429211
--- /dev/null
+++ b/notification-ex/event_info_implementation.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_EVENT_INFO_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_EVENT_INFO_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include <sys/types.h>
+
+#include "notification-ex/dbus_sender.h"
+#include "notification-ex/ievent_info.h"
+#include "notification-ex/common.h"
+
+namespace notification {
+
+class EventInfo::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class EventInfo;
+ Impl(EventInfo* parent, int type, std::string owner, std::string channel,
+ std::string item_id, std::string tag);
+
+ private:
+ int type_;
+ std::string owner_;
+ std::string channel_;
+ std::string item_id_;
+ std::string tag_;
+ uid_t uid_;
+ int request_id_;
+ NotificationError error_;
+ EventInfo* parent_;
+};
+
+} // namespace notification
+#endif // NOTIFICATION_EX_EVENT_INFO_IMPLEMENTATION_H_ \ No newline at end of file
diff --git a/notification-ex/event_info_internal.h b/notification-ex/event_info_internal.h
new file mode 100644
index 0000000..234c861
--- /dev/null
+++ b/notification-ex/event_info_internal.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_EVENT_INFO_INTERNAL_H_
+#define NOTIFICATION_EX_EVENT_INFO_INTERNAL_H_
+
+#include <string>
+#include <list>
+
+#include "notification-ex/common.h"
+#include "notification-ex/ex_bundle.h"
+#include "notification-ex/ievent_info_internal.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EventInfo : public IEventInfoInternal {
+ public:
+ EventInfo(int type, std::string owner, std::string channel = "",
+ std::string item_id = "", std::string tag = "");
+ EventInfo(Bundle serialized);
+ virtual ~EventInfo();
+ uid_t GetUid() const override;
+ void SetUid(uid_t uid) override;
+ NotificationError GetError() const override;
+ void SetError(NotificationError error) override;
+ int GetEventType() const override;
+ void SetEventType(int type) override;
+ std::string GetOwner() const override;
+ std::string GetChannel() const override;
+ std::string GetItemId() const override;
+ std::string GetTag() const override;
+ int GetRequestId() const override;
+ Bundle Serialize() const override;
+ static std::string GetString(int type);
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_EVENT_INFO_INTERNAL_H_
diff --git a/notification-ex/event_listener_interface.h b/notification-ex/event_listener_interface.h
new file mode 100644
index 0000000..c59908b
--- /dev/null
+++ b/notification-ex/event_listener_interface.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_EVENT_LISTENER_INTERFACE_H_
+#define NOTIFICATION_EX_EVENT_LISTENER_INTERFACE_H_
+
+#include <list>
+
+#include "notification-ex/event_observer_interface.h"
+#include "notification-ex/ievent_info.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API IEventListener {
+ public:
+ virtual ~IEventListener() = default;
+ virtual void RegisterObserver(IEventObserver* observer) = 0;
+ virtual void UnRegisterObserver(IEventObserver* observer) = 0;
+ virtual void NotifyObserver(const IEventInfo& info, std::list<Bundle> serialized) = 0;
+ virtual std::list<Bundle> NotifyObserver(const IEventInfo& info) = 0;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_EVENT_LISTENER_INTERFACE_H_
diff --git a/notification-ex/event_observer_interface.h b/notification-ex/event_observer_interface.h
new file mode 100644
index 0000000..e3192a5
--- /dev/null
+++ b/notification-ex/event_observer_interface.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_OBSERVER_INTERFACE_H_
+#define NOTIFICATION_EX_OBSERVER_INTERFACE_H_
+
+#include <list>
+
+#include "notification-ex/ex_bundle.h"
+#include "notification-ex/ievent_info.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API IEventObserver {
+ public:
+ virtual ~IEventObserver() = default;
+ virtual void OnEvent(const IEventInfo& info, std::list<Bundle> serialized) = 0;
+ virtual std::list<Bundle> OnRequest(const IEventInfo& info) = 0;
+};
+
+} // namespace notification
+
+#endif
diff --git a/notification-ex/event_sender_interface.h b/notification-ex/event_sender_interface.h
new file mode 100644
index 0000000..8b8bb1f
--- /dev/null
+++ b/notification-ex/event_sender_interface.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_EVENT_SENDER_INTERFACE_H_
+#define NOTIFICATION_EX_EVENT_SENDER_INTERFACE_H_
+
+#include <list>
+
+#include "notification-ex/ex_bundle.h"
+#include "notification-ex/ievent_info.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API IEventSender {
+ public:
+ virtual void Notify(const IEventInfo& info, std::list<Bundle> serialized,
+ std::string dest_appid = "") = 0;
+ virtual std::list<Bundle> Request(const IEventInfo &info) = 0;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_EVENT_SENDER_INTERFACE_H_
diff --git a/notification-ex/ex_bundle.h b/notification-ex/ex_bundle.h
new file mode 100644
index 0000000..6587920
--- /dev/null
+++ b/notification-ex/ex_bundle.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_BUNDLE_H_
+#define NOTIFICATION_EX_BUNDLE_H_
+
+#include <bundle.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <cstdio>
+
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+class EXPORT_API Bundle final {
+ public:
+ using BundleRaw =
+ std::pair<std::unique_ptr<bundle_raw, decltype(std::free)*>, int>;
+
+ class KeyInfo final {
+ public:
+ KeyInfo(const bundle_keyval_t* handle, std::string name)
+ : handle_(handle), name_(std::move(name)) {}
+
+ bundle_type GetType() const {
+ return static_cast<bundle_type>(
+ bundle_keyval_get_type(const_cast<bundle_keyval_t*>(handle_)));
+ }
+
+ bool IsArray() const {
+ return bundle_keyval_type_is_array(const_cast<bundle_keyval_t*>(handle_));
+ }
+
+ const std::string& GetName() const {
+ return name_;
+ }
+
+ private:
+ const bundle_keyval_t* handle_;
+ std::string name_;
+ };
+
+ Bundle() {
+ handle_ = bundle_create();
+ }
+
+ Bundle(BundleRaw raw) {
+ handle_ = bundle_decode(raw.first.get(), raw.second);
+ }
+
+
+ Bundle(const std::string& raw) {
+ handle_ = bundle_decode(reinterpret_cast<const bundle_raw*>(raw.c_str()),
+ raw.length());
+ }
+
+ Bundle(bundle* b, bool copy = true, bool own = true)
+ : own_(own), copy_(copy) {
+ if (!copy_)
+ handle_ = b;
+ else
+ handle_ = bundle_dup(b);
+ }
+
+ ~Bundle() {
+ if (handle_ && (own_ || copy_))
+ bundle_free(handle_);
+ }
+
+ Bundle(const Bundle& b) {
+ handle_ = bundle_dup(b.handle_);
+ }
+
+ Bundle& operator = (const Bundle& b) {
+ handle_ = bundle_dup(b.handle_);
+ return *this;
+ }
+
+ Bundle(Bundle&& b) noexcept {
+ handle_ = b.handle_;
+ b.handle_ = nullptr;
+ }
+
+ Bundle& operator = (Bundle&& b) noexcept {
+ handle_ = b.handle_;
+ b.handle_ = nullptr;
+ return *this;
+ }
+
+ std::vector<KeyInfo> GetKeys() {
+ std::vector<KeyInfo> v;
+
+ bundle_foreach(handle_, [](const char *key, const int type,
+ const bundle_keyval_t *kv, void *user_data) {
+ auto* v = static_cast<std::vector<KeyInfo>*>(user_data);
+ v->emplace_back(kv, key);
+ }, &v);
+
+ return v;
+ }
+
+ int Add(const std::string& key, const std::string& val) {
+ return bundle_add_str(handle_, key.c_str(), val.c_str());
+ }
+
+ int Add(const std::string& key, const std::vector<std::string>& val) {
+ std::vector<const char*> v;
+ for (auto& i : val) {
+ v.push_back(i.c_str());
+ }
+
+ return bundle_add_str_array(handle_, key.c_str(), v.data(), v.size());
+ }
+
+ int Add(const std::string& key, const std::vector<unsigned char>& val) {
+ return bundle_add_byte(handle_, key.c_str(), val.data(), val.size());
+ }
+
+ int Merge(Bundle& b) {
+ std::vector<KeyInfo> keys = b.GetKeys();
+ for (auto& k : keys) {
+ int ret;
+ if (k.IsArray())
+ ret = Add(k.GetName(), b.GetStringArray(k.GetName()));
+ else
+ ret = Add(k.GetName(), b.GetString(k.GetName()));
+ if (ret != 0)
+ return ret;
+ }
+ return 0;
+ }
+
+ int Delete(const std::string& key) {
+ return bundle_del(handle_, key.c_str());
+ }
+
+ std::string GetString(const std::string& key) const {
+ char* str = nullptr;
+ bundle_get_str(handle_, key.c_str(), &str);
+
+ if (!str)
+ return "";
+
+ return std::string(str);
+ }
+
+ std::vector<std::string> GetStringArray(const std::string& key) const {
+ std::vector<std::string> v;
+
+ const char** str_array = nullptr;
+ int len = 0;
+
+ str_array = bundle_get_str_array(handle_, key.c_str(), &len);
+
+ for (int i = 0; i < len; i++) {
+ v.emplace_back(str_array[i]);
+ }
+
+ return v;
+ }
+
+ std::vector<unsigned char> GetByte(const std::string& key) const {
+ size_t size;
+ unsigned char* bytes = nullptr;
+ bundle_get_byte(handle_, key.c_str(),
+ reinterpret_cast<void**>(&bytes), &size);
+ return std::vector<unsigned char>(bytes, bytes + size);
+ }
+
+ BundleRaw ToRaw() {
+ bundle_raw* raw = nullptr;
+ int len = 0;
+ bundle_encode(handle_, &raw, &len);
+
+ return BundleRaw(
+ std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free), len);
+ }
+
+ int GetCount() const {
+ return bundle_get_count(handle_);
+ }
+
+ bundle_type GetType(const std::string& key) const {
+ return static_cast<bundle_type>(bundle_get_type(handle_, key.c_str()));
+ }
+
+ bundle* GetHandle() const {
+ return handle_;
+ }
+
+ bundle* Detach() {
+ auto* h = handle_;
+ handle_ = nullptr;
+ return h;
+ }
+
+ private:
+ bundle* handle_;
+ bool own_ = true;
+ bool copy_ = true;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_BUNDLE_H_
diff --git a/notification-ex/ex_util.cc b/notification-ex/ex_util.cc
new file mode 100644
index 0000000..975a6ee
--- /dev/null
+++ b/notification-ex/ex_util.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <aul.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "notification-ex/ex_util.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define MAX_PACKAGE_STR_SIZE 512
+
+using namespace std;
+namespace notification {
+namespace util {
+GQuark GetQuarkFromString(string str) {
+ return g_quark_from_string(str.c_str());
+}
+
+std::string GetQuarkToString(GQuark quark) {
+ return g_quark_to_string(quark);
+}
+
+int GetRequestId() {
+ static int id = 0;
+ g_atomic_int_inc(&id);
+ return id;
+}
+
+string GetAppId() {
+ static string appid = "";
+ char appid_buf[MAX_PACKAGE_STR_SIZE] = {0, };
+
+ if (!appid.empty()) {
+ LOGI("appid(%s)", appid.c_str());
+ return appid;
+ }
+
+ int pid = getpid();
+ int ret = aul_app_get_appid_bypid(pid, appid_buf, sizeof(appid_buf));
+ if (ret == AUL_R_OK) {
+ appid = string(appid_buf);
+ } else {
+ int fd, i;
+ int last_slash_index = 0;
+ char proc_buf[MAX_PACKAGE_STR_SIZE] = { 0, };
+
+ snprintf(proc_buf, sizeof(proc_buf), "/proc/%d/cmdline", pid);
+
+ fd = open(proc_buf, O_RDONLY);
+ if (fd < 0) {
+ LOGE("Fail to get appid (%d)", errno);
+ return "";
+ }
+
+ ret = read(fd, appid_buf, sizeof(appid_buf) - 1);
+ if (ret <= 0) {
+ LOGE("Fail to get appid (%d)", errno);
+ close(fd);
+ return "";
+ }
+ close(fd);
+
+ for (i = 0 ; i < ret ; i++) {
+ if (appid_buf[i] == '/')
+ last_slash_index = i;
+ }
+
+ if (last_slash_index == (ret - 1)) {
+ LOGE("Fail to get appid (%s)", appid_buf);
+ return "";
+ }
+
+ if (last_slash_index == 0)
+ appid = string(appid_buf);
+ else
+ appid = string(&appid_buf[last_slash_index + 1]);
+ }
+
+ LOGI("appid(%s)", appid.c_str());
+ return appid;
+}
+
+} // namespace util
+} // namespace notification
diff --git a/notification-ex/ex_util.h b/notification-ex/ex_util.h
new file mode 100644
index 0000000..958a348
--- /dev/null
+++ b/notification-ex/ex_util.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_EX_UTIL_H_
+#define NOTIFICATION_EX_EX_UTIL_H_
+
+#include <gmodule.h>
+
+#include <string>
+
+namespace notification {
+namespace util {
+ std::string GetAppId();
+ GQuark GetQuarkFromString(std::string str);
+ std::string GetQuarkToString(GQuark quark);
+ int GetRequestId();
+} // namespace util
+} // namespace notification
+
+#endif // NOTIFICATION_EX_EX_UTIL_H_
diff --git a/notification-ex/exception.h b/notification-ex/exception.h
new file mode 100644
index 0000000..4da7af0
--- /dev/null
+++ b/notification-ex/exception.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_EXCEPTION_H_
+#define NOTIFICATION_EX_EXCEPTION_H_
+
+#include <dlog.h>
+
+#include <string>
+#include <exception>
+
+#include "notification-ex/common.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+#define THROW(error_code) throw Exception(error_code, __FILE__, __LINE__)
+
+namespace notification {
+
+class Exception : public std::exception {
+ public:
+ explicit Exception(int error_code, std::string file = __FILE__,
+ int line = __LINE__ ) {
+ error_code_ = error_code;
+ message_ = file.substr(file.find_last_of("/") + 1) + ":"
+ + std::to_string(line) + GetErrorString(error_code);
+ LOGE("%s", message_.c_str());
+ }
+ virtual ~Exception() {}
+ virtual const char *what(void) const noexcept {
+ return message_.c_str();
+ }
+ int GetErrorCode() {
+ return error_code_;
+ }
+
+ private:
+ int error_code_;
+ std::string message_;
+ std::string GetErrorString(int error_code) {
+ switch (error_code) {
+ case NOTIFICATION_ERROR_INVALID_PARAMETER:
+ return ": INVALID_PARAMETER";
+ case NOTIFICATION_ERROR_OUT_OF_MEMORY:
+ return ": OUT_OF_MEMORY";
+ case NOTIFICATION_ERROR_IO_ERROR:
+ return ": IO_ERROR";
+ case NOTIFICATION_ERROR_PERMISSION_DENIED:
+ return ": PERMISSION_DENIED";
+ case NOTIFICATION_ERROR_INVALID_OPERATION:
+ return ": INVALID_OPERATION";
+ case NOTIFICATION_ERROR_FROM_DB:
+ return ": ERROR_FROM_DB";
+ case NOTIFICATION_ERROR_ALREADY_EXIST_ID:
+ return ": ALREADY_EXIST_ID";
+ case NOTIFICATION_ERROR_FROM_DBUS:
+ return ": ERROR_FROM_DBUS";
+ case NOTIFICATION_ERROR_NOT_EXIST_ID:
+ return ": NOT_EXIST_ID";
+ case NOTIFICATION_ERROR_SERVICE_NOT_READY:
+ return ": SERVICE_NOT_READY";
+ case NOTIFICATION_ERROR_MAX_EXCEEDED:
+ return ": MAX_EXCEEDED";
+ default:
+ return "";
+ }
+ }
+}; // class Exception
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_EXCEPTION_H_
diff --git a/notification-ex/factory_manager.cc b/notification-ex/factory_manager.cc
new file mode 100644
index 0000000..10e3118
--- /dev/null
+++ b/notification-ex/factory_manager.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/default_item_factory.h"
+#include "notification-ex/default_action_factory.h"
+#include "notification-ex/null_item.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+FactoryManager& FactoryManager::GetInst() {
+ static FactoryManager manager;
+ return manager;
+}
+
+void FactoryManager::RegisterFactory(std::unique_ptr<IItemFactory> factory) {
+ item_factory_ = std::move(factory);
+}
+
+void FactoryManager::RegisterFactory(std::unique_ptr<IActionFactory> factory) {
+ action_factory_ = std::move(factory);
+}
+
+std::unique_ptr<AbstractItem> FactoryManager::CreateItem(int type) {
+ if (item_factory_.get() == nullptr)
+ item_factory_.reset(new DefaultItemFactory());
+
+ return item_factory_->CreateItem(type);
+}
+
+std::unique_ptr<AbstractAction> FactoryManager::CreateAction(int type) {
+ if (action_factory_.get() == nullptr)
+ action_factory_.reset(new DefaultActionFactory());
+
+ return action_factory_->CreateAction(type);
+}
+
+AbstractItem& FactoryManager::GetNullItem() {
+ static NullItem item;
+ return item;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/factory_manager.h b/notification-ex/factory_manager.h
new file mode 100644
index 0000000..66a356e
--- /dev/null
+++ b/notification-ex/factory_manager.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_FACTORY_MANAGER_H_
+#define NOTIFICATION_EX_FACTORY_MANAGER_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/iitem_factory.h"
+#include "notification-ex/iaction_factory.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API FactoryManager {
+ public:
+ static FactoryManager& GetInst();
+ void RegisterFactory(std::unique_ptr<IItemFactory> factory);
+ void RegisterFactory(std::unique_ptr<IActionFactory> factory);
+ std::unique_ptr<AbstractItem> CreateItem(int type);
+ std::unique_ptr<AbstractAction> CreateAction(int type);
+ AbstractItem& GetNullItem();
+
+ private:
+ FactoryManager() {}
+
+ private:
+ std::unique_ptr<IItemFactory> item_factory_;
+ std::unique_ptr<IActionFactory> action_factory_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_FACTORY_MANAGER_H_
diff --git a/notification-ex/group_item.cc b/notification-ex/group_item.cc
new file mode 100644
index 0000000..4022c73
--- /dev/null
+++ b/notification-ex/group_item.cc
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <app_common.h>
+
+#include <memory>
+#include <vector>
+
+#include "notification-ex/group_item.h"
+#include "notification-ex/group_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define GROUP_CHILDREN_KEY "__GROUP_CHILDREN_KEY__"
+#define GROUP_CHILDREN_TYPE_KEY "__GROUP_CHILDREN_TYPE_KEY__"
+#define GROUP_DIRECTION_KEY "__GROUP_DIRECTION_KEY__"
+#define GROUP_DIRECTION_VERTICAL "VERTICAL"
+#define GROUP_DIRECTION_HORIZONTAL "HORIZONTAL"
+#define GROUP_APP_LABEL_KEY "__GROUP_APP_LABEL_KEY__"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+GroupItem::GroupItem(string id, shared_ptr<AbstractAction> action)
+ : AbstractItem(id), impl_(new Impl(this)) {
+}
+
+GroupItem::GroupItem(shared_ptr<AbstractAction> action)
+ : AbstractItem(), impl_(new Impl(this)) {
+}
+
+GroupItem::Impl::Impl(GroupItem* parent)
+ : parent_(parent) {
+ LOGI("GroupItem created");
+}
+
+GroupItem::~GroupItem() {
+}
+
+int GroupItem::GetType() const {
+ return AbstractItem::Group;
+}
+
+Bundle GroupItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+ b.Add(GROUP_DIRECTION_KEY, impl_->is_vertical_ ?
+ GROUP_DIRECTION_VERTICAL : GROUP_DIRECTION_HORIZONTAL);
+ if (!impl_->app_label_.empty())
+ b.Add(GROUP_APP_LABEL_KEY, impl_->app_label_);
+
+ if (impl_->children_list_.size() == 0)
+ return b;
+
+ vector<std::string> arr;
+ for (auto& i : impl_->children_list_) {
+ Bundle serialized = i.get()->Serialize();
+ serialized.Add(
+ GROUP_CHILDREN_TYPE_KEY, to_string((int)i.get()->GetType()));
+ arr.push_back(reinterpret_cast<char*>(serialized.ToRaw().first.get()));
+ }
+ b.Add(GROUP_CHILDREN_KEY, arr);
+
+ return b;
+}
+
+void GroupItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+ impl_->is_vertical_ =
+ (b.GetString(GROUP_DIRECTION_KEY) == GROUP_DIRECTION_VERTICAL);
+ impl_->app_label_ = b.GetString(GROUP_APP_LABEL_KEY);
+
+ vector<string> str_arr = b.GetStringArray(GROUP_CHILDREN_KEY);
+ if (str_arr.size() == 0)
+ return;
+
+ for (string str : str_arr) {
+ Bundle serialized(str);
+ string type_str = serialized.GetString(GROUP_CHILDREN_TYPE_KEY);
+ AbstractItem::Type child_type =
+ static_cast<AbstractItem::Type>(strtol(type_str.c_str(), NULL, 10));
+ shared_ptr<AbstractItem> child =
+ FactoryManager::GetInst().CreateItem(child_type);
+ child.get()->Deserialize(serialized);
+ AddChild(child);
+ }
+}
+
+AbstractItem& GroupItem::FindByID(std::string id) {
+ for (auto& i : impl_->children_list_) {
+ if (i.get()->GetId() == id)
+ return *i;
+ }
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+list<string> GroupItem::GetSharedPath() const {
+ list<string> ret;
+
+ for (auto& i : impl_->children_list_) {
+ auto s = i->GetSharedPath();
+ for (auto& j : s) {
+ ret.push_back(move(j));
+ }
+ }
+
+ return ret;
+}
+
+void GroupItem::AddChild(shared_ptr<AbstractItem> child) {
+ impl_->children_list_.emplace_back(child);
+}
+
+void GroupItem::RemoveChild(string itemId) {
+ for (auto& i : impl_->children_list_) {
+ if (i.get()->GetId() == itemId) {
+ impl_->children_list_.remove(i);
+ break;
+ }
+ }
+}
+
+list<shared_ptr<AbstractItem>> GroupItem::GetChildren() {
+ return impl_->children_list_;
+}
+
+void GroupItem::SetDirection(bool vertical) {
+ impl_->is_vertical_ = vertical;
+}
+
+bool GroupItem::IsVertical() {
+ return impl_->is_vertical_;
+}
+
+string GroupItem::GetAppLabel() {
+ if (impl_->app_label_.empty()) {
+ char* name;
+ int ret = app_get_name(&name);
+ if (ret != APP_ERROR_NONE)
+ THROW(NOTIFICATION_ERROR_IO_ERROR);
+ impl_->app_label_ = string(name);
+ }
+ return impl_->app_label_;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/group_item.h b/notification-ex/group_item.h
new file mode 100644
index 0000000..5702376
--- /dev/null
+++ b/notification-ex/group_item.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_GROUP_ITEM_H_
+#define NOTIFICATION_EX_GROUP_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API GroupItem : public AbstractItem {
+ public:
+ GroupItem(std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ GroupItem(std::string id,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~GroupItem();
+
+ public:
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ int GetType() const override;
+ std::list<std::string> GetSharedPath() const override;
+
+ void SetDirection(bool vertical);
+ bool IsVertical();
+ std::string GetAppLabel();
+ void AddChild(std::shared_ptr<AbstractItem> child);
+ void RemoveChild(std::string itemId);
+ std::list<std::shared_ptr<AbstractItem>> GetChildren();
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_GROUP_ITEM_H_
diff --git a/notification-ex/group_item_implementation.h b/notification-ex/group_item_implementation.h
new file mode 100644
index 0000000..df83034
--- /dev/null
+++ b/notification-ex/group_item_implementation.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_GROUP_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_GROUP_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/group_item.h"
+
+namespace notification {
+namespace item {
+
+class GroupItem::Impl {
+ public:
+ virtual ~Impl() = default;
+
+ private:
+ Impl(GroupItem* parent);
+
+ private:
+ friend class GroupItem;
+
+ std::list<std::shared_ptr<AbstractItem>> children_list_;
+ bool is_vertical_ = true;
+ std::string app_label_;
+ GroupItem* parent_;
+
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_GROUP_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/iaction_factory.h b/notification-ex/iaction_factory.h
new file mode 100644
index 0000000..fd03ab8
--- /dev/null
+++ b/notification-ex/iaction_factory.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_IACTION_FACTORY_H_
+#define NOTIFICATION_EX_IACTION_FACTORY_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_action.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API IActionFactory {
+ public:
+ virtual ~IActionFactory() = default;
+ virtual std::unique_ptr<AbstractAction> CreateAction(int type) = 0;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_IACTION_FACTORY_H_
diff --git a/notification-ex/icon_item.cc b/notification-ex/icon_item.cc
new file mode 100644
index 0000000..bee8104
--- /dev/null
+++ b/notification-ex/icon_item.cc
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include "notification-ex/icon_item.h"
+#include "notification-ex/icon_item_implementation.h"
+#include "notification-ex/abstract_item.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+namespace notification {
+namespace item {
+
+IconItem::IconItem(std::string iconPath, std::shared_ptr<AbstractAction> action)
+ : ImageItem(iconPath, action) , impl_(new Impl(this, iconPath)) {
+}
+
+IconItem::IconItem(std::string id, std::string iconPath,
+ std::shared_ptr<AbstractAction> action)
+ : ImageItem(id, iconPath, action), impl_(new Impl(this, iconPath)) {
+}
+
+IconItem::Impl::Impl(IconItem* parent, std::string iconPath)
+ : parent_(parent), iconPath_(iconPath) {
+ LOGI("IconItem impl created");
+}
+
+IconItem::~IconItem() = default;
+IconItem::Impl::~Impl() = default;
+
+int IconItem::GetType() const {
+ return AbstractItem::Icon;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/icon_item.h b/notification-ex/icon_item.h
new file mode 100644
index 0000000..35e9c56
--- /dev/null
+++ b/notification-ex/icon_item.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ICON_ITEM_H_
+#define NOTIFICATION_EX_ICON_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/image_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API IconItem : public ImageItem {
+ public:
+ IconItem(std::string iconPath,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ IconItem(std::string id, std::string iconPath,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~IconItem();
+ int GetType() const override;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class IconItem
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_ICON_ITEM_H_
diff --git a/notification-ex/icon_item_implementation.h b/notification-ex/icon_item_implementation.h
new file mode 100644
index 0000000..4da0f01
--- /dev/null
+++ b/notification-ex/icon_item_implementation.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ICON_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_ICON_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/icon_item.h"
+
+namespace notification {
+namespace item {
+
+class IconItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class IconItem;
+ Impl(IconItem* parent, std::string iconPath);
+
+ private:
+ IconItem* parent_;
+ std::string iconPath_;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_ICON_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/icon_text_item.cc b/notification-ex/icon_text_item.cc
new file mode 100644
index 0000000..813a230
--- /dev/null
+++ b/notification-ex/icon_text_item.cc
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include "notification-ex/icon_text_item.h"
+#include "notification-ex/icon_text_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define ICONTEXT_PATH_KEY "__ICONTEXT_PATH_KEY__"
+#define ICONTEXT_TITLE_KEY "__ICONTEXT_TITLE_KEY__"
+
+namespace notification {
+namespace item {
+
+IconTextItem::IconTextItem(std::string id, std::shared_ptr<IconItem> icon,
+ std::shared_ptr<TextItem> text, std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action), impl_(new Impl(this, icon, text)) {
+}
+
+IconTextItem::Impl::Impl(IconTextItem* parent, std::shared_ptr<IconItem> icon,
+ std::shared_ptr<TextItem> text)
+ : parent_(parent), icon_(icon), text_(text) {
+ LOGI("IconTextItem impl created");
+}
+
+int IconTextItem::GetType() const {
+ return AbstractItem::IconText;
+}
+
+Bundle IconTextItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+
+ b.Add(ICONTEXT_PATH_KEY,
+ reinterpret_cast<char*>(impl_->icon_->Serialize().ToRaw().first.get()));
+ b.Add(ICONTEXT_TITLE_KEY,
+ reinterpret_cast<char*>(impl_->text_->Serialize().ToRaw().first.get()));
+ return b;
+}
+
+void IconTextItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+
+ std::shared_ptr<AbstractItem> icon =
+ FactoryManager::GetInst().CreateItem(AbstractItem::Icon);
+ icon.get()->Deserialize(Bundle(b.GetString(ICONTEXT_PATH_KEY)));
+ impl_->icon_ = std::static_pointer_cast<IconItem>(icon);
+
+ std::shared_ptr<AbstractItem> text =
+ FactoryManager::GetInst().CreateItem(AbstractItem::Text);
+ text.get()->Deserialize(Bundle(b.GetString(ICONTEXT_TITLE_KEY)));
+ impl_->text_ = std::static_pointer_cast<TextItem>(text);
+}
+
+AbstractItem& IconTextItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+IconItem& IconTextItem::GetIconItem() const {
+ return *(impl_->icon_);
+}
+
+TextItem& IconTextItem::GetTextItem() const {
+ return *(impl_->text_);
+}
+
+IconTextItem::~IconTextItem() = default;
+IconTextItem::Impl::~Impl() = default;
+
+} // namespace item
+} // namespace notification_ex
diff --git a/notification-ex/icon_text_item.h b/notification-ex/icon_text_item.h
new file mode 100644
index 0000000..9a3330e
--- /dev/null
+++ b/notification-ex/icon_text_item.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ICON_TEXT_ITEM_H_
+#define NOTIFICATION_EX_ICON_TEXT_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+#include "notification-ex/icon_item.h"
+#include "notification-ex/text_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API IconTextItem : public AbstractItem {
+ public:
+ IconTextItem(std::string id, std::shared_ptr<IconItem> icon,
+ std::shared_ptr<TextItem> text,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+
+ virtual ~IconTextItem();
+
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ int GetType() const override;
+
+ IconItem& GetIconItem() const;
+ TextItem& GetTextItem() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class IconTextItem
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_ICON_TEXT_ITEM_H_
diff --git a/notification-ex/icon_text_item_implementation.h b/notification-ex/icon_text_item_implementation.h
new file mode 100644
index 0000000..7c74512
--- /dev/null
+++ b/notification-ex/icon_text_item_implementation.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ICON_TEXT_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_ICON_TEXT_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/icon_text_item.h"
+
+namespace notification {
+namespace item {
+
+class IconTextItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class IconTextItem;
+ Impl(IconTextItem* parent, std::shared_ptr<IconItem> icon,
+ std::shared_ptr<TextItem> text);
+
+ private:
+ IconTextItem* parent_;
+ std::shared_ptr<IconItem> icon_;
+ std::shared_ptr<TextItem> text_;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_ICON_TEXT_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/ievent_info.h b/notification-ex/ievent_info.h
new file mode 100644
index 0000000..57eddb0
--- /dev/null
+++ b/notification-ex/ievent_info.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_IEVENT_INFO_H_
+#define NOTIFICATION_EX_IEVENT_INFO_H_
+
+#include "notification-ex/ex_bundle.h"
+
+namespace notification {
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+class EXPORT_API IEventInfo {
+ public:
+ enum EventType {
+ Post,
+ Update,
+ Delete,
+ Get,
+ Error,
+ Custom = 100
+ };
+ virtual ~IEventInfo() = default;
+ virtual int GetEventType() const = 0;
+ virtual std::string GetOwner() const = 0;
+ virtual std::string GetChannel() const = 0;
+ virtual std::string GetItemId() const = 0;
+ virtual std::string GetTag() const = 0;
+ virtual int GetRequestId() const = 0;
+ virtual Bundle Serialize() const = 0;
+};
+
+} // namespace notification
+#endif // NOTIFICATION_EX_IEVENT_INFO_H_
diff --git a/notification-ex/ievent_info_internal.h b/notification-ex/ievent_info_internal.h
new file mode 100644
index 0000000..d5ef3a6
--- /dev/null
+++ b/notification-ex/ievent_info_internal.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_IEVENT_INFO_INTERNAL_H_
+#define NOTIFICATION_EX_IEVENT_INFO_INTERNAL_H_
+
+#include "notification-ex/common.h"
+#include "notification-ex/ievent_info.h"
+
+namespace notification {
+
+class IEventInfoInternal : public IEventInfo {
+ public:
+ virtual ~IEventInfoInternal() = default;
+ virtual uid_t GetUid() const = 0;
+ virtual void SetUid(uid_t uid) = 0;
+ virtual NotificationError GetError() const = 0;
+ virtual void SetError(NotificationError error) = 0;
+ virtual void SetEventType(int type) = 0;
+};
+
+} // namespace notification
+#endif // NOTIFICATION_EX_IEVENT_INFO_INTERNAL_H_
diff --git a/notification-ex/iitem_factory.h b/notification-ex/iitem_factory.h
new file mode 100644
index 0000000..0511184
--- /dev/null
+++ b/notification-ex/iitem_factory.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_IITEM_FACTORY_H_
+#define NOTIFICATION_EX_IITEM_FACTORY_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API IItemFactory {
+ public:
+ virtual ~IItemFactory() = default;
+ virtual std::unique_ptr<AbstractItem> CreateItem(int type) = 0;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_ITEM_FACTORY_H_
diff --git a/notification-ex/iitem_info.h b/notification-ex/iitem_info.h
new file mode 100644
index 0000000..e1e40ff
--- /dev/null
+++ b/notification-ex/iitem_info.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_IITEM_INFO_H_
+#define NOTIFICATION_EX_IITEM_INFO_H_
+
+#include <time.h>
+
+namespace notification {
+namespace item {
+
+class EXPORT_API IItemInfo {
+ public:
+ virtual ~IItemInfo() = default;
+ virtual int GetHideTime() const = 0;
+ virtual void SetHideTime(int hide_time) = 0;
+ virtual int GetDeleteTime() const = 0;
+ virtual void SetDeleteTime(int delete_time) = 0;
+ virtual time_t GetTime() const = 0;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_IITEM_INFO_H_
diff --git a/notification-ex/iitem_info_internal.h b/notification-ex/iitem_info_internal.h
new file mode 100644
index 0000000..39b22b0
--- /dev/null
+++ b/notification-ex/iitem_info_internal.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_IITEM_INFO_INTERNAL_H_
+#define NOTIFICATION_EX_IITEM_INFO_INTERNAL_H_
+
+#include "notification-ex/iitem_info.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+namespace item {
+
+class EXPORT_API IItemInfoInternal : public IItemInfo {
+ public:
+ virtual ~IItemInfoInternal() = default;
+ virtual int GetUid() const = 0;
+ virtual void SetUid(int uid) = 0;
+ virtual int GetVersion() const = 0;
+ virtual void SetVersion(int ver) = 0;
+ virtual void AddHideViewer(std::string appid) = 0;
+ virtual std::list<std::string> GetHideViewerList() const = 0;
+ virtual void SetTime(time_t time) = 0;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_IITEM_INFO_INTERNAL_H_
diff --git a/notification-ex/image_item.cc b/notification-ex/image_item.cc
new file mode 100644
index 0000000..c829f5e
--- /dev/null
+++ b/notification-ex/image_item.cc
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include "notification-ex/image_item.h"
+#include "notification-ex/image_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define IMAGE_PATH_KEY "__IMAGE_PATH_KEY__"
+
+namespace notification {
+namespace item {
+
+ImageItem::ImageItem(std::string imagePath,
+ std::shared_ptr<AbstractAction> action)
+ : AbstractItem(action), impl_(new Impl(this, imagePath)) {
+}
+
+ImageItem::ImageItem(std::string id, std::string imagePath,
+ std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action), impl_(new Impl(this, imagePath)) {
+}
+
+ImageItem::Impl::Impl(ImageItem* parent, std::string imagePath)
+ : parent_(parent), imagePath_(imagePath) {
+ LOGI("ImageItem impl created");
+}
+
+int ImageItem::GetType() const {
+ return AbstractItem::Image;
+}
+
+Bundle ImageItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+ b.Add(IMAGE_PATH_KEY, impl_->imagePath_);
+
+ return b;
+}
+
+void ImageItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+ impl_->imagePath_ = b.GetString(IMAGE_PATH_KEY);
+}
+
+AbstractItem& ImageItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+std::string ImageItem::GetImagePath() const {
+ return impl_->imagePath_;
+}
+
+ImageItem::~ImageItem() = default;
+ImageItem::Impl::~Impl() = default;
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/image_item.h b/notification-ex/image_item.h
new file mode 100644
index 0000000..a17516d
--- /dev/null
+++ b/notification-ex/image_item.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_IMAGE_ITEM_H_
+#define NOTIFICATION_EX_IMAGE_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API ImageItem : public AbstractItem {
+ public:
+ ImageItem(std::string imagePath,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ ImageItem(std::string id, std::string imagePath,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~ImageItem();
+ int GetType() const override;
+
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ std::string GetImagePath() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; //class ImageItem
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_IMAGE_ITEM_H_
diff --git a/notification-ex/image_item_implementation.h b/notification-ex/image_item_implementation.h
new file mode 100644
index 0000000..367649f
--- /dev/null
+++ b/notification-ex/image_item_implementation.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_IMAGE_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_IMAGE_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/image_item.h"
+
+namespace notification {
+namespace item {
+
+class ImageItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class ImageItem;
+ Impl(ImageItem* parent, std::string imagePath);
+
+ private:
+ ImageItem* parent_;
+ std::string imagePath_;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_IMAGE_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/input_selector_item.cc b/notification-ex/input_selector_item.cc
new file mode 100644
index 0000000..f8ea926
--- /dev/null
+++ b/notification-ex/input_selector_item.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+#include <vector>
+#include <algorithm>
+
+#include "notification-ex/input_selector_item.h"
+#include "notification-ex/input_selector_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define INPUT_SELECTOR_CONTENTS_KEY "__INPUT_SELECTOR_CONTENTS_KEY__"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+InputSelectorItem::InputSelectorItem(std::shared_ptr<AbstractAction> action)
+ : AbstractItem(action), impl_(new Impl(this)) {
+}
+
+InputSelectorItem::InputSelectorItem(string id, std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action), impl_(new Impl(this)) {
+}
+
+InputSelectorItem::~InputSelectorItem() = default;
+InputSelectorItem::Impl::~Impl() = default;
+
+InputSelectorItem::Impl::Impl(InputSelectorItem* parent)
+ : parent_(parent) {
+ LOGI("InputSelectorItem impl created");
+}
+
+int InputSelectorItem::GetType() const {
+ return AbstractItem::InputSelector;
+}
+
+Bundle InputSelectorItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+ vector<string> contents_vector {
+ begin(impl_->contents_),
+ end(impl_->contents_)
+ };
+ b.Add(INPUT_SELECTOR_CONTENTS_KEY, contents_vector);
+ return b;
+}
+
+void InputSelectorItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+ vector<string> contents = b.GetStringArray(INPUT_SELECTOR_CONTENTS_KEY);
+ impl_->contents_ = list<string>(contents.begin(), contents.end());
+}
+
+AbstractItem& InputSelectorItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+list<string> InputSelectorItem::GetContents() const {
+ return impl_->contents_;
+}
+
+void InputSelectorItem::SetContents(list<string> contents) {
+ impl_->contents_ = move(contents);
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/input_selector_item.h b/notification-ex/input_selector_item.h
new file mode 100644
index 0000000..f9a873a
--- /dev/null
+++ b/notification-ex/input_selector_item.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_INPUT_SELECTOR_ITEM_H_
+#define NOTIFICATION_EX_INPUT_SELECTOR_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API InputSelectorItem : public AbstractItem {
+ public:
+ InputSelectorItem(std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ InputSelectorItem(std::string id,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~InputSelectorItem();
+
+ public:
+ virtual Bundle Serialize() const override;
+ virtual void Deserialize(Bundle b) override;
+ virtual AbstractItem& FindByID(std::string id) override;
+ int GetType() const override;
+
+ std::list<std::string> GetContents() const;
+ void SetContents(std::list<std::string> contents);
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_INPUT_SELECTOR_ITEM_H_
diff --git a/notification-ex/input_selector_item_implementation.h b/notification-ex/input_selector_item_implementation.h
new file mode 100644
index 0000000..21a12b2
--- /dev/null
+++ b/notification-ex/input_selector_item_implementation.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_INPUT_SELECTOR_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_INPUT_SELECTOR_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/input_selector_item.h"
+
+namespace notification {
+namespace item {
+
+class InputSelectorItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ Impl(InputSelectorItem* parent);
+
+ private:
+ friend class InputSelectorItem;
+
+ std::list<std::string> contents_;
+ InputSelectorItem* parent_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_INPUT_SELECTOR_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/item_inflator.cc b/notification-ex/item_inflator.cc
new file mode 100644
index 0000000..ffb014f
--- /dev/null
+++ b/notification-ex/item_inflator.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/item_inflator.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+shared_ptr<AbstractItem> ItemInflator::Create(Bundle b) {
+ shared_ptr<AbstractItem> item =
+ FactoryManager::GetInst().CreateItem(AbstractItem::GetType(b));
+ item.get()->Deserialize(b);
+ return item;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/item_inflator.h b/notification-ex/item_inflator.h
new file mode 100644
index 0000000..0f2e9df
--- /dev/null
+++ b/notification-ex/item_inflator.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ITEM_INFLATOR_H_
+#define NOTIFICATION_EX_ITEM_INFLATOR_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API ItemInflator {
+ public:
+ static std::shared_ptr<AbstractItem> Create(Bundle b);
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_ITEM_INFLATOR_H_
diff --git a/notification-ex/item_info.cc b/notification-ex/item_info.cc
new file mode 100644
index 0000000..94a900c
--- /dev/null
+++ b/notification-ex/item_info.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+#include <algorithm>
+
+#include "notification-ex/item_info_internal.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+AbstractItem::Impl::ItemInfo::ItemInfo(AbstractItem::Impl* impl) : impl_(impl) {
+}
+int AbstractItem::Impl::ItemInfo::GetUid() const {
+ return impl_->uid_;
+}
+
+void AbstractItem::Impl::ItemInfo::SetUid(int uid) {
+ impl_->uid_ = uid;
+}
+
+time_t AbstractItem::Impl::ItemInfo::GetTime() const {
+ return impl_->time_;
+}
+
+void AbstractItem::Impl::ItemInfo::SetTime(time_t time) {
+ impl_->time_ = time;
+}
+
+int AbstractItem::Impl::ItemInfo::GetVersion() const {
+ return impl_->version_;
+}
+
+void AbstractItem::Impl::ItemInfo::SetVersion(int ver) {
+ impl_->version_ = ver;
+}
+
+void AbstractItem::Impl::ItemInfo::SetHideTime(int hide_time) {
+ impl_->hide_time_ = hide_time;
+}
+
+int AbstractItem::Impl::ItemInfo::GetHideTime() const {
+ return impl_->hide_time_;
+}
+
+void AbstractItem::Impl::ItemInfo::SetDeleteTime(int delete_time) {
+ impl_->delete_time_ = delete_time;
+}
+
+int AbstractItem::Impl::ItemInfo::GetDeleteTime() const {
+ return impl_->delete_time_;
+}
+
+void AbstractItem::Impl::ItemInfo::AddHideViewer(std::string appid) {
+ if (find(impl_->hide_viewer_list_.begin(),
+ impl_->hide_viewer_list_.end(), appid) !=
+ impl_->hide_viewer_list_.end()) {
+ return;
+ }
+ impl_->hide_viewer_list_.push_back(appid);
+}
+
+std::list<std::string> AbstractItem::Impl::ItemInfo::GetHideViewerList() const {
+ return impl_->hide_viewer_list_;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/item_info_internal.h b/notification-ex/item_info_internal.h
new file mode 100644
index 0000000..fad736d
--- /dev/null
+++ b/notification-ex/item_info_internal.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_ITEM_INFO_INTERNAL_H_
+#define NOTIFICATION_EX_ITEM_INFO_INTERNAL_H_
+
+#include "notification-ex/abstract_item_implementation.h"
+#include "notification-ex/iitem_info_internal.h"
+
+namespace notification {
+namespace item {
+
+class AbstractItem::Impl::ItemInfo : public IItemInfoInternal {
+ public:
+ ItemInfo(AbstractItem::Impl* impl);
+ virtual ~ItemInfo() = default;
+ int GetUid() const override;
+ void SetUid(int uid) override;
+ time_t GetTime() const override;
+ void SetTime(time_t time) override;
+ int GetVersion() const override;
+ void SetVersion(int ver) override;
+ void SetHideTime(int hide_time) override;
+ int GetHideTime() const override;
+ void SetDeleteTime(int delete_time) override;
+ int GetDeleteTime() const override;
+ void AddHideViewer(std::string appid) override;
+ std::list<std::string> GetHideViewerList() const override;
+
+ private:
+ AbstractItem::Impl* impl_;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_ITEM_INFO_INTERNAL_H_
diff --git a/notification-ex/manager.cc b/notification-ex/manager.cc
new file mode 100644
index 0000000..d1c9e57
--- /dev/null
+++ b/notification-ex/manager.cc
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <glib.h>
+#include <unistd.h>
+
+#include <list>
+
+#include "notification-ex/item_inflator.h"
+#include "notification-ex/manager.h"
+#include "notification-ex/manager_implementation.h"
+#include "notification-ex/event_info_internal.h"
+#include "notification-ex/dbus_connection_manager.h"
+#include "notification-ex/ex_util.h"
+#include "notification-ex/item_info_internal.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+#define MAX_PACKAGE_STR_SIZE 512
+#define NOTIFICATION_EX_MANAGER_OBJECT_PATH "/org/tizen/notification_ex_manager"
+
+using namespace std;
+using namespace notification::item;
+namespace notification {
+
+Manager::Manager(unique_ptr<IEventSender> sender,
+ unique_ptr<IEventListener> listener, string receiver_group)
+ : impl_(new Impl(this, move(sender), move(listener), receiver_group)) {
+}
+Manager::~Manager() = default;
+
+Manager::Impl::~Impl() {
+ listener_->UnRegisterObserver(parent_);
+}
+Manager::Impl::Impl(Manager* parent,
+ unique_ptr<IEventSender> sender,
+ unique_ptr<IEventListener> listener, string receiver_group)
+ : sender_(move(sender)), listener_(move(listener)),
+ receiver_group_(receiver_group),
+ parent_(parent) {
+ LOGI("impl created");
+ listener_->RegisterObserver(parent_);
+}
+
+int Manager::Impl::SendNotify(shared_ptr<item::AbstractItem> noti,
+ IEventInfo::EventType type) {
+ Bundle serialized = noti->Serialize();
+ EventInfo info(type, util::GetAppId(), noti->GetChannel());
+ list<Bundle> serialized_list {serialized};
+
+ /* Reply to Sender */
+ sender_->Notify(info, serialized_list, noti->GetSenderAppId());
+ return info.GetRequestId();
+}
+
+void Manager::SendError(const IEventInfo& info, NotificationError error) {
+ list<Bundle> serialized_list {};
+ IEventInfo& i = const_cast<IEventInfo&>(info);
+ static_cast<IEventInfoInternal&>(i).SetError(error);
+ static_cast<IEventInfoInternal&>(i).SetEventType(EventInfo::Error);
+ impl_->sender_->Notify(info, serialized_list, info.GetOwner());
+}
+
+int Manager::Update(shared_ptr<item::AbstractItem> noti) {
+ return impl_->SendNotify(noti, EventInfo::Update);
+}
+
+int Manager::Delete(shared_ptr<item::AbstractItem> noti) {
+ return impl_->SendNotify(noti, EventInfo::Delete);
+}
+
+int Manager::DeleteAll() {
+ //TODO
+ return -1;
+}
+
+int Manager::GetCount() const {
+ //TODO
+ return -1;
+}
+
+int Manager::Hide(shared_ptr<item::AbstractItem> noti) {
+ ((IItemInfoInternal*)noti->GetInfo().get())->AddHideViewer(util::GetAppId());
+ return impl_->SendNotify(noti, EventInfo::Update);
+}
+
+shared_ptr<item::AbstractItem> Manager::FindByRootID(string id) {
+ EventInfo info(EventInfo::Get, util::GetAppId(), "", id);
+ list<Bundle> result = impl_->sender_->Request(info);
+ if (result.size() == 0) {
+ LOGE("Fail to get noti");
+ return shared_ptr<item::AbstractItem>({});
+ }
+ Bundle b = result.front();
+ shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ return gen_item;
+}
+
+list<shared_ptr<item::AbstractItem>> Manager::Get() {
+ EventInfo info(EventInfo::Get, util::GetAppId(), "");
+ list<Bundle> result = impl_->sender_->Request(info);
+ list<shared_ptr<item::AbstractItem>> gen_list;
+ for (auto& i : result) {
+ shared_ptr<AbstractItem> gen_item = ItemInflator::Create(i);
+ gen_list.emplace_back(gen_item);
+ }
+ return gen_list;
+}
+
+int Manager::SendEvent(const IEventInfo& info,
+ shared_ptr<item::AbstractItem> noti) {
+ Bundle serialized = noti->Serialize();
+ Bundle serialized_info = info.Serialize();
+ list<Bundle> serialized_list {serialized};
+ impl_->sender_->Notify(info, serialized_list, noti->GetSenderAppId());
+ return info.GetRequestId();
+}
+
+list<Bundle> Manager::OnRequest(const IEventInfo& info) {
+ list<shared_ptr<item::AbstractItem>> item_list = OnRequestEvent(info);
+ list<Bundle> serialized_list;
+ for (auto& i : item_list) {
+ if (i->CanReceive(impl_->receiver_group_))
+ serialized_list.push_back(i->Serialize());
+ }
+ return serialized_list;
+}
+
+void Manager::OnEvent(const IEventInfo& info, list<Bundle> serialized) {
+ shared_ptr<AbstractItem> gen_item;
+ int type = info.GetEventType();
+ NotificationError error =
+ (static_cast<const IEventInfoInternal&>(info)).GetError();
+ if (error != NOTIFICATION_ERROR_NONE) {
+ LOGE("Handling error event (%d)", error);
+ OnError(error, info.GetRequestId());
+ return;
+ }
+
+ switch(type) {
+ case EventInfo::Post: {
+ list<shared_ptr<item::AbstractItem>> added;
+ for (auto& i : serialized) {
+ gen_item = ItemInflator::Create(i);
+ if (gen_item->CanReceive(impl_->receiver_group_))
+ added.emplace_back(gen_item);
+ }
+ if (added.size() > 0)
+ OnAdd(info, added);
+ break;
+ }
+ case EventInfo::Update: {
+ for (auto& i : serialized) {
+ gen_item = ItemInflator::Create(i);
+ if (gen_item->CanReceive(impl_->receiver_group_))
+ OnUpdate(info, gen_item);
+ }
+ break;
+ }
+ case EventInfo::Delete: {
+ for (auto& i : serialized) {
+ gen_item = ItemInflator::Create(i);
+ if (gen_item->CanReceive(impl_->receiver_group_))
+ OnDelete(info, gen_item);
+ }
+ break;
+ }
+ case EventInfo::Get:
+ break;
+ case EventInfo::Error:
+ break;
+ case EventInfo::Custom:
+ break;
+ }
+}
+
+void Manager::OnAdd(const IEventInfo& info,
+ list<shared_ptr<item::AbstractItem>> addedItem) {
+}
+
+void Manager::OnUpdate(const IEventInfo& info,
+ shared_ptr<item::AbstractItem> updatedItem) {
+}
+
+void Manager::OnDelete(const IEventInfo& info,
+ shared_ptr<item::AbstractItem> deletedItem) {
+}
+
+void Manager::OnError(NotificationError error, int requestId) {
+}
+
+list<shared_ptr<item::AbstractItem>> Manager::OnRequestEvent(const IEventInfo& info) {
+ return list<shared_ptr<item::AbstractItem>>({});
+}
+
+string Manager::GetPath() {
+ return NOTIFICATION_EX_MANAGER_OBJECT_PATH;
+}
+
+} // namespace notification
diff --git a/notification-ex/manager.h b/notification-ex/manager.h
new file mode 100644
index 0000000..6672076
--- /dev/null
+++ b/notification-ex/manager.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_MANAGER_H_
+#define NOTIFICATION_EX_MANAGER_H_
+
+#include <string>
+#include <list>
+#include <memory>
+
+#include "notification-ex/common.h"
+#include "notification-ex/abstract_item.h"
+#include "notification-ex/event_observer_interface.h"
+#include "notification-ex/event_sender_interface.h"
+#include "notification-ex/event_listener_interface.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API Manager : public IEventObserver {
+ public:
+ Manager(std::unique_ptr<IEventSender> sender,
+ std::unique_ptr<IEventListener> listener, std::string receiver_group = "");
+ virtual ~Manager();
+
+ std::list<std::shared_ptr<item::AbstractItem>> Get();
+ int Update(std::shared_ptr<item::AbstractItem> noti);
+ int Delete(std::shared_ptr<item::AbstractItem> noti);
+ int DeleteAll();
+ int Hide(std::shared_ptr<item::AbstractItem> noti);
+ std::shared_ptr<item::AbstractItem> FindByRootID(std::string id);
+ int SendEvent(const IEventInfo& info, std::shared_ptr<item::AbstractItem> noti);
+ void OnEvent(const IEventInfo& info, std::list<Bundle> serialized) override;
+ std::list<Bundle> OnRequest(const IEventInfo& info) override;
+ void SendError(const IEventInfo& info, NotificationError error);
+ int GetCount() const;
+ static std::string GetPath();
+
+ protected:
+ virtual void OnAdd(const IEventInfo& info, std::list<std::shared_ptr<item::AbstractItem>> addedItem);
+ virtual void OnUpdate(const IEventInfo& info, std::shared_ptr<item::AbstractItem> updatedItem);
+ virtual void OnDelete(const IEventInfo& info, std::shared_ptr<item::AbstractItem> deletedItem);
+ virtual void OnError(NotificationError error, int requestId);
+ virtual std::list<std::shared_ptr<item::AbstractItem>> OnRequestEvent(
+ const IEventInfo& info);
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_MANAGER_H_
diff --git a/notification-ex/manager_implementation.h b/notification-ex/manager_implementation.h
new file mode 100644
index 0000000..5502822
--- /dev/null
+++ b/notification-ex/manager_implementation.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_MANAGER_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_MANAGER_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/manager.h"
+
+namespace notification {
+
+class Manager::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ Impl(Manager* parent, std::unique_ptr<IEventSender> sender,
+ std::unique_ptr<IEventListener> listener, std::string receiver_group);
+
+ private:
+ friend class Manager;
+ int SendNotify(std::shared_ptr<item::AbstractItem> noti,
+ IEventInfo::EventType type);
+ std::unique_ptr<IEventSender> sender_;
+ std::unique_ptr<IEventListener> listener_;
+ std::string receiver_group_;
+ Manager* parent_;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_MANAGER_IMPLEMENTATION_H_
diff --git a/notification-ex/mock_listener.h b/notification-ex/mock_listener.h
new file mode 100644
index 0000000..1df439b
--- /dev/null
+++ b/notification-ex/mock_listener.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_MOCK_LISTENER_H_
+#define NOTIFICATION_EX_MOCK_LISTENER_H_
+
+#include "notification-ex/observer_interface.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API MockEventsListener : public IEventListener {
+ public:
+ MockEventsListener();
+ virtual ~MockEventsListener();
+
+ void RegisterObserver(IEventObserver observer) override;
+ void UnRegisterObserver(IEventObserver observer) override;
+ void NotifyAll() override;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_MOCK_LISTENER_H_
diff --git a/notification-ex/mock_sender.h b/notification-ex/mock_sender.h
new file mode 100644
index 0000000..509a525
--- /dev/null
+++ b/notification-ex/mock_sender.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_MOCK_SENDER_H_
+#define NOTIFICATION_EX_MOCK_SENDER_H_
+
+#include "notification-ex/ex_bundle.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API MockSender : public IEventSender {
+ public:
+ MockSender();
+ virtual ~MockSender();
+
+ void Notify(Bundle serialized) override;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_MOCK_SENDER_H_
diff --git a/notification-ex/notification-ex.pc.in b/notification-ex/notification-ex.pc.in
new file mode 100644
index 0000000..e51c660
--- /dev/null
+++ b/notification-ex/notification-ex.pc.in
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: notification-ex
+Description: Support development of the notification
+Version: @VERSION@
+Libs: -L${libdir} -lnotification-ex
+Cflags: -I${includedir}
+cppflags: -I${includedir}
diff --git a/notification-ex/null_item.cc b/notification-ex/null_item.cc
new file mode 100644
index 0000000..3c0f7f8
--- /dev/null
+++ b/notification-ex/null_item.cc
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/null_item.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+NullItem::NullItem(shared_ptr<AbstractAction> action)
+ : AbstractItem(action) {
+}
+
+NullItem::NullItem(string id,
+ shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action) {
+}
+NullItem::~NullItem() = default;
+
+int NullItem::GetType() const {
+ return AbstractItem::NullObject;
+}
+
+Bundle NullItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+ return b;
+}
+
+void NullItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+}
+
+AbstractItem& NullItem::FindByID(std::string id) {
+ return *this;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/null_item.h b/notification-ex/null_item.h
new file mode 100644
index 0000000..6864c1a
--- /dev/null
+++ b/notification-ex/null_item.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_NULL_ITEM_H_
+#define NOTIFICATION_EX_NULL_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API NullItem : public AbstractItem {
+ public:
+ NullItem(std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ NullItem(std::string id,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~NullItem();
+ int GetType() const override;
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_NULL_ITEM_H_
diff --git a/notification-ex/progress_item.cc b/notification-ex/progress_item.cc
new file mode 100644
index 0000000..9738ea3
--- /dev/null
+++ b/notification-ex/progress_item.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/exception.h"
+#include "notification-ex/progress_item.h"
+#include "notification-ex/progress_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define PROGRESS_MIN_KEY "__PROGRESS_MIN_KEY__"
+#define PROGRESS_CURRENT_KEY "__PROGRESS_CURRENT_KEY__"
+#define PROGRESS_MAX_KEY "__PROGRESS_MAX_KEY__"
+
+using namespace std;
+namespace notification {
+namespace item {
+
+ProgressItem::ProgressItem(float min_val, float current, float max_val,
+ std::shared_ptr<AbstractAction> action)
+ : AbstractItem(action),
+ impl_(new Impl(min_val, current, max_val, this)) {
+}
+
+ProgressItem::ProgressItem(string id, float min_val, float current,
+ float max_val, std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action),
+ impl_(new Impl(min_val, current, max_val, this)) {
+}
+
+ProgressItem::~ProgressItem() = default;
+ProgressItem::Impl::~Impl() = default;
+
+ProgressItem::Impl::Impl(float min_val, float current, float max_val,
+ ProgressItem* parent)
+ : min_(min_val), current_(current), max_(max_val), parent_(parent) {
+ if (min_val > current || max_val < current)
+ THROW(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ LOGI("ProgressItem impl created");
+}
+
+int ProgressItem::GetType() const {
+ return AbstractItem::Progress;
+}
+
+Bundle ProgressItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+ b.Add(PROGRESS_MIN_KEY, to_string(impl_->min_));
+ b.Add(PROGRESS_CURRENT_KEY, to_string(impl_->current_));
+ b.Add(PROGRESS_MAX_KEY, to_string(impl_->max_));
+ return b;
+}
+
+void ProgressItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+ impl_->min_ = strtof(b.GetString(PROGRESS_MIN_KEY).c_str(), 0);
+ impl_->current_ = strtof(b.GetString(PROGRESS_CURRENT_KEY).c_str(), 0);
+ impl_->max_ = strtof(b.GetString(PROGRESS_MAX_KEY).c_str(), 0);
+}
+
+AbstractItem& ProgressItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+float ProgressItem::GetCurrent() const {
+ return impl_->current_;
+}
+
+void ProgressItem::SetCurrent(float current) {
+ impl_->current_ = current;
+}
+
+float ProgressItem::GetMin() const {
+ return impl_->min_;
+}
+
+float ProgressItem::GetMax() const {
+ return impl_->max_;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/progress_item.h b/notification-ex/progress_item.h
new file mode 100644
index 0000000..04fa3a7
--- /dev/null
+++ b/notification-ex/progress_item.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_PROGRESS_ITEM_H_
+#define NOTIFICATION_EX_PROGRESS_ITEM_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API ProgressItem : public AbstractItem {
+ public:
+ ProgressItem(float min, float current, float max,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ ProgressItem(std::string id, float min, float current, float max,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~ProgressItem();
+
+ public:
+ virtual Bundle Serialize() const override;
+ virtual void Deserialize(Bundle b) override;
+ virtual AbstractItem& FindByID(std::string id) override;
+ int GetType() const override;
+
+ float GetCurrent() const;
+ void SetCurrent(float current);
+ float GetMin() const;
+ float GetMax() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_PROGRESS_ITEM_H_
diff --git a/notification-ex/progress_item_implementation.h b/notification-ex/progress_item_implementation.h
new file mode 100644
index 0000000..865e96f
--- /dev/null
+++ b/notification-ex/progress_item_implementation.h
@@ -0,0 +1,51 @@
+
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_INPUT_SELECTOR_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_INPUT_SELECTOR_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/progress_item.h"
+
+namespace notification {
+namespace item {
+
+class ProgressItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ Impl(float min_val, float current, float max_val,
+ ProgressItem* parent);
+
+ private:
+ friend class ProgressItem;
+
+ float min_;
+ float current_;
+ float max_;
+ ProgressItem* parent_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_INPUT_SELECTOR_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/reporter.cc b/notification-ex/reporter.cc
new file mode 100644
index 0000000..5bfbaec
--- /dev/null
+++ b/notification-ex/reporter.cc
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <glib.h>
+#include <unistd.h>
+
+#include <list>
+
+#include "notification-ex/reporter.h"
+#include "notification-ex/reporter_implementation.h"
+#include "notification-ex/event_info_internal.h"
+#include "notification-ex/item_inflator.h"
+#include "notification-ex/dbus_connection_manager.h"
+#include "notification-ex/ex_util.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define MAX_PACKAGE_STR_SIZE 512
+#define NOTIFICATION_EX_REPORTER_OBJECT_PATH "/org/tizen/notification_ex_reporter"
+
+using namespace std;
+using namespace notification::item;
+namespace notification {
+
+Reporter::Reporter(
+ unique_ptr<IEventSender> sender, unique_ptr<IEventListener> listener)
+ : impl_(new Impl(this, move(sender), move(listener))) {
+}
+Reporter::~Reporter() = default;
+
+Reporter::Impl::~Impl() {
+ listener_->UnRegisterObserver(parent_);
+}
+Reporter::Impl::Impl(Reporter* parent,
+ unique_ptr<IEventSender> sender, unique_ptr<IEventListener> listener)
+ : sender_(move(sender)), listener_(move(listener)), parent_(parent) {
+ LOGI("impl created");
+ listener_->RegisterObserver(parent_);
+}
+
+int Reporter::Impl::SendNotify(shared_ptr<item::AbstractItem> noti,
+ IEventInfo::EventType type) {
+ Bundle serialized = noti->Serialize();
+ EventInfo info(type, util::GetAppId(), noti->GetChannel());
+ list<Bundle> serialized_list {serialized};
+ sender_->Notify(info, serialized_list);
+ return info.GetRequestId();
+}
+
+void Reporter::SendError(const IEventInfo& info, NotificationError error) {
+ list<Bundle> serialized_list {};
+ IEventInfo& i = const_cast<IEventInfo&>(info);
+ static_cast<IEventInfoInternal&>(i).SetError(error);
+ static_cast<IEventInfoInternal&>(i).SetEventType(EventInfo::Error);
+ impl_->sender_->Notify(info, serialized_list, info.GetOwner());
+}
+
+int Reporter::Post(std::shared_ptr<item::AbstractItem> noti) {
+ LOGI("Post noti");
+ return impl_->SendNotify(noti, EventInfo::Post);
+}
+
+int Reporter::Post(std::list<std::shared_ptr<AbstractItem>> notiList) {
+ EventInfo info(EventInfo::Post, util::GetAppId(), "");
+ list<Bundle> serialized_list;
+ for (auto& i : notiList) {
+ Bundle b = i->Serialize();
+ serialized_list.push_back(b);
+ }
+ impl_->sender_->Notify(info, serialized_list);
+ return info.GetRequestId();
+}
+
+int Reporter::Update(std::shared_ptr<AbstractItem> noti) {
+ return impl_->SendNotify(noti, EventInfo::Update);
+}
+
+int Reporter::Delete(std::shared_ptr<AbstractItem> noti) {
+ return impl_->SendNotify(noti, EventInfo::Delete);
+}
+
+int Reporter::DeleteAll() {
+ //TODO
+ return -1;
+}
+
+std::shared_ptr<AbstractItem> Reporter::FindByRootID(std::string id) {
+ Bundle serialized;
+ EventInfo info(EventInfo::Get, util::GetAppId(), "", id);
+ list<Bundle> result = impl_->sender_->Request(info);
+ if (result.size() == 0) {
+ LOGE("Fail to get noti");
+ return shared_ptr<item::AbstractItem>({});
+ }
+ Bundle b = result.front();
+ shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ return gen_item;
+}
+
+int Reporter::SendEvent(const IEventInfo& info,
+ shared_ptr<item::AbstractItem> noti) {
+ Bundle serialized = noti->Serialize();
+ list<Bundle> serialized_list {serialized};
+ impl_->sender_->Notify(info, serialized_list);
+ return info.GetRequestId();
+}
+
+void Reporter::OnEvent(const IEventInfo& info, list<Bundle> serialized) {
+ NotificationError error =
+ (static_cast<const IEventInfoInternal&>(info)).GetError();
+ if (info.GetEventType() == EventInfo::Error) {
+ OnError(error, info.GetRequestId());
+ return;
+ }
+
+ list<shared_ptr<item::AbstractItem>> item_list;
+ for (auto& i : serialized) {
+ shared_ptr<AbstractItem> gen_item = ItemInflator::Create(i);
+ item_list.emplace_back(gen_item);
+ }
+ OnEvent(info, item_list);
+}
+
+list<shared_ptr<item::AbstractItem>> Reporter::OnRequestEvent(const IEventInfo& info) {
+ return list<shared_ptr<item::AbstractItem>>({});
+}
+
+list<Bundle> Reporter::OnRequest(const IEventInfo& info) {
+ list<shared_ptr<item::AbstractItem>> item_list = OnRequestEvent(info);
+ list<Bundle> serialized_list;
+ for (auto& i : item_list) {
+ serialized_list.push_back(i->Serialize());
+ }
+ return serialized_list;
+}
+
+void Reporter::OnEvent(
+ const IEventInfo& info, list<shared_ptr<item::AbstractItem>> notiList) {
+}
+
+void Reporter::OnError(NotificationError error, int requestId) {
+}
+
+string Reporter::GetPath() {
+ return NOTIFICATION_EX_REPORTER_OBJECT_PATH;
+}
+
+} // namespace notification
diff --git a/notification-ex/reporter.h b/notification-ex/reporter.h
new file mode 100644
index 0000000..77620dc
--- /dev/null
+++ b/notification-ex/reporter.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_REPOTER_H_
+#define NOTIFICATION_EX_REPOTER_H_
+
+#include <string>
+#include <list>
+#include <memory>
+
+#include "notification-ex/common.h"
+#include "notification-ex/ievent_info.h"
+#include "notification-ex/event_observer_interface.h"
+#include "notification-ex/event_sender_interface.h"
+#include "notification-ex/event_listener_interface.h"
+#include "notification-ex/abstract_item.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+
+class EXPORT_API Reporter : public IEventObserver {
+ public:
+ Reporter(std::unique_ptr<IEventSender> sender,
+ std::unique_ptr<IEventListener> listener);
+ virtual ~Reporter();
+
+ int SendEvent(const IEventInfo& info, std::shared_ptr<item::AbstractItem> noti);
+ void SendError(const IEventInfo& info, NotificationError error);
+ int Post(std::shared_ptr<item::AbstractItem> noti);
+ int Post(std::list<std::shared_ptr<item::AbstractItem>> notiList);
+ int Update(std::shared_ptr<item::AbstractItem> noti);
+ int Delete(std::shared_ptr<item::AbstractItem> noti);
+ int DeleteAll();
+ std::shared_ptr<item::AbstractItem> FindByRootID(std::string id);
+ virtual void OnEvent(const IEventInfo& info,
+ std::list<std::shared_ptr<item::AbstractItem>> notiList);
+ virtual std::list<std::shared_ptr<item::AbstractItem>> OnRequestEvent(
+ const IEventInfo& info);
+ virtual void OnError(NotificationError error, int requestId);
+ void OnEvent(const IEventInfo& info, std::list<Bundle> serialized) override;
+ std::list<Bundle> OnRequest(const IEventInfo& info) override;
+ static std::string GetPath();
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_REPOTER_H_
diff --git a/notification-ex/reporter_implementation.h b/notification-ex/reporter_implementation.h
new file mode 100644
index 0000000..8628dcf
--- /dev/null
+++ b/notification-ex/reporter_implementation.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_REPORTER_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_REPORTER_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/reporter.h"
+
+namespace notification {
+
+class Reporter::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ Impl(Reporter* parent, std::unique_ptr<IEventSender> sender,
+ std::unique_ptr<IEventListener> listener);
+
+ private:
+ friend class Reporter;
+ int SendNotify(std::shared_ptr<item::AbstractItem> noti,
+ IEventInfo::EventType type);
+ std::unique_ptr<IEventSender> sender_;
+ std::unique_ptr<IEventListener> listener_;
+ Reporter* parent_;
+};
+
+} // namespace notification
+
+#endif // NOTIFICATION_EX_REPORTER_IMPLEMENTATION_H_
diff --git a/notification-ex/text_item.cc b/notification-ex/text_item.cc
new file mode 100644
index 0000000..075df87
--- /dev/null
+++ b/notification-ex/text_item.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include <memory>
+
+#include "notification-ex/text_item.h"
+#include "notification-ex/text_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define TEXT_CONTENTS_KEY "__TEXT_CONTENTS_KEY__"
+#define TEXT_HYPERLINK_KEY "__TEXT_HYPERLINK_KEY__"
+
+namespace notification {
+namespace item {
+TextItem::TextItem(std::string id, std::string text, std::string hyperlink,
+ std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action), impl_(new Impl(this, text, hyperlink)) {
+}
+
+TextItem::Impl::Impl(TextItem* parent, std::string text, std::string hyperlink)
+ : parent_(parent), text_(text), hyperlink_(hyperlink) {
+ LOGI("TextItem created");
+}
+
+TextItem::~TextItem() = default;
+TextItem::Impl::~Impl() = default;
+
+int TextItem::GetType() const {
+ return AbstractItem::Text;
+}
+
+Bundle TextItem::Serialize() const {
+ Bundle b;
+ b = AbstractItem::Serialize();
+
+ if (!impl_->text_.empty())
+ b.Add(TEXT_CONTENTS_KEY, impl_->text_);
+
+ if (!impl_->hyperlink_.empty())
+ b.Add(TEXT_HYPERLINK_KEY, impl_->hyperlink_);
+
+ return b;
+}
+
+void TextItem::Deserialize(Bundle b) {
+ AbstractItem::Deserialize(b);
+ impl_->text_ = b.GetString(TEXT_CONTENTS_KEY);
+ impl_->hyperlink_ = b.GetString(TEXT_HYPERLINK_KEY);
+}
+
+AbstractItem& TextItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+void TextItem::SetContents(std::string contents) {
+ impl_->text_ = contents;
+}
+
+std::string TextItem::GetContents() const {
+ return impl_->text_;
+}
+
+std::string TextItem::GetHyperLink() const {
+ return impl_->hyperlink_;
+}
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/text_item.h b/notification-ex/text_item.h
new file mode 100644
index 0000000..178d7c4
--- /dev/null
+++ b/notification-ex/text_item.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_TEXT_ITEM_H_
+#define NOTIFICATION_EX_TEXT_ITEM_H_
+
+#include <memory>
+#include <string>
+
+#include "notification-ex/abstract_item.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+namespace item {
+
+class EXPORT_API TextItem : public AbstractItem {
+ public:
+ TextItem(std::string id ,std::string text,
+ std::string hyperlink = std::string(),
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ virtual ~TextItem();
+ int GetType() const override;
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ void SetContents(std::string contents);
+ std::string GetContents() const;
+ std::string GetHyperLink() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class TextItem
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_TEXT_ITEM_H_ \ No newline at end of file
diff --git a/notification-ex/text_item_implementation.h b/notification-ex/text_item_implementation.h
new file mode 100644
index 0000000..ee0e567
--- /dev/null
+++ b/notification-ex/text_item_implementation.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_TEXT_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_TEXT_ITEM_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+
+#include "notification-ex/text_item.h"
+
+namespace notification {
+namespace item {
+
+class TextItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ Impl(TextItem* parent, std::string text, std::string hyperlink);
+
+ private:
+ friend class TextItem;
+
+ TextItem* parent_;
+ std::string text_;
+ std::string hyperlink_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_TEXT_ITEM_IMPLEMENTATION_H_ \ No newline at end of file
diff --git a/notification-ex/time_item.cc b/notification-ex/time_item.cc
new file mode 100644
index 0000000..f02e413
--- /dev/null
+++ b/notification-ex/time_item.cc
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+
+#include "notification-ex/time_item.h"
+#include "notification-ex/time_item_implementation.h"
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define TIME_KEY "__TIME_KEY__"
+
+namespace notification {
+namespace item {
+
+TimeItem::TimeItem(std::shared_ptr<AbstractAction> action)
+ : AbstractItem(action), impl_(new Impl(this, 0)) {
+ time_t current_time;
+ time(&current_time);
+
+ impl_->time_ = current_time;
+}
+
+TimeItem::TimeItem(time_t time, std::shared_ptr<AbstractAction> action)
+ : AbstractItem(action), impl_(new Impl(this, time)) {
+}
+
+TimeItem::TimeItem(std::string id, time_t time,
+ std::shared_ptr<AbstractAction> action)
+ : AbstractItem(id, action), impl_(new Impl(this, time)) {
+}
+
+TimeItem::Impl::Impl(TimeItem* parent, time_t time)
+ : parent_(parent), time_(time) {
+ LOGI("TimeItem impl created");
+}
+
+int TimeItem::GetType() const {
+ return AbstractItem::Time;
+}
+
+Bundle TimeItem::Serialize() const {
+ Bundle b;
+ struct tm* timeinfo;
+ char buf[80] = {0,};
+
+ b = AbstractItem::Serialize();
+
+ //timt_t to tm
+ timeinfo = localtime(&impl_->time_);
+ //tm to str
+ strftime (buf, sizeof(buf), "%s", timeinfo);
+ b.Add(TIME_KEY, std::string(buf));
+
+ return b;
+}
+
+void TimeItem::Deserialize(Bundle b) {
+ std::string time_s;
+ struct tm timeinfo;
+
+ AbstractItem::Deserialize(b);
+ time_s = b.GetString(TIME_KEY);
+
+ //str to tm
+ strptime(time_s.c_str(), "%s", &timeinfo);
+ //tm to time_t
+ impl_->time_ = mktime(&timeinfo);
+}
+
+AbstractItem& TimeItem::FindByID(std::string id) {
+ if (GetId() == id)
+ return *this;
+
+ return FactoryManager::GetInst().GetNullItem();
+}
+
+time_t TimeItem::GetTime() const {
+ return impl_->time_;
+}
+
+TimeItem::~TimeItem() = default;
+TimeItem::Impl::~Impl() = default;
+
+} // namespace item
+} // namespace notification
diff --git a/notification-ex/time_item.h b/notification-ex/time_item.h
new file mode 100644
index 0000000..5322eb3
--- /dev/null
+++ b/notification-ex/time_item.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_TIME_ITEM_H_
+#define NOTIFICATION_EX_TIME_ITEM_H_
+
+#include <time.h>
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/abstract_item.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API TimeItem : public AbstractItem {
+ public:
+ TimeItem(
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ TimeItem(time_t time,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+ TimeItem(std::string id, time_t time,
+ std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}));
+
+ virtual ~TimeItem();
+ int GetType() const override;
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ AbstractItem& FindByID(std::string id) override;
+ time_t GetTime() const;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+}; // class TimeItem
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_TIME_ITEM_H_
diff --git a/notification-ex/time_item_implementation.h b/notification-ex/time_item_implementation.h
new file mode 100644
index 0000000..6330db0
--- /dev/null
+++ b/notification-ex/time_item_implementation.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_TIME_ITEM_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_TIME_ITEM_IMPLEMENTATION_H_
+
+#include <time.h>
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include "notification-ex/time_item.h"
+
+namespace notification {
+namespace item {
+
+class TimeItem::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class TimeItem;
+ Impl(TimeItem* parent, time_t time);
+
+ private:
+ TimeItem* parent_;
+ time_t time_;
+};
+
+} // namespace item
+} // namespace notification
+#endif // NOTIFICATION_EX_TIME_ITEM_IMPLEMENTATION_H_
diff --git a/notification-ex/visibility_action.cc b/notification-ex/visibility_action.cc
new file mode 100644
index 0000000..f274eb2
--- /dev/null
+++ b/notification-ex/visibility_action.cc
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 "notification-ex/abstract_item.h"
+#include "notification-ex/visibility_action.h"
+#include "notification-ex/visibility_action_implementation.h"
+#include "notification-ex/exception.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define VISIBILITY_ACTION_ENTITY_KEY "__VISIBILITY_ACTION_VISIBLE_KEY__"
+#define VISIBILITY_ACTION_ENTITY_SIZE_KEY "__VISIBILITY_ACTION_ENTITY_SIZE_KEY__"
+
+namespace notification {
+namespace item {
+
+VisibilityAction::VisibilityAction()
+ : AbstractAction(true), impl_(new Impl(this)) {
+}
+
+VisibilityAction::VisibilityAction(std::string extra)
+ : AbstractAction(true, extra), impl_(new Impl(this)) {
+}
+
+VisibilityAction::Impl::Impl(VisibilityAction* parent) : parent_(parent) {
+ LOGI("VisibilityAction created");
+}
+
+VisibilityAction::~VisibilityAction() = default;
+VisibilityAction::Impl::~Impl() = default;
+
+int VisibilityAction::GetType() const {
+ return AbstractAction::Visibility;
+}
+
+Bundle VisibilityAction::Serialize() const {
+ char buf_key[128];
+ char buf_data[128];
+ Bundle b;
+ int i = 0;
+
+ b = AbstractAction::Serialize();
+
+ std::list<std::unique_ptr<Impl::VisibilityEntity>>::iterator it;
+
+ for (it = impl_->entities_.begin(); it != impl_->entities_.end(); it++) {
+ buf_key[0] = '\0';
+ buf_data[0] = '\0';
+
+ snprintf(buf_key, sizeof(buf_key), "%s:%d",
+ VISIBILITY_ACTION_ENTITY_SIZE_KEY, i);
+
+ snprintf(buf_data, sizeof(buf_data), "%s:%d",
+ (*it)->id_.c_str(), (*it)->visibility_);
+
+ b.Add(std::string(buf_key), std::string(buf_data));
+ i++;
+ }
+
+ b.Add(VISIBILITY_ACTION_ENTITY_SIZE_KEY, std::to_string(i));
+ return b;
+}
+
+void VisibilityAction::Deserialize(Bundle b) {
+ char buf_key[128];
+ int size;
+ std::size_t pos;
+
+ AbstractAction::Deserialize(b);
+
+ size = std::stoi(b.GetString(VISIBILITY_ACTION_ENTITY_SIZE_KEY));
+
+ for (int i = 0; i < size; i++) {
+ buf_key[0] = '\0';
+
+ snprintf(buf_key, sizeof(buf_key), "%s:%d",
+ VISIBILITY_ACTION_ENTITY_SIZE_KEY, i);
+
+ std::string str = b.GetString(std::string(buf_key));
+
+ pos = str.find(":");
+ std::string id = str.substr(0, pos);
+ bool visible = std::stoi(str.substr(pos+1));
+
+ impl_->entities_.emplace_back(new VisibilityAction::Impl::VisibilityEntity(
+ id, visible));
+ }
+}
+
+bool VisibilityAction::IsLocal() const {
+ return AbstractAction::IsLocal();
+}
+
+void VisibilityAction::Execute(std::shared_ptr<AbstractItem> item) {
+ for (const auto& entity : impl_->entities_) {
+ AbstractItem& item_ = item->FindByID(entity->id_);
+ if (item_.GetType() != AbstractItem::NullObject)
+ item_.SetVisible(entity->visibility_);
+ }
+}
+
+std::string VisibilityAction::GetExtra() const {
+ return AbstractAction::GetExtra();
+}
+
+void VisibilityAction::SetVisibility(std::string id, bool visible) {
+ impl_->entities_.emplace_back(new VisibilityAction::Impl::VisibilityEntity(
+ id, visible));
+}
+
+} //namespace item
+} //namespace notification
diff --git a/notification-ex/visibility_action.h b/notification-ex/visibility_action.h
new file mode 100644
index 0000000..ebc543a
--- /dev/null
+++ b/notification-ex/visibility_action.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_VISIBILITY_ACTION_H_
+#define NOTIFICATION_EX_VISIBILITY_ACTION_H_
+
+#include "notification-ex/abstract_action.h"
+
+namespace notification {
+namespace item {
+
+class EXPORT_API VisibilityAction : public AbstractAction {
+ public:
+ VisibilityAction();
+ VisibilityAction(std::string extra);
+ virtual ~VisibilityAction();
+
+ int GetType() const override;
+ Bundle Serialize() const override;
+ void Deserialize(Bundle b) override;
+ bool IsLocal() const override;
+ void Execute(std::shared_ptr<AbstractItem> item) override;
+ std::string GetExtra() const override;
+ void SetVisibility(std::string id, bool visible);
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_VISIBILITY_ACTION_H_
diff --git a/notification-ex/visibility_action_implementation.h b/notification-ex/visibility_action_implementation.h
new file mode 100644
index 0000000..d21479f
--- /dev/null
+++ b/notification-ex/visibility_action_implementation.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef NOTIFICATION_EX_VISIBILITY_ACTION_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_VISIBILITY_ACTION_IMPLEMENTATION_H_
+
+#include <list>
+
+#include "notification-ex/visibility_action.h"
+
+namespace notification {
+namespace item {
+
+class VisibilityAction::Impl {
+ public:
+ virtual ~Impl();
+
+ private:
+ friend class VisibilityAction;
+ Impl(VisibilityAction* parent);
+
+ class VisibilityEntity {
+ public:
+ std::string id_;
+ bool visibility_;
+ public:
+ VisibilityEntity(std::string id, bool visibility)
+ : id_(id), visibility_(visibility) {
+ }
+ };
+
+ private:
+ VisibilityAction* parent_;
+ std::list<std::unique_ptr<VisibilityEntity>> entities_;
+};
+
+} // namespace item
+} // namespace notification
+
+#endif // NOTIFICATION_EX_VISIBILITY_ACTION_IMPLEMENTATION_H_
diff --git a/notification.manifest b/notification.manifest
new file mode 100644
index 0000000..6c61ae0
--- /dev/null
+++ b/notification.manifest
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
diff --git a/notification/11_notification-add.post b/notification/11_notification-add.post
new file mode 100644
index 0000000..a0faef0
--- /dev/null
+++ b/notification/11_notification-add.post
@@ -0,0 +1 @@
+notification_init --uid $2 \ No newline at end of file
diff --git a/notification/CMakeLists.txt b/notification/CMakeLists.txt
new file mode 100644
index 0000000..24fb7d5
--- /dev/null
+++ b/notification/CMakeLists.txt
@@ -0,0 +1,68 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(notification C)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR ${LIB_INSTALL_DIR})
+SET(INCLUDEDIR "\${prefix}/include/${PROJECT_NAME}")
+
+#ADD_SUBDIRECTORY(test-app)
+
+SET(INIT-SRCS
+ ./src/notification_init.c
+)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRCS)
+LIST(REMOVE_ITEM SRCS ${INIT-SRCS})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED
+ sqlite3
+ vconf
+ bundle
+ dlog
+ aul
+ dbus-1
+ capi-appfw-app-control
+ capi-appfw-package-manager
+ pkgmgr-info
+ libtzplatform-config
+ glib-2.0
+ gio-2.0
+ gio-unix-2.0
+ iniparser
+ security-manager
+ libsmack
+)
+
+FOREACH(flag ${pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -g -Wall")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE")
+
+SET(CMAKE_SKIP_BUILD_RPATH TRUE)
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${MAJORVER})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${FULLVER})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
+
+ADD_EXECUTABLE(notification_init ${INIT-SRCS})
+TARGET_LINK_LIBRARIES(notification_init ${pkgs_LDFLAGS} notification "-pie")
+
+CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
+ DESTINATION include/notification
+ FILES_MATCHING
+ PATTERN "*_private.h" EXCLUDE
+ PATTERN "*_group.h" EXCLUDE
+ PATTERN "*_debug.h" EXCLUDE
+ PATTERN "*.h")
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/11_notification-add.post DESTINATION ${SYSCONF_INSTALL_DIR}/gumd/useradd.d/)
+INSTALL(TARGETS notification_init DESTINATION bin)
diff --git a/notification/include/notification.h b/notification/include/notification.h
new file mode 100644
index 0000000..cb45eed
--- /dev/null
+++ b/notification/include/notification.h
@@ -0,0 +1,1865 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_H__
+#define __NOTIFICATION_H__
+
+#include <time.h>
+#include <bundle.h>
+#include <app_control.h>
+
+#include <notification_error.h>
+#include <notification_type.h>
+#include <notification_status.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @file notification.h
+ * @brief This file contains the notification API.
+ */
+
+
+/**
+ * @addtogroup NOTIFICATION_MODULE
+ * @{
+ */
+
+
+/**
+ * @brief Sets an absolute path for an image file to display on the notification view.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] type The notification image type
+ * @param[in] image_path The image file full path
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_image_type_e
+ * @see notification_create()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, APP_IMAGE_FULL_PATH);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_image(notification_h noti, notification_image_type_e type, const char *image_path);
+
+
+/**
+ * @brief Gets the absolute path of an image file.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks Do not free @a image_path. It will be freed when notification_free() is called.
+ * @param[in] noti Notification handle
+ * @param[in] type Notification image type
+ * @param[out] image_path Image file full path
+ * @return NOTIFICATION_ERROR_NONE on success,
+ * other value on failure
+ * @retval NOTIFICATION_ERROR_NONE Success
+ * @retval NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_image_type_e
+ * @see notification_create()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ char *image_path = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, &image_path);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_get_image(notification_h noti, notification_image_type_e type, char **image_path);
+
+
+/**
+ * @brief Sets a timestamp.
+ * @details If input_time is @c 0, time information is taken from the current time.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] input_time The input time. If you want the time stamp to not be shown, set this as NOTIFICATION_DO_NOT_SHOW_TIME_STAMP
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see notification_create()
+ * @see NOTIFICATION_DO_NOT_SHOW_TIME_STAMP
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_time(noti, time(NULL));
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_time(notification_h noti, time_t input_time);
+
+
+/**
+ * @brief Gets a timestamp.
+ * @details If ret_time is @c 0, time information is not set before.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] ret_time The return time value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see notification_create()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ time_t ret_time;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_time(noti, &ret_time);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_get_time(notification_h noti, time_t *ret_time);
+
+
+/**
+ * @brief Gets an insertion timestamp of the notification.
+ * @details If ret_time is @c 0, this notification data is not inserted before.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] ret_time The return time value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ time_t ret_time;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_insert_time(noti, &ret_time);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_get_insert_time(notification_h noti, time_t *ret_time);
+
+
+/**
+ * @brief Sets the text to display on the notification view.
+ * @details Sets title, content string. If the text is formatted data (only %d, %f, %s are supported), type - value pair should be set.
+ * If %d, the type #NOTIFICATION_VARIABLE_TYPE_INT and the value is an integer.
+ * If %f, the type #NOTIFICATION_VARIABLE_TYPE_DOUBLE and the value is a double.
+ * If %s, the type #NOTIFICATION_VARIABLE_TYPE_STRING and the value is a string.
+ * If the type is #NOTIFICATION_VARIABLE_TYPE_COUNT, notification count is displaying with text.
+ * If the value is #NOTIFICATION_COUNT_POS_LEFT, count is displayed at the left of the text.
+ * If the value is #NOTIFICATION_COUNT_POS_IN, count is displayed in the text when text has %d format.
+ * If the value is #NOTIFICATION_COUNT_POS_RIGHT, count is displayed at the right of the text.
+ * Variable parameters should be terminated #NOTIFICATION_VARIABLE_TYPE_NONE.
+ *
+ * Note that You can display the translated contents according to the language of the system.
+ * The application must supply a String KEY as the fourth argument to support localization.
+ * If the language on the system changes, the contents of the notification are also translated.
+ *
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] type The notification text type
+ * @param[in] text The basic text
+ * @param[in] key The text key for localization
+ * @param[in] args_type The variable parameter that type - value pair
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre notification handle should be created by notification_create().
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
+ "I'm Title", "IDS_APP_BODY_IM_TITLE", NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_text(notification_h noti, notification_text_type_e type,
+ const char *text, const char *key, int args_type, ...);
+
+
+/**
+ * @brief Gets the text from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] type The notification text type
+ * @param[out] text The notification text
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ char *text = NULL;
+
+ noti_err = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE, &text);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_text(notification_h noti, notification_text_type_e type, char **text);
+
+
+/**
+ * @brief Sets the timestamp to display on the notification view.
+ * @details The timestamp will be converted to a formatted string and it will be displayed on the set text area.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] type The notification text type
+ * @param[in] time The timestamp
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ */
+int notification_set_time_to_text(notification_h noti, notification_text_type_e type, time_t time);
+
+
+/**
+ * @brief Gets the timestamp from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] type The notification text type
+ * @param[in] time The pointer of time stamp
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ */
+int notification_get_time_from_text(notification_h noti, notification_text_type_e type, time_t *time);
+
+
+/**
+ * @brief Sets the sound type for the notification.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] type The notification sound type
+ * @param[in] path The user sound file path
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_set_sound(noti, NOTIFICATION_SOUND_TYPE_DEFAULT, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_set_sound(notification_h noti, notification_sound_type_e type, const char *path);
+
+
+/**
+ * @brief Gets the sound type from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] type The notification sound type
+ * @param[out] path The user sound file path
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ notification_sound_type_e type = NOTIFICATION_SOUND_TYPE_NONE;
+
+ noti_err = notification_get_sound(noti, &type, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_sound(notification_h noti, notification_sound_type_e *type, const char **path);
+
+
+/**
+ * @brief Sets the vibration type for the notification.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] type The notification vibration type
+ * @param[in] path The user vibration file path
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_set_vibration(noti, NOTIFICATION_VIBRATION_TYPE_DEFAULT, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_set_vibration(notification_h noti, notification_vibration_type_e type, const char *path);
+
+
+/**
+ * @brief Gets the vibrate type from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] type The notification sound type
+ * @param[out] path The user vibration file path
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ notification_vibration_type_e type = NOTIFICATION_VIBRATION_TYPE_NONE;
+
+ noti_err = notification_get_vibration(noti, &type, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_vibration(notification_h noti, notification_vibration_type_e *type, const char **path);
+
+
+/**
+ * @brief Sets the LED displaying option.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] operation The LED notification operation
+ * @param[in] led_argb The notification LED color
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_set_led(noti, NOTIFICATION_LED_OP_ON, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_set_led(notification_h noti, notification_led_op_e operation, int led_argb);
+
+
+/**
+ * @brief Gets the LED displaying option from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] operation The LED notification operation
+ * @param[out] led_argb The notification LED color
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ notification_led_type_e type = NOTIFICATION_LED_OP_OFF;
+
+ noti_err = notification_get_led(noti, &type, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_led(notification_h noti, notification_led_op_e *operation, int *led_argb);
+
+
+/**
+ * @brief Sets the time period of flashing the LED.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] on_ms The time for turning on the LED
+ * @param[in] off_ms The time for turning off the LED
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_set_led_time_period(noti, 100, 100);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_set_led_time_period(notification_h noti, int on_ms, int off_ms);
+
+
+/**
+ * @brief Gets the time period of flashing the LED from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] on_ms The time for turning on the LED
+ * @param[out] off_ms The time for turning on the LED
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int led_on_ms = 0;
+ int led_off_ms = 0;
+
+ noti_err = notification_get_led_time_period(noti, &led_on_ms, &led_off_ms);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_led_time_period(notification_h noti, int *on_ms, int *off_ms);
+
+
+/**
+ * @brief Sets the launch option for a notification.
+ * @details When notification data selected in display application, application launched by app_control_send_launch_request with app_control handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] type Launching option type
+ * @param[in] option App Control handler
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ app_control_h app_control = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ // Do something
+
+ app_control_create(&app_control);
+ app_control_set_app_id(app_control, "org.tizen.app");
+
+ // Do something
+
+ noti_err = notification_set_launch_option(noti, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)app_control);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ app_control_destroy(app_control);
+ notification_free(noti);
+ return;
+ }
+
+ app_control_destroy(app_control);
+}
+ * @endcode
+ */
+int notification_set_launch_option(notification_h noti, notification_launch_option_type type, void *option);
+
+
+/**
+ * @brief Gets the launch option from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks You must release @a app_control using app_control_destroy().
+ * @param[in] noti The notification handle
+ * @param[in] type Launching option type
+ * @param[out] option The pointer of App Control handler
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ app_control_h app_control = NULL;
+ app_control_create(&app_control);
+
+ // Do something
+
+ noti_err = notification_get_launch_option(noti, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)&app_control);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_get_launch_option(notification_h noti, notification_launch_option_type type, void *option);
+
+
+/**
+ * @brief Sets the handler for a specific event.
+ * @details When some event occurs on notification, application launched by app_control_send_launch_request with app_control handle. \n
+ * Setting event handler of a button means that the notification will show the button.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] noti The notification handle
+ * @param[in] event_type Event type
+ * @param[in] event_handler App control 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
+ * @see #notification_event_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ app_control_h app_control = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ // Do something
+
+ app_control_create(&app_control);
+ app_control_set_app_id(app_control, "org.tizen.app");
+
+ // Do something
+
+ noti_err = notification_set_event_handler(noti, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1, app_control);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ app_control_destroy(app_control);
+ notification_free(noti);
+ return;
+ }
+
+ app_control_destroy(app_control);
+}
+ * @endcode
+ */
+int notification_set_event_handler(notification_h noti, notification_event_type_e event_type, app_control_h event_handler);
+
+
+/**
+ * @brief Gets the event handler of a specific event.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @remarks You must release @a app_control using app_control_destroy().
+ * @param[in] noti The notification handle
+ * @param[in] event_type Launching option type
+ * @param[out] event_handler The handler of App Control
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #notification_event_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ app_control_h app_control = NULL;
+ app_control_create(&app_control);
+
+ // Do something
+
+ noti_err = notification_get_event_handler(noti, NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1, &app_control);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_event_handler(notification_h noti, notification_event_type_e event_type, app_control_h *event_handler);
+
+
+/**
+ * @brief Sets the property of the notification.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] flags The property with | operation
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ bundle *b = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_property(noti, NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE | NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_property(notification_h noti, int flags);
+
+
+/**
+ * @brief Gets the property of the notification from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] flags The notification property
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int flags = 0;
+
+ noti_err = notification_get_property(noti, &flags);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_property(notification_h noti, int *flags);
+
+
+/**
+ * @brief Sets applications to display the notification.
+ * @details All display application is enabled(NOTIFICATION_DISPLAY_APP_ALL) if you do not call this API.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] applist The with | operation
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ bundle *b = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_display_applist(noti, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
+ NOTIFICATION_DISPLAY_APP_TICKER | NOTIFICATION_DISPLAY_APP_INDICATOR);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_display_applist(notification_h noti, int applist);
+
+
+/**
+ * @brief Gets the application list displaying the notification from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] applist The display application list
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int applist = 0;
+
+ noti_err = notification_get_display_applist(noti, &applist);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_display_applist(notification_h noti, int *applist);
+
+
+/**
+ * @brief Sets the initial size for the ongoing type.
+ * @details After notification_post() call, the size is not updated.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] size The double type size
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_size(noti, 0.0);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_size(notification_h noti, double size);
+
+
+/**
+ * @brief Gets the progress size.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] size The progress size
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ double size = 0.0;
+
+ noti_err = notification_get_size(noti, &size);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_get_size(notification_h noti, double *size);
+
+
+/**
+ * @brief Sets the initial progress for the ongoing type.
+ * @details After the notification_post() call, the progress is not updated.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] percentage The progress percentage
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_progress(noti, 0.0);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_progress(notification_h noti, double percentage);
+
+
+/**
+ * @brief Gets the progress from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks At the end of the operation, the progress should be @c 1.0.
+ * @param[in] noti The notification handle
+ * @param[out] percentage The progress percentage
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ double percentage = 0.0;
+
+ noti_err = notification_get_progress(noti, &percentage);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_progress(notification_h noti, double *percentage);
+
+
+/**
+ * @brief Sets the layout of the notification view.
+ * @details Caller can set displaying layout of notification.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[in] layout The type of layout
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_ly_type_e
+ */
+int notification_set_layout(notification_h noti, notification_ly_type_e layout);
+
+
+/**
+ * @brief Gets the layout of the notification view from the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] layout The type of layout
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_ly_type_e
+ */
+int notification_get_layout(notification_h noti, notification_ly_type_e *layout);
+
+
+/**
+ * @brief Gets the type of a notification.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification handle
+ * @param[out] type The notification type
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ notification_type_e type;
+
+ noti_err = notification_get_type(noti, &type);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_get_type(notification_h noti, notification_type_e *type);
+
+
+/**
+ * @brief Updates notification data.
+ * @details The updated notification will appear in the notification area.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] noti The notification handle that is created by notification_create()
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @retval #NOTIFICATION_ERROR_NOT_EXIST_ID Priv ID does not exist
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_update(NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_update(notification_h noti);
+
+
+/**
+ * @brief Deletes a notification with the given handle.
+ * @details notification_delete() removes notification data from database and notification_free() releases memory of notification data.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] noti The notification handle
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @retval NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ // Do something
+
+ noti_err = notification_delete(noti);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_delete(notification_h noti);
+
+
+/**
+ * @brief Creates internal structure data and returns a notification handle.
+ * @details Available type is #NOTIFICATION_TYPE_NOTI and #NOTIFICATION_TYPE_ONGOING.
+ * #NOTIFICATION_TYPE_NOTI is remaining notification data even if device is restarted.
+ * #NOTIFICATION_TYPE_ONGOING can display progress on a notification with #NOTIFICATION_LY_ONGOING_PROGRESS layout.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] type The notification type
+ * @return Notification handle(notification_h) on success,
+ * otherwise @c NULL on failure
+ * @retval notification_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @exception #NOTIFICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception #NOTIFICATION_ERROR_IO_ERROR I/O error
+ * @see #notification_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ // Do something
+
+}
+ * @endcode
+ */
+notification_h notification_create(notification_type_e type);
+
+
+/**
+ * @brief Creates a notification clone.
+ * @details Newly created notification handle is returned.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks This cloned notification handle should be freed using notification_free().
+ * @param[in] noti The notification handle
+ * @param[out] clone The newly created notification handle that has same with input @a noti
+ * @return #NOTIFICATION_ERROR_NONE if success,
+ * otherwise any other value if failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #notification_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ notification_h clone = NULL;
+
+ notification_clone(noti, &clone);
+
+ // Do something
+
+}
+ * @endcode
+ */
+int notification_clone(notification_h noti, notification_h *clone);
+
+
+/**
+ * @brief Frees the internal structure data of a notification handle.
+ * @details Internal data of a notification handle is released. Data of the inserted notification is not deleted.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti The notification 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
+ * @pre Notification handle should be created by notification_create().
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ // Do something
+
+ noti_err = notification_free(noti);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_free(notification_h noti);
+
+
+/**
+ * @brief Sets the tag of the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti Notification handle
+ * @param[in] tag Tag for loading notification handle
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see notification_get_tag()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ // Do something
+
+ noti_err = notification_set_tag(noti, tag);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_set_tag(notification_h noti, const char *tag);
+
+
+/**
+ * @brief Gets the tag of the notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] noti Notification handle
+ * @param[out] tag Tag for loading notification handle
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see notification_set_tag()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ const char *tag = NULL;
+
+ // Do something
+
+ noti_err = notification_get_tag(noti, &tag);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_tag(notification_h noti, const char **tag);
+
+
+/**
+ * @brief Loads a notification from the notification's database with the tag.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] tag Tag for loading notification handle
+ * @return Notification handle(notification_h) on success,
+ * NULL on failure
+ * @retval notification_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @exception #NOTIFICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @see #notification_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+
+ noti = notification_load_by_tag(tag);
+ if (noti == NULL)
+ return;
+
+ // Do something
+
+}
+ * @endcode
+ */
+notification_h notification_load_by_tag(const char *tag);
+
+
+/**
+ * @brief Deletes all notifications of the given type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] type Notification type
+ * @return #NOTIFICATION_ERROR_NONE if success,
+ * other value if failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_delete_all(NOTIFICATION_TYPE_NOTI);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_delete_all(notification_type_e type);
+
+
+/**
+ * @brief Posts a notification.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] noti Notification handle
+ * @return #NOTIFICATION_ERROR_NONE if success,
+ * other value if 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
+ * @pre Notification handle should be created by notification_create().
+ * @post notification_free().
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_post(noti);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_post(notification_h noti);
+
+
+/**
+ * @brief Gets the package name of the notification.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] noti Notification handle
+ * @param[out] pkgname The package name of the notification
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise a negative error value
+ * @retval NOTIFICATION_ERROR_NONE Success
+ * @retval NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ char *pkgname = NULL;
+
+ // Do something
+
+ noti_err = notification_get_pkgname(noti, &pkgname);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_pkgname(notification_h noti, char **pkgname);
+
+
+/**
+ * @brief Adds a button on the notification.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] noti Notification handle
+ * @param[in] button_index Button index
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise a negative error value
+ * @retval NOTIFICATION_ERROR_NONE Success
+ * @retval NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ char *pkgname = NULL;
+
+ // Do something
+
+ noti_err = notification_add_button(noti, NOTIFICATION_BUTTON_1);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_add_button(notification_h noti, notification_button_index_e button_index);
+
+
+/**
+ * @brief Removes a button on the notification.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] noti Notification handle
+ * @param[in] button_index Button index
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise a negative error value
+ * @retval NOTIFICATION_ERROR_NONE Success
+ * @retval NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ char *pkgname = NULL;
+
+ // Do something
+
+ noti_err = notification_remove_button(noti, NOTIFICATION_BUTTON_1);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_remove_button(notification_h noti, notification_button_index_e button_index);
+
+
+/**
+ * @brief Sets the 'auto remove' option of the active notification.
+ * @details The 'auto remove' option lets the active notification be removed several seconds after it shows. Default value is true.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @remarks When 'auto_remove' is set as false, the active notification will not be removed
+ * as long as the user removes the active notification or the app which posted the active notification removes the active notification.
+ * @param[in] noti Notification handle
+ * @param[in] auto_remove Auto remove option
+ * @return #NOTIFICATION_ERROR_NONE On success,
+ * other value if failure
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #notification_h
+ * @see #notification_get_auto_remove
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ // Do something
+
+ noti_err = notification_set_auto_remove(noti, false);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_set_auto_remove(notification_h noti, bool auto_remove);
+
+
+/**
+ * @brief Gets the 'auto remove' option of the active notification.
+ * @details The 'auto remove' option lets the active notification be removed several seconds after it shows. Default value is true.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] noti Notification handle
+ * @param[out] auto_remove Auto remove option
+ * @return #NOTIFICATION_ERROR_NONE On success, other value on failure
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #notification_h
+ * @see #notification_get_auto_remove
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ bool auto_remove;
+
+ // Do something
+
+ noti_err = notification_get_auto_remove(noti, &auto_remove);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_auto_remove(notification_h noti, bool *auto_remove);
+
+
+/**
+ * @brief Saves a notification template to the notification database.
+ * @details An application can save the created notification as a template for later reuse.
+ * If the template has the same name as a saved one, the saved template will be overwritten.
+ * A saved template can be loaded only by the application which saved it.
+ * All templates are removed when the application package is uninstalled.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @remarks The number of templates is limited to 10.
+ * When you try to add more than 10 templates, #NOTIFICATION_ERROR_MAX_EXCEEDED will be returned.
+ * @param[in] noti Notification handle
+ * @param[in] template_name Template name
+ * @return #NOTIFICATION_ERROR_NONE On success, other value on failure
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #NOTIFICATION_ERROR_IO_ERROR I/O error
+ * @retval #NOTIFICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED The Permission denied
+ * @retval #NOTIFICATION_ERROR_MAX_EXCEEDED Max notification count exceeded
+ * @see #notification_h
+ * @see notification_create_from_template()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ notification_h noti = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ // add the content you want to use for the template.
+
+ noti_err = notification_save_as_template(noti, "CALL_ACCEPT");
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_free(noti);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_save_as_template(notification_h noti, const char *template_name);
+
+
+/**
+ * @brief Loads a notification template from the notification database.
+ * @details An application can load a saved template and post it.
+ * An application can load only templates that it has saved.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @remarks The returned handle should be destroyed using notification_free().
+ * The specific error code can be obtained using get_last_result().
+ * Error codes are described in the Exception section.
+ * If an invalid template name is given, the result will be set to #NOTIFICATION_ERROR_FROM_DB.
+ * @param[in] template_name Template name
+ * @return Notification handle on success, NULL on failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @exception #NOTIFICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @exception #NOTIFICATION_ERROR_FROM_DB Error from DB query
+ * @see #notification_h
+ * @see notification_save_as_template()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+
+ noti = notification_create_from_template("CALL_ACCEPT");
+ if (noti == NULL)
+ return;
+
+}
+ * @endcode
+ */
+notification_h notification_create_from_template(const char *template_name);
+
+
+/**
+ * @brief Gets notification block state.
+ * @details The user can set the notification block state in settings.
+ * The block state indicates whether or not notifications can be posted.
+ * Additionally only notifications to the notification panel are
+ * allowed in "Do not disturb mode". Sound, Vibrate and
+ * Active/Instant notifications are blocked.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[out] state Notification block state
+ * @return #NOTIFICATION_ERROR_NONE On success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #NOTIFICATION_ERROR_OUT_OF_MEMORY out of memory
+ * @retval #NOTIFICATION_ERROR_IO_ERROR I/O Error
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #NOTIFICATION_ERROR_SERVICE_NOT_READY No response from notification service
+ * @see #notification_block_state_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ notification_block_state_e state;
+
+ // Do something
+
+ noti_err = notification_get_noti_block_state(&state);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+ * @endcode
+ */
+int notification_get_noti_block_state(notification_block_state_e *state);
+
+
+/**
+ * @brief Sets a text input box to reply directly on the notification.
+ * @details When you add a text input to the active notification, the notification UI will show a text input with a button.
+ * So, the user can enter any text and press the button to confirm the text as a input.
+ * You can edit some UI component that is related to the text input.
+ * First, you can add placeholder text to guide the user using notification_set_text() with #NOTIFICATION_TEXT_TYPE_TEXT_INPUT_PLACEHOLDER type.
+ * You also can edit button for the text input.
+ * For setting just a text to the button, you can set the text using notification_set_text() with #NOTIFICATION_TEXT_TYPE_TEXT_INPUT_BUTTON type.
+ * If you want to show image button, you can set an image for the button using notification_set_image() with #NOTIFICATION_IMAGE_TYPE_TEXT_INPUT_BUTTON type.
+ *
+ * Note that you should set an app_control for handling the event for user input using notification_set_event_handler().
+ * #NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON is the event type for the text input.
+ * You can get the text the user enters in the app_control handle that is passed as a result of the event.
+ * The app_control will contain APP_CONTROL_DATA_TEXT key, so you can get the text using app_control_get_extra_data() using APP_CONTROL_DATA_TEXT key.
+ * The value will contain the text user enters.
+ *
+ * Note that you are able to make the switching button to the text input box.
+ * You have to set the app_control which you will set in a text input box to the switching button.
+ * Refer to the second sample code.
+ * @since_tizen 3.0
+ * @param[in] noti Notification handle
+ * @param[in] text_input_max_length The maximum value which can be inputted
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ notification_h noti = NULL;
+ app_control = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_text_input(noti, 160);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_text(noti,
+ NOTIFICATION_TEXT_TYPE_TEXT_INPUT_PLACEHOLDER,
+ "Text message",
+ NULL,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_text(noti,
+ NOTIFICATION_TEXT_TYPE_TEXT_INPUT_BUTTON,
+ "SEND",
+ NULL,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_display_applist(noti,
+ NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY | NOTIFICATION_DISPLAY_APP_ACTIVE);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ // Do something
+
+ noti_err = app_control_create(&app_control);
+ if (noti_err != APP_CONTROL_ERROR_NONE)
+ return;
+
+ noti_err = app_control_set_app_id(app_control, appid);
+ if (noti_err != APP_CONTROL_ERROR_NONE)
+ return;
+
+ noti_err = app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
+ if (noti_err != APP_CONTROL_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_event_handler(noti,
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON,
+ app_control);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = app_control_destroy(app_control);
+ if (noti_err != APP_CONTROL_ERROR_NONE)
+ return;
+
+ noti_err = notification_post(noti);
+ if(noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+}
+
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ notification_h noti = NULL;
+ app_control = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_text_input(noti, 160);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_text(noti,
+ NOTIFICATION_TEXT_TYPE_TEXT_INPUT_PLACEHOLDER,
+ "Text message",
+ NULL,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_text(noti,
+ NOTIFICATION_TEXT_TYPE_TEXT_INPUT_BUTTON,
+ "SEND",
+ NULL,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_add_button(notification, NOTIFICATION_BUTTON_1);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_text(notification,
+ NOTIFICATION_TEXT_TYPE_BUTTON_1,
+ "reply",
+ NULL,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_display_applist(noti,
+ NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY | NOTIFICATION_DISPLAY_APP_ACTIVE);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ // Do something
+
+ noti_err = app_control_create(&app_control);
+ if (noti_err != APP_CONTROL_ERROR_NONE)
+ return;
+
+ noti_err = app_control_set_app_id(app_control, appid);
+ if (noti_err != APP_CONTROL_ERROR_NONE)
+ return;
+
+ noti_err = app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
+ if (noti_err != APP_CONTROL_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_event_handler(notification,
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1,
+ app_control);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_event_handler(noti,
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON,
+ app_control);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = app_control_destroy(app_control);
+ if (noti_err != APP_CONTROL_ERROR_NONE)
+ return;
+
+ noti_err = notification_post(noti);
+ if(noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_set_text_input(notification_h noti, int text_input_max_length);
+
+
+/**
+ * @brief Sets the image height for the extended notification.
+ * @details The image is shown under the notification's text. The application can set the image height.
+ * The image is modified to fit into the height set by this function.
+ * The image can be scaled down and/or cropped.
+ * If @a height is 0, the default value is used. The default height depends on the screen size.
+ * @since_tizen 4.0
+ * @param[in] noti The notification handle
+ * @param[in] height The image height
+ * @return #NOTIFICATION_ERROR_NONE On success,
+ * otherwise a negative error value
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see notification_get_extension_image_size()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL)
+ return;
+
+ noti_err = notification_set_text(noti,
+ NOTIFICATION_TEXT_TYPE_CONTENT_EXTENTION,
+ "message",
+ NULL,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_image(noti,
+ NOTIFICATION_IMAGE_TYPE_EXTENTION,
+ image_path);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_layout(noti, NOTIFICATION_LY_EXTENTION);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ noti_err = notification_set_extension_image_size(noti, 20);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ // Do something
+}
+ * @endcode
+ */
+int notification_set_extension_image_size(notification_h noti, int height);
+
+
+/**
+ * @brief Gets the image height for the extended notification.
+ * @since_tizen 4.0
+ * @param[in] noti The notification handle
+ * @param[out] height The image height
+ * @return #NOTIFICATION_ERROR_NONE On success, otherwise a negative error value
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see notification_set_extension_image_size()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int height;
+
+ // Do something
+
+ noti_err = notification_get_extension_image_size(noti, &height);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_get_extension_image_size(notification_h noti, int *height);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __NOTIFICATION_H__ */
+
diff --git a/notification/include/notification_db.h b/notification/include/notification_db.h
new file mode 100644
index 0000000..219e507
--- /dev/null
+++ b/notification/include/notification_db.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_DB_H__
+#define __NOTIFICATION_DB_H__
+
+#include <bundle.h>
+#include <sqlite3.h>
+#include <tzplatform_config.h>
+
+#define DBPATH tzplatform_mkpath(TZ_SYS_DB, ".notification.db")
+#define NOTIFICATION_QUERY_MAX 4096
+#define NOTIFICATION_EMPTY_STR ""
+#define NOTIFICATION_CHECK_STR(p) ((p) ? (p) : NOTIFICATION_EMPTY_STR)
+
+sqlite3 *notification_db_open();
+int notification_db_close(sqlite3 **db);
+int notification_db_exec(sqlite3 *db, const char *query, int *num_changes);
+char *notification_db_column_text(sqlite3_stmt *stmt, int col);
+bundle *notification_db_column_bundle(sqlite3_stmt *stmt, int col);
+int notification_db_init();
+
+#endif /* __NOTIFICATION_DB_H__ */
+
diff --git a/notification/include/notification_debug.h b/notification/include/notification_debug.h
new file mode 100644
index 0000000..f3f0514
--- /dev/null
+++ b/notification/include/notification_debug.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_DEBUG_H__
+#define __NOTIFICATION_DEBUG_H__
+
+#define LOG_TAG "NOTIFICATION"
+#include <dlog.h>
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__ ((visibility("default")))
+#endif
+
+#ifndef _DLOG_H_
+#include <stdio.h>
+
+#define DBG(fmt , args...) \
+ do { \
+ printf("[D][%s : %d] "fmt"\n", __func__, __LINE__, ##args); \
+ } while (0)
+
+#define INFO(fmt , args...) \
+ do { \
+ printf("[I][%s : %d] "fmt"\n", __func__, __LINE__, ##args); \
+ } while (0)
+
+#define WARN(fmt , args...) \
+ do { \
+ printf("[W][%s : %d] "fmt"\n", __func__, __LINE__, ##args); \
+ } while (0)
+
+#define ERR(fmt , args...) \
+ do { \
+ printf("[E][%s : %d] "fmt"\n", __func__, __LINE__, ##args); \
+ } while (0)
+
+#else /* _DLOG_H_ */
+
+#define DBG(fmt , args...) \
+ do { \
+ SECURE_LOGD("[%s : %d] "fmt"\n", __func__, __LINE__, ##args); \
+ } while (0)
+
+#define INFO(fmt , args...) \
+ do { \
+ SECURE_LOGI("[%s : %d] "fmt"\n", __func__, __LINE__, ##args); \
+ } while (0)
+
+#define WARN(fmt , args...) \
+ do { \
+ SECURE_LOGW("[%s : %d] "fmt"\n", __func__, __LINE__, ##args); \
+ } while (0)
+
+#define ERR(fmt , args...) \
+ do { \
+ SECURE_LOGE("[%s : %d] "fmt"\n", __func__, __LINE__, ##args); \
+ } while (0)
+
+#endif /* _DLOG_H_ */
+
+#endif /* __NOTIFICATION_DEBUG_H__ */
+
diff --git a/notification/include/notification_error.h b/notification/include/notification_error.h
new file mode 100644
index 0000000..91f768d
--- /dev/null
+++ b/notification/include/notification_error.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+
+#ifndef __NOTIFICATION_ERROR_H__
+#define __NOTIFICATION_ERROR_H__
+
+
+#include <tizen.h>
+
+
+/**
+ * @file notification_error.h
+ */
+
+
+/**
+ * @addtogroup NOTIFICATION_MODULE
+ * @{
+ */
+
+
+/**
+ * @brief Enumeration for notification errors.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_error {
+ NOTIFICATION_ERROR_NONE = TIZEN_ERROR_NONE, /**< Success */
+ NOTIFICATION_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ NOTIFICATION_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+ NOTIFICATION_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< I/O error */
+ NOTIFICATION_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+ NOTIFICATION_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Function not implemented (@b Since: @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif) */
+ NOTIFICATION_ERROR_FROM_DB = TIZEN_ERROR_NOTIFICATION | 0x01, /**< Error from DB query */
+ NOTIFICATION_ERROR_ALREADY_EXIST_ID = TIZEN_ERROR_NOTIFICATION | 0x02, /**< Already exist private ID */
+ NOTIFICATION_ERROR_FROM_DBUS = TIZEN_ERROR_NOTIFICATION | 0x03, /**< Error from DBus */
+ NOTIFICATION_ERROR_NOT_EXIST_ID = TIZEN_ERROR_NOTIFICATION | 0x04, /**< Not exist private ID */
+ NOTIFICATION_ERROR_SERVICE_NOT_READY = TIZEN_ERROR_NOTIFICATION | 0x05, /**< No response from notification service */
+ NOTIFICATION_ERROR_MAX_EXCEEDED = TIZEN_ERROR_NOTIFICATION | 0x06, /**< Max notification count exceeded (@b Since: 3.0) */
+} notification_error_e;
+
+
+/**
+ * @}
+ */
+
+
+#endif /* __NOTIFICATION_ERROR_H__ */
+
diff --git a/notification/include/notification_group.h b/notification/include/notification_group.h
new file mode 100644
index 0000000..27c326a
--- /dev/null
+++ b/notification/include/notification_group.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_GROUP_H__
+#define __NOTIFICATION_GROUP_H__
+
+#include <notification.h>
+
+NOTIFICATION_DEPRECATED_API int notification_group_set_title(
+ const char *app_id, int group_id, const char *title,
+ const char *loc_title,
+ notification_count_display_type_e count_display);
+
+NOTIFICATION_DEPRECATED_API int notification_group_get_title(
+ const char *app_id, int group_id, char **ret_title,
+ char **ret_loc_title,
+ notification_count_display_type_e *count_display);
+
+NOTIFICATION_DEPRECATED_API int notification_group_set_content(
+ const char *app_id, int group_id, const char *content,
+ const char *loc_content,
+ notification_count_display_type_e count_display);
+
+NOTIFICATION_DEPRECATED_API int notification_group_get_content(
+ const char *app_id, int group_id, char **ret_content,
+ char **ret_loc_content,
+ notification_count_display_type_e *count_display);
+
+NOTIFICATION_DEPRECATED_API int notification_group_set_badge(
+ const char *app_id, int group_id, int count);
+
+NOTIFICATION_DEPRECATED_API int notification_group_get_badge(
+ const char *app_id, int group_id, int *count);
+
+#endif /* __NOTIFICATION_GROUP_H__ */
+
diff --git a/notification/include/notification_internal.h b/notification/include/notification_internal.h
new file mode 100644
index 0000000..194405d
--- /dev/null
+++ b/notification/include/notification_internal.h
@@ -0,0 +1,1506 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_INTERNAL_H__
+#define __NOTIFICATION_INTERNAL_H__
+#include <glib.h>
+#include <sys/types.h>
+
+#include <notification_error.h>
+#include <notification_type.h>
+#include <notification_list.h>
+#include <notification_type_internal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup NOTIFICATION_INTERNAL
+ * @{
+ */
+
+#define NOTIFICATION_ERROR (notification_error_quark())
+
+GQuark notification_error_quark(void);
+
+/**
+ * @brief This function add deferred task. The registered task will be executed when notification service become ready.
+ * @param[in] deferred_task_cb The callback function
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @see #notification_error_e
+ * @see notification_is_service_ready()
+ */
+int notification_add_deferred_task(
+ void (*deferred_task_cb)(void *data), void *user_data);
+
+/**
+ * @brief This function remove deferred task.
+ * @param[in] deferred_task_cb The callback function
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @see #notification_error_e
+ * @see notification_is_service_ready()
+ */
+int notification_del_deferred_task(
+ void (*deferred_task_cb)(void *data));
+
+/**
+ * @brief This function will be removed.
+ * @see notification_register_detailed_changed_cb()
+ */
+int notification_resister_changed_cb(
+ void (*changed_cb)(void *data, notification_type_e type),
+ void *user_data);
+int notification_resister_changed_cb_for_uid(
+ void (*changed_cb)(void *data, notification_type_e type),
+ void *user_data, uid_t uid);
+
+/**
+ * @brief This function will be removed.
+ * @see notification_unregister_detailed_changed_cb()
+ */
+int notification_unresister_changed_cb(
+ void (*changed_cb)(void *data, notification_type_e type));
+int notification_unresister_changed_cb_for_uid(
+ void (*changed_cb)(void *data, notification_type_e type), uid_t uid);
+
+/**
+ * @brief Updates the progress of the inserted notification. This only works for the ongoing notification (NOTIFICATION_TYPE_ONGOING).
+ * @details The Notification view on the notification area could be updated.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] noti Notification handle or NULL if priv_id is valid
+ * @param[in] priv_id Private ID
+ * @param[in] progress Percentage value of progressive data
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification_internal.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_update_progress(NULL, APP_NOTI_PRIV_ID, 0.6);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_update_progress(notification_h noti, int priv_id, double progress);
+
+/**
+ * @brief Updates the size of inserted notification data. This only works for the ongoing notification (NOTIFICATION_TYPE_ONGOING).
+ * @details Notification view on notification area could be updated.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] noti Notification handle or NULL if priv_id is valid
+ * @param[in] priv_id Private ID
+ * @param[in] size Bytes of progressive data
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification_internal.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_update_size(NULL, APP_NOTI_PRIV_ID, 3000000);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_update_size(notification_h noti, int priv_id, double size);
+
+/**
+ * @brief Updates the content of the inserted notification data. This is only for the ongoing notification (NOTIFICATION_TYPE_ONGOING).
+ * @details Notification view on notification area could be updated.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] noti Notification handle or NULL if priv_id is valid
+ * @param[in] priv_id Private ID
+ * @param[in] content Text to update
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification_internal.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_update_content(NULL, APP_NOTI_PRIV_ID, "updated string");
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_update_content(notification_h noti, int priv_id, const char *content);
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_set_image()
+ */
+int notification_set_icon(notification_h noti, const char *icon_path) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_get_image()
+ */
+int notification_get_icon(notification_h noti, char **icon_path) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_set_text()
+ */
+int notification_set_title(notification_h noti, const char *title, const char *loc_title) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_get_text()
+ */
+int notification_get_title(notification_h noti, char **title, char **loc_title) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_set_text()
+ */
+int notification_set_content(notification_h noti, const char *content, const char *loc_content) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_get_text()
+ */
+int notification_get_content(notification_h noti, char **content, char **loc_content) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be removed.
+ * @see notification_set_execute_option()
+ */
+int notification_set_application(notification_h noti, const char *app_id) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be removed.
+ * @see notification_get_execute_option()
+ */
+int notification_get_application(notification_h noti, char **app_id) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_set_execute_option()
+ */
+int notification_set_args(notification_h noti, bundle *args, bundle *group_args) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_get_execute_option()
+ */
+int notification_get_args(notification_h noti, bundle **args, bundle **group_args) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function is deprecated.
+ * @see notification_get_grouping_list()
+ */
+int notification_get_grouping_list(notification_type_e type, int count, notification_list_h *list) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_delete_by_priv_id()
+ */
+int notification_delete_group_by_group_id(const char *app_id, notification_type_e type, int group_id) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_delete_by_priv_id()
+ */
+int notification_delete_group_by_priv_id(const char *app_id, notification_type_e type, int priv_id) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ */
+int notifiation_clear(notification_type_e type) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ */
+int notification_get_count(notification_type_e type, const char *app_id, int group_id, int priv_id, int *count) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief Gets the numbers of all notifications.
+ * @since tizen 4.0
+ * @param[in] type The type of notification
+ * @param[out] count The numbers of all notifications
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @retval #NOTIFICATION_ERROR_IO_ERROR I/O Error
+ * @retval #NOTIFICATION_ERROR_FROM_DB Error from DB
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ */
+int notification_get_all_count(notification_type_e type, int *count);
+int notification_get_all_count_for_uid(notification_type_e type, int *count, uid_t uid);
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @details Use only for the notification tray's clear button operation.
+ * @param[in] type Notification type
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_clear(NOTIFICATION_TYPE_NOTI);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_clear(notification_type_e type) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @return 1 on ready, other value on not ready
+ */
+int notification_is_service_ready(void) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @param[in] list Notification list handle
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre notification_get_grouping_list() or notification_get_detail_list().
+ * @see #notification_op
+ */
+int notification_op_get_data(notification_op *noti_op, notification_op_data_type_e type, void *data) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_set_app_id()
+ */
+int notification_set_pkgname(notification_h noti, const char *pkgname) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief Sets caller's app_id.
+ * @details caller_app_id is set automatically when notification_create() is called. We do not recommend to use this API.
+ * @since_tizen 4.0
+ * @param[in] noti Notification handle
+ * @param[in] app_id Caller application id
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_app_id(noti, "org.tizen.phone");
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_app_id(notification_h noti, const char *app_id);
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @details If @a app_id is NULL, caller_app_id is set internally.
+ * @param[in] app_id Caller application ID or NULL
+ * @param[in] type Notification type
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_NOTI);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_delete_all_by_type(const char *app_id, notification_type_e type) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @details If @a app_id is NULL, caller_app_id is set internally.
+ * @param[in] app_id Caller application ID or NULL
+ * @param[in] type Notification type
+ * @param[in] priv_id Priv ID
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+ {
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NOTI, APP_PRIV_ID);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_delete_by_priv_id(const char *app_id, notification_type_e type, int priv_id) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @details When notification data selected in display application, application launched by appsvc_run_service with service_handle.
+ * @param[in] noti Notification handle
+ * @param[in] type Notification execute type
+ * @param[in] text Basic text for button
+ * @param[in] key Value for localized text
+ * @param[in] service_handle Appsvc bundle data
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ bundle *b = NULL;
+
+ ...
+
+ b = bundle_create();
+ appsvc_set_operation(b, APPSVC_OPERATION_VIEW);
+ appsvc_set_uri(b,"http://www.samsung.com");
+
+ noti_err = notification_set_execute_option(noti, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, b);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+
+ bundle_free(b);
+}
+ * @endcode
+ */
+int notification_set_execute_option(notification_h noti,
+ notification_execute_type_e type,
+ const char *text,
+ const char *key,
+ bundle *service_handle) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @remarks ID is valid only after inserting the notification.
+ * @param[in] noti Notification handle
+ * @param[out] group_id Group ID
+ * @param[out] priv_id Private ID
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+ ...
+ {
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int group_id, priv_id;
+
+ noti_err = notification_get_id(noti, &group_id, &priv_id);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+ }
+ * @endcode
+ */
+int notification_get_id(notification_h noti, int *group_id, int *priv_id) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief Sets priv_id of the notification.
+ * @since_tizen 4.0
+ * @param[in] noti Notification handle
+ * @param[in] priv_id Private ID
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int notification_set_priv_id(notification_h noti, int priv_id);
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @param[in] type Notification type
+ * @param[in] group_id Group ID
+ * @param[in] priv_id Priv ID
+ * @return Notification handle(#notification_h) on success, NULL on failure
+ * @retval #notification_h Success
+ * @retval NULL Failure
+ * @see #notification_type_e
+ * @see #notification_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+
+ noti = notification_load("org.tizen.app", priv_id);
+ if (noti == NULL) {
+ return;
+ }
+ ...
+}
+ * @endcode
+ */
+notification_h notification_load(char *app_id, int priv_id) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @details Available types are #NOTIFICATION_TYPE_NOTI and #NOTIFICATION_TYPE_ONGOING.
+ * #NOTIFICATION_TYPE_NOTI is remaining notification data even if device is restarted.
+ * #NOTIFICATION_TYPE_ONGOING can display progressive feather, but notification data is removed after device is restarted.
+ * If group_id is #NOTIFICATION_GROUP_ID_NONE, notification data is not grouped. #NOTIFICATION_GROUP_ID_DEFAULT,
+ * notification data is grouped with same title. Positive number ( > 0 ) is grouped with same number.
+ * If priv_id is #NOTIFICATION_PRIV_ID_NONE, priv_id is set internally and return it when notification_insert() call.
+ * Positive number and zero ( >= 0 ) is application set private ID. These ID should have be unique each application package.
+ * @param[in] type Notification type
+ * @param[in] group_id Group ID
+ * @param[in] priv_id Priv ID
+ * @return Notification handle(#notification_h) on success, NULL on failure
+ * @retval #notification_h Success
+ * @retval NULL Failure
+ * @see #notification_type_e
+ * @see #notification_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+
+ noti = notification_new(NOTIFICATION_TYPE_NOTI, APP_GROUP_ID, NOTIFICATION_PRIV_ID_NONE);
+ if (noti == NULL) {
+ return;
+ }
+ ...
+}
+ * @endcode
+ */
+notification_h notification_new(notification_type_e type,
+ int group_id, int priv_id) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief This function will be deprecated.
+ * @param[in] noti Notification handle
+ * @param[in] type Notification execute type
+ * @param[out] text Text for button
+ * @param[out] service_handle Appsvc bundle data
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ bundle *b = NULL;
+
+ ...
+
+ noti_err = notification_get_execute_option(noti, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, &b);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_execute_option(notification_h noti,
+ notification_execute_type_e type,
+ const char **text,
+ bundle **service_handle) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @internal
+ * @brief Inserts a notification.
+ * @details The notification will be inserted to the database and then it will appear in the notification area.
+ * When notification_create() is called, if priv_id is #NOTIFICATION_PRIV_ID_NONE, priv_id returns the internally set priv_id.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] noti The notification handle
+ * @param[out] priv_id The private ID
+ * @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
+ * @pre Notification handle should be created by notification_create().
+ * @post notification_free().
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_insert(noti, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_insert(notification_h noti, int *priv_id);
+int notification_insert_for_uid(notification_h noti, int *priv_id, uid_t uid);
+
+/**
+ * @internal
+ * @brief Updates a notification, asynchronously.
+ * @details The updated notification will appear in the notification area.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @remarks This function updates the notification asynchronously.
+ * @param[in] noti The notification handle that is created by notification_create()
+ * @param[in] result_cb The callback called when an update completed
+ * @param[in] user_data The user data which you want to use in callback
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @retval #NOTIFICATION_ERROR_NOT_EXIST_ID Priv ID does not exist
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_update_async(NULL, result_cb, data);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_update_async(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data), void *user_data);
+int notification_update_async_for_uid(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data), void *user_data, uid_t uid);
+
+/**
+ * @internal
+ * @brief Registers a callback for all notification events.
+ * @details The registered callback could be called for all notification events.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] changed_cb The callback function
+ * @param[in] user_data The user data
+ * @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_unregister_detailed_changed_cb()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ noti_err = notification_register_detailed_changed_cb(app_changed_cb, user_data);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_register_detailed_changed_cb(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data);
+int notification_register_detailed_changed_cb_for_uid(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data, uid_t uid);
+
+/**
+ * @internal
+ * @brief Unregisters a callback for all notification events.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] changed_cb The callback function
+ * @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_register_detailed_changed_cb()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ noti_err = notification_register_detailed_changed_cb(app_changed_cb, user_data);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_unregister_detailed_changed_cb(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data);
+int notification_unregister_detailed_changed_cb_for_uid(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data, uid_t uid);
+
+/**
+ * @brief Sets the default button to display highlight on the notification.
+ * @since_tizen 3.0
+ * @remarks If you want to default button is off, you set that index is zero
+ * @param[in] noti The notification handle
+ * @param[in] index The notification button index
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_button_index_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if(noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_default_button(noti, NOTIFICATION_BUTTON_1);
+ if(noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+
+ ...
+
+}
+ * @endcode
+ */
+int notification_set_default_button(notification_h noti,
+ notification_button_index_e index);
+
+/**
+ * @brief Gets the default button to display highlight on the notification.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[out] index The notification button index
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_button_index_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ notification_button_index_e index;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if(noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_default_button(noti, &index);
+ if(noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+
+ ...
+}
+ * @endcode
+ */
+int notification_get_default_button(notification_h noti,
+ notification_button_index_e *index);
+
+/**
+ * @brief Gets the notification ongoing value type.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[out] type The notification ongoing value type
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_ongoing_value_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ notification_ongoing_value_type_e type;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_get_ongoing_value_type(noti, &type);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_ongoing_value_type(notification_h noti,
+ notification_ongoing_value_type_e *type);
+
+/**
+ * @brief Sets the notification ongoing value type.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[in] type The notification ongoing value type
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_ongoing_value_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ notification_ongoing_value_type_e type;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ type = NOTIFICATION_ONGOING_VALUE_TYPE_TIME;
+
+ noti_err = notification_set_ongoing_value_type(noti, type);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_ongoing_value_type(notification_h noti,
+ notification_ongoing_value_type_e type);
+
+/**
+ * @brief Gets the notification ongoing time when ongoint type value is set #NOTIFICATION_ONGOING_VALUE_TYPE_TIME.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[out] current The ongoing current time
+ * @param[out] duration The ongoing duration time
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_ongoing_value_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int current;
+ int duration;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_get_ongoing_time(noti, &current, &duration);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_ongoing_time(notification_h noti, int *current, int *duration);
+
+/**
+ * @brief Sets the notification ongoing time when ongoint type value is set #NOTIFICATION_ONGOING_VALUE_TYPE_TIME.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[in] current The ongoing current time
+ * @param[in] duration The ongoing duration time
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_ongoing_value_type_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int current;
+ int duration;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ current = 0;
+ duration = 30;
+
+ noti_err = notification_set_ongoing_time(noti, current, duration)
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_ongoing_time(notification_h noti, int current, int duration);
+
+/**
+ * @brief Gets timeout value in second when the notification can be hidden from the viewer.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[out] timeout The timeout time(sec)
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_event_type_extension_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int timeout;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_get_hide_timeout(noti, &timeout)
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_hide_timeout(notification_h noti, int *timeout);
+
+/**
+ * @brief Sets timeout value in second when the notification can be hidden from the viewer.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[in] timeout The timeout time(sec)
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @see #notification_event_type_extension_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_hide_timeout(noti, 10)
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_hide_timeout(notification_h noti, int timeout);
+
+/**
+ * @brief Gets timeout value in second when the notification can be deleted from the viewer.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[out] timeout The timeout time(sec)
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int timeout;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_get_delete_timeout(noti, &timeout)
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_delete_timeout(notification_h noti, int *timeout);
+
+/**
+ * @brief Sets timeout value in second when the notification can be deleted from the viewer.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[in] timeout The timeout time(sec)
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_delete_timeout(noti, 10)
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_delete_timeout(notification_h noti, int timeout);
+
+typedef void (*event_handler_cb)(notification_h noti, int event_type, void *userdata);
+
+/**
+ * @brief Posts a notification with event handler callback.
+ * @details The registered callback could be called when take notification event
+ * and the callback is automatically deleted when notification you posted is deleted.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @remarks Providing one event callback for each notification handle and distinguish the event by parameter.
+ * @param[in] noti The notification handle
+ * @param[in] cb The event handler callback function
+ * @param[in] userdata The user data
+ * @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_IO_ERROR I/O Error
+ * @retval #NOTIFICATION_PERMISSION_DENIED Permission denied
+ * @pre Notification handle should be created by notification_create().
+ * @par Sample code:
+ * @code
+#include <notification.h>
+
+static void event_callback(notification_h noti, int event_type, void *userdata)
+{
+ ...
+}
+
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_post_with_event_cb(noti, event_callback, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+
+ ...
+
+ notification_free(noti);
+}
+ * @endcode
+ */
+int notification_post_with_event_cb(notification_h noti, event_handler_cb cb, void *userdata);
+int notification_post_with_event_cb_for_uid(notification_h noti,
+ event_handler_cb cb, void *userdata, uid_t uid);
+
+/**
+ * @brief Sends a event type to an application that posted notification.
+ * @details Sends occured event from viewer application to an application.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] noti The notification handle
+ * @param[in] event_type The event type
+ * @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_IO_ERROR I/O Error
+ * @retval #NOTIFICATION_PERMISSION_DENIED Permission denied
+ * @see #notification_event_type_e
+ * @see #notification_event_type_extension_e
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ int noti_err;
+ int event_type;
+
+ ...
+
+ event_type = NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER;
+
+ noti_err = notification_send_event(noti, event_type);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_send_event(notification_h noti, int event_type);
+int notification_send_event_by_priv_id(int priv_id, int event_type);
+
+/**
+ * @brief Gets the event flag.
+ * @details When you create a notification handle, a default value of event flag is false.
+ * The flag automatically set true when post a notification using notification_post_with_event_cb().
+ * The viewer application for showing the notifications can use this API to check if it needs to call
+ * notification_send_event() to sends event of notification for making the callback of the processes
+ * that have posted notification to be called. Call notification_send_event()
+ * when the notification_get_event_flag() tells that the @event_flag is true.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[out] event_flag The event flag
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Notification handle should be created by notification_create().
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err;
+ bool event_flag;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_get_event_flag(noti, &event_flag);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+
+ ...
+
+ notification_free(noti);
+}
+ * @endcode
+ */
+int notification_get_event_flag(notification_h noti, bool *event_flag);
+
+/**
+ * @brief Gets whether sending event is available.
+ * @details If the application is terminated, registered callback isn't called
+ * for event sent by other process. So you need to check whether the
+ * callback can be called before sending event.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[out] available The value whether sending event is available
+ * @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_IO_ERROR I/O Error
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #NOTIFICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #NOTIFICATION_ERROR_SERVICE_NOT_READY No response from notification service
+ * @see #notification_send_event()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err;
+ bool available;
+
+ ...
+
+ noti_err = notification_check_event_receiver_available(noti, &available);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+
+ ...
+
+ notification_free(noti);
+}
+ * @endcode
+ */
+int notification_check_event_receiver_available(notification_h noti, bool *available);
+
+/**
+ * @brief This function translate localized texts.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle that is created by notification_create()
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @see notification_create()
+ */
+int notification_translate_localized_text(notification_h noti);
+
+/**
+ * @internal
+ * @brief Loads a notification template from the applcation id.
+ * @details An application can load a saved template and post it.
+ * @since_tizen 3.0
+ * @privilege %http://tizen.org/privilege/notification
+ * @remarks The returned handle should be destroyed using notification_free().
+ * The specific error code can be obtained using get_last_result().
+ * Error codes are described in the Exception section.
+ * If an invalid template name or application id is given, the result will be set to #NOTIFICATION_ERROR_FROM_DB.
+ * @param[in] app_id Application ID
+ * @param[in] template_name Template name
+ * @return Notification handle on success, NULL on failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @exception #NOTIFICATION_ERROR_IO_ERROR I/O Error
+ * @exception #NOTIFICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @exception #NOTIFICATION_ERROR_FROM_DB Error from DB query
+ * @exception #NOTIFICATION_ERROR_SERVICE_NOT_READY No response from notification service
+ * @see #notification_h
+ * @see notification_save_as_template()
+ */
+notification_h notification_create_from_package_template(const char *app_id,
+ const char *template_name);
+
+void notification_reset_event_handler_list(void);
+int notification_set_uid(notification_h noti, uid_t uid);
+int notification_get_uid(notification_h noti, uid_t *uid);
+int notification_post_for_uid(notification_h noti, uid_t uid);
+int notification_update_for_uid(notification_h noti, uid_t uid);
+int notification_delete_for_uid(notification_h noti, uid_t uid);
+int notification_delete_all_for_uid(notification_type_e type, uid_t uid);
+notification_h notification_load_by_tag_for_uid(const char *tag, uid_t uid);
+
+/**
+ * @brief Gets a max length of text input.
+ * @since_tizen 3.0
+ * @param[in] noti The notification handle
+ * @param[in] Max length of Text input
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int text_input_max_length;
+
+ noti_err = notification_get_text_input_max_length(noti, &text_input_max_length);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+ ...
+ }
+ * @endcode
+ */
+int notification_get_text_input_max_length(notification_h noti, int *text_input_max_length);
+
+/**
+ * @brief Sets an extension data.
+ * @since_tizen 4.0
+ * @param[in] noti The notification handle
+ * @param[in] key The key
+ * @param[in] value The bundle data
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int notification_set_extension_data(notification_h noti, const char *key, bundle *value);
+
+/**
+ * @brief Gets an extension data.
+ * @since_tizen 4.0
+ * @param[in] noti The notification handle
+ * @param[in] key The key
+ * @param[out] value The bundle data
+ * @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_IO_ERROR IO Error
+ */
+int notification_get_extension_data(notification_h noti, const char *key, bundle **value);
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_set_extension_data()
+ */
+int notification_set_extention_data(notification_h noti, const char *key, bundle *value) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief This function will be deprecated.
+ * @see notification_get_extension_data()
+ */
+int notification_get_extention_data(notification_h noti, const char *key, bundle **value) NOTIFICATION_DEPRECATED_API;
+
+/**
+ * @brief Sets the handler for a specific extension event.
+ * @details When some extension event occurs on notification, application launched by app_control_send_launch_request with app_control handle.
+ * @since_tizen 4.0
+ * @param[in] noti The notification handle
+ * @param[in] event_type Event type
+ * @param[in] event_handler App control 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_IO_ERROR I/O error
+ * @see #notification_event_type_extension_e
+ */
+int notification_set_extension_event_handler(notification_h noti,
+ notification_event_type_extension_e event,
+ app_control_h event_handler);
+
+/**
+ * @brief Gets the handler for a specific extension event.
+ * @details When extension event occurs on notification, application launched by app_control_send_launch_request with app_control handle.
+ * @since_tizen 4.0
+ * @param[in] noti The notification handle
+ * @param[in] event Event type
+ * @param[out] event_handler App control 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_IO_ERROR I/O error
+ * @see #notification_event_type_extension_e
+ */
+int notification_get_extension_event_handler(notification_h noti,
+ notification_event_type_extension_e event,
+ app_control_h *event_handler);
+
+/**
+ * @internal
+ * @brief Sets the label of caller application.
+ * @details It recommends for daemons. For an Application, the label is set when notification create.
+ * @since_tizen 5.0
+ * @param[in] noti Notification handle
+ * @param[in] label Label of Caller application
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_app_label(noti, "message");
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_app_label(notification_h noti, char *label);
+
+/**
+ * @internal
+ * @brief Gets the label of caller application.
+ * @details Label may be null if it was not set.
+ * Do not free @a label. It will be freed when notification_free() is called.
+ * @since_tizen 5.0
+ * @param[in] noti Notification handle
+ * @param[out] label Label of Caller application
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ char *label = NULL;
+
+ noti_err = notification_get_app_label(noti, &label);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_app_label(notification_h noti, char **label);
+
+/**
+ * @ This API is only for App Framework internally.
+ */
+int notification_set_indirect_request(notification_h noti, pid_t pid, uid_t uid);
+
+/**
+ * @internal
+ * @brief Notification viewer can delete all notifications displayed in the viewer.
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] display_applist Combination value of display list
+ * @return #NOTIFICATION_ERROR_NONE on success, other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @retval #NOTIFICATION_ERROR_IO_ERROR I/O error
+ * @retval #NOTIFICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @retval #NOTIFICATION_ERROR_FROM_DB Error from DB query
+ * @retval #NOTIFICATION_ERROR_SERVICE_NOT_READY No response from notification service
+ * @par Sample code:
+ * @code
+#include <notification_internal.h>
+...
+{
+ noti_err = notification_delete_by_display_applist(NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_delete_by_display_applist(int display_applist);
+int notification_delete_by_display_applist_for_uid(int display_applist, uid_t uid);
+
+/**
+ * @}
+ */
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/notification/include/notification_ipc.h b/notification/include/notification_ipc.h
new file mode 100644
index 0000000..b88de0a
--- /dev/null
+++ b/notification/include/notification_ipc.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_IPC_H__
+#define __NOTIFICATION_IPC_H__
+
+#include <gio/gio.h>
+#include <sys/types.h>
+
+#include <notification.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include <notification_list.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GVariant *notification_ipc_make_gvariant_from_noti(notification_h noti, bool translate);
+int notification_ipc_make_noti_from_gvariant(notification_h noti,
+ GVariant *variant);
+
+GVariant *notification_ipc_make_gvariant_from_setting(
+ struct notification_setting *noti_setting);
+int notification_ipc_make_setting_from_gvariant(
+ struct notification_setting *noti_setting, GVariant *variant);
+
+GVariant *notification_ipc_make_gvariant_from_system_setting(
+ struct notification_system_setting *noti_setting);
+int notification_ipc_make_system_setting_from_gvariant(
+ struct notification_system_setting *noti_setting,
+ GVariant *variant);
+
+int notification_dbus_init();
+int notification_ipc_monitor_init(uid_t uid);
+int notification_ipc_monitor_fini(void);
+void notification_ipc_event_monitor_fini(void);
+
+int notification_ipc_is_master_ready(void);
+int notification_ipc_add_deffered_task(void (*deferred_task_cb)(void *data),
+ void *user_data);
+int notification_ipc_del_deffered_task(void (*deferred_task_cb)(void *data));
+int notification_ipc_request_insert(notification_h noti, int *priv_id);
+int notification_ipc_request_update(notification_h noti);
+int notification_ipc_request_update_async(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data),
+ void *user_data);
+int notification_ipc_request_refresh(uid_t uid);
+int notification_ipc_request_delete_multiple(notification_type_e type,
+ char *app_id, uid_t uid);
+int notification_ipc_request_delete_by_display_applist(int display_applist, uid_t uid);
+int notification_ipc_request_delete_single(notification_type_e type,
+ char *app_id, int priv_id, uid_t uid);
+int notification_ipc_update_setting(notification_setting_h setting, uid_t uid);
+int notification_ipc_update_system_setting(
+ notification_system_setting_h system_setting, uid_t uid);
+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, 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(
+ const char *app_id, notification_setting_h *setting, uid_t uid);
+int notification_ipc_request_load_system_setting(
+ notification_system_setting_h *setting, uid_t uid);
+int notification_ipc_request_get_count(notification_type_e type,
+ const char *app_id, int group_id, int priv_id, int *count, uid_t uid);
+int notification_ipc_request_load_noti_by_priv_id(notification_h noti,
+ const char *app_id, int priv_id, uid_t uid);
+int notification_ipc_request_load_noti_detail_list(const char *app_id,
+ int group_id, int priv_id, int count,
+ notification_list_h *list, uid_t uid);
+int notification_ipc_request_save_as_template(notification_h noti, const char *template_name);
+int notification_ipc_request_create_from_template(notification_h noti, const char *template_name);
+int notification_ipc_request_create_from_package_template(notification_h noti,
+ const char *app_id, const char *template_name);
+int notification_ipc_get_noti_block_state(const char *app_id, int *do_not_disturb, int *do_not_disturb_except,
+ int *allow_to_notify, uid_t uid);
+GVariant *notification_ipc_make_gvariant_from_dnd_allow_exception(
+ struct notification_system_setting_dnd_allow_exception *dnd_allow_exception);
+int notification_ipc_make_dnd_allow_exception_from_gvariant(
+ struct notification_system_setting_dnd_allow_exception *dnd_allow_exception,
+ GVariant *variant);
+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
+#endif /* __NOTIFICATION_IPC_H__ */
+
diff --git a/notification/include/notification_list.h b/notification/include/notification_list.h
new file mode 100644
index 0000000..a05d61f
--- /dev/null
+++ b/notification/include/notification_list.h
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_LIST_H__
+#define __NOTIFICATION_LIST_H__
+
+#include <sys/types.h>
+#include <notification.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file notification_list.h
+ * @brief This file contains the notification list APIs.
+ */
+
+/**
+ * @internal
+ * @addtogroup NOTIFICATION_LIST
+ * @{
+ */
+
+/**
+ * @brief Notification list handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef struct _notification_list *notification_list_h;
+
+
+/**
+ * @internal
+ * @brief Returns the notification list handle.
+ * @details If count is equal to @c -1, all notifications are returned.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] type The notification type
+ * @param[in] count The returned notification data number
+ * @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
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_list(NOTIFICATION_TYPE_NONE, -1, &noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_list(notification_type_e type,
+ int count,
+ notification_list_h *list);
+
+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.
+ * @details If count is equal to c -1, all notifications are returned.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] app_id The caller application ID
+ * @param[in] group_id The group ID
+ * @param[in] priv_id The private ID
+ * @param[in] count The returned notification data number
+ * @param[out] list The notification list handle
+ * @return #NOTIFICATION_ERROR_NONE if success,
+ * other value if 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
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_detail_list(app_id, group_id, priv_id, -1, &noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_detail_list(const char *app_id,
+ int group_id,
+ int priv_id,
+ int count,
+ notification_list_h *list);
+
+int notification_get_detail_list_for_uid(const char *app_id,
+ int group_id,
+ int priv_id,
+ int count,
+ notification_list_h *list,
+ uid_t uid);
+
+/**
+ * @internal
+ * @brief Frees a notification list.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] 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
+ * @pre notification_get_grouping_list() or notification_get_detail_list().
+ * @see #notification_list_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ ...
+
+ noti_err = notification_free_list(noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_free_list(notification_list_h list);
+
+
+/**
+ * @internal
+ * @brief Gets the head pointer of the notification list.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] list Notification list handle
+ * @return Notification list handle on success, NULL on failure
+ * @retval #notification_list_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_list_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1, &noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ noti_list = notification_list_get_head(noti_list);
+}
+ * @endcode
+ */
+notification_list_h notification_list_get_head(notification_list_h list);
+
+/**
+ * @internal
+ * @brief Gets the tail pointer to the notification list.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] list Notification list handle
+ * @return Notification list handle on success, NULL on failure
+ * @retval #notification_list_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_list_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1, &noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ noti_list = notification_list_get_tail(noti_list);
+}
+ * @endcode
+ */
+notification_list_h notification_list_get_tail(notification_list_h list);
+
+/**
+ * @internal
+ * @brief Gets the previous pointer of the current notification list.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] list Notification list handle
+ * @return Notification list handle on success, NULL on failure
+ * @retval #notification_list_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_list_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1, &noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ noti_list = notification_list_get_prev(noti_list);
+}
+ * @endcode
+ */
+notification_list_h notification_list_get_prev(notification_list_h list);
+
+/**
+ * @internal
+ * @brief Gets the next pointer of the current notification list.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] list Notification list handle
+ * @return Notification list handle on success, NULL on failure
+ * @retval #notification_list_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_list_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1, &noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ noti_list = notification_list_get_next(noti_list);
+}
+ * @endcode
+ */
+notification_list_h notification_list_get_next(notification_list_h list);
+
+/**
+ * @internal
+ * @brief Gets the notification handle that the list has.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] list Notification list handle
+ * @return Notification handle on success, NULL on failure
+ * @retval #notification_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_list_h
+ * @see #notification_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1, &noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ noti = notification_list_get_data(noti_list);
+}
+ * @endcode
+ */
+notification_h notification_list_get_data(notification_list_h list);
+
+
+/**
+ * @internal
+ * @brief Gets a number of the notification list.
+ * @since_tizen 3.0
+ * @param[in] list Notification list handle
+ * @return A number of notification list handle on success, 0 on failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_list_h
+ * @see #notification_h
+ * @par Sample code:
+ * @code
+include <notification.h>
+...
+{
+ int count = 0;
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_err = notification_get_detail_list(app_id, group_id, priv_id, -1, &noti_list);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ count = notification_list_get_count(noti_list);
+}
+ * @endcode
+ */
+int notification_list_get_count(notification_list_h list);
+
+/**
+ * @internal
+ * @brief Appends notification data to the notification list.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] list Notification list handle
+ * @param[in] noti Notification handle
+ * @return Notification handle on success, NULL on failure
+ * @retval #notification_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @exception #NOTIFICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @see #notification_list_h
+ * @see #notification_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_new(NOTIFICATION_TYPE_NOTI, NOTIFICATION_GROUP_ID_NONE, NOTIFICATION_PRIV_ID_NONE);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_list = notification_list_append(noti_list, noti);
+}
+ * @endcode
+ */
+notification_list_h notification_list_append(notification_list_h list,
+ notification_h noti);
+
+/**
+ * @internal
+ * @brief Removes notification data from the notification list.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @param[in] list The notification list handle
+ * @param[in] noti The notification handle
+ * @return Notification handle on success,
+ * otherwise @c NULL on failure
+ * @retval #notification_h Success
+ * @retval NULL Failure
+ * @exception #NOTIFICATION_ERROR_NONE Success
+ * @exception #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @see #notification_list_h
+ * @see #notification_h
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ notification_list_h noti_list = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ ...
+
+ noti_list = notification_list_remove(noti_list, noti);
+}
+ * @endcode
+ */
+notification_list_h notification_list_remove(notification_list_h list,
+ notification_h noti);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __NOTIFICATION_LIST_H__ */
+
diff --git a/notification/include/notification_noti.h b/notification/include/notification_noti.h
new file mode 100644
index 0000000..4a2807e
--- /dev/null
+++ b/notification/include/notification_noti.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_NOTI_H__
+#define __NOTIFICATION_NOTI_H__
+
+#include <sys/types.h>
+#include <glib.h>
+
+#include <notification.h>
+#include <notification_list.h>
+
+#define TAG_TIME "TIME"
+#define TAG_TYPE_INVALID -1
+#define TAG_TYPE_TIME 1
+
+struct _notification_deleted_list_info {
+ int priv_id;
+ char *app_id;
+};
+
+typedef struct _notification_deleted_list_info notification_deleted_list_info_s;
+
+int notification_noti_set_tag(const char *tag, char *value, char *buf, int buf_len);
+
+char *notification_noti_strip_tag(const char *tagged_str);
+
+int notification_noti_get_tag_type(const char *tagged_str);
+
+int notification_noti_insert(notification_h noti);
+
+int notification_noti_update(notification_h noti);
+
+int notification_noti_delete_all(notification_type_e type, const char *app_id,
+ int *deleted_num, int **deleted_list, uid_t uid);
+
+int notification_noti_get_by_priv_id(notification_h noti, int priv_id);
+int notification_noti_get_by_tag(notification_h noti, char *app_id, char* tag, uid_t uid);
+
+int notification_noti_delete_by_priv_id(const char *app_id, int priv_id);
+int notification_noti_delete_by_priv_id_get_changes(const char *app_id, int priv_id,
+ int *num_changes, uid_t uid);
+
+int notification_noti_delete_by_display_applist(int display_applist,
+ int *deleted_num,
+ notification_deleted_list_info_s **deleted_list,
+ uid_t uid);
+
+int notification_noti_get_count(notification_type_e type,
+ const char *app_id,
+ int group_id, int priv_id,
+ int *count, uid_t uid);
+
+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 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,
+ int group_id,
+ int priv_id, int count,
+ notification_list_h *list,
+ uid_t uid);
+
+int notification_noti_check_tag(notification_h noti);
+int notification_noti_check_count_for_template(notification_h noti, int *count);
+
+int notification_noti_add_template(notification_h noti, char *template_name);
+int notification_noti_get_package_template(notification_h noti, char *app_id, char *template_name);
+int notification_noti_delete_template(const char *pkg_id);
+
+void notification_noti_init_data(void);
+int notification_noti_check_limit(notification_h noti, uid_t uid, GList **list);
+
+#endif /* __NOTIFICATION_NOTI_H__ */
+
diff --git a/notification/include/notification_ongoing.h b/notification/include/notification_ongoing.h
new file mode 100644
index 0000000..fa6e95a
--- /dev/null
+++ b/notification/include/notification_ongoing.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_ONGOING_H__
+#define __NOTIFICATION_ONGOING_H__
+
+#include <notification.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @file notification_ongoing.h
+ */
+
+typedef enum {
+ ONGOING_TYPE_PROGRESS,
+ ONGOING_TYPE_SIZE,
+ ONGOING_TYPE_CONTENT,
+} ongoing_type_e;
+
+struct ongoing_info_s {
+ char *pkgname;
+ int priv_id;
+ ongoing_type_e type;
+ double progress;
+ double size;
+ char *content;
+};
+
+/**
+ * @internal
+ * @brief Called when a notification ongoing data is updated.
+ * @since_tizen 3.0
+ * @param[in] info The ongoing information handle
+ * @param[in] data The user data
+ * @pre notification_ongoing_update_cb_set() used to register this callback.
+ * @see notification_ongoing_update_cb_set()
+*/
+typedef void (*notification_ongoing_update_cb)(struct ongoing_info_s *info, void *data);
+
+/**
+ * @internal
+ * @brief Registers a callback to receive the ongoing progress, size ,content.
+ * @since_tizen 3.0
+ * @param[in] callback The callback function
+ * @param[in] data The user_data
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #NOTIFICATION_ERROR_FROM_DBUS Error from DBus
+ */
+int notification_ongoing_update_cb_set(notification_ongoing_update_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief Unregisters a callback to receive.
+ * @since_tizen 3.0
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ */
+int notification_ongoing_update_cb_unset(void);
+
+/**
+ * @brief Updates progress.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] caller_app_id
+ * @param[in] priv_id
+ * @param[in] progress
+ * @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_FROM_DBUS Error from DBus
+ */
+int notification_ongoing_update_progress(const char *caller_app_id,
+ int priv_id, double progress);
+
+/**
+ * @brief Updates size.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] caller_app_id
+ * @param[in] priv_id
+ * @param[in] size
+ * @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_FROM_DBUS Error from DBus
+ */
+int notification_ongoing_update_size(const char *caller_app_id,
+ int priv_id, double size);
+
+/**
+ * @brief Updates content.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] caller_app_id
+ * @param[in] priv_id
+ * @param[in] content
+ * @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_FROM_DBUS Error from DBus
+ */
+int notification_ongoing_update_content(const char *caller_app_id,
+ int priv_id, const char *content);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __NOTIFICATION_ONGOING_H__ */
+
diff --git a/notification/include/notification_ongoing_flag.h b/notification/include/notification_ongoing_flag.h
new file mode 100644
index 0000000..e7238a4
--- /dev/null
+++ b/notification/include/notification_ongoing_flag.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 - 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.
+ */
+
+#ifndef __NOTIFICATION_ONGOING_FLAG_H__
+#define __NOTIFICATION_ONGOING_FLAG_H__
+
+#include <notification.h>
+
+/**
+ * @brief Sets the ongoing flag of the notification
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] noti The notification handle
+ * @param[in] ongoing_flag The ongoing flag
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ bundle *b = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_ongoing_flag(noti, true);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_ongoing_flag(notification_h noti, bool ongoing_flag);
+
+/**
+ * @brief Gets the ongoing flag of the notification
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] noti The notification handle
+ * @param[out] ongoing_flag The ongoing flag
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid input value
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ bool ongoing_flag = 0;
+
+ noti_err = notification_get_ongoing_flag(noti, &ongoing_flag);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_ongoing_flag(notification_h noti, bool *ongoing_flag);
+
+#endif /* __NOTIFICATION_ONGOING_H__ */
+
diff --git a/notification/include/notification_private.h b/notification/include/notification_private.h
new file mode 100644
index 0000000..a9ce8ed
--- /dev/null
+++ b/notification/include/notification_private.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_PRIVATE_H__
+#define __NOTIFICATION_PRIVATE_H__
+#include <sys/types.h>
+#include <notification_internal.h>
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__ ((visibility("default")))
+#endif
+
+#define SAFE_STRDUP(s) ((s) ? strdup(s) : NULL)
+#define SAFE_FREE(s) \
+ do { \
+ if (s) { \
+ free(s); \
+ s = NULL; \
+ } \
+ } while (0)
+
+struct _notification {
+ notification_type_e type;
+ notification_ly_type_e layout;
+
+ int group_id; /* Group ID */
+ int internal_group_id; /* Internal Group ID */
+ int priv_id; /* Private ID */
+
+ char *pkg_id;
+ char *caller_app_id; /* Caller App ID */
+ char *launch_app_id; /* Launch App ID */
+ bundle *args; /* Will be removed. */
+ bundle *group_args; /* Will be removed. */
+
+ bundle *b_execute_option;
+ bundle *b_service_responding;
+ bundle *b_service_single_launch;
+ bundle *b_service_multi_launch;
+
+ bundle *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1];
+
+ char *domain; /* Text domain for localization */
+ char *dir; /* Text dir for localization */
+
+ bundle *b_text; /* basic text */
+ bundle *b_key; /* key for localized text */
+ bundle *b_format_args; /* args type and value for format string */
+ int num_format_args; /* number of format string args */
+
+ bundle *b_image_path; /* image path */
+ bundle *b_priv_image_path; /* resource path for image */
+
+ notification_sound_type_e sound_type;
+ char *sound_path;
+ char *priv_sound_path; /* resource path for sound */
+ notification_vibration_type_e vibration_type;
+ char *vibration_path;
+ char *priv_vibration_path; /* resource path for vibration */
+ notification_led_op_e led_operation;
+ int led_argb;
+ int led_on_ms;
+ int led_off_ms;
+
+ time_t time; /* time set by application */
+ time_t insert_time; /* insert time */
+
+ int flags_for_property; /* property NOTIFICATION_PROP_XXX */
+ int display_applist; /* display app list NOTIFICATION_DISPLAY_APP_XXX */
+
+ double progress_size; /* size of progress */
+ double progress_percentage; /* percentage of progress */
+
+ char *app_icon_path; /* Temporary stored app icon path from AIL */
+ char *app_label;
+ char *temp_title;
+ char *temp_content;
+ char *tag;
+ bool ongoing_flag;
+ int ongoing_value_type;
+ int ongoing_current; /* Ongoing current time */
+ int ongoing_duration; /* Ongoing duration time */
+ bool auto_remove;
+ notification_button_index_e default_button_index;
+ int hide_timeout; /* Time for hide in banner */
+ int delete_timeout; /* Time for delete in view notification */
+ int text_input_max_length;
+ bool event_flag;
+ bool is_translation;
+ int extension_image_size;
+
+ uid_t uid;
+};
+
+typedef enum notification_data_type {
+ NOTIFICATION_DATA_TYPE_NOTI_TYPE = 1,
+ NOTIFICATION_DATA_TYPE_LAYOUT,
+ NOTIFICATION_DATA_TYPE_GROUP_ID,
+ NOTIFICATION_DATA_TYPE_INTERNAL_GROUP_ID,
+ NOTIFICATION_DATA_TYPE_PRIV_ID,
+ NOTIFICATION_DATA_TYPE_PKG_ID,
+ NOTIFICATION_DATA_TYPE_CALLER_APP_ID,
+ NOTIFICATION_DATA_TYPE_LAUNCH_APP_ID,
+ NOTIFICATION_DATA_TYPE_ARGS,
+ NOTIFICATION_DATA_TYPE_GROUP_ARGS,
+ NOTIFICATION_DATA_TYPE_EXECUTE_OPTION,
+ NOTIFICATION_DATA_TYPE_SERVICE_RESPONDING,
+ NOTIFICATION_DATA_TYPE_SERVICE_SINGLE_LAUNCH,
+ NOTIFICATION_DATA_TYPE_SERVICE_MULTI_LAUNCH,
+ NOTIFICATION_DATA_TYPE_BUTTON1_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON2_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON3_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON4_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON5_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON6_EVENT,
+ NOTIFICATION_DATA_TYPE_ICON_EVENT,
+ NOTIFICATION_DATA_TYPE_THUMBNAIL_EVENT,
+ NOTIFICATION_DATA_TYPE_TEXT_INPUT_BUTTON_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON7_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON8_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON9_EVENT,
+ NOTIFICATION_DATA_TYPE_BUTTON10_EVENT,
+ NOTIFICATION_DATA_TYPE_DOMAIN,
+ NOTIFICATION_DATA_TYPE_DIR,
+ NOTIFICATION_DATA_TYPE_TEXT,
+ NOTIFICATION_DATA_TYPE_KEY,
+ NOTIFICATION_DATA_TYPE_FORMAT_ARGS,
+ NOTIFICATION_DATA_TYPE_NUM_FORMAT_ARGS,
+ NOTIFICATION_DATA_TYPE_IMAGE_PATH,
+ NOTIFICATION_DATA_TYPE_PRIV_IMAGE_PATH,
+ NOTIFICATION_DATA_TYPE_SOUND_TYPE,
+ NOTIFICATION_DATA_TYPE_SOUND_PATH,
+ NOTIFICATION_DATA_TYPE_PRIV_SOUND_PATH,
+ NOTIFICATION_DATA_TYPE_VIBRATION_TYPE,
+ NOTIFICATION_DATA_TYPE_VIBRATION_PATH,
+ NOTIFICATION_DATA_TYPE_PRIV_VIBRATION_PATH,
+ NOTIFICATION_DATA_TYPE_LED_OPERATION,
+ NOTIFICATION_DATA_TYPE_LED_ARGB,
+ NOTIFICATION_DATA_TYPE_LED_ON_MS,
+ NOTIFICATION_DATA_TYPE_LED_OFF_MS,
+ NOTIFICATION_DATA_TYPE_TIME,
+ NOTIFICATION_DATA_TYPE_INSERT_TIME,
+ NOTIFICATION_DATA_TYPE_FLAGS_FOR_PROPERTY,
+ NOTIFICATION_DATA_TYPE_DISPLAY_APPLIST,
+ NOTIFICATION_DATA_TYPE_PROGRESS_SIZE,
+ NOTIFICATION_DATA_TYPE_PROGRESS_PERCENTAGE,
+ NOTIFICATION_DATA_TYPE_APP_ICON_PATH,
+ NOTIFICATION_DATA_TYPE_APP_LABEL,
+ NOTIFICATION_DATA_TYPE_TEMP_TITLE,
+ NOTIFICATION_DATA_TYPE_TEMP_CONTENT,
+ NOTIFICATION_DATA_TYPE_TAG,
+ NOTIFICATION_DATA_TYPE_ONGOING_FLAG,
+ NOTIFICATION_DATA_TYPE_ONGOING_VALUE_TYPE,
+ NOTIFICATION_DATA_TYPE_ONGOING_CURRENT,
+ NOTIFICATION_DATA_TYPE_ONGOING_DURATION,
+ NOTIFICATION_DATA_TYPE_AUTO_REMOVE,
+ NOTIFICATION_DATA_TYPE_DEFAULT_BUTTON,
+ NOTIFICATION_DATA_TYPE_HIDE_TIMEOUT,
+ NOTIFICATION_DATA_TYPE_DELETE_TIMEOUT,
+ NOTIFICATION_DATA_TYPE_TEXT_INPUT_MAX_LENGTH,
+ NOTIFICATION_DATA_TYPE_EVENT_FLAG,
+ NOTIFICATION_DATA_TYPE_TRANSLATION,
+ NOTIFICATION_DATA_TYPE_EXTENSION_IMAGE_SIZE,
+ NOTIFICATION_DATA_TYPE_UID,
+} notification_data_type_e;
+
+void notification_call_changed_cb_for_uid(notification_op *op_list, int op_num, uid_t uid);
+void notification_call_dnd_changed_cb_for_uid(int do_not_disturb, uid_t uid);
+void notification_call_event_handler_cb(notification_h noti, int event_type);
+void notification_delete_event_handler_cb(int priv_id);
+char *notification_get_app_id_by_pid(int pid);
+
+#endif /* __NOTIFICATION_PRIVATE_H__ */
+
diff --git a/notification/include/notification_setting.h b/notification/include/notification_setting.h
new file mode 100644
index 0000000..9186cd6
--- /dev/null
+++ b/notification/include/notification_setting.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_SETTING_H__
+#define __NOTIFICATION_SETTING_H__
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "notification.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct notification_setting *notification_setting_h;
+
+/**
+ * @internal
+ * @brief Gets setting handle of current process.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[out] setting The setting 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_OUT_OF_MEMORY Out of memory
+ * @retval #NOTIFICATION_ERROR_NOT_EXIST_ID Already exist private ID
+ * @retval #NOTIFICATION_ERROR_IO_ERROR I/O error
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED Permission denied
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int noti_err = 0;
+ notification_setting_h setting = NULL;
+
+ noti_err = notification_setting_get_setting(&setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_setting_get_setting(notification_setting_h *setting);
+
+/**
+ * @internal
+ * @brief Gets value which whether information on the notification view is visible.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] setting The notification setting handle
+ * @param[out] value The visibility_class value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_setting_get_visibility_class(setting, &value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_get_visibility_class(notification_setting_h setting, int *value);
+
+/**
+ * @internal
+ * @brief Sets value which whether information on the notification view is visible.
+ * @details After notification_setting_update_setting() call, the visibility_class value is not updated.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] setting The notification setting handle
+ * @param[in] value The visibility_class value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ value = true; // or false
+
+ noti_err = notification_setting_set_visibility_class(setting, value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_set_visibility_class(notification_setting_h setting, int value);
+
+/**
+ * @internal
+ * @brief Updates the notification setting handle.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] setting The notification setting 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_IO_ERROR I/O error
+ * @retval #NOTIFICATION_ERROR_SERVICE_NOT_READY No response from notification service
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED Permission denied
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_setting_update_setting(setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_update_setting(notification_setting_h setting);
+
+/**
+ * @internal
+ * @brief Frees the internal structure data of a notification setting handle.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] setting The notification setting 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
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int noti_err = 0;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_setting_free_notification(setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_free_notification(notification_setting_h setting);
+
+/**
+ * @internal
+ * @brief Refreshs the setting table of current user.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] uid User id
+ * @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_FROM_DB Error from DB query
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int ret;
+
+ ret = notification_setting_refresh_setting_table(uid);
+ if (ret = NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_setting_refresh_setting_table(uid_t uid);
+
+/**
+ * @internal
+ * @brief Initializes the system setting table of the current user.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ * @param[in] uid User id
+ * @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_OUT_OF_MEMORY Out of memory
+ * @retval #NOTIFICATION_ERROR_NOT_EXIST_ID Already exist private ID
+ * @retval #NOTIFICATION_ERROR_IO_ERROR I/O error
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int ret;
+
+ ret = notification_system_setting_init_system_setting_table(uid);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_system_setting_init_system_setting_table(uid_t uid);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __NOTIFICATION_SETTING_H__ */
+
diff --git a/notification/include/notification_setting_internal.h b/notification/include/notification_setting_internal.h
new file mode 100644
index 0000000..951d4d3
--- /dev/null
+++ b/notification/include/notification_setting_internal.h
@@ -0,0 +1,1493 @@
+/*
+ * Copyright (c) 2015 - 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.
+ */
+
+#ifndef __NOTIFICATION_SETTING_INTERNAL_H__
+#define __NOTIFICATION_SETTING_INTERNAL_H__
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <glib.h>
+#include "notification.h"
+#include "notification_setting.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct notification_system_setting *notification_system_setting_h;
+typedef struct notification_system_setting_dnd_allow_exception *dnd_allow_exception_h;
+
+/**
+ * @brief The prototype of handler that 'Do not disturb' mode set schdule changed alarm.
+ * @since_tizen 3.0
+ */
+typedef void (*dnd_changed_cb)(void *user_data, int do_not_disturb);
+
+/**
+ * @brief Enumeration for Week Flag, the days of the week.
+ * @since_tizen 3.0
+ */
+typedef enum {
+ DND_SCHEDULE_WEEK_FLAG_SUNDAY = 0x01, /**< Sunday */
+ DND_SCHEDULE_WEEK_FLAG_MONDAY = 0x02, /**< Monday */
+ DND_SCHEDULE_WEEK_FLAG_TUESDAY = 0x04, /**< Tuesday */
+ DND_SCHEDULE_WEEK_FLAG_WEDNESDAY = 0x08, /**< Wednesday */
+ DND_SCHEDULE_WEEK_FLAG_THURSDAY = 0x10, /**< Thursday */
+ DND_SCHEDULE_WEEK_FLAG_FRIDAY = 0x20, /**< Friday */
+ DND_SCHEDULE_WEEK_FLAG_SATURDAY = 0x40, /**< Saturday */
+ DND_SCHEDULE_WEEK_FLAG_ALL = DND_SCHEDULE_WEEK_FLAG_SUNDAY|
+ DND_SCHEDULE_WEEK_FLAG_MONDAY |
+ DND_SCHEDULE_WEEK_FLAG_TUESDAY |
+ DND_SCHEDULE_WEEK_FLAG_WEDNESDAY |
+ DND_SCHEDULE_WEEK_FLAG_THURSDAY |
+ DND_SCHEDULE_WEEK_FLAG_FRIDAY |
+ DND_SCHEDULE_WEEK_FLAG_SATURDAY
+} dnd_schedule_week_flag_e;
+
+/**
+ * @brief Enumeration for lock screen content.
+ * @since_tizen 3.0
+ */
+typedef enum lock_screen_content_level {
+ SHOW_ALL_CONTENT = 0, /**< Show all*/
+ HIDE_SENSITIVE_CONTENT, /**< Hide sensitive */
+ DO_NOT_SHOW_NOTIFICATIONS, /**< Do not Showw */
+} lock_screen_content_level_e;
+
+/**
+ * @brief Enumeration for do_not_disturb allow exception type.
+ * @since_tizen 3.0
+ */
+typedef enum dnd_allow_exception_type {
+ NOTIFICATION_DND_ALLOWED_CALLS = 0, /**< Call */
+ /* possible to add */
+} dnd_allow_exception_type_e;
+
+/**
+ * @brief Enumeration for allowed_calls.
+ * @since_tizen 3.0
+ */
+typedef enum notification_dnd_allowed_calls {
+ NOTIFICATION_DND_ALLOWED_CALLS_EVERYONE = 0, /**< Everyone */
+ NOTIFICATION_DND_ALLOWED_CALLS_CONTACT, /**< Contact */
+ NOTIFICATION_DND_ALLOWED_CALLS_FAVORITE, /**< Favorite */
+ NOTIFICATION_DND_ALLOWED_CALLS_NOBODY, /**< Nobody */
+} notification_dnd_allowed_calls_e;
+
+/* Application setting */
+struct notification_setting {
+ char *package_name;
+ char *app_id;
+ bool allow_to_notify;
+ bool do_not_disturb_except;
+ bool pop_up_notification;
+ int visibility_class;
+ lock_screen_content_level_e lock_screen_content_level;
+ bool app_disabled;
+};
+
+/* System setting */
+struct notification_system_setting {
+ bool do_not_disturb;
+ int visibility_class;
+ bool dnd_schedule_enabled;
+ int dnd_schedule_day;
+ int dnd_start_hour;
+ int dnd_start_min;
+ int dnd_end_hour;
+ int dnd_end_min;
+ lock_screen_content_level_e lock_screen_content_level;
+ GList *dnd_allow_exceptions;
+};
+
+/* dnd_allow_exception */
+struct notification_system_setting_dnd_allow_exception {
+ int type;
+ int value;
+};
+
+/**
+ * @internal
+ * @brief Gets the array of notification setting.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[out] setting_array The array of notification setting
+ * @param[out] count The count of array
+ * @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_IO_ERROR I/O error
+ * @retval #NOTIFICATION_ERROR_OUT_OF_MEMORY out of memory
+ * @retval #NOTIFICATION_ERROR_SERVICE_NOT_READY No reponse from notification service
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED Permission denied
+ * @par Sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int count = 0;
+ notification_setting_h setting;
+
+ noti_err = notification_setting_get_setting_array(&setting, &count);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ ...
+
+ notification_setting_free_notification(setting);
+}
+ * @endcode
+ */
+
+int notification_setting_get_setting_array(notification_setting_h *setting_array, int *count);
+int notification_setting_get_setting_array_for_uid(notification_setting_h *setting_array, int *count, uid_t uid);
+
+/**
+ * @internal
+ * @brief Gets notification setting by package name.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] package_name The package_name
+ * @param[out] setting The notification setting
+ * @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_IO_ERROR I/O error I/O error
+ * @retval #NOTIFICATION_ERROR_OUT_OF_MEMORY out of memory
+ * @retval #NOTIFICATION_ERROR_SERVICE_NOT_READY No reponse from notification service
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED Permission denied
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ notification_setting_h setting = NULL;
+
+ noti_err = notification_setting_get_setting_by_package_name(PACKAGE_NAME, &setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_get_setting_by_package_name(const char *package_name, notification_setting_h *setting);
+int notification_setting_get_setting_by_appid_for_uid(const char *app_id, notification_setting_h *setting, uid_t uid);
+
+/**
+ * @internal
+ * @brief Gets package name from notification setting handle.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] setting The notification setting handle
+ * @param[out] value The package name
+ * @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_NOT_EXIST_ID Already exist private ID
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ char *package_name = NULL;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_setting_get_package_name(setting, &package_name);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_get_package_name(notification_setting_h setting, char **value);
+
+/**
+ * @internal
+ * @brief Gets application id from notification setting handle.
+ * @since_tizen 3.0
+ * @param[in] setting The notification setting handle
+ * @param[out] app_id The application id
+ * @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_NOT_EXIST_ID Already exist private ID
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ char *app_id = NULL;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_setting_get_appid(setting, &app_id);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_get_appid(notification_setting_h setting, char **app_id);
+
+/**
+ * @internal
+ * @brief Gets value which whether allow notification from individual applications.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] setting The notification setting handle
+ * @param[out] value The value which whether allow to notification
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_setting_get_allow_to_notify(setting, &value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_get_allow_to_notify(notification_setting_h setting, bool *value);
+
+/**
+ * @internal
+ * @brief Sets value which whether allow notification from individual applications.
+ * @details After notification_setting_update_setting() call, the allow_to_notify is updated.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] setting The notification setting handle
+ * @param[in] value The value whether allow to notification
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ value = true; // or false
+
+ noti_err = notification_setting_set_allow_to_notify(setting, value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_set_allow_to_notify(notification_setting_h setting, bool value);
+
+/**
+ * @internal
+ * @brief Gets value which whether do not disturb notification from notification setting handle.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] setting The notification setting handle
+ * @param[out] value The value which whether do not disturb notification or not
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_setting_get_do_not_disturb_except(setting, &value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_get_do_not_disturb_except(notification_setting_h setting, bool *value);
+
+/**
+ * @internal
+ * @brief Sets value which whether do not disturb notification or not.
+ * @details After notification_setting_update_setting() call, the do_not_disturb value is updated.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] setting The notification setting handle
+ * @param[in] value The value which do not disturb notification or not
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ value = true; // or false
+
+ noti_err = notification_setting_set_do_not_disturb_except(setting, value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_set_do_not_disturb_except(notification_setting_h setting, bool value);
+
+/**
+ * @internal
+ * @brief Gets value whether Pop up notification is allowed or not.
+ * @since_tizen 3.0
+ * @param[in] setting The notification setting handle
+ * @param[in] value The value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ value = true; // or false
+
+ noti_err = notification_setting_get_pop_up_notification(setting, value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_get_pop_up_notification(notification_setting_h setting, bool *value);
+
+/**
+ * @internal
+ * @brief Sets value which Pop up notification allow or block.
+ * @details After notification_setting_update_setting() call, the pop_up_notification value is updated.
+ * @since_tizen 3.0
+ * @param[in] setting The notification setting handle
+ * @param[in] value The value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ value = true; // or false
+
+ noti_err = notification_setting_get_pop_up_notification(setting, value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_set_pop_up_notification(notification_setting_h setting, bool value);
+
+/**
+ * @internal
+ * @brief Gets displaying level that notification's information on lock screen from individual application.
+ * @since_tizen 3.0
+ * @param[in] setting The notification setting handle
+ * @param[out] level The displaying level of notification's information on lock screen
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #lock_screen_content_level_e
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ notification_setting_h setting = NULL;
+ lock_screen_content_level_e level;
+
+ ...
+
+ noti_err = notification_setting_get_lock_screen_content(setting, &level);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_get_lock_screen_content(notification_setting_h setting, lock_screen_content_level_e *level);
+
+/**
+ * @internal
+ * @brief Sets displaying level that notification's information on lock screen from individual application.
+ * @details After notification_setting_update_setting() call, the lock_screen_content_level value is updated.
+ * @since_tizen 3.0
+ * @param[in] setting The notification setting handle
+ * @param[out] level The displaying level of notification's information on lock screen
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #lock_screen_content_level_e
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ notification_setting_h setting = NULL;
+ lock_screen_content_level_e level;
+
+ ...
+
+ level = SHOW_ALL_CONTENT; // or HIDE_SENSITIVE_CONTENT or DO_NOT_SHOW_NOTIFICATIONS;
+
+ noti_err = notification_setting_get_lock_screen_content(setting, level);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_setting_free_notification(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_setting_set_lock_screen_content(notification_setting_h setting, lock_screen_content_level_e level);
+
+/**
+ * @internal
+ * @brief Gets The value that determines whether the app is disabled.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] setting The notification system setting handle
+ * @param[out] value The value that determines whether the app is disabled
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+{
+ int err = 0;
+ bool value = true;
+ notification_system_setting_h setting = NULL;
+
+ err = notification_setting_get_setting(&setting);
+ if (err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ err = notification_setting_get_app_disabled(setting, &value);
+ if (err != NOTIFICATION_ERROR_NONE)
+ return;
+
+ return 0;
+}
+ * @endcode
+ */
+int notification_setting_get_app_disabled(notification_setting_h setting, bool *value);
+
+/**
+ * @internal
+ * @brief Gets the notification system setting handle.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] system_setting The notification system setting 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_OUT_OF_MEMORY Out of memory
+ * @retval #NOTIFICATION_ERROR_IO_ERROR I/O error
+ * @retval #NOTIFICATION_ERROR_SERVICE_NOT_READY No response from notification service
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED Permission denied
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_load_system_setting(&setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_load_system_setting(notification_system_setting_h *system_setting);
+int notification_system_setting_load_system_setting_for_uid(notification_system_setting_h *system_setting, uid_t uid);
+
+/**
+ * @internal
+ * @brief Updates the notification system handle.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] system_setting The notification system setting 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
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_update_system_setting(setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_update_system_setting(notification_system_setting_h system_setting);
+int notification_system_setting_update_system_setting_for_uid(notification_system_setting_h system_setting, uid_t uid);
+
+/**
+ * @internal
+ * @brief Frees the internal structure data of a notification system setting handle.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] system_setting The notification system setting 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
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_free_system_setting(setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_free_system_setting(notification_system_setting_h system_setting);
+
+/**
+ * @internal
+ * @brief Gets value which whether do not disturb notification from notification system setting handle.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] system_setting The notification system setting handle
+ * @param[out] value The value which whether do not disturb notification or not
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_get_do_not_disturb_except(setting, &value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_get_do_not_disturb(notification_system_setting_h system_setting, bool *value);
+
+/**
+ * @internal
+ * @brief Sets value which whether do not disturb notification or not.
+ * @details After notification_system_setting_update_system_setting() call, the do_not_disturb value is not updated.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] system_setting The notification system setting handle
+ * @param[in] value The value which do not disturb notification or not
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ value = true; // or false
+
+ noti_err = notification_setting_set_do_not_disturb_except(setting, value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_set_do_not_disturb(notification_system_setting_h system_setting, bool value);
+
+/**
+ * @internal
+ * @brief Gets value which whether information on the notification view is visible.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] system_setting The notification system setting handle
+ * @param[out] value The visibility_class value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_get_visibility_class(setting, &value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_get_visibility_class(notification_system_setting_h system_setting, int *value);
+
+/**
+ * @internal
+ * @brief Sets value which whether information on the notification view is visible.
+ * @details After notification_system_setting_update_system_setting() call, the visibility_class value is not updated.
+ * @since_tizen @if wearable 2.3.1 @elseif mobile 2.3 @endif
+ * @param[in] system_setting The notification setting handle
+ * @param[in] value The visibility_class value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ value = true; // or false
+
+ noti_err = notification_setting_set_visibility_class(setting, value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_set_visibility_class(notification_system_setting_h system_setting, int value);
+
+/**
+ * @internal
+ * @brief Gets value which whether 'Do not disturb' mode is enable or not.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[out] enabled The dnd_schedule_enabled value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_dnd_schedule_get_enabled(setting, &value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_dnd_schedule_get_enabled(notification_system_setting_h system_setting, bool *enabled);
+
+/**
+ * @internal
+ * @brief Sets value which whether 'Do not disturb' mode is enable or not.
+ * @details After notification_system_setting_update_system_setting() call, the 'Do not disturb' mode is not updated.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[in] enabled The dnd_schedule_enabled value
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ bool value;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ value = true; // or false
+
+ noti_err = notification_system_setting_dnd_schedule_set_enabled(setting, &value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_dnd_schedule_set_enabled(notification_system_setting_h system_setting, bool enabled);
+
+/**
+ * @internal
+ * @brief Gets days of the week that 'Do not disturb' mode is enable.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[out] day The days of the week that enable 'Do not disturb' mode
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #dnd_schedule_week_flag_e
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int day;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_dnd_schedule_get_day(setting, &day);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_dnd_schedule_get_day(notification_system_setting_h system_setting, int *day);
+
+/**
+ * @internal
+ * @brief Sets days of the week that 'Do not disturb' mode is enable.
+ * @details After notification_system_setting_update_system_setting() call, the days not updated.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[in] day The days of the week that enable 'Do not disturb' mode
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #dnd_schedule_week_flag_e
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int day;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ day = DND_SCHEDULE_WEEK_FLAG_SUNDAY;
+
+ noti_err = notification_system_setting_dnd_schedule_set_day(setting, day);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_dnd_schedule_set_day(notification_system_setting_h system_setting, int day);
+
+/**
+ * @internal
+ * @brief Gets time that 'Do not disturb' mode is started.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[out] hour The hour that 'Do not disturb' mode is started
+ * @param[out] min The min that 'Do not disturb' mode is started
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int hour;
+ int min;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_dnd_schedule_get_start_time(setting, &hour, &min);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_dnd_schedule_get_start_time(notification_system_setting_h system_setting, int *hour, int *min);
+
+/**
+ * @internal
+ * @brief Sets time that 'Do not disturb' mode is started.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[in] hour The hour that 'Do not disturb' mode is startd
+ * @param[in] min The min that 'Do not disturb' mode is started
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int hour;
+ int min;
+ notification_setting_h setting = NULL;
+
+ ...
+
+ hour = START_HOUR; // 0 ~ 23
+ min = START_MIN // 0 ~ 59
+
+ noti_err = notification_system_setting_dnd_schedule_set_start_time(setting, hour, min);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_dnd_schedule_set_start_time(notification_system_setting_h system_setting, int hour, int min);
+
+/**
+ * @internal
+ * @brief Gets time that 'Do not disturb' mode is ended.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[out] hour The hour that 'Do not disturb' mode is ended
+ * @param[out] min The min that 'Do not disturb' mode is ended
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int hour;
+ int min;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ noti_err = notification_system_setting_dnd_schedule_get_end_time(setting, &hour, &min);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_dnd_schedule_get_end_time(notification_system_setting_h system_setting, int *hour, int *min);
+
+/**
+ * @internal
+ * @brief Sets time that 'Do not disturb' mode is ended.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[in] hour The hour that 'Do not disturb' mode is ended
+ * @param[in] min The min that 'Do not disturb' mode is ended
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int hour;
+ int min;
+ notification_system_setting_h setting = NULL;
+
+ ...
+
+ hour = START_HOUR; // 0 ~ 23
+ min = START_MIN // 0 ~ 59
+
+ noti_err = notification_system_setting_dnd_schedule_set_end_time(setting, hour, min);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_dnd_schedule_set_end_time(notification_system_setting_h system_setting, int hour, int min);
+
+/**
+ * @internal
+ * @brief Gets displaying level that notification's information on lock screen.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[out] level The displaying level of notification's information on lock screen
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #lock_screen_content_level_e
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ notification_setting_h setting = NULL;
+ lock_screen_content_level_e level;
+
+ ...
+
+ noti_err = notification_system_setting_get_lock_screen_content(setting, &level);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_get_lock_screen_content(notification_system_setting_h system_setting, lock_screen_content_level_e *level);
+
+/*
+ * @internal
+ * @brief Sets displaying level that notification's information on lock screen.
+ * @since_tizen 3.0
+ * @param[in] system_setting The notification system setting handle
+ * @param[in] level The displaying level of notification's information on lock screen
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #lock_screen_content_level_e
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ notification_system_setting_h setting = NULL;
+ lock_screen_content_level_e level;
+
+ ...
+
+ level = SHOW_ALL_CONTENT; // or HIDE_SENSITIVE_CONTENT or DO_NOT_SHOW_NOTIFICATIONS;
+
+ noti_err = notification_system_setting_set_lock_screen_content(setting, &level);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ *
+ */
+int notification_system_setting_set_lock_screen_content(notification_system_setting_h system_setting, lock_screen_content_level_e level);
+
+/**
+ * @internal
+ * @brief Gets a value of the do_not_disturb allow exceptions.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] system_setting The notification system setting handle
+ * @param[in] type The exceptional item of do_not_distrub
+ * @param[out] value The value of the exceptional item
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int value;
+ notification_system_setting_h setting = NULL;
+ ...
+ noti_err = notification_system_setting_load_system_setting(&setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ noti_err = notification_system_setting_get_dnd_allow_exceptions(setting, ALLOWED_CALLS, &value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+ ...
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_get_dnd_allow_exceptions(notification_system_setting_h system_setting, dnd_allow_exception_type_e type, int *value);
+
+/**
+ * @internal
+ * @brief Sets a value of the do_not_disturb allow exceptions.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] system_setting The notification system setting handle
+ * @param[in] type The exceptional item of do_not_distrub
+ * @param[in] value The value of the exceptional item
+ * @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_OUT_OF_MEMORY out of memory
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+{
+ int noti_err = 0;
+ int value = 0;
+ notification_system_setting_h setting = NULL;
+ ...
+ noti_err = notification_system_setting_load_system_setting(&setting);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ noti_err = notification_system_setting_set_dnd_allow_exceptions(setting, ALLOWED_CALLS, value);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+ ...
+ notification_system_setting_free_system_setting(setting);
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_system_setting_set_dnd_allow_exceptions(notification_system_setting_h system_setting, dnd_allow_exception_type_e type, int value);
+
+/**
+ * @internal
+ * @brief Registers a callback for turn on/off 'Do not disturb' mode by user_data
+ * or 'Do not disturb' mode setting schedule is start or end.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data
+ * @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_IO_ERROR I/O Error
+ * @retval #NOTIFICATION_ERROR_OUT_OF_MEMORY out of memory
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+
+static void changed_cb(void *user_data, int do_not_disturb)
+{
+ ...
+}
+
+...
+{
+ int noti_err = 0;
+
+ ...
+
+ noti_err = notification_register_system_setting_dnd_changed_cb(changed_cb, NULL);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ return 0;
+
+}
+ * @endcode
+ */
+int notification_register_system_setting_dnd_changed_cb(dnd_changed_cb callback, void *user_data);
+int notification_register_system_setting_dnd_changed_cb_for_uid(dnd_changed_cb callback, void *user_data, uid_t uid);
+
+/**
+ * @internal
+ * @brief Unregisters a callback for turn on/off 'Do not disturb' mode by user_data
+ * or 'Do not disturb' mode setting schedule is start or end.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] callback The callback function
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par sample code:
+ * @code
+#include <notification_setting_internal.h>
+...
+
+static void changed_cb(void *user_data, int do_not_disturb)
+{
+ ...
+}
+
+...
+{
+ int noti_err = 0;
+
+ ...
+
+ noti_err = notification_unregister_system_setting_dnd_changed_cb(changed_cb);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+
+ return 0;
+}
+ * @endcode
+ */
+int notification_unregister_system_setting_dnd_changed_cb(dnd_changed_cb callback);
+int notification_unregister_system_setting_dnd_changed_cb_for_uid(dnd_changed_cb callback, uid_t uid);
+
+/**
+ * @internal
+ * @brief Updates the notification setting if the pacakge is installed or updated.
+ * @since_tizen 3.0
+ * @param[in] package_name
+ * @param[in] uid User id
+ * @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_FROM_DB Error from DB query
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int ret;
+
+ ret = notification_setting_insert_package_for_uid(pkg_name, uid);
+ if (ret = NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_setting_insert_package_for_uid(const char *package_name, uid_t uid);
+
+/**
+ * @internal
+ * @brief Deletes the notification setting if the pacakge is uninstalled.
+ * @since_tizen 3.0
+ * @param[in] package_name
+ * @param[in] uid User id
+ * @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_FROM_DB Error from DB query
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int ret;
+
+ ret = notification_setting_delete_package_for_uid(pkg_name, uid);
+ if (ret = NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_setting_delete_package_for_uid(const char *package_name, uid_t uid);
+
+/**
+ * @internal
+ * @brief Updates the notification setting.
+ * @since_tizen 3.0
+ * @param[in] setting Notification setting handle
+ * @param[in] uid User id
+ * @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_OUT_OF_MEMORY Out of memory
+ * @retval #NOTIFICATION_ERROR_IO_ERROR I/O error
+ * @retval #NOTIFICATION_ERROR_SERVICE_NOT_READY No response from notification service
+ * @retval #NOTIFICATION_ERROR_PERMISSION_DENIED Permission denied
+ * @par sample code:
+ * @code
+#include <notification_setting.h>
+...
+{
+ int ret;
+ notification_setting_h setting;
+
+ // Get setting data
+
+ // Update setting data
+
+ ret = notification_setting_update_setting_for_uid(setting, uid);
+ if (ret = NOTIFICATION_ERROR_NONE)
+ return;
+}
+ * @endcode
+ */
+int notification_setting_update_setting_for_uid(notification_setting_h setting, uid_t uid);
+
+/* OLD IMPLEMENTATION */
+int notification_setting_property_set(const char *pkgname, const char *property, const char *value) NOTIFICATION_DEPRECATED_API;
+int notification_setting_property_get(const char *pkgname, const char *property, char **value) NOTIFICATION_DEPRECATED_API;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __NOTIFICATION_SETTING_INTERNAL_H__ */
+
diff --git a/notification/include/notification_setting_service.h b/notification/include/notification_setting_service.h
new file mode 100644
index 0000000..f5a1947
--- /dev/null
+++ b/notification/include/notification_setting_service.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_SETTING_SERVICE_H__
+#define __NOTIFICATION_SETTING_SERVICE_H__
+
+#include <sys/types.h>
+#include <notification.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int notification_setting_db_set(const char *pkgname, const char *property, const char *value);
+int notification_setting_db_get(const char *pkgname, const char *property, char **value);
+
+int notification_setting_db_update(const char *package_name, const char *app_id, int allow_to_notify, int do_not_disturb_except, int visibility_class,
+ int pop_up_notification, int lock_screen_content_level, uid_t uid);
+int notification_setting_db_update_system_setting(int do_not_disturb, int visibility_class,
+ int dnd_schedule_enabled, int dnd_schedule_day,
+ int dnd_start_hour, int dnd_start_min,
+ int dnd_end_hour, int dnd_end_min,
+ int lock_screen_content_level, uid_t uid);
+int notification_setting_db_update_do_not_disturb(int do_not_disturb, uid_t uid);
+
+int noti_setting_service_get_setting_by_app_id(const char *app_id, notification_setting_h *setting, uid_t uid);
+int noti_setting_get_setting_array(notification_setting_h *setting_array, int *count, uid_t uid);
+int noti_system_setting_load_system_setting(notification_system_setting_h *system_setting, uid_t uid);
+int noti_system_setting_get_do_not_disturb(int *do_not_disturb, uid_t uid);
+int notification_system_setting_get_dnd_schedule_enabled_uid(uid_t **uids, int *count);
+int notification_get_dnd_and_allow_to_notify(const char *app_id, int *do_not_disturb, int *do_not_disturb_except, int *allow_to_notify, uid_t uid);
+int notification_system_setting_load_dnd_allow_exception(dnd_allow_exception_h *dnd_allow_exception, int *count, uid_t uid);
+int notification_system_setting_update_dnd_allow_exception(int type, int value, uid_t uid);
+int notification_setting_db_update_app_disabled(const char *app_id, bool value, uid_t uid);
+int notification_setting_db_update_pkg_disabled(const char *pkg_id, bool value, uid_t uid);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __NOTIFICATION_SETTING_SERVICE_H__ */
+
diff --git a/notification/include/notification_shared_file.h b/notification/include/notification_shared_file.h
new file mode 100644
index 0000000..97c7511
--- /dev/null
+++ b/notification/include/notification_shared_file.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef __NOTIFICATION_SHARED_FILE_H__
+#define __NOTIFICATION_SHARED_FILE_H__
+
+#include "notification.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int notification_copy_private_file(const char* src_path, const char* dst_path);
+char *notification_check_file_path_is_private(const char *pkg_id, const char *file_path);
+int notification_set_private_sharing(notification_h noti, uid_t uid);
+void notification_remove_private_sharing(const char *src_app_id, int priv_id, uid_t uid);
+void notification_add_private_sharing_target_id(pid_t pid, const char *sender, uid_t uid);
+void notification_remove_private_sharing_target_id(const char *sender, uid_t uid);
+void notification_calibrate_private_sharing(notification_h updated_noti, notification_h source_noti);
+bool notification_validate_private_sharing(notification_h updated_noti);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __NOTIFICATION_SHARED_FILE_H__ */
diff --git a/notification/include/notification_status.h b/notification/include/notification_status.h
new file mode 100644
index 0000000..b8ff7d1
--- /dev/null
+++ b/notification/include/notification_status.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+
+#ifndef __NOTIFICATION_STATUS_DEF_H__
+#define __NOTIFICATION_STATUS_DEF_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/**
+ * @file notification_status.h
+ */
+
+
+/**
+ * @addtogroup NOTIFICATION_STATUS
+ * @{
+ */
+
+
+/**
+ * @brief Shows a toast popup window with given message.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ * @param[in] message The messages to be posted
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #NOTIFICATION_ERROR_FROM_DBUS Error from DBus
+ * @see #notification_error_e
+ */
+int notification_status_message_post(const char *message);
+
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __NOTIFICATION_STATUS_DEF_H__ */
+
diff --git a/notification/include/notification_status_internal.h b/notification/include/notification_status_internal.h
new file mode 100644
index 0000000..a70fa2e
--- /dev/null
+++ b/notification/include/notification_status_internal.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_STATUS_INTERNAL_DEF_H__
+#define __NOTIFICATION_STATUS_INTERNAL_DEF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @file notification_status_internal.h
+ */
+
+/**
+ * @addtogroup NOTIFICATION_STATUS
+ * @{
+ */
+
+/**
+ * @internal
+ * @brief Unregisters a callback for all notification events.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/notification
+ * @param[in] changed_cb The callback function
+ * @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_register_detailed_changed_cb()
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ noti_err = notification_register_detailed_changed_cb(app_changed_cb, user_data);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_unregister_detailed_changed_cb(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data);
+
+/**
+ * @internal
+ * @brief Called when a new message is posted.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] message The message posted
+ * @param[in] data The user data
+ * @pre notification_status_monitor_message_cb_set() used to register this callback.
+ * @see notification_status_monitor_message_cb_set()
+*/
+typedef void (*notification_status_message_cb)(const char *message, void *data);
+
+/**
+ * @internal
+ * @brief Registers a callback to receive a message.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] callback The callback function
+ * @param[in] data The user_data
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #NOTIFICATION_ERROR_FROM_DBUS Error from DBus
+ */
+int notification_status_monitor_message_cb_set(notification_status_message_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief Unregisters a callback to receive a message.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] callback The callback function
+ * @param[in] data The user_data
+ * @return #NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ */
+int notification_status_monitor_message_cb_unset(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __NOTIFICATION_STATUS_INTERNAL_DEF_H__ */
+
diff --git a/notification/include/notification_text_domain.h b/notification/include/notification_text_domain.h
new file mode 100644
index 0000000..f8c36d8
--- /dev/null
+++ b/notification/include/notification_text_domain.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015 - 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.
+ */
+
+#ifndef __NOTIFICATION_TEXT_DOMAIN_H__
+#define __NOTIFICATION_TEXT_DOMAIN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Sets the text domain to localize the notification.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @param[in] noti The notification handle
+ * @param[in] domain The text domain
+ * @param[in] dir The text dir
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ return;
+ }
+
+ noti_err = notification_set_text_domain(noti, PACKAGE, LOCALEDIR);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_set_text_domain(notification_h noti,
+ const char *domain,
+ const char *dir);
+
+/**
+ * @brief Gets the text domain from the notification handle.
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ * @remarks Do not free returned domain and dir. They are freed when notification_free() or notification_free_list() is called.
+ * @param[in] noti The notification handle
+ * @param[out] domain The domain
+ * @param[out] dir The locale dir
+ * @return #NOTIFICATION_ERROR_NONE on success,
+ * otherwise any other value on failure
+ * @retval #NOTIFICATION_ERROR_NONE Success
+ * @retval #NOTIFICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <notification.h>
+...
+{
+ notification_h noti = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ char *domain = NULL;
+ char *dir = NULL;
+
+ noti_err = notification_get_text_domain(noti, &domain, &dir);
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ return;
+ }
+}
+ * @endcode
+ */
+int notification_get_text_domain(notification_h noti,
+ char **domain,
+ char **dir);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __NOTIFICATION_TEXT_DOMAIN_H__ */
+
diff --git a/notification/include/notification_type.h b/notification/include/notification_type.h
new file mode 100644
index 0000000..bb0d580
--- /dev/null
+++ b/notification/include/notification_type.h
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+
+#ifndef __NOTIFICATION_TYPE_H__
+#define __NOTIFICATION_TYPE_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef NOTIFICATION_DEPRECATED_API
+#if 0 /* __GNUC__ */
+#define NOTIFICATION_DEPRECATED_API __attribute__((deprecated))
+#else
+#define NOTIFICATION_DEPRECATED_API
+#endif
+#endif
+
+
+/**
+ * @file notification_type.h
+ * @brief This file contains type definitions and enumerations for Notification API.
+ */
+
+
+/**
+ * @addtogroup NOTIFICATION_MODULE
+ * @{
+ */
+#define NOTIFICATION_DO_NOT_SHOW_TIME_STAMP -1 /**< Do not show time stamp on the notification. Could be passed as a argument of notification_set_time() */
+
+
+/**
+ * @brief Enumeration for notification layout type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_ly_type {
+ NOTIFICATION_LY_NONE = 0, /**< Default */
+ NOTIFICATION_LY_NOTI_EVENT_SINGLE, /**< Layout for notification. Used to inform single event */
+ NOTIFICATION_LY_NOTI_EVENT_MULTIPLE, /**< Layout for notification. Used to inform multiple event */
+ NOTIFICATION_LY_NOTI_THUMBNAIL, /**< Layout for notification. Used to display images */
+ NOTIFICATION_LY_ONGOING_EVENT, /**< Layout for ongoing notification. Used to display text message.
+ * notifications with NOTIFICATION_LY_ONGOING_EVENT can not be protected from
+ * removing by user since tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif */
+ NOTIFICATION_LY_ONGOING_PROGRESS, /**< Layout for ongoing notification. Used to display progress */
+ NOTIFICATION_LY_EXTENSION, /**< Layout for extended notification (Since 4.0) */
+} notification_ly_type_e;
+
+
+/**
+ * @brief Enumeration for notification launch option type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_launch_option_type {
+ NOTIFICATION_LAUNCH_OPTION_APP_CONTROL = 1, /**< Launching with app control */
+} notification_launch_option_type;
+
+
+/**
+ * @brief Enumeration for event type on notification.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ */
+typedef enum _notification_event_type {
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1 = 0, /**< Event type : Click on button 1 */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2 = 1, /**< Event type : Click on button 2 */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3 = 2, /**< Event type : Click on button 3 */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4 = 3, /**< Event type : Click on button 4 */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5 = 4, /**< Event type : Click on button 5 */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6 = 5, /**< Event type : Click on button 6 */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON = 6, /**< Event type : Click on icon */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL = 7, /**< Event type : Click on thumbnail */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON = 8, /**< Event type : Click on text_input button(Since 3.0) */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_7, /**< Event type : Click on button 7 (Since 5.0) */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_8, /**< Event type : Click on button 8 (Since 5.0) */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_9, /**< Event type : Click on button 9 (Since 5.0) */
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_10, /**< Event type : Click on button 10 (Since 5.0) */
+} notification_event_type_e;
+
+
+/**
+ * @brief Enumeration for notification sound type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_sound_type {
+ NOTIFICATION_SOUND_TYPE_NONE = -1, /**< Default value. no sound */
+ NOTIFICATION_SOUND_TYPE_DEFAULT = 0, /**< Default sound */
+ NOTIFICATION_SOUND_TYPE_USER_DATA, /**< User sound data */
+} notification_sound_type_e;
+
+
+/**
+ * @brief Enumeration for notification vibration type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_vibration_type {
+ NOTIFICATION_VIBRATION_TYPE_NONE = -1, /**< Default value. No vibration */
+ NOTIFICATION_VIBRATION_TYPE_DEFAULT = 0, /**< Default vibrate pattern */
+ NOTIFICATION_VIBRATION_TYPE_USER_DATA, /**< User vibration data */
+} notification_vibration_type_e;
+
+
+/**
+ * @brief Enumeration for notification LED operation.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_led_op {
+ NOTIFICATION_LED_OP_OFF = -1, /**< Default value. Disable the LED notification */
+ NOTIFICATION_LED_OP_ON = 0, /**< Turn on the LED with default color */
+ NOTIFICATION_LED_OP_ON_CUSTOM_COLOR, /**< Turn on the LED with custom color */
+} notification_led_op_e;
+
+
+/**
+ * @deprecated Deprecated since 2.3.1
+ * @brief Enumeration for setting display type of count.
+ * @since_tizen 2.3
+ */
+typedef enum _notification_count_display_type {
+ NOTIFICATION_COUNT_DISPLAY_TYPE_NONE = -1, /**< None */
+ NOTIFICATION_COUNT_DISPLAY_TYPE_LEFT = 0, /**< The number is placed to left */
+ NOTIFICATION_COUNT_DISPLAY_TYPE_IN, /**< The number is placed to center */
+ NOTIFICATION_COUNT_DISPLAY_TYPE_RIGHT, /**< The number is placed to right */
+} notification_count_display_type_e;
+
+
+/**
+ * @brief Enumeration for button.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ */
+typedef enum _notification_button_index {
+ NOTIFICATION_BUTTON_1 = 1, /**< button 1 */
+ NOTIFICATION_BUTTON_2 = 2, /**< button 2 */
+ NOTIFICATION_BUTTON_3 = 3, /**< button 3 */
+ NOTIFICATION_BUTTON_4 = 4, /**< button 4 */
+ NOTIFICATION_BUTTON_5 = 5, /**< button 5 */
+ NOTIFICATION_BUTTON_6 = 6, /**< button 6 */
+ NOTIFICATION_BUTTON_7 = 10, /**< button 7 (Since 5.0) */
+ NOTIFICATION_BUTTON_8 = 11, /**< button 8 (Since 5.0) */
+ NOTIFICATION_BUTTON_9 = 12, /**< button 9 (Since 5.0) */
+ NOTIFICATION_BUTTON_10 = 13, /**< button 10 (Since 5.0) */
+} notification_button_index_e;
+
+
+/**
+ * @brief Enumeration for notification text type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_text_type {
+ NOTIFICATION_TEXT_TYPE_NONE = -1, /**< None */
+ NOTIFICATION_TEXT_TYPE_TITLE = 0, /**< Title */
+ NOTIFICATION_TEXT_TYPE_CONTENT, /**< Content */
+ NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF, /**< Content for content display option is off of the Settings */
+ NOTIFICATION_TEXT_TYPE_EVENT_COUNT, /**< Text to display event count */
+ NOTIFICATION_TEXT_TYPE_INFO_1, /**< Box contents 1 */
+ NOTIFICATION_TEXT_TYPE_INFO_SUB_1, /**< Box contents 1-1 */
+ NOTIFICATION_TEXT_TYPE_INFO_2, /**< Box contents 2 */
+ NOTIFICATION_TEXT_TYPE_INFO_SUB_2, /**< Box contents 2-1 */
+ NOTIFICATION_TEXT_TYPE_INFO_3, /**< Box contents 3 */
+ NOTIFICATION_TEXT_TYPE_INFO_SUB_3, /**< Box contents 3-1 */
+ NOTIFICATION_TEXT_TYPE_GROUP_TITLE, /**< Group title */
+ NOTIFICATION_TEXT_TYPE_GROUP_CONTENT, /**< Group content */
+ NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF, /**< Group content for content display option is off of the Settings */
+ NOTIFICATION_TEXT_TYPE_BUTTON_1, /**< Text on button 1 */
+ NOTIFICATION_TEXT_TYPE_BUTTON_2, /**< Text on button 2 */
+ NOTIFICATION_TEXT_TYPE_BUTTON_3, /**< Text on button 3 */
+ NOTIFICATION_TEXT_TYPE_BUTTON_4, /**< Text on button 4 */
+ NOTIFICATION_TEXT_TYPE_BUTTON_5, /**< Text on button 5 */
+ NOTIFICATION_TEXT_TYPE_BUTTON_6, /**< Text on button 6 */
+ NOTIFICATION_TEXT_TYPE_TEXT_INPUT_PLACEHOLDER, /**< Guide text on the message reply box(Since 3.0) */
+ NOTIFICATION_TEXT_TYPE_TEXT_INPUT_BUTTON, /**< Text on button the on message reply box(Since 3.0) */
+ NOTIFICATION_TEXT_TYPE_CONTENT_EXTENSION, /**< Content for extended notification (Since 4.0) */
+ NOTIFICATION_TEXT_TYPE_BUTTON_7, /**< Text on button 7 (Since 5.0) */
+ NOTIFICATION_TEXT_TYPE_BUTTON_8, /**< Text on button 8 (Since 5.0) */
+ NOTIFICATION_TEXT_TYPE_BUTTON_9, /**< Text on button 9 (Since 5.0) */
+ NOTIFICATION_TEXT_TYPE_BUTTON_10, /**< Text on button 10 (Since 5.0) */
+} notification_text_type_e;
+
+
+/**
+ * @brief Enumeration for image type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_image_type {
+ NOTIFICATION_IMAGE_TYPE_NONE = -1, /**< None */
+ NOTIFICATION_IMAGE_TYPE_ICON = 0, /**< Icon */
+ NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, /**< Indicator icon */
+ NOTIFICATION_IMAGE_TYPE_ICON_FOR_LOCK, /**< Lock screen icon */
+ NOTIFICATION_IMAGE_TYPE_THUMBNAIL, /**< Thumbnail */
+ NOTIFICATION_IMAGE_TYPE_THUMBNAIL_FOR_LOCK, /**< Lock screen thumbnail */
+ NOTIFICATION_IMAGE_TYPE_ICON_SUB, /**< Icon */
+ NOTIFICATION_IMAGE_TYPE_BACKGROUND, /**< image displayed on background */
+ NOTIFICATION_IMAGE_TYPE_LIST_1, /**< Image for thumbnail list */
+ NOTIFICATION_IMAGE_TYPE_LIST_2, /**< Image for thumbnail list */
+ NOTIFICATION_IMAGE_TYPE_LIST_3, /**< Image for thumbnail list */
+ NOTIFICATION_IMAGE_TYPE_LIST_4, /**< Image for thumbnail list */
+ NOTIFICATION_IMAGE_TYPE_LIST_5, /**< Image for thumbnail list */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_1, /**< Image for button 1 */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_2, /**< Image for button 2 */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_3, /**< Image for button 3 */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_4, /**< Image for button 4 */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_5, /**< Image for button 5 */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_6, /**< Image for button 6 */
+ NOTIFICATION_IMAGE_TYPE_TEXT_INPUT_BUTTON, /**< Image for message reply(Since 3.0) */
+ NOTIFICATION_IMAGE_TYPE_EXTENSION, /**< Image for extended notification (Since 4.0) */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_7, /**< Image for button 7 (Since 5.0) */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_8, /**< Image for button 8 (Since 5.0) */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_9, /**< Image for button 9 (Since 5.0) */
+ NOTIFICATION_IMAGE_TYPE_BUTTON_10, /**< Image for button 10 (Since 5.0) */
+} notification_image_type_e;
+
+
+/**
+ * @brief Enumeration for application execution type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_execute_type {
+ NOTIFICATION_EXECUTE_TYPE_NONE = -1, /**< No operation */
+ NOTIFICATION_EXECUTE_TYPE_RESPONDING = 0, /**< Responding action*/
+ NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, /**< Launching when notification data is single */
+ NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH, /**< Launching when notification data is grouping(multi) */
+} notification_execute_type_e;
+
+
+/**
+ * @brief Enumeration for notification type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_type {
+ NOTIFICATION_TYPE_NONE = -1, /**< None */
+ NOTIFICATION_TYPE_NOTI = 0, /**< Notification type */
+ NOTIFICATION_TYPE_ONGOING, /**< Ongoing type */
+} notification_type_e;
+
+
+/**
+ * @brief Enumeration for Group ID.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+enum _notification_group_id {
+ NOTIFICATION_GROUP_ID_NONE = -1, /**< Not Grouping */
+ NOTIFICATION_GROUP_ID_DEFAULT = 0, /**< Notification that has same title is grouping */
+};
+
+
+/**
+ * @brief Enumeration for Private ID.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+enum _notification_priv_id {
+ NOTIFICATION_PRIV_ID_NONE = -1, /**< Internally set priv_id */
+};
+
+
+/**
+ * @brief Enumeration for notification property.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+enum _notification_property {
+ NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE = 0x00000001, /**< Display only SIM card inserted */
+ NOTIFICATION_PROP_DISABLE_APP_LAUNCH = 0x00000002, /**< Disable application launch when it selected */
+ NOTIFICATION_PROP_DISABLE_AUTO_DELETE = 0x00000004, /**< Disable auto delete when it selected */
+ NOTIFICATION_PROP_LAUNCH_UG = 0x00000008, /**< Notification Tray should launch application using appsvc API (Deprecated since 2.3.1) */
+ NOTIFICATION_PROP_DISABLE_TICKERNOTI = 0x00000010, /**< Use notification_set_display_applist API (Deprecated since 2.3.1) */
+ NOTIFICATION_PROP_PERMANENT_DISPLAY = 0x00000020, /**< The notification will not be removed (Deprecated since 2.3.1) */
+ NOTIFICATION_PROP_DISABLE_UPDATE_ON_INSERT = 0x00000040, /**< Disable update when it inserted. */
+ NOTIFICATION_PROP_DISABLE_UPDATE_ON_DELETE = 0x00000080, /**< Disable update when it deleted. */
+ NOTIFICATION_PROP_VOLATILE_DISPLAY = 0x00000100, /**< Deleted when device is rebooted eventhough NOTIFICATION_TYPE_NOTI type */
+};
+
+
+/**
+ * @brief Enumeration for display application list.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+enum _notification_display_applist {
+ NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY = 0x00000001, /**< Notification Tray(Quickpanel) */
+ NOTIFICATION_DISPLAY_APP_TICKER = 0x00000002, /**< Ticker notification */
+ NOTIFICATION_DISPLAY_APP_LOCK = 0x00000004, /**< Lock screen */
+ NOTIFICATION_DISPLAY_APP_INDICATOR = 0x00000008, /**< Indicator */
+ NOTIFICATION_DISPLAY_APP_ACTIVE = 0x00000010, /**< Active notification */
+ NOTIFICATION_DISPLAY_APP_ALL = 0x0000000f, /**< All display application except active notification*/
+};
+
+
+/**
+ * @brief Enumeration for notification operation code.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_op_type {
+ NOTIFICATION_OP_NONE = 0, /**< Default */
+ NOTIFICATION_OP_INSERT = 1, /**< Notification inserted */
+ NOTIFICATION_OP_UPDATE, /**< Notification updated */
+ NOTIFICATION_OP_DELETE, /**< Notification deleted */
+ NOTIFICATION_OP_DELETE_ALL, /**< Notifications deleted */
+ NOTIFICATION_OP_REFRESH, /**< (Deprecated Since 2.3.1) */
+ NOTIFICATION_OP_SERVICE_READY, /**< Notification service is ready */
+} notification_op_type_e;
+
+
+/**
+ * @brief Enumeration for notification operation data code.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_op_data_type {
+ NOTIFICATION_OP_DATA_MIN = 0, /**< Default */
+ NOTIFICATION_OP_DATA_TYPE, /**< Operation type */
+ NOTIFICATION_OP_DATA_PRIV_ID, /**< Private ID */
+ NOTIFICATION_OP_DATA_NOTI, /**< Notification handler */
+ NOTIFICATION_OP_DATA_EXTRA_INFO_1, /**< Reserved */
+ NOTIFICATION_OP_DATA_EXTRA_INFO_2, /**< Reserved */
+} notification_op_data_type_e;
+
+
+/**
+ * @brief Enumeration for notification count position in the text.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notifcation_count_pos_type {
+ NOTIFICATION_COUNT_POS_NONE = -1, /**< Count data is not displaying in the text */
+ NOTIFICATION_COUNT_POS_LEFT = 0, /**< Count data is displaying at the left of the text */
+ NOTIFICATION_COUNT_POS_IN, /**< Count data is displaying in the text */
+ NOTIFICATION_COUNT_POS_RIGHT, /**< Count data is displaying at the right of the text */
+} notification_count_pos_type_e;
+
+
+/**
+ * @brief Enumeration for notification variable parameter type.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef enum _notification_variable_type {
+ NOTIFICATION_VARIABLE_TYPE_NONE = -1, /**< Variable parameter type is NONE */
+ NOTIFICATION_VARIABLE_TYPE_INT = 0, /**< Variable parameter type is int */
+ NOTIFICATION_VARIABLE_TYPE_DOUBLE, /**< Variable parameter type is double */
+ NOTIFICATION_VARIABLE_TYPE_STRING, /**< Variable parameter type is string */
+ NOTIFICATION_VARIABLE_TYPE_COUNT, /**< Variable parameter type is count */
+} notification_variable_type_e;
+
+
+/**
+ * @brief Notification handle.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef struct _notification *notification_h;
+
+
+/**
+ * @brief The structure for notification operation.
+ * @since_tizen @if WEARABLE 2.3.1 @elseif MOBILE 2.3 @endif
+ */
+typedef struct _notification_op {
+ notification_op_type_e type; /**< Notification operation type */
+ int priv_id; /**< private ID */
+ int extra_info_1; /**< Reserved */
+ int extra_info_2; /**< Reserved */
+ notification_h noti; /**< Notification handler */
+} notification_op;
+
+
+/**
+ * @brief Enumeration for permission.
+ * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif
+ */
+typedef enum notification_permission_type {
+ NOTIFICATION_PERMISSION_TYPE_NONE = 0, /**< None */
+ NOTIFICATION_PERMISSION_TYPE_DELETE = 1, /**< Delete */
+ NOTIFICATION_PERMISSION_TYPE_UPDATE = 2, /**< Update */
+} notification_permission_type_e;
+
+/**
+ * @brief Enumeration for notification block state.
+ * @since_tizen 3.0
+ */
+typedef enum notification_block_state {
+ NOTIFICATION_BLOCK_STATE_ALLOWED = 0, /**< The app is allowed to post notifications */
+ NOTIFICATION_BLOCK_STATE_BLOCKED, /**< The app is not allowed to post any notifications */
+ NOTIFICATION_BLOCK_STATE_DO_NOT_DISTURB /**< User set do not disturb mode */
+} notification_block_state_e;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __NOTIFICATION_TYPE_H__ */
+
diff --git a/notification/include/notification_type_internal.h b/notification/include/notification_type_internal.h
new file mode 100644
index 0000000..cd93858
--- /dev/null
+++ b/notification/include/notification_type_internal.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_TYPE_INTERNAL_H__
+#define __NOTIFICATION_TYPE_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup NOTIFICATION_INTERNAL
+ * @{
+ */
+
+#define NOTIFICATION_GLOBAL_UID -1
+#define NOTIFICATION_DISPLAY_APP_HEADS_UP NOTIFICATION_DISPLAY_APP_ACTIVE /* To avoid build error */
+
+#define NOTIFICATION_LY_MAX NOTIFICATION_LY_EXTENSION
+#define NOTIFICATION_EVENT_TYPE_MAX NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_10
+#define NOTIFICATION_SOUND_TYPE_MAX NOTIFICATION_SOUND_TYPE_USER_DATA
+#define NOTIFICATION_VIBRATION_TYPE_MAX NOTIFICATION_VIBRATION_TYPE_USER_DATA
+#define NOTIFICATION_LED_OP_MAX NOTIFICATION_LED_OP_ON_CUSTOM_COLOR
+#define NOTIFICATION_COUNT_DISPLAY_TYPE_MAX NOTIFICATION_COUNT_DISPLAY_TYPE_RIGHT
+#define NOTIFICATION_TEXT_TYPE_MAX NOTIFICATION_TEXT_TYPE_BUTTON_10
+#define NOTIFICATION_IMAGE_TYPE_MAX NOTIFICATION_IMAGE_TYPE_BUTTON_10
+#define NOTIFICATION_EXECUTE_TYPE_MAX NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH
+#define NOTIFICATION_TYPE_MAX NOTIFICATION_TYPE_ONGOING
+#define NOTIFICATION_OP_DATA_MAX NOTIFICATION_OP_DATA_EXTRA_INFO_2
+#define NOTIFICATION_COUNT_POS_MAX NOTIFICATION_COUNT_POS_RIGHT
+#define NOTIFICATION_VARIABLE_TYPE_MAX NOTIFICATION_VARIABLE_TYPE_COUNT
+
+/**
+ * @brief Enumeration for notification resource path type.
+ * @since_tizen 3.0
+ */
+typedef enum _notification_res_path_type {
+ NOTIFICATION_RES_PATH_TYPE_SOUND = NOTIFICATION_IMAGE_TYPE_MAX + 1, /**< Sound */
+ NOTIFICATION_RES_PATH_TYPE_VIBRATION, /**< Vibration */
+} notification_res_path_type_e;
+
+/**
+ * @brief Enumeration for notification ongoing value type.
+ * @since_tizen 3.0
+ */
+typedef enum _notification_ongoing_value_type {
+ NOTIFICATION_ONGOING_VALUE_TYPE_PERCENT = 0, /**< Percent */
+ NOTIFICATION_ONGOING_VALUE_TYPE_TIME, /**< Time */
+} notification_ongoing_value_type_e;
+
+/**
+ * @brief Enumeration for extension event type on notification.
+ * @since_tizen 3.0
+ * @see #notification_event_type_e
+ */
+typedef enum _notification_event_type_extension {
+ NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER = 100, /**< Hidden by user */
+ NOTIFICATION_EVENT_TYPE_HIDDEN_BY_TIMEOUT = 101, /**< Hidden by timeout */
+ NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL = 102, /**< Hidden by external */
+ NOTIFICATION_EVENT_TYPE_PRESSED = 200, /**< Pressed by user */
+ NOTIFICATION_EVENT_TYPE_DELETED = 201, /**< Deleted by user */
+} notification_event_type_extension_e;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __NOTIFICATION_TYPE_INTERNAL_H__ */
diff --git a/notification/include/notification_viewer.h b/notification/include/notification_viewer.h
new file mode 100644
index 0000000..f4b9609
--- /dev/null
+++ b/notification/include/notification_viewer.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+
+#ifndef __NOTIFICATION_VIEWER_H__
+#define __NOTIFICATION_VIEWER_H__
+
+int notification_get_default_viewer(const char *path, char **default_viewer);
+int notification_launch_default_viewer(const char *default_viewer, int priv_id,
+ notification_op_type_e status, uid_t uid);
+
+#endif /* __NOTIFICATION_VIEWER_H__ */
diff --git a/notification/notification.pc.in b/notification/notification.pc.in
new file mode 100644
index 0000000..296e2b1
--- /dev/null
+++ b/notification/notification.pc.in
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: notification
+Description: Notification Library
+Version: @VERSION@
+Requires: bundle glib-2.0 capi-base-common capi-appfw-app-control
+Libs: -L${libdir} -lnotification
+Cflags: -I${includedir}
diff --git a/notification/src/notification.c b/notification/src/notification.c
new file mode 100644
index 0000000..698b150
--- /dev/null
+++ b/notification/src/notification.c
@@ -0,0 +1,2035 @@
+/*
+ * Copyright (c) 2000 - 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <dbus/dbus.h>
+
+#include <app_control.h>
+#include <app_control_internal.h>
+#include <package_manager.h>
+#include <aul.h>
+#include <tizen.h>
+#include <pkgmgr-info.h>
+#include <pkgmgrinfo_type.h>
+
+#include <notification.h>
+#include <notification_list.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_noti.h>
+#include <notification_ongoing.h>
+#include <notification_group.h>
+#include <notification_ipc.h>
+#include <notification_internal.h>
+#include <notification_shared_file.h>
+
+static void (*posted_toast_message_cb)(void *data);
+
+#define NOTI_TEXT_RESULT_LEN 4096
+#define REGULAR_UID_MIN 5000
+
+char *notification_get_app_id_by_pid(int pid)
+{
+#define NOTI_APP_ID_LEN 512
+ char app_id[NOTI_APP_ID_LEN + 1] = { 0, };
+ int ret = AUL_R_OK;
+ int fd;
+ char *dup_app_id;
+ char buf[NOTI_APP_ID_LEN + 1] = { 0, };
+
+ ret = aul_app_get_appid_bypid(pid, app_id, sizeof(app_id));
+ if (ret != AUL_R_OK) {
+
+ snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
+
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ ret = read(fd, app_id, sizeof(app_id) - 1);
+ close(fd);
+
+ if (ret <= 0)
+ return NULL;
+
+ app_id[ret] = '\0';
+ /*!
+ * \NOTE
+ * "ret" is not able to be larger than "sizeof(app_id) - 1",
+ * if the system is not going wrong.
+ */
+ } else {
+ if (strlen(app_id) <= 0)
+ return NULL;
+ }
+
+ dup_app_id = strdup(app_id);
+ if (!dup_app_id)
+ ERR("Failed to strdup, errno[%d]", errno);
+
+ return dup_app_id;
+}
+
+EXPORT_API int notification_set_image(notification_h noti,
+ notification_image_type_e type,
+ const char *image_path)
+{
+ bundle *b = NULL;
+ bundle *priv_b = NULL;
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+ char *priv_path = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_IMAGE_TYPE_NONE
+ || type > NOTIFICATION_IMAGE_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_image_path) {
+ b = noti->b_image_path;
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ if (image_path != NULL)
+ bundle_add_str(b, buf_key, image_path);
+ } else {
+ if (image_path == NULL)
+ return NOTIFICATION_ERROR_NONE;
+
+ b = bundle_create();
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ bundle_add_str(b, buf_key, image_path);
+ noti->b_image_path = b;
+ }
+
+ priv_path = notification_check_file_path_is_private(noti->pkg_id, image_path);
+ if (noti->b_priv_image_path) {
+ priv_b = noti->b_priv_image_path;
+
+ ret_val = NULL;
+ bundle_get_str(priv_b, buf_key, &ret_val);
+ if (ret_val)
+ bundle_del(b, buf_key);
+
+ if (priv_path != NULL)
+ bundle_add_str(priv_b, buf_key, priv_path);
+ } else if (priv_path != NULL) {
+ priv_b = bundle_create();
+ bundle_add_str(priv_b, buf_key, priv_path);
+ noti->b_priv_image_path = priv_b;
+ }
+
+ if (priv_path)
+ free(priv_path);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_image(notification_h noti,
+ notification_image_type_e type,
+ char **image_path)
+{
+ bundle *b = NULL;
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+
+ if (noti == NULL || image_path == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_IMAGE_TYPE_NONE
+ || type > NOTIFICATION_IMAGE_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_image_path) {
+ b = noti->b_image_path;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ *image_path = ret_val;
+ } else {
+ /* If image path bundle does not exist, image path is NULL */
+ *image_path = NULL;
+ }
+
+ /* If image path is NULL and type is ICON, icon path set from AIL */
+ /* order : user icon -> launch_app_id icon -> caller_app_id icon -> service app icon */
+ if (*image_path == NULL && type == NOTIFICATION_IMAGE_TYPE_ICON) {
+ if (noti->app_icon_path != NULL)
+ *image_path = noti->app_icon_path;
+ else
+ *image_path = NULL;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_time(notification_h noti, time_t input_time)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (input_time == 0)
+ noti->time = time(NULL);
+ else
+ noti->time = input_time;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_time(notification_h noti, time_t *ret_time)
+{
+ if (noti == NULL || ret_time == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *ret_time = noti->time;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_insert_time(notification_h noti,
+ time_t *ret_time)
+{
+ if (noti == NULL || ret_time == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *ret_time = noti->insert_time;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_text(notification_h noti,
+ notification_text_type_e type, const char *text,
+ const char *key, int args_type, ...)
+{
+ bundle *b = NULL;
+ char buf_key[32] = { 0, };
+ char buf_val[NOTI_TEXT_RESULT_LEN] = { 0, };
+ char *ret_val = NULL;
+ va_list var_args;
+ notification_variable_type_e var_type;
+ int num_args = 0;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int var_value_int = 0;
+ double var_value_double = 0.0;
+ char *var_value_string = NULL;
+ notification_count_pos_type_e var_value_count =
+ NOTIFICATION_COUNT_POS_NONE;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_TEXT_TYPE_NONE
+ || type > NOTIFICATION_TEXT_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (text != NULL) {
+ if (noti->b_text != NULL) {
+ b = noti->b_text;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ snprintf(buf_val, sizeof(buf_val), "%s", text);
+
+ bundle_add_str(b, buf_key, buf_val);
+ } else {
+ b = bundle_create();
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ snprintf(buf_val, sizeof(buf_val), "%s", text);
+
+ bundle_add_str(b, buf_key, buf_val);
+
+ noti->b_text = b;
+ }
+ } else {
+ if (noti->b_text != NULL) {
+ b = noti->b_text;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+ }
+ }
+
+ if (key != NULL) {
+ if (noti->b_key != NULL) {
+ b = noti->b_key;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ snprintf(buf_val, sizeof(buf_val), "%s", key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ } else {
+ b = bundle_create();
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ snprintf(buf_val, sizeof(buf_val), "%s", key);
+
+ bundle_add_str(b, buf_key, buf_val);
+
+ noti->b_key = b;
+ }
+ } else {
+ if (noti->b_key != NULL) {
+ b = noti->b_key;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+ }
+ }
+
+ if (noti->b_format_args != NULL)
+ b = noti->b_format_args;
+ else
+ b = bundle_create();
+
+ va_start(var_args, args_type);
+
+ var_type = args_type;
+ num_args = 0;
+
+ while (var_type != NOTIFICATION_VARIABLE_TYPE_NONE) {
+ /* Type */
+ snprintf(buf_key, sizeof(buf_key), "%dtype%d", type, num_args);
+ snprintf(buf_val, sizeof(buf_val), "%d", var_type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+
+ switch (var_type) {
+ case NOTIFICATION_VARIABLE_TYPE_INT:
+ var_value_int = va_arg(var_args, int);
+
+ /* Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
+ num_args);
+ snprintf(buf_val, sizeof(buf_val), "%d", var_value_int);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ break;
+
+ case NOTIFICATION_VARIABLE_TYPE_DOUBLE:
+ var_value_double = va_arg(var_args, double);
+
+ /* Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
+ num_args);
+ snprintf(buf_val, sizeof(buf_val), "%.2f",
+ var_value_double);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ break;
+
+ case NOTIFICATION_VARIABLE_TYPE_STRING:
+ var_value_string = va_arg(var_args, char *);
+
+ /* Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
+ num_args);
+ snprintf(buf_val, sizeof(buf_val), "%s",
+ var_value_string);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ break;
+
+ case NOTIFICATION_VARIABLE_TYPE_COUNT:
+ var_value_count =
+ va_arg(var_args, notification_count_pos_type_e);
+
+ /* Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
+ num_args);
+ snprintf(buf_val, sizeof(buf_val), "%d",
+ var_value_count);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ break;
+
+ default:
+ ERR("Invalid variable type. : %d", var_type);
+ noti_err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ break;
+ }
+
+ num_args++;
+ var_type = va_arg(var_args, notification_variable_type_e);
+ }
+ va_end(var_args);
+
+ if (noti_err == NOTIFICATION_ERROR_NONE)
+ noti->num_format_args = num_args;
+ else
+ noti->num_format_args = 0;
+
+ snprintf(buf_key, sizeof(buf_key), "num%d", type);
+ snprintf(buf_val, sizeof(buf_val), "%d", noti->num_format_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+
+ noti->b_format_args = b;
+
+ return noti_err;
+}
+
+EXPORT_API int notification_get_text(notification_h noti,
+ notification_text_type_e type,
+ char **text)
+{
+ char result_str[NOTI_TEXT_RESULT_LEN] = { 0, };
+ char buf_str[NOTI_TEXT_RESULT_LEN] = { 0, };
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+ char *get_str = NULL;
+ char *temp_str = NULL;
+ char *translated_str = NULL;
+ bundle *b = NULL;
+ int num_args = 0;
+ int src_len = 0;
+ int max_len = 0;
+ int ret_variable_int = 0;
+ double ret_variable_double = 0.0;
+ notification_text_type_e text_type = NOTIFICATION_TEXT_TYPE_NONE;
+ notification_variable_type_e ret_var_type = 0;
+
+ if (noti == NULL || text == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_TEXT_TYPE_NONE
+ || type > NOTIFICATION_TEXT_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ text_type = type;
+
+ if (noti->b_key != NULL) {
+ b = noti->b_key;
+
+ /* Get text domain and dir */
+ /* _notification_get_text_domain(noti); */
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ bundle_get_str(b, buf_key, &ret_val);
+
+ if (noti->is_translation == false) {
+ if (ret_val != NULL && noti->domain != NULL
+ && noti->dir != NULL) {
+ /* Get application string */
+ bindtextdomain(noti->domain, noti->dir);
+
+ get_str = dgettext(noti->domain, ret_val);
+ if (get_str == ret_val) /* not found */
+ get_str = NULL;
+ } else if (ret_val != NULL) {
+ /* Get system string */
+ get_str = dgettext("sys_string", ret_val);
+ if (get_str == ret_val) /* not found */
+ get_str = NULL;
+ } else {
+ get_str = NULL;
+ }
+ }
+ }
+
+ if (get_str == NULL && noti->b_text != NULL) {
+ b = noti->b_text;
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ bundle_get_str(b, buf_key, &get_str);
+ }
+
+ if (get_str == NULL && ret_val != NULL)
+ get_str = ret_val; /* fallback for printing anything */
+
+ if (get_str == NULL) {
+ *text = NULL;
+ return NOTIFICATION_ERROR_NONE;
+ }
+
+ /* Get number format args */
+ noti->num_format_args = 0;
+
+ b = noti->b_format_args;
+ if (b != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "num%d", text_type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ noti->num_format_args = atoi(ret_val);
+ }
+
+ if (noti->num_format_args == 0 || noti->is_translation == true) {
+ *text = (char *)get_str;
+ return NOTIFICATION_ERROR_NONE;
+ }
+
+ /* Check first variable is count, LEFT pos */
+ snprintf(buf_key, sizeof(buf_key), "%dtype%d", text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_var_type = atoi(ret_val);
+
+ if (ret_var_type == NOTIFICATION_VARIABLE_TYPE_COUNT) {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_int = atoi(ret_val);
+
+ if (ret_variable_int == NOTIFICATION_COUNT_POS_LEFT) {
+ notification_get_count(noti->type,
+ noti->caller_app_id,
+ noti->group_id,
+ noti->priv_id,
+ &ret_variable_int);
+ snprintf(buf_str, sizeof(buf_str),
+ "%d ", ret_variable_int);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+ num_args++;
+ }
+ }
+
+ /* Check variable IN pos */
+ for (temp_str = (char *)get_str; *temp_str != '\0'; temp_str++) {
+ if (*temp_str != '%') {
+ if (NOTI_TEXT_RESULT_LEN - 1 > strlen(result_str)) {
+ strncat(result_str, temp_str, 1);
+ } else {
+ WARN("The buffer is full");
+ break;
+ }
+ } else {
+ if (*(temp_str + 1) == '%') {
+ if (NOTI_TEXT_RESULT_LEN - 1 > strlen(result_str)) {
+ strncat(result_str, temp_str, 1);
+ } else {
+ WARN("The buffer is full");
+ break;
+ }
+ } else if (*(temp_str + 1) == 'd') {
+ /* Get var Type */
+ ret_variable_int = 0;
+
+ snprintf(buf_key, sizeof(buf_key), "%dtype%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_var_type = atoi(ret_val);
+
+ if (ret_var_type ==
+ NOTIFICATION_VARIABLE_TYPE_COUNT) {
+ /* Get notification count */
+ notification_get_count(noti->type,
+ noti->caller_app_id,
+ noti->group_id,
+ noti->priv_id,
+ &ret_variable_int);
+ } else {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key),
+ "%dvalue%d", text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_int = atoi(ret_val);
+ }
+
+ snprintf(buf_str, sizeof(buf_str), "%d",
+ ret_variable_int);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str++;
+ num_args++;
+ } else if (*(temp_str + 1) == 's') {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ if (ret_val != NULL && noti->domain != NULL
+ && noti->dir != NULL) {
+ /* Get application string */
+ bindtextdomain(noti->domain, noti->dir);
+ translated_str =
+ dgettext(noti->domain, ret_val);
+ INFO("translated_str[%s]", translated_str);
+ } else if (ret_val != NULL) {
+ /* Get system string */
+ translated_str =
+ dgettext("sys_string", ret_val);
+ INFO("translated_str[%s]", translated_str);
+ } else {
+ translated_str = NULL;
+ }
+
+ if (translated_str != NULL) {
+ strncpy(buf_str, translated_str,
+ sizeof(buf_str) - 1);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+ }
+
+ temp_str++;
+ num_args++;
+ } else if (*(temp_str + 1) == 'f') {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_double = atof(ret_val);
+
+ snprintf(buf_str, sizeof(buf_str), "%.2f",
+ ret_variable_double);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str++;
+ num_args++;
+ } else if (*(temp_str + 1) >= '1' && *(temp_str + 1) <= '9') {
+ if (*(temp_str + 3) == 'd') {
+ /* Get var Type */
+ ret_variable_int = 0;
+
+ snprintf(buf_key, sizeof(buf_key),
+ "%dtype%d", text_type,
+ num_args + *(temp_str + 1) - 49);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_var_type = atoi(ret_val);
+
+ if (ret_var_type ==
+ NOTIFICATION_VARIABLE_TYPE_COUNT) {
+ /* Get notification count */
+ notification_get_count(noti->type,
+ noti->caller_app_id,
+ noti->group_id,
+ noti->priv_id,
+ &ret_variable_int);
+ } else {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key),
+ "%dvalue%d", text_type,
+ num_args + *(temp_str + 1) - 49);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_int = atoi(ret_val);
+ }
+
+ snprintf(buf_str, sizeof(buf_str), "%d",
+ ret_variable_int);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str += 3;
+ } else if (*(temp_str + 3) == 's') {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key),
+ "%dvalue%d", text_type,
+ num_args + *(temp_str + 1) - 49);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ snprintf(buf_str, sizeof(buf_str), "%s",
+ ret_val);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str += 3;
+ } else if (*(temp_str + 3) == 'f') {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key),
+ "%dvalue%d", text_type,
+ num_args + *(temp_str + 1) - 49);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_double = atof(ret_val);
+
+ snprintf(buf_str, sizeof(buf_str),
+ "%.2f", ret_variable_double);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str += 3;
+ } else {
+ if (NOTI_TEXT_RESULT_LEN - 1 > strlen(result_str)) {
+ strncat(result_str, temp_str, 1);
+ } else {
+ WARN("The buffer is full");
+ break;
+ }
+ }
+ } else {
+ if (NOTI_TEXT_RESULT_LEN - 1 > strlen(result_str)) {
+ strncat(result_str, temp_str, 1);
+ } else {
+ WARN("The buffer is full");
+ break;
+ }
+ }
+ }
+ }
+
+ /* Check last variable is count, LEFT pos */
+ if (num_args < noti->num_format_args) {
+ snprintf(buf_key, sizeof(buf_key), "%dtype%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_var_type = atoi(ret_val);
+
+ if (ret_var_type == NOTIFICATION_VARIABLE_TYPE_COUNT) {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_int = atoi(ret_val);
+
+ if (ret_variable_int == NOTIFICATION_COUNT_POS_RIGHT) {
+ notification_get_count(noti->type,
+ noti->caller_app_id,
+ noti->group_id,
+ noti->priv_id,
+ &ret_variable_int);
+ snprintf(buf_str, sizeof(buf_str), " %d",
+ ret_variable_int);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ num_args++;
+ }
+ }
+ }
+
+ switch (text_type) {
+ case NOTIFICATION_TEXT_TYPE_TITLE:
+ case NOTIFICATION_TEXT_TYPE_GROUP_TITLE:
+ if (noti->temp_title != NULL)
+ free(noti->temp_title);
+
+ noti->temp_title = strdup(result_str);
+
+ *text = noti->temp_title;
+ break;
+ case NOTIFICATION_TEXT_TYPE_CONTENT:
+ case NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF:
+ case NOTIFICATION_TEXT_TYPE_GROUP_CONTENT:
+ case NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF:
+ if (noti->temp_content !=
+ NULL)
+ free(noti->temp_content);
+
+ noti->temp_content = strdup(result_str);
+
+ *text = noti->temp_content;
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_text_domain(notification_h noti,
+ const char *domain,
+ const char *dir)
+{
+ if (noti == NULL || domain == NULL || dir == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->domain)
+ free(noti->domain);
+
+ noti->domain = strdup(domain);
+
+ if (noti->dir)
+ free(noti->dir);
+
+ noti->dir = strdup(dir);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_text_domain(notification_h noti,
+ char **domain,
+ char **dir)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (domain != NULL && noti->domain != NULL)
+ *domain = noti->domain;
+
+ if (dir != NULL && noti->dir != NULL)
+ *dir = noti->dir;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_time_to_text(notification_h noti, notification_text_type_e type,
+ time_t time)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char buf[256] = { 0, };
+ char buf_tag[512] = { 0, };
+
+ if (noti == NULL || time <= 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_TEXT_TYPE_NONE
+ || type > NOTIFICATION_TEXT_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ snprintf(buf, sizeof(buf), "%lu", time);
+ ret = notification_noti_set_tag(TAG_TIME, buf, buf_tag, sizeof(buf_tag));
+
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ return notification_set_text(noti, type, buf_tag, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+}
+
+EXPORT_API int notification_get_time_from_text(notification_h noti, notification_text_type_e type,
+ time_t *time)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *ret_text = NULL;
+ char *tag_value;
+
+ if (noti == NULL || time == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_TEXT_TYPE_NONE
+ || type > NOTIFICATION_TEXT_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_get_text(noti, type, &ret_text);
+ if (ret != NOTIFICATION_ERROR_NONE || ret_text == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (notification_noti_get_tag_type(ret_text) == TAG_TYPE_INVALID)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ tag_value = notification_noti_strip_tag(ret_text);
+ if (tag_value == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *time = atol(tag_value);
+ free(tag_value);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_sound(notification_h noti,
+ notification_sound_type_e type,
+ const char *path)
+{
+ char *priv_path = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type < NOTIFICATION_SOUND_TYPE_NONE
+ || type > NOTIFICATION_SOUND_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->sound_type = type;
+
+ /* Save sound path if user data type */
+ if (type == NOTIFICATION_SOUND_TYPE_USER_DATA && path != NULL) {
+ if (noti->sound_path != NULL)
+ free(noti->sound_path);
+ noti->sound_path = strdup(path);
+
+ if (noti->priv_sound_path != NULL)
+ free(noti->priv_sound_path);
+
+ priv_path = notification_check_file_path_is_private(noti->pkg_id, path);
+ if (priv_path)
+ noti->priv_sound_path = priv_path;
+ } else {
+ if (noti->sound_path != NULL) {
+ free(noti->sound_path);
+ noti->sound_path = NULL;
+ }
+
+ if (noti->priv_sound_path != NULL) {
+ free(noti->priv_sound_path);
+ noti->priv_sound_path = NULL;
+ }
+
+ if (type == NOTIFICATION_SOUND_TYPE_USER_DATA) {
+ noti->sound_type = NOTIFICATION_SOUND_TYPE_DEFAULT;
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_sound(notification_h noti,
+ notification_sound_type_e *type,
+ const char **path)
+{
+ if (noti == NULL || type == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *type = noti->sound_type;
+
+ /* Set sound path if user data type */
+ if (noti->sound_type == NOTIFICATION_SOUND_TYPE_USER_DATA
+ && path != NULL)
+ *path = noti->sound_path;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_vibration(notification_h noti,
+ notification_vibration_type_e type,
+ const char *path)
+{
+ char *priv_path = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type < NOTIFICATION_VIBRATION_TYPE_NONE
+ || type > NOTIFICATION_VIBRATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->vibration_type = type;
+
+ /* Save sound path if user data type */
+ if (type == NOTIFICATION_VIBRATION_TYPE_USER_DATA && path != NULL) {
+ if (noti->vibration_path != NULL) {
+ free(noti->vibration_path);
+ noti->vibration_path = NULL;
+ }
+ noti->vibration_path = strdup(path);
+
+ if (noti->priv_vibration_path != NULL) {
+ free(noti->priv_vibration_path);
+ noti->priv_vibration_path = NULL;
+ }
+ priv_path = notification_check_file_path_is_private(noti->pkg_id, path);
+ if (priv_path)
+ noti->priv_vibration_path = priv_path;
+ } else {
+ if (noti->vibration_path != NULL) {
+ free(noti->vibration_path);
+ noti->vibration_path = NULL;
+ }
+ if (noti->priv_vibration_path != NULL) {
+ free(noti->priv_vibration_path);
+ noti->priv_vibration_path = NULL;
+ }
+
+ if (type == NOTIFICATION_VIBRATION_TYPE_USER_DATA) {
+ noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_DEFAULT;
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_vibration(notification_h noti,
+ notification_vibration_type_e *type,
+ const char **path)
+{
+ if (noti == NULL || type == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *type = noti->vibration_type;
+ /* Set sound path if user data type */
+ if (noti->vibration_type == NOTIFICATION_VIBRATION_TYPE_USER_DATA
+ && path != NULL)
+ *path = noti->vibration_path;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_led(notification_h noti,
+ notification_led_op_e operation,
+ int led_argb)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (operation < NOTIFICATION_LED_OP_OFF
+ || operation > NOTIFICATION_LED_OP_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->led_operation = operation;
+
+ /* Save led argb if operation is turning on LED with custom color */
+ if (operation == NOTIFICATION_LED_OP_ON_CUSTOM_COLOR)
+ noti->led_argb = led_argb;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_led(notification_h noti,
+ notification_led_op_e *operation,
+ int *led_argb)
+{
+ if (noti == NULL || operation == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *operation = noti->led_operation;
+
+ /* Save led argb if operation is turning on LED with custom color */
+ if (noti->led_operation == NOTIFICATION_LED_OP_ON_CUSTOM_COLOR
+ && led_argb != NULL)
+ *led_argb = noti->led_argb;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_led_time_period(notification_h noti,
+ int on_ms, int off_ms)
+{
+ if (noti == NULL || on_ms < 0 || off_ms < 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->led_on_ms = on_ms;
+ noti->led_off_ms = off_ms;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_led_time_period(notification_h noti,
+ int *on_ms, int *off_ms)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (on_ms)
+ *(on_ms) = noti->led_on_ms;
+ if (off_ms)
+ *(off_ms) = noti->led_off_ms;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_launch_option(notification_h noti,
+ notification_launch_option_type type, void *option)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ int ret = 0;
+ bundle *b = NULL;
+ app_control_h app_control = option;
+
+ if (noti == NULL || app_control == NULL || type != NOTIFICATION_LAUNCH_OPTION_APP_CONTROL) {
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = app_control_export_as_bundle(app_control, &b);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ ERR("Failed to convert appcontrol to bundle[%d]", ret);
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ err = notification_set_execute_option(noti, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, b);
+
+out:
+ if (b)
+ bundle_free(b);
+
+ return err;
+}
+
+EXPORT_API int notification_get_launch_option(notification_h noti,
+ notification_launch_option_type type, void *option)
+{
+ int ret = 0;
+ bundle *b = NULL;
+ app_control_h *app_control = (app_control_h *)option;
+ app_control_h app_control_new = NULL;
+
+ if (noti == NULL || app_control == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type != NOTIFICATION_LAUNCH_OPTION_APP_CONTROL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_get_execute_option(noti,
+ NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH,
+ NULL,
+ &b);
+ if (ret == NOTIFICATION_ERROR_NONE && b != NULL) {
+ ret = app_control_create(&app_control_new);
+ if (ret == APP_CONTROL_ERROR_NONE && app_control_new != NULL) {
+ ret = app_control_import_from_bundle(app_control_new, b);
+ if (ret == APP_CONTROL_ERROR_NONE) {
+ *app_control = app_control_new;
+ } else {
+ /* LCOV_EXCL_START */
+ app_control_destroy(app_control_new);
+ ERR("Failed to import app control from bundle[%d]", ret);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+ } else {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create app control[%d]", ret);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+ } else {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get execute option[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_event_handler(notification_h noti, notification_event_type_e event_type, app_control_h event_handler)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ bundle *app_control_bundle = NULL;
+
+ if (noti == NULL) {
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ ERR("Invalid notification handle");
+ goto out;
+ }
+
+ if (event_type < NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
+ || event_type > NOTIFICATION_EVENT_TYPE_MAX) {
+ ERR("Invalid event type");
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ err = app_control_export_as_bundle(event_handler, &app_control_bundle);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("Failed to export app_control to bundle[%d]", err);
+ goto out;
+ }
+
+ if (noti->b_event_handler[event_type] != NULL)
+ bundle_free(noti->b_event_handler[event_type]);
+
+ noti->b_event_handler[event_type] = app_control_bundle;
+
+out:
+ return err;
+}
+
+EXPORT_API int notification_get_event_handler(notification_h noti, notification_event_type_e event_type, app_control_h *event_handler)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ bundle *b = NULL;
+ app_control_h app_control_new = NULL;
+
+ if (noti == NULL || event_handler == NULL) {
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ ERR("Invalid handle");
+ goto out;
+ }
+
+ if (event_type < NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
+ || event_type > NOTIFICATION_EVENT_TYPE_MAX) {
+ /* LCOV_EXCL_START */
+ ERR("Invalid event type");
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ b = noti->b_event_handler[event_type];
+ if (b == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("No event handler");
+ err = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = app_control_create(&app_control_new);
+ if (err != APP_CONTROL_ERROR_NONE || app_control_new == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create app_control[%d]", err);
+ err = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = app_control_import_from_bundle(app_control_new, b);
+ if (err == APP_CONTROL_ERROR_NONE) {
+ *event_handler = app_control_new;
+ } else {
+ /* LCOV_EXCL_START */
+ app_control_destroy(app_control_new);
+ app_control_new = NULL;
+ ERR("Failed to import app control from bundle[%d]", err);
+ err = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+out:
+ if (event_handler)
+ *event_handler = app_control_new;
+
+ return err;
+}
+
+EXPORT_API int notification_set_property(notification_h noti,
+ int flags)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->flags_for_property = flags;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_property(notification_h noti,
+ int *flags)
+{
+ if (noti == NULL || flags == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *flags = noti->flags_for_property;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_display_applist(notification_h noti,
+ int applist)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (applist == 0xffffffff) /* 0xffffffff means old NOTIFICATION_DISPLAY_APP_ALL */
+ applist = NOTIFICATION_DISPLAY_APP_ALL;
+
+ noti->display_applist = applist;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_display_applist(notification_h noti,
+ int *applist)
+{
+ if (noti == NULL || applist == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *applist = noti->display_applist;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_size(notification_h noti,
+ double size)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->progress_size = size;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_size(notification_h noti,
+ double *size)
+{
+ if (noti == NULL || size == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *size = noti->progress_size;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_progress(notification_h noti,
+ double percentage)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->progress_percentage = percentage;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_progress(notification_h noti,
+ double *percentage)
+{
+ if (noti == NULL || percentage == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *percentage = noti->progress_percentage;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_pkgname(notification_h noti,
+ char **pkgname)
+{
+ if (noti == NULL || pkgname == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->caller_app_id)
+ *pkgname = noti->caller_app_id;
+ else
+ *pkgname = NULL;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_layout(notification_h noti,
+ notification_ly_type_e layout)
+{
+ if (noti == NULL || (layout < NOTIFICATION_LY_NONE || layout > NOTIFICATION_LY_MAX))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->layout = layout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_layout(notification_h noti,
+ notification_ly_type_e *layout)
+{
+ if (noti == NULL || layout == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *layout = noti->layout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_type(notification_h noti,
+ notification_type_e *type)
+{
+ if (noti == NULL || type == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *type = noti->type;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_post(notification_h noti)
+{
+ return notification_post_for_uid(noti, getuid());
+}
+
+EXPORT_API int notification_update(notification_h noti)
+{
+ return notification_update_for_uid(noti, getuid());
+}
+
+EXPORT_API int notification_delete_all(notification_type_e type)
+{
+ return notification_delete_all_for_uid(type, getuid());
+}
+
+EXPORT_API int notification_delete(notification_h noti)
+{
+ return notification_delete_for_uid(noti, getuid());
+}
+
+static int _notification_get_domain_name(const char *app_id, char **name)
+{
+ char *name_token = NULL;
+
+ if (app_id == NULL)
+ return -1;
+
+ /* com.vendor.name -> name */
+ name_token = strrchr(app_id, '.');
+ if (name_token == NULL)
+ return -1;
+
+ name_token++;
+
+ *name = strdup(name_token);
+ if (*name == NULL)
+ return -1;
+
+ return 0;
+}
+
+static notification_h _notification_create(notification_type_e type)
+{
+#define NOTI_PKG_ID_LEN 512
+ notification_h noti = NULL;
+ package_info_h package_info = NULL;
+ pkgmgrinfo_appinfo_h appinfo = NULL;
+ char *domain_name = NULL;
+ char *app_root_path = NULL;
+ char *label = NULL;
+ char locale_directory[PATH_MAX] = { 0, }; /* PATH_MAX 4096 */
+ char pkg_id[NOTI_PKG_ID_LEN + 1] = { 0, };
+ int err = 0;
+
+ if (type <= NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX) {
+ ERR("Invalid notification type[%d]", type);
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ noti->type = type;
+
+ if (type == NOTIFICATION_TYPE_NOTI)
+ noti->layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
+ else if (type == NOTIFICATION_TYPE_ONGOING)
+ noti->layout = NOTIFICATION_LY_ONGOING_PROGRESS;
+
+ noti->group_id = NOTIFICATION_GROUP_ID_NONE;
+ noti->sound_type = NOTIFICATION_SOUND_TYPE_NONE;
+ noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+ noti->led_operation = NOTIFICATION_LED_OP_OFF;
+ noti->display_applist = NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
+ NOTIFICATION_DISPLAY_APP_LOCK |
+ NOTIFICATION_DISPLAY_APP_TICKER |
+ NOTIFICATION_DISPLAY_APP_INDICATOR;
+ noti->auto_remove = true;
+ noti->caller_app_id = notification_get_app_id_by_pid(getpid());
+ if (noti->caller_app_id == NULL) {
+ ERR("Failed to get caller_app_id");
+ err = -1;
+ goto out;
+ }
+
+ if (getuid() < REGULAR_UID_MIN) {
+ noti->pkg_id = strdup(noti->caller_app_id);
+ if (noti->pkg_id == NULL)
+ err = -1;
+ } else {
+ err = aul_app_get_pkgid_bypid(getpid(), pkg_id, sizeof(pkg_id));
+ if (err != AUL_R_OK)
+ noti->pkg_id = strdup(noti->caller_app_id);
+ else
+ noti->pkg_id = strdup(pkg_id);
+
+ if (noti->pkg_id == NULL) {
+ err = -1;
+ goto out;
+ }
+
+ err = _notification_get_domain_name(pkg_id, &domain_name);
+ if (err != 0 || domain_name == NULL) {
+ WARN("Failed to get domain_name");
+ err = 0;
+ /* In the case of the web app,
+ the domain can not be obtained. */
+ goto out;
+ }
+
+ noti->domain = strdup(domain_name);
+
+ err = package_info_create(pkg_id, &package_info);
+ if (err != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
+ /* LCOV_EXCL_START */
+ WARN("Failed to create package_info err[%d] pkg_id[%s]",
+ err, pkg_id);
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = package_info_get_root_path(package_info, &app_root_path);
+ if (err != PACKAGE_MANAGER_ERROR_NONE || app_root_path == NULL) {
+ /* LCOV_EXCL_START */
+ WARN("Failed to get root path err[%d] path[%p]",
+ err, app_root_path);
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ snprintf(locale_directory, PATH_MAX, "%s/res/locale", app_root_path);
+ noti->dir = strdup(locale_directory);
+
+ err = pkgmgrinfo_appinfo_get_usr_appinfo(noti->caller_app_id,
+ getuid(), &appinfo);
+ if (err != PMINFO_R_OK || appinfo == NULL) {
+ WARN("Failed to get appinfo err[%d] caller_app_id[%s]",
+ err, noti->caller_app_id);
+ err = 0;
+ goto out;
+ }
+
+ err = pkgmgrinfo_appinfo_get_label(appinfo, &label);
+ if (err != PMINFO_R_OK || label == NULL) {
+ WARN("Failed to get app_label err[%d]", err);
+ err = 0;
+ goto out;
+ }
+
+ noti->app_label = strdup(label);
+ }
+
+out:
+ if (domain_name)
+ free(domain_name);
+
+ if (app_root_path)
+ free(app_root_path);
+
+ if (package_info)
+ package_info_destroy(package_info);
+
+ if (appinfo)
+ pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
+
+ if (err != 0) {
+ notification_free(noti);
+ noti = NULL;
+ set_last_result(NOTIFICATION_ERROR_IO_ERROR);
+ } else {
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ }
+
+ /*!
+ * \NOTE
+ * Other fields are already initialized with ZERO.
+ */
+
+ return noti;
+}
+
+EXPORT_API notification_h notification_create(notification_type_e type)
+{
+ return _notification_create(type);
+}
+
+EXPORT_API notification_h notification_load_by_tag(const char *tag)
+{
+ return notification_load_by_tag_for_uid(tag, getuid());
+}
+
+EXPORT_API int notification_clone(notification_h noti, notification_h *clone)
+{
+ int i = 0;
+ notification_h new_noti = NULL;
+
+ if (noti == NULL || clone == NULL) {
+ ERR("Invalid handle");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ new_noti = (notification_h) calloc(1, sizeof(struct _notification));
+ if (new_noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ new_noti->type = noti->type;
+ new_noti->layout = noti->layout;
+ new_noti->group_id = noti->group_id;
+ new_noti->internal_group_id = noti->internal_group_id;
+ new_noti->priv_id = noti->priv_id;
+
+ if (noti->pkg_id != NULL)
+ new_noti->pkg_id = strdup(noti->pkg_id);
+
+ if (noti->caller_app_id != NULL)
+ new_noti->caller_app_id = strdup(noti->caller_app_id);
+
+ if (noti->launch_app_id != NULL)
+ new_noti->launch_app_id = strdup(noti->launch_app_id);
+
+ if (noti->args != NULL)
+ new_noti->args = bundle_dup(noti->args);
+
+ if (noti->group_args != NULL)
+ new_noti->group_args = bundle_dup(noti->group_args);
+
+ if (noti->b_execute_option != NULL)
+ new_noti->b_execute_option = bundle_dup(noti->b_execute_option);
+
+ if (noti->b_service_responding != NULL)
+ new_noti->b_service_responding = bundle_dup(noti->b_service_responding);
+
+ if (noti->b_service_single_launch != NULL)
+ new_noti->b_service_single_launch = bundle_dup(noti->b_service_single_launch);
+
+ if (noti->b_service_multi_launch != NULL)
+ new_noti->b_service_multi_launch = bundle_dup(noti->b_service_multi_launch);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i] != NULL)
+ new_noti->b_event_handler[i] = bundle_dup(noti->b_event_handler[i]);
+ }
+
+ if (noti->domain != NULL)
+ new_noti->domain = strdup(noti->domain);
+
+ if (noti->dir != NULL)
+ new_noti->dir = strdup(noti->dir);
+
+ if (noti->b_text != NULL)
+ new_noti->b_text = bundle_dup(noti->b_text);
+
+ if (noti->b_key != NULL)
+ new_noti->b_key = bundle_dup(noti->b_key);
+
+ if (noti->b_format_args != NULL)
+ new_noti->b_format_args = bundle_dup(noti->b_format_args);
+
+ new_noti->num_format_args = noti->num_format_args;
+
+ if (noti->b_image_path != NULL)
+ new_noti->b_image_path = bundle_dup(noti->b_image_path);
+
+ if (noti->b_priv_image_path != NULL)
+ new_noti->b_priv_image_path = bundle_dup(noti->b_priv_image_path);
+
+ new_noti->sound_type = noti->sound_type;
+
+ if (noti->sound_path != NULL)
+ new_noti->sound_path = strdup(noti->sound_path);
+
+ if (noti->priv_sound_path != NULL)
+ new_noti->priv_sound_path = strdup(noti->priv_sound_path);
+
+ new_noti->vibration_type = noti->vibration_type;
+
+ if (noti->vibration_path != NULL)
+ new_noti->vibration_path = strdup(noti->vibration_path);
+
+ if (noti->priv_vibration_path != NULL)
+ new_noti->priv_vibration_path = strdup(noti->priv_vibration_path);
+
+ new_noti->led_operation = noti->led_operation;
+ new_noti->led_argb = noti->led_argb;
+ new_noti->led_on_ms = noti->led_on_ms;
+ new_noti->led_off_ms = noti->led_off_ms;
+ new_noti->time = noti->time;
+ new_noti->insert_time = noti->insert_time;
+ new_noti->flags_for_property = noti->flags_for_property;
+ new_noti->display_applist = noti->display_applist;
+ new_noti->progress_size = noti->progress_size;
+ new_noti->progress_percentage = noti->progress_percentage;
+
+ if (noti->tag != NULL)
+ new_noti->tag = strdup(noti->tag);
+
+ new_noti->ongoing_flag = noti->ongoing_flag;
+ new_noti->ongoing_value_type = noti->ongoing_value_type;
+ new_noti->ongoing_current = noti->ongoing_current;
+ new_noti->ongoing_duration = noti->ongoing_duration;
+ new_noti->auto_remove = noti->auto_remove;
+ new_noti->default_button_index = noti->default_button_index;
+ new_noti->hide_timeout = noti->hide_timeout;
+ new_noti->delete_timeout = noti->delete_timeout;
+ new_noti->text_input_max_length = noti->text_input_max_length;
+ new_noti->event_flag = noti->event_flag;
+ new_noti->is_translation = noti->is_translation;
+ new_noti->extension_image_size = noti->extension_image_size;
+
+ if (noti->app_label != NULL)
+ new_noti->app_label = strdup(noti->app_label);
+
+ new_noti->uid = noti->uid;
+
+ *clone = new_noti;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_free(notification_h noti)
+{
+ int i = 0;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->pkg_id)
+ free(noti->pkg_id);
+
+ if (noti->caller_app_id)
+ free(noti->caller_app_id);
+
+ if (noti->launch_app_id)
+ free(noti->launch_app_id);
+
+ if (noti->args)
+ bundle_free(noti->args);
+
+ if (noti->group_args)
+ bundle_free(noti->group_args);
+
+ if (noti->b_execute_option)
+ bundle_free(noti->b_execute_option);
+
+ if (noti->b_service_responding)
+ bundle_free(noti->b_service_responding);
+
+ if (noti->b_service_single_launch)
+ bundle_free(noti->b_service_single_launch);
+
+ if (noti->b_service_multi_launch)
+ bundle_free(noti->b_service_multi_launch);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i] != NULL)
+ bundle_free(noti->b_event_handler[i]);
+ }
+
+ if (noti->b_image_path)
+ bundle_free(noti->b_image_path);
+
+ if (noti->b_priv_image_path)
+ bundle_free(noti->b_priv_image_path);
+
+ if (noti->sound_path)
+ free(noti->sound_path);
+
+ if (noti->priv_sound_path)
+ free(noti->priv_sound_path);
+
+ if (noti->vibration_path)
+ free(noti->vibration_path);
+
+ if (noti->priv_vibration_path)
+ free(noti->priv_vibration_path);
+
+ if (noti->domain)
+ free(noti->domain);
+
+ if (noti->dir)
+ free(noti->dir);
+
+ if (noti->b_text)
+ bundle_free(noti->b_text);
+
+ if (noti->b_key)
+ bundle_free(noti->b_key);
+
+ if (noti->b_format_args)
+ bundle_free(noti->b_format_args);
+
+ if (noti->app_icon_path)
+ free(noti->app_icon_path);
+
+ if (noti->app_label)
+ free(noti->app_label);
+
+ if (noti->temp_title)
+ free(noti->temp_title);
+
+ if (noti->temp_content)
+ free(noti->temp_content);
+
+ if (noti->tag)
+ free(noti->tag);
+
+ free(noti);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_tag(notification_h noti, const char *tag)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (tag != NULL) {
+ if (noti->tag != NULL)
+ free(noti->tag);
+
+ noti->tag = strdup(tag);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_tag(notification_h noti, const char **tag)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *tag = noti->tag;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+/* LCOV_EXCL_START */
+void notification_call_posted_toast_cb(const char *message)
+{
+ if (posted_toast_message_cb != NULL)
+ posted_toast_message_cb((void *)message);
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_set_ongoing_flag(notification_h noti, bool ongoing_flag)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->ongoing_flag = ongoing_flag;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_ongoing_flag(notification_h noti, bool *ongoing_flag)
+{
+ if (noti == NULL || ongoing_flag == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *ongoing_flag = noti->ongoing_flag;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_add_button(notification_h noti, notification_button_index_e button_index)
+{
+ if (noti == NULL ||
+ !((button_index >= NOTIFICATION_BUTTON_1 && button_index <= NOTIFICATION_BUTTON_6) ||
+ (button_index >= NOTIFICATION_BUTTON_7 && button_index <= NOTIFICATION_BUTTON_10)))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_remove_button(notification_h noti, notification_button_index_e button_index)
+{
+ if (noti == NULL ||
+ !((button_index >= NOTIFICATION_BUTTON_1 && button_index <= NOTIFICATION_BUTTON_6) ||
+ (button_index >= NOTIFICATION_BUTTON_7 && button_index <= NOTIFICATION_BUTTON_10)))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_event_handler[button_index - 1]) {
+ bundle_free(noti->b_event_handler[button_index - 1]);
+ noti->b_event_handler[button_index - 1] = NULL;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_auto_remove(notification_h noti, bool auto_remove)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->auto_remove = auto_remove;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_auto_remove(notification_h noti, bool *auto_remove)
+{
+ if (noti == NULL || auto_remove == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *auto_remove = noti->auto_remove;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_save_as_template(notification_h noti, const char *template_name)
+{
+ if (noti == NULL || template_name == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_request_save_as_template(noti, template_name);
+}
+
+EXPORT_API notification_h notification_create_from_template(const char *template_name)
+{
+ int ret = 0;
+ notification_h noti = NULL;
+
+ if (template_name == NULL) {
+ ERR("Invalid parameter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_ipc_request_create_from_template(noti, template_name);
+
+ set_last_result(ret);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return NULL;
+ }
+
+ return noti;
+}
+
+EXPORT_API int notification_get_noti_block_state(notification_block_state_e *state)
+{
+ int ret;
+ char *app_id;
+ int do_not_disturb;
+ int do_not_disturb_except;
+ int allow_to_notify;
+
+ if (state == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ app_id = notification_get_app_id_by_pid(getpid());
+
+ ret = notification_ipc_get_noti_block_state(app_id, &do_not_disturb, &do_not_disturb_except, &allow_to_notify, getuid());
+
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ if (app_id)
+ free(app_id);
+ return ret;
+ }
+
+ if (allow_to_notify) {
+ *state = NOTIFICATION_BLOCK_STATE_ALLOWED;
+ if (do_not_disturb && !do_not_disturb_except)
+ *state = NOTIFICATION_BLOCK_STATE_DO_NOT_DISTURB;
+ } else {
+ *state = NOTIFICATION_BLOCK_STATE_BLOCKED;
+ }
+
+ if (app_id)
+ free(app_id);
+
+ return ret;
+}
+
+EXPORT_API int notification_set_text_input(notification_h noti, int text_input_max_length)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->text_input_max_length = text_input_max_length;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_extension_image_size(notification_h noti, int height)
+{
+ if (noti == NULL || height <= 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->extension_image_size = height;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_extension_image_size(notification_h noti, int *height)
+{
+ if (noti == NULL || height == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *height = noti->extension_image_size;
+
+ return NOTIFICATION_ERROR_NONE;
+}
diff --git a/notification/src/notification_db.c b/notification/src/notification_db.c
new file mode 100644
index 0000000..485a207
--- /dev/null
+++ b/notification/src/notification_db.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2000 - 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 <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sqlite3.h>
+#include <tizen.h>
+
+#include <notification_error.h>
+#include <notification_debug.h>
+#include <notification_db.h>
+#include "notification_db_query.h"
+
+static bool is_db_corrupted = false;
+
+/* LCOV_EXCL_START */
+static int __check_integrity_cb(void *pid, int argc, char **argv, char **notUsed)
+{
+ char *check_str = "ok";
+
+ if (strncmp(argv[0], check_str, strlen(check_str))) {
+ ERR("db integrity result : %s", argv[0]);
+ is_db_corrupted = true;
+ return -1;
+ }
+
+ INFO("db integrity result : %s", argv[0]);
+ return 0;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static int __recover_corrupted_db(sqlite3 *db)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ char *errmsg = NULL;
+
+ INFO("DB is corrupted, start to recover corrupted db");
+ if (db)
+ sqlite3_close(db);
+ unlink(DBPATH);
+
+ sql_ret = sqlite3_open_v2(DBPATH, &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE,
+ NULL);
+ if (sql_ret != SQLITE_OK) {
+ ERR("Failed to open db[%d]", sql_ret);
+ unlink(DBPATH);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
+ if (sql_ret != SQLITE_OK) {
+ ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+out:
+ if (errmsg)
+ sqlite3_free(errmsg);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_db_init(void)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ sqlite3 *db = NULL;
+ char *errmsg = NULL;
+
+ sql_ret = sqlite3_open_v2(DBPATH, &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
+ if (sql_ret != SQLITE_OK) {
+ ERR("Failed to open db[%d]", ret);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
+ if (sql_ret != SQLITE_OK) {
+ ERR("Failed to exec sqlite[%d][%s]", ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
+ __check_integrity_cb, NULL, &errmsg);
+ if (sql_ret != SQLITE_OK || is_db_corrupted) {
+ ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+out:
+ if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
+ ret = __recover_corrupted_db(db);
+ if (errmsg)
+ sqlite3_free(errmsg);
+ if (db)
+ sqlite3_close(db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+sqlite3 *notification_db_open()
+{
+ int ret = 0;
+ sqlite3 *db = 0;
+
+ ret = access(DBPATH, R_OK | W_OK);
+ if (ret != 0) {
+ /* LCOV_EXCL_START */
+ set_last_result(NOTIFICATION_ERROR_FROM_DB);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ if (ret == SQLITE_PERM)
+ set_last_result(NOTIFICATION_ERROR_PERMISSION_DENIED);
+ else
+ set_last_result(NOTIFICATION_ERROR_FROM_DB);
+
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return db;
+}
+
+int notification_db_close(sqlite3 **db)
+{
+ int ret = 0;
+
+ if (db == NULL || *db == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = sqlite3_close(*db);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to close db[%d]", ret);
+ return NOTIFICATION_ERROR_FROM_DB;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *db = NULL;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_db_exec(sqlite3 *db, const char *query, int *num_changes)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ sqlite3_stmt *stmt = NULL;
+
+ if (db == NULL || query == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Sqlite3 err[%d][%s]", ret, sqlite3_errmsg(db));
+ return NOTIFICATION_ERROR_FROM_DB;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE) {
+ if (num_changes != NULL)
+ *num_changes = sqlite3_changes(db);
+
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ /* LCOV_EXCL_START */
+ ERR("Sqlite err[%d][%s]", ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sqlite3_finalize(stmt);
+
+ return ret;
+}
+
+char *notification_db_column_text(sqlite3_stmt *stmt, int col)
+{
+ const unsigned char *col_text = NULL;
+
+ col_text = sqlite3_column_text(stmt, col);
+ if (col_text == NULL || col_text[0] == '\0')
+ return NULL;
+
+ return strdup((char *)col_text);
+}
+
+bundle *notification_db_column_bundle(sqlite3_stmt *stmt, int col)
+{
+ const unsigned char *col_bundle = NULL;
+
+ col_bundle = sqlite3_column_text(stmt, col);
+ if (col_bundle == NULL || col_bundle[0] == '\0')
+ return NULL;
+
+ return bundle_decode(col_bundle, strlen((char *)col_bundle));
+}
+
diff --git a/notification/src/notification_db_query.h b/notification/src/notification_db_query.h
new file mode 100644
index 0000000..dd6a65a
--- /dev/null
+++ b/notification/src/notification_db_query.h
@@ -0,0 +1,359 @@
+/*
+ * 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.
+ */
+
+#define NOTIFICATION_DB_TABLE "noti_list"
+#define NOTIFICATION_SETTING_DB_TABLE "notification_setting"
+#define NOTIFICATION_SYSTEM_SETTING_DB_TABLE "notification_system_setting"
+#define NOTIFICATION_DND_ALLOW_EXCEPTION "dnd_allow_exception"
+
+#define CREATE_NOTIFICATION_TABLE \
+ "PRAGMA journal_mode = PERSIST;\n" \
+ "PRAGMA synchronous = FULL;\n" \
+ "CREATE TABLE IF NOT EXISTS noti_list (\n" \
+ " type INTEGER NOT NULL,\n" \
+ " layout INTEGER NOT NULL DEFAULT 0,\n" \
+ " pkg_id TEXT NOT NULL,\n" \
+ " caller_app_id TEXT NOT NULL,\n" \
+ " launch_app_id TEXT,\n" \
+ " app_label TEXT,\n" \
+ " image_path TEXT,\n" \
+ " priv_image_path TEXT,\n" \
+ " group_id INTEGER DEFAULT 0,\n" \
+ " internal_group_id INTEGER DEFAULT 0,\n" \
+ " priv_id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+ " title_key TEXT,\n" \
+ " b_text TEXT,\n" \
+ " b_key TEXT,\n" \
+ " tag TEXT,\n" \
+ " b_format_args TEXT,\n" \
+ " num_format_args INTEGER DEFAULT 0,\n" \
+ " text_domain TEXT,\n" \
+ " text_dir TEXT,\n" \
+ " time INTEGER DEFAULT 0,\n" \
+ " insert_time INTEGER DEFAULT 0,\n" \
+ " args TEXT,\n" \
+ " group_args TEXT,\n" \
+ " b_execute_option TEXT,\n" \
+ " b_service_responding TEXT,\n" \
+ " b_service_single_launch TEXT,\n" \
+ " b_service_multi_launch TEXT,\n" \
+ " b_event_handler_click_on_button_1 TEXT,\n" \
+ " b_event_handler_click_on_button_2 TEXT,\n" \
+ " b_event_handler_click_on_button_3 TEXT,\n" \
+ " b_event_handler_click_on_button_4 TEXT,\n" \
+ " b_event_handler_click_on_button_5 TEXT,\n" \
+ " b_event_handler_click_on_button_6 TEXT,\n" \
+ " b_event_handler_click_on_icon TEXT,\n" \
+ " b_event_handler_click_on_thumbnail TEXT,\n" \
+ " b_event_handler_click_on_text_input_button TEXT,\n" \
+ " b_event_handler_click_on_button_7 TEXT,\n" \
+ " b_event_handler_click_on_button_8 TEXT,\n" \
+ " b_event_handler_click_on_button_9 TEXT,\n" \
+ " b_event_handler_click_on_button_10 TEXT,\n" \
+ " sound_type INTEGER DEFAULT 0,\n" \
+ " sound_path TEXT,\n" \
+ " priv_sound_path TEXT,\n" \
+ " vibration_type INTEGER DEFAULT 0,\n" \
+ " vibration_path TEXT,\n" \
+ " priv_vibration_path TEXT,\n" \
+ " led_operation INTEGER DEFAULT 0,\n" \
+ " led_argb INTEGER DEFAULT 0,\n" \
+ " led_on_ms INTEGER DEFAULT -1,\n" \
+ " led_off_ms INTEGER DEFAULT -1,\n" \
+ " flags_for_property INTEGER DEFAULT 0,\n" \
+ " flag_simmode INTEGER DEFAULT 0,\n" \
+ " display_applist INTEGER,\n" \
+ " progress_size DOUBLE DEFAULT 0,\n" \
+ " progress_percentage DOUBLE DEFAULT 0,\n" \
+ " ongoing_flag INTEGER DEFAULT 0,\n" \
+ " ongoing_value_type INTEGER DEFAULT 0,\n" \
+ " ongoing_current INTEGER DEFAULT 0,\n" \
+ " ongoing_duration INTEGER DEFAULT 0,\n" \
+ " auto_remove INTEGER DEFAULT 1,\n" \
+ " default_button_index INTEGER DEFAULT 0,\n" \
+ " hide_timeout INTEGER DEFAULT 0,\n" \
+ " delete_timeout INTEGER DEFAULT 0,\n" \
+ " text_input_max_length INTEGER DEFAULT 0,\n" \
+ " event_flag INTEGER DEFAULT 0,\n" \
+ " extension_image_size INTEGER DEFAULT 0,\n" \
+ " uid INTEGER );\n" \
+ "CREATE TABLE IF NOT EXISTS noti_group_data (\n" \
+ " caller_app_id TEXT NOT NULL,\n" \
+ " group_id INTEGER DEFAULT 0,\n" \
+ " badge INTEGER DEFAULT 0,\n" \
+ " title TEXT,\n" \
+ " content TEXT,\n" \
+ " loc_title TEXT,\n" \
+ " loc_content TEXT,\n" \
+ " count_display_title INTEGER,\n" \
+ " count_display_content INTEGER,\n" \
+ " rowid INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+ " UNIQUE (caller_app_id, group_id));\n" \
+ "CREATE TABLE IF NOT EXISTS ongoing_list (\n" \
+ " caller_app_id TEXT NOT NULL,\n" \
+ " launch_app_id TEXT,\n" \
+ " icon_path TEXT,\n" \
+ " group_id INTEGER DEFAULT 0,\n" \
+ " internal_group_id INTEGER DEFAULT 0,\n" \
+ " priv_id INTERGER NOT NULL,\n" \
+ " title TEXT,\n" \
+ " content TEXT,\n" \
+ " default_content TEXT,\n" \
+ " loc_title TEXT,\n" \
+ " loc_content TEXT,\n" \
+ " loc_default_content TEXT,\n" \
+ " text_domain TEXT,\n" \
+ " text_dir TEXT,\n" \
+ " args TEXT,\n" \
+ " group_args TEXT,\n" \
+ " flag INTEGER DEFAULT 0,\n" \
+ " progress_size DOUBLE DEFAULT 0,\n" \
+ " progress_percentage DOUBLE DEFAULT 0,\n" \
+ " rowid INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+ " UNIQUE (caller_app_id, priv_id));\n" \
+ "CREATE TABLE IF NOT EXISTS notification_setting (\n" \
+ " uid INTEGER,\n" \
+ " package_name TEXT NOT NULL,\n" \
+ " app_id TEXT NOT NULL,\n" \
+ " allow_to_notify INTEGER DEFAULT 1,\n" \
+ " do_not_disturb_except INTEGER DEFAULT 0,\n" \
+ " visibility_class INTEGER DEFAULT 0,\n" \
+ " pop_up_notification INTEGER DEFAULT 1,\n" \
+ " lock_screen_content_level INTEGER DEFAULT 0,\n" \
+ " app_disabled INTEGER DEFAULT 0,\n" \
+ " UNIQUE (uid, package_name, app_id));\n" \
+ "CREATE TABLE IF NOT EXISTS notification_system_setting (\n" \
+ " uid INTEGER,\n" \
+ " do_not_disturb INTEGER DEFAULT 0,\n" \
+ " visibility_class INTEGER DEFAULT 0,\n" \
+ " dnd_schedule_enabled INTEGER DEFAULT 0,\n" \
+ " dnd_schedule_day INTEGER DEFAULT 62,\n" \
+ " dnd_start_hour INTEGER DEFAULT 22,\n" \
+ " dnd_start_min INTEGER DEFAULT 0,\n" \
+ " dnd_end_hour INTEGER DEFAULT 8,\n" \
+ " dnd_end_min INTEGER DEFAULT 0,\n" \
+ " lock_screen_content_level INTEGER DEFAULT 0,\n" \
+ " UNIQUE (uid));\n"\
+ "CREATE TABLE IF NOT EXISTS dnd_allow_exception (\n" \
+ " uid INTEGER,\n" \
+ " type INTEGER DEFAULT 0,\n" \
+ " value INTEGER DEFAULT 0,\n" \
+ " UNIQUE (uid, type));\n" \
+ "CREATE TABLE IF NOT EXISTS noti_template (\n" \
+ " type INTEGER NOT NULL,\n" \
+ " layout INTEGER NOT NULL DEFAULT 0,\n" \
+ " pkg_id TEXT NOT NULL,\n" \
+ " caller_app_id TEXT NOT NULL,\n" \
+ " launch_app_id TEXT,\n" \
+ " app_label TEXT,\n" \
+ " image_path TEXT,\n" \
+ " priv_image_path TEXT,\n" \
+ " group_id INTEGER DEFAULT 0,\n" \
+ " internal_group_id INTEGER DEFAULT 0,\n" \
+ " priv_id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+ " title_key TEXT,\n" \
+ " b_text TEXT,\n" \
+ " b_key TEXT,\n" \
+ " tag TEXT,\n" \
+ " b_format_args TEXT,\n" \
+ " num_format_args INTEGER DEFAULT 0,\n" \
+ " text_domain TEXT,\n" \
+ " text_dir TEXT,\n" \
+ " time INTEGER DEFAULT 0,\n" \
+ " insert_time INTEGER DEFAULT 0,\n" \
+ " args TEXT,\n" \
+ " group_args TEXT,\n" \
+ " b_execute_option TEXT,\n" \
+ " b_service_responding TEXT,\n" \
+ " b_service_single_launch TEXT,\n" \
+ " b_service_multi_launch TEXT,\n" \
+ " b_event_handler_click_on_button_1 TEXT,\n" \
+ " b_event_handler_click_on_button_2 TEXT,\n" \
+ " b_event_handler_click_on_button_3 TEXT,\n" \
+ " b_event_handler_click_on_button_4 TEXT,\n" \
+ " b_event_handler_click_on_button_5 TEXT,\n" \
+ " b_event_handler_click_on_button_6 TEXT,\n" \
+ " b_event_handler_click_on_icon TEXT,\n" \
+ " b_event_handler_click_on_thumbnail TEXT,\n" \
+ " b_event_handler_click_on_text_input_button TEXT,\n" \
+ " b_event_handler_click_on_button_7 TEXT,\n" \
+ " b_event_handler_click_on_button_8 TEXT,\n" \
+ " b_event_handler_click_on_button_9 TEXT,\n" \
+ " b_event_handler_click_on_button_10 TEXT,\n" \
+ " sound_type INTEGER DEFAULT 0,\n" \
+ " sound_path TEXT,\n" \
+ " priv_sound_path TEXT,\n" \
+ " vibration_type INTEGER DEFAULT 0,\n" \
+ " vibration_path TEXT,\n" \
+ " priv_vibration_path TEXT,\n" \
+ " led_operation INTEGER DEFAULT 0,\n" \
+ " led_argb INTEGER DEFAULT 0,\n" \
+ " led_on_ms INTEGER DEFAULT -1,\n" \
+ " led_off_ms INTEGER DEFAULT -1,\n" \
+ " flags_for_property INTEGER DEFAULT 0,\n" \
+ " flag_simmode INTEGER DEFAULT 0,\n" \
+ " display_applist INTEGER,\n" \
+ " progress_size DOUBLE DEFAULT 0,\n" \
+ " progress_percentage DOUBLE DEFAULT 0,\n" \
+ " ongoing_flag INTEGER DEFAULT 0,\n" \
+ " ongoing_value_type INTEGER DEFAULT 0,\n" \
+ " ongoing_current INTEGER DEFAULT 0,\n" \
+ " ongoing_duration INTEGER DEFAULT 0,\n" \
+ " auto_remove INTEGER DEFAULT 1,\n" \
+ " default_button_index INTEGER DEFAULT 0,\n" \
+ " hide_timeout INTEGER DEFAULT 0,\n" \
+ " delete_timeout INTEGER DEFAULT 0,\n" \
+ " text_input_max_length INTEGER DEFAULT 0,\n" \
+ " event_flag INTEGER DEFAULT 0,\n" \
+ " extension_image_size INTEGER DEFAULT 0,\n" \
+ " uid INTEGER,\n" \
+ " template_name TEXT,\n" \
+ " UNIQUE (caller_app_id, template_name));\n"
+
+#define NOTI_LIST_DB_ATTRIBUTES_SELECT \
+ "type, layout, pkg_id, caller_app_id, launch_app_id, app_label, "\
+ "image_path, priv_image_path, group_id, priv_id, b_text, b_key, " \
+ "tag, b_format_args, num_format_args, text_domain, text_dir, " \
+ "time, insert_time, args, group_args, b_execute_option, " \
+ "b_service_responding, b_service_single_launch, b_service_multi_launch, " \
+ "b_event_handler_click_on_button_1, b_event_handler_click_on_button_2, " \
+ "b_event_handler_click_on_button_3, b_event_handler_click_on_button_4, " \
+ "b_event_handler_click_on_button_5, b_event_handler_click_on_button_6, " \
+ "b_event_handler_click_on_icon, b_event_handler_click_on_thumbnail, " \
+ "b_event_handler_click_on_text_input_button, " \
+ "b_event_handler_click_on_button_7, b_event_handler_click_on_button_8, " \
+ "b_event_handler_click_on_button_9, b_event_handler_click_on_button_10, " \
+ "sound_type, sound_path, priv_sound_path, " \
+ "vibration_type, vibration_path, priv_vibration_path, " \
+ "led_operation, led_argb, led_on_ms, led_off_ms, " \
+ "flags_for_property, display_applist, " \
+ "progress_size, progress_percentage, ongoing_flag, ongoing_value_type, " \
+ "ongoing_current, ongoing_duration, auto_remove, default_button_index, " \
+ "hide_timeout, delete_timeout, text_input_max_length, event_flag, "\
+ "extension_image_size, uid"
+
+#define NOTI_LIST_DB_ATTRIBUTES_INSERT \
+ "type, layout, pkg_id, caller_app_id, launch_app_id, app_label, " \
+ "image_path, priv_image_path, group_id, internal_group_id, title_key, " \
+ "b_text, b_key, tag, b_format_args, num_format_args, text_domain, " \
+ "text_dir, time, insert_time, args, group_args, b_execute_option, " \
+ "b_service_responding, b_service_single_launch, b_service_multi_launch, " \
+ "b_event_handler_click_on_button_1, b_event_handler_click_on_button_2, " \
+ "b_event_handler_click_on_button_3, b_event_handler_click_on_button_4, " \
+ "b_event_handler_click_on_button_5, b_event_handler_click_on_button_6, " \
+ "b_event_handler_click_on_icon, b_event_handler_click_on_thumbnail, " \
+ "b_event_handler_click_on_text_input_button, " \
+ "b_event_handler_click_on_button_7, b_event_handler_click_on_button_8, " \
+ "b_event_handler_click_on_button_9, b_event_handler_click_on_button_10, " \
+ "sound_type, sound_path, priv_sound_path, " \
+ "vibration_type, vibration_path, priv_vibration_path, " \
+ "led_operation, led_argb, led_on_ms, led_off_ms, " \
+ "flags_for_property, flag_simmode, display_applist, " \
+ "progress_size, progress_percentage, ongoing_flag, ongoing_value_type, " \
+ "ongoing_current, ongoing_duration, auto_remove, default_button_index, " \
+ "hide_timeout, delete_timeout, text_input_max_length, event_flag, " \
+ "extension_image_size, uid"
+
+#define NOTI_LIST_INSERT_VALUES \
+ "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " \
+ "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " \
+ "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " \
+ "?, ?, ?, ?, ?, ? "
+
+#define NOTI_LIST_DB_ATTRIBUTES_UPDATE \
+ "type = ?, layout = ?, launch_app_id = ?, app_label = ?, " \
+ "image_path = ?, priv_image_path = ?, b_text = ?, b_key = ?, tag = ?, " \
+ "b_format_args = ?, num_format_args = ?, text_domain = ?, text_dir = ?, " \
+ "time = ?, insert_time = ?, args = ?, group_args = ?, " \
+ "b_execute_option = ?, b_service_responding = ?, " \
+ "b_service_single_launch = ?, b_service_multi_launch = ?, " \
+ "b_event_handler_click_on_button_1 = ?, " \
+ "b_event_handler_click_on_button_2 = ?, " \
+ "b_event_handler_click_on_button_3 = ?, " \
+ "b_event_handler_click_on_button_4 = ?, " \
+ "b_event_handler_click_on_button_5 = ?, " \
+ "b_event_handler_click_on_button_6 = ?, " \
+ "b_event_handler_click_on_icon = ?, " \
+ "b_event_handler_click_on_thumbnail = ?, " \
+ "b_event_handler_click_on_text_input_button = ?, " \
+ "b_event_handler_click_on_button_7 = ?, " \
+ "b_event_handler_click_on_button_8 = ?, " \
+ "b_event_handler_click_on_button_9 = ?, " \
+ "b_event_handler_click_on_button_10 = ?, " \
+ "sound_type = ?, sound_path = ?, priv_sound_path = ?, " \
+ "vibration_type = ?, vibration_path = ?, priv_vibration_path = ?, " \
+ "led_operation = ?, led_argb = ?, led_on_ms = ?, led_off_ms = ?, " \
+ "flags_for_property = ?, flag_simmode = ?, display_applist = ?, " \
+ "progress_size = ?, progress_percentage = ?, " \
+ "ongoing_flag = ?, ongoing_value_type = ?, " \
+ "ongoing_current = ?, ongoing_duration = ?, " \
+ "auto_remove = ?, default_button_index = ?, " \
+ "hide_timeout = ?, delete_timeout = ?, " \
+ "text_input_max_length = ?, event_flag = ?, extension_image_size = ? "
+
+#define NOTIFICATION_SETTING_DB_ATTRIBUTES \
+ "package_name, app_id, allow_to_notify, do_not_disturb_except, "\
+ "visibility_class, pop_up_notification, lock_screen_content_level, "\
+ "app_disabled"
+
+#define NOTIFICATION_SYSTEM_SETTING_DB_ATTRIBUTES \
+ "do_not_disturb, visibility_class, dnd_schedule_enabled, " \
+ "dnd_schedule_day, dnd_start_hour, dnd_start_min, dnd_end_hour, " \
+ "dnd_end_min, lock_screen_content_level"
+
+#define __BIND_TEXT(db, stmt, i, text, ret, label) \
+do { \
+ ret = sqlite3_bind_text(stmt, i, text, -1, SQLITE_TRANSIENT); \
+ if (ret != SQLITE_OK) { \
+ ERR("bind error(index %d): [%d][%s]", i, ret, \
+ sqlite3_errmsg(db)); \
+ ret = NOTIFICATION_ERROR_FROM_DB; \
+ goto label; \
+ } \
+} while (0)
+
+#define __BIND_TEXT_STATIC(db, stmt, i, text, ret, label) \
+do { \
+ ret = sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC); \
+ if (ret != SQLITE_OK) { \
+ ERR("bind error(index %d): [%d][%s]", i, ret, \
+ sqlite3_errmsg(db)); \
+ ret = NOTIFICATION_ERROR_FROM_DB; \
+ goto label; \
+ } \
+} while (0)
+
+#define __BIND_INT(db, stmt, i, int, ret, label) \
+do { \
+ ret = sqlite3_bind_int(stmt, i, int); \
+ if (ret != SQLITE_OK) { \
+ ERR("bind error(index %d): [%d][%s]", i, ret, \
+ sqlite3_errmsg(db)); \
+ ret = NOTIFICATION_ERROR_FROM_DB; \
+ goto label; \
+ } \
+} while (0)
+
+#define __BIND_DOUBLE(db, stmt, i, double, ret, label) \
+do { \
+ ret = sqlite3_bind_double(stmt, i, double); \
+ if (ret != SQLITE_OK) { \
+ ERR("bind error(index %d): [%d][%s]", i, ret, \
+ sqlite3_errmsg(db)); \
+ ret = NOTIFICATION_ERROR_FROM_DB; \
+ goto label; \
+ } \
+} while (0)
diff --git a/notification/src/notification_error.c b/notification/src/notification_error.c
new file mode 100644
index 0000000..4e4c98b
--- /dev/null
+++ b/notification/src/notification_error.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2000 - 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 <string.h>
+#include <gio/gio.h>
+#include "notification_error.h"
+
+static const GDBusErrorEntry dbus_error_entries[] = {
+ {NOTIFICATION_ERROR_INVALID_PARAMETER, "org.freedesktop.Notification.Error.INVALID_PARAMETER"},
+ {NOTIFICATION_ERROR_OUT_OF_MEMORY, "org.freedesktop.Notification.Error.OUT_OF_MEMORY"},
+ {NOTIFICATION_ERROR_IO_ERROR, "org.freedesktop.Notification.Error.IO_ERROR"},
+ {NOTIFICATION_ERROR_PERMISSION_DENIED, "org.freedesktop.Notification.Error.PERMISSION_DENIED"},
+ {NOTIFICATION_ERROR_FROM_DB, "org.freedesktop.Notification.Error.FROM_DB"},
+ {NOTIFICATION_ERROR_ALREADY_EXIST_ID, "org.freedesktop.Notification.Error.ALREADY_EXIST_ID"},
+ {NOTIFICATION_ERROR_FROM_DBUS, "org.freedesktop.Notification.Error.FROM_DBUS"},
+ {NOTIFICATION_ERROR_NOT_EXIST_ID, "org.freedesktop.Notification.Error.NOT_EXIST_ID"},
+ {NOTIFICATION_ERROR_SERVICE_NOT_READY, "org.freedesktop.Notification.Error.SERVICE_NOT_READY"},
+ {NOTIFICATION_ERROR_INVALID_OPERATION, "org.freedesktop.Notification.Error.INVALID_OPERATION"},
+ {NOTIFICATION_ERROR_MAX_EXCEEDED, "org.freedesktop.Notification.Error.MAX_EXCEEDED"},
+};
+
+#define NOTIFICATION_ERROR_QUARK "notification-error-quark"
+
+EXPORT_API GQuark notification_error_quark(void)
+{
+ static volatile gsize quark_volatile = 0;
+ static const char *domain_name = NULL;
+
+ /* This is for preventing crash when notification api is used in ui-gadget */
+ /* ui-gadget libraries can be unloaded when it is needed and the static string */
+ /* parameter to g_dbus_error_register_error_domain may cause crash. */
+ GQuark quark = g_quark_try_string(NOTIFICATION_ERROR_QUARK);
+
+ if (quark == 0) {
+ if (domain_name == NULL)
+ domain_name = strdup(NOTIFICATION_ERROR_QUARK);
+ } else {
+ domain_name = NOTIFICATION_ERROR_QUARK;
+ }
+
+ g_dbus_error_register_error_domain(domain_name,
+ &quark_volatile,
+ dbus_error_entries,
+ G_N_ELEMENTS(dbus_error_entries));
+ return (GQuark)quark_volatile;
+}
+
diff --git a/notification/src/notification_group.c b/notification/src/notification_group.c
new file mode 100644
index 0000000..b03496a
--- /dev/null
+++ b/notification/src/notification_group.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2000 - 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <notification_debug.h>
+#include <notification_group.h>
+#include <notification_db.h>
+
+/* LCOV_EXCL_START */
+static int _notification_group_check_data_inserted(const char *app_id,
+ int group_id, sqlite3 *db)
+{
+ sqlite3_stmt *stmt = NULL;
+ char query[NOTIFICATION_QUERY_MAX] = { 0, };
+ int ret;
+ int result;
+
+ snprintf(query, sizeof(query),
+ "select count(*) from noti_group_data where caller_app_id = '%s' and group_id = %d",
+ app_id, group_id);
+
+ ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ERR("Get count DB err(%d) : %s", ret, sqlite3_errmsg(db));
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+
+ sqlite3_finalize(stmt);
+
+ if (result > 0)
+ return NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+
+ INFO("Check Data Inserted appid[%s] group_id[%d] result[%d]",
+ app_id, group_id, result);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_group_set_badge(const char *app_id,
+ int group_id, int count)
+{
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char query[NOTIFICATION_QUERY_MAX] = { 0, };
+ int ret;
+ int result;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ ret = _notification_group_check_data_inserted(app_id, group_id, db);
+
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ /* Insert if does not exist */
+ snprintf(query, sizeof(query), "insert into noti_group_data ("
+ "caller_app_id, group_id, badge, content, loc_content) values ("
+ "'%s', %d, %d, '', '')", app_id, group_id, count);
+
+ } else {
+ /* Update if exist */
+ snprintf(query, sizeof(query), "update noti_group_data "
+ "set badge = %d "
+ "where caller_app_id = '%s' and group_id = %d",
+ count, app_id, group_id);
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ERR("Failed to insert data app_id[%s] err[%d][%s]",
+ app_id, ret, sqlite3_errmsg(db));
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (db)
+ notification_db_close(&db);
+
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE)
+ result = NOTIFICATION_ERROR_NONE;
+ else
+ result = NOTIFICATION_ERROR_FROM_DB;
+
+ sqlite3_finalize(stmt);
+
+ if (db)
+ notification_db_close(&db);
+
+ return result;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_group_get_badge(const char *app_id,
+ int group_id, int *count)
+{
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char query[NOTIFICATION_QUERY_MAX] = { 0, };
+ int ret;
+ int col = 0;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ if (group_id == NOTIFICATION_GROUP_ID_NONE) {
+ ret = _notification_group_check_data_inserted(app_id, group_id, db);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ /* Get all of app_id count if none group id is not exist */
+ snprintf(query, sizeof(query),
+ "select sum(badge) "
+ "from noti_group_data "
+ "where caller_app_id = '%s'", app_id);
+ else
+ /* Get none group id count */
+ snprintf(query, sizeof(query),
+ "select badge "
+ "from noti_group_data "
+ "where caller_app_id = '%s' and group_id = %d",
+ app_id, group_id);
+ } else {
+ snprintf(query, sizeof(query),
+ "select badge "
+ "from noti_group_data "
+ "where caller_app_id = '%s' and group_id = %d",
+ app_id, group_id);
+ }
+
+ INFO("Get badge : query[%s]", query);
+
+ ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ERR("Failed to insert data app_id[%s] err[%d][%s]",
+ app_id, ret, sqlite3_errmsg(db));
+ if (db)
+ notification_db_close(&db);
+
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ *count = sqlite3_column_int(stmt, col++);
+
+ sqlite3_finalize(stmt);
+
+ if (db)
+ notification_db_close(&db);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/src/notification_init.c b/notification/src/notification_init.c
new file mode 100644
index 0000000..72d6cdc
--- /dev/null
+++ b/notification/src/notification_init.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016 - 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.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include <notification_setting.h>
+
+/* For multi-user support */
+#include <tzplatform_config.h>
+
+#define OWNER_ROOT 0
+
+#ifdef _E
+#undef _E
+#endif
+#define _E(fmt, arg...) fprintf(stderr, "[NOTIFICATION_INIT][E][%s,%d] "fmt"\n", \
+ __func__, __LINE__, ##arg)
+
+/* LCOV_EXCL_START */
+static int _is_authorized(void)
+{
+ /* pkg_init db should be called by as root privilege. */
+ uid_t uid = getuid();
+
+ if ((uid_t) OWNER_ROOT == uid)
+ return 1;
+ else
+ return 0;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int main(int argc, char *argv[])
+{
+ int ret;
+ uid_t uid = 0;
+
+ if (!_is_authorized()) {
+ _E("Not an authorized user");
+ return -1;
+ }
+
+ if (argc > 2)
+ uid = (uid_t)atoi(argv[2]);
+
+ ret = notification_setting_refresh_setting_table(uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ _E("Failed to refresh setting table");
+ return ret;
+ }
+
+ ret = notification_system_setting_init_system_setting_table(uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ _E("Failed to init system setting table");
+ return ret;
+ }
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/src/notification_internal.c b/notification/src/notification_internal.c
new file mode 100644
index 0000000..bee6eb3
--- /dev/null
+++ b/notification/src/notification_internal.c
@@ -0,0 +1,2133 @@
+/*
+ * Copyright (c) 2000 - 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+
+#include <aul.h>
+#include <tizen.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <app_control.h>
+#include <app_control_internal.h>
+#include <pkgmgr-info.h>
+
+#include <notification.h>
+#include <notification_list.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_noti.h>
+#include <notification_ongoing.h>
+#include <notification_group.h>
+#include <notification_ipc.h>
+#include <notification_internal.h>
+#include <notification_shared_file.h>
+
+#define REGULAR_UID_MIN 5000
+
+typedef struct _notification_cb_info notification_cb_info_s;
+typedef struct _notification_event_cb_info notification_event_cb_info_s;
+
+typedef enum __notification_cb_type {
+ NOTIFICATION_CB_NORMAL = 1,
+ NOTIFICATION_CB_DETAILED,
+} _notification_cb_type_e;
+
+struct _notification_cb_info {
+ _notification_cb_type_e cb_type;
+ void (*changed_cb)(void *data, notification_type_e type);
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op);
+ void *data;
+};
+
+struct _notification_event_cb_info {
+ int priv_id;
+ event_handler_cb cb;
+ void *userdata;
+};
+
+static GHashTable *_noti_cb_hash = NULL;
+static GList *__noti_event_cb_list = NULL;
+
+void notification_reset_event_handler_list(void)
+{
+ GList *iter;
+ notification_event_cb_info_s *info;
+
+ if (!__noti_event_cb_list)
+ return;
+
+ iter = g_list_first(__noti_event_cb_list);
+ while (iter) {
+ info = g_list_nth_data(iter, 0);
+ if (info)
+ notification_ipc_reset_event_handler(info->priv_id);
+ iter = g_list_next(iter);
+ }
+}
+
+/* LCOV_EXCL_START */
+static void __free_changed_cb_info(gpointer data)
+{
+ notification_cb_info_s *noti_cb_info = (notification_cb_info_s *)data;
+
+ if (noti_cb_info)
+ free(noti_cb_info);
+}
+/* LCOV_EXCL_STOP */
+
+void notification_call_changed_cb_for_uid(notification_op *op_list, int op_num, uid_t uid)
+{
+ notification_type_e type = NOTIFICATION_TYPE_NOTI;
+ GList *noti_cb_list;
+ notification_cb_info_s *noti_cb_info;
+
+ if (_noti_cb_hash == NULL)
+ return;
+
+ noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+ if (noti_cb_list == NULL)
+ return;
+
+ if (op_list == NULL) {
+ ERR("Invalid parameter");
+ return;
+ }
+
+ noti_cb_list = g_list_first(noti_cb_list);
+ notification_get_type(op_list->noti, &type);
+
+ for (; noti_cb_list != NULL; noti_cb_list = noti_cb_list->next) {
+ noti_cb_info = noti_cb_list->data;
+
+ if (noti_cb_info->cb_type == NOTIFICATION_CB_NORMAL && noti_cb_info->changed_cb)
+ noti_cb_info->changed_cb(noti_cb_info->data, type);
+
+ if (noti_cb_info->cb_type == NOTIFICATION_CB_DETAILED && noti_cb_info->detailed_changed_cb) {
+ noti_cb_info->detailed_changed_cb(noti_cb_info->data,
+ type, op_list, op_num);
+ }
+ }
+}
+
+static gint __priv_id_compare(gconstpointer a, gconstpointer b)
+{
+ const notification_event_cb_info_s *info = NULL;
+
+ if (!a)
+ return -1;
+
+ info = (notification_event_cb_info_s *)a;
+
+ if (info->priv_id == GPOINTER_TO_INT(b))
+ return 0;
+
+ return 1;
+}
+
+void notification_call_event_handler_cb(notification_h noti, int event_type)
+{
+ int ret;
+ int priv_id;
+ GList *find_list;
+ notification_event_cb_info_s *info;
+
+ if (__noti_event_cb_list == NULL)
+ return;
+
+ ret = notification_get_id(noti, NULL, &priv_id);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return;
+
+ __noti_event_cb_list = g_list_first(__noti_event_cb_list);
+ find_list = g_list_find_custom(__noti_event_cb_list, GINT_TO_POINTER(priv_id),
+ (GCompareFunc)__priv_id_compare);
+ if (find_list == NULL)
+ return;
+
+ info = g_list_nth_data(find_list, 0);
+ info->cb(noti, event_type, info->userdata);
+}
+
+/* LCOV_EXCL_START */
+void notification_delete_event_handler_cb(int priv_id)
+{
+ GList *delete_list;
+ notification_event_cb_info_s *info;
+
+ if (__noti_event_cb_list == NULL)
+ return;
+
+ __noti_event_cb_list = g_list_first(__noti_event_cb_list);
+ delete_list = g_list_find_custom(__noti_event_cb_list, GINT_TO_POINTER(priv_id),
+ (GCompareFunc)__priv_id_compare);
+
+ if (delete_list == NULL)
+ return;
+
+ info = g_list_nth_data(delete_list, 0);
+ __noti_event_cb_list = g_list_remove(g_list_first(__noti_event_cb_list), info);
+
+ if (info)
+ free(info);
+
+ if (__noti_event_cb_list == NULL)
+ notification_ipc_event_monitor_fini();
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_add_deferred_task(
+ void (*deferred_task_cb)(void *data), void *user_data)
+{
+ if (deferred_task_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_add_deffered_task(deferred_task_cb, user_data);
+}
+
+EXPORT_API int notification_del_deferred_task(
+ void (*deferred_task_cb)(void *data))
+{
+ if (deferred_task_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_del_deffered_task(deferred_task_cb);
+}
+
+EXPORT_API int notification_resister_changed_cb_for_uid(
+ void (*changed_cb)(void *data, notification_type_e type),
+ void *user_data, uid_t uid)
+{
+ GList *noti_cb_list;
+ notification_cb_info_s *noti_cb_info_new;
+
+ if (changed_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_cb_hash == NULL)
+ _noti_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
+ if (noti_cb_info_new == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ noti_cb_info_new->cb_type = NOTIFICATION_CB_NORMAL;
+ noti_cb_info_new->changed_cb = changed_cb;
+ noti_cb_info_new->detailed_changed_cb = NULL;
+ noti_cb_info_new->data = user_data;
+
+ noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_cb_list == NULL) {
+ noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
+ g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
+ } else {
+ noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
+ }
+
+ if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE) {
+ notification_unresister_changed_cb_for_uid(changed_cb, uid);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_resister_changed_cb(
+ void (*changed_cb)(void *data, notification_type_e type),
+ void *user_data)
+{
+ return notification_resister_changed_cb_for_uid(changed_cb, user_data, getuid());
+}
+
+static gint _noti_changed_compare(gconstpointer a, gconstpointer b)
+{
+ const struct _notification_cb_info *info = NULL;
+
+ if (!a)
+ return -1;
+ info = (notification_cb_info_s *)a;
+
+ if (info->changed_cb == b)
+ return 0;
+
+ return 1;
+}
+
+EXPORT_API int notification_unresister_changed_cb_for_uid(
+ void (*changed_cb)(void *data, notification_type_e type), uid_t uid)
+{
+ notification_cb_info_s *noti_cb_info;
+ GList *noti_cb_list;
+ GList *delete_cb_list;
+
+ if (changed_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_cb_hash == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+ if (noti_cb_list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_cb_list = g_list_first(noti_cb_list);
+ delete_cb_list = g_list_find_custom(noti_cb_list, (gconstpointer)changed_cb,
+ (GCompareFunc)_noti_changed_compare);
+ if (delete_cb_list) {
+ noti_cb_info = g_list_nth_data(delete_cb_list, 0);
+ noti_cb_list = g_list_delete_link(noti_cb_list, delete_cb_list);
+ __free_changed_cb_info(noti_cb_info);
+
+ if (noti_cb_list == NULL) {
+ g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
+ } else {
+ noti_cb_list = g_list_first(noti_cb_list);
+ g_hash_table_replace(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
+ }
+
+ } else {
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (g_hash_table_size(_noti_cb_hash) == 0)
+ notification_ipc_monitor_fini();
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_unresister_changed_cb(
+ void (*changed_cb)(void *data, notification_type_e type))
+{
+ return notification_unresister_changed_cb_for_uid(changed_cb, getuid());
+}
+
+EXPORT_API int notification_update_progress(notification_h noti,
+ int priv_id,
+ double progress)
+{
+ int ret;
+ int input_priv_id;
+ char *caller_app_id;
+ double input_progress;
+
+ if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ input_priv_id = noti->priv_id;
+ } else {
+ input_priv_id = priv_id;
+ }
+
+ if (noti == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(noti->caller_app_id);
+
+ if (progress < 0.0)
+ input_progress = 0.0;
+ else if (progress > 1.0)
+ input_progress = 1.0;
+ else
+ input_progress = progress;
+
+ ret = notification_ongoing_update_progress(caller_app_id, input_priv_id,
+ input_progress);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+
+EXPORT_API int notification_update_size(notification_h noti,
+ int priv_id,
+ double size)
+{
+ int ret;
+ int input_priv_id;
+ char *caller_app_id;
+ double input_size;
+
+ if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ input_priv_id = noti->priv_id;
+ } else {
+ input_priv_id = priv_id;
+ }
+
+ if (noti == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(noti->caller_app_id);
+
+ if (size < 0.0)
+ input_size = 0.0;
+ else
+ input_size = size;
+
+ ret = notification_ongoing_update_size(caller_app_id, input_priv_id,
+ input_size);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+
+EXPORT_API int notification_update_content(notification_h noti,
+ int priv_id,
+ const char *content)
+{
+ char *caller_app_id;
+ int input_priv_id;
+ int ret;
+
+ if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ input_priv_id = noti->priv_id;
+ } else {
+ input_priv_id = priv_id;
+ }
+
+ if (noti == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(noti->caller_app_id);
+
+ ret = notification_ongoing_update_content(caller_app_id, input_priv_id,
+ content);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+
+/* notification_set_icon will be removed */
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_icon(notification_h noti,
+ const char *icon_path)
+{
+ return notification_set_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, icon_path);
+}
+/* LCOV_EXCL_STOP */
+
+/* notification_get_icon will be removed */
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_icon(notification_h noti,
+ char **icon_path)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *ret_image_path = NULL;
+
+ ret = notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON,
+ &ret_image_path);
+
+ if (ret == NOTIFICATION_ERROR_NONE && icon_path != NULL)
+ *icon_path = ret_image_path;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_translate_localized_text(notification_h noti)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *ret_text = NULL;
+ char buf_key[32];
+ char *bundle_val = NULL;
+ char *new_text;
+ bundle *b;
+ notification_text_type_e type = NOTIFICATION_TEXT_TYPE_TITLE;
+
+ noti->is_translation = false;
+
+ for (; type <= NOTIFICATION_TEXT_TYPE_MAX; type++) {
+ ret = notification_get_text(noti, type, &ret_text);
+ if (ret == NOTIFICATION_ERROR_NONE && ret_text) {
+ if (noti->b_text == NULL) {
+ noti->b_text = bundle_create();
+ if (noti->b_text == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ b = noti->b_text;
+
+ new_text = strdup(ret_text);
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ bundle_get_str(b, buf_key, &bundle_val);
+ if (bundle_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, new_text);
+ free(new_text);
+ new_text = NULL;
+
+ noti->num_format_args = 0;
+ bundle_val = NULL;
+ }
+ }
+
+ noti->is_translation = true;
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_title(notification_h noti,
+ const char *title,
+ const char *loc_title)
+{
+ return notification_set_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
+ title, loc_title,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_title(notification_h noti,
+ char **title,
+ char **loc_title)
+{
+ int ret;
+ char *ret_text = NULL;
+
+ ret = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
+ &ret_text);
+
+ if (title != NULL)
+ *title = ret_text;
+
+ if (loc_title != NULL)
+ *loc_title = NULL;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_content(notification_h noti,
+ const char *content,
+ const char *loc_content)
+{
+ return notification_set_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
+ content, loc_content,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_content(notification_h noti,
+ char **content,
+ char **loc_content)
+{
+ int ret;
+ char *ret_text = NULL;
+
+ ret = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
+ &ret_text);
+
+ if (content != NULL)
+ *content = ret_text;
+
+ if (loc_content != NULL)
+ *loc_content = NULL;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_application(notification_h noti,
+ const char *app_id)
+{
+ if (noti == NULL || app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->launch_app_id)
+ free(noti->launch_app_id);
+
+ noti->launch_app_id = strdup(app_id);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_application(notification_h noti,
+ char **app_id)
+{
+ if (noti == NULL || app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->launch_app_id)
+ *app_id = noti->launch_app_id;
+ else
+ *app_id = noti->caller_app_id;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_args(notification_h noti, bundle *args,
+ bundle *group_args)
+{
+ if (noti == NULL || args == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->args)
+ bundle_free(noti->args);
+
+ noti->args = bundle_dup(args);
+
+ if (noti->group_args) {
+ bundle_free(noti->group_args);
+ noti->group_args = NULL;
+ }
+
+ if (group_args != NULL)
+ noti->group_args = bundle_dup(group_args);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_args(notification_h noti,
+ bundle **args,
+ bundle **group_args)
+{
+ if (noti == NULL || args == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->args)
+ *args = noti->args;
+ else
+ *args = NULL;
+
+ if (group_args != NULL && noti->group_args)
+ *group_args = noti->group_args;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_get_grouping_list_for_uid(notification_type_e type, int count,
+ notification_list_h *list, uid_t uid)
+{
+ notification_list_h get_list = NULL;
+ int ret = 0;
+
+ if (list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_noti_get_grouping_list(type, 1, count, &get_list, NULL, uid);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ *list = get_list;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_grouping_list(notification_type_e type, int count,
+ notification_list_h *list)
+{
+ return notification_get_grouping_list_for_uid(type, count, list, getuid());
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_delete_group_by_group_id(const char *app_id,
+ notification_type_e type,
+ int group_id)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_delete_multiple(type, caller_app_id, getuid());
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_delete_group_by_priv_id_for_uid(const char *app_id,
+ notification_type_e type,
+ int priv_id, uid_t uid)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_delete_single(type, caller_app_id, priv_id, uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_delete_group_by_priv_id(const char *app_id,
+ notification_type_e type,
+ int priv_id)
+{
+ return notification_delete_group_by_priv_id_for_uid(app_id, type, priv_id, getuid());
+}
+
+int notification_get_count_for_uid(notification_type_e type,
+ const char *app_id,
+ int group_id,
+ int priv_id, int *count,
+ uid_t uid)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (count == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_get_count(
+ type,
+ caller_app_id,
+ group_id,
+ priv_id,
+ count,
+ uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_count(notification_type_e type,
+ const char *app_id,
+ int group_id,
+ int priv_id, int *count)
+{
+ return notification_get_count_for_uid(type, app_id, group_id, priv_id, count, getuid());
+}
+
+int notification_clear_for_uid(notification_type_e type, uid_t uid)
+{
+ if (type <= NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_request_delete_multiple(type, NULL, uid);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_clear(notification_type_e type)
+{
+ return notification_clear_for_uid(type, getuid());
+}
+
+EXPORT_API int notification_op_get_data(notification_op *noti_op, notification_op_data_type_e type,
+ void *data)
+{
+ if (noti_op == NULL || data == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ switch (type) {
+ case NOTIFICATION_OP_DATA_TYPE:
+ *((int *)data) = noti_op->type;
+ break;
+ case NOTIFICATION_OP_DATA_PRIV_ID:
+ *((int *)data) = noti_op->priv_id;
+ break;
+ case NOTIFICATION_OP_DATA_NOTI:
+ *((notification_h *)data) = noti_op->noti;
+ break;
+ case NOTIFICATION_OP_DATA_EXTRA_INFO_1:
+ *((int *)data) = noti_op->extra_info_1;
+ break;
+ case NOTIFICATION_OP_DATA_EXTRA_INFO_2:
+ *((int *)data) = noti_op->extra_info_2;
+ break;
+ default:
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_pkgname(notification_h noti,
+ const char *pkgname)
+{
+ return notification_set_app_id(noti, pkgname);
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_set_app_id(notification_h noti,
+ const char *app_id)
+{
+ if (noti == NULL || app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ /* Remove previous caller app_id */
+ if (noti->caller_app_id) {
+ free(noti->caller_app_id);
+ noti->caller_app_id = NULL;
+ }
+
+ noti->caller_app_id = strdup(app_id);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+/* LCOV_EXCL_START */
+int notification_delete_all_by_type_for_uid(const char *app_id,
+ notification_type_e type, uid_t uid)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (type <= NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_delete_multiple(type, caller_app_id, uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_delete_all_by_type(const char *app_id,
+ notification_type_e type)
+{
+ return notification_delete_all_by_type_for_uid(app_id, type, getuid());
+}
+
+int notification_delete_by_priv_id_for_uid(const char *app_id,
+ notification_type_e type,
+ int priv_id,
+ uid_t uid)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (priv_id <= NOTIFICATION_PRIV_ID_NONE)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_delete_single(type, caller_app_id, priv_id, uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_delete_by_priv_id(const char *app_id,
+ notification_type_e type,
+ int priv_id)
+{
+ return notification_delete_by_priv_id_for_uid(app_id, type, priv_id, getuid());
+}
+
+EXPORT_API int notification_set_execute_option(notification_h noti,
+ notification_execute_type_e type,
+ const char *text,
+ const char *key,
+ bundle *service_handle)
+{
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+ bundle *b = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
+ || type > NOTIFICATION_EXECUTE_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_execute_option == NULL)
+ noti->b_execute_option = bundle_create();
+
+ b = noti->b_execute_option;
+
+ if (text != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "text%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, text);
+ }
+
+ if (key != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "key%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, key);
+ }
+
+ switch ((int)type) {
+ case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
+ if (noti->b_service_responding != NULL) {
+ bundle_free(noti->b_service_responding);
+ noti->b_service_responding = NULL;
+ }
+
+ if (service_handle != NULL)
+ noti->b_service_responding = bundle_dup(service_handle);
+
+ break;
+ case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
+ if (noti->b_service_single_launch != NULL) {
+ bundle_free(noti->b_service_single_launch);
+ noti->b_service_single_launch = NULL;
+ }
+
+ if (service_handle != NULL)
+ noti->b_service_single_launch =
+ bundle_dup(service_handle);
+
+ break;
+ case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
+ if (noti->b_service_multi_launch != NULL) {
+ bundle_free(noti->b_service_multi_launch);
+ noti->b_service_multi_launch = NULL;
+ }
+
+ if (service_handle != NULL)
+ noti->b_service_multi_launch =
+ bundle_dup(service_handle);
+
+ break;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_id(notification_h noti,
+ int *group_id, int *priv_id)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (group_id) {
+ if (noti->group_id < NOTIFICATION_GROUP_ID_NONE)
+ *group_id = NOTIFICATION_GROUP_ID_NONE;
+ else
+ *group_id = noti->group_id;
+ }
+
+ if (priv_id)
+ *priv_id = noti->priv_id;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_set_priv_id(notification_h noti, int priv_id)
+{
+ if (noti == NULL || priv_id <= 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->priv_id = priv_id;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+/* LCOV_EXCL_START */
+notification_h notification_load_for_uid(char *app_id,
+ int priv_id, uid_t uid)
+{
+ int ret;
+ notification_h noti;
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ ret = notification_ipc_request_load_noti_by_priv_id(noti, app_id, priv_id, uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ set_last_result(ret);
+ return NULL;
+ }
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+
+ return noti;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API notification_h notification_load(char *app_id,
+ int priv_id)
+{
+ return notification_load_for_uid(app_id, priv_id, getuid());
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API notification_h notification_new(notification_type_e type,
+ int group_id, int priv_id)
+{
+ return notification_create(type);
+}
+
+static void _notification_get_text_domain(notification_h noti)
+{
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_execute_option(notification_h noti,
+ notification_execute_type_e type,
+ const char **text,
+ bundle **service_handle)
+{
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+ char *get_str = NULL;
+ bundle *b = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
+ || type > NOTIFICATION_EXECUTE_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ switch (type) {
+ case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
+ b = noti->b_service_responding;
+ break;
+ case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
+ b = noti->b_service_single_launch;
+ break;
+ case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
+ b = noti->b_service_multi_launch;
+ break;
+ default:
+ break;
+ }
+
+ if (b != NULL) {
+ if (text != NULL) {
+ if (noti->domain == NULL || noti->dir == NULL)
+ _notification_get_text_domain(noti);
+
+ snprintf(buf_key, sizeof(buf_key), "key%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL && noti->domain != NULL
+ && noti->dir != NULL) {
+ bindtextdomain(noti->domain, noti->dir);
+
+ get_str = dgettext(noti->domain, ret_val);
+
+ *text = get_str;
+ } else if (ret_val != NULL) {
+ get_str = dgettext("sys_string", ret_val);
+
+ *text = get_str;
+ } else {
+ snprintf(buf_key, sizeof(buf_key), "text%d",
+ type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ *text = ret_val;
+ }
+ }
+ }
+
+ if (service_handle != NULL)
+ *service_handle = b;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_insert_for_uid(notification_h noti,
+ int *priv_id, uid_t uid)
+{
+ int ret;
+ int id;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->type <= NOTIFICATION_TYPE_NONE
+ || noti->type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->uid = uid;
+ noti->insert_time = time(NULL);
+
+ ret = notification_ipc_request_insert(noti, &id);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ noti->priv_id = id;
+
+ /* If priv_id is valid data, set priv_id */
+ if (priv_id != NULL)
+ *priv_id = noti->priv_id;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_insert(notification_h noti,
+ int *priv_id)
+{
+ return notification_insert_for_uid(noti, priv_id, getuid());
+}
+
+EXPORT_API int notification_update_async_for_uid(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data), void *user_data, uid_t uid)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->uid = uid;
+ /* Update insert time ? */
+ noti->insert_time = time(NULL);
+
+ return notification_ipc_request_update_async(noti, result_cb, user_data);
+}
+
+EXPORT_API int notification_update_async(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data), void *user_data)
+{
+ return notification_update_async_for_uid(noti, result_cb, user_data, getuid());
+}
+
+EXPORT_API int notification_register_detailed_changed_cb_for_uid(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data, uid_t uid)
+{
+ GList *noti_cb_list = NULL;
+ notification_cb_info_s *noti_cb_info_new = NULL;
+
+ if (detailed_changed_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_cb_hash == NULL)
+ _noti_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
+ if (noti_cb_info_new == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ noti_cb_info_new->cb_type = NOTIFICATION_CB_DETAILED;
+ noti_cb_info_new->changed_cb = NULL;
+ noti_cb_info_new->detailed_changed_cb = detailed_changed_cb;
+ noti_cb_info_new->data = user_data;
+
+ noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_cb_list == NULL) {
+ noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
+ g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
+ } else {
+ noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
+ }
+
+ if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE) {
+ notification_unregister_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, uid);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_register_detailed_changed_cb(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data)
+{
+ return notification_register_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
+}
+
+static gint _noti_detailed_changed_compare(gconstpointer a, gconstpointer b)
+{
+ const struct _notification_cb_info *info = NULL;
+
+ if (!a)
+ return -1;
+ info = (notification_cb_info_s *)a;
+
+ if (info->detailed_changed_cb == b)
+ return 0;
+
+ return 1;
+}
+
+EXPORT_API int notification_unregister_detailed_changed_cb_for_uid(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data, uid_t uid)
+{
+ notification_cb_info_s *noti_cb_info;
+ GList *noti_cb_list;
+ GList *delete_cb_list;
+
+ if (detailed_changed_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_cb_hash == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_cb_list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_cb_list = g_list_first(noti_cb_list);
+ delete_cb_list = g_list_find_custom(noti_cb_list, (gconstpointer)detailed_changed_cb,
+ (GCompareFunc)_noti_detailed_changed_compare);
+
+ if (delete_cb_list) {
+ noti_cb_info = (notification_cb_info_s *)g_list_nth_data(delete_cb_list, 0);
+ noti_cb_list = g_list_delete_link(noti_cb_list, delete_cb_list);
+ __free_changed_cb_info(noti_cb_info);
+ if (noti_cb_list == NULL) {
+ g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
+ } else {
+ noti_cb_list = g_list_first(noti_cb_list);
+ g_hash_table_replace(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
+ }
+
+ } else {
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (g_hash_table_size(_noti_cb_hash) == 0)
+ notification_ipc_monitor_fini();
+
+ return NOTIFICATION_ERROR_NONE;
+
+}
+
+EXPORT_API int notification_unregister_detailed_changed_cb(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data)
+{
+ return notification_unregister_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_is_service_ready(void)
+{
+ return notification_ipc_is_master_ready();
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_set_uid(notification_h noti,
+ uid_t uid)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->uid = uid;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_uid(notification_h noti,
+ uid_t *uid)
+{
+ if (noti == NULL || uid == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *uid = noti->uid;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static GList *__copy_private_file(notification_h noti)
+{
+ bundle *dst_b;
+ bundle *src_b;
+ char buf_key[32];
+ char *src_path;
+ char *dst_path;
+ int i;
+ GList *file_list = NULL;
+ int ret;
+
+ if (noti->b_priv_image_path && noti->b_image_path) {
+ dst_b = noti->b_priv_image_path;
+ src_b = noti->b_image_path;
+ for (i = NOTIFICATION_IMAGE_TYPE_ICON; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ src_path = NULL;
+ dst_path = NULL;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+
+ bundle_get_str(dst_b, buf_key, &dst_path);
+ if (dst_path == NULL)
+ continue;
+
+ bundle_get_str(src_b, buf_key, &src_path);
+ if (src_path == NULL)
+ continue;
+
+ ret = notification_copy_private_file(src_path, dst_path);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ file_list = g_list_append(file_list, strdup(dst_path));
+ }
+ }
+ if (noti->sound_path && noti->priv_sound_path) {
+ ret = notification_copy_private_file(noti->sound_path,
+ noti->priv_sound_path);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ file_list = g_list_append(file_list,
+ strdup(noti->priv_sound_path));
+ }
+
+ if (noti->vibration_path && noti->priv_vibration_path) {
+ ret = notification_copy_private_file(noti->vibration_path,
+ noti->priv_vibration_path);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ file_list = g_list_append(file_list,
+ strdup(noti->priv_vibration_path));
+ }
+
+ return file_list;
+}
+
+/* LCOV_EXCL_START */
+static void __remove_private_file(gpointer data, gpointer user_data)
+{
+ GFile *src = NULL;
+ char *path = (char *)data;
+
+ src = g_file_new_for_path(path);
+ if (src) {
+ g_file_delete(src, NULL, NULL);
+ g_object_unref(src);
+ }
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_post_for_uid(notification_h noti, uid_t uid)
+{
+ int ret = 0;
+ int id = 0;
+ GList *file_list;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->type <= NOTIFICATION_TYPE_NONE
+ || noti->type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ /* Save insert time */
+ noti->insert_time = time(NULL);
+ noti->uid = uid;
+
+ file_list = __copy_private_file(noti);
+ ret = notification_ipc_request_insert(noti, &id);
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ noti->priv_id = id;
+ INFO("Posted notification id[%d]", id);
+ } else {
+ g_list_foreach(file_list, __remove_private_file, NULL);
+ }
+
+ if (file_list)
+ g_list_free_full(file_list, free);
+
+ return ret;
+}
+
+EXPORT_API int notification_update_for_uid(notification_h noti, uid_t uid)
+{
+ if (noti == NULL) {
+ notification_ipc_request_refresh(uid);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ noti->uid = uid;
+ /* Update insert time ? */
+ noti->insert_time = time(NULL);
+
+ return notification_ipc_request_update(noti);
+}
+
+EXPORT_API int notification_delete_for_uid(notification_h noti, uid_t uid)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_request_delete_single(NOTIFICATION_TYPE_NONE,
+ noti->caller_app_id, noti->priv_id, uid);
+}
+
+EXPORT_API int notification_delete_all_for_uid(notification_type_e type, uid_t uid)
+{
+ int ret = 0;
+ char *caller_app_id = NULL;
+
+ if (type <= NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+
+ ret = notification_ipc_request_delete_multiple(type, caller_app_id, uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+
+EXPORT_API notification_h notification_load_by_tag_for_uid(const char *tag, uid_t uid)
+{
+ int ret;
+ notification_h noti;
+ char *caller_app_id;
+
+ if (tag == NULL) {
+ ERR("Invalid tag");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ if (!caller_app_id) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get a package name");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc a new notification");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ free(caller_app_id);
+
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_ipc_request_load_noti_by_tag(noti, caller_app_id, (char *)tag, uid);
+ free(caller_app_id);
+
+ set_last_result(ret);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return NULL;
+ }
+
+ return noti;
+}
+
+EXPORT_API notification_h notification_create_from_package_template(const char *app_id, const char *template_name)
+{
+ int ret;
+ notification_h noti;
+
+ if (app_id == NULL || template_name == NULL) {
+ ERR("Invalid parameter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_ipc_request_create_from_package_template(noti, app_id, template_name);
+ set_last_result(ret);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return NULL;
+ }
+
+ return noti;
+}
+
+EXPORT_API int notification_set_default_button(notification_h noti, notification_button_index_e index)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (index < 0 || index > NOTIFICATION_BUTTON_6)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->default_button_index = index;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_default_button(notification_h noti, notification_button_index_e *index)
+{
+ if (noti == NULL || index == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *index = noti->default_button_index;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_ongoing_value_type(notification_h noti, notification_ongoing_value_type_e *type)
+{
+ if (noti == NULL || type == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *type = noti->ongoing_value_type;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_ongoing_value_type(notification_h noti, notification_ongoing_value_type_e type)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type < NOTIFICATION_ONGOING_VALUE_TYPE_PERCENT || type > NOTIFICATION_ONGOING_VALUE_TYPE_TIME)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->ongoing_value_type = type;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_ongoing_time(notification_h noti, int *current, int *duration)
+{
+ if (noti == NULL || current == NULL || duration == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *current = noti->ongoing_current;
+ *duration = noti->ongoing_duration;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_ongoing_time(notification_h noti, int current, int duration)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (current < 0 || duration < 0 || current > duration)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->ongoing_current = current;
+ noti->ongoing_duration = duration;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_hide_timeout(notification_h noti, int *timeout)
+{
+ if (noti == NULL || timeout == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *timeout = noti->hide_timeout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_hide_timeout(notification_h noti, int timeout)
+{
+ if (noti == NULL || timeout < 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->hide_timeout = timeout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_delete_timeout(notification_h noti, int *timeout)
+{
+ if (noti == NULL || timeout == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *timeout = noti->delete_timeout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_delete_timeout(notification_h noti, int timeout)
+{
+ if (noti == NULL || timeout < 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->delete_timeout = timeout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_text_input_max_length(notification_h noti, int *text_input_max_length)
+{
+ if (noti == NULL || text_input_max_length == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *text_input_max_length = noti->text_input_max_length;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_post_with_event_cb_for_uid(notification_h noti, event_handler_cb cb,
+ void *userdata, uid_t uid)
+{
+ int ret;
+ int priv_id;
+ notification_event_cb_info_s *info = NULL;
+ GList *find_list;
+
+ if (noti == NULL || cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->type <= NOTIFICATION_TYPE_NONE || noti->type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->insert_time = time(NULL);
+ noti->event_flag = true;
+ noti->uid = uid;
+
+ ret = notification_ipc_request_insert(noti, &priv_id);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ noti->priv_id = priv_id;
+
+ __noti_event_cb_list = g_list_first(__noti_event_cb_list);
+ find_list = g_list_find_custom(__noti_event_cb_list, GINT_TO_POINTER(priv_id),
+ (GCompareFunc)__priv_id_compare);
+
+ if (find_list) {
+ info = g_list_nth_data(find_list, 0);
+ info->cb = cb;
+ info->userdata = userdata;
+ } else {
+ info = (notification_event_cb_info_s *)malloc(sizeof(notification_event_cb_info_s));
+ if (info == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+ info->priv_id = priv_id;
+ info->cb = cb;
+ info->userdata = userdata;
+ __noti_event_cb_list = g_list_append(__noti_event_cb_list, info);
+ }
+
+ return ret;
+}
+
+EXPORT_API int notification_post_with_event_cb(notification_h noti, event_handler_cb cb, void *userdata)
+{
+ return notification_post_with_event_cb_for_uid(noti, cb, userdata, getuid());
+}
+
+EXPORT_API int notification_send_event(notification_h noti, int event_type)
+{
+ int ret;
+ bool event_flag;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (!((event_type >= NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
+ && event_type <= NOTIFICATION_EVENT_TYPE_MAX) ||
+ (event_type >= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER
+ && event_type <= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL) ||
+ (event_type >= NOTIFICATION_EVENT_TYPE_PRESSED
+ && event_type <= NOTIFICATION_EVENT_TYPE_DELETED)))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_get_event_flag(noti, &event_flag);
+ if (ret != NOTIFICATION_ERROR_NONE || event_flag == false)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_ipc_send_event(noti, event_type, -1);
+
+ return ret;
+}
+
+EXPORT_API int notification_send_event_by_priv_id(int priv_id, int event_type)
+{
+ int ret;
+
+ if (priv_id <= 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (!((event_type >= NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
+ && event_type <= NOTIFICATION_EVENT_TYPE_MAX) ||
+ (event_type >= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER
+ && event_type <= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL) ||
+ (event_type >= NOTIFICATION_EVENT_TYPE_PRESSED
+ && event_type <= NOTIFICATION_EVENT_TYPE_DELETED)))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_ipc_send_event(NULL, event_type, priv_id);
+ return ret;
+}
+
+EXPORT_API int notification_get_event_flag(notification_h noti, bool *flag)
+{
+ if (noti == NULL || flag == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *flag = noti->event_flag;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_check_event_receiver_available(notification_h noti, bool *available)
+{
+ int ret;
+ int priv_id;
+
+ if (noti == NULL || available == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_get_id(noti, NULL, &priv_id);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get priv id");
+ return ret;
+ }
+
+ ret = notification_ipc_check_event_receiver(priv_id, available);
+
+ return ret;
+}
+
+static bundle *_create_bundle_from_bundle_raw(bundle_raw *string)
+{
+ if (string == NULL || string[0] == '\0')
+ return NULL;
+
+ return bundle_decode(string, strlen((char *)string));
+}
+
+EXPORT_API int notification_set_extention_data(notification_h noti, const char *key, bundle *value)
+{
+ return notification_set_extension_data(noti, key, value);
+}
+
+EXPORT_API int notification_set_extension_data(notification_h noti, const char *key, bundle *value)
+{
+ int ret;
+ int len = 0;
+ char *del = NULL;
+ bundle_raw *raw = NULL;
+
+ if (noti == NULL || key == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->args == NULL)
+ noti->args = bundle_create();
+
+ if (value == NULL) {
+ ret = bundle_del(noti->args, key);
+ if (ret == BUNDLE_ERROR_NONE)
+ return NOTIFICATION_ERROR_NONE;
+ else
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle_get_str(noti->args, key, &del);
+ if (del != NULL) {
+ bundle_del(noti->args, key);
+ del = NULL;
+ }
+
+ bundle_encode(value, &raw, &len);
+ bundle_add_str(noti->args, key, (const char *)raw);
+ bundle_free_encoded_rawdata(&raw);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_extention_data(notification_h noti, const char *key, bundle **value)
+{
+ return notification_get_extension_data(noti, key, value);
+}
+
+EXPORT_API int notification_get_extension_data(notification_h noti, const char *key, bundle **value)
+{
+ char *ret_str;
+ bundle *args;
+
+ if (noti == NULL || key == NULL || value == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->args == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ args = noti->args;
+
+ bundle_get_str(args, key, &ret_str);
+ if (ret_str == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *value = _create_bundle_from_bundle_raw((bundle_raw *)ret_str);
+ if (*value == NULL)
+ return NOTIFICATION_ERROR_IO_ERROR;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+#define KEY_LEN 40
+#define EXTENSION_EVENT_KEY "_NOTIFICATION_EXTENSION_EVENT_"
+EXPORT_API int notification_set_extension_event_handler(notification_h noti,
+ notification_event_type_extension_e event,
+ app_control_h event_handler)
+{
+ int err;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int len;
+ bundle *app_control_bundle = NULL;
+ bundle_raw *b_raw = NULL;
+ char key[KEY_LEN];
+ char *del = NULL;
+
+ if (noti == NULL || event_handler == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (event < NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER ||
+ event > NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL) {
+ ERR("Invalid event [%d]", event);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (noti->args == NULL)
+ noti->args = bundle_create();
+
+ snprintf(key, sizeof(key), "%s%d", EXTENSION_EVENT_KEY, event);
+ bundle_get_str(noti->args, key, &del);
+ if (del != NULL) {
+ bundle_del(noti->args, key);
+ del = NULL;
+ }
+
+ err = app_control_export_as_bundle(event_handler, &app_control_bundle);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to export app_control to bundle [%d]", err);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = bundle_encode(app_control_bundle, &b_raw, &len);
+ if (err != BUNDLE_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to encode bundle [%d]", err);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = bundle_add_str(noti->args, key, (const char *)b_raw);
+ if (err != BUNDLE_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to add str to bundle [%d]", err);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+out:
+ if (b_raw)
+ bundle_free_encoded_rawdata(&b_raw);
+ if (app_control_bundle)
+ bundle_free(app_control_bundle);
+
+ return ret;
+}
+
+EXPORT_API int notification_get_extension_event_handler(notification_h noti,
+ notification_event_type_extension_e event,
+ app_control_h *event_handler)
+{
+ int err;
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *ret_str = NULL;
+ char key[KEY_LEN];
+ bundle *app_control_bundle = NULL;
+ app_control_h ret_app_control = NULL;
+
+ if (noti == NULL || event_handler == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (event < NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER ||
+ event > NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL) {
+ ERR("Invalid event [%d]", event);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ snprintf(key, sizeof(key), "%s%d", EXTENSION_EVENT_KEY, event);
+
+ bundle_get_str(noti->args, key, &ret_str);
+ if (ret_str == NULL) {
+ ERR("No handler, Invalid event[%d]", event);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ app_control_bundle = _create_bundle_from_bundle_raw((bundle_raw *)ret_str);
+ if (app_control_bundle == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create bundle");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = app_control_create(&ret_app_control);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create app control [%d]", err);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = app_control_import_from_bundle(ret_app_control, app_control_bundle);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to import app control from bundle [%d]", err);
+ app_control_destroy(ret_app_control);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *event_handler = ret_app_control;
+
+out:
+ if (app_control_bundle)
+ bundle_free(app_control_bundle);
+
+ return ret;
+}
+
+EXPORT_API int notification_get_all_count_for_uid(notification_type_e type, int *count, uid_t uid)
+{
+ int ret;
+
+ if (count == NULL) {
+ ERR("Invalid parameter - count is null");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (type < NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX) {
+ ERR("Invalid parameter - wrong type");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = notification_ipc_request_get_all_count(type, count, uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get count [%d]", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+EXPORT_API int notification_get_all_count(notification_type_e type, int *count)
+{
+ return notification_get_all_count_for_uid(type, count, getuid());
+}
+
+EXPORT_API int notification_set_app_label(notification_h noti, char *label)
+{
+ if (noti == NULL || label == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->app_label)
+ free(noti->app_label);
+
+ noti->app_label = strdup(label);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_app_label(notification_h noti, char **label)
+{
+ if (noti == NULL || label == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->app_label)
+ *label = noti->app_label;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static void __set_caller_info(bundle *b, const char *appid, uid_t uid)
+{
+ pkgmgrinfo_appinfo_h handle;
+ char buf[12];
+ char *pkgid = NULL;
+ int r;
+
+ snprintf(buf, sizeof(buf), "%u", uid);
+ bundle_del(b, AUL_K_ORG_CALLER_UID);
+ bundle_add(b, AUL_K_ORG_CALLER_UID, buf);
+
+ bundle_del(b, AUL_K_ORG_CALLER_APPID);
+ bundle_add(b, AUL_K_ORG_CALLER_APPID, appid);
+
+ r = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
+ if (r != PMINFO_R_OK)
+ return;
+
+ pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
+ if (pkgid) {
+ bundle_del(b, AUL_K_ORG_CALLER_PKGID);
+ bundle_add(b, AUL_K_ORG_CALLER_PKGID, pkgid);
+ }
+ pkgmgrinfo_appinfo_destroy_appinfo(handle);
+}
+
+static void __set_indirect_request(bundle *b)
+{
+ bundle_del(b, AUL_K_REQUEST_TYPE);
+ bundle_add(b, AUL_K_REQUEST_TYPE, "indirect-request");
+}
+
+EXPORT_API int notification_set_indirect_request(notification_h noti,
+ pid_t pid, uid_t uid)
+{
+ char appid[256] = { 0, };
+ int r;
+ int i;
+
+ if (noti == NULL || pid <= 1 || uid < REGULAR_UID_MIN)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ r = aul_app_get_appid_bypid(pid, appid, sizeof(appid));
+ if (r != AUL_R_OK)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_service_responding) {
+ __set_caller_info(noti->b_service_responding, appid, uid);
+ __set_indirect_request(noti->b_service_responding);
+ }
+
+ if (noti->b_service_single_launch) {
+ __set_caller_info(noti->b_service_single_launch, appid, uid);
+ __set_indirect_request(noti->b_service_single_launch);
+ }
+
+ if (noti->b_service_multi_launch) {
+ __set_caller_info(noti->b_service_multi_launch, appid, uid);
+ __set_indirect_request(noti->b_service_multi_launch);
+ }
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i]) {
+ __set_caller_info(noti->b_event_handler[i], appid, uid);
+ __set_indirect_request(noti->b_event_handler[i]);
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+
+int notification_delete_by_display_applist_for_uid(int display_applist, uid_t uid)
+{
+ if (display_applist < NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_request_delete_by_display_applist(display_applist, uid);
+}
+
+EXPORT_API int notification_delete_by_display_applist(int display_applist)
+{
+ return notification_delete_by_display_applist_for_uid(display_applist, getuid());
+}
diff --git a/notification/src/notification_ipc.c b/notification/src/notification_ipc.c
new file mode 100644
index 0000000..c0446e9
--- /dev/null
+++ b/notification/src/notification_ipc.c
@@ -0,0 +1,2726 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <bundle_internal.h>
+
+#include <notification_ipc.h>
+#include <notification_db.h>
+#include <notification_type.h>
+#include <notification_private.h>
+#include <notification_debug.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#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"
+#define PROVIDER_NOTI_INTERFACE_NAME "org.tizen.data_provider_noti_service"
+#define PROVIDER_NOTI_EVENT_INTERFACE_NAME "org.tizen.data_provider_noti_event_service"
+
+#define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
+#define DBUS_PATH_DBUS "/org/freedesktop/DBus"
+#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
+#define ERR_BUFFER_SIZE 1024
+
+static const gchar *_bus_name = NULL;
+static GDBusConnection *_gdbus_conn = NULL;
+static guint provider_watcher_id = 0;
+static int monitor_id = 0;
+static int event_monitor_id = 0;
+static int provider_monitor_id = 0;
+static int is_master_started = 0;
+
+typedef struct _result_cb_item {
+ void (*result_cb)(int priv_id, int result, void *data);
+ void *data;
+} result_cb_item;
+
+typedef struct _task_list task_list;
+struct _task_list {
+ task_list *prev;
+ task_list *next;
+
+ void (*task_cb)(void *data);
+ void *data;
+};
+
+static task_list *g_task_list;
+
+static int _ipc_monitor_register(uid_t uid);
+static int _ipc_monitor_deregister(void);
+static void _do_deffered_task(void);
+
+static void _print_noti(notification_h noti)
+{
+ char *app_id = NULL;
+ char *text = NULL;
+ char *content = NULL;
+ const char *tag = NULL;
+
+ notification_get_pkgname(noti, &app_id);
+ notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE, &text);
+ notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT, &content);
+ notification_get_tag(noti, &tag);
+
+ DBG("Noti-info : app_id[%s] title[%s] content[%s] tag[%s] priv_id[%d]",
+ app_id, text, content, tag, noti->priv_id);
+}
+
+static void __provider_appeared_cb(GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ INFO("name [%s] name_owner[%s]", name, name_owner);
+ notification_reset_event_handler_list();
+}
+
+/* LCOV_EXCL_START */
+static void __provider_vanished_cb(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ INFO("name [%s]", name);
+}
+/* LCOV_EXCL_STOP */
+
+static int _dbus_init(void)
+{
+ GError *error = NULL;
+
+ if (_gdbus_conn == NULL) {
+ _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+
+ if (_gdbus_conn == NULL) {
+ /* LCOV_EXCL_START */
+ if (error != NULL) {
+ ERR("Failed to get dbus[%s]",
+ error->message);
+ g_error_free(error);
+ }
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+ _bus_name = g_dbus_connection_get_unique_name(_gdbus_conn);
+ INFO("Connected bus name[%s]", _bus_name);
+
+ notification_error_quark();
+ }
+
+ if (provider_watcher_id == 0) {
+ provider_watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
+ PROVIDER_BUS_NAME,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ __provider_appeared_cb,
+ __provider_vanished_cb,
+ NULL,
+ NULL);
+ DBG("Watching data-provider-master is [%s] watcher_id [%d]",
+ provider_watcher_id ? "success" : "fail", provider_watcher_id);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+/* LCOV_EXCL_START */
+int notification_ipc_is_master_ready(void)
+{
+ GVariant *result;
+ GError *err = NULL;
+ gboolean name_exist;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", ret);
+ is_master_started = 0;
+ return is_master_started;
+ }
+
+ result = g_dbus_connection_call_sync(
+ _gdbus_conn,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "NameHasOwner",
+ g_variant_new("(s)", PROVIDER_BUS_NAME),
+ G_VARIANT_TYPE("(b)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err);
+
+ if (err || (result == NULL)) {
+ if (err) {
+ ERR("No reply[%s]", err->message);
+ g_error_free(err);
+ }
+ ERR("Failed to ready master");
+ is_master_started = 0;
+ } else {
+ g_variant_get(result, "(b)", &name_exist);
+
+ if (!name_exist) {
+ ERR("The master has been stopped, Not exsited name[%s]", PROVIDER_BUS_NAME);
+ is_master_started = 0;
+ } else {
+ DBG("The master has been started");
+ is_master_started = 1;
+ }
+ }
+
+ if (result)
+ g_variant_unref(result);
+
+ return is_master_started;
+}
+/* LCOV_EXCL_STOP */
+
+/* TODO: dbus activation isn't enough ? */
+/*
+ * store tasks when daemon stopped
+ */
+int notification_ipc_add_deffered_task(
+ void (*deferred_task_cb)(void *data),
+ void *user_data)
+{
+ task_list *list;
+ task_list *list_new;
+
+ list_new = (task_list *) malloc(sizeof(task_list));
+ if (list_new == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ list_new->next = NULL;
+ list_new->prev = NULL;
+
+ list_new->task_cb = deferred_task_cb;
+ list_new->data = user_data;
+
+ if (g_task_list == NULL) {
+ g_task_list = list_new;
+ } else {
+ list = g_task_list;
+
+ while (list->next != NULL)
+ list = list->next;
+
+ list->next = list_new;
+ list_new->prev = list;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ipc_del_deffered_task(
+ void (*deferred_task_cb)(void *data))
+{
+ task_list *list_del;
+ task_list *list_prev;
+ task_list *list_next;
+
+ list_del = g_task_list;
+
+ if (list_del == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ while (list_del->prev != NULL)
+ list_del = list_del->prev;
+
+ do {
+ if (list_del->task_cb == deferred_task_cb) {
+ list_prev = list_del->prev;
+ list_next = list_del->next;
+
+ if (list_prev == NULL)
+ g_task_list = list_next;
+ else
+ list_prev->next = list_next;
+
+ if (list_next == NULL) {
+ if (list_prev != NULL)
+ list_prev->next = NULL;
+ } else {
+ list_next->prev = list_prev;
+ }
+
+ free(list_del);
+ return NOTIFICATION_ERROR_NONE;
+ }
+ list_del = list_del->next;
+ } while (list_del != NULL);
+
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+}
+
+/* LCOV_EXCL_START */
+static void _do_deffered_task(void)
+{
+ task_list *list_do;
+ task_list *list_temp;
+
+ if (g_task_list == NULL)
+ return;
+
+ list_do = g_task_list;
+ g_task_list = NULL;
+
+ while (list_do->prev != NULL)
+ list_do = list_do->prev;
+
+ while (list_do != NULL) {
+ if (list_do->task_cb != NULL) {
+ list_do->task_cb(list_do->data);
+ DBG("called:%p", list_do->task_cb);
+ }
+ list_temp = list_do->next;
+ free(list_do);
+ list_do = list_temp;
+ }
+}
+/* LCOV_EXCL_STOP */
+
+/*!
+ * functions to create operation list
+ */
+static notification_op *_ipc_create_op(notification_op_type_e type,
+ int num_op, int *list_priv_id, int num_priv_id, notification_h *noti_list)
+{
+ int i;
+ notification_op *op_list;
+
+ if (num_op <= 0)
+ return NULL;
+
+ op_list = (notification_op *)malloc(sizeof(notification_op) * num_op);
+ if (op_list == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ memset(op_list, 0x0, sizeof(notification_op) * num_op);
+
+ for (i = 0; i < num_op; i++) {
+ (op_list + i)->type = type;
+ if (list_priv_id != NULL)
+ (op_list + i)->priv_id = *(list_priv_id + i);
+ if (noti_list != NULL)
+ (op_list + i)->noti = *(noti_list + i);
+ }
+
+ return op_list;
+}
+
+/*!
+ * utility functions creating notification packet
+ */
+static inline char *_dup_string(const char *string)
+{
+ char *ret;
+ char err_buf[ERR_BUFFER_SIZE];
+
+ if (string == NULL || string[0] == '\0')
+ return NULL;
+
+ ret = strdup(string);
+ if (!ret)
+ ERR("Failed to strdup[%s]",
+ strerror_r(errno, err_buf, sizeof(err_buf)));
+
+ return ret;
+}
+
+static inline bundle *_create_bundle_from_bundle_raw(bundle_raw *string)
+{
+ if (string == NULL || string[0] == '\0')
+ return NULL;
+
+ return bundle_decode(string, strlen((char *)string));
+}
+
+/* LCOV_EXCL_START */
+static void _add_noti_notify(GVariant *parameters)
+{
+ int ret;
+ notification_h noti;
+ notification_op *noti_op = NULL;
+ GVariant *body = NULL;
+ uid_t uid;
+
+ DBG("add noti notify");
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (!noti) {
+ ERR("Failed to create notification handle");
+ return;
+ }
+
+ g_variant_get(parameters, "(v)", &body);
+ notification_ipc_make_noti_from_gvariant(noti, body);
+ _print_noti(noti);
+ if (noti->flags_for_property & NOTIFICATION_PROP_DISABLE_UPDATE_ON_INSERT) {
+ ERR("Disable changed callback[%d]", noti->flags_for_property);
+ /* Disable changed cb */
+ } else {
+ /* Enable changed cb */
+ noti_op = _ipc_create_op(NOTIFICATION_OP_INSERT, 1, &(noti->priv_id), 1, &noti);
+ ret = notification_get_uid(noti, &uid);
+ if (noti_op != NULL && ret == NOTIFICATION_ERROR_NONE)
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+ }
+ g_variant_unref(body);
+ notification_free(noti);
+ if (noti_op)
+ free(noti_op);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _update_noti_notify(GVariant *parameters)
+{
+ int ret;
+ notification_h noti;
+ notification_op *noti_op = NULL;
+ GVariant *body = NULL;
+ uid_t uid;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (!noti) {
+ ERR("Failed to create notification handle");
+ return;
+ }
+
+ g_variant_get(parameters, "(v)", &body);
+ notification_ipc_make_noti_from_gvariant(noti, body);
+ _print_noti(noti);
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_UPDATE, 1, &(noti->priv_id), 1, &noti);
+ ret = notification_get_uid(noti, &uid);
+ if (noti_op != NULL && ret == NOTIFICATION_ERROR_NONE)
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+
+ g_variant_unref(body);
+ notification_free(noti);
+ if (noti_op)
+ free(noti_op);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _refresh_noti_notify(GVariant *parameters)
+{
+ uid_t uid;
+ notification_op *noti_op = _ipc_create_op(NOTIFICATION_OP_REFRESH, 1, NULL, 0, NULL);
+
+ g_variant_get(parameters, "(i)", &uid);
+
+ if (noti_op != NULL) {
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+ free(noti_op);
+ }
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _delete_single_notify(GVariant *parameters)
+{
+ int num_deleted;
+ int priv_id;
+ notification_op *noti_op;
+ uid_t uid;
+
+ /* num_deleted ?? */
+ g_variant_get(parameters, "(iii)", &num_deleted, &priv_id, &uid);
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_DELETE, 1, &priv_id, 1, NULL);
+ if (noti_op != NULL) {
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+ free(noti_op);
+ }
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _delete_multiple_notify(GVariant *parameters)
+{
+ int *buf;
+ int idx = 0;
+ int num;
+ notification_op *noti_op;
+ GVariantIter *iter;
+ uid_t uid;
+
+ g_variant_get(parameters, "(a(i)ii)", &iter, &num, &uid);
+ if (num <= 0) {
+ ERR("Invalid number to delete");
+ return;
+ }
+ DBG("Deleted count[%d]", num);
+
+ buf = (int *)malloc(sizeof(int) * num);
+ if (buf == NULL) {
+ ERR("Failed to alloc");
+ return;
+ }
+
+ while (idx < num && g_variant_iter_loop(iter, "(i)", &buf[idx])) {
+ DBG("priv id[%d]", buf[idx]);
+ idx++;
+ }
+ g_variant_iter_free(iter);
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_DELETE, idx, buf, idx, NULL);
+ if (noti_op == NULL) {
+ ERR("Failed to create op");
+ free(buf);
+ return;
+ }
+
+ notification_call_changed_cb_for_uid(noti_op, idx, uid);
+ free(noti_op);
+ free(buf);
+}
+/* LCOV_EXCL_STOP */
+
+static void _delete_by_display_applist_notify(GVariant *parameters)
+{
+ int *buf;
+ int idx = 0;
+ int num;
+ notification_op *noti_op;
+ GVariantIter *iter;
+ uid_t uid;
+
+ g_variant_get(parameters, "(a(i)ii)", &iter, &num, &uid);
+ if (num <= 0) {
+ ERR("Invalid number to delete");
+ return;
+ }
+
+ DBG("Deleted count[%d]", num);
+
+ buf = (int *)malloc(sizeof(int) * num);
+ if (buf == NULL) {
+ ERR("Failed to alloc");
+ return;
+ }
+
+ while (idx < num && g_variant_iter_loop(iter, "(i)", &buf[idx])) {
+ DBG("priv id[%d]", buf[idx]);
+ idx++;
+ }
+ g_variant_iter_free(iter);
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_DELETE, idx, buf, idx, NULL);
+ if (noti_op == NULL) {
+ ERR("Failed to create op");
+ free(buf);
+ return;
+ }
+
+ notification_call_changed_cb_for_uid(noti_op, idx, uid);
+ free(noti_op);
+ free(buf);
+}
+
+/* LCOV_EXCL_START */
+static void _change_dnd_notify(GVariant *parameters)
+{
+ int do_not_disturb;
+ uid_t uid;
+
+ g_variant_get(parameters, "(ii)", &do_not_disturb, &uid);
+ DBG("do_not_disturb[%d], uid[%d]", do_not_disturb, uid);
+
+ notification_call_dnd_changed_cb_for_uid(do_not_disturb, uid);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _handle_noti_notify(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ DBG("own_name : %s signal_name: %s",
+ g_dbus_connection_get_unique_name(connection),
+ signal_name);
+
+ if (g_strcmp0(signal_name, "add_noti_notify") == 0)
+ _add_noti_notify(parameters);
+ else if (g_strcmp0(signal_name, "update_noti_notify") == 0)
+ _update_noti_notify(parameters);
+ else if (g_strcmp0(signal_name, "delete_single_notify") == 0)
+ _delete_single_notify(parameters);
+ else if (g_strcmp0(signal_name, "delete_multiple_notify") == 0)
+ _delete_multiple_notify(parameters);
+ else if (g_strcmp0(signal_name, "refresh_noti_notify") == 0)
+ _refresh_noti_notify(parameters);
+ else if (g_strcmp0(signal_name, "change_dnd_notify") == 0)
+ _change_dnd_notify(parameters);
+ else if (g_strcmp0(signal_name, "delete_by_display_applist_notify") == 0)
+ _delete_by_display_applist_notify(parameters);
+}
+/* LCOV_EXCL_STOP */
+
+static void _send_event(GVariant *parameters)
+{
+ int ret;
+ int event_type;
+ notification_h noti;
+ GVariant *coupled_body;
+ GVariant *body;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create notification handle");
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ g_variant_get(parameters, "(vi)", &coupled_body, &event_type);
+ g_variant_get(coupled_body, "(v)", &body);
+
+ ret = notification_ipc_make_noti_from_gvariant(noti, body);
+ g_variant_unref(coupled_body);
+ g_variant_unref(body);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to make notification handle from gvariant");
+ notification_free(noti);
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ notification_call_event_handler_cb(noti, event_type);
+ notification_free(noti);
+}
+
+/* LCOV_EXCL_START */
+static void _delete_event(GVariant *parameters)
+{
+ int priv_id;
+
+ g_variant_get(parameters, "(i)", &priv_id);
+ notification_delete_event_handler_cb(priv_id);
+}
+/* LCOV_EXCL_STOP */
+
+static void _handle_noti_event_handler_notify(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ DBG("own_name : %s signal_name: %s",
+ g_dbus_connection_get_unique_name(connection), signal_name);
+
+ if (g_strcmp0(signal_name, "send_event") == 0)
+ _send_event(parameters);
+ else if (g_strcmp0(signal_name, "delete_noti") == 0)
+ _delete_event(parameters);
+}
+
+static int _dbus_event_handler_signal_init(void)
+{
+ int id;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (event_monitor_id == 0) {
+ id = g_dbus_connection_signal_subscribe(_gdbus_conn,
+ PROVIDER_BUS_NAME,
+ PROVIDER_NOTI_EVENT_INTERFACE_NAME, /* interface */
+ NULL, /* member */
+ PROVIDER_OBJECT_PATH, /* path */
+ NULL, /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ _handle_noti_event_handler_notify,
+ NULL,
+ NULL);
+
+ DBG("subscribe id[%d]", id);
+ if (id == 0) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to subscribe connection signal");
+ /* LCOV_EXCL_STOP */
+ } else {
+ event_monitor_id = id;
+ }
+ }
+
+ return ret;
+}
+
+static int _dbus_signal_init(void)
+{
+ int id;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (monitor_id == 0) {
+ id = g_dbus_connection_signal_subscribe(_gdbus_conn,
+ PROVIDER_BUS_NAME,
+ PROVIDER_NOTI_INTERFACE_NAME, /* interface */
+ NULL, /* member */
+ PROVIDER_OBJECT_PATH, /* path */
+ NULL, /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ _handle_noti_notify,
+ NULL,
+ NULL);
+
+ DBG("subscribe id : %d", id);
+ if (id == 0) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to register dbus_interface");
+ /* LCOV_EXCL_STOP */
+ } else {
+ monitor_id = id;
+ ret = NOTIFICATION_ERROR_NONE;
+ }
+ }
+
+ return ret;
+}
+
+static GDBusMessage *__get_new_msg(GVariant *body, const char *cmd)
+{
+ GDBusMessage *msg = NULL;
+
+ msg = g_dbus_message_new_method_call(
+ PROVIDER_BUS_NAME,
+ PROVIDER_OBJECT_PATH,
+ PROVIDER_NOTI_INTERFACE_NAME,
+ cmd);
+ if (!msg) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc new method call");
+ if (body)
+ g_variant_unref(body);
+ 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,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ &g_err);
+
+ if (!*reply) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_SERVICE_NOT_READY;
+ 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(g_err);
+ }
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ 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 = g_err->code;
+ g_error_free(g_err);
+ return ret;
+ }
+
+ 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) {
+ /* LCOV_EXCL_START */
+ 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;
+ /* LCOV_EXCL_STOP */
+ }
+
+ 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)
+{
+ GVariant *body;
+ int result = NOTIFICATION_ERROR_NONE;
+ int priv_id;
+ GDBusMessage *reply = NULL;
+ GError *err = NULL;
+ result_cb_item *cb_item = (result_cb_item *)user_data;
+
+ if (cb_item == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get a callback item");
+ return;
+ /* LCOV_EXCL_START */
+ }
+
+ reply = g_dbus_connection_send_message_with_reply_finish(
+ connection,
+ res,
+ &err);
+
+ if (!reply) {
+ /* LCOV_EXCL_START */
+ if (err != NULL) {
+ ERR("No reply[%s]", err->message);
+ g_error_free(err);
+ }
+ result = NOTIFICATION_ERROR_SERVICE_NOT_READY;
+ /* LCOV_EXCL_STOP */
+
+ } else if (g_dbus_message_to_gerror(reply, &err)) {
+ /* LCOV_EXCL_START */
+ if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
+ result = NOTIFICATION_ERROR_PERMISSION_DENIED;
+ else
+ result = err->code;
+
+ ERR("Failed to send message[%s]", err->message);
+ g_error_free(err);
+ /* LCOV_EXCL_STOP */
+ }
+
+ INFO("Async message callback result[%d]", result);
+ if (result == NOTIFICATION_ERROR_NONE) {
+ body = g_dbus_message_get_body(reply);
+ g_variant_get(body, "(i)", &priv_id);
+
+ if (cb_item->result_cb)
+ cb_item->result_cb(priv_id, result, cb_item->data);
+ } else {
+ if (cb_item->result_cb)
+ cb_item->result_cb(NOTIFICATION_PRIV_ID_NONE, result, cb_item->data);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+ free(cb_item);
+}
+
+static int _send_async_noti(GVariant *body, result_cb_item *cb_item, char *cmd)
+{
+ GDBusMessage *msg;
+
+ msg = g_dbus_message_new_method_call(
+ PROVIDER_BUS_NAME,
+ PROVIDER_OBJECT_PATH,
+ PROVIDER_NOTI_INTERFACE_NAME,
+ cmd);
+ if (!msg) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc new method call");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_variant_is_floating(body))
+ g_variant_ref(body);
+
+ if (body != NULL)
+ g_dbus_message_set_body(msg, body);
+
+ g_dbus_connection_send_message_with_reply(
+ _gdbus_conn,
+ msg,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ (GAsyncReadyCallback)_send_message_with_reply_async_cb,
+ cb_item);
+
+ if (msg)
+ g_object_unref(msg);
+
+ DBG("Success to send async message");
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ipc_request_insert(notification_h noti, int *priv_id)
+{
+ int result;
+ int id = NOTIFICATION_PRIV_ID_NONE;
+ bool event_flag;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = notification_get_event_flag(noti, &event_flag);
+ if (result != NOTIFICATION_ERROR_NONE)
+ return result;
+
+ if (event_flag == true && event_monitor_id == 0) {
+ result = _dbus_event_handler_signal_init();
+ if (result != NOTIFICATION_ERROR_NONE)
+ return result;
+ }
+
+ /* Initialize private ID */
+ noti->group_id = NOTIFICATION_GROUP_ID_NONE;
+ noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
+
+ _print_noti(noti);
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to make gvariant from notification handle");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_sync_noti(body, &reply, "add_noti");
+ DBG("_send_sync_noti %d", result);
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &id);
+
+ if (priv_id != NULL)
+ *priv_id = id;
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("priv_id[%d] result[%d]", id, result);
+ return result;
+}
+
+int notification_ipc_request_update(notification_h noti)
+{
+ int result;
+ int priv_id = NOTIFICATION_PRIV_ID_NONE;
+
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("cannot make gvariant");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_sync_noti(body, &reply, "update_noti");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &priv_id);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("priv_id[%d] result[%d]", priv_id, result);
+ return result;
+}
+
+int notification_ipc_request_update_async(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data), void *user_data)
+{
+ int result;
+ result_cb_item *cb_item;
+ GVariant *body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ cb_item = calloc(1, sizeof(result_cb_item));
+ if (cb_item == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ cb_item->result_cb = result_cb;
+ cb_item->data = user_data;
+
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to make gvariant from notification handle");
+ free(cb_item);
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_async_noti(body, cb_item, "update_noti");
+ DBG("Update async result[%d]", result);
+
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ free(cb_item);
+ cb_item = NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ g_variant_unref(body);
+
+ return result;
+}
+
+int notification_ipc_request_refresh(uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(i)", uid);
+ result = _send_sync_noti(body, &reply, "refresh_noti");
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_delete_single(notification_type_e type, char *app_id, int priv_id, uid_t uid)
+{
+ int result;
+ int id;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(sii)", app_id, priv_id, uid);
+ result = _send_sync_noti(body, &reply, "del_noti_single");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &id);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_delete_multiple(notification_type_e type, char *app_id, uid_t uid)
+{
+ int result;
+ int num_deleted;
+ GVariant *body;
+ GVariant *reply_body;
+ GDBusMessage *reply = NULL;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!app_id)
+ app_id = "";
+
+ body = g_variant_new("(sii)", app_id, type, uid);
+ result = _send_sync_noti(body, &reply, "del_noti_multiple");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &num_deleted);
+ DBG("Deleted count[%d]", num_deleted);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_delete_by_display_applist(int display_applist, uid_t uid)
+{
+ int result;
+ int num_deleted;
+ GVariant *body;
+ GVariant *reply_body;
+ GDBusMessage *reply = NULL;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ body = g_variant_new("(ii)", display_applist, uid);
+
+ result = _send_sync_noti(body, &reply, "del_noti_by_display_applist");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &num_deleted);
+ DBG("Deleted count[%d]", num_deleted);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_load_noti_by_tag(notification_h noti, const char *app_id, const char *tag, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(ssi)", app_id, tag, uid);
+ result = _send_sync_noti(body, &reply, "load_noti_by_tag");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &noti_body);
+
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ g_variant_unref(noti_body);
+ _print_noti(noti);
+
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("tag[%s] result[%d]", tag, result);
+ return result;
+}
+
+/* LCOV_EXCL_START */
+int notification_ipc_request_load_noti_by_priv_id(notification_h noti, const char *app_id, int priv_id, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ if (!app_id)
+ app_id = "";
+
+ body = g_variant_new("(sii)", app_id, priv_id, uid);
+ result = _send_sync_noti(body, &reply, "load_noti_by_priv_id");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &noti_body);
+
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ g_variant_unref(noti_body);
+ _print_noti(noti);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("priv id[%d], result[%d]", priv_id, result);
+ return result;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_ipc_request_get_count(notification_type_e type,
+ const char *app_id, int group_id, int priv_id, int *count, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ int re_count;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ body = g_variant_new("(isiii)", type, app_id, group_id, priv_id, uid);
+ result = _send_sync_noti(body, &reply, "get_noti_count");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &re_count);
+
+ *count = re_count;
+ DBG("notification count[%d]", re_count);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("Count notification result[%d]", result);
+ return result;
+}
+/* LCOV_EXCL_STOP */
+
+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;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ 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, "(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]);
+
+ INFO("result [%d]", result);
+ return result;
+}
+
+int notification_ipc_request_load_noti_detail_list(const char *app_id,
+ int group_id,
+ int priv_id,
+ int count,
+ notification_list_h *list,
+ uid_t uid)
+{
+ int result;
+ 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) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ body = g_variant_new("(siiii)", app_id, group_id, priv_id, count, uid);
+ result = _send_sync_noti(body, &reply, "load_noti_detail_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) {
+ result = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ ERR("failed to create a notification");
+ notification_free_list(*list);
+ break;
+ }
+ 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);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_get_setting_array(
+ notification_setting_h *setting_array,
+ int *count,
+ uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *reply_body;
+ GVariant *iter_body;
+ GVariantIter *iter;
+ int setting_cnt;
+ notification_setting_h result_setting_array;
+ notification_setting_h temp;
+ int setting_idx;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_sync_noti(g_variant_new("(i)", uid), &reply, "get_setting_array");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(ia(v))", &setting_cnt, &iter);
+
+ DBG("get setting arr cnt: %d", setting_cnt);
+ result_setting_array = (struct notification_setting *)malloc(sizeof(struct notification_setting) * setting_cnt);
+ if (result_setting_array == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("malloc failed");
+ g_object_unref(reply);
+ g_variant_iter_free(iter);
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ setting_idx = 0;
+ while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
+ temp = result_setting_array + setting_idx;
+ notification_ipc_make_setting_from_gvariant(temp, iter_body);
+ setting_idx++;
+ }
+
+ *count = setting_cnt;
+ *setting_array = result_setting_array;
+ g_variant_iter_free(iter);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_get_setting_by_app_id(
+ const char *app_id, notification_setting_h *setting, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *setting_body;
+ notification_setting_h result_setting;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ body = g_variant_new("(si)", app_id, uid);
+ result = _send_sync_noti(body, &reply, "get_setting_by_app_id");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &setting_body);
+
+ result_setting = (struct notification_setting *)malloc(sizeof(struct notification_setting));
+ if (result_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("malloc failed");
+ g_object_unref(reply);
+ g_variant_unref(body);
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+ notification_ipc_make_setting_from_gvariant(result_setting, setting_body);
+
+ *setting = result_setting;
+ g_variant_unref(setting_body);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_load_system_setting(notification_system_setting_h *setting, uid_t uid)
+{
+ int result;
+ int count;
+ GDBusMessage *reply = NULL;
+ GVariant *setting_body = NULL;
+ GVariant *reply_body = NULL;
+ GVariant *iter_body = NULL;
+ GVariantIter *iter = NULL;
+ notification_system_setting_h result_setting = NULL;
+ dnd_allow_exception_h dnd_allow_exception;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_sync_noti(g_variant_new("(i)", uid), &reply, "load_system_setting");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &setting_body);
+
+ result_setting = (struct notification_system_setting *)calloc(1, sizeof(struct notification_system_setting));
+ if (result_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("malloc failed");
+ result = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ notification_ipc_make_system_setting_from_gvariant(result_setting, setting_body);
+
+ result = _send_sync_noti(g_variant_new("(i)", uid), &reply, "load_dnd_allow_exception");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(ia(v))", &count, &iter);
+
+ while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
+ dnd_allow_exception = (dnd_allow_exception_h)calloc(1, sizeof(struct notification_system_setting_dnd_allow_exception));
+ if (dnd_allow_exception == NULL) {
+ /* LCOV_EXCL_START */
+ result = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ notification_ipc_make_dnd_allow_exception_from_gvariant(dnd_allow_exception, iter_body);
+ result_setting->dnd_allow_exceptions = g_list_append(result_setting->dnd_allow_exceptions, dnd_allow_exception);
+ }
+ *setting = result_setting;
+ }
+ }
+
+out:
+ if (result != NOTIFICATION_ERROR_NONE && result_setting)
+ notification_system_setting_free_system_setting(result_setting);
+ if (iter)
+ g_variant_iter_free(iter);
+ if (setting_body)
+ g_variant_unref(setting_body);
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_update_setting(notification_setting_h setting, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(ssiiiiii)",
+ setting->package_name,
+ setting->app_id,
+ (int)(setting->allow_to_notify),
+ (int)(setting->do_not_disturb_except),
+ (int)(setting->visibility_class),
+ (int)(setting->pop_up_notification),
+ (int)(setting->lock_screen_content_level),
+ uid);
+
+ result = _send_sync_noti(body, &reply, "update_noti_setting");
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_update_system_setting(notification_system_setting_h system_setting, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GList *list;
+ dnd_allow_exception_h dnd_allow_exception;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(iiiiiiiiii)",
+ (int)(system_setting->do_not_disturb),
+ (int)(system_setting->visibility_class),
+ (int)(system_setting->dnd_schedule_enabled),
+ (int)(system_setting->dnd_schedule_day),
+ (int)(system_setting->dnd_start_hour),
+ (int)(system_setting->dnd_start_min),
+ (int)(system_setting->dnd_end_hour),
+ (int)(system_setting->dnd_end_min),
+ (int)(system_setting->lock_screen_content_level),
+ uid);
+
+ result = _send_sync_noti(body, &reply, "update_noti_sys_setting");
+
+ /* update dnd_allow_exceptions */
+ list = g_list_first(system_setting->dnd_allow_exceptions);
+
+ for (; list != NULL; list = list->next) {
+ dnd_allow_exception = list->data;
+
+ body = g_variant_new("(iii)",
+ (int)(dnd_allow_exception->type),
+ (int)(dnd_allow_exception->value),
+ uid);
+ result = _send_sync_noti(body, &reply, "update_dnd_allow_exception");
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_save_as_template(notification_h noti, const char *template_name)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ ERR("Failed to make gvariant from notification handle");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ result = _send_sync_noti(g_variant_new("(vs)", body, template_name), &reply, "save_as_template");
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_create_from_template(notification_h noti, const char *template_name)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(s)", template_name);
+
+ result = _send_sync_noti(body, &reply, "create_from_template");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &noti_body);
+
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ g_variant_unref(noti_body);
+ _print_noti(noti);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+
+ return result;
+}
+
+int notification_ipc_request_create_from_package_template(notification_h noti, const char *app_id, const char *template_name)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(ss)", app_id, template_name);
+
+ result = _send_sync_noti(body, &reply, "create_from_package_template");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &noti_body);
+
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ g_variant_unref(noti_body);
+ _print_noti(noti);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+
+ return result;
+}
+
+int notification_ipc_get_noti_block_state(const char *app_id, int *do_not_disturb,
+ int *do_not_disturb_except, int *allow_to_notify,
+ uid_t uid)
+{
+ int ret;
+ int dnd;
+ int dnd_except;
+ int allow;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *result_body;
+
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(si)", app_id, uid);
+
+ ret = _send_sync_noti(body, &reply, "get_noti_block_state");
+
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &result_body);
+ g_variant_get(result_body, "(iii)", &dnd, &dnd_except, &allow);
+ *do_not_disturb = dnd;
+ *do_not_disturb_except = dnd_except;
+ *allow_to_notify = allow;
+ g_variant_unref(result_body);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", ret);
+
+ return ret;
+}
+
+int notification_ipc_request_get_all_count(notification_type_e type, int *count, uid_t uid)
+{
+ int ret;
+ int ret_count = -1;
+ GDBusMessage *reply = NULL;
+ GVariant *reply_body = NULL;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ }
+
+ ret = _send_sync_noti(g_variant_new("(ii)", type, uid),
+ &reply, "get_noti_all_count");
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &ret_count);
+ *count = ret_count;
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ return ret;
+}
+
+int notification_ipc_send_event(notification_h noti, int event_type, int priv_id)
+{
+ int ret;
+ GVariant *body = NULL;
+ GDBusMessage *reply = NULL;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (priv_id > 0) {
+ ret = _send_sync_noti(g_variant_new("(ii)", priv_id, event_type), &reply, "send_noti_event_by_priv_id");
+ } else {
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ ERR("Can't make gvariant to noti");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = _send_sync_noti(g_variant_new("(vi)", body, event_type), &reply, "send_noti_event");
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", ret);
+
+ return ret;
+}
+
+int notification_ipc_check_event_receiver(int priv_id, bool *available)
+{
+ int ret;
+ int ret_available;
+ GVariant *reply_body = NULL;
+ GDBusMessage *reply = NULL;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _send_sync_noti(g_variant_new("(i)", priv_id), &reply, "check_event_receiver");
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &ret_available);
+ *available = (bool)ret_available;
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", ret);
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+void notification_ipc_reset_event_handler(int priv_id)
+{
+ int ret;
+ GDBusMessage *reply = NULL;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", ret);
+ return;
+ }
+
+ _send_sync_noti(g_variant_new("(i)", priv_id), &reply, "reset_event_handler");
+
+ if (reply)
+ g_object_unref(reply);
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API GVariant *notification_ipc_make_gvariant_from_noti(notification_h noti, bool translate)
+{
+ DBG("make gvariant from noti");
+ int i = 0;
+ int b_encode_len = 0;
+ bundle_raw *args = NULL;
+ bundle_raw *group_args = NULL;
+ bundle_raw *b_image_path = NULL;
+ bundle_raw *b_priv_image_path = NULL;
+ bundle_raw *b_execute_option = NULL;
+ bundle_raw *b_service_responding = NULL;
+ bundle_raw *b_service_single_launch = NULL;
+ bundle_raw *b_service_multi_launch = NULL;
+ bundle_raw *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1] = {NULL, };
+ bundle_raw *b_text = NULL;
+ bundle_raw *b_key = NULL;
+ bundle_raw *b_format_args = NULL;
+ GVariant *body = NULL;
+ GVariant *result_body = NULL;
+ GVariantBuilder builder;
+
+ if (translate)
+ notification_translate_localized_text(noti);
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("a{iv}"));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_NOTI_TYPE, g_variant_new_int32(noti->type));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LAYOUT, g_variant_new_int32(noti->layout));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_GROUP_ID, g_variant_new_int32(noti->group_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_INTERNAL_GROUP_ID, g_variant_new_int32(noti->internal_group_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_ID, g_variant_new_int32(noti->priv_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PKG_ID, g_variant_new_string((const gchar *)noti->pkg_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_CALLER_APP_ID, g_variant_new_string((const gchar *)noti->caller_app_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DISPLAY_APPLIST, g_variant_new_int32(noti->display_applist));
+
+ if (noti->args) {
+ bundle_encode(noti->args, (bundle_raw **)&args, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ARGS, g_variant_new_string((const gchar *)args));
+
+ if (args)
+ bundle_free_encoded_rawdata(&args);
+ }
+
+ if (noti->group_args) {
+ bundle_encode(noti->group_args, (bundle_raw **)&group_args,
+ &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_GROUP_ARGS, g_variant_new_string((const gchar *)group_args));
+
+ if (group_args)
+ bundle_free_encoded_rawdata(&group_args);
+ }
+
+ if (noti->b_execute_option) {
+ bundle_encode(noti->b_execute_option,
+ (bundle_raw **)&b_execute_option, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_EXECUTE_OPTION, g_variant_new_string((const gchar *)b_execute_option));
+
+ if (b_execute_option)
+ bundle_free_encoded_rawdata(&b_execute_option);
+ }
+
+ if (noti->b_service_responding) {
+ bundle_encode(noti->b_service_responding,
+ (bundle_raw **)&b_service_responding, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_RESPONDING, g_variant_new_string((const gchar *)b_service_responding));
+
+ if (b_service_responding)
+ bundle_free_encoded_rawdata(&b_service_responding);
+ }
+
+ if (noti->b_service_single_launch) {
+ bundle_encode(noti->b_service_single_launch,
+ (bundle_raw **)&b_service_single_launch, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_SINGLE_LAUNCH, g_variant_new_string((const gchar *)b_service_single_launch));
+
+ if (b_service_single_launch)
+ bundle_free_encoded_rawdata(&b_service_single_launch);
+ }
+
+ if (noti->b_service_multi_launch) {
+ bundle_encode(noti->b_service_multi_launch,
+ (bundle_raw **)&b_service_multi_launch, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_MULTI_LAUNCH, g_variant_new_string((const gchar *)b_service_multi_launch));
+
+ if (b_service_multi_launch)
+ bundle_free_encoded_rawdata(&b_service_multi_launch);
+ }
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i]) {
+ bundle_encode(noti->b_event_handler[i],
+ (bundle_raw **)&b_event_handler[i], &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_BUTTON1_EVENT + i, g_variant_new_string((const gchar *)b_event_handler[i]));
+
+ if (b_event_handler[i])
+ bundle_free_encoded_rawdata(&b_event_handler[i]);
+ }
+ }
+
+ if (noti->launch_app_id)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LAUNCH_APP_ID, g_variant_new_string((const gchar *)noti->launch_app_id));
+
+ if (noti->domain != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DOMAIN, g_variant_new_string((const gchar *)noti->domain));
+
+ if (noti->dir != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DIR, g_variant_new_string((const gchar *)noti->dir));
+
+ if (noti->b_text) {
+ bundle_encode(noti->b_text, (bundle_raw **)&b_text, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEXT, g_variant_new_string((const gchar *)b_text));
+
+ if (b_text)
+ bundle_free_encoded_rawdata(&b_text);
+ }
+
+ if (noti->b_key) {
+ bundle_encode(noti->b_key, (bundle_raw **)&b_key, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_KEY, g_variant_new_string((const gchar *)b_key));
+
+ if (b_key)
+ bundle_free_encoded_rawdata(&b_key);
+ }
+
+ if (noti->b_format_args) {
+ bundle_encode(noti->b_format_args,
+ (bundle_raw **)&b_format_args, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_FORMAT_ARGS, g_variant_new_string((const gchar *)b_format_args));
+
+ if (b_format_args)
+ bundle_free_encoded_rawdata(&b_format_args);
+ }
+
+ if (noti->num_format_args != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_NUM_FORMAT_ARGS, g_variant_new_int32(noti->num_format_args));
+
+ if (noti->b_image_path) {
+ bundle_encode(noti->b_image_path,
+ (bundle_raw **)&b_image_path, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_IMAGE_PATH, g_variant_new_string((const gchar *)b_image_path));
+
+ if (b_image_path)
+ bundle_free_encoded_rawdata(&b_image_path);
+ }
+
+ if (noti->b_priv_image_path) {
+ bundle_encode(noti->b_priv_image_path,
+ (bundle_raw **)&b_priv_image_path, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_IMAGE_PATH, g_variant_new_string((const gchar *)b_priv_image_path));
+
+ if (b_priv_image_path)
+ bundle_free_encoded_rawdata(&b_priv_image_path);
+ }
+
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SOUND_TYPE, g_variant_new_int32(noti->sound_type));
+
+ if (noti->sound_path)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SOUND_PATH, g_variant_new_string((const gchar *)noti->sound_path));
+
+ if (noti->priv_sound_path)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_SOUND_PATH, g_variant_new_string((const gchar *)noti->priv_sound_path));
+
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_VIBRATION_TYPE, g_variant_new_int32(noti->vibration_type));
+
+ if (noti->vibration_path)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_VIBRATION_PATH, g_variant_new_string((const gchar *)noti->vibration_path));
+
+ if (noti->priv_vibration_path)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_VIBRATION_PATH, g_variant_new_string((const gchar *)noti->priv_vibration_path));
+
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_OPERATION, g_variant_new_int32(noti->led_operation));
+
+ if (noti->led_argb != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_ARGB, g_variant_new_int32(noti->led_argb));
+
+ if (noti->led_on_ms != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_ON_MS, g_variant_new_int32(noti->led_on_ms));
+
+ if (noti->led_off_ms != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_OFF_MS, g_variant_new_int32(noti->led_off_ms));
+
+ if (noti->time != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TIME, g_variant_new_int32(noti->time));
+
+ if (noti->insert_time != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_INSERT_TIME, g_variant_new_int32(noti->insert_time));
+
+ if (noti->flags_for_property != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_FLAGS_FOR_PROPERTY, g_variant_new_int32(noti->flags_for_property));
+
+ if (noti->progress_size != 0.0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PROGRESS_SIZE, g_variant_new_double(noti->progress_size));
+
+ if (noti->progress_percentage != 0.0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PROGRESS_PERCENTAGE, g_variant_new_double(noti->progress_percentage));
+
+ if (noti->app_icon_path != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_APP_ICON_PATH, g_variant_new_string((const gchar *)noti->app_icon_path));
+ if (noti->app_label != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_APP_LABEL, g_variant_new_string((const gchar *)noti->app_label));
+ if (noti->temp_title != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEMP_TITLE, g_variant_new_string((const gchar *)noti->temp_title));
+ if (noti->temp_content != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEMP_CONTENT, g_variant_new_string((const gchar *)noti->temp_content));
+ if (noti->tag != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TAG, g_variant_new_string((const gchar *)noti->tag));
+
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_FLAG, g_variant_new_int32(noti->ongoing_flag));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_VALUE_TYPE, g_variant_new_int32(noti->ongoing_value_type));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_CURRENT, g_variant_new_int32(noti->ongoing_current));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_DURATION, g_variant_new_int32(noti->ongoing_duration));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_AUTO_REMOVE, g_variant_new_int32(noti->auto_remove));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DEFAULT_BUTTON, g_variant_new_int32(noti->default_button_index));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_HIDE_TIMEOUT, g_variant_new_int32(noti->hide_timeout));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DELETE_TIMEOUT, g_variant_new_int32(noti->delete_timeout));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEXT_INPUT_MAX_LENGTH, g_variant_new_int32(noti->text_input_max_length));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_EVENT_FLAG, g_variant_new_int32(noti->event_flag));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TRANSLATION, g_variant_new_int32(noti->is_translation));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_EXTENSION_IMAGE_SIZE, g_variant_new_int32(noti->extension_image_size));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_UID, g_variant_new_int32(noti->uid));
+
+ result_body = g_variant_builder_end(&builder);
+ body = g_variant_new("(v)", result_body);
+
+ return body;
+}
+
+static gboolean _variant_to_int_dict(GHashTable **dict, GVariant *variant)
+{
+ GVariantIter iter;
+ int key;
+ int *hash_key;
+ GVariant *value;
+
+ *dict = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, (GDestroyNotify)g_variant_unref);
+ if (*dict == NULL)
+ return FALSE;
+
+ g_variant_iter_init(&iter, variant);
+ while (g_variant_iter_next(&iter, "{iv}", &key, &value)) {
+ hash_key = (int *)calloc(sizeof(int), 1);
+ if (hash_key == NULL) {
+ /* LCOV_EXCL_START */
+ g_hash_table_unref(*dict);
+ return FALSE;
+ /* LCOV_EXCL_STOP */
+ }
+ *hash_key = key;
+ g_hash_table_insert(*dict, (gpointer)hash_key, value);
+ }
+ return TRUE;
+}
+
+static gboolean _variant_dict_lookup(GHashTable *dict,
+ int key,
+ const gchar *format_string,
+ ...)
+{
+ GVariant *value;
+ va_list ap;
+
+ value = g_hash_table_lookup(dict, (gpointer)&key);
+
+ if (value == NULL || !g_variant_check_format_string(value, format_string, FALSE))
+ return FALSE;
+
+ va_start(ap, format_string);
+ g_variant_get_va(value, format_string, NULL, &ap);
+ va_end(ap);
+
+ return TRUE;
+}
+
+/*!
+ * functions creating notification packet
+ */
+EXPORT_API int notification_ipc_make_noti_from_gvariant(notification_h noti,
+ GVariant *variant) {
+
+ DBG("make noti from GVariant");
+ GHashTable *dict;
+
+ int i;
+ char *pkg_id = NULL;
+ char *caller_app_id = NULL;
+ char *launch_app_id = NULL;
+ bundle_raw *args = NULL;
+ bundle_raw *group_args = NULL;
+ bundle_raw *b_execute_option = NULL;
+ bundle_raw *b_service_responding = NULL;
+ bundle_raw *b_service_single_launch = NULL;
+ bundle_raw *b_service_multi_launch = NULL;
+ bundle_raw *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1] = { NULL, };
+ char *domain = NULL;
+ char *dir = NULL;
+ bundle_raw *b_text = NULL;
+ bundle_raw *b_key = NULL;
+ bundle_raw *b_format_args = NULL;
+ bundle_raw *b_image_path = NULL;
+ bundle_raw *b_priv_image_path = NULL;
+ char *sound_path = NULL;
+ char *priv_sound_path = NULL;
+ char *vibration_path = NULL;
+ char *priv_vibration_path = NULL;
+ char *app_icon_path = NULL;
+ char *app_label = NULL;
+ char *temp_title = NULL;
+ char *temp_content = NULL;
+ char *tag = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid noti NULL");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (variant == NULL) {
+ ERR("Invalid variant NULL");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!_variant_to_int_dict(&dict, variant))
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_NOTI_TYPE, "i", &noti->type);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LAYOUT, "i", &noti->layout);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_GROUP_ID, "i", &noti->group_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_INTERNAL_GROUP_ID, "i", &noti->internal_group_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_ID, "i", &noti->priv_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PKG_ID, "&s", &pkg_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_CALLER_APP_ID, "&s", &caller_app_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LAUNCH_APP_ID, "&s", &launch_app_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ARGS, "&s", &args);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_GROUP_ARGS, "&s", &group_args);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EXECUTE_OPTION, "&s", &b_execute_option);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_RESPONDING, "&s", &b_service_responding);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_SINGLE_LAUNCH, "&s", &b_service_single_launch);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_MULTI_LAUNCH, "&s", &b_service_multi_launch);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON1_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON2_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON3_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON4_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON5_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON6_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ICON_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_THUMBNAIL_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEXT_INPUT_BUTTON_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON7_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_7]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON8_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_8]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON9_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_9]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON10_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_10]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DOMAIN, "&s", &domain);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DIR, "&s", &dir);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEXT, "&s", &b_text);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_KEY, "&s", &b_key);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_FORMAT_ARGS, "&s", &b_format_args);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_NUM_FORMAT_ARGS, "i", &noti->num_format_args);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_IMAGE_PATH, "&s", &b_image_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_IMAGE_PATH, "&s", &b_priv_image_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SOUND_TYPE, "i", &noti->sound_type);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SOUND_PATH, "&s", &sound_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_SOUND_PATH, "&s", &priv_sound_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_VIBRATION_TYPE, "i", &noti->vibration_type);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_VIBRATION_PATH, "&s", &vibration_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_VIBRATION_PATH, "&s", &priv_vibration_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_OPERATION, "i", &noti->led_operation);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_ARGB, "i", &noti->led_argb);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_ON_MS, "i", &noti->led_on_ms);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_OFF_MS, "i", &noti->led_off_ms);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TIME, "i", &noti->time);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_INSERT_TIME, "i", &noti->insert_time);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_FLAGS_FOR_PROPERTY, "i", &noti->flags_for_property);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DISPLAY_APPLIST, "i", &noti->display_applist);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PROGRESS_SIZE, "d", &noti->progress_size);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PROGRESS_PERCENTAGE, "d", &noti->progress_percentage);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_APP_ICON_PATH, "&s", &app_icon_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_APP_LABEL, "&s", &app_label);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEMP_TITLE, "&s", &temp_title);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEMP_CONTENT, "&s", &temp_content);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TAG, "&s", &tag);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_FLAG, "i", &noti->ongoing_flag);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_VALUE_TYPE, "i", &noti->ongoing_value_type);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_CURRENT, "i", &noti->ongoing_current);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_DURATION, "i", &noti->ongoing_duration);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_AUTO_REMOVE, "i", &noti->auto_remove);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DEFAULT_BUTTON, "i", &noti->default_button_index);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_HIDE_TIMEOUT, "i", &noti->hide_timeout);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DELETE_TIMEOUT, "i", &noti->delete_timeout);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEXT_INPUT_MAX_LENGTH, "i", &noti->text_input_max_length);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EVENT_FLAG, "i", &noti->event_flag);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TRANSLATION, "i", &noti->is_translation);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EXTENSION_IMAGE_SIZE, "i", &noti->extension_image_size);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_UID, "i", &noti->uid);
+
+ if (noti->pkg_id)
+ free(noti->pkg_id);
+ noti->pkg_id = _dup_string(pkg_id);
+
+ if (noti->caller_app_id)
+ free(noti->caller_app_id);
+ noti->caller_app_id = _dup_string(caller_app_id);
+
+ noti->launch_app_id = _dup_string(launch_app_id);
+
+ noti->args = _create_bundle_from_bundle_raw(args);
+ noti->group_args = _create_bundle_from_bundle_raw(group_args);
+ noti->b_execute_option = _create_bundle_from_bundle_raw(b_execute_option);
+ noti->b_service_responding = _create_bundle_from_bundle_raw(
+ b_service_responding);
+ noti->b_service_single_launch = _create_bundle_from_bundle_raw(
+ b_service_single_launch);
+ noti->b_service_multi_launch = _create_bundle_from_bundle_raw(
+ b_service_multi_launch);
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ noti->b_event_handler[i] = _create_bundle_from_bundle_raw(
+ b_event_handler[i]);
+ }
+
+ if (noti->domain)
+ free(noti->domain);
+ noti->domain = _dup_string(domain);
+
+ if (noti->dir)
+ free(noti->dir);
+ noti->dir = _dup_string(dir);
+
+ noti->b_text = _create_bundle_from_bundle_raw(b_text);
+ noti->b_key = _create_bundle_from_bundle_raw(b_key);
+ noti->b_format_args = _create_bundle_from_bundle_raw(b_format_args);
+ noti->b_image_path = _create_bundle_from_bundle_raw(b_image_path);
+ noti->b_priv_image_path = _create_bundle_from_bundle_raw(b_priv_image_path);
+ noti->sound_path = _dup_string(sound_path);
+ noti->priv_sound_path = _dup_string(priv_sound_path);
+ noti->vibration_path = _dup_string(vibration_path);
+ noti->priv_vibration_path = _dup_string(priv_vibration_path);
+ noti->app_icon_path = _dup_string(app_icon_path);
+ noti->app_label = _dup_string(app_label);
+ noti->temp_title = _dup_string(temp_title);
+ noti->temp_content = _dup_string(temp_content);
+ noti->tag = _dup_string(tag);
+
+ g_hash_table_unref(dict);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API GVariant *notification_ipc_make_gvariant_from_system_setting(struct notification_system_setting *noti_setting)
+{
+ GVariant *body = NULL;
+
+ body = g_variant_new("(iiiiiiiii)",
+ noti_setting->do_not_disturb,
+ noti_setting->visibility_class,
+ noti_setting->dnd_schedule_enabled,
+ noti_setting->dnd_schedule_day,
+ noti_setting->dnd_start_hour,
+ noti_setting->dnd_start_min,
+ noti_setting->dnd_end_hour,
+ noti_setting->dnd_end_min,
+ noti_setting->lock_screen_content_level);
+ return body;
+}
+
+EXPORT_API int notification_ipc_make_system_setting_from_gvariant(struct notification_system_setting *noti_setting,
+ GVariant *variant)
+{
+ int do_not_disturb;
+ int visibility_class;
+ int dnd_schedule_enabled;
+ int dnd_schedule_day;
+ int dnd_start_hour;
+ int dnd_start_min;
+ int dnd_end_hour;
+ int dnd_end_min;
+ int lock_screen_content_level;
+
+ if (noti_setting == NULL) {
+ ERR("Invalid setting handle");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ g_variant_get(variant,
+ "(iiiiiiiii)",
+ &do_not_disturb,
+ &visibility_class,
+ &dnd_schedule_enabled,
+ &dnd_schedule_day,
+ &dnd_start_hour,
+ &dnd_start_min,
+ &dnd_end_hour,
+ &dnd_end_min,
+ &lock_screen_content_level);
+
+ DBG("system setting %d, %d, %d, %d, [%d:%d] [%d:%d], %d",
+ do_not_disturb, visibility_class, dnd_schedule_enabled,
+ dnd_schedule_day, dnd_start_hour, dnd_start_min,
+ dnd_end_hour, dnd_end_min, lock_screen_content_level);
+
+ noti_setting->do_not_disturb = do_not_disturb;
+ noti_setting->visibility_class = visibility_class;
+ noti_setting->dnd_schedule_enabled = dnd_schedule_enabled;
+ noti_setting->dnd_schedule_day = dnd_schedule_day;
+ noti_setting->dnd_start_hour = dnd_start_hour;
+ noti_setting->dnd_start_min = dnd_start_min;
+ noti_setting->dnd_end_hour = dnd_end_hour;
+ noti_setting->dnd_end_min = dnd_end_min;
+ noti_setting->lock_screen_content_level = lock_screen_content_level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API GVariant *notification_ipc_make_gvariant_from_setting(struct notification_setting *noti_setting)
+{
+ GVariant *body = NULL;
+
+ body = g_variant_new("(ssiiiiii)",
+ noti_setting->package_name,
+ noti_setting->app_id,
+ noti_setting->allow_to_notify,
+ noti_setting->do_not_disturb_except,
+ noti_setting->visibility_class,
+ noti_setting->pop_up_notification,
+ noti_setting->lock_screen_content_level,
+ noti_setting->app_disabled);
+
+ return body;
+}
+
+EXPORT_API int notification_ipc_make_setting_from_gvariant(struct notification_setting *noti_setting,
+ GVariant *variant)
+{
+ char *pkgname;
+ char *app_id;
+ int allow_to_notify;
+ int do_not_disturb_except;
+ int visibility_class;
+ int pop_up_notification;
+ int lock_screen_content_level;
+ int app_disabled;
+
+ if (noti_setting == NULL || variant == NULL) {
+ ERR("invalid data");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+ g_variant_get(variant,
+ "(&s&siiiiii)",
+ &pkgname,
+ &app_id,
+ &allow_to_notify,
+ &do_not_disturb_except,
+ &visibility_class,
+ &pop_up_notification,
+ &lock_screen_content_level,
+ &app_disabled);
+
+ DBG("setting from variant %s !!", pkgname);
+
+ noti_setting->package_name = _dup_string(pkgname);
+ noti_setting->app_id = _dup_string(app_id);
+ noti_setting->allow_to_notify = allow_to_notify;
+ noti_setting->do_not_disturb_except = do_not_disturb_except;
+ noti_setting->visibility_class = visibility_class;
+ noti_setting->pop_up_notification = pop_up_notification;
+ noti_setting->lock_screen_content_level = lock_screen_content_level;
+ noti_setting->app_disabled = app_disabled;
+
+ DBG("setting->pkgname[%s] pkgname[%s]",
+ noti_setting->package_name, pkgname);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API GVariant *notification_ipc_make_gvariant_from_dnd_allow_exception(struct notification_system_setting_dnd_allow_exception *dnd_allow_exception)
+{
+ GVariant *body = NULL;
+
+ body = g_variant_new("(ii)",
+ dnd_allow_exception->type,
+ dnd_allow_exception->value);
+
+ return body;
+}
+
+int notification_ipc_make_dnd_allow_exception_from_gvariant(struct notification_system_setting_dnd_allow_exception *dnd_allow_exception, GVariant *variant)
+{
+ int type;
+ int value;
+
+ if (dnd_allow_exception == NULL) {
+ ERR("Invalid data");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ g_variant_get(variant, "(ii)", &type, &value);
+
+ dnd_allow_exception->type = type;
+ dnd_allow_exception->value = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static int _send_service_register(uid_t uid)
+{
+ int result;
+ notification_op *noti_op = NULL;
+ GDBusMessage *reply = NULL;
+
+ result = _send_sync_noti(g_variant_new("(i)", uid), &reply, "noti_service_register");
+ if (reply)
+ g_object_unref(reply);
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("send sync noti [%d]", result);
+ return result;
+ }
+
+ is_master_started = 1;
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_SERVICE_READY, 1, NULL, 1, NULL);
+ if (noti_op != NULL) {
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+ free(noti_op);
+ } else {
+ ERR("Failed to create op");
+ }
+
+ DBG("bus name[%s] result[%d]", _bus_name, result);
+ return result;
+}
+
+static int _ipc_monitor_register(uid_t uid)
+{
+ return _send_service_register(uid);
+}
+
+/* LCOV_EXCL_START */
+static void _on_name_appeared(GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ int uid = GPOINTER_TO_INT(user_data);
+
+ DBG("uid[%d] name[%s]", uid, name);
+
+ if (is_master_started == 0)
+ _ipc_monitor_register(uid);
+
+ /* TODO: dbus activation isn't enough ? */
+ _do_deffered_task();
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _on_name_vanished(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ int uid = GPOINTER_TO_INT(user_data);
+
+ DBG("uid[%d] name[%s]", uid, name);
+ is_master_started = 0;
+}
+/* LCOV_EXCL_STOP */
+
+int notification_ipc_monitor_init(uid_t uid)
+{
+ int ret;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _dbus_signal_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init signal[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _ipc_monitor_register(uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to register service[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (provider_monitor_id == 0) {
+ provider_monitor_id = g_bus_watch_name_on_connection(
+ _gdbus_conn,
+ PROVIDER_BUS_NAME,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ _on_name_appeared,
+ _on_name_vanished,
+ GINT_TO_POINTER((int)uid),
+ NULL);
+ if (provider_monitor_id == 0) {
+ /* LCOV_EXCL_START */
+ g_dbus_connection_signal_unsubscribe(_gdbus_conn, monitor_id);
+ monitor_id = 0;
+ ERR("Failed to watch name");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static int _ipc_monitor_deregister(void)
+{
+ if (provider_monitor_id) {
+ g_bus_unwatch_name(provider_monitor_id);
+ provider_monitor_id = 0;
+ }
+
+ if (monitor_id) {
+ g_dbus_connection_signal_unsubscribe(_gdbus_conn, monitor_id);
+ monitor_id = 0;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ipc_monitor_fini(void)
+{
+ return _ipc_monitor_deregister();
+}
+
+/* LCOV_EXCL_START */
+void notification_ipc_event_monitor_fini(void)
+{
+ if (event_monitor_id == 0)
+ return;
+
+ g_dbus_connection_signal_unsubscribe(_gdbus_conn, event_monitor_id);
+ event_monitor_id = 0;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/src/notification_ipc_socket.c b/notification/src/notification_ipc_socket.c
new file mode 100644
index 0000000..54090ac
--- /dev/null
+++ b/notification/src/notification_ipc_socket.c
@@ -0,0 +1,173 @@
+/*
+ * 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_socket_get_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) {
+ /* LCOV_EXCL_START */
+ 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;
+ /* LCOV_EXCL_STOP */
+ }
+
+ 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) {
+ /* LCOV_EXCL_START */
+ ERR("write string_len fail");
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (string_len > 0) {
+ ret = notification_ipc_socket_write(fd, buffer, string_len);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("write string fail");
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ 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;
+}
diff --git a/notification/src/notification_list.c b/notification/src/notification_list.c
new file mode 100644
index 0000000..18d14b2
--- /dev/null
+++ b/notification/src/notification_list.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2000 - 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 <stdlib.h>
+
+#include <tizen.h>
+
+#include <notification.h>
+#include <notification_list.h>
+#include <notification_noti.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_ipc.h>
+
+
+struct _notification_list {
+ notification_list_h prev;
+ notification_list_h next;
+ notification_h noti;
+};
+
+notification_list_h _notification_list_create(void)
+{
+ notification_list_h list = NULL;
+
+ list = (notification_list_h)malloc(sizeof(struct _notification_list));
+ if (list == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ list->prev = NULL;
+ list->next = NULL;
+
+ list->noti = NULL;
+
+ return list;
+}
+
+EXPORT_API notification_list_h notification_list_get_head(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("Invalid parameter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ while (cur_list->prev != NULL)
+ cur_list = cur_list->prev;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list;
+}
+
+EXPORT_API notification_list_h notification_list_get_tail(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("INVALID DATA : list == NULL");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ while (cur_list->next != NULL)
+ cur_list = cur_list->next;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list;
+}
+
+EXPORT_API notification_list_h notification_list_get_prev(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("INVALID DATA : list == NULL");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list->prev;
+}
+
+EXPORT_API notification_list_h notification_list_get_next(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("INVALID DATA : list == NULL");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list->next;
+}
+
+EXPORT_API notification_h notification_list_get_data(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("INVALID DATA : list == NULL");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list->noti;
+}
+
+EXPORT_API int notification_list_get_count(notification_list_h list)
+{
+ int count = 0;
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("Invalid paramter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ cur_list = notification_list_get_head(list);
+
+ while (cur_list != NULL) {
+ count++;
+ cur_list = cur_list->next;
+ }
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return count;
+}
+
+EXPORT_API notification_list_h notification_list_append(notification_list_h list,
+ notification_h noti)
+{
+ notification_list_h new_list = NULL;
+ notification_list_h cur_list = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid parameter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ if (list != NULL) {
+ cur_list = notification_list_get_tail(list);
+
+ new_list = _notification_list_create();
+ if (new_list == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ cur_list->next = new_list;
+ new_list->prev = cur_list;
+
+ new_list->noti = noti;
+ } else {
+ cur_list = _notification_list_create();
+ if (cur_list == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ new_list = cur_list;
+ new_list->noti = noti;
+ }
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return new_list;
+}
+
+EXPORT_API notification_list_h notification_list_remove(notification_list_h list,
+ notification_h noti)
+{
+ notification_list_h cur_list = NULL;
+ notification_list_h prev_list = NULL;
+ notification_list_h next_list = NULL;
+
+ cur_list = notification_list_get_head(list);
+ while (cur_list != NULL) {
+ if (cur_list->noti == noti) {
+ /* remove */
+ prev_list = cur_list->prev;
+ next_list = cur_list->next;
+
+ if (next_list != NULL) {
+ if (prev_list != NULL) {
+ prev_list->next = next_list;
+ next_list->prev = prev_list;
+ } else {
+ next_list->prev = NULL;
+ }
+ } else {
+ if (prev_list != NULL)
+ prev_list->next = NULL;
+ }
+
+ free(cur_list);
+ break;
+ }
+
+ cur_list = cur_list->next;
+ }
+
+ if (prev_list != NULL)
+ return notification_list_get_head(prev_list);
+ else if (next_list != NULL)
+ return next_list;
+
+ return NULL;
+}
+
+EXPORT_API int notification_get_list_for_uid(notification_type_e type,
+ int count,
+ notification_list_h *list, uid_t uid)
+{
+ notification_list_h get_list = NULL;
+ int ret = 0;
+
+ if (list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_ipc_request_load_noti_grouping_list(type, 1, count, &get_list, uid);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ if (get_list != NULL)
+ *list = notification_list_get_head(get_list);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_list(notification_type_e type,
+ int count,
+ notification_list_h *list)
+{
+ 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,
+ int count,
+ notification_list_h *list,
+ uid_t uid)
+{
+ int ret = 0;
+ notification_list_h get_list = NULL;
+
+ if (list == NULL || app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_ipc_request_load_noti_detail_list(app_id, group_id, priv_id, count,
+ &get_list, uid);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ if (get_list != NULL)
+ *list = notification_list_get_head(get_list);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_detail_list(const char *app_id,
+ int group_id,
+ int priv_id,
+ int count,
+ notification_list_h *list)
+{
+ return notification_get_detail_list_for_uid(app_id, group_id,
+ priv_id, count, list, getuid());
+}
+
+EXPORT_API int notification_free_list(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+ notification_h noti = NULL;
+
+ if (list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ cur_list = notification_list_get_head(list);
+
+ while (cur_list != NULL) {
+ noti = notification_list_get_data(cur_list);
+ cur_list = notification_list_remove(cur_list, noti);
+
+ notification_free(noti);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
diff --git a/notification/src/notification_noti.c b/notification/src/notification_noti.c
new file mode 100644
index 0000000..df0455e
--- /dev/null
+++ b/notification/src/notification_noti.c
@@ -0,0 +1,2299 @@
+/*
+ * Copyright (c) 2000 - 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.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <vconf.h>
+#include <pkgmgr-info.h>
+#include <package_manager.h>
+#include <app_control_internal.h>
+#include <bundle_internal.h>
+#include <iniparser.h>
+
+#include <notification.h>
+#include <notification_internal.h>
+#include <notification_db.h>
+#include <notification_list.h>
+#include <notification_noti.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include <notification_setting_service.h>
+#include "notification_db_query.h"
+
+#define NOTI_BURST_DELETE_UNIT 10
+#define ERR_BUFFER_SIZE 1024
+#define NOTI_LIMIT 100
+
+static void __free_and_set(void **target_ptr, void *new_ptr)
+{
+ if (target_ptr != NULL) {
+ if (*target_ptr != NULL)
+ free(*target_ptr);
+
+ *target_ptr = new_ptr;
+ }
+}
+
+static void __free_encoded_data(char *encoded_data)
+{
+ if (encoded_data)
+ bundle_free_encoded_rawdata((bundle_raw **)&encoded_data);
+}
+
+static void __free_deleted_list(notification_deleted_list_info_s *info, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if ((info + i)->app_id != NULL)
+ free((info + i)->app_id);
+ }
+
+ free(info);
+}
+
+static void __notification_noti_populate_from_stmt(sqlite3_stmt *stmt, notification_h noti)
+{
+ int col = 0;
+ int i = 0;
+
+ if (stmt == NULL || noti == NULL)
+ return;
+
+ noti->type = sqlite3_column_int(stmt, col++);
+ noti->layout = sqlite3_column_int(stmt, col++);
+ __free_and_set((void **)&(noti->pkg_id), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->caller_app_id), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->launch_app_id), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->app_label), notification_db_column_text(stmt, col++));
+ noti->b_image_path = notification_db_column_bundle(stmt, col++);
+ noti->b_priv_image_path = notification_db_column_bundle(stmt, col++);
+ noti->group_id = sqlite3_column_int(stmt, col++);
+ noti->internal_group_id = 0;
+ noti->priv_id = sqlite3_column_int(stmt, col++);
+ noti->b_text = notification_db_column_bundle(stmt, col++);
+ noti->b_key = notification_db_column_bundle(stmt, col++);
+ __free_and_set((void **)&(noti->tag), notification_db_column_text(stmt, col++));
+ noti->b_format_args = notification_db_column_bundle(stmt, col++);
+ noti->num_format_args = sqlite3_column_int(stmt, col++);
+
+ __free_and_set((void **)&(noti->domain), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->dir), notification_db_column_text(stmt, col++));
+ noti->time = sqlite3_column_int(stmt, col++);
+ noti->insert_time = sqlite3_column_int(stmt, col++);
+ noti->args = notification_db_column_bundle(stmt, col++);
+ noti->group_args = notification_db_column_bundle(stmt, col++);
+
+ noti->b_execute_option = notification_db_column_bundle(stmt, col++);
+ noti->b_service_responding = notification_db_column_bundle(stmt, col++);
+ noti->b_service_single_launch =
+ notification_db_column_bundle(stmt, col++);
+ noti->b_service_multi_launch =
+ notification_db_column_bundle(stmt, col++);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++)
+ noti->b_event_handler[i] = notification_db_column_bundle(stmt, col++);
+
+ noti->sound_type = sqlite3_column_int(stmt, col++);
+ __free_and_set((void **)&(noti->sound_path), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->priv_sound_path), notification_db_column_text(stmt, col++));
+ noti->vibration_type = sqlite3_column_int(stmt, col++);
+ __free_and_set((void **)&(noti->vibration_path), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->priv_vibration_path), notification_db_column_text(stmt, col++));
+ noti->led_operation = sqlite3_column_int(stmt, col++);
+ noti->led_argb = sqlite3_column_int(stmt, col++);
+ noti->led_on_ms = sqlite3_column_int(stmt, col++);
+ noti->led_off_ms = sqlite3_column_int(stmt, col++);
+
+ noti->flags_for_property = sqlite3_column_int(stmt, col++);
+ noti->display_applist = sqlite3_column_int(stmt, col++);
+ noti->progress_size = sqlite3_column_double(stmt, col++);
+ noti->progress_percentage = sqlite3_column_double(stmt, col++);
+
+ noti->ongoing_flag = sqlite3_column_int(stmt, col++);
+ noti->ongoing_value_type = sqlite3_column_int(stmt, col++);
+ noti->ongoing_current = sqlite3_column_int(stmt, col++);
+ noti->ongoing_duration = sqlite3_column_int(stmt, col++);
+ noti->auto_remove = sqlite3_column_int(stmt, col++);
+ noti->default_button_index = sqlite3_column_int(stmt, col++);
+ noti->hide_timeout = sqlite3_column_int(stmt, col++);
+ noti->delete_timeout = sqlite3_column_int(stmt, col++);
+ noti->text_input_max_length = sqlite3_column_int(stmt, col++);
+ noti->event_flag = sqlite3_column_int(stmt, col++);
+ noti->extension_image_size = sqlite3_column_int(stmt, col++);
+ noti->uid = sqlite3_column_int(stmt, col++);
+
+ noti->app_icon_path = NULL;
+ noti->temp_title = NULL;
+ noti->temp_content = NULL;
+}
+
+static int _notification_noti_check_priv_id(notification_h noti, sqlite3 *db)
+{
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int result = 0;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ query = sqlite3_mprintf("SELECT count(*) FROM noti_list "
+ "WHERE caller_app_id = %Q AND priv_id = %d",
+ noti->caller_app_id, noti->priv_id);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_v2 Failed [%d][%s]",
+ ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+ /* If result > 0, there is priv_id in DB */
+ if (result > 0)
+ ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ return ret;
+}
+
+static int _notification_noti_get_internal_group_id_by_priv_id(const char *app_id,
+ int priv_id,
+ sqlite3 *db)
+{
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int result = 0;
+
+ query = sqlite3_mprintf("SELECT internal_group_id FROM noti_list "
+ "WHERE caller_app_id = %Q AND priv_id = %d",
+ app_id, priv_id);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (ret != NOTIFICATION_ERROR_NONE)
+ ERR("Failed to get internal group ID [%d]", ret);
+
+ return result;
+}
+
+static int _create_insertion_query(sqlite3 *db, notification_h noti, sqlite3_stmt *stmt, int *index)
+{
+ char buf_key[32] = { 0, };
+ char *title_key = NULL;
+ char *b_text = NULL;
+ char *b_key = NULL;
+ char *b_format_args = NULL;
+ char *args = NULL;
+ char *group_args = NULL;
+ char *b_image_path = NULL;
+ char *b_priv_image_path = NULL;
+ char *b_execute_option = NULL;
+ char *b_service_responding = NULL;
+ char *b_service_single_launch = NULL;
+ char *b_service_multi_launch = NULL;
+ char *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1] = { NULL, };
+ int flag_simmode = 0;
+ int idx = 1;
+ int i = 0;
+ int b_encode_len = 0;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (noti == NULL || stmt == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_image_path)
+ bundle_encode(noti->b_image_path, (bundle_raw **)&b_image_path,
+ &b_encode_len);
+
+ if (noti->b_priv_image_path)
+ bundle_encode(noti->b_priv_image_path,
+ (bundle_raw **)&b_priv_image_path, &b_encode_len);
+
+ /* Get title key */
+ if (noti->b_key != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "%d",
+ NOTIFICATION_TEXT_TYPE_TITLE);
+
+ bundle_get_str(noti->b_key, buf_key, &title_key);
+ }
+
+ if (title_key == NULL && noti->b_text != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "%d",
+ NOTIFICATION_TEXT_TYPE_TITLE);
+
+ bundle_get_str(noti->b_text, buf_key, &title_key);
+ }
+
+ if (title_key == NULL)
+ title_key = noti->caller_app_id;
+
+ if (noti->b_text)
+ bundle_encode(noti->b_text, (bundle_raw **)&b_text, &b_encode_len);
+
+ if (noti->b_key)
+ bundle_encode(noti->b_key, (bundle_raw **)&b_key, &b_encode_len);
+
+ if (noti->b_format_args)
+ bundle_encode(noti->b_format_args,
+ (bundle_raw **)&b_format_args, &b_encode_len);
+
+ if (noti->args)
+ bundle_encode(noti->args, (bundle_raw **)&args, &b_encode_len);
+
+ if (noti->group_args)
+ bundle_encode(noti->group_args, (bundle_raw **)&group_args,
+ &b_encode_len);
+
+ if (noti->b_execute_option)
+ bundle_encode(noti->b_execute_option,
+ (bundle_raw **)&b_execute_option, &b_encode_len);
+
+ if (noti->b_service_responding)
+ bundle_encode(noti->b_service_responding,
+ (bundle_raw **)&b_service_responding, &b_encode_len);
+
+ if (noti->b_service_single_launch)
+ bundle_encode(noti->b_service_single_launch,
+ (bundle_raw **)&b_service_single_launch, &b_encode_len);
+
+ if (noti->b_service_multi_launch)
+ bundle_encode(noti->b_service_multi_launch,
+ (bundle_raw **)&b_service_multi_launch, &b_encode_len);
+
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i])
+ bundle_encode(noti->b_event_handler[i],
+ (bundle_raw **)&b_event_handler[i], &b_encode_len);
+ }
+
+ /* Check only simmode property is enable */
+ if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE)
+ flag_simmode = 1;
+
+ __BIND_INT(db, stmt, idx++, noti->type, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->layout, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->pkg_id), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->caller_app_id), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->launch_app_id), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->app_label), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_image_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_priv_image_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->group_id, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->internal_group_id, ret, out);
+ __BIND_TEXT_STATIC(db, stmt, idx++, NOTIFICATION_CHECK_STR(title_key), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_text), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_key), ret, out);
+ __BIND_TEXT_STATIC(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->tag), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_format_args), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->num_format_args, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->domain), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->dir), ret, out);
+ __BIND_INT(db, stmt, idx++, (int)noti->time, ret, out);
+ __BIND_INT(db, stmt, idx++, (int)noti->insert_time, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(args), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(group_args), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_execute_option), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_responding), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_single_launch), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_multi_launch), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_7]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_8]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_9]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_10]), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->sound_type, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->sound_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->priv_sound_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->vibration_type, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->vibration_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->priv_vibration_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_operation, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_argb, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_on_ms, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_off_ms, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->flags_for_property, ret, out);
+ __BIND_INT(db, stmt, idx++, flag_simmode, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->display_applist, ret, out);
+ __BIND_DOUBLE(db, stmt, idx++, noti->progress_size, ret, out);
+ __BIND_DOUBLE(db, stmt, idx++, noti->progress_percentage, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_flag, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_value_type, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_current, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_duration, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->auto_remove, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->default_button_index, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->hide_timeout, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->delete_timeout, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->text_input_max_length, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->event_flag, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->extension_image_size, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->uid, ret, out);
+
+out:
+ __free_encoded_data(b_image_path);
+ __free_encoded_data(b_priv_image_path);
+ __free_encoded_data(b_text);
+ __free_encoded_data(b_key);
+ __free_encoded_data(b_format_args);
+ __free_encoded_data(args);
+ __free_encoded_data(group_args);
+ __free_encoded_data(b_execute_option);
+ __free_encoded_data(b_service_responding);
+ __free_encoded_data(b_service_single_launch);
+ __free_encoded_data(b_service_multi_launch);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++)
+ __free_encoded_data(b_event_handler[i]);
+
+ if (index != NULL && ret == NOTIFICATION_ERROR_NONE)
+ *index = idx;
+
+ return ret;
+}
+
+static int _create_update_query(sqlite3 *db, notification_h noti, sqlite3_stmt *stmt)
+{
+ char *b_image_path = NULL;
+ char *b_priv_image_path = NULL;
+ char *b_text = NULL;
+ char *b_key = NULL;
+ char *b_format_args = NULL;
+ char *args = NULL;
+ char *group_args = NULL;
+ char *b_execute_option = NULL;
+ char *b_service_responding = NULL;
+ char *b_service_single_launch = NULL;
+ char *b_service_multi_launch = NULL;
+ char *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1] = { NULL, };
+ int flag_simmode = 0;
+ int idx = 1;
+ int i = 0;
+ int b_encode_len = 0;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (noti == NULL || stmt == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ /* Decode bundle to update DB */
+ if (noti->b_image_path)
+ bundle_encode(noti->b_image_path,
+ (bundle_raw **)&b_image_path, &b_encode_len);
+
+ if (noti->b_priv_image_path)
+ bundle_encode(noti->b_priv_image_path,
+ (bundle_raw **)&b_priv_image_path, &b_encode_len);
+
+ if (noti->b_text)
+ bundle_encode(noti->b_text,
+ (bundle_raw **)&b_text, &b_encode_len);
+
+ if (noti->b_key)
+ bundle_encode(noti->b_key,
+ (bundle_raw **)&b_key, &b_encode_len);
+
+ if (noti->b_format_args)
+ bundle_encode(noti->b_format_args,
+ (bundle_raw **)&b_format_args, &b_encode_len);
+
+ if (noti->args)
+ bundle_encode(noti->args, (bundle_raw **)&args, &b_encode_len);
+
+ if (noti->group_args)
+ bundle_encode(noti->group_args, (bundle_raw **)&group_args,
+ &b_encode_len);
+
+ if (noti->b_execute_option)
+ bundle_encode(noti->b_execute_option,
+ (bundle_raw **)&b_execute_option, &b_encode_len);
+
+ if (noti->b_service_responding)
+ bundle_encode(noti->b_service_responding,
+ (bundle_raw **)&b_service_responding, &b_encode_len);
+
+ if (noti->b_service_single_launch)
+ bundle_encode(noti->b_service_single_launch,
+ (bundle_raw **)&b_service_single_launch, &b_encode_len);
+
+ if (noti->b_service_multi_launch)
+ bundle_encode(noti->b_service_multi_launch,
+ (bundle_raw **)&b_service_multi_launch, &b_encode_len);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i])
+ bundle_encode(noti->b_event_handler[i],
+ (bundle_raw **)&b_event_handler[i], &b_encode_len);
+ }
+
+ /* Check only simmode property is enable */
+ if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE)
+ flag_simmode = 1;
+
+ __BIND_INT(db, stmt, idx++, noti->type, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->layout, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->launch_app_id), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->app_label), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_image_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_priv_image_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_text), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_key), ret, out);
+ __BIND_TEXT_STATIC(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->tag), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_format_args), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->num_format_args, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->domain), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->dir), ret, out);
+ __BIND_INT(db, stmt, idx++, (int)noti->time, ret, out);
+ __BIND_INT(db, stmt, idx++, (int)noti->insert_time, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(args), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(group_args), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_execute_option), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_responding), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_single_launch), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_multi_launch), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_7]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_8]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_9]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_10]), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->sound_type, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->sound_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->priv_sound_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->vibration_type, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->vibration_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->priv_vibration_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_operation, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_argb, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_on_ms, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_off_ms, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->flags_for_property, ret, out);
+ __BIND_INT(db, stmt, idx++, flag_simmode, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->display_applist, ret, out);
+ __BIND_DOUBLE(db, stmt, idx++, noti->progress_size, ret, out);
+ __BIND_DOUBLE(db, stmt, idx++, noti->progress_percentage, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_flag, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_value_type, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_current, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_duration, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->auto_remove, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->default_button_index, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->hide_timeout, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->delete_timeout, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->text_input_max_length, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->event_flag, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->extension_image_size, ret, out);
+
+out:
+ __free_encoded_data(b_image_path);
+ __free_encoded_data(b_priv_image_path);
+ __free_encoded_data(b_text);
+ __free_encoded_data(b_key);
+ __free_encoded_data(b_format_args);
+ __free_encoded_data(args);
+ __free_encoded_data(group_args);
+ __free_encoded_data(b_execute_option);
+ __free_encoded_data(b_service_responding);
+ __free_encoded_data(b_service_single_launch);
+ __free_encoded_data(b_service_multi_launch);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++)
+ __free_encoded_data(b_event_handler[i]);
+
+ return ret;
+}
+
+static int _get_notification(char *query_where, notification_h noti)
+{
+ int ret;
+ char *query = NULL;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+
+ if (query_where == NULL || noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s",
+ NOTI_LIST_DB_ATTRIBUTES_SELECT, query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW) {
+ __notification_noti_populate_from_stmt(stmt, noti);
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ if (ret == SQLITE_DONE)
+ DBG("No valid record found");
+ else
+ ERR("sqlite3_step failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+err:
+ if (query)
+ sqlite3_free(query);
+
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (db != NULL)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+static int _get_notification_list(char *query_where, notification_list_h *list, int *list_count, int count)
+{
+ int ret;
+ int internal_count = 0;
+ char *query = NULL;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ notification_list_h get_list = NULL;
+ notification_h noti = NULL;
+
+ if (query_where == NULL || list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s",
+ NOTI_LIST_DB_ATTRIBUTES_SELECT, query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ if (get_list) {
+ get_list = notification_list_get_head(get_list);
+ notification_free_list(get_list);
+ }
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ __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);
+ break;
+ }
+ }
+ }
+
+ if (get_list != NULL) {
+ *list = notification_list_get_head(get_list);
+ if (list_count)
+ *list_count = internal_count;
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (db != NULL)
+ notification_db_close(&db);
+
+ if (query)
+ sqlite3_free(query);
+
+ return ret;
+}
+int notification_noti_set_tag(const char *tag, char *value, char *buf, int buf_len)
+{
+ int len_total = 0;
+
+ len_total += (strlen(tag) * 2) + 5 + strlen(value) + 1;
+
+ if (buf_len <= len_total)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ snprintf(buf, buf_len, "<%s>%s</%s>", tag, value, tag);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+char *notification_noti_strip_tag(const char *tagged_str)
+{
+ if (tagged_str == NULL)
+ return NULL;
+
+ int len_total = strlen(tagged_str);
+
+ if (len_total == 0)
+ return NULL;
+
+ char *b_f_e = strstr(tagged_str, ">");
+ char *b_e_s = strstr(tagged_str, "</");
+
+ if (b_f_e == NULL || b_e_s == NULL || (b_e_s - b_f_e - 1) <= 0)
+ return NULL;
+
+ return strndup(b_f_e + 1, b_e_s - b_f_e - 1);
+}
+
+int notification_noti_get_tag_type(const char *tagged_str)
+{
+ if (tagged_str == NULL)
+ return TAG_TYPE_INVALID;
+
+ if (strlen(tagged_str) == 0)
+ return TAG_TYPE_INVALID;
+
+ char *b_f_s = strstr(tagged_str, "<");
+ char *b_f_e = strstr(tagged_str, ">");
+
+ if (b_f_s == NULL || b_f_e == NULL || (b_f_e - b_f_s - 1) <= 0)
+ return TAG_TYPE_INVALID;
+
+ char *start = b_f_s + 1;
+ int len_tag = b_f_e - b_f_s - 1;
+
+ if (strncmp(start, TAG_TIME, len_tag) == 0)
+ return TAG_TYPE_TIME;
+
+ return TAG_TYPE_INVALID;
+}
+
+/* LCOV_EXCL_START */
+static int __get_setting_from_app_control(notification_h noti, notification_setting_h *setting)
+{
+ notification_setting_h setting_new = NULL;
+ app_control_h app_control = NULL;
+ bundle *b = NULL;
+ char *app_id = NULL;
+ int ret;
+
+ ret = notification_get_execute_option(noti,
+ NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH,
+ NULL,
+ &b);
+ if (ret != NOTIFICATION_ERROR_NONE || b == NULL) {
+ WARN("Failed to get or no the excute option [%x]", ret);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = app_control_create(&app_control);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ ERR("Failed to create app_control [%x]", ret);
+ goto out;
+ }
+
+ ret = app_control_import_from_bundle(app_control, b);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ ERR("Failed to import from bundle to app_control [%x]", ret);
+ goto out;
+ }
+
+ ret = app_control_get_app_id(app_control, &app_id);
+ if (ret != APP_CONTROL_ERROR_NONE || app_id == NULL) {
+ ERR("Failed to get app id from app_control [%x]", ret);
+ goto out;
+ }
+
+ ret = noti_setting_service_get_setting_by_app_id(app_id, &setting_new, noti->uid);
+ if (ret != APP_CONTROL_ERROR_NONE || setting == NULL) {
+ ERR("Failed to get setting by app id[%s][%x]",
+ app_id, ret);
+ goto out;
+ }
+
+ *setting = setting_new;
+
+out:
+ if (app_id)
+ free(app_id);
+
+ if (app_control)
+ app_control_destroy(app_control);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+static bool _is_allowed_to_notify(notification_h noti)
+{
+ notification_setting_h setting = NULL;
+ bool allow_to_notify = true;
+ bool app_disabled = false;
+ bool ret = true;
+ int err;
+
+ err = noti_setting_service_get_setting_by_app_id(noti->caller_app_id,
+ &setting, noti->uid);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ err = __get_setting_from_app_control(noti, &setting);
+ if (err != NOTIFICATION_ERROR_NONE)
+ return ret;
+ }
+
+ err = notification_setting_get_allow_to_notify(setting, &allow_to_notify);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get allow_to_notify [%x]", err);
+ goto out;
+ }
+
+ err = notification_setting_get_app_disabled(setting, &app_disabled);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get app_disabled [%x]", err);
+ goto out;
+ }
+
+ if (!allow_to_notify || app_disabled)
+ ret = false;
+
+out:
+ if (setting)
+ notification_setting_free_notification(setting);
+
+ return ret;
+}
+
+static int _handle_do_not_disturb_option(notification_h noti)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ bool do_not_disturb = false;
+ bool do_not_disturb_exception = false;
+ notification_setting_h setting = NULL;
+ notification_system_setting_h system_setting = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid notification handle");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ /* Get system setting */
+ err = noti_system_setting_load_system_setting(&system_setting, noti->uid);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to load system setting [%d]", err);
+ goto out;
+ }
+
+ err = notification_system_setting_get_do_not_disturb(system_setting,
+ &do_not_disturb);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get do_not_disturb [%d]", err);
+ goto out;
+ }
+
+ DBG("do_not_disturb [%d]", do_not_disturb);
+
+ if (do_not_disturb) {
+ /* Check exception option of the caller app_id */
+ err = noti_setting_service_get_setting_by_app_id(noti->caller_app_id, &setting, noti->uid);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get setting by app_id [%d]", err);
+ goto out;
+ }
+
+ err = notification_setting_get_do_not_disturb_except(setting, &do_not_disturb_exception);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get do_not_disturb_exception [%d]", err);
+ goto out;
+ }
+
+ if (do_not_disturb_exception == false) {
+ /* do_not_disturb is ON and do_not_disturb_exception is OFF */
+ /* Then add this notification only on quick panel and indicator */
+ noti->display_applist = noti->display_applist &
+ (NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
+ NOTIFICATION_DISPLAY_APP_INDICATOR);
+ /* and reset all sound and vibration and led options */
+ noti->sound_type = NOTIFICATION_SOUND_TYPE_NONE;
+ SAFE_FREE(noti->sound_path);
+ SAFE_FREE(noti->priv_sound_path);
+ noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+ SAFE_FREE(noti->vibration_path);
+ SAFE_FREE(noti->priv_vibration_path);
+ noti->led_operation = NOTIFICATION_LED_OP_OFF;
+ noti->led_argb = 0;
+ noti->led_on_ms = 0;
+ noti->led_off_ms = 0;
+ }
+ }
+
+out:
+ if (system_setting)
+ notification_system_setting_free_system_setting(system_setting);
+
+ if (setting)
+ notification_setting_free_notification(setting);
+
+ return err;
+}
+
+static bool _is_pop_up_notification(const char *app_id, uid_t uid)
+{
+ int err;
+ bool ret = true;
+ notification_setting_h setting = NULL;
+
+ err = noti_setting_service_get_setting_by_app_id(app_id, &setting, uid);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ WARN("Failed get the setting for [%s] [%x]", app_id, err);
+ goto out;
+ }
+
+ err = notification_setting_get_pop_up_notification(setting, &ret);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get pop_up_notification [%d]", err);
+ goto out;
+ }
+
+ if (ret != true)
+ DBG("[%s] is not allowed Pop-up notification", app_id);
+
+out:
+ if (setting)
+ notification_setting_free_notification(setting);
+
+ return ret;
+}
+
+static int _check_text_input(notification_h noti)
+{
+ int err;
+ int text_input_max_length;
+ app_control_h app_control = NULL;
+
+ err = notification_get_text_input_max_length(noti, &text_input_max_length);
+ if (err == NOTIFICATION_ERROR_NONE && text_input_max_length != 0) {
+ err = notification_get_event_handler(noti, NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON, &app_control);
+ if (err != NOTIFICATION_ERROR_NONE || app_control == NULL) {
+ ERR("Event handler for text_input is not set");
+ return -1;
+ }
+ app_control_destroy(app_control);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static int _get_noti_count(sqlite3 *db, char *query_where, int *count)
+{
+ int ret;
+ char *query = NULL;
+ sqlite3_stmt *stmt = NULL;
+
+ if (db == NULL || query_where == NULL || count == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ query = sqlite3_mprintf("SELECT COUNT(*) FROM noti_list %s", query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW) {
+ *count = sqlite3_column_int(stmt, 0);
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (query)
+ sqlite3_free(query);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_insert(notification_h noti)
+{
+ int ret = 0;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid notification handle");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (_is_allowed_to_notify(noti) == false) {
+ ERR("[%s] is not allowed to notify", noti->caller_app_id);
+ return NOTIFICATION_ERROR_PERMISSION_DENIED;
+ }
+
+ if (_handle_do_not_disturb_option(noti) != NOTIFICATION_ERROR_NONE)
+ WARN("Failed to handle do_not_disturb");
+
+ if (_is_pop_up_notification((const char *)noti->caller_app_id, noti->uid) == false) {
+ noti->display_applist = (noti->display_applist & (~NOTIFICATION_DISPLAY_APP_ACTIVE));
+ DBG("notification display applist - app_id [%s], applist [%d]",
+ noti->caller_app_id, noti->display_applist);
+ }
+
+ if (_check_text_input(noti) != NOTIFICATION_ERROR_NONE)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ /* Initialize private ID */
+ noti->group_id = NOTIFICATION_GROUP_ID_NONE;
+ noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("INSERT INTO noti_list (%s) VALUES (%s)",
+ NOTI_LIST_DB_ATTRIBUTES_INSERT, NOTI_LIST_INSERT_VALUES);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _create_insertion_query(db, noti, stmt, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE) {
+ noti->priv_id = (int)sqlite3_last_insert_rowid(db);
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_noti_get_by_priv_id(notification_h noti, int priv_id)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *query_where = NULL;
+
+ if (priv_id < 0 || noti == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ query_where = sqlite3_mprintf("noti_list WHERE priv_id = %d", priv_id);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _get_notification(query_where, noti);
+
+err:
+ if (query_where)
+ sqlite3_free(query_where);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_noti_get_by_tag(notification_h noti, char *app_id, char *tag, uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *query_where;
+
+ if (tag == NULL || noti == NULL) {
+ ERR("Invalid paramter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ query_where = sqlite3_mprintf("noti_list WHERE caller_app_id = %Q "
+ "AND tag = %Q AND uid = %d", app_id, tag, uid);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _get_notification(query_where, noti);
+
+err:
+ if (query_where)
+ sqlite3_free(query_where);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_update(notification_h noti)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (_is_allowed_to_notify(noti) == false) {
+ DBG("[%s] is not allowed to notify", noti->caller_app_id);
+ return NOTIFICATION_ERROR_PERMISSION_DENIED;
+ }
+
+ if (_handle_do_not_disturb_option(noti) != NOTIFICATION_ERROR_NONE)
+ WARN("Failed to handle do_not_disturb");
+
+ if (_is_pop_up_notification((const char *)noti->caller_app_id, noti->uid) == false) {
+ noti->display_applist = (noti->display_applist & (~NOTIFICATION_DISPLAY_APP_ACTIVE));
+ DBG("notification display applist - app_id [%s], applist [%d]",
+ noti->caller_app_id, noti->display_applist);
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ /* Check private ID is exist */
+ ret = _notification_noti_check_priv_id(noti, db);
+ if (ret != NOTIFICATION_ERROR_ALREADY_EXIST_ID) {
+ ERR("The ID is not existed");
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ goto err;
+ }
+
+ query = sqlite3_mprintf("UPDATE noti_list SET %s WHERE priv_id = %d ",
+ NOTI_LIST_DB_ATTRIBUTES_UPDATE, noti->priv_id);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _create_update_query(db, noti, stmt);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE)
+ ret = NOTIFICATION_ERROR_NONE;
+ else
+ ret = NOTIFICATION_ERROR_FROM_DB;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_delete_all(notification_type_e type,
+ const char *app_id, int *deleted_num,
+ int **deleted_list, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ char *query_where = NULL;
+ int *tmp = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int count = 0;
+ int i = 0;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ /* create query_where according to appid and type */
+ if (app_id == NULL || strlen(app_id) == 0) {
+ if (type == NOTIFICATION_TYPE_NONE)
+ query_where = sqlite3_mprintf("WHERE uid = %d", uid);
+ else
+ query_where = sqlite3_mprintf("WHERE type = %d "
+ "AND uid = %d", type, uid);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+ } else {
+ if (type == NOTIFICATION_TYPE_NONE)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND uid = %d", app_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND type = %d AND uid = %d",
+ app_id, type, uid);
+
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ /* check count to delete */
+ ret = _get_noti_count(db, query_where, &count);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get count to delete %d", ret);
+ goto err;
+ }
+
+ /* Get priv_id and add to list */
+ if (count > 0 && deleted_list != NULL) {
+ query = sqlite3_mprintf("SELECT priv_id FROM noti_list %s",
+ query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_V2 [%d][%s]",
+ ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ tmp = (int *)calloc(count, sizeof(int));
+ if (tmp == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ *(tmp + i) = sqlite3_column_int(stmt, 0);
+ i++;
+ }
+
+ sqlite3_free(query);
+ query = NULL;
+ }
+
+ /* execute main query */
+ query = sqlite3_mprintf("DELETE FROM noti_list %s", query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+ if (deleted_list)
+ *deleted_list = tmp;
+
+ if (deleted_num != NULL)
+ *deleted_num = count;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (query_where)
+ sqlite3_free(query_where);
+
+ if (db)
+ notification_db_close(&db);
+
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ if (tmp != NULL)
+ free(tmp);
+ }
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_noti_delete_by_priv_id(const char *app_id, int priv_id)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("DELETE FROM noti_list WHERE caller_app_id = %Q "
+ "AND priv_id = %d", app_id, priv_id);
+ if (query == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+
+err:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_noti_delete_by_priv_id_get_changes(const char *app_id,
+ int priv_id,
+ int *num_changes,
+ uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("DELETE FROM noti_list WHERE caller_app_id = %Q "
+ "AND priv_id = %d AND uid = %d",
+ app_id, priv_id, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, num_changes);
+
+err:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_delete_by_display_applist(int display_applist,
+ int *deleted_num,
+ notification_deleted_list_info_s **deleted_list,
+ uid_t uid)
+{
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ notification_deleted_list_info_s *info = NULL;
+ char *query = NULL;
+ char *query_where = NULL;
+ int count = 0;
+ int ret;
+ int i = 0;
+
+ if (display_applist < NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query_where = sqlite3_mprintf("WHERE (display_applist & %d) = %d "
+ "AND uid = %d", display_applist, display_applist,
+ uid);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* check count to delete */
+ ret = _get_noti_count(db, query_where, &count);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get count to delete %d", ret);
+ goto err;
+ }
+
+ /* get priv_id, app_id to add deleted_list */
+ if (count > 0 && deleted_list != NULL) {
+ query = sqlite3_mprintf("SELECT priv_id, caller_app_id "
+ "FROM noti_list %s", query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ info = (notification_deleted_list_info_s *)calloc(count,
+ sizeof(notification_deleted_list_info_s));
+ if (info == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ (info + i)->priv_id = sqlite3_column_int(stmt, 0);
+ (info + i)->app_id = notification_db_column_text(stmt, 1);
+ i++;
+ }
+
+ if (query) {
+ sqlite3_free(query);
+ query = NULL;
+ }
+ }
+
+ /* execute main query */
+ query = sqlite3_mprintf("DELETE FROM noti_list %s", query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+
+ if (deleted_num != NULL)
+ *deleted_num = count;
+
+ if (deleted_list != NULL)
+ *deleted_list = info;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (query_where)
+ sqlite3_free(query_where);
+ if (query)
+ sqlite3_free(query);
+ if (db)
+ notification_db_close(&db);
+
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ if (info != NULL)
+ __free_deleted_list(info, count);
+ }
+
+ return ret;
+}
+
+/* todo refactoring */
+/* LCOV_EXCL_START */
+EXPORT_API int notification_noti_get_count(notification_type_e type,
+ const char *app_id,
+ int group_id, int priv_id,
+ int *count, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ char *query_base = NULL;
+ char *query_where = NULL;
+ char *query_where_more = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int get_count = 0;
+ int internal_group_id = 0;
+ int status = VCONFKEY_TELEPHONY_SIM_UNKNOWN;
+
+ /* Check current sim status */
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
+ if (ret < 0) {
+ status = VCONFKEY_TELEPHONY_SIM_INSERTED;
+ WARN("vconf_get_int");
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query_base = sqlite3_mprintf("SELECT count(*) FROM noti_list ");
+ if (query_base == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ internal_group_id =
+ _notification_noti_get_internal_group_id_by_priv_id(app_id, priv_id, db);
+
+ if (group_id == NOTIFICATION_GROUP_ID_NONE) {
+ if (priv_id == NOTIFICATION_PRIV_ID_NONE)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND uid = %d ", app_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND internal_group_id = %d AND uid = %d ",
+ app_id, internal_group_id, uid);
+ } else {
+ if (priv_id == NOTIFICATION_PRIV_ID_NONE)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND group_id = %d AND uid = %d ",
+ app_id, group_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND internal_group_id = %d AND uid = %d ",
+ app_id, internal_group_id, uid);
+ }
+
+ if (query_where == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ if (status == VCONFKEY_TELEPHONY_SIM_INSERTED) {
+ if (type != NOTIFICATION_TYPE_NONE) {
+ query_where_more = sqlite3_mprintf("type = %d ", type);
+ if (query_where_more == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ }
+ } else {
+ if (type != NOTIFICATION_TYPE_NONE)
+ query_where_more = sqlite3_mprintf("type = %d AND "
+ "flag_simmode = 0 ", type);
+ else
+ query_where_more = sqlite3_mprintf("flag_simmode = 0 ");
+
+ if (query_where_more == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ }
+
+ if (query_where_more) {
+ query = sqlite3_mprintf("%s %s AND %s", query_base, query_where,
+ query_where_more);
+ if (query == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ } else {
+ query = sqlite3_mprintf("%s %s", query_base, query_where);
+ if (query == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ERR("Failed to sqlite3_prepare_v2[%d][%s]",
+ ret, sqlite3_errmsg(db));
+
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ get_count = sqlite3_column_int(stmt, 0);
+
+ ret = NOTIFICATION_ERROR_NONE;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (query_base)
+ sqlite3_free(query_base);
+
+ if (query_where)
+ sqlite3_free(query_where);
+
+ if (query_where_more)
+ sqlite3_free(query_where_more);
+
+ if (db)
+ notification_db_close(&db);
+
+ *count = get_count;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_noti_get_all_count(notification_type_e type, int *count, uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *sql_buf = NULL;
+
+ if (count == NULL) {
+ ERR("Invalid parameter - count is null");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (db == NULL) {
+ /* LCOV_EXCL_START */
+ ret = get_last_result();
+ ERR("Failed to open db [%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (type != NOTIFICATION_TYPE_NONE)
+ sql_buf = sqlite3_mprintf("SELECT count(*) FROM %q "
+ "WHERE uid = %d AND type = %d",
+ NOTIFICATION_DB_TABLE, uid, type);
+ else
+ sql_buf = sqlite3_mprintf("SELECT count(*) FROM %q WHERE uid = %d",
+ NOTIFICATION_DB_TABLE, uid);
+
+ if (sql_buf == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ ERR("OOM - sqlite3_mprintf");
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_prepare_v2(db, sql_buf, -1, &stmt, NULL);
+ if (sql_ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ ERR("SQLITE3 Error - sqlite3_prepare_v2 [%d][%s]",
+ sql_ret, sqlite3_errmsg(db));
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_step(stmt);
+ if (sql_ret == SQLITE_ROW)
+ *count = sqlite3_column_int(stmt, 0);
+ else
+ *count = 0;
+
+ INFO("The numbers of all notification is [%d]", *count);
+
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (sql_buf)
+ sqlite3_free(sql_buf);
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_get_grouping_list(notification_type_e type,
+ int page_number,
+ int count_per_page,
+ notification_list_h *list,
+ int *list_count,
+ uid_t uid)
+{
+ char *query = NULL;
+ char *query_uid = NULL;
+ 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);
+ if (ret < 0) {
+ status = VCONFKEY_TELEPHONY_SIM_INSERTED;
+ WARN("vconf_get_int");
+ }
+
+ if (status == VCONFKEY_TELEPHONY_SIM_INSERTED) {
+ if (type != NOTIFICATION_TYPE_NONE) {
+ query_where = sqlite3_mprintf(" AND type = %d ", type);
+ if (query_where == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ if (type != NOTIFICATION_TYPE_NONE)
+ query_where = sqlite3_mprintf(" AND type = %d AND "
+ "flag_simmode = 0 ", type);
+ else
+ query_where = sqlite3_mprintf(" AND flag_simmode = 0 ");
+
+ if (query_where == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (uid != NOTIFICATION_GLOBAL_UID) {
+ query_uid = sqlite3_mprintf(" AND uid = %d ", uid);
+ if (query_uid == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ 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;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _get_notification_list(query, list, list_count, count_per_page);
+
+err:
+ if (query_where)
+ sqlite3_free(query_where);
+
+ if (query_uid)
+ sqlite3_free(query_uid);
+
+ if (query)
+ sqlite3_free(query);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_get_detail_list(const char *app_id,
+ int group_id,
+ int priv_id, int count,
+ notification_list_h *list,
+ uid_t uid)
+{
+ char *query_where = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int internal_group_id = 0;
+ int status = 0;
+ sqlite3 *db = NULL;
+
+ /* Check current sim status */
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
+ if (ret < 0) {
+ status = VCONFKEY_TELEPHONY_SIM_INSERTED;
+ WARN("vconf_get_int");
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ if (priv_id == NOTIFICATION_PRIV_ID_NONE &&
+ group_id == NOTIFICATION_GROUP_ID_NONE) {
+ if (status == VCONFKEY_TELEPHONY_SIM_INSERTED)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND uid = %d ", app_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND flag_simmode = 0 AND uid = %d ", app_id, uid);
+
+ } else {
+ internal_group_id =
+ _notification_noti_get_internal_group_id_by_priv_id(app_id,
+ priv_id, db);
+
+ if (status == VCONFKEY_TELEPHONY_SIM_INSERTED)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND internal_group_id = %d AND uid = %d ",
+ app_id, internal_group_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND internal_group_id = %d AND flag_simmode = 0 "
+ "AND uid = %d ",
+ app_id, internal_group_id, uid);
+ }
+
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ query = sqlite3_mprintf("noti_list %s ORDER BY rowid DESC, time DESC",
+ query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _get_notification_list(query, list, NULL, count);
+
+err:
+ if (query_where)
+ sqlite3_free(query_where);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_check_tag(notification_h noti)
+{
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int result = 0;
+
+ if (noti->tag == NULL)
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT priv_id FROM noti_list "
+ "WHERE caller_app_id = %Q AND tag = %Q",
+ NOTIFICATION_CHECK_STR(noti->caller_app_id),
+ NOTIFICATION_CHECK_STR(noti->tag));
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_v2[%d][%s]",
+ ret, sqlite3_errmsg(db));
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+ /* If result > 0, there is priv_id in DB */
+ if (result > 0) {
+ noti->priv_id = result;
+ ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+ } else {
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_check_count_for_template(notification_h noti, int *count)
+{
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int result = 0;
+
+ if (noti == NULL || count == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT COUNT(caller_app_id) FROM noti_template "
+ "WHERE caller_app_id = %Q",
+ NOTIFICATION_CHECK_STR(noti->caller_app_id));
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_v2[%d][%s]",
+ ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+ *count = result;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_add_template(notification_h noti, char *template_name)
+{
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int idx = 1;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (noti == NULL || template_name == NULL) {
+ ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ /* Initialize private ID */
+ noti->group_id = NOTIFICATION_GROUP_ID_NONE;
+ noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("INSERT OR REPLACE INTO noti_template "
+ "(%s, template_name) VALUES (%s, %Q)",
+ NOTI_LIST_DB_ATTRIBUTES_INSERT,
+ NOTI_LIST_INSERT_VALUES,
+ template_name);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_v2[%d][%s]",
+ ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _create_insertion_query(db, noti, stmt, &idx);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE)
+ ret = NOTIFICATION_ERROR_NONE;
+ else
+ ret = NOTIFICATION_ERROR_FROM_DB;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_get_package_template(notification_h noti, char *app_id, char *template_name)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *query_where = NULL;
+
+ if (noti == NULL || app_id == NULL || template_name == NULL) {
+ ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ query_where = sqlite3_mprintf("noti_template WHERE caller_app_id = %Q "
+ "AND template_name = %Q", app_id, template_name);
+ if (query_where == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ ret = _get_notification(query_where, noti);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ ERR("Failed to get notification [%d]", ret);
+
+ if (query_where)
+ sqlite3_free(query_where);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_delete_template(const char *pkg_id)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (pkg_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("DELETE FROM noti_template WHERE pkg_id = %Q",
+ NOTIFICATION_CHECK_STR(pkg_id));
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+
+err:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API void notification_noti_init_data(void)
+{
+ int ret;
+ sqlite3 *db = NULL;
+ char *query = NULL;
+
+ db = notification_db_open();
+ if (!db) {
+ ERR("db open");
+ return;
+ }
+
+ query = sqlite3_mprintf("DELETE FROM noti_list WHERE type = %d OR flags_for_property & %d",
+ NOTIFICATION_TYPE_ONGOING, NOTIFICATION_PROP_VOLATILE_DISPLAY);
+ if (!query) {
+ ERR("OOM - sql query");
+ notification_db_close(&db);
+ return;
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ ERR("notification_db_exec");
+
+ sqlite3_free(query);
+ notification_db_close(&db);
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_noti_check_limit(notification_h noti, uid_t uid, GList **list)
+{
+ int ret;
+ int priv_id;
+ int count = 0;
+ char *query = NULL;
+ char *query_where = NULL;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q AND uid = %d ",
+ noti->caller_app_id, uid);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* check count to delete */
+ ret = _get_noti_count(db, query_where, &count);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get count to delete %d", ret);
+ goto err;
+ }
+
+ /* get priv_id to delete */
+ if (count > NOTI_LIMIT) {
+ count -= NOTI_LIMIT;
+
+ query = sqlite3_mprintf("SELECT priv_id FROM noti_list %s "
+ "AND type = %d ORDER BY insert_time ASC, priv_id ASC",
+ query_where, NOTIFICATION_TYPE_NOTI);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW && count > 0) {
+ priv_id = sqlite3_column_int(stmt, 0);
+ *list = g_list_append(*list, GINT_TO_POINTER(priv_id));
+ count--;
+ }
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (query)
+ sqlite3_free(query);
+ if (query_where)
+ sqlite3_free(query_where);
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
diff --git a/notification/src/notification_ongoing.c b/notification/src/notification_ongoing.c
new file mode 100644
index 0000000..89ee0c9
--- /dev/null
+++ b/notification/src/notification_ongoing.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2000 - 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <notification_db.h>
+#include <notification_debug.h>
+#include <notification_ongoing.h>
+#include <notification_private.h>
+
+#define PATH_NAME "/dbus/signal"
+#define INTERFACE_NAME "notification.ongoing"
+#define MEMBER_PROGRESS "update_progress"
+#define MEMBER_SIZE "update_size"
+#define MEMBER_CONTENT "update_content"
+
+struct _ongoing_update_cb_data {
+ notification_ongoing_update_cb callback;
+ void *data;
+ GDBusConnection *conn;
+ guint subscribe_id;
+};
+
+static struct _ongoing_update_cb_data od;
+
+static void __notification_ongoing_update_callback(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ struct ongoing_info_s *info;
+ char *app_id = NULL;
+ int priv_id = 0;
+ double progress = 0;
+ double size = 0;
+ char *content = NULL;
+
+ info = calloc(1, sizeof(struct ongoing_info_s));
+ if (info == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_strcmp0(signal_name, MEMBER_PROGRESS) == 0) {
+ g_variant_get(parameters, "(&sid)", &app_id, &priv_id, &progress);
+ info->type = ONGOING_TYPE_PROGRESS;
+ } else if (g_strcmp0(signal_name, MEMBER_SIZE) == 0) {
+ g_variant_get(parameters, "(&sid)", &app_id, &priv_id, &size);
+ info->type = ONGOING_TYPE_SIZE;
+ } else if (g_strcmp0(signal_name, MEMBER_CONTENT) == 0) {
+ g_variant_get(parameters, "(&si&s)", &app_id, &priv_id, &content);
+ info->type = ONGOING_TYPE_CONTENT;
+ }
+
+ if (app_id == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("app_id is NULL");
+ free(info);
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ info->pkgname = app_id;
+ info->priv_id = priv_id;
+ info->progress = progress;
+ info->size = size;
+ info->content = content;
+
+ od.callback(info, od.data);
+
+ free(info);
+}
+
+static int __send_ongoing_update_signal(const char *signal_name, GVariant *param)
+{
+ GError *err = NULL;
+ GDBusConnection *conn;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (signal_name == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (conn == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to connect to the D-BUS Daemon[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_dbus_connection_emit_signal(conn,
+ NULL,
+ PATH_NAME,
+ INTERFACE_NAME,
+ signal_name,
+ param,
+ &err) == FALSE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to emit gdbus signal[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to flush connection sync[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+
+end:
+ if (err)
+ g_error_free(err);
+
+ if (conn)
+ g_object_unref(conn);
+
+
+ return ret;
+}
+
+EXPORT_API
+int notification_ongoing_update_cb_set(notification_ongoing_update_cb callback,
+ void *user_data)
+{
+ GError *error = NULL;
+
+ if (!callback)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (od.conn == NULL) {
+ od.conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (od.conn == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to connect to the D-BUS Daemon: %s",
+ error->message);
+ g_error_free(error);
+ return NOTIFICATION_ERROR_FROM_DBUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ if (!od.subscribe_id) {
+ od.subscribe_id = g_dbus_connection_signal_subscribe(od.conn,
+ NULL,
+ INTERFACE_NAME,
+ NULL,
+ PATH_NAME,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ __notification_ongoing_update_callback,
+ NULL,
+ NULL);
+ if (od.subscribe_id == 0) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to subscribe signal");
+ g_object_unref(od.conn);
+ return NOTIFICATION_ERROR_FROM_DBUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ od.callback = callback;
+ od.data = user_data;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API
+int notification_ongoing_update_cb_unset(void)
+{
+ if (od.subscribe_id) {
+ g_dbus_connection_signal_unsubscribe(od.conn, od.subscribe_id);
+ od.subscribe_id = 0;
+ }
+
+ if (od.conn) {
+ g_object_unref(od.conn);
+ od.conn = NULL;
+ }
+
+ od.callback = NULL;
+ od.data = NULL;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ongoing_update_progress(const char *caller_app_id,
+ int priv_id, double progress)
+{
+ GVariant *param;
+ int ret;
+
+ param = g_variant_new("(sid)", caller_app_id, priv_id, progress);
+
+ ret = __send_ongoing_update_signal(MEMBER_PROGRESS, param);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to update progress[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ongoing_update_size(const char *caller_app_id,
+ int priv_id, double size)
+{
+ GVariant *param;
+ int ret;
+
+ param = g_variant_new("(sid)", caller_app_id, priv_id, size);
+
+ ret = __send_ongoing_update_signal(MEMBER_SIZE, param);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to update size[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ongoing_update_content(const char *caller_app_id,
+ int priv_id, const char *content)
+{
+ GVariant *param;
+ int ret;
+
+ param = g_variant_new("(sis)", caller_app_id, priv_id, content);
+
+ ret = __send_ongoing_update_signal(MEMBER_CONTENT, param);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to update content[%d]",
+ ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+ return NOTIFICATION_ERROR_NONE;
+}
diff --git a/notification/src/notification_setting.c b/notification/src/notification_setting.c
new file mode 100644
index 0000000..6be851f
--- /dev/null
+++ b/notification/src/notification_setting.c
@@ -0,0 +1,1125 @@
+/*
+ * Copyright (c) 2000 - 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <package_manager.h>
+#include <pkgmgr-info.h>
+#include <tizen_type.h>
+#include <tzplatform_config.h>
+
+#include <notification.h>
+#include <notification_db.h>
+#include <notification_list.h>
+#include <notification_noti.h>
+#include <notification_debug.h>
+#include <notification_ipc.h>
+#include <notification_private.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include "notification_db_query.h"
+
+#define NOTIFICATION_PRIVILEGE "http://tizen.org/privilege/notification"
+
+typedef struct _noti_dnd_cb_info noti_dnd_cb_info_s;
+
+typedef struct {
+ uid_t uid;
+ sqlite3 *db;
+} setting_local_info;
+
+struct _noti_dnd_cb_info {
+ dnd_changed_cb callback;
+ void *user_data;
+};
+
+static GHashTable *_noti_dnd_cb_hash = NULL;
+
+EXPORT_API int notification_setting_get_setting_array_for_uid(notification_setting_h *setting_array, int *count, uid_t uid)
+{
+ if (setting_array == NULL || count == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_request_get_setting_array(setting_array, count, uid);
+}
+
+EXPORT_API int notification_setting_get_setting_array(notification_setting_h *setting_array, int *count)
+{
+ return notification_setting_get_setting_array_for_uid(setting_array, count, getuid());
+}
+
+EXPORT_API int notification_setting_get_setting_by_appid_for_uid(const char *app_id, notification_setting_h *setting, uid_t uid)
+{
+ if (app_id == NULL || setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_request_get_setting_by_app_id(app_id, setting, uid);
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_setting_get_setting_by_package_name(const char *package_name, notification_setting_h *setting)
+{
+ return notification_setting_get_setting_by_appid_for_uid(package_name, setting, getuid());
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_setting_get_setting(notification_setting_h *setting)
+{
+ int ret;
+ char *app_id = NULL;
+
+ app_id = notification_get_app_id_by_pid(getpid());
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+ ret = notification_setting_get_setting_by_package_name(app_id, setting);
+
+ free(app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_setting_get_package_name(notification_setting_h setting, char **value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (setting->package_name == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("setting->package_name is null");
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *value = SAFE_STRDUP(setting->package_name);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_appid(notification_setting_h setting, char **app_id)
+{
+ if (setting == NULL || app_id == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (setting->app_id == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("setting->app_id is null");
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *app_id = SAFE_STRDUP(setting->app_id);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_allow_to_notify(notification_setting_h setting, bool *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->allow_to_notify;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_allow_to_notify(notification_setting_h setting, bool value)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->allow_to_notify = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_do_not_disturb_except(notification_setting_h setting, bool *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->do_not_disturb_except;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_do_not_disturb_except(notification_setting_h setting, bool value)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->do_not_disturb_except = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_visibility_class(notification_setting_h setting, int *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->visibility_class;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_visibility_class(notification_setting_h setting, int value)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->visibility_class = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_pop_up_notification(notification_setting_h setting, bool *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->pop_up_notification;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_pop_up_notification(notification_setting_h setting, bool value)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->pop_up_notification = value;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_lock_screen_content(notification_setting_h setting, lock_screen_content_level_e *level)
+{
+ if (setting == NULL || level == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *level = setting->lock_screen_content_level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_lock_screen_content(notification_setting_h setting, lock_screen_content_level_e level)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->lock_screen_content_level = level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_app_disabled(notification_setting_h setting, bool *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->app_disabled;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_update_setting_for_uid(notification_setting_h setting, uid_t uid)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_update_setting(setting, uid);
+}
+
+EXPORT_API int notification_setting_update_setting(notification_setting_h setting)
+{
+ return notification_setting_update_setting_for_uid(setting, getuid());
+}
+
+EXPORT_API int notification_setting_free_notification(notification_setting_h setting)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ SAFE_FREE(setting->package_name);
+ SAFE_FREE(setting->app_id);
+
+ /* add codes to free all properties */
+
+ SAFE_FREE(setting);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static bool _is_package_in_setting_table(sqlite3 *db, const char *package_name,
+ const char *app_id, uid_t uid)
+{
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int sql_ret;
+ bool err = true;
+
+ if (app_id != NULL)
+ query = sqlite3_mprintf("SELECT app_id FROM %s WHERE uid = %d "
+ "AND package_name = %Q AND app_id = %Q",
+ NOTIFICATION_SETTING_DB_TABLE,
+ uid, package_name, app_id);
+ else
+ query = sqlite3_mprintf("SELECT package_name FROM %s "
+ "WHERE uid = %d AND package_name = %Q",
+ NOTIFICATION_SETTING_DB_TABLE,
+ uid, package_name);
+
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("fail to alloc query");
+ return false;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (sql_ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 failed [%d][%s]", sql_ret,
+ sqlite3_errmsg(db));
+ err = false;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_step(stmt);
+ if (sql_ret == SQLITE_DONE) {
+ INFO("No matched [%s] from package_name [%s], [%d]",
+ app_id, package_name, sql_ret);
+ err = false;
+ goto out;
+ }
+
+ if (sql_ret != SQLITE_OK && sql_ret != SQLITE_ROW) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_step failed [%d][%s]", sql_ret,
+ sqlite3_errmsg(db));
+ err = false;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ return err;
+}
+
+static int _foreach_app_info_callback(const pkgmgrinfo_appinfo_h handle,
+ void *user_data)
+{
+ setting_local_info *info = (setting_local_info *)user_data;
+ sqlite3 *db = info->db;
+ char *query = NULL;
+ int ret;
+ int err = true;
+ char *app_id = NULL;
+ char *package_name = NULL;
+
+ ret = pkgmgrinfo_appinfo_get_appid(handle, &app_id);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get appid from pkgmgrinfo [%d]",
+ ret);
+ err = false;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = pkgmgrinfo_appinfo_get_pkgname(handle, &package_name);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get pkgname from pkgmgrinfo[%d]",
+ ret);
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (_is_package_in_setting_table(db, package_name, app_id, info->uid) == true) {
+ INFO("uid %d [%s] is exist", info->uid, app_id);
+ err = false;
+ goto out;
+ }
+
+ query = sqlite3_mprintf("INSERT INTO %s (uid, package_name, app_id) "
+ "VALUES (%d, %Q, %Q) ",
+ NOTIFICATION_SETTING_DB_TABLE,
+ info->uid, package_name, app_id);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("fail to alloc query");
+ err = false;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ err = false;
+ else
+ INFO("uid [%d] package_name [%s] appid [%s] is inserted",
+ info->uid, package_name, app_id);
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ return err;
+}
+
+static int _install_and_update_package(const char *package_name, uid_t uid)
+{
+ sqlite3 *db;
+ int err = NOTIFICATION_ERROR_NONE;
+ int pkgmgr_ret;
+ setting_local_info info;
+ pkgmgrinfo_appinfo_filter_h handle = NULL;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_create(&handle);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_add_string(handle,
+ PMINFO_APPINFO_PROP_PRIVILEGE, NOTIFICATION_PRIVILEGE);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to add string to appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_add_string(handle,
+ PMINFO_APPINFO_PROP_APP_PACKAGE, package_name);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to add string to appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ info.db = db;
+ info.uid = uid;
+ pkgmgr_ret = pkgmgrinfo_appinfo_usr_filter_foreach_appinfo(handle,
+ _foreach_app_info_callback, &info, uid);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to iterate appinfo[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+out:
+ if (handle)
+ pkgmgrinfo_appinfo_filter_destroy(handle);
+
+ if (db)
+ notification_db_close(&db);
+
+ return err;
+}
+
+static int _delete_package_from_setting_db(const char *package_name, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int err = NOTIFICATION_ERROR_NONE;
+ bool is_package_in_setting_table = false;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ is_package_in_setting_table = _is_package_in_setting_table(db,
+ package_name, NULL, uid);
+ if (is_package_in_setting_table == false) {
+ INFO("[%s] is not exist", package_name);
+ goto out;
+ }
+
+ query = sqlite3_mprintf("DELETE FROM %s WHERE uid = %d "
+ "AND package_name = %Q ",
+ NOTIFICATION_SETTING_DB_TABLE, uid,
+ package_name);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query");
+ err = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = notification_db_exec(db, query, NULL);
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return err;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_setting_refresh_setting_table(uid_t uid)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ sqlite3 *db = NULL;
+ int pkgmgr_ret;
+ pkgmgrinfo_appinfo_filter_h filter = NULL;
+ setting_local_info info;
+
+ INFO("Refresh setting table [%d]", uid);
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_create(&filter);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ ERR("Failed to create appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_add_string(filter,
+ PMINFO_APPINFO_PROP_PRIVILEGE, NOTIFICATION_PRIVILEGE);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ ERR("Failed to add string to appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ info.db = db;
+ info.uid = uid;
+ pkgmgr_ret = pkgmgrinfo_appinfo_usr_filter_foreach_appinfo(filter,
+ _foreach_app_info_callback, &info, uid);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ ERR("Failed to foreach appinfo[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+out:
+ if (filter)
+ pkgmgrinfo_appinfo_filter_destroy(filter);
+
+ if (db)
+ notification_db_close(&db);
+
+ return err;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_setting_insert_package_for_uid(const char *package_name, uid_t uid)
+{
+ return _install_and_update_package(package_name, uid);
+}
+
+EXPORT_API int notification_setting_delete_package_for_uid(const char *package_name, uid_t uid)
+{
+ return _delete_package_from_setting_db(package_name, uid);
+}
+
+EXPORT_API int notification_system_setting_load_system_setting_for_uid(notification_system_setting_h *system_setting, uid_t uid)
+{
+ if (system_setting == NULL) {
+ ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_request_load_system_setting(system_setting, uid);
+}
+
+EXPORT_API int notification_system_setting_load_system_setting(notification_system_setting_h *system_setting)
+{
+ return notification_system_setting_load_system_setting_for_uid(system_setting, getuid());
+}
+
+EXPORT_API int notification_system_setting_update_system_setting_for_uid(notification_system_setting_h system_setting, uid_t uid)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_update_system_setting(system_setting, uid);
+}
+
+EXPORT_API int notification_system_setting_update_system_setting(notification_system_setting_h system_setting)
+{
+ return notification_system_setting_update_system_setting_for_uid(system_setting, getuid());
+}
+
+EXPORT_API int notification_system_setting_free_system_setting(notification_system_setting_h system_setting)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ /* add codes to free all properties */
+
+ if (system_setting->dnd_allow_exceptions != NULL)
+ g_list_free_full(system_setting->dnd_allow_exceptions, free);
+
+ SAFE_FREE(system_setting);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_get_do_not_disturb(notification_system_setting_h system_setting, bool *value)
+{
+ if (system_setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = system_setting->do_not_disturb;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_set_do_not_disturb(notification_system_setting_h system_setting, bool value)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->do_not_disturb = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_get_visibility_class(notification_system_setting_h system_setting, int *value)
+{
+ if (system_setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = system_setting->visibility_class;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_set_visibility_class(notification_system_setting_h system_setting, int value)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->visibility_class = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_get_enabled(notification_system_setting_h system_setting, bool *enabled)
+{
+ if (system_setting == NULL || enabled == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *enabled = system_setting->dnd_schedule_enabled;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_set_enabled(notification_system_setting_h system_setting, bool enabled)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->dnd_schedule_enabled = enabled;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_get_day(notification_system_setting_h system_setting, int *day)
+{
+ if (system_setting == NULL || day == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *day = system_setting->dnd_schedule_day;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_set_day(notification_system_setting_h system_setting, int day)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->dnd_schedule_day = day;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_get_start_time(notification_system_setting_h system_setting, int *hour, int *min)
+{
+ if (system_setting == NULL || hour == NULL || min == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *hour = system_setting->dnd_start_hour;
+ *min = system_setting->dnd_start_min;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_set_start_time(notification_system_setting_h system_setting, int hour, int min)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->dnd_start_hour = hour;
+ system_setting->dnd_start_min = min;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_get_end_time(notification_system_setting_h system_setting, int *hour, int *min)
+{
+ if (system_setting == NULL || hour == NULL || min == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *hour = system_setting->dnd_end_hour;
+ *min = system_setting->dnd_end_min;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_set_end_time(notification_system_setting_h system_setting, int hour, int min)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->dnd_end_hour = hour;
+ system_setting->dnd_end_min = min;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_get_lock_screen_content(notification_system_setting_h system_setting, lock_screen_content_level_e *level)
+{
+ if (system_setting == NULL || level == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *level = system_setting->lock_screen_content_level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_set_lock_screen_content(notification_system_setting_h system_setting, lock_screen_content_level_e level)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->lock_screen_content_level = level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static gint _dnd_allow_exception_compare(gconstpointer a, gconstpointer b)
+{
+ dnd_allow_exception_h dnd_allow_exception_data_a;
+
+ if (a == NULL)
+ return -1;
+
+ dnd_allow_exception_data_a = (dnd_allow_exception_h)a;
+
+ if (dnd_allow_exception_data_a->type == GPOINTER_TO_INT(b))
+ return 0;
+
+ return -1;
+}
+
+EXPORT_API int notification_system_setting_get_dnd_allow_exceptions(notification_system_setting_h system_setting, dnd_allow_exception_type_e type, int *value)
+{
+ dnd_allow_exception_h dnd_allow_exception_data;
+ GList *list;
+
+ if (system_setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ list = g_list_find_custom(system_setting->dnd_allow_exceptions, GINT_TO_POINTER(type), (GCompareFunc)_dnd_allow_exception_compare);
+ if (list) {
+ dnd_allow_exception_data = (dnd_allow_exception_h)list->data;
+ *value = dnd_allow_exception_data->value;
+ } else {
+ ERR("Invalid type");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_set_dnd_allow_exceptions(notification_system_setting_h system_setting, dnd_allow_exception_type_e type, int value)
+{
+ dnd_allow_exception_h dnd_allow_exception_data;
+ GList *list = NULL;
+
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ list = g_list_first(system_setting->dnd_allow_exceptions);
+ list = g_list_find_custom(list, GINT_TO_POINTER(type), (GCompareFunc)_dnd_allow_exception_compare);
+
+ if (list) {
+ dnd_allow_exception_data = (dnd_allow_exception_h)list->data;
+ dnd_allow_exception_data->value = value;
+ } else {
+ dnd_allow_exception_data = (dnd_allow_exception_h)malloc(sizeof(struct notification_system_setting_dnd_allow_exception));
+ if (dnd_allow_exception_data == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ dnd_allow_exception_data->type = type;
+ dnd_allow_exception_data->value = value;
+ system_setting->dnd_allow_exceptions = g_list_append(list, dnd_allow_exception_data);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static gint _noti_dnd_cb_compare(gconstpointer a, gconstpointer b)
+{
+ noti_dnd_cb_info_s *info = NULL;
+
+ if (a == NULL)
+ return -1;
+
+ info = (noti_dnd_cb_info_s *)a;
+ if (info->callback == b)
+ return 0;
+
+ return 1;
+}
+
+/* LCOV_EXCL_START */
+void notification_call_dnd_changed_cb_for_uid(int do_not_disturb, uid_t uid)
+{
+ GList *noti_dnd_cb_list = NULL;
+ noti_dnd_cb_info_s *dnd_data = NULL;
+
+ if (_noti_dnd_cb_hash == NULL)
+ return;
+
+ noti_dnd_cb_list = (GList *)g_hash_table_lookup(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid));
+ if (noti_dnd_cb_list == NULL) {
+ ERR("Invalid data");
+ return;
+ }
+
+ noti_dnd_cb_list = g_list_first(noti_dnd_cb_list);
+
+ for (; noti_dnd_cb_list != NULL; noti_dnd_cb_list = noti_dnd_cb_list->next) {
+ dnd_data = noti_dnd_cb_list->data;
+
+ if (dnd_data != NULL && dnd_data->callback != NULL)
+ dnd_data->callback(dnd_data->user_data, do_not_disturb);
+ }
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_register_system_setting_dnd_changed_cb_for_uid(dnd_changed_cb callback, void *user_data, uid_t uid)
+{
+ GList *noti_dnd_list = NULL;
+ GList *noti_dnd_found_list = NULL;
+ noti_dnd_cb_info_s *dnd_data = NULL;
+
+ if (callback == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init monitor");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (_noti_dnd_cb_hash == NULL)
+ _noti_dnd_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ dnd_data = (noti_dnd_cb_info_s *)malloc(sizeof(noti_dnd_cb_info_s));
+ if (dnd_data == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ dnd_data->callback = callback;
+ dnd_data->user_data = user_data;
+
+ noti_dnd_list = (GList *)g_hash_table_lookup(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_dnd_list == NULL) {
+ noti_dnd_list = g_list_append(noti_dnd_list, dnd_data);
+ g_hash_table_insert(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid), noti_dnd_list);
+ } else {
+ noti_dnd_found_list = g_list_find_custom(noti_dnd_list, (gconstpointer)callback,
+ (GCompareFunc)_noti_dnd_cb_compare);
+ if (noti_dnd_found_list) {
+ ERR("Already existing callback");
+ free(dnd_data);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ noti_dnd_list = g_list_append(noti_dnd_list, dnd_data);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_register_system_setting_dnd_changed_cb(dnd_changed_cb callback, void *user_data)
+{
+ return notification_register_system_setting_dnd_changed_cb_for_uid(callback, user_data, getuid());
+}
+
+EXPORT_API int notification_unregister_system_setting_dnd_changed_cb_for_uid(dnd_changed_cb callback, uid_t uid)
+{
+ GList *noti_dnd_cb_list = NULL;
+ GList *noti_dnd_del_list = NULL;
+ noti_dnd_cb_info_s *dnd_data = NULL;
+
+ if (callback == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_dnd_cb_hash == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_dnd_cb_list = (GList *)g_hash_table_lookup(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_dnd_cb_list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_dnd_del_list = g_list_find_custom(noti_dnd_cb_list, (gconstpointer)callback,
+ (GCompareFunc)_noti_dnd_cb_compare);
+
+ if (noti_dnd_del_list) {
+ dnd_data = g_list_nth_data(noti_dnd_del_list, 0);
+ noti_dnd_cb_list = g_list_delete_link(noti_dnd_cb_list, noti_dnd_del_list);
+ free(dnd_data);
+ } else {
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (noti_dnd_cb_list == NULL) {
+ g_hash_table_steal(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid));
+ } else {
+ noti_dnd_cb_list = g_list_first(noti_dnd_cb_list);
+ g_hash_table_replace(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid), noti_dnd_cb_list);
+ }
+
+ if (g_hash_table_size(_noti_dnd_cb_hash) == 0)
+ notification_ipc_monitor_fini();
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_unregister_system_setting_dnd_changed_cb(dnd_changed_cb callback)
+{
+ return notification_unregister_system_setting_dnd_changed_cb_for_uid(callback, getuid());
+}
+
+/* LCOV_EXCL_START */
+static bool _is_uid_in_system_setting_table(sqlite3 *db, uid_t uid)
+{
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int sql_ret;
+ bool err = true;
+
+ query = sqlite3_mprintf("SELECT uid FROM %s WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE, uid);
+ if (query == NULL) {
+ ERR("Failed to alloc query");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ sql_ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (sql_ret != SQLITE_OK) {
+ ERR("sqlite3_prepare_v2 failed [%d][%s]", sql_ret,
+ sqlite3_errmsg(db));
+ err = false;
+ goto out;
+ }
+
+ sql_ret = sqlite3_step(stmt);
+ if (sql_ret == SQLITE_DONE) {
+ INFO("No matched uid[%d] err[%d]", uid, sql_ret);
+ err = false;
+ goto out;
+ }
+
+ if (sql_ret != SQLITE_OK && sql_ret != SQLITE_ROW) {
+ ERR("sqlite3_step failed [%d][%s]",
+ sql_ret, sqlite3_errmsg(db));
+ err = false;
+ }
+
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ return err;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_system_setting_init_system_setting_table(uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query_system_setting = NULL;
+ char *query_dnd_allow_exception = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ INFO("init system setting table [%d]", uid);
+
+ db = notification_db_open();
+ if (db == NULL)
+ return get_last_result();
+
+ if (_is_uid_in_system_setting_table(db, uid) == true) {
+ INFO("Setting table is already initialized.");
+ goto out;
+ }
+
+ /* notification_system_setting */
+ query_system_setting = sqlite3_mprintf("INSERT INTO %s (uid) "
+ "VALUES (%d) ",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE,
+ uid);
+ if (query_system_setting == NULL) {
+ ERR("fail to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query_system_setting, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ /* dnd_allow_exception */
+ query_dnd_allow_exception = sqlite3_mprintf("INSERT INTO %s "
+ "(uid) VALUES (%d) ",
+ NOTIFICATION_DND_ALLOW_EXCEPTION,
+ uid);
+ if (query_dnd_allow_exception == NULL) {
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query_dnd_allow_exception, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ DBG("Initialization is success.");
+
+out:
+ if (query_system_setting)
+ sqlite3_free(query_system_setting);
+
+ if (query_dnd_allow_exception)
+ sqlite3_free(query_dnd_allow_exception);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/src/notification_setting_service.c b/notification/src/notification_setting_service.c
new file mode 100644
index 0000000..7faee55
--- /dev/null
+++ b/notification/src/notification_setting_service.c
@@ -0,0 +1,931 @@
+/*
+ * Copyright (c) 2000 - 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 <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sqlite3.h>
+#include <tizen.h>
+
+#include <notification.h>
+#include <notification_db.h>
+#include <notification_error.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include <notification_setting_service.h>
+#include "notification_db_query.h"
+
+static int _get_table_field_data_int(char **table, int *buf, int index)
+{
+ if (table == NULL || buf == NULL || index < 0) {
+ /* LCOV_EXCL_START */
+ ERR("table[%p], buf[%p], index[%d]", table, buf, index);
+ return false;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (table[index] != NULL) {
+ *buf = atoi(table[index]);
+ return true;
+ }
+
+ /* LCOV_EXCL_START */
+ *buf = 0;
+ return false;
+ /* LCOV_EXCL_STOP */
+}
+
+static int _get_table_field_data_string(char **table, char **buf, int ucs2, int index)
+{
+ int ret = false;
+ int sLen = 0;
+ char *pTemp;
+
+ if (table == NULL || buf == NULL || index < 0) {
+ /* LCOV_EXCL_START */
+ ERR("table[%p], buf[%p], index[%d]", table, buf, index);
+ return false;
+ /* LCOV_EXCL_STOP */
+ }
+
+ pTemp = table[index];
+
+ if (pTemp == NULL) {
+ *buf = NULL; /* LCOV_EXCL_LINE */
+ } else {
+ sLen = strlen(pTemp);
+ if (sLen) {
+ *buf = (char *)malloc(sLen + 1);
+ if (*buf == NULL) {
+ ERR("Failed to alloc memory"); /* LCOV_EXCL_LINE */
+ goto out;
+ }
+ memset(*buf, 0, sLen + 1);
+ strncpy(*buf, pTemp, sLen);
+ } else {
+ *buf = NULL; /* LCOV_EXCL_LINE */
+ }
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+EXPORT_API
+int noti_setting_service_get_setting_by_app_id(const char *app_id, notification_setting_h *setting, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ char **query_result = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count = 0;
+ int column_count = 0;
+ int i = 0;
+ int col_index = 0;
+ notification_setting_h result_setting_array = NULL;
+
+ if (app_id == NULL || setting == NULL) {
+ ERR("Invalid parameter"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s WHERE app_id = %Q AND uid = %d",
+ NOTIFICATION_SETTING_DB_ATTRIBUTES, NOTIFICATION_SETTING_DB_TABLE,
+ app_id, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_get_table failed [%d][%s]", sql_ret,
+ query);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!row_count) {
+ DBG("No setting found for [%s]", app_id);
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ goto out;
+ }
+
+ DBG("row_count[%d] column_count[%d]", row_count, column_count);
+
+ row_count = 1;
+
+ result_setting_array = (struct notification_setting *)malloc(sizeof(struct notification_setting) * row_count);
+ if (result_setting_array == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ col_index = column_count;
+
+ _get_table_field_data_string(query_result, &(result_setting_array[i].package_name), 1, col_index++);
+ _get_table_field_data_string(query_result, &(result_setting_array[i].app_id), 1, col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].allow_to_notify), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].do_not_disturb_except), col_index++);
+ _get_table_field_data_int(query_result, &(result_setting_array[i].visibility_class), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].pop_up_notification), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].lock_screen_content_level), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].app_disabled), col_index++);
+
+ *setting = result_setting_array;
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int noti_setting_get_setting_array(notification_setting_h *setting_array, int *count, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ char **query_result = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count = 0;
+ int column_count = 0;
+ int i = 0;
+ int col_index = 0;
+ notification_setting_h result_setting_array = NULL;
+
+ if (setting_array == NULL || count == NULL) {
+ ERR("NOTIFICATION_ERROR_INVALID_PARAMETER"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s WHERE uid = %d "
+ "AND app_disabled = %d ORDER BY package_name, "
+ "app_id ", NOTIFICATION_SETTING_DB_ATTRIBUTES,
+ NOTIFICATION_SETTING_DB_TABLE, uid, 0);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get db table [%d][%s]",
+ sql_ret, query); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!row_count) {
+ DBG("No setting found"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ goto out;
+ }
+
+ DBG("row_count[%d] column_count[%d]", row_count, column_count);
+
+ result_setting_array = (struct notification_setting *)malloc(sizeof(struct notification_setting) * row_count);
+ if (result_setting_array == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ col_index = column_count;
+
+ for (i = 0; i < row_count; i++) {
+ _get_table_field_data_string(query_result, &(result_setting_array[i].package_name), 1, col_index++);
+ _get_table_field_data_string(query_result, &(result_setting_array[i].app_id), 1, col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].allow_to_notify), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].do_not_disturb_except), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].visibility_class), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].pop_up_notification), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].lock_screen_content_level), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].app_disabled), col_index++);
+ }
+
+ *setting_array = result_setting_array;
+ *count = row_count;
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+
+EXPORT_API
+int noti_system_setting_load_system_setting(notification_system_setting_h *system_setting, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ char **query_result = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count = 0;
+ int column_count = 0;
+ int col_index = 0;
+ notification_system_setting_h result_system_setting = NULL;
+
+ if (system_setting == NULL) {
+ ERR("Invalid parameter"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_ATTRIBUTES,
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get db table [%d][%s]", sql_ret, query);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ DBG("row_count [%d] column_count [%d]", row_count, column_count);
+
+ result_system_setting = (struct notification_system_setting *)malloc(sizeof(struct notification_system_setting));
+ if (result_system_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* no system setting record. allow everyting */
+ if (!row_count) {
+ /* LCOV_EXCL_START */
+ DBG("No setting found");
+ result_system_setting->do_not_disturb = 0;
+ result_system_setting->visibility_class = 0;
+ result_system_setting->dnd_schedule_enabled = 0;
+ result_system_setting->dnd_schedule_day = 0;
+ result_system_setting->dnd_start_hour = 0;
+ result_system_setting->dnd_start_min = 0;
+ result_system_setting->dnd_end_hour = 0;
+ result_system_setting->dnd_end_min = 0;
+ result_system_setting->lock_screen_content_level = 0;
+ result_system_setting->dnd_allow_exceptions = NULL;
+ /* LCOV_EXCL_STOP */
+ } else {
+ /* LCOV_EXCL_START */
+ col_index = column_count;
+ _get_table_field_data_int(query_result, (int *)&(result_system_setting->do_not_disturb), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->visibility_class), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_system_setting->dnd_schedule_enabled), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_schedule_day), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_start_hour), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_start_min), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_end_hour), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_end_min), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_system_setting->lock_screen_content_level), col_index++);
+ result_system_setting->dnd_allow_exceptions = NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *system_setting = result_system_setting;
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int notification_setting_db_update(const char *package_name, const char *app_id,
+ int allow_to_notify, int do_not_disturb_except,
+ int visibility_class, int pop_up_notification,
+ int lock_screen_content_level, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (package_name == NULL || app_id == NULL) {
+ ERR("Invalid paramter"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("UPDATE %s SET allow_to_notify = %d, "
+ "do_not_disturb_except = %d, visibility_class = %d, "
+ "pop_up_notification = %d, lock_screen_content_level = %d "
+ "WHERE app_id = %Q AND package_name = %Q AND uid = %d ",
+ NOTIFICATION_SETTING_DB_TABLE, allow_to_notify,
+ do_not_disturb_except, visibility_class,
+ pop_up_notification, lock_screen_content_level, app_id,
+ package_name, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int notification_setting_db_update_system_setting(int do_not_disturb, int visibility_class,
+ int dnd_schedule_enabled, int dnd_schedule_day,
+ int dnd_start_hour, int dnd_start_min,
+ int dnd_end_hour, int dnd_end_min,
+ int lock_screen_content_level, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int num_changes = 0;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("INSERT OR REPLACE INTO %s (uid, %s) "
+ "VALUES(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d) ",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE,
+ NOTIFICATION_SYSTEM_SETTING_DB_ATTRIBUTES,
+ uid, do_not_disturb, visibility_class,
+ dnd_schedule_enabled, dnd_schedule_day, dnd_start_hour,
+ dnd_start_min, dnd_end_hour, dnd_end_min,
+ lock_screen_content_level);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, &num_changes);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ if (num_changes == 0)
+ WARN("No changes on DB");
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API
+int notification_setting_db_update_do_not_disturb(int do_not_disturb, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("UPDATE %s SET do_not_disturb = %d "
+ "WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE,
+ do_not_disturb, uid);
+ if (query == NULL) {
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API
+int notification_system_setting_get_dnd_schedule_enabled_uid(uid_t **uids, int *count)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int i;
+ int row_count = 0;
+ int column_count = 0;
+ int column_index = 0;
+ char *query = NULL;
+ char **query_result = NULL;
+ sqlite3 *db = NULL;
+ uid_t *result_uids;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT uid FROM %s "
+ "WHERE dnd_schedule_enabled = 1",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE);
+ if (query == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (ret != SQLITE_OK && ret != -1) {
+ ERR("Failed to get DB table [%d][%s]", ret, query);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ if (row_count == 0) {
+ DBG("No enabled do_not_disturb user");
+ ret = NOTIFICATION_ERROR_NONE;
+ goto out;
+ }
+
+ result_uids = (uid_t *)malloc(sizeof(int) * row_count);
+ if (result_uids == NULL) {
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ column_index = column_count;
+ for (i = 0; i < row_count; i++)
+ _get_table_field_data_int(query_result, (int *)&(result_uids[i]), column_index++);
+
+ *uids = result_uids;
+ *count = row_count;
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API
+int notification_get_dnd_and_allow_to_notify(const char *app_id,
+ int *do_not_disturb,
+ int *do_not_disturb_except,
+ int *allow_to_notify,
+ uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count;
+ int col_count;
+ int col_index;
+ sqlite3 *db;
+ char *query_setting = NULL;
+ char **query_setting_result = NULL;
+ char *query_system_setting = NULL;
+ char **query_system_setting_result = NULL;
+
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query_setting = sqlite3_mprintf("SELECT allow_to_notify, "
+ "do_not_disturb_except FROM %s WHERE app_id = %Q "
+ "AND (uid = %d OR uid = %d) ORDER BY uid DESC",
+ NOTIFICATION_SETTING_DB_TABLE, app_id,
+ uid, tzplatform_getuid(TZ_SYS_GLOBALAPP_USER));
+ if (query_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ query_system_setting = sqlite3_mprintf("SELECT do_not_disturb FROM %s "
+ "WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE, uid);
+ if (query_system_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query_setting, &query_setting_result, &row_count, &col_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get DB table [%d][%s]", sql_ret, query_setting);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (row_count == 0) {
+ ERR("Invalid uid [%d] or app id [%s]", uid, app_id);
+ ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ col_index = col_count;
+ _get_table_field_data_int(query_setting_result, (int *)allow_to_notify, col_index++);
+ _get_table_field_data_int(query_setting_result, (int *)do_not_disturb_except, col_index++);
+
+ sql_ret = sqlite3_get_table(db, query_system_setting, &query_system_setting_result, &row_count, &col_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get DB table [%d][%s]", sql_ret, query_setting);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (row_count == 0) {
+ ERR("Invalid uid [%d]", uid);
+ ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ col_index = col_count;
+ _get_table_field_data_int(query_system_setting_result, (int *)do_not_disturb, col_index++);
+
+out:
+ if (query_setting_result)
+ sqlite3_free_table(query_setting_result);
+
+ if (query_system_setting_result)
+ sqlite3_free_table(query_system_setting_result);
+
+ if (query_setting)
+ sqlite3_free(query_setting);
+
+ if (query_system_setting)
+ sqlite3_free(query_system_setting);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_system_setting_load_dnd_allow_exception(dnd_allow_exception_h *dnd_allow_exception, int *count, uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count = 0;
+ int column_count = 0;
+ int col_index = 0;
+ int i;
+ char *query = NULL;
+ char **query_result = NULL;
+ sqlite3 *db = NULL;
+ dnd_allow_exception_h dnd_allow_exception_data = NULL;
+
+ if (dnd_allow_exception == NULL) {
+ ERR("Invalid paramter"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT type, value FROM %s WHERE uid = %d",
+ NOTIFICATION_DND_ALLOW_EXCEPTION, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get DB table [%d][%s]", sql_ret, query); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!row_count) {
+ DBG("No setting found"); /* LCOV_EXCL_LINE */
+ goto out;
+ } else {
+ dnd_allow_exception_data = (dnd_allow_exception_h)malloc(sizeof(struct notification_system_setting_dnd_allow_exception) * row_count);
+ if (dnd_allow_exception_data == NULL) {
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ col_index = column_count;
+
+ for (i = 0; i < row_count; i++) {
+ _get_table_field_data_int(query_result, (int *)&(dnd_allow_exception_data[i].type), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(dnd_allow_exception_data[i].value), col_index++);
+ }
+ }
+
+ *dnd_allow_exception = dnd_allow_exception_data;
+ *count = row_count;
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int notification_system_setting_update_dnd_allow_exception(int type, int value, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int num_changes = 0;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("INSERT OR REPLACE INTO %s (uid, type, value) "
+ "VALUES(%d, %d, %d) ",
+ NOTIFICATION_DND_ALLOW_EXCEPTION,
+ uid, type, value);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, &num_changes);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ if (num_changes == 0)
+ WARN("No changes on DB");
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int noti_system_setting_get_do_not_disturb(int *do_not_disturb, uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int row_count = 0;
+ int col_count = 0;
+ int col_index = 0;
+ char *query = NULL;
+ char **query_result = NULL;
+ sqlite3 *db = NULL;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT do_not_disturb FROM %s WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_get_table(db, query, &query_result, &row_count, &col_count, NULL);
+ if (ret != SQLITE_OK && ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get DB table [%d][%s]", ret, query);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ col_index = col_count;
+ if (row_count == 0) {
+ /* LCOV_EXCL_START */
+ ERR("No system setting found");
+ ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ /* LCOV_EXCL_STOP */
+ } else {
+ if (_get_table_field_data_int(query_result, (int *)do_not_disturb, col_index++) == false)
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API
+int notification_setting_db_update_app_disabled(const char *app_id, bool value, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int num_changes = 0;
+
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("UPDATE %s SET app_disabled= %d " \
+ "WHERE app_id = %Q AND uid = %d",
+ NOTIFICATION_SETTING_DB_TABLE, value,
+ app_id, uid);
+ if (query == NULL) {
+ ERR("Failed to alloc memory"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query, &num_changes);
+ if (ret == NOTIFICATION_ERROR_NONE && num_changes <= 0)
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API
+int notification_setting_db_update_pkg_disabled(const char *pkg_id, bool value, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int num_changes = 0;
+
+ if (pkg_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open(DBPATH);
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("UPDATE %s SET app_disabled= %d " \
+ "WHERE package_name = %Q AND uid = %d",
+ NOTIFICATION_SETTING_DB_TABLE, value,
+ pkg_id, uid);
+ if (query == NULL) {
+ ERR("Failed to alloc memory"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query, &num_changes);
+ if (ret == NOTIFICATION_ERROR_NONE && num_changes <= 0)
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
diff --git a/notification/src/notification_shared_file.c b/notification/src/notification_shared_file.c
new file mode 100644
index 0000000..7ca23d9
--- /dev/null
+++ b/notification/src/notification_shared_file.c
@@ -0,0 +1,1185 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+
+#include <tzplatform_config.h>
+#include <security-manager.h>
+#include <sys/smack.h>
+#include <sys/stat.h>
+#include <linux/xattr.h>
+#include <sys/types.h>
+#include <utime.h>
+#include <sys/time.h>
+#include <package_manager.h>
+
+#include "notification.h"
+#include "notification_debug.h"
+#include "notification_shared_file.h"
+#include <notification_private.h>
+
+
+#define DUMMY_PARAM
+#define __OOM_CHECK(value, ret_value, free_fun) \
+do { \
+ if (value == NULL) { \
+ ERR("out of memory"); \
+ free_fun; \
+ return ret_value; \
+ } \
+} while (0)
+
+GList *__uid_list;
+typedef struct uid_info {
+ uid_t uid;
+ GList *sharing_req_list;
+ GList *target_app_list;
+} uid_info_s;
+
+typedef struct sharing_req_data {
+ char *app_id;
+ char *dir;
+ GList *priv_id_list;
+ GList *shared_file_list;
+ GList *target_app_table;
+} sharing_req_data_s;
+
+typedef struct sharing_file_info {
+ char *src_path;
+ char *dst_path;
+ time_t modification_time;
+} sharing_file_info_s;
+
+typedef struct target_app_info {
+ char *app_id;
+ char *dbus_sender_name;
+} target_app_info_s;
+
+static bool __make_sharing_dir(const char *dir)
+{
+ GFile *noti_dir = NULL;
+ GError *g_err = NULL;
+
+ if (access(dir, R_OK) != 0) {
+ noti_dir = g_file_new_for_path(dir);
+ if (g_file_make_directory(noti_dir, NULL, &g_err) == false) {
+ /* LCOV_EXCL_START */
+ if (g_err) {
+ ERR("Failed to make sharing dir[%s]",
+ g_err->message);
+ g_error_free(g_err);
+ }
+ g_object_unref(noti_dir);
+ return false;
+ /* LCOV_EXCL_STOP */
+ }
+ g_object_unref(noti_dir);
+ }
+
+ return true;
+}
+
+static char *__get_data_path_by_pkg_id(const char *pkg_id,
+ const char *file_name, uid_t uid)
+{
+#define NOTI_PRIV_DATA_DIR "data/.notification"
+
+ const char *path;
+ char dir[PATH_MAX];
+
+ tzplatform_set_user(uid);
+ path = tzplatform_getenv(TZ_USER_APP);
+ tzplatform_reset_user();
+
+ if (pkg_id == NULL || path == NULL)
+ return NULL;
+
+ snprintf(dir, sizeof(dir), "%s/%s/%s", path, pkg_id, NOTI_PRIV_DATA_DIR);
+
+ if (__make_sharing_dir(dir) == false)
+ return NULL;
+
+ snprintf(dir, sizeof(dir), "%s/%s/%s/%s", path, pkg_id,
+ NOTI_PRIV_DATA_DIR, file_name);
+
+ return strdup(dir);
+}
+
+static const char *__last_index_of(const char *path, const char *search)
+{
+ int i;
+ int search_len;
+ const char *index;
+
+ if (path == NULL || search == NULL)
+ return NULL;
+
+ search_len = strlen(search);
+ index = path + strlen(path) - search_len;
+
+ while (index >= path) {
+ for (i = 0; i < search_len; i++)
+ if (index[i] != search[i])
+ break;
+
+ if (i == search_len)
+ return index;
+ index--;
+ }
+
+ return NULL;
+}
+
+/* Check path that include res directory */
+/* LCOV_EXCL_START */
+static bool __is_private_file(const char *smack_label, const char *pkg_id)
+{
+ const char *smack_index;
+ bool ret = false;
+
+ if (smack_label == NULL || pkg_id == NULL)
+ return ret;
+
+ smack_index = __last_index_of(smack_label, pkg_id);
+ if (smack_index != NULL && (strlen(smack_index) == strlen(pkg_id)))
+ ret = true;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+static bool __is_RO_file(const char *smack_label)
+{
+#define CHECK_LABEL "::RO"
+
+ const char *smack_index;
+ bool ret = false;
+
+ smack_index = __last_index_of(smack_label, CHECK_LABEL);
+ if (smack_index != NULL && (strlen(smack_index) == strlen(CHECK_LABEL)))
+ ret = true;
+
+ return ret;
+}
+
+/* file copy from /res to /data */
+int notification_copy_private_file(const char *src_path,
+ const char *dst_path)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ GFile *src = NULL;
+ GFile *dst = NULL;
+ GError *g_err = NULL;
+ struct utimbuf ut = {0,};
+
+ dst = g_file_new_for_path(dst_path);
+ if (dst == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("dst path is wrong [%s]", dst_path);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_file_query_exists(dst, NULL) == true) {
+ ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+ INFO("dst path existed [%s]", dst_path);
+ goto out;
+ }
+
+ src = g_file_new_for_path(src_path);
+ if (src == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("src path is wrong [%s]", src_path);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!g_file_copy(src, dst, G_FILE_COPY_NOFOLLOW_SYMLINKS,
+ /* LCOV_EXCL_START */
+ NULL, NULL, NULL, &g_err)) {
+ if (g_err) {
+ ERR(
+ "Copying file from [%s] to [%s] is failed [%s]",
+ src_path, dst_path, g_err->message);
+ g_error_free(g_err);
+ }
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ut.modtime = time(NULL);
+ if (g_utime(dst_path, &ut) != 0)
+ DBG("Failed to set g_utime %d ", errno);
+
+out:
+ if (src)
+ g_object_unref(src);
+ if (dst)
+ g_object_unref(dst);
+
+ return ret;
+}
+
+static void __free_file_info(gpointer data)
+{
+ sharing_file_info_s *info = (sharing_file_info_s *)data;
+
+ if (info != NULL) {
+ if (info->src_path)
+ free(info->src_path);
+ if (info->dst_path)
+ free(info->dst_path);
+ free(info);
+ }
+}
+
+/* LCOV_EXCL_START */
+static void __free_req_info(gpointer data)
+{
+ sharing_req_data_s *info = (sharing_req_data_s *)data;
+
+ if (info == NULL)
+ return;
+ if (info->app_id)
+ free(info->app_id);
+ if (info->dir)
+ free(info->dir);
+ if (info->shared_file_list)
+ g_list_free_full(info->shared_file_list, __free_file_info);
+ if (info->target_app_table)
+ g_list_free_full(info->target_app_table, free);
+
+ free(info);
+}
+/* LCOV_EXCL_STOP */
+
+static char **__convert_list_to_array(GList *list, int *length)
+{
+ int len, i;
+ char **array;
+ GList *iter;
+
+ if (list == NULL)
+ return NULL;
+
+ len = g_list_length(list);
+ if (len == 0)
+ return NULL;
+
+ array = (char **)calloc(len + 1, sizeof(char *));
+ __OOM_CHECK(array, NULL, DUMMY_PARAM);
+
+ for (i = 0, iter = list; iter != NULL; i++, iter = g_list_next(iter))
+ array[i] = ((sharing_file_info_s *)iter->data)->dst_path;
+
+ *length = len;
+
+ return array;
+}
+
+static gint __comp_str(gconstpointer a, gconstpointer b)
+{
+ char *new_file = (char *)a;
+ char *file = (char *)b;
+
+ if (new_file == NULL || file == NULL)
+ return -1;
+
+ return strcmp(new_file, file);
+}
+
+/* LCOV_EXCL_START */
+static gint __comp_file_info(gconstpointer a, gconstpointer b)
+{
+ sharing_file_info_s *file = (sharing_file_info_s *)a;
+ sharing_file_info_s *new_file = (sharing_file_info_s *)b;
+
+ if (!file || !new_file || !new_file->dst_path || !file->dst_path)
+ return -1;
+
+ return strcmp(new_file->dst_path, file->dst_path);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static gint __comp_dst_path(gconstpointer a, gconstpointer b)
+{
+ sharing_file_info_s *info = (sharing_file_info_s *)a;
+ char *path = (char *)b;
+
+ if (!info || !path || !info->dst_path)
+ return -1;
+
+ return strcmp(info->dst_path, path);
+}
+/* LCOV_EXCL_STOP */
+
+static sharing_file_info_s *__dup_file_info(sharing_file_info_s *src)
+{
+ sharing_file_info_s *file_info;
+
+ file_info = (sharing_file_info_s *)calloc(1, sizeof(sharing_file_info_s));
+ __OOM_CHECK(file_info, NULL, DUMMY_PARAM);
+
+ file_info->dst_path = strdup(src->dst_path);
+ __OOM_CHECK(file_info->dst_path, NULL, __free_file_info(file_info));
+
+ file_info->src_path = strdup(src->src_path);
+ __OOM_CHECK(file_info->src_path, NULL, __free_file_info(file_info));
+
+ file_info->modification_time = src->modification_time;
+
+ return file_info;
+
+}
+
+static void __make_file_info(char *src_path, char *dst_path,
+ GList **new_file_list, GList *shared_file_list, bool *is_overlapping)
+{
+ int ret;
+ GList *tmp;
+ sharing_file_info_s *file_info;
+ sharing_file_info_s *dup_file_info;
+ struct stat stat_buf = {0,};
+
+ /*
+ * If the file copy is successful,
+ * ignore the shared_file_list check for private sharing
+ */
+ ret = notification_copy_private_file(src_path, dst_path);
+
+ if (ret == NOTIFICATION_ERROR_ALREADY_EXIST_ID) {
+ tmp = g_list_find_custom(shared_file_list, dst_path,
+ __comp_dst_path);
+ if (tmp == NULL) {
+ file_info = (sharing_file_info_s *)calloc(1,
+ sizeof(sharing_file_info_s));
+ __OOM_CHECK(file_info, DUMMY_PARAM, DUMMY_PARAM);
+
+ file_info->dst_path = strdup(dst_path);
+ __OOM_CHECK(file_info->dst_path, DUMMY_PARAM,
+ __free_file_info(file_info));
+
+ file_info->src_path = strdup(src_path);
+ __OOM_CHECK(file_info->src_path, DUMMY_PARAM,
+ __free_file_info(file_info));
+
+ if (stat(dst_path, &stat_buf) != 0)
+ ERR("Failed to get stat info");
+ file_info->modification_time = stat_buf.st_mtime;
+
+ *new_file_list = g_list_append(*new_file_list, file_info);
+ } else {
+ file_info = (sharing_file_info_s *)tmp->data;
+
+ if (stat(file_info->dst_path, &stat_buf) != 0)
+ ERR("Failed to get stat info");
+
+ if (file_info->modification_time != stat_buf.st_mtime) {
+ dup_file_info = __dup_file_info(file_info);
+ __OOM_CHECK(dup_file_info, DUMMY_PARAM, DUMMY_PARAM);
+
+ *new_file_list = g_list_append(*new_file_list,
+ dup_file_info);
+ *is_overlapping = true;
+ }
+ }
+ } else if (ret == NOTIFICATION_ERROR_NONE) {
+ *is_overlapping = true;
+ }
+
+}
+
+static GList *__get_new_file_list(notification_h noti,
+ GList *shared_file_list,
+ bool *is_overlapping)
+{
+ GList *new_file_list = NULL;
+ char *src_path, *dst_path, *dup_str;
+ char buf_key[32] = { 0, };
+ int i = NOTIFICATION_IMAGE_TYPE_ICON;
+
+
+ if (noti->priv_sound_path != NULL && noti->sound_path != NULL) {
+ dst_path = noti->priv_sound_path;
+ src_path = noti->sound_path;
+
+ dup_str = strdup(dst_path);
+ __OOM_CHECK(dup_str, NULL, DUMMY_PARAM);
+
+ __make_file_info(src_path, dst_path, &new_file_list,
+ shared_file_list, is_overlapping);
+
+ free(noti->sound_path);
+ noti->sound_path = dup_str;
+ }
+
+ if (noti->priv_vibration_path != NULL && noti->vibration_path != NULL) {
+ dst_path = noti->priv_vibration_path;
+ src_path = noti->vibration_path;
+
+ dup_str = strdup(dst_path);
+ __OOM_CHECK(dup_str, NULL,
+ g_list_free_full(new_file_list, __free_file_info));
+
+ __make_file_info(src_path, dst_path, &new_file_list,
+ shared_file_list, is_overlapping);
+
+ free(noti->vibration_path);
+ noti->vibration_path = dup_str;
+ }
+
+ if (noti->b_priv_image_path == NULL)
+ return new_file_list;
+
+ for (; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ src_path = NULL;
+ dst_path = NULL;
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+ bundle_get_str(noti->b_priv_image_path, buf_key, &dst_path);
+ bundle_get_str(noti->b_image_path, buf_key, &src_path);
+ if (dst_path != NULL && src_path != NULL) {
+ __make_file_info(src_path, dst_path, &new_file_list,
+ shared_file_list, is_overlapping);
+
+ bundle_del(noti->b_image_path, buf_key);
+ bundle_add_str(noti->b_image_path, buf_key, dst_path);
+ }
+ }
+
+ return new_file_list;
+}
+
+static char *__get_shared_dir(notification_h noti)
+{
+ char *path = NULL;
+ char *dir;
+ const char *index;
+ char buf_key[32] = { 0, };
+ int i = NOTIFICATION_IMAGE_TYPE_ICON, dir_len;
+
+ if (noti->b_priv_image_path != NULL) {
+ for (; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+ bundle_get_str(noti->b_priv_image_path, buf_key, &path);
+ if (path != NULL)
+ break;
+ }
+ }
+
+ if (path == NULL && noti->priv_sound_path != NULL)
+ path = noti->priv_sound_path;
+ else if (path == NULL && noti->priv_vibration_path != NULL)
+ path = noti->priv_vibration_path;
+
+ if (path == NULL) {
+ DBG("No private resource");
+ return NULL;
+ }
+
+ index = __last_index_of(path, "/");
+ if (index == NULL) {
+ ERR("Failed to find directory separator");
+ return NULL;
+ }
+
+ dir_len = index - path + 1;
+ if (dir_len <= 0 || dir_len > PATH_MAX)
+ return NULL;
+
+ dir = (char *)calloc(dir_len, sizeof(char));
+ __OOM_CHECK(dir, NULL, DUMMY_PARAM);
+
+ snprintf(dir, dir_len, "%s", path);
+
+ return dir;
+}
+
+static gint __comp_sharing_req_list(gconstpointer a, gconstpointer b)
+{
+ sharing_req_data_s *req_data = (sharing_req_data_s *)a;
+ char *app_id = (char *)b;
+
+ if (!req_data || !app_id || !req_data->app_id)
+ return -1;
+
+ if (!strcmp(app_id, req_data->app_id))
+ return 0;
+
+ return -1;
+}
+
+static gint __comp_uid_info_list(gconstpointer a, gconstpointer b)
+{
+ uid_info_s *uid_info = (uid_info_s *)a;
+
+ if (!a || !b)
+ return -1;
+
+ if (uid_info->uid == GPOINTER_TO_INT(b))
+ return 0;
+
+ return -1;
+}
+
+static gint __comp_priv_id(gconstpointer a, gconstpointer b)
+{
+ if (!a || !b)
+ return -1;
+
+ if (GPOINTER_TO_INT(a) == GPOINTER_TO_INT(b))
+ return 0;
+
+ return 1;
+}
+
+static gint __comp_target_app(gconstpointer a, gconstpointer b)
+{
+ target_app_info_s *target = (target_app_info_s *)a;
+ char *sender = (char *)b;
+
+ if (!target || !sender || !target->dbus_sender_name)
+ return -1;
+
+ return strcmp(sender, target->dbus_sender_name);
+}
+
+EXPORT_API void notification_remove_private_sharing_target_id(
+ const char *sender, uid_t uid)
+{
+ target_app_info_s *target_info;
+ uid_info_s *uid_info;
+ GList *sharing_req_list, *target_app;
+
+ sharing_req_list = g_list_find_custom(__uid_list, GINT_TO_POINTER(uid),
+ __comp_uid_info_list);
+ if (sharing_req_list == NULL)
+ return;
+
+ uid_info = sharing_req_list->data;
+ target_app = g_list_find_custom(uid_info->target_app_list, sender,
+ __comp_target_app);
+
+ if (target_app != NULL) {
+ target_info = target_app->data;
+ if (target_info) {
+ uid_info->target_app_list = g_list_remove(
+ uid_info->target_app_list, target_info);
+
+ free(target_info->app_id);
+ free(target_info->dbus_sender_name);
+ free(target_info);
+ target_info = NULL;
+ }
+ }
+}
+
+EXPORT_API void notification_add_private_sharing_target_id(pid_t pid,
+ const char *sender, uid_t uid)
+{
+ char *app_id;
+ target_app_info_s *target_info;
+ uid_info_s *uid_info;
+ GList *sharing_req_list, *target_app;
+
+ sharing_req_list = g_list_find_custom(__uid_list, GINT_TO_POINTER(uid),
+ __comp_uid_info_list);
+ if (sharing_req_list == NULL) {
+ uid_info = (uid_info_s *)calloc(1, sizeof(uid_info_s));
+ __OOM_CHECK(uid_info, DUMMY_PARAM, DUMMY_PARAM);
+ uid_info->uid = uid;
+
+ __uid_list = g_list_append(__uid_list, uid_info);
+ } else {
+ uid_info = sharing_req_list->data;
+ }
+
+ target_app = g_list_find_custom(uid_info->target_app_list, sender,
+ __comp_target_app);
+ if (target_app == NULL) {
+ app_id = notification_get_app_id_by_pid((int)pid);
+ if (app_id == NULL) {
+ ERR("Failed to get app id by pid");
+ return;
+ }
+
+ target_info = (target_app_info_s *)calloc(1, sizeof(target_app_info_s));
+ if (target_info == NULL) {
+ ERR("Failed to alloc memory");
+ free(app_id);
+ return;
+ }
+
+ target_info->app_id = app_id;
+ target_info->dbus_sender_name = strdup(sender);
+ if (target_info->dbus_sender_name == NULL) {
+ ERR("Failed to alloc memory");
+ free(target_info);
+ free(app_id);
+ return;
+ }
+
+ uid_info->target_app_list = g_list_append(
+ uid_info->target_app_list, target_info);
+ }
+}
+
+char *notification_check_file_path_is_private(const char *pkg_id,
+ const char *file_path)
+{
+ char *smack_label = NULL;
+ char *dst_path = NULL;
+ int size;
+ uid_t uid = getuid();
+
+ size = smack_new_label_from_path(file_path, XATTR_NAME_SMACK,
+ TRUE, &smack_label);
+ if (size <= 0) {
+ ERR("Failed to get smack info");
+ return NULL;
+ }
+
+ if (__is_RO_file(smack_label))
+ dst_path = __get_data_path_by_pkg_id(pkg_id,
+ __last_index_of(file_path, "/") + 1, uid);
+
+ if (dst_path == NULL && __is_private_file(smack_label, pkg_id)) {
+ dst_path = strdup(file_path);
+ if (dst_path == NULL)
+ ERR("Failed to strdup");
+ }
+
+ free(smack_label);
+ return dst_path;
+}
+
+EXPORT_API bool notification_validate_private_sharing(
+ notification_h updated_noti)
+{
+ char *updated_path = NULL;
+ char *private_path;
+ char buf_key[32] = { 0, };
+ int i = NOTIFICATION_IMAGE_TYPE_ICON;
+
+ if (updated_noti->b_image_path && updated_noti->b_priv_image_path) {
+ for (; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+
+ bundle_get_str(updated_noti->b_image_path, buf_key,
+ &updated_path);
+ if (updated_path == NULL)
+ continue;
+
+ bundle_get_str(updated_noti->b_priv_image_path,
+ buf_key, &private_path);
+ if (private_path == NULL)
+ continue;
+
+ if (strcmp(updated_path, private_path) == 0)
+ return false;
+
+ updated_path = NULL;
+ }
+ }
+
+ if (updated_noti->sound_path && updated_noti->priv_sound_path) {
+ if (strcmp(updated_noti->sound_path,
+ updated_noti->priv_sound_path) == 0)
+ return false;
+ }
+
+ if (updated_noti->vibration_path && updated_noti->priv_vibration_path) {
+ if (strcmp(updated_noti->vibration_path,
+ updated_noti->priv_vibration_path) == 0)
+ return false;
+ }
+
+ return true;
+}
+
+EXPORT_API void notification_calibrate_private_sharing(
+ notification_h updated_noti, notification_h source_noti)
+{
+ char *updated_path = NULL;
+ char *source_path;
+ char *private_path;
+ char buf_key[32] = { 0, };
+ int i = NOTIFICATION_IMAGE_TYPE_ICON;
+
+ if (updated_noti->b_image_path && updated_noti->b_priv_image_path) {
+ for (; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+ bundle_get_str(updated_noti->b_image_path, buf_key,
+ &updated_path);
+ if (updated_path == NULL)
+ continue;
+ bundle_get_str(updated_noti->b_priv_image_path,
+ buf_key, &private_path);
+ if (private_path == NULL)
+ continue;
+ if (strcmp(updated_path, private_path) == 0) {
+ bundle_get_str(source_noti->b_image_path,
+ buf_key, &source_path);
+ bundle_del(updated_noti->b_image_path, buf_key);
+ bundle_add_str(updated_noti->b_image_path,
+ buf_key, source_path);
+ }
+ updated_path = NULL;
+ private_path = NULL;
+ }
+ }
+
+ if (updated_noti->sound_path && updated_noti->priv_sound_path) {
+ if (strcmp(updated_noti->sound_path,
+ updated_noti->priv_sound_path) == 0) {
+ free(updated_noti->sound_path);
+ updated_noti->sound_path = strdup(source_noti->sound_path);
+ if (updated_noti->sound_path == NULL)
+ ERR("out of memory");
+ }
+ }
+
+ if (updated_noti->vibration_path && updated_noti->priv_vibration_path) {
+ if (strcmp(updated_noti->vibration_path,
+ updated_noti->priv_vibration_path) == 0) {
+ free(updated_noti->vibration_path);
+ updated_noti->vibration_path =
+ strdup(source_noti->priv_vibration_path);
+ if (updated_noti->vibration_path == NULL)
+ ERR("out of memory");
+ }
+ }
+}
+
+
+int __set_sharing_for_new_target(sharing_req_data_s *req_data,
+ GList *target_app_list)
+{
+ char **path_array = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int len;
+ private_sharing_req *handle = NULL;
+ GList *iter, *tmp;
+ target_app_info_s *target_info;
+ char *app_info = NULL;
+
+ iter = target_app_list;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ target_info = (target_app_info_s *)iter->data;
+ tmp = g_list_find_custom(req_data->target_app_table,
+ target_info->app_id, __comp_str);
+ if (tmp != NULL)
+ continue;
+
+ app_info = strdup(target_info->app_id);
+ if (app_info == NULL) {
+ ERR("out of memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if (handle == NULL) {
+ ret = security_manager_private_sharing_req_new(&handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to create PS handle");
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_set_owner_appid(
+ handle, req_data->app_id);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR(
+ "Failed to set owner appid(%s) %d",
+ req_data->app_id, ret);
+ goto out;
+ }
+ path_array = __convert_list_to_array(
+ req_data->shared_file_list, &len);
+ if (path_array == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_add_paths(
+ handle, (const char **)path_array, len);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to add paths %d", ret);
+ goto out;
+ }
+ }
+
+ ret = security_manager_private_sharing_req_set_target_appid(
+ handle, target_info->app_id);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to set target appid(%s)",
+ (const char *)iter->data);
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_apply(handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to apply PS %d", ret);
+ goto out;
+ }
+
+ req_data->target_app_table = g_list_append(
+ req_data->target_app_table,
+ app_info);
+ }
+
+out:
+ if (ret != NOTIFICATION_ERROR_NONE && app_info)
+ free(app_info);
+
+ if (handle != NULL)
+ security_manager_private_sharing_req_free(handle);
+ if (path_array != NULL)
+ free(path_array);
+
+ return ret;
+}
+
+int __set_sharing_for_new_file(sharing_req_data_s *req_data,
+ GList *new_file_list, bool is_overlapping)
+{
+ char **path_array = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int len;
+ private_sharing_req *handle = NULL;
+ GList *iter;
+
+ path_array = __convert_list_to_array(new_file_list, &len);
+ if (path_array == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_new(&handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to create private sharing request handle[%d]", ret);
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_set_owner_appid(handle,
+ req_data->app_id);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to set owner appid[%s][%d]",
+ req_data->app_id, ret);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = security_manager_private_sharing_req_add_paths(handle,
+ (const char **)path_array, len);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to add paths [%d]", ret);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (is_overlapping == true) {
+ iter = req_data->target_app_table;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ ret = security_manager_private_sharing_req_set_target_appid(
+ handle, (const char *)iter->data);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to set target appid [%s]",
+ (const char *)iter->data);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = security_manager_private_sharing_drop(handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to drop [%d]", ret);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+ }
+
+ iter = req_data->target_app_table;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ ret = security_manager_private_sharing_req_set_target_appid(handle,
+ (const char *)iter->data);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to set target appid [%s]",
+ (const char *)iter->data);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = security_manager_private_sharing_apply(handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to apply PS [%d]", ret);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+out:
+ if (handle != NULL)
+ security_manager_private_sharing_req_free(handle);
+ if (path_array != NULL)
+ free(path_array);
+
+ return ret;
+}
+
+EXPORT_API int notification_set_private_sharing(notification_h noti,
+ uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ bool is_overlapping = false;
+ sharing_req_data_s *req_data;
+ sharing_file_info_s *file_info, *dup_file_info;
+ uid_info_s *uid_info;
+ GList *req_list, *iter, *tmp;
+ GList *new_file_list = NULL;
+
+ if (noti == NULL || noti->caller_app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ tmp = g_list_find_custom(__uid_list, GINT_TO_POINTER(uid),
+ __comp_uid_info_list);
+ if (tmp == NULL) {
+ uid_info = (uid_info_s *)calloc(1, sizeof(uid_info_s));
+ __OOM_CHECK(uid_info, NOTIFICATION_ERROR_OUT_OF_MEMORY, DUMMY_PARAM);
+
+ uid_info->uid = uid;
+ __uid_list = g_list_append(__uid_list, uid_info);
+ } else {
+ uid_info = tmp->data;
+ }
+
+ req_list = g_list_find_custom(uid_info->sharing_req_list,
+ noti->caller_app_id, __comp_sharing_req_list);
+ if (req_list == NULL) {
+ req_data = (sharing_req_data_s *)calloc(1, sizeof(sharing_req_data_s));
+ __OOM_CHECK(req_data, NOTIFICATION_ERROR_OUT_OF_MEMORY, DUMMY_PARAM);
+
+ req_data->app_id = strdup(noti->caller_app_id);
+ __OOM_CHECK(req_data->app_id, NOTIFICATION_ERROR_OUT_OF_MEMORY,
+ __free_req_info(req_data));
+
+ req_data->dir = __get_shared_dir(noti);
+ if (req_data->dir == NULL) {
+ __free_req_info(req_data);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ uid_info->sharing_req_list = g_list_append(
+ uid_info->sharing_req_list, req_data);
+ } else {
+ req_data = (sharing_req_data_s *)req_list->data;
+ }
+
+ __make_sharing_dir(req_data->dir);
+
+ tmp = g_list_find_custom(req_data->priv_id_list,
+ GINT_TO_POINTER(noti->priv_id), __comp_priv_id);
+ if (tmp == NULL)
+ req_data->priv_id_list = g_list_append(req_data->priv_id_list,
+ GINT_TO_POINTER(noti->priv_id));
+
+ new_file_list = __get_new_file_list(noti, req_data->shared_file_list,
+ &is_overlapping);
+ if (new_file_list != NULL) {
+ if (__set_sharing_for_new_file(req_data, new_file_list,
+ is_overlapping) != NOTIFICATION_ERROR_NONE) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ }
+ }
+
+ for (iter = new_file_list; iter != NULL; iter = g_list_next(iter)) {
+ tmp = NULL;
+ file_info = iter->data;
+ if (is_overlapping == true)
+ tmp = g_list_find_custom(
+ req_data->shared_file_list, file_info,
+ __comp_file_info);
+
+ if (tmp == NULL) {
+ dup_file_info = __dup_file_info(file_info);
+ req_data->shared_file_list = g_list_append(
+ req_data->shared_file_list, dup_file_info);
+ }
+ }
+
+ if (__set_sharing_for_new_target(req_data, uid_info->target_app_list)
+ != NOTIFICATION_ERROR_NONE) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ }
+ INFO("PS success priv id[%d] shared file count[%d] target app count[%d]",
+ noti->priv_id,
+ g_list_length(req_data->shared_file_list),
+ g_list_length(req_data->target_app_table));
+
+out:
+ if (new_file_list != NULL)
+ g_list_free_full(new_file_list, __free_file_info);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ req_data->priv_id_list = g_list_remove(req_data->priv_id_list,
+ GINT_TO_POINTER(noti->priv_id));
+ return ret;
+}
+
+EXPORT_API void notification_remove_private_sharing(
+ const char *src_app_id, int priv_id, uid_t uid)
+{
+ char **path_array = NULL;
+ sharing_req_data_s *req_data;
+ private_sharing_req *handle = NULL;
+ uid_info_s *uid_info;
+ GList *req_list;
+ GList *iter;
+ GList *priv_id_info = NULL;
+ GList *tmp_list = NULL;
+ int len, ret;
+
+ tmp_list = g_list_find_custom(__uid_list, GINT_TO_POINTER(uid),
+ __comp_uid_info_list);
+ if (tmp_list == NULL)
+ return;
+
+ uid_info = tmp_list->data;
+
+ req_list = g_list_find_custom(uid_info->sharing_req_list, src_app_id,
+ __comp_sharing_req_list);
+ if (req_list == NULL)
+ return;
+
+ req_data = (sharing_req_data_s *)req_list->data;
+
+ priv_id_info = g_list_find_custom(req_data->priv_id_list,
+ GINT_TO_POINTER(priv_id), __comp_priv_id);
+ if (priv_id_info == NULL)
+ return;
+
+ len = g_list_length(req_data->priv_id_list);
+ if (len > 1) {
+ req_data->priv_id_list = g_list_remove(req_data->priv_id_list,
+ priv_id_info->data);
+ return;
+ }
+
+ /* If there is no shared file, the private sharing is not dropped. */
+ __make_sharing_dir(req_data->dir);
+ iter = req_data->shared_file_list;
+ for (; iter != NULL; iter = g_list_next(iter))
+ notification_copy_private_file(
+ ((sharing_file_info_s *)(iter->data))->src_path,
+ ((sharing_file_info_s *)(iter->data))->dst_path);
+
+ if (g_list_length(req_data->target_app_table) > 0) {
+ ret = security_manager_private_sharing_req_new(&handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to create PS request handle");
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_set_owner_appid(
+ handle, src_app_id);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to set owner appid(%s) %d",
+ req_data->app_id, ret);
+ goto out;
+ }
+
+ path_array = __convert_list_to_array(req_data->shared_file_list, &len);
+ if (path_array == NULL) {
+ ERR("path_array is null %d",
+ g_list_length(req_data->shared_file_list));
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_add_paths(handle,
+ (const char **)path_array, len);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to add paths %d", ret);
+ goto out;
+ }
+
+ iter = req_data->target_app_table;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ ret = security_manager_private_sharing_req_set_target_appid(
+ handle, (const char *)iter->data);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to set target appid(%s)",
+ (const char *)iter->data);
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_drop(handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to drop %d", ret);
+ goto out;
+ }
+ }
+ }
+
+ iter = req_data->shared_file_list;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ if (g_remove(((sharing_file_info_s *)(iter->data))->dst_path) != 0)
+ ERR("Failed [%s] [%d]",
+ (const char *)iter->data, errno);
+ }
+
+ g_rmdir(req_data->dir);
+ req_data->priv_id_list = g_list_remove(req_data->priv_id_list,
+ priv_id_info->data);
+
+ uid_info->sharing_req_list = g_list_remove(uid_info->sharing_req_list,
+ req_data);
+ __free_req_info(req_data);
+
+out:
+ if (handle != NULL)
+ security_manager_private_sharing_req_free(handle);
+
+ if (path_array)
+ free(path_array);
+}
+
diff --git a/notification/src/notification_status.c b/notification/src/notification_status.c
new file mode 100644
index 0000000..cb69bbc
--- /dev/null
+++ b/notification/src/notification_status.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2000 - 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 <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <notification.h>
+#include <notification_db.h>
+#include <notification_list.h>
+#include <notification_noti.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_status.h>
+#include <notification_status_internal.h>
+
+#define PATH_NAME "/Org/Tizen/System/Notification/Status_message"
+#define INTERFACE_NAME "org.tizen.system.notification.status_message"
+#define MEMBER_NAME "status_message"
+
+struct _message_cb_data {
+ notification_status_message_cb callback;
+ void *data;
+ GDBusConnection *conn;
+ uint message_id;
+};
+
+static struct _message_cb_data md;
+
+static void __notification_status_message_dbus_callback(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ char *message = NULL;
+
+ g_variant_get(parameters, "(&s)", &message);
+ if (strlen(message) <= 0) {
+ /* LCOV_EXCL_START */
+ ERR("message is NULL");
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!md.callback) {
+ /* LCOV_EXCL_START */
+ ERR("No callback");
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ md.callback(message, md.data);
+}
+
+EXPORT_API
+int notification_status_monitor_message_cb_set(notification_status_message_cb callback, void *user_data)
+{
+ GError *error = NULL;
+
+ if (!callback)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (md.conn == NULL) {
+ md.conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (md.conn == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to connect to the D-BUS Daemon[%s]",
+ error->message);
+ g_error_free(error);
+ return NOTIFICATION_ERROR_FROM_DBUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ if (!md.message_id) {
+ md.message_id = g_dbus_connection_signal_subscribe(md.conn,
+ NULL,
+ INTERFACE_NAME,
+ MEMBER_NAME,
+ PATH_NAME,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ __notification_status_message_dbus_callback,
+ NULL,
+ NULL);
+ if (md.message_id == 0) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to subscribe signal");
+ g_object_unref(md.conn);
+ return NOTIFICATION_ERROR_FROM_DBUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ md.callback = callback;
+ md.data = user_data;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API
+int notification_status_monitor_message_cb_unset(void)
+{
+ if (md.message_id) {
+ g_dbus_connection_signal_unsubscribe(md.conn, md.message_id);
+ md.message_id = 0;
+ }
+
+ if (md.conn) {
+ g_object_unref(md.conn);
+ md.conn = NULL;
+ }
+
+ md.callback = NULL;
+ md.data = NULL;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API
+int notification_status_message_post(const char *message)
+{
+ GError *err = NULL;
+ GDBusConnection *conn;
+ GVariant *param;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (!message) {
+ ERR("message is NULL");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (conn == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to connect to the D-BUS Daemon[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+ param = g_variant_new("(s)", message);
+
+ if (g_dbus_connection_emit_signal(conn,
+ NULL,
+ PATH_NAME,
+ INTERFACE_NAME,
+ MEMBER_NAME,
+ param,
+ &err) == FALSE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to emit signal[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to flush connection sync[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+end:
+ if (err)
+ g_error_free(err); /* LCOV_EXCL_LINE */
+
+ if (conn)
+ g_object_unref(conn);
+
+ return ret;
+}
diff --git a/notification/src/notification_viewer.c b/notification/src/notification_viewer.c
new file mode 100644
index 0000000..6200d6b
--- /dev/null
+++ b/notification/src/notification_viewer.c
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <app_control_internal.h>
+#include <iniparser.h>
+#include <aul_svc.h>
+
+#include <notification.h>
+#include <notification_debug.h>
+#include <notification_viewer.h>
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_default_viewer(const char *path, char **default_viewer)
+{
+ char *viewer = NULL;
+ dictionary *dict = NULL;
+
+ if (access(path, F_OK) != 0) {
+ ERR("can't access file_path(%s)", path);
+ return -1;
+ }
+
+ dict = iniparser_load(path);
+ if (!dict) {
+ ERR("can't load file");
+ return -1;
+ }
+
+ viewer = iniparser_getstring(dict, "Notification:DefaultViewer", NULL);
+ if (viewer != NULL)
+ *default_viewer = strdup(viewer);
+
+ iniparser_freedict(dict);
+
+ return 0;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_launch_default_viewer(const char *default_viewer,
+ int priv_id, notification_op_type_e status, uid_t uid)
+{
+ int ret;
+ char buf[32] = {0,};
+ bundle *b = NULL;
+
+ b = bundle_create();
+ if (b == NULL) {
+ ERR("Failed to create bundle");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = aul_svc_set_appid(b, default_viewer);
+ if (ret != AUL_SVC_RET_OK) {
+ ERR("Failed to set appid to bundle[%x]", ret);
+ goto out;
+ }
+
+ snprintf(buf, sizeof(buf), "%d", priv_id);
+
+ ret = aul_svc_add_data(b, "NOTIFICATION_PRIVATE_ID", buf);
+ if (ret != AUL_SVC_RET_OK) {
+ ERR("Failed to add extra_data[%x]", ret);
+ goto out;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, sizeof(buf), "%d", status);
+
+ ret = aul_svc_add_data(b, "NOTIFICATION_OP_TYPE", buf);
+ if (ret != AUL_SVC_RET_OK) {
+ ERR("Failed to add extra_data[%x]", ret);
+ goto out;
+ }
+
+ ret = aul_svc_run_service_async_for_uid(b, 0, NULL, NULL, uid);
+ if (ret < 0) {
+ ERR("Failed to request app launch[%d]", ret);
+ } else {
+ INFO("successed to request app launch[%d],[%d]",
+ ret, uid);
+ ret = APP_CONTROL_ERROR_NONE;
+ }
+
+out:
+ if (b)
+ bundle_free(b);
+
+ if (ret == 0)
+ ret = NOTIFICATION_ERROR_NONE;
+ else
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/test-app/CMakeLists.txt b/notification/test-app/CMakeLists.txt
new file mode 100644
index 0000000..458ad38
--- /dev/null
+++ b/notification/test-app/CMakeLists.txt
@@ -0,0 +1,44 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(notification C)
+
+SET(CMAKE_SKIP_BUILD_RPATH TRUE)
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+ SET(CMAKE_BUILD_TYPE "Debug")
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+
+MESSAGE("")
+MESSAGE(">>> current directory: ${CMAKE_CURRENT_SOURCE_DIR}")
+MESSAGE(">>> Build type: ${CMAKE_BUILD_TYPE}")
+
+SET(VISIBILITY "-DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\"")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${VISIBILITY} -fvisibility=hidden")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,--gc-sections -fPIC")
+
+##########################################################
+# Define Test App
+##########################################################
+
+SET(TEST-APP-SRCS
+ ${CMAKE_SOURCE_DIR}/test-app/main.c
+)
+
+INCLUDE_DIRECTORIES(
+ ${CMAKE_SOURCE_DIR}/include
+)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(test_app_pkgs REQUIRED glib-2.0 gthread-2.0 vconf capi-appfw-app-control libtzplatform-config)
+
+FOREACH(flag ${test_app_pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
+
+ADD_EXECUTABLE(notification-test-app ${TEST-APP-SRCS})
+TARGET_LINK_LIBRARIES(notification-test-app ${test_app_pkgs_LDFLAGS} notification)
+
+#INSTALL(TARGETS notification-test-app DESTINATION bin)
+
diff --git a/notification/test-app/main.c b/notification/test-app/main.c
new file mode 100644
index 0000000..c6034ef
--- /dev/null
+++ b/notification/test-app/main.c
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2015 - 2016 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.
+ */
+
+/* common header */
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+/* open header */
+#include <glib.h>
+
+/* notification header */
+#include <notification.h>
+#include <notification_internal.h>
+#include <notification_ongoing_flag.h>
+#include <notification_status.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include <notification_list.h>
+#include <notification_text_domain.h>
+#include <tzplatform_config.h>
+
+#define PATH_FMT_RO_APP_ROOT tzplatform_getenv(TZ_SYS_RO_APP)
+#define TIZEN_PATH_MAX 1024
+
+/*-----------------------------------------------------------------------------------------*/
+/* types */
+typedef enum testapp_menu_type {
+ TESTAPP_MENU_TYPE_MAIN_MENU = 1,
+ TESTAPP_MENU_TYPE_BASIC_TEST_MENU = 2,
+ TESTAPP_MENU_TYPE_SETTING_TEST_MENU = 3
+} testapp_menu_type_e;
+
+/*-----------------------------------------------------------------------------------------*/
+/* function prototypes */
+static void testapp_system_signal_handler(int signal_number);
+void testapp_show_prompt(testapp_menu_type_e menu);
+
+/*-----------------------------------------------------------------------------------------*/
+/* implementation */
+void testapp_print(char *fmt, ...)
+{
+ va_list args = {0};
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ fflush(stdout);
+}
+
+static gboolean testapp_initialize_testing()
+{
+ struct timeval tv_1, tv_2;
+ int interval;
+
+ /* register signal handler */
+ if (signal(SIGINT, testapp_system_signal_handler) == SIG_ERR) {
+ testapp_print("register signal handler fail\n");
+ return FALSE;
+ }
+
+ if (signal(SIGQUIT, testapp_system_signal_handler) == SIG_ERR) {
+ testapp_print("register signal handler fail\n");
+ return FALSE;
+ }
+
+ if (signal(SIGTSTP, testapp_system_signal_handler) == SIG_ERR) {
+ testapp_print("register signal handler fail\n");
+ return FALSE;
+ }
+
+ if (signal(SIGTERM, testapp_system_signal_handler) == SIG_ERR) {
+ testapp_print("register signal handler fail\n");
+ return FALSE;
+ }
+
+
+ gettimeofday(&tv_1, NULL);
+
+ /* TODO : initializing notification */
+
+ gettimeofday(&tv_2, NULL);
+ interval = tv_2.tv_usec - tv_1.tv_usec;
+ testapp_print("\t Initializing Proceed time %d us\n", interval);
+
+
+ return TRUE;
+}
+
+static gboolean testapp_finalize_testing()
+{
+ /* TODO : finalizing notification */
+
+ return TRUE;
+}
+
+static void testapp_system_signal_handler(int signal_number)
+{
+ testapp_print("signal:%d\n", signal_number);
+ switch (signal_number) {
+ case SIGQUIT:
+ case SIGINT:
+ case SIGTSTP:
+ case SIGTERM:
+ testapp_finalize_testing();
+ break;
+
+ default:
+ testapp_print("unhandled signal:%d\n", signal_number);
+ break;
+ }
+ exit(0);
+}
+
+
+
+
+void testapp_show_menu(testapp_menu_type_e menu)
+{
+ switch (menu) {
+ case TESTAPP_MENU_TYPE_MAIN_MENU:
+ testapp_print("==========================================\n");
+ testapp_print(" Notification test application \n");
+ testapp_print("==========================================\n");
+ testapp_print("1. Basic Test\n");
+ testapp_print("2. Setting Test\n");
+ testapp_print("0. Exit \n");
+ testapp_print("------------------------------------------\n");
+ break;
+ case TESTAPP_MENU_TYPE_BASIC_TEST_MENU:
+ testapp_print("==========================================\n");
+ testapp_print(" Basic test menu \n");
+ testapp_print("==========================================\n");
+ testapp_print(" 1. Post a simple notification\n");
+ testapp_print(" 2. Post simple notifications repeatedly\n");
+ testapp_print(" 3. Post a notification on indicator\n");
+ testapp_print(" 4. Post status status message\n");
+ testapp_print(" 5. Delete all notification\n");
+ testapp_print(" 6. Post a heads notification with a button\n");
+ testapp_print(" 7. Post a notification with domain text\n");
+ testapp_print(" 8. Load by tag\n");
+ testapp_print(" 9. Get list\n");
+ testapp_print(" 10. Post noti to 5002 \n");
+ testapp_print("------------------------------------------\n");
+ break;
+ case TESTAPP_MENU_TYPE_SETTING_TEST_MENU:
+ testapp_print("==========================================\n");
+ testapp_print(" Setting test menu \n");
+ testapp_print("==========================================\n");
+ testapp_print(" 1. Get setting list\n");
+ testapp_print(" 2. Update setting\n");
+ testapp_print(" 3. Update system setting\n");
+ testapp_print(" 4. Refresh setting table\n");
+ testapp_print("------------------------------------------\n");
+ break;
+ default:
+ break;
+ }
+}
+/* Common { ------------------------------------------------------------------*/
+
+
+static int testapp_add_a_notification_to_bob()
+{
+ notification_h noti_handle = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_handle = notification_create(NOTIFICATION_TYPE_NOTI);
+
+ if (noti_handle == NULL) {
+ testapp_print("notification_create failed");
+ goto FINISH_OFF;
+ }
+
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, "I'm Title", "TITLE", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, "I'm Content", "CONTENT", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, "3", "3", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_1, "I'm Info 1", "INFO_1", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_SUB_1, "I'm Info Sub 1", "INFO_SUB_1", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_2, "I'm Info 2", "INFO_2", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_SUB_2, "I'm Info Sub 2", "INFO_SUB_2", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_3, "I'm Info 3", "INFO_3", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_SUB_3, "I'm Info Sub 3", "INFO_SUB_3", NOTIFICATION_VARIABLE_TYPE_NONE);
+
+ noti_err = notification_set_ongoing_flag(noti_handle, true);
+ noti_err = notification_set_auto_remove(noti_handle, false);
+
+ noti_err = notification_set_display_applist(noti_handle, NOTIFICATION_DISPLAY_APP_INDICATOR | NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY | NOTIFICATION_DISPLAY_APP_TICKER);
+
+ noti_err = notification_post_for_uid(noti_handle, 5002);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_post failed[%d]", noti_err);
+ goto FINISH_OFF;
+ }
+
+FINISH_OFF:
+ if (noti_handle)
+ notification_free(noti_handle);
+
+ return noti_err;
+}
+
+
+static int testapp_add_a_notification()
+{
+ notification_h noti_handle = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_handle = notification_create(NOTIFICATION_TYPE_NOTI);
+
+ if (noti_handle == NULL) {
+ testapp_print("notification_create failed");
+ goto FINISH_OFF;
+ }
+
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, "I'm Title", "TITLE", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, "I'm Content", "CONTENT", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, "3", "3", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_1, "I'm Info 1", "INFO_1", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_SUB_1, "I'm Info Sub 1", "INFO_SUB_1", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_2, "I'm Info 2", "INFO_2", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_SUB_2, "I'm Info Sub 2", "INFO_SUB_2", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_3, "I'm Info 3", "INFO_3", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_INFO_SUB_3, "I'm Info Sub 3", "INFO_SUB_3", NOTIFICATION_VARIABLE_TYPE_NONE);
+
+ noti_err = notification_set_ongoing_flag(noti_handle, true);
+ noti_err = notification_set_auto_remove(noti_handle, false);
+
+ noti_err = notification_set_display_applist(noti_handle, NOTIFICATION_DISPLAY_APP_INDICATOR | NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY | NOTIFICATION_DISPLAY_APP_TICKER);
+
+ noti_err = notification_post(noti_handle);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_post failed[%d]", noti_err);
+ goto FINISH_OFF;
+ }
+
+FINISH_OFF:
+ if (noti_handle)
+ notification_free(noti_handle);
+
+ return noti_err;
+}
+
+/* Common } ------------------------------------------------------------------ */
+
+/* Basic Test { -------------------------------------------------------------- */
+static int testapp_test_post_notification()
+{
+ int err = NOTIFICATION_ERROR_NONE;
+
+ if ((err = testapp_add_a_notification()) != NOTIFICATION_ERROR_NONE) {
+ testapp_print("testapp_add_a_notification failed[%d]", err);
+ goto FINISH_OFF;
+ }
+
+
+FINISH_OFF:
+
+ return err;
+}
+
+static int testapp_test_post_notifications()
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ int repeat_count = 0;
+ int i = 0;
+
+ testapp_print("Input count : ");
+
+ if (0 >= scanf("%d", &repeat_count)) {
+ testapp_print("Invalid input");
+ goto FINISH_OFF;
+ }
+
+ for (i = 0; i < repeat_count; i++) {
+ if ((err = testapp_add_a_notification()) != NOTIFICATION_ERROR_NONE) {
+ testapp_print("testapp_add_a_notification failed[%d]", err);
+ goto FINISH_OFF;
+ }
+ }
+
+FINISH_OFF:
+ return err;
+}
+
+static int testapp_test_post_notification_on_indicator()
+{
+ notification_h noti_handle = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ char image_path[TIZEN_PATH_MAX] = {0, };
+
+ noti_handle = notification_create(NOTIFICATION_TYPE_ONGOING);
+
+ if (noti_handle == NULL) {
+ testapp_print("notification_create failed");
+ goto FINISH_OFF;
+ }
+
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, "I'm Title", "TITLE", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, "I'm Content", "CONTENT", NOTIFICATION_VARIABLE_TYPE_NONE);
+
+ snprintf(image_path, TIZEN_PATH_MAX, "%s/org.tizen.indicator/res/resource/icons/Notify/b03_notify_more.png", PATH_FMT_RO_APP_ROOT);
+ noti_err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, image_path);
+
+ noti_err = notification_set_display_applist(noti_handle, NOTIFICATION_DISPLAY_APP_TICKER | NOTIFICATION_DISPLAY_APP_INDICATOR);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_set_display_applist failed[%d]", noti_err);
+ goto FINISH_OFF;
+ }
+
+ noti_err = notification_post(noti_handle);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_post failed[%d]", noti_err);
+ goto FINISH_OFF;
+ }
+
+FINISH_OFF:
+ if (noti_handle)
+ notification_free(noti_handle);
+
+ return noti_err;
+}
+
+static int testapp_test_post_status_message()
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+
+ noti_err = notification_status_message_post("This is only a test");
+
+ if (noti_err != NOTIFICATION_ERROR_NONE)
+ testapp_print("notification_status_message_post failed[%d]", noti_err);
+
+ return noti_err;
+}
+
+static int testapp_test_delete_all_notifications()
+{
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ //noti_err = notification_delete_all(NOTIFICATION_TYPE_NOTI);
+ noti_err = notification_delete_by_display_applist(NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
+
+ testapp_print("notification_delete_all returns[%d]", noti_err);
+
+ return noti_err;
+}
+
+static int testapp_test_post_heads_up_notification_with_button()
+{
+ notification_h noti = NULL;
+ int err = NOTIFICATION_ERROR_NONE;
+ int app_control_err = APP_CONTROL_ERROR_NONE;
+ app_control_h app_control = NULL;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ testapp_print("notification_create failed");
+ return get_last_result();
+ }
+
+ err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
+ "I'm Title", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set title failed[%d]\n", err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
+ "I'm Content", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set content failed[%d]\n", err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_set_display_applist(noti,
+ NOTIFICATION_DISPLAY_APP_ACTIVE |
+ NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set display_applist failed[%d]\n", err);
+ goto FINISH_OFF;
+ }
+
+ app_control_err = app_control_create(&app_control);
+ if (app_control_err != APP_CONTROL_ERROR_NONE) {
+ testapp_print("app_control_create failed[%d]\n", app_control_err);
+ goto FINISH_OFF;
+ }
+
+ app_control_err = app_control_set_app_id(app_control, "org.tizen.quickpanel");
+ if (app_control_err != APP_CONTROL_ERROR_NONE) {
+ testapp_print("app_control_set_app_id failed[%d]\n", app_control_err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_set_event_handler(noti,
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1, app_control);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set event_handler failed[%d]", err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_BUTTON_1,
+ "reply", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set text failed[%d]\n", err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_set_event_handler(noti,
+ NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON,
+ app_control);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set event_handler failed[%d]", err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_set_text(noti,
+ NOTIFICATION_TEXT_TYPE_TEXT_INPUT_BUTTON,
+ "SEND", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set text failed[%d]\n", err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_set_text(noti,
+ NOTIFICATION_TEXT_TYPE_TEXT_INPUT_PLACEHOLDER,
+ "input message", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set text failed[%d]\n", err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_set_text_input(noti, 160);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("set text_input failed[%d]\n", err);
+ goto FINISH_OFF;
+ }
+
+ err = notification_post(noti);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_post failed[%d]", err);
+ goto FINISH_OFF;
+ }
+
+FINISH_OFF:
+ if (app_control)
+ app_control_destroy(app_control);
+
+ if (noti)
+ notification_free(noti);
+
+ return err;
+}
+
+static int testapp_test_post_notification_with_domain_text()
+{
+ notification_h noti_handle = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ time_t result = time(NULL);
+ char tag[100] = { 0, };
+
+ noti_handle = notification_create(NOTIFICATION_TYPE_NOTI);
+
+ if (noti_handle == NULL) {
+ testapp_print("notification_create failed");
+ goto FINISH_OFF;
+ }
+
+ noti_err = notification_set_text_domain(noti_handle, "message", "/usr/apps/org.tizen.message/res/locale");
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_set_display_applist failed[%d]\n", noti_err);
+ goto FINISH_OFF;
+ }
+
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, "I'm Title", "IDS_MSGF_POP_NEW_MESSAGES", NOTIFICATION_VARIABLE_TYPE_NONE);
+ noti_err = notification_set_text(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, "I'm Content", "IDS_MSG_TPOP_MAXIMUM_MESSAGE_SIZE_HPS_EXCEEDED_RESIZING_ATTACHMENTS_ING",
+ NOTIFICATION_VARIABLE_TYPE_STRING, "200KB",
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+
+ noti_err = notification_set_display_applist(noti_handle, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_set_display_applist failed[%d]\n", noti_err);
+ goto FINISH_OFF;
+ }
+
+ snprintf(tag, 100, "%d", (int)result);
+
+ noti_err = notification_set_tag(noti_handle, tag);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_set_tag failed[%d]\n", noti_err);
+ goto FINISH_OFF;
+ }
+
+ noti_err = notification_post(noti_handle);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_post failed[%d]", noti_err);
+ goto FINISH_OFF;
+ }
+
+FINISH_OFF:
+
+
+ if (noti_handle)
+ notification_free(noti_handle);
+
+ return noti_err;
+}
+
+static int testapp_test_load_by_tag()
+{
+ notification_h noti_handle = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+
+ noti_handle = notification_load_by_tag("hfe4fif#$sd$ew");
+
+ if (noti_handle == NULL) {
+ testapp_print("notification_load_by_tag failed");
+ goto FINISH_OFF;
+ }
+
+FINISH_OFF:
+ if (noti_handle)
+ notification_free(noti_handle);
+
+ return noti_err;
+}
+
+static int testapp_test_get_list()
+{
+ notification_h noti_handle = NULL;
+ notification_list_h noti_list_handle = NULL;
+ notification_list_h noti_list_cursor_handle = NULL;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int priv_id;
+ int group_id;
+ int type;
+ bool ongoing_flag;
+ bool auto_remove;
+
+ noti_err = notification_get_list(NOTIFICATION_TYPE_NONE, -1, &noti_list_handle);
+
+ if (noti_err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_get_detail_list failed[%d]\n", noti_err);
+ goto FINISH_OFF;
+ }
+
+ noti_list_cursor_handle = notification_list_get_head(noti_list_handle);
+
+ while (noti_list_cursor_handle) {
+ noti_handle = notification_list_get_data(noti_list_cursor_handle);
+ notification_get_id(noti_handle, &group_id, &priv_id);
+ notification_get_type(noti_handle, &type);
+ notification_get_ongoing_flag(noti_handle, &ongoing_flag);
+ notification_get_auto_remove(noti_handle, &auto_remove);
+
+ testapp_print("priv_id[%d] type[%d] ongoing_flag[%d] auto_remove[%d]\n", priv_id, type, ongoing_flag, auto_remove);
+ noti_list_cursor_handle = notification_list_get_next(noti_list_cursor_handle);
+ }
+
+
+FINISH_OFF:
+ if (noti_list_handle)
+ notification_free_list(noti_list_handle);
+
+ return noti_err;
+}
+
+static gboolean testapp_interpret_command_basic_test(int selected_number)
+{
+ gboolean go_to_loop = TRUE;
+
+ switch (selected_number) {
+ case 1:
+ testapp_test_post_notification();
+ break;
+
+ case 2:
+ testapp_test_post_notifications();
+ break;
+
+ case 3:
+ testapp_test_post_notification_on_indicator();
+ break;
+
+ case 4:
+ testapp_test_post_status_message();
+ break;
+
+ case 5:
+ testapp_test_delete_all_notifications();
+ break;
+
+ case 6:
+ testapp_test_post_heads_up_notification_with_button();
+ break;
+
+ case 7:
+ testapp_test_post_notification_with_domain_text();
+ break;
+
+ case 8:
+ testapp_test_load_by_tag();
+ break;
+
+ case 9:
+ testapp_test_get_list();
+ break;
+ case 10:
+ testapp_add_a_notification_to_bob();
+ break;
+
+ case 0:
+ go_to_loop = FALSE;
+ break;
+
+ default:
+ break;
+ }
+
+ return go_to_loop;
+
+}
+
+void testapp_notification_main()
+{
+ gboolean go_to_loop = TRUE;
+ int menu_number = 0;
+
+ while (go_to_loop) {
+ testapp_show_menu(TESTAPP_MENU_TYPE_BASIC_TEST_MENU);
+ testapp_show_prompt(TESTAPP_MENU_TYPE_BASIC_TEST_MENU);
+
+ if (0 >= scanf("%d", &menu_number))
+ testapp_print("Invalid input");
+
+ go_to_loop = testapp_interpret_command_basic_test(menu_number);
+ }
+}
+/* Basic Test } ---------------------------------------------------------------*/
+
+/* Setting Test } ---------------------------------------------------------------*/
+
+static int testapp_test_get_setting_list()
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ int i = 0;
+ int count = 0;
+ char *package_name = NULL;
+ char *appid = NULL;
+ bool allow_to_notify = false;
+ bool do_not_disturb_except = false;
+ int visibility_class = false;
+ bool pop_up_notification = false;
+ lock_screen_content_level_e level = 0;
+ notification_setting_h setting_array = NULL;
+ notification_setting_h tmp = NULL;
+
+ notification_setting_get_setting_array(&setting_array, &count);
+
+ testapp_print("count [%d]\n", count);
+
+ for (i = 0; i < count; i++) {
+ tmp = setting_array + i;
+ notification_setting_get_package_name(tmp, &package_name);
+ notification_setting_get_appid(tmp, &appid);
+ notification_setting_get_allow_to_notify(tmp, &allow_to_notify);
+ notification_setting_get_do_not_disturb_except(tmp, &do_not_disturb_except);
+ notification_setting_get_visibility_class(tmp, &visibility_class);
+ notification_setting_get_pop_up_notification(tmp, &pop_up_notification);
+ notification_setting_get_lock_screen_content(tmp, &level);
+ testapp_print("[%d] : package_name[%s], appid [%s], allow_to_notify[%d], do_not_disturb_except[%d] visibility_class[%d] pop_up_notification[%d] level[%d]\n",
+ i, package_name, appid, allow_to_notify, do_not_disturb_except, visibility_class, pop_up_notification, level);
+ free(package_name);
+ free(appid);
+ }
+
+ notification_setting_free_notification(setting_array);
+
+ return err;
+}
+
+static int testapp_test_update_setting()
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ notification_setting_h setting = NULL;
+
+ err = notification_setting_get_setting_by_package_name("org.tizen.browser", &setting);
+
+ if (err != NOTIFICATION_ERROR_NONE || setting == NULL) {
+ testapp_print("notification_setting_get_setting_by_package_name failed [%d]", err);
+ } else {
+ notification_setting_set_allow_to_notify(setting, 0);
+ notification_setting_update_setting(setting);
+ }
+
+ if (setting)
+ notification_setting_free_notification(setting);
+
+ return err;
+}
+
+static int testapp_test_update_system_setting()
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ bool do_not_disturb;
+ int visibility_class;
+ bool dnd_schedule_enabled;
+ lock_screen_content_level_e lock_screen_content_level = SHOW_ALL_CONTENT;
+ notification_system_setting_h system_setting = NULL;
+ dnd_allow_exception_type_e dnd_allow_exception_type = NOTIFICATION_DND_ALLOWED_CALLS;
+ int dnd_allowed_calls_value;
+
+ err = notification_system_setting_load_system_setting(&system_setting);
+
+ if (err != NOTIFICATION_ERROR_NONE || system_setting == NULL) {
+ testapp_print("notification_system_setting_load_system_setting failed [%d]\n", err);
+ goto out;
+ }
+
+ notification_system_setting_get_do_not_disturb(system_setting, &do_not_disturb);
+ testapp_print("do_not_disturb [%d]\n", do_not_disturb);
+ do_not_disturb = !do_not_disturb;
+ notification_system_setting_set_do_not_disturb(system_setting, do_not_disturb);
+
+ notification_system_setting_get_visibility_class(system_setting, &visibility_class);
+ testapp_print("visibility_class [%d]\n", visibility_class);
+ visibility_class = !visibility_class;
+ notification_system_setting_set_visibility_class(system_setting, visibility_class);
+
+ notification_system_setting_dnd_schedule_get_enabled(system_setting, &dnd_schedule_enabled);
+ testapp_print("dnd_schedule_enabled [%d]\n", dnd_schedule_enabled);
+ dnd_schedule_enabled = !dnd_schedule_enabled;
+ notification_system_setting_dnd_schedule_set_enabled(system_setting, dnd_schedule_enabled);
+
+ notification_system_setting_get_lock_screen_content(system_setting, &lock_screen_content_level);
+ testapp_print("lock_screen_content_level [%d]\n", lock_screen_content_level);
+ lock_screen_content_level = !lock_screen_content_level;
+ notification_system_setting_set_lock_screen_content(system_setting, lock_screen_content_level);
+
+ notification_system_setting_get_dnd_allow_exceptions(system_setting, dnd_allow_exception_type, &dnd_allowed_calls_value);
+ testapp_print("dnd_allowed_calls_value [%d]\n", dnd_allowed_calls_value);
+ dnd_allowed_calls_value = !dnd_allowed_calls_value;
+ notification_system_setting_set_dnd_allow_exceptions(system_setting, dnd_allow_exception_type, dnd_allowed_calls_value);
+
+ err = notification_system_setting_update_system_setting(system_setting);
+ if (err != NOTIFICATION_ERROR_NONE || system_setting == NULL) {
+ testapp_print("notification_system_setting_update_system_setting failed [%d]\n", err);
+ goto out;
+ }
+
+out:
+ if (system_setting)
+ notification_system_setting_free_system_setting(system_setting);
+
+ return err;
+}
+
+static int testapp_test_refresh_setting_table()
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ err = notification_setting_refresh_setting_table(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
+
+ if (err != NOTIFICATION_ERROR_NONE) {
+ testapp_print("notification_setting_refresh_setting_table failed [%d]\n", err);
+ goto out;
+ }
+
+out:
+
+ return err;
+}
+
+static gboolean testapp_interpret_command_setting_test(int selected_number)
+{
+ gboolean go_to_loop = TRUE;
+
+ switch (selected_number) {
+ case 1:
+ testapp_test_get_setting_list();
+ break;
+
+ case 2:
+ testapp_test_update_setting();
+ break;
+
+ case 3:
+ testapp_test_update_system_setting();
+ break;
+
+ case 4:
+ testapp_test_refresh_setting_table();
+ break;
+
+ case 0:
+ go_to_loop = FALSE;
+ break;
+
+ default:
+ break;
+ }
+
+ return go_to_loop;
+
+}
+
+void testapp_setting_main()
+{
+ gboolean go_to_loop = TRUE;
+ int menu_number = 0;
+
+ while (go_to_loop) {
+ testapp_show_menu(TESTAPP_MENU_TYPE_SETTING_TEST_MENU);
+ testapp_show_prompt(TESTAPP_MENU_TYPE_SETTING_TEST_MENU);
+
+ if (0 >= scanf("%d", &menu_number))
+ testapp_print("Invalid input");
+
+ go_to_loop = testapp_interpret_command_setting_test(menu_number);
+ }
+}
+/* Setting Test } ---------------------------------------------------------------*/
+
+/* Main { ---------------------------------------------------------------------*/
+static gboolean testapp_interpret_command(int menu_number)
+{
+ gboolean go_to_loop = TRUE;
+
+ switch (menu_number) {
+ case 1:
+ testapp_notification_main();
+ break;
+
+ case 2:
+ testapp_setting_main();
+ break;
+
+ case 0:
+ go_to_loop = FALSE;
+ break;
+
+ default:
+ break;
+ }
+
+ return go_to_loop;
+}
+
+void testapp_show_prompt(testapp_menu_type_e menu)
+{
+ switch (menu) {
+ case TESTAPP_MENU_TYPE_MAIN_MENU:
+ testapp_print("[MAIN]# ");
+ break;
+
+ case TESTAPP_MENU_TYPE_BASIC_TEST_MENU:
+ testapp_print("[BASIC_TEST]# ");
+ break;
+
+ case TESTAPP_MENU_TYPE_SETTING_TEST_MENU:
+ testapp_print("[SETTING_TEST]# ");
+ break;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ gboolean go_to_loop = TRUE;
+ int menu_number = 0;
+
+ if (testapp_initialize_testing() == FALSE) {
+ testapp_print("Initializing failed.\n");
+ return 1;
+ }
+
+ while (go_to_loop) {
+ testapp_show_menu(TESTAPP_MENU_TYPE_MAIN_MENU);
+ testapp_show_prompt(TESTAPP_MENU_TYPE_MAIN_MENU);
+ if (0 >= scanf("%d", &menu_number))
+ testapp_print("Invalid input");
+ go_to_loop = testapp_interpret_command(menu_number);
+ }
+
+ testapp_finalize_testing();
+
+ return 0;
+}
+/* Main } ---------------------------------------------------------------------*/
+
diff --git a/packaging/notification.spec b/packaging/notification.spec
index 8803c75..02252ac 100755
--- a/packaging/notification.spec
+++ b/packaging/notification.spec
@@ -1,29 +1,38 @@
+%bcond_with wayland
Name: notification
-Summary: notification library
-Version: 0.1.1
+Summary: Notification library
+Version: 0.5.1
Release: 1
-Group: TBD
+Group: Applications/Core Applications
License: Apache-2.0
Source0: %{name}-%{version}.tar.gz
BuildRequires: pkgconfig(sqlite3)
-BuildRequires: pkgconfig(db-util)
-BuildRequires: pkgconfig(heynoti)
BuildRequires: pkgconfig(vconf)
BuildRequires: pkgconfig(bundle)
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(dlog)
-BuildRequires: pkgconfig(ail)
BuildRequires: pkgconfig(aul)
-BuildRequires: pkgconfig(appsvc)
-BuildRequires: pkgconfig(dbus-glib-1)
+BuildRequires: pkgconfig(capi-appfw-app-control)
+BuildRequires: pkgconfig(capi-appfw-app-common)
+BuildRequires: pkgconfig(capi-appfw-package-manager)
+BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(iniparser)
+BuildRequires: pkgconfig(security-manager)
+BuildRequires: pkgconfig(libsmack)
+BuildRequires: pkgconfig(gmock)
+BuildRequires: pkgconfig(uuid)
BuildRequires: cmake
Requires(post): /sbin/ldconfig
-Requires(post): /usr/bin/sqlite3
-requires(postun): /sbin/ldconfig
+Requires(post): %{TZ_SYS_BIN}/sqlite3
+Requires(postun): /sbin/ldconfig
+
+%define upgrade_script_path /usr/share/upgrade/scripts
%description
-Notificaiton library.
+Client/Server library for sending notifications.
%prep
%setup -q
@@ -34,16 +43,26 @@ Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
%description devel
-Notificaiton library (devel).
+Development files needed to build software that needs to system a system notification.
%build
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
export LDFLAGS+="-Wl,--rpath=%{_prefix}/lib -Wl,--as-needed"
-LDFLAGS="$LDFLAGS" cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+LDFLAGS="$LDFLAGS"
+%cmake . \
+ -DCMAKE_INSTALL_PREFIX=%{_prefix} \
+ -DMAJORVER=${MAJORVER} -DFULLVER=%{version}
make %{?jobs:-j%jobs}
%install
rm -rf %{buildroot}
+
%make_install
+mkdir -p %{buildroot}%{upgrade_script_path}
+cp -f scripts/505.notification_upgrade.sh %{buildroot}%{upgrade_script_path}
+
+%check
+ctest --output-on-failure %{?_smp_mflags}
%clean
rm -rf %{buildroot}
@@ -51,101 +70,93 @@ rm -rf %{buildroot}
%post
/sbin/ldconfig
-if [ ! -d /opt/dbspace ]
-then
- mkdir /opt/dbspace
-fi
-
-if [ ! -f /opt/dbspace/.notification.db ]
+if [ ! -d %{TZ_SYS_DB} ]
then
- sqlite3 /opt/dbspace/.notification.db 'PRAGMA journal_mode = PERSIST;
- create table if not exists noti_list (
- type INTEGER NOT NULL,
- caller_pkgname TEXT NOT NULL,
- launch_pkgname TEXT,
- image_path TEXT,
- group_id INTEGER default 0,
- internal_group_id INTEGER default 0,
- priv_id INTERGER NOT NULL,
- title_key TEXT,
- b_text TEXT,
- b_key TEXT,
- b_format_args TEXT,
- num_format_args INTEGER default 0,
- text_domain TEXT,
- text_dir TEXT,
- time INTEGER default 0,
- insert_time INTEGER default 0,
- args TEXT,
- group_args TEXT,
- b_execute_option TEXT,
- b_service_responding TEXT,
- b_service_single_launch TEXT,
- b_service_multi_launch TEXT,
- sound_type INTEGER default 0,
- sound_path TEXT,
- vibration_type INTEGER default 0,
- vibration_path TEXT,
- flags_for_property INTEGER default 0,
- flag_simmode INTEGER default 0,
- display_applist INTEGER,
- progress_size DOUBLE default 0,
- progress_percentage DOUBLE default 0,
- rowid INTEGER PRIMARY KEY AUTOINCREMENT,
- UNIQUE (caller_pkgname, priv_id)
- );
- create table if not exists noti_group_data (
- caller_pkgname TEXT NOT NULL,
- group_id INTEGER default 0,
- badge INTEGER default 0,
- title TEXT,
- content TEXT,
- loc_title TEXT,
- loc_content TEXT,
- count_display_title INTEGER,
- count_display_content INTEGER,
- rowid INTEGER PRIMARY KEY AUTOINCREMENT,
- UNIQUE (caller_pkgname, group_id)
- );
- create table if not exists ongoing_list (
- caller_pkgname TEXT NOT NULL,
- launch_pkgname TEXT,
- icon_path TEXT,
- group_id INTEGER default 0,
- internal_group_id INTEGER default 0,
- priv_id INTERGER NOT NULL,
- title TEXT,
- content TEXT,
- default_content TEXT,
- loc_title TEXT,
- loc_content TEXT,
- loc_default_content TEXT,
- text_domain TEXT,
- text_dir TEXT,
- args TEXT,
- group_args TEXT,
- flag INTEGER default 0,
- progress_size DOUBLE default 0,
- progress_percentage DOUBLE default 0,
- rowid INTEGER PRIMARY KEY AUTOINCREMENT,
- UNIQUE (caller_pkgname, priv_id)
- );
- '
+ mkdir %{TZ_SYS_DB}
fi
-chown :5000 /opt/dbspace/.notification.db
-chown :5000 /opt/dbspace/.notification.db-journal
-chmod 660 /opt/dbspace/.notification.db
-chmod 660 /opt/dbspace/.notification.db-journal
-
%postun -p /sbin/ldconfig
%files
+%manifest notification.manifest
%defattr(-,root,root,-)
-%{_libdir}/libnotification.so*
+%{_libdir}/libnotification.so.*
+%license LICENSE
+%attr(755,root,root) %{_sysconfdir}/gumd/useradd.d/11_notification-add.post
+%{_bindir}/notification_init
+%{upgrade_script_path}/505.notification_upgrade.sh
+#%{_bindir}/notification-test-app
%files devel
%defattr(-,root,root,-)
-%{_includedir}/notification/*.h
+%{_includedir}/notification/notification.h
+%{_includedir}/notification/notification_db.h
+%{_includedir}/notification/notification_internal.h
+%{_includedir}/notification/notification_error.h
+%{_includedir}/notification/notification_type.h
+%{_includedir}/notification/notification_list.h
+%{_includedir}/notification/notification_ongoing.h
+%{_includedir}/notification/notification_ongoing_flag.h
+%{_includedir}/notification/notification_text_domain.h
+%{_includedir}/notification/notification_status.h
+%{_includedir}/notification/notification_status_internal.h
+%{_includedir}/notification/notification_setting.h
+%{_includedir}/notification/notification_setting_internal.h
+%{_includedir}/notification/notification_ipc.h
+%{_includedir}/notification/notification_noti.h
+%{_includedir}/notification/notification_setting_service.h
+%{_includedir}/notification/notification_viewer.h
+%{_includedir}/notification/notification_shared_file.h
+%{_includedir}/notification/notification_type_internal.h
%{_libdir}/pkgconfig/notification.pc
+%{_libdir}/libnotification.so
+
+
+
+#################################################
+# notification-ex
+#################################################
+%package -n %{name}-ex
+Summary: Library for developing the notification
+Group: Applications/Application Utility
+License: Apache-2.0
+
+%description -n %{name}-ex
+Provide APIs to develop the notification.
+
+%package -n %{name}-ex-devel
+Summary: Notification development library (dev)
+Group: Development/Libraries
+Requires: %{name}-ex
+
+%description -n %{name}-ex-devel
+Header & package configuration files to support development of the notification.
+
+%post -n %{name}-ex
+/sbin/ldconfig
+
+%postun -n %{name}-ex -p /sbin/ldconfig
+
+%files -n %{name}-ex
+%manifest %{name}-ex.manifest
+%attr(0644,root,root) %{_libdir}/libnotification-ex.so.*
+%license LICENSE
+
+%files -n %{name}-ex-devel
+%{_includedir}/notification-ex/*.h
+%{_libdir}/pkgconfig/notification-ex.pc
+%attr(0644,root,root) %{_libdir}/libnotification-ex.so
+
+
+#################################################
+# notification-ex_unittests
+#################################################
+%package -n notification-ex_unittests
+Summary: GTest for notification-ex
+Group: Development/Libraries
+
+%description -n notification-ex_unittests
+GTest for notification-ex
+%files -n notification-ex_unittests
+%{_bindir}/notification-ex_unittests
diff --git a/scripts/505.notification_upgrade.sh b/scripts/505.notification_upgrade.sh
new file mode 100644
index 0000000..90590cd
--- /dev/null
+++ b/scripts/505.notification_upgrade.sh
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#------------------------------------------#
+# notification patch for upgrade (3.0 -> 4.0) #
+#------------------------------------------#
+
+# Macro
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+
+DB_DIR=/opt/dbspace
+DB_NOTIFICATION=$DB_DIR/.notification.db
+
+sqlite3 $DB_NOTIFICATION << EOF
+
+DROP TABLE IF EXISTS notification_setting_temp;
+CREATE TABLE notification_setting_temp (
+ uid INTEGER,
+ package_name TEXT NOT NULL,
+ app_id TEXT NOT NULL,
+ allow_to_notify INTEGER DEFAULT 1,
+ do_not_disturb_except INTEGER DEFAULT 0,
+ visibility_class INTEGER DEFAULT 0,
+ pop_up_notification INTEGER DEFAULT 1,
+ lock_screen_content_level INTEGER DEFAULT 0,
+ app_disabled INTEGER DEFAULT 0,
+ UNIQUE (uid, package_name, app_id)
+);
+INSERT INTO notification_setting_temp (uid, package_name, app_id, allow_to_notify, do_not_disturb_except, visibility_class, pop_up_notification, lock_screen_content_level, app_disabled) \
+SELECT uid, package_name, appid, allow_to_notify, do_not_disturb_except, visibility_class, pop_up_notification, lock_screen_content_level, app_disabled FROM notification_setting;
+DROP TABLE notification_setting;
+ALTER TABLE notification_setting_temp RENAME TO notification_setting;
+
+
+DROP TABLE IF EXISTS noti_list_temp;
+CREATE TABLE noti_list_temp (
+ type INTEGER NOT NULL,
+ layout INTEGER NOT NULL default 0,
+ pkg_id TEXT NOT NULL,
+ caller_app_id TEXT NOT NULL,
+ launch_app_id TEXT,
+ app_label TEXT,
+ image_path TEXT,
+ priv_image_path TEXT,
+ group_id INTEGER default 0,
+ internal_group_id INTEGER default 0,
+ priv_id INTEGER PRIMARY KEY AUTOINCREMENT,
+ title_key TEXT,
+ b_text TEXT,
+ b_key TEXT,
+ tag TEXT,
+ b_format_args TEXT,
+ num_format_args INTEGER default 0,
+ text_domain TEXT,
+ text_dir TEXT,
+ time INTEGER default 0,
+ insert_time INTEGER default 0,
+ args TEXT,
+ group_args TEXT,
+ b_execute_option TEXT,
+ b_service_responding TEXT,
+ b_service_single_launch TEXT,
+ b_service_multi_launch TEXT,
+ b_event_handler_click_on_button_1 TEXT,
+ b_event_handler_click_on_button_2 TEXT,
+ b_event_handler_click_on_button_3 TEXT,
+ b_event_handler_click_on_button_4 TEXT,
+ b_event_handler_click_on_button_5 TEXT,
+ b_event_handler_click_on_button_6 TEXT,
+ b_event_handler_click_on_icon TEXT,
+ b_event_handler_click_on_thumbnail TEXT,
+ b_event_handler_click_on_text_input_button TEXT,
+ sound_type INTEGER default 0,
+ sound_path TEXT,
+ priv_sound_path TEXT,
+ vibration_type INTEGER default 0,
+ vibration_path TEXT,
+ priv_vibration_path TEXT,
+ led_operation INTEGER default 0,
+ led_argb INTEGER default 0,
+ led_on_ms INTEGER default -1,
+ led_off_ms INTEGER default -1,
+ flags_for_property INTEGER default 0,
+ flag_simmode INTEGER default 0,
+ display_applist INTEGER,
+ progress_size DOUBLE default 0,
+ progress_percentage DOUBLE default 0,
+ ongoing_flag INTEGER default 0,
+ ongoing_value_type INTEGER default 0,
+ ongoing_current INTEGER default 0,
+ ongoing_duration INTEGER default 0,
+ auto_remove INTEGER default 1,
+ default_button_index INTEGER default 0,
+ hide_timeout INTEGER default 0,
+ delete_timeout INTEGER default 0,
+ text_input_max_length INTEGER default 0,
+ event_flag INTEGER default 0,
+ extension_image_size INTEGER default 0,
+ uid INTEGER
+);
+INSERT INTO noti_list_temp (type, layout, caller_app_id, launch_app_id, image_path, group_id, internal_group_id, priv_id, title_key, b_text, b_key, tag, b_format_args, num_format_args, text_domain, text_dir, time, insert_time, args, group_args, b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, b_event_handler_click_on_button_1, b_event_handler_click_on_button_2, b_event_handler_click_on_button_3, b_event_handler_click_on_button_4, b_event_handler_click_on_button_5, b_event_handler_click_on_button_6, b_event_handler_click_on_icon, b_event_handler_click_on_thumbnail, b_event_handler_click_on_text_input_button, sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, flags_for_property, flag_simmode, display_applist, progress_size, progress_percentage, ongoing_flag, ongoing_value_type, ongoing_current, ongoing_duration, auto_remove, default_button_index, hide_timeout, text_input_max_length, event_flag, uid, pkg_id) \
+SELECT type, layout, caller_pkgname, launch_pkgname, image_path, group_id, internal_group_id, priv_id, title_key, b_text, b_key, tag, b_format_args, num_format_args, text_domain, text_dir, time, insert_time, args, group_args, b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, b_event_handler_click_on_button_1, b_event_handler_click_on_button_2, b_event_handler_click_on_button_3, b_event_handler_click_on_button_4, b_event_handler_click_on_button_5, b_event_handler_click_on_button_6, b_event_handler_click_on_icon, b_event_handler_click_on_thumbnail, b_event_handler_click_on_text_input_button, sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, flags_for_property, flag_simmode, display_applist, progress_size, progress_percentage, ongoing_flag, ongoing_value_type, ongoing_current, ongoing_duration, auto_remove, default_button_index, timeout, text_input_max_length, event_flag, nl.uid, COALESCE(package_name, caller_pkgname) FROM noti_list nl LEFT OUTER JOIN notification_setting as ns ON nl.caller_pkgname=ns.app_id;
+DROP TABLE noti_list;
+ALTER TABLE noti_list_temp RENAME TO noti_list;
+
+
+DROP TABLE IF EXISTS noti_group_data_temp;
+CREATE TABLE noti_group_data_temp (
+ caller_app_id TEXT NOT NULL,
+ group_id INTEGER default 0,
+ badge INTEGER default 0,
+ title TEXT,
+ content TEXT,
+ loc_title TEXT,
+ loc_content TEXT,
+ count_display_title INTEGER,
+ count_display_content INTEGER,
+ rowid INTEGER PRIMARY KEY AUTOINCREMENT,
+ UNIQUE (caller_app_id, group_id)
+);
+INSERT INTO noti_group_data_temp (caller_app_id, group_id, badge, title, content, loc_title, loc_content, count_display_title, count_display_content, rowid) \
+SELECT caller_pkgname, group_id, badge, title, content, loc_title, loc_content, count_display_title, count_display_content, rowid FROM noti_group_data;
+DROP TABLE noti_group_data;
+ALTER TABLE noti_group_data_temp RENAME TO noti_group_data;
+
+
+DROP TABLE IF EXISTS ongoing_list_temp;
+CREATE TABLE ongoing_list_temp (
+ caller_app_id TEXT NOT NULL,
+ launch_app_id TEXT,
+ icon_path TEXT,
+ group_id INTEGER default 0,
+ internal_group_id INTEGER default 0,
+ priv_id INTERGER NOT NULL,
+ title TEXT,
+ content TEXT,
+ default_content TEXT,
+ loc_title TEXT,
+ loc_content TEXT,
+ loc_default_content TEXT,
+ text_domain TEXT,
+ text_dir TEXT,
+ args TEXT,
+ group_args TEXT,
+ flag INTEGER default 0,
+ progress_size DOUBLE default 0,
+ progress_percentage DOUBLE default 0,
+ rowid INTEGER PRIMARY KEY AUTOINCREMENT,
+ UNIQUE (caller_app_id, priv_id)
+);
+INSERT INTO ongoing_list_temp (caller_app_id, launch_app_id, icon_path, group_id, internal_group_id, priv_id, title, content, default_content, loc_title, loc_content, loc_default_content, text_domain, text_dir, args, group_args, flag, progress_size, progress_percentage, rowid) \
+SELECT caller_pkgname, launch_pkgname, icon_path, group_id, internal_group_id, priv_id, title, content, default_content, loc_title, loc_content, loc_default_content, text_domain, text_dir, args, group_args, flag, progress_size, progress_percentage, rowid FROM ongoing_list;
+DROP TABLE ongoing_list;
+ALTER TABLE ongoing_list_temp RENAME TO ongoing_list;
+
+
+DROP TABLE IF EXISTS noti_template_temp;
+CREATE TABLE noti_template_temp (
+ type INTEGER NOT NULL,
+ layout INTEGER NOT NULL default 0,
+ pkg_id TEXT NOT NULL,
+ caller_app_id TEXT NOT NULL,
+ launch_app_id TEXT,
+ app_label TEXT,
+ image_path TEXT,
+ priv_image_path TEXT,
+ group_id INTEGER default 0,
+ internal_group_id INTEGER default 0,
+ priv_id INTEGER PRIMARY KEY AUTOINCREMENT,
+ title_key TEXT,
+ b_text TEXT,
+ b_key TEXT,
+ tag TEXT,
+ b_format_args TEXT,
+ num_format_args INTEGER default 0,
+ text_domain TEXT,
+ text_dir TEXT,
+ time INTEGER default 0,
+ insert_time INTEGER default 0,
+ args TEXT,
+ group_args TEXT,
+ b_execute_option TEXT,
+ b_service_responding TEXT,
+ b_service_single_launch TEXT,
+ b_service_multi_launch TEXT,
+ b_event_handler_click_on_button_1 TEXT,
+ b_event_handler_click_on_button_2 TEXT,
+ b_event_handler_click_on_button_3 TEXT,
+ b_event_handler_click_on_button_4 TEXT,
+ b_event_handler_click_on_button_5 TEXT,
+ b_event_handler_click_on_button_6 TEXT,
+ b_event_handler_click_on_icon TEXT,
+ b_event_handler_click_on_thumbnail TEXT,
+ b_event_handler_click_on_text_input_button TEXT,
+ sound_type INTEGER default 0,
+ sound_path TEXT,
+ priv_sound_path TEXT,
+ vibration_type INTEGER default 0,
+ vibration_path TEXT,
+ priv_vibration_path TEXT,
+ led_operation INTEGER default 0,
+ led_argb INTEGER default 0,
+ led_on_ms INTEGER default -1,
+ led_off_ms INTEGER default -1,
+ flags_for_property INTEGER default 0,
+ flag_simmode INTEGER default 0,
+ display_applist INTEGER,
+ progress_size DOUBLE default 0,
+ progress_percentage DOUBLE default 0,
+ ongoing_flag INTEGER default 0,
+ ongoing_value_type INTEGER default 0,
+ ongoing_current INTEGER default 0,
+ ongoing_duration INTEGER default 0,
+ auto_remove INTEGER default 1,
+ default_button_index INTEGER default 0,
+ hide_timeout INTEGER default 0,
+ delete_timeout INTEGER default 0,
+ text_input_max_length INTEGER default 0,
+ event_flag INTEGER default 0,
+ extension_image_size INTEGER default 0,
+ uid INTEGER,
+ template_name TEXT,
+ UNIQUE (caller_app_id, template_name)
+);
+INSERT INTO noti_template_temp (type, layout, caller_app_id, launch_app_id, image_path, group_id, internal_group_id, priv_id, title_key, b_text, b_key, tag, b_format_args, num_format_args, text_domain, text_dir, time, insert_time, args, group_args, b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, b_event_handler_click_on_button_1, b_event_handler_click_on_button_2, b_event_handler_click_on_button_3, b_event_handler_click_on_button_4, b_event_handler_click_on_button_5, b_event_handler_click_on_button_6, b_event_handler_click_on_icon, b_event_handler_click_on_thumbnail, b_event_handler_click_on_text_input_button, sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, flags_for_property, flag_simmode, display_applist, progress_size, progress_percentage, ongoing_flag, ongoing_value_type, ongoing_current, ongoing_duration, auto_remove, default_button_index, hide_timeout, text_input_max_length, event_flag, uid, template_name, pkg_id) \
+SELECT type, layout, caller_pkgname, launch_pkgname, image_path, group_id, internal_group_id, priv_id, title_key, b_text, b_key, tag, b_format_args, num_format_args, text_domain, text_dir, time, insert_time, args, group_args, b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, b_event_handler_click_on_button_1, b_event_handler_click_on_button_2, b_event_handler_click_on_button_3, b_event_handler_click_on_button_4, b_event_handler_click_on_button_5, b_event_handler_click_on_button_6, b_event_handler_click_on_icon, b_event_handler_click_on_thumbnail, b_event_handler_click_on_text_input_button, sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, flags_for_property, flag_simmode, display_applist, progress_size, progress_percentage, ongoing_flag, ongoing_value_type, ongoing_current, ongoing_duration, auto_remove, default_button_index, timeout, text_input_max_length, event_flag, nl.uid, template_name, COALESCE(package_name, caller_pkgname) FROM noti_template as nl LEFT OUTER JOIN notification_setting as ns ON nl.caller_pkgname=ns.app_id;
+DROP TABLE noti_template;
+ALTER TABLE noti_template_temp RENAME TO noti_template;
+EOF
+
+chown app_fw:app_fw $DB_NOTIFICATION
+chown app_fw:app_fw $DB_NOTIFICATION-journal
+
+chsmack -a System $DB_NOTIFICATION
+chsmack -a System $DB_NOTIFICATION-journal
diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt
new file mode 100644
index 0000000..5af53a6
--- /dev/null
+++ b/unittest/CMakeLists.txt
@@ -0,0 +1,42 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(notification-ex_unittests CXX)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(notification-ex_unittests REQUIRED
+ dlog
+ gmock
+ capi-appfw-app-control
+ glib-2.0
+ aul
+)
+
+FOREACH(flag ${notification-ex_unittests_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../notification-ex)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../unittest/mock)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../)
+
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/mock UNIT_TEST_SOURCES)
+AUX_SOURCE_DIRECTORY(src SOURCES)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../notification-ex NOTIFICATION_EX_SOURCES)
+ADD_EXECUTABLE(${PROJECT_NAME}
+ ${SOURCES}
+ ${NOTIFICATION_EX_SOURCES}
+ ${UNIT_TEST_SOURCES}
+)
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${notification-ex_unittests_LDFLAGS}
+ ${pkgs_LDFLAGS}
+ ${pkgs_LIBRARIES}
+ gmock
+ notification-ex
+)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/)
diff --git a/unittest/mock/app_common.h b/unittest/mock/app_common.h
new file mode 100644
index 0000000..69f440c
--- /dev/null
+++ b/unittest/mock/app_common.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef MOCK_APP_COMMON_H_
+#define MOCK_APP_COMMON_H_
+
+#include "mock.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ APP_ERROR_NONE = 0, /**< Successful */
+ APP_ERROR_INVALID_PARAMETER = -22, /**< Invalid parameter */
+ APP_ERROR_OUT_OF_MEMORY = -12, /**< Out of memory */
+ APP_ERROR_INVALID_CONTEXT = -0x01100000 | 0x01, /**< Invalid application context */
+ APP_ERROR_NO_SUCH_FILE = -2, /**< No such file or directory */
+ APP_ERROR_NOT_SUPPORTED = -3, /**< Not supported (Since 4.0) */
+ APP_ERROR_ALREADY_RUNNING = -4, /**< Application is already running */
+ APP_ERROR_PERMISSION_DENIED = -5, /**< Permission denied @if MOBILE (Since 2.3.1) @endif */
+} app_error_e;
+
+DECLARE_FAKE_VALUE_FUNC(int, app_get_name, char**);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* MOCK_APP_COMMON_H_ */
diff --git a/unittest/mock/fff.h b/unittest/mock/fff.h
new file mode 100644
index 0000000..f8d6d5f
--- /dev/null
+++ b/unittest/mock/fff.h
@@ -0,0 +1,6493 @@
+/*
+LICENSE
+
+The MIT License (MIT)
+
+Copyright (c) 2010 Michael Long
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#ifndef FAKE_FUNCTIONS
+#define FAKE_FUNCTIONS
+
+#include <stdarg.h>
+#include <string.h> /* For memset and memcpy */
+
+#define FFF_MAX_ARGS (20u)
+#ifndef FFF_ARG_HISTORY_LEN
+ #define FFF_ARG_HISTORY_LEN (50u)
+#endif
+#ifndef FFF_CALL_HISTORY_LEN
+ #define FFF_CALL_HISTORY_LEN (50u)
+#endif
+/* -- INTERNAL HELPER MACROS -- */
+#define SET_RETURN_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \
+ FUNCNAME##_fake.return_val_seq = ARRAY_POINTER; \
+ FUNCNAME##_fake.return_val_seq_len = ARRAY_LEN;
+#define SET_CUSTOM_FAKE_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \
+ FUNCNAME##_fake.custom_fake_seq = ARRAY_POINTER; \
+ FUNCNAME##_fake.custom_fake_seq_len = ARRAY_LEN;
+
+/* Defining a function to reset a fake function */
+#define RESET_FAKE(FUNCNAME) { \
+ FUNCNAME##_reset(); \
+} \
+
+
+#define DECLARE_ARG(type, n, FUNCNAME) \
+ type arg##n##_val; \
+ type arg##n##_history[FFF_ARG_HISTORY_LEN];
+
+#define DECLARE_ALL_FUNC_COMMON \
+ unsigned int call_count; \
+ unsigned int arg_history_len; \
+ unsigned int arg_histories_dropped; \
+
+#define DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ RETURN_TYPE return_val_history[FFF_ARG_HISTORY_LEN];
+
+#define SAVE_ARG(FUNCNAME, n) \
+ memcpy((void*)&FUNCNAME##_fake.arg##n##_val, (void*)&arg##n, sizeof(arg##n));
+
+#define ROOM_FOR_MORE_HISTORY(FUNCNAME) \
+ FUNCNAME##_fake.call_count < FFF_ARG_HISTORY_LEN
+
+#define SAVE_RET_HISTORY(FUNCNAME, RETVAL) \
+ if ((FUNCNAME##_fake.call_count - 1) < FFF_ARG_HISTORY_LEN) \
+ memcpy((void *)&FUNCNAME##_fake.return_val_history[FUNCNAME##_fake.call_count - 1], (const void *) &RETVAL, sizeof(RETVAL)); \
+
+#define SAVE_ARG_HISTORY(FUNCNAME, ARGN) \
+ memcpy((void*)&FUNCNAME##_fake.arg##ARGN##_history[FUNCNAME##_fake.call_count], (void*)&arg##ARGN, sizeof(arg##ARGN));
+
+#define HISTORY_DROPPED(FUNCNAME) \
+ FUNCNAME##_fake.arg_histories_dropped++
+
+#define DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ RETURN_TYPE return_val; \
+ int return_val_seq_len; \
+ int return_val_seq_idx; \
+ RETURN_TYPE * return_val_seq; \
+
+#define DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ int custom_fake_seq_len; \
+ int custom_fake_seq_idx; \
+
+#define INCREMENT_CALL_COUNT(FUNCNAME) \
+ FUNCNAME##_fake.call_count++
+
+#define RETURN_FAKE_RESULT(FUNCNAME) \
+ if (FUNCNAME##_fake.return_val_seq_len){ /* then its a sequence */ \
+ if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) { \
+ SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx]) \
+ return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++]; \
+ } \
+ SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]) \
+ return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */ \
+ } \
+ SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val) \
+ return FUNCNAME##_fake.return_val; \
+
+#ifdef __cplusplus
+ #define FFF_EXTERN_C extern "C"{
+ #define FFF_END_EXTERN_C }
+#else /* ansi c */
+ #define FFF_EXTERN_C
+ #define FFF_END_EXTERN_C
+#endif /* cpp/ansi c */
+
+#define DEFINE_RESET_FUNCTION(FUNCNAME) \
+ void FUNCNAME##_reset(void){ \
+ memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake)); \
+ FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN; \
+ }
+/* -- END INTERNAL HELPER MACROS -- */
+
+typedef void (*fff_function_t)(void);
+typedef struct {
+ fff_function_t call_history[FFF_CALL_HISTORY_LEN];
+ unsigned int call_history_idx;
+} fff_globals_t;
+
+FFF_EXTERN_C
+extern fff_globals_t fff;
+FFF_END_EXTERN_C
+
+#define DEFINE_FFF_GLOBALS \
+ FFF_EXTERN_C \
+ fff_globals_t fff; \
+ FFF_END_EXTERN_C
+
+#define FFF_RESET_HISTORY() \
+ fff.call_history_idx = 0; \
+ memset(fff.call_history, 0, sizeof(fff.call_history));
+
+#define REGISTER_CALL(function) \
+ if(fff.call_history_idx < FFF_CALL_HISTORY_LEN) \
+ fff.call_history[fff.call_history_idx++] = (fff_function_t)function;
+
+#define DECLARE_FAKE_VOID_FUNC0(FUNCNAME) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(void); \
+ void(**custom_fake_seq)(void); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(void); \
+
+#define DEFINE_FAKE_VOID_FUNC0(FUNCNAME) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(void){ \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC0(FUNCNAME) \
+ DECLARE_FAKE_VOID_FUNC0(FUNCNAME) \
+ DEFINE_FAKE_VOID_FUNC0(FUNCNAME) \
+
+
+#define DECLARE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0); \
+
+#define DEFINE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \
+ DECLARE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \
+ DEFINE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1); \
+
+#define DEFINE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+ DECLARE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+ DEFINE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
+
+#define DEFINE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+ DECLARE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+ DEFINE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \
+
+#define DEFINE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+ DECLARE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+ DEFINE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \
+
+#define DEFINE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+ DECLARE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+ DEFINE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \
+
+#define DEFINE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+ DECLARE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+ DEFINE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \
+
+#define DEFINE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+ DECLARE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+ DEFINE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \
+
+#define DEFINE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+ DECLARE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+ DEFINE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \
+
+#define DEFINE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+ DECLARE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+ DEFINE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \
+
+#define DEFINE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+ DECLARE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+ DEFINE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \
+
+#define DEFINE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+ DECLARE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+ DEFINE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \
+
+#define DEFINE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+ DECLARE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+ DEFINE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \
+
+#define DEFINE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+ DECLARE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+ DEFINE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \
+
+#define DEFINE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+ DECLARE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+ DEFINE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \
+
+#define DEFINE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+ DECLARE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+ DEFINE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \
+
+#define DEFINE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+ DECLARE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+ DEFINE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \
+
+#define DEFINE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+ DECLARE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+ DEFINE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \
+
+#define DEFINE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+ DECLARE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+ DEFINE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \
+
+#define DEFINE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ SAVE_ARG(FUNCNAME, 18); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ SAVE_ARG_HISTORY(FUNCNAME, 18); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+ DECLARE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+ DEFINE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \
+ DECLARE_ARG(ARG19_TYPE, 19, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \
+
+#define DEFINE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ SAVE_ARG(FUNCNAME, 18); \
+ SAVE_ARG(FUNCNAME, 19); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ SAVE_ARG_HISTORY(FUNCNAME, 18); \
+ SAVE_ARG_HISTORY(FUNCNAME, 19); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \
+ } \
+ else{ \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+ DECLARE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+ DEFINE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(void); \
+ RETURN_TYPE(**custom_fake_seq)(void); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(void); \
+
+#define DEFINE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(void){ \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \
+ DECLARE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \
+ DEFINE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0); \
+
+#define DEFINE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1); \
+
+#define DEFINE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
+
+#define DEFINE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \
+
+#define DEFINE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \
+
+#define DEFINE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \
+
+#define DEFINE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \
+
+#define DEFINE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \
+
+#define DEFINE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \
+
+#define DEFINE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \
+
+#define DEFINE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \
+
+#define DEFINE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \
+
+#define DEFINE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \
+
+#define DEFINE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \
+
+#define DEFINE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \
+
+#define DEFINE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \
+
+#define DEFINE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \
+
+#define DEFINE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \
+
+#define DEFINE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \
+
+#define DEFINE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ SAVE_ARG(FUNCNAME, 18); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ SAVE_ARG_HISTORY(FUNCNAME, 18); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \
+ DECLARE_ARG(ARG19_TYPE, 19, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \
+
+#define DEFINE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ SAVE_ARG(FUNCNAME, 18); \
+ SAVE_ARG(FUNCNAME, 19); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ SAVE_ARG_HISTORY(FUNCNAME, 18); \
+ SAVE_ARG_HISTORY(FUNCNAME, 19); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ else{ \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \
+ } \
+ } \
+ if (FUNCNAME##_fake.custom_fake) return FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+ DECLARE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+ DEFINE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \
+
+
+#define DECLARE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg0); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg0); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg0); \
+ FUNCNAME##_fake.custom_fake(arg0, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg1); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg1); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg1); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg2); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg2); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg2); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg3); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg3); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg3); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg4); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg4); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg4); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg5); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg5); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg5); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg6); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg6); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg6); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg7); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg7); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg7); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg8); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg8); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg8); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg9); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg9); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg9); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg10); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg10); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg10); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg11); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg11); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg11); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg12); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg12); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg12); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg13); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg13); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg13); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg14); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg14); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg14); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg15); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg15); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg15); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg16); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg16); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg16); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg17); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg17); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg17); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ void(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, va_list ap); \
+ void(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...); \
+
+#define DEFINE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ SAVE_ARG(FUNCNAME, 18); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ SAVE_ARG_HISTORY(FUNCNAME, 18); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg18); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \
+ va_end(ap); \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg18); \
+ FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \
+ va_end(ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ va_list ap; \
+ va_start(ap, arg18); \
+ FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \
+ va_end(ap); \
+ } \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+ DECLARE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+ DEFINE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg0); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg0); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg0); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg1); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg1); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg1); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg2); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg2); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg2); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg3); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg3); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg3); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg4); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg4); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg4); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg5); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg5); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg5); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg6); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg6); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg6); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg7); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg7); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg7); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg8); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg8); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg8); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg9); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg9); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg9); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg10); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg10); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg10); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg11); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg11); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg11); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg12); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg12); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg12); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg13); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg13); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg13); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg14); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg14); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg14); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg15); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg15); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg15); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg16); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg16); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg16); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg17); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg17); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg17); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \
+
+
+#define DECLARE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+ typedef struct FUNCNAME##_Fake { \
+ DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \
+ DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \
+ DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \
+ DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \
+ DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \
+ DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \
+ DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \
+ DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \
+ DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \
+ DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \
+ DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \
+ DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \
+ DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \
+ DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \
+ DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \
+ DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \
+ DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \
+ DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \
+ DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \
+ DECLARE_ALL_FUNC_COMMON \
+ DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \
+ DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \
+ DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
+ RETURN_TYPE(*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, va_list ap); \
+ RETURN_TYPE(**custom_fake_seq)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, va_list ap); \
+ } FUNCNAME##_Fake; \
+ extern FUNCNAME##_Fake FUNCNAME##_fake; \
+ void FUNCNAME##_reset(void); \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...); \
+
+#define DEFINE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+ FUNCNAME##_Fake FUNCNAME##_fake; \
+ RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...){ \
+ SAVE_ARG(FUNCNAME, 0); \
+ SAVE_ARG(FUNCNAME, 1); \
+ SAVE_ARG(FUNCNAME, 2); \
+ SAVE_ARG(FUNCNAME, 3); \
+ SAVE_ARG(FUNCNAME, 4); \
+ SAVE_ARG(FUNCNAME, 5); \
+ SAVE_ARG(FUNCNAME, 6); \
+ SAVE_ARG(FUNCNAME, 7); \
+ SAVE_ARG(FUNCNAME, 8); \
+ SAVE_ARG(FUNCNAME, 9); \
+ SAVE_ARG(FUNCNAME, 10); \
+ SAVE_ARG(FUNCNAME, 11); \
+ SAVE_ARG(FUNCNAME, 12); \
+ SAVE_ARG(FUNCNAME, 13); \
+ SAVE_ARG(FUNCNAME, 14); \
+ SAVE_ARG(FUNCNAME, 15); \
+ SAVE_ARG(FUNCNAME, 16); \
+ SAVE_ARG(FUNCNAME, 17); \
+ SAVE_ARG(FUNCNAME, 18); \
+ if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \
+ SAVE_ARG_HISTORY(FUNCNAME, 0); \
+ SAVE_ARG_HISTORY(FUNCNAME, 1); \
+ SAVE_ARG_HISTORY(FUNCNAME, 2); \
+ SAVE_ARG_HISTORY(FUNCNAME, 3); \
+ SAVE_ARG_HISTORY(FUNCNAME, 4); \
+ SAVE_ARG_HISTORY(FUNCNAME, 5); \
+ SAVE_ARG_HISTORY(FUNCNAME, 6); \
+ SAVE_ARG_HISTORY(FUNCNAME, 7); \
+ SAVE_ARG_HISTORY(FUNCNAME, 8); \
+ SAVE_ARG_HISTORY(FUNCNAME, 9); \
+ SAVE_ARG_HISTORY(FUNCNAME, 10); \
+ SAVE_ARG_HISTORY(FUNCNAME, 11); \
+ SAVE_ARG_HISTORY(FUNCNAME, 12); \
+ SAVE_ARG_HISTORY(FUNCNAME, 13); \
+ SAVE_ARG_HISTORY(FUNCNAME, 14); \
+ SAVE_ARG_HISTORY(FUNCNAME, 15); \
+ SAVE_ARG_HISTORY(FUNCNAME, 16); \
+ SAVE_ARG_HISTORY(FUNCNAME, 17); \
+ SAVE_ARG_HISTORY(FUNCNAME, 18); \
+ } \
+ else{ \
+ HISTORY_DROPPED(FUNCNAME); \
+ } \
+ INCREMENT_CALL_COUNT(FUNCNAME); \
+ REGISTER_CALL(FUNCNAME); \
+ if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \
+ if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \
+ va_list ap; \
+ va_start(ap, arg18); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ } \
+ else{ \
+ va_list ap; \
+ va_start(ap, arg18); \
+ RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ va_end(ap); \
+ return ret; \
+ return FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \
+ } \
+ } \
+ if(FUNCNAME##_fake.custom_fake){ \
+ RETURN_TYPE ret; \
+ va_list ap; \
+ va_start(ap, arg18); \
+ ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \
+ va_end(ap); \
+ SAVE_RET_HISTORY(FUNCNAME, ret); \
+ return ret; \
+ } \
+ RETURN_FAKE_RESULT(FUNCNAME) \
+ } \
+ DEFINE_RESET_FUNCTION(FUNCNAME) \
+
+#define FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+ DECLARE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+ DEFINE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \
+
+/* MSVC expand macro fix */
+#define EXPAND(x) x
+
+#define PP_NARG_MINUS2(...) EXPAND(PP_NARG_MINUS2_(__VA_ARGS__, PP_RSEQ_N_MINUS2()))
+
+#define PP_NARG_MINUS2_(...) EXPAND(PP_ARG_MINUS2_N(__VA_ARGS__))
+
+#define PP_ARG_MINUS2_N(returnVal, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N
+
+#define PP_RSEQ_N_MINUS2() 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+
+#define PP_NARG_MINUS1(...) EXPAND(PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1()))
+
+#define PP_NARG_MINUS1_(...) EXPAND(PP_ARG_MINUS1_N(__VA_ARGS__))
+
+#define PP_ARG_MINUS1_N( _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N
+
+#define PP_RSEQ_N_MINUS1() 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+
+
+
+/* DECLARE AND DEFINE FAKE FUNCTIONS - PLACE IN TEST FILES */
+
+#define FAKE_VALUE_FUNC(...) EXPAND(FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__))
+
+#define FUNC_VALUE_(N,...) EXPAND(FUNC_VALUE_N(N,__VA_ARGS__))
+
+#define FUNC_VALUE_N(N,...) EXPAND(FAKE_VALUE_FUNC ## N(__VA_ARGS__))
+
+
+#define FAKE_VOID_FUNC(...) EXPAND(FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__))
+
+#define FUNC_VOID_(N,...) EXPAND(FUNC_VOID_N(N,__VA_ARGS__))
+
+#define FUNC_VOID_N(N,...) EXPAND(FAKE_VOID_FUNC ## N(__VA_ARGS__))
+
+
+#define FAKE_VALUE_FUNC_VARARG(...) EXPAND(FUNC_VALUE_VARARG_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__))
+
+#define FUNC_VALUE_VARARG_(N,...) EXPAND(FUNC_VALUE_VARARG_N(N,__VA_ARGS__))
+
+#define FUNC_VALUE_VARARG_N(N,...) EXPAND(FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__))
+
+
+#define FAKE_VOID_FUNC_VARARG(...) EXPAND(FUNC_VOID_VARARG_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__))
+
+#define FUNC_VOID_VARARG_(N,...) EXPAND(FUNC_VOID_VARARG_N(N,__VA_ARGS__))
+
+#define FUNC_VOID_VARARG_N(N,...) EXPAND(FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__))
+
+
+
+/* DECLARE FAKE FUNCTIONS - PLACE IN HEADER FILES */
+
+#define DECLARE_FAKE_VALUE_FUNC(...) EXPAND(DECLARE_FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__))
+
+#define DECLARE_FUNC_VALUE_(N,...) EXPAND(DECLARE_FUNC_VALUE_N(N,__VA_ARGS__))
+
+#define DECLARE_FUNC_VALUE_N(N,...) EXPAND(DECLARE_FAKE_VALUE_FUNC ## N(__VA_ARGS__))
+
+
+#define DECLARE_FAKE_VOID_FUNC(...) EXPAND(DECLARE_FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__))
+
+#define DECLARE_FUNC_VOID_(N,...) EXPAND(DECLARE_FUNC_VOID_N(N,__VA_ARGS__))
+
+#define DECLARE_FUNC_VOID_N(N,...) EXPAND(DECLARE_FAKE_VOID_FUNC ## N(__VA_ARGS__))
+
+
+#define DECLARE_FAKE_VALUE_FUNC_VARARG(...) EXPAND(DECLARE_FUNC_VALUE_VARARG_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__))
+
+#define DECLARE_FUNC_VALUE_VARARG_(N,...) EXPAND(DECLARE_FUNC_VALUE_VARARG_N(N,__VA_ARGS__))
+
+#define DECLARE_FUNC_VALUE_VARARG_N(N,...) EXPAND(DECLARE_FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__))
+
+
+#define DECLARE_FAKE_VOID_FUNC_VARARG(...) EXPAND(DECLARE_FUNC_VOID_VARARG_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__))
+
+#define DECLARE_FUNC_VOID_VARARG_(N,...) EXPAND(DECLARE_FUNC_VOID_VARARG_N(N,__VA_ARGS__))
+
+#define DECLARE_FUNC_VOID_VARARG_N(N,...) EXPAND(DECLARE_FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__))
+
+
+
+/* DEFINE FAKE FUNCTIONS - PLACE IN SOURCE FILES */
+
+#define DEFINE_FAKE_VALUE_FUNC(...) EXPAND(DEFINE_FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__))
+
+#define DEFINE_FUNC_VALUE_(N,...) EXPAND(DEFINE_FUNC_VALUE_N(N,__VA_ARGS__))
+
+#define DEFINE_FUNC_VALUE_N(N,...) EXPAND(DEFINE_FAKE_VALUE_FUNC ## N(__VA_ARGS__))
+
+
+#define DEFINE_FAKE_VOID_FUNC(...) EXPAND(DEFINE_FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__))
+
+#define DEFINE_FUNC_VOID_(N,...) EXPAND(DEFINE_FUNC_VOID_N(N,__VA_ARGS__))
+
+#define DEFINE_FUNC_VOID_N(N,...) EXPAND(DEFINE_FAKE_VOID_FUNC ## N(__VA_ARGS__))
+
+
+#define DEFINE_FAKE_VALUE_FUNC_VARARG(...) EXPAND(DEFINE_FUNC_VALUE_VARARG_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__))
+
+#define DEFINE_FUNC_VALUE_VARARG_(N,...) EXPAND(DEFINE_FUNC_VALUE_VARARG_N(N,__VA_ARGS__))
+
+#define DEFINE_FUNC_VALUE_VARARG_N(N,...) EXPAND(DEFINE_FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__))
+
+
+#define DEFINE_FAKE_VOID_FUNC_VARARG(...) EXPAND(DEFINE_FUNC_VOID_VARARG_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__))
+
+#define DEFINE_FUNC_VOID_VARARG_(N,...) EXPAND(DEFINE_FUNC_VOID_VARARG_N(N,__VA_ARGS__))
+
+#define DEFINE_FUNC_VOID_VARARG_N(N,...) EXPAND(DEFINE_FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__))
+
+
+
+
+#endif /* FAKE_FUNCTIONS */
diff --git a/unittest/mock/mock.cc b/unittest/mock/mock.cc
new file mode 100644
index 0000000..687ad67
--- /dev/null
+++ b/unittest/mock/mock.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "app_common.h"
+#include "mock.h"
+
+DEFINE_FFF_GLOBALS;
+
+DEFINE_FAKE_VALUE_FUNC(int, app_get_name, char**); \ No newline at end of file
diff --git a/unittest/mock/mock.h b/unittest/mock/mock.h
new file mode 100644
index 0000000..23adbd0
--- /dev/null
+++ b/unittest/mock/mock.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef MOCK_MOCK_H__
+#define MOCK_MOCK_H__
+
+#include "fff.h"
+
+#endif // MOCK_MOCK_H__
diff --git a/unittest/src/test_abstract_item.cc b/unittest/src/test_abstract_item.cc
new file mode 100644
index 0000000..2c1e6da
--- /dev/null
+++ b/unittest/src/test_abstract_item.cc
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <app_control.h>
+
+#include "notification-ex/item_inflator.h"
+#include "notification-ex/app_control_action.h"
+#include "notification-ex/item_info_internal.h"
+#include "notification-ex/iitem_factory.h"
+#include "notification-ex/factory_manager.h"
+#include "notification-ex/default_item_factory.h"
+
+#define MY_ITEM_TYPE AbstractItem::Type::Custom + 1
+
+using namespace notification;
+using namespace notification::item;
+
+namespace {
+class TestItem : public AbstractItem {
+ public:
+ TestItem(std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}))
+ : AbstractItem(action) {
+ }
+ TestItem(std::string id, std::shared_ptr<AbstractAction> action = std::shared_ptr<AbstractAction>({}))
+ : AbstractItem(id, action) {
+ }
+ virtual ~TestItem() {}
+
+ Bundle Serialize() const override {
+ Bundle b;
+ b = AbstractItem::Serialize();
+ return b;
+ }
+ void Deserialize(Bundle b) override {
+ AbstractItem::Deserialize(b);
+ }
+ AbstractItem& FindByID(std::string id) override {
+ return *this;
+ }
+ int GetType() const override {
+ return MY_ITEM_TYPE;
+ }
+};
+
+class MyFactory : public IItemFactory {
+ public:
+ MyFactory() {}
+ virtual ~MyFactory() {}
+
+ std::unique_ptr<AbstractItem> CreateItem(int type) override {
+ if (type == MY_ITEM_TYPE)
+ return std::unique_ptr<AbstractItem>(new TestItem(""));
+
+ return nullptr;
+ }
+};
+
+class AbstractItemTest : public ::testing::Test {
+ public:
+ virtual void SetUp() {
+ FactoryManager::GetInst().RegisterFactory(std::unique_ptr<IItemFactory>(new MyFactory()));
+ }
+ virtual void TearDown() {
+ FactoryManager::GetInst().RegisterFactory(std::unique_ptr<IItemFactory>(new DefaultItemFactory()));
+ }
+};
+
+TEST_F(AbstractItemTest, SerializeDeserialize) {
+ /* Serialize */
+ app_control_h app_control, app_control_1;
+ char* app_id = NULL;
+ time_t current_time;
+
+ app_control_create(&app_control);
+ app_control_set_app_id(app_control, "new_appid");
+ std::shared_ptr<AppControlAction> action = std::make_shared<AppControlAction>(app_control);
+ app_control_destroy(app_control);
+
+ app_control_create(&app_control_1);
+ app_control_set_app_id(app_control_1, "new_appid_1");
+ std::shared_ptr<AppControlAction> action_1 = std::make_shared<AppControlAction>(app_control_1);
+ app_control_destroy(app_control_1);
+
+ TestItem item("test_id", action);
+
+ Color color(50, 100,150,200);
+ Padding padding(10, 20, 30, 40);
+ Geometry geometry(110, 120, 130, 140);
+
+ item.SetStyle(std::make_shared<Style>(color, padding, geometry));
+ item.SetVisible(false);
+ item.SetEnable(false);
+ item.AddReceiver("receiver_1");
+ item.AddReceiver("receiver_2");
+ std::static_pointer_cast<IItemInfoInternal>(item.GetInfo())->AddHideViewer("hide_1");
+ std::static_pointer_cast<IItemInfoInternal>(item.GetInfo())->AddHideViewer("hide_2");
+ item.SetPolicy(AbstractItem::Policy::OnBootClear);
+ std::static_pointer_cast<IItemInfoInternal>(item.GetInfo())->SetVersion(3);
+ item.GetInfo()->SetHideTime(5);
+ item.GetInfo()->SetDeleteTime(9);
+ item.SetChannel("channel99");
+ item.SetSoundPath("soundpath");
+ item.SetVibrationPath("vibrationpath");
+ std::static_pointer_cast<IItemInfoInternal>(item.GetInfo())->SetUid(3);
+ item.SetSenderAppId("sender");
+
+ time(&current_time);
+ std::static_pointer_cast<IItemInfoInternal>(item.GetInfo())->SetTime(current_time);
+
+ Color color2(150, 160, 170, 180);
+
+ std::shared_ptr<LEDInfo> led = std::make_shared<LEDInfo>(color2);
+ led->SetOnPeriod(10);
+ led->SetOffPeriod(20);
+
+ item.SetLEDInfo(led);
+
+ /* Deserialize */
+ Bundle b = item.Serialize();
+
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ TestItem* gen_test = static_cast<TestItem*>(gen_item.get());
+
+ ASSERT_EQ(gen_test->GetId(), "test_id");
+ ASSERT_EQ(gen_test->GetType(), MY_ITEM_TYPE);
+ ASSERT_EQ(std::static_pointer_cast<IItemInfoInternal>(gen_test->GetInfo())->GetUid(), 3);
+ ASSERT_EQ(gen_test->GetEnable(), false);
+ ASSERT_EQ(gen_test->GetVisible(),false);
+ ASSERT_EQ(gen_test->GetPolicy(), AbstractItem::Policy::OnBootClear);
+ ASSERT_EQ(std::static_pointer_cast<IItemInfoInternal>(gen_test->GetInfo())->GetVersion(), 3);
+ ASSERT_EQ(gen_test->GetInfo()->GetHideTime(), 5);
+ ASSERT_EQ(gen_test->GetInfo()->GetDeleteTime(), 9);
+ ASSERT_EQ(gen_test->GetChannel(), "channel99");
+ ASSERT_EQ(gen_test->GetSoundPath(), "soundpath");
+ ASSERT_EQ(gen_test->GetVibrationPath(), "vibrationpath");
+ ASSERT_EQ(gen_test->GetSenderAppId(), "sender");
+ ASSERT_EQ(gen_test->GetInfo()->GetTime(), current_time);
+
+ ASSERT_EQ(gen_test->GetStyle()->GetPadding().GetLeft(), 10);
+ ASSERT_EQ(gen_test->GetStyle()->GetPadding().GetTop(), 20);
+ ASSERT_EQ(gen_test->GetStyle()->GetPadding().GetRight(), 30);
+ ASSERT_EQ(gen_test->GetStyle()->GetPadding().GetBottom(), 40);
+
+ ASSERT_EQ(gen_test->GetStyle()->GetColor().GetAVal(), 50);
+ ASSERT_EQ(gen_test->GetStyle()->GetColor().GetRVal(), 100);
+ ASSERT_EQ(gen_test->GetStyle()->GetColor().GetGVal(), 150);
+ ASSERT_EQ(gen_test->GetStyle()->GetColor().GetBVal(), 200);
+
+ ASSERT_EQ(gen_test->GetStyle()->GetGeometry().GetX(), 110);
+ ASSERT_EQ(gen_test->GetStyle()->GetGeometry().GetY(), 120);
+ ASSERT_EQ(gen_test->GetStyle()->GetGeometry().GetWidth(), 130);
+ ASSERT_EQ(gen_test->GetStyle()->GetGeometry().GetHeight(), 140);
+
+ ASSERT_EQ(gen_test->GetLEDInfo()->GetColor().GetAVal(), 150);
+ ASSERT_EQ(gen_test->GetLEDInfo()->GetColor().GetRVal(), 160);
+ ASSERT_EQ(gen_test->GetLEDInfo()->GetColor().GetGVal(), 170);
+ ASSERT_EQ(gen_test->GetLEDInfo()->GetColor().GetBVal(), 180);
+ ASSERT_EQ(gen_test->GetLEDInfo()->GetOnPeriod(), 10);
+ ASSERT_EQ(gen_test->GetLEDInfo()->GetOffPeriod(), 20);
+
+ std::list<std::string> receiver1 = item.GetReceiverList();
+ std::list<std::string> receiver2 = gen_test->GetReceiverList();
+
+ ASSERT_EQ(receiver1.size(), receiver2.size());
+
+ for (unsigned int i = 0; i < receiver1.size(); i++) {
+ ASSERT_EQ(receiver1.front(), receiver2.front());
+ receiver1.pop_front();
+ receiver2.pop_front();
+ }
+
+ std::list<std::string> hide1 =
+ std::static_pointer_cast<IItemInfoInternal>(item.GetInfo())->GetHideViewerList();
+ std::list<std::string> hide2 =
+ std::static_pointer_cast<IItemInfoInternal>(gen_test->GetInfo())->GetHideViewerList();
+
+ ASSERT_EQ(hide1.size(), hide2.size());
+
+ for (unsigned int i = 0; i < hide1.size(); i++) {
+ ASSERT_EQ(hide1.front(), hide2.front());
+ hide1.pop_front();
+ hide2.pop_front();
+ }
+
+ ASSERT_EQ(gen_test->GetAction()->GetType(), AbstractAction::Type::AppControl);
+
+ std::shared_ptr<AppControlAction> ac =
+ std::static_pointer_cast<AppControlAction>(gen_test->GetAction());
+ app_control_get_app_id(ac->GetAppControl(), &app_id);
+
+ ASSERT_STREQ(app_id, "new_appid");
+
+ item.SetAction(action_1);
+
+ b = item.Serialize();
+ gen_item = ItemInflator::Create(b);
+ gen_test = static_cast<TestItem*>(gen_item.get());
+
+ ac = std::static_pointer_cast<AppControlAction>(gen_test->GetAction());
+ app_control_get_app_id(ac->GetAppControl(), &app_id);
+
+ ASSERT_STREQ(app_id, "new_appid_1");
+}
+
+} // namespace \ No newline at end of file
diff --git a/unittest/src/test_app_control_action.cc b/unittest/src/test_app_control_action.cc
new file mode 100644
index 0000000..ff575c1
--- /dev/null
+++ b/unittest/src/test_app_control_action.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/app_control_action.h"
+#include "notification-ex/action_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+class AppControlActionTest : public ::testing::Test {
+ public:
+ AppControlAction* action;
+ app_control_h app_control;
+ const char* app_id = "test_appid";
+ std::string extra = "appcontrol_extra";
+
+ virtual void SetUp() {
+ app_control_create(&app_control);
+ app_control_set_app_id(app_control, app_id);
+
+ action = new AppControlAction(app_control, extra);
+ }
+ virtual void TearDown() {
+ delete action;
+ app_control_destroy(app_control);
+ }
+};
+
+TEST_F(AppControlActionTest, create) {
+ EXPECT_NE(AppControlActionTest::action, nullptr);
+}
+
+TEST_F(AppControlActionTest, IsLocal) {
+ ASSERT_EQ(AppControlActionTest::action->IsLocal(), 1);
+}
+
+TEST_F(AppControlActionTest, GetExtra) {
+ ASSERT_EQ(AppControlActionTest::action->GetExtra(),
+ AppControlActionTest::extra);
+}
+
+TEST_F(AppControlActionTest, SerializeDeserialize) {
+ Bundle b = AppControlActionTest::action->Serialize();
+
+ std::shared_ptr<AbstractAction> gen_action = ActionInflator::Create(b);
+ ASSERT_EQ(gen_action->GetType(), AbstractAction::AppControl);
+
+ AppControlAction* gen_appcontrol_action =
+ static_cast<AppControlAction*>(gen_action.get());
+
+ char* app_id = nullptr;
+ app_control_get_app_id(gen_appcontrol_action->GetAppControl(), &app_id);
+ std::unique_ptr<char, decltype(std::free)*> ptr(app_id, std::free);
+ ASSERT_STREQ(app_id, AppControlActionTest::app_id);
+}
+
+TEST_F(AppControlActionTest, AppControl) {
+ app_control_h app_control;
+ const char* app_id = "new_appid";
+
+ app_control_create(&app_control);
+ app_control_set_app_id(app_control, app_id);
+ AppControlActionTest::action->SetAppControl(app_control);
+ app_control_destroy(app_control);
+
+ Bundle b = AppControlActionTest::action->Serialize();
+
+ std::shared_ptr<AbstractAction> gen_action = ActionInflator::Create(b);
+ AppControlAction* gen_appcontrol_action =
+ static_cast<AppControlAction*>(gen_action.get());
+
+ char* app_id_ = nullptr;
+ app_control_get_app_id(gen_appcontrol_action->GetAppControl(), &app_id_);
+ std::unique_ptr<char, decltype(std::free)*> ptr(app_id_, std::free);
+ EXPECT_STREQ(app_id, app_id_);
+}
diff --git a/unittest/src/test_bundle.cc b/unittest/src/test_bundle.cc
new file mode 100644
index 0000000..a7e66cc
--- /dev/null
+++ b/unittest/src/test_bundle.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <string>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/ex_bundle.h"
+
+using ::testing::AtLeast;
+using namespace notification;
+
+TEST(Bundle, CtorDtor) {
+ Bundle bundle;
+}
+
+TEST(Bundle, CopyCtor) {
+ Bundle bundle;
+ bundle.Add("TestKey", "TestVal");
+
+ Bundle b2(bundle);
+ EXPECT_EQ(b2.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, MoveCtor) {
+ Bundle bundle;
+ bundle.Add("TestKey", "TestVal");
+
+ Bundle b2(std::move(bundle));
+ EXPECT_EQ(b2.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, AddStringGetString) {
+ Bundle bundle;
+ bundle.Add("TestKey", "TestVal");
+
+ EXPECT_EQ(bundle.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, AddByteGetByte) {
+ Bundle bundle;
+ std::vector<unsigned char> v = { 0, 1, 2, 3};
+ bundle.Add("TestKey", v);
+ auto v2 = bundle.GetByte("TestKey");
+
+ EXPECT_EQ(v2.size(), 4);
+ EXPECT_EQ(v2[0], 0);
+ EXPECT_EQ(v2[1], 1);
+ EXPECT_EQ(v2[2], 2);
+ EXPECT_EQ(v2[3], 3);
+}
+
+TEST(Bundle, AddStringArrayGetStringArray) {
+ Bundle bundle;
+ bundle.Add("TestKey", { "TestVal1", "TestVal2", "TestVal3" });
+
+ auto v = bundle.GetStringArray("TestKey");
+
+ EXPECT_EQ(v.size(), 3);
+ EXPECT_EQ(v[0], "TestVal1");
+ EXPECT_EQ(v[1], "TestVal2");
+ EXPECT_EQ(v[2], "TestVal3");
+}
+
+TEST(Bundle, ToRaw) {
+ Bundle bundle;
+ bundle.Add("TestKey", "TestVal");
+
+ auto r = bundle.ToRaw();
+ Bundle b2(std::move(r));
+ EXPECT_EQ(bundle.GetString("TestKey"), "TestVal");
+}
+
+TEST(Bundle, GetCount) {
+ Bundle bundle;
+ bundle.Add("TestKey1", "TestVal1");
+ bundle.Add("TestKey2", "TestVal2");
+
+ EXPECT_EQ(bundle.GetCount(), 2);
+}
+
+TEST(Bundle, Delete) {
+ Bundle bundle;
+ int r = bundle.Add("TestKey1", "TestVal1");
+ EXPECT_EQ(r, 0);
+
+ r = bundle.Delete("TestKey1");
+ EXPECT_EQ(r, 0);
+
+ EXPECT_EQ(bundle.GetString("TestKey1"), "");
+}
+
+TEST(Bundle, GetKeys) {
+ Bundle bundle;
+ bundle.Add("TestKey1", "TestVal1");
+ bundle.Add("TestKey2", "TestVal2");
+ bundle.Add("TestKey3", "TestVal3");
+
+ auto v = bundle.GetKeys();
+
+ EXPECT_EQ(bundle.GetCount(), 3);
+
+ for (auto& i : v) {
+ EXPECT_EQ(i.GetType(), BUNDLE_TYPE_STR);
+ }
+}
diff --git a/unittest/src/test_button_item.cc b/unittest/src/test_button_item.cc
new file mode 100644
index 0000000..ad4a996
--- /dev/null
+++ b/unittest/src/test_button_item.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <gmock/gmock.h>
+
+#include "notification-ex/button_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+using namespace std;
+
+namespace {
+
+class ButtonItemTest : public ::testing::Test {
+ protected:
+ void SetUp() override {}
+ void TearDown() override {}
+};
+
+
+TEST_F(ButtonItemTest, FindByID) {
+ ButtonItem item("btn_id", "title");
+
+ AbstractItem& child = item.FindByID("btn_id");
+ ButtonItem& btn = static_cast<ButtonItem&>(child);
+ ASSERT_EQ(btn.GetTitle(), "title");
+}
+
+TEST_F(ButtonItemTest, FindByIDNullItemReturn) {
+ ButtonItem item("btn_id", "title");
+
+ AbstractItem& child = item.FindByID("not_exist_button");
+ ASSERT_EQ(child.GetType(), AbstractItem::NullObject);
+}
+
+TEST_F(ButtonItemTest, SerializeDeserializeGetTitle) {
+ ButtonItem item("title");
+ Bundle b = item.Serialize();
+ shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(gen_item->GetType(), item.GetType());
+
+ auto gen_btn = std::static_pointer_cast<ButtonItem>(gen_item);
+ ASSERT_EQ(item.GetTitle(), gen_btn->GetTitle());
+}
+
+} // namespace
diff --git a/unittest/src/test_chat_message_item.cc b/unittest/src/test_chat_message_item.cc
new file mode 100644
index 0000000..c72e6fb
--- /dev/null
+++ b/unittest/src/test_chat_message_item.cc
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/chat_message_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+class ChatMessageItemTest : public ::testing::Test {
+ public:
+ ChatMessageItem* item;
+ ChatMessageItem::Type type = ChatMessageItem::Type::user;
+ std::string id = "chatmessage_id";
+ time_t current_time;
+ virtual void SetUp() {
+ time(&current_time);
+
+ item = new ChatMessageItem(id,
+ std::make_shared<TextItem>("name_id", "name"),
+ std::make_shared<TextItem>("text_id", "text"),
+ std::make_shared<ImageItem>("image_id", "path"),
+ std::make_shared<TimeItem>(current_time),type);
+ }
+ virtual void TearDown() {
+ delete item;
+ }
+};
+
+TEST_F(ChatMessageItemTest, create) {
+ EXPECT_NE(ChatMessageItemTest::item, nullptr);
+}
+
+TEST_F(ChatMessageItemTest, FindByID) {
+ AbstractItem& child = ChatMessageItemTest::item->FindByID(ChatMessageItemTest::id);
+ ChatMessageItem& message = static_cast<ChatMessageItem&>(child);
+ ASSERT_EQ(message.GetNameItem().GetContents(), "name");
+ ASSERT_EQ(message.GetTextItem().GetContents(), "text");
+ ASSERT_EQ(message.GetImageItem().GetImagePath(), "path");
+ ASSERT_EQ(message.GetMessageType(), ChatMessageItemTest::type);
+}
+
+TEST_F(ChatMessageItemTest, FindByIDNullItemReturn) {
+ AbstractItem& child = ChatMessageItemTest::item->FindByID("not_existed_item");
+ ASSERT_EQ(child.GetType(), ChatMessageItem::NullObject);
+}
+
+TEST_F(ChatMessageItemTest, SerializeDeserialize) {
+ Bundle b = ChatMessageItemTest::item->Serialize();
+
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ auto gen_message = std::static_pointer_cast<ChatMessageItem>(gen_item);
+ ASSERT_EQ(gen_message->GetNameItem().GetContents(), "name");
+ ASSERT_EQ(gen_message->GetTextItem().GetContents(), "text");
+ ASSERT_EQ(gen_message->GetImageItem().GetImagePath(), "path");
+ ASSERT_EQ(gen_message->GetTimeItem().GetTime(), ChatMessageItemTest::current_time);
+ ASSERT_EQ(gen_message->GetMessageType(), ChatMessageItemTest::type);
+}
diff --git a/unittest/src/test_checkbox_item.cc b/unittest/src/test_checkbox_item.cc
new file mode 100644
index 0000000..bdcb246
--- /dev/null
+++ b/unittest/src/test_checkbox_item.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/checkbox_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+class CheckBoxItemTest : public ::testing::Test {
+ public:
+ CheckBoxItem* item;
+ std::string id = "checkbox_id";
+ std::string title = "title";
+ bool isChecked = false;
+ virtual void SetUp() {
+ item = new CheckBoxItem(id, title, isChecked);
+ }
+ virtual void TearDown() {
+ delete item;
+ }
+};
+
+TEST_F(CheckBoxItemTest, create) {
+ EXPECT_NE(CheckBoxItemTest::item, nullptr);
+}
+
+TEST_F(CheckBoxItemTest, FindByID) {
+ AbstractItem& child = CheckBoxItemTest::item->FindByID(CheckBoxItemTest::id);
+ CheckBoxItem& checkbox = static_cast<CheckBoxItem&>(child);
+ ASSERT_EQ(checkbox.GetTitle(), CheckBoxItemTest::title);
+ ASSERT_EQ(checkbox.IsChecked(), CheckBoxItemTest::isChecked);
+}
+
+TEST_F(CheckBoxItemTest, FindByIDNullItemReturn) {
+ AbstractItem& child = CheckBoxItemTest::item->FindByID("not_existed_item");
+ ASSERT_EQ(child.GetType(), CheckBoxItem::NullObject);
+}
+
+TEST_F(CheckBoxItemTest, SerializeDeserialize) {
+ Bundle b = CheckBoxItemTest::item->Serialize();
+
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(CheckBoxItemTest::item->GetType(), gen_item->GetType());
+
+ auto gen_checkbox = std::static_pointer_cast<CheckBoxItem>(gen_item);
+ ASSERT_EQ(CheckBoxItemTest::item->GetTitle(), gen_checkbox->GetTitle());
+}
diff --git a/unittest/src/test_entry_item.cc b/unittest/src/test_entry_item.cc
new file mode 100644
index 0000000..b4e3e05
--- /dev/null
+++ b/unittest/src/test_entry_item.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/entry_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+namespace {
+
+class EntryItemTest : public ::testing::Test {
+ public:
+ virtual void SetUp() {}
+ virtual void TearDown() {}
+};
+
+TEST_F(EntryItemTest, FindByID) {
+ EntryItem item("entry_id");
+
+ AbstractItem& child = item.FindByID("entry_id");
+ EntryItem& btn = static_cast<EntryItem&>(child);
+ ASSERT_EQ(btn.GetId(), "entry_id");
+}
+
+TEST_F(EntryItemTest, FindByIDNullItemReturn) {
+ EntryItem item("entry_id");
+
+ AbstractItem& child = item.FindByID("not_existed_item");
+ ASSERT_EQ(child.GetType(), EntryItem::NullObject);
+}
+
+TEST_F(EntryItemTest, SerializeDeserialize) {
+ EntryItem item("entry_id");
+
+ Bundle b = item.Serialize();
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(gen_item->GetType(), item.GetType());
+
+ auto gen_effect = std::static_pointer_cast<EntryItem>(gen_item);
+ ASSERT_EQ(item.GetId(), gen_effect->GetId());
+}
+
+TEST_F(EntryItemTest, SetTextGetText) {
+ EntryItem item("entry_id");
+ item.SetText("test");
+
+ ASSERT_EQ(item.GetText(), "test");
+}
+
+TEST_F(EntryItemTest, GetTextLimit) {
+ EntryItem item("entry_id");
+
+ ASSERT_EQ(item.GetTextLimit(), 160);
+}
+
+} // namespace \ No newline at end of file
diff --git a/unittest/src/test_event_info.cc b/unittest/src/test_event_info.cc
new file mode 100644
index 0000000..7daafa6
--- /dev/null
+++ b/unittest/src/test_event_info.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <gmock/gmock.h>
+
+#include "notification-ex/event_info_internal.h"
+
+using namespace notification;
+using namespace std;
+
+namespace {
+
+class EventInfoTest : public ::testing::Test {
+ protected:
+ void SetUp() override {}
+ void TearDown() override {}
+};
+
+TEST_F(EventInfoTest, SerializeDeserialize) {
+ EventInfo info(EventInfo::Get, "test", "channel", "id", "tag");
+ Bundle b = info.Serialize();
+ EventInfo serialized(b);
+ ASSERT_EQ(serialized.GetEventType(), info.GetEventType());
+ ASSERT_EQ(serialized.GetOwner(), info.GetOwner());
+ ASSERT_EQ(serialized.GetChannel(), info.GetChannel());
+ ASSERT_EQ(serialized.GetItemId(), info.GetItemId());
+ ASSERT_EQ(serialized.GetTag(), info.GetTag());
+ ASSERT_EQ(serialized.GetUid(), info.GetUid());
+}
+
+TEST_F(EventInfoTest, GetString) {
+ ASSERT_EQ(EventInfo::GetString(EventInfo::Post), "Post");
+ ASSERT_EQ(EventInfo::GetString(EventInfo::Update), "Update");
+ ASSERT_EQ(EventInfo::GetString(EventInfo::Delete), "Delete");
+ ASSERT_EQ(EventInfo::GetString(EventInfo::Get), "Get");
+}
+
+} // namespace
diff --git a/unittest/src/test_group_item.cc b/unittest/src/test_group_item.cc
new file mode 100644
index 0000000..c4fb43f
--- /dev/null
+++ b/unittest/src/test_group_item.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <gmock/gmock.h>
+
+#include "notification-ex/group_item.h"
+#include "notification-ex/button_item.h"
+#include "notification-ex/item_inflator.h"
+#include "unittest/mock/app_common.h"
+
+using namespace notification;
+using namespace notification::item;
+using namespace std;
+
+namespace {
+
+class GroupItemTest : public ::testing::Test {
+ protected:
+ void SetUp() override {}
+ void TearDown() override {}
+};
+
+TEST_F(GroupItemTest, AddChild) {
+ GroupItem item("GROUP1");
+ item.AddChild(std::make_shared<ButtonItem>("btn1", "test1"));
+ item.AddChild(std::make_shared<ButtonItem>("btn2", "test2"));
+ ASSERT_EQ(item.GetChildren().size(), 2);
+}
+
+TEST_F(GroupItemTest, RemoveChild) {
+ GroupItem item("GROUP1");
+ item.AddChild(std::make_shared<ButtonItem>("btn1", "test1"));
+ item.AddChild(std::make_shared<ButtonItem>("btn2", "test2"));
+ ASSERT_EQ(item.GetChildren().size(), 2);
+
+ item.RemoveChild("btn1");
+ ASSERT_EQ(item.GetChildren().size(), 1);
+}
+
+TEST_F(GroupItemTest, SerializeDeserialize) {
+ GroupItem item("GROUP1");
+ item.AddChild(std::make_shared<ButtonItem>("btn1", "test1"));
+ item.AddChild(std::make_shared<ButtonItem>("btn2", "test2"));
+
+ Bundle b = item.Serialize();
+ shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(gen_item->GetType(), item.GetType());
+
+ auto gen_group = static_pointer_cast<GroupItem>(gen_item);
+ list<shared_ptr<AbstractItem>> gen_children_list = gen_group->GetChildren();
+ list<shared_ptr<AbstractItem>> origin_children_list = item.GetChildren();
+
+ list<shared_ptr<AbstractItem>>::iterator it = origin_children_list.begin();
+ for (auto& i : gen_children_list) {
+ ASSERT_EQ(i->GetType(), (*it)->GetType());
+ if (i->GetType() == AbstractItem::Button) {
+ ButtonItem* btn1 = static_cast<ButtonItem*>(i.get());
+ ButtonItem* btn2 = static_cast<ButtonItem*>((*it).get());
+ ASSERT_EQ(btn1->GetTitle(), btn2->GetTitle());
+ }
+ it++;
+ }
+ ASSERT_EQ(item.GetChildren().size(), 2);
+}
+
+TEST_F(GroupItemTest, FindByID) {
+ GroupItem item("GROUP1");
+ item.AddChild(std::make_shared<ButtonItem>("btn1", "test1"));
+ item.AddChild(std::make_shared<ButtonItem>("btn2", "test2"));
+ ASSERT_EQ(item.GetChildren().size(), 2);
+
+ AbstractItem& child = item.FindByID("btn2");
+ ButtonItem& btn = static_cast<ButtonItem&>(child);
+ ASSERT_EQ(btn.GetTitle(), "test2");
+}
+
+TEST_F(GroupItemTest, FindByIDNullItemReturn) {
+ GroupItem item("GROUP1");
+ item.AddChild(std::make_shared<ButtonItem>("btn1", "test1"));
+ item.AddChild(std::make_shared<ButtonItem>("btn2", "test2"));
+ ASSERT_EQ(item.GetChildren().size(), 2);
+
+ AbstractItem& child = item.FindByID("not_exist_button");
+ ASSERT_EQ(child.GetType(), AbstractItem::NullObject);
+}
+
+int __fake_app_get_name(char** app_name) {
+ *app_name = (char*)"unittest_appname";
+ return 0;
+}
+
+TEST_F(GroupItemTest, GetAppLabel) {
+ app_get_name_fake.custom_fake = __fake_app_get_name;
+
+ GroupItem item("GROUP1");
+ string app_label = item.GetAppLabel();
+
+ ASSERT_EQ(app_label, "unittest_appname");
+}
+
+TEST_F(GroupItemTest, SetDirection) {
+ GroupItem item("GROUP1");
+ item.SetDirection(true);
+
+ ASSERT_TRUE(item.IsVertical());
+}
+
+} // namespace
diff --git a/unittest/src/test_icon_item.cc b/unittest/src/test_icon_item.cc
new file mode 100644
index 0000000..df7fb7f
--- /dev/null
+++ b/unittest/src/test_icon_item.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/icon_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+class IconItemTest : public ::testing::Test {
+ public:
+ IconItem* item;
+ std::string id = "icon_id";
+ virtual void SetUp() {
+ item = new IconItem(id, "icon_path");
+ }
+ virtual void TearDown() {
+ delete item;
+ }
+};
+
+TEST_F(IconItemTest, create) {
+ EXPECT_NE(IconItemTest::item, nullptr);
+}
+
+TEST_F(IconItemTest, FindByID) {
+ AbstractItem& child = IconItemTest::item->FindByID(IconItemTest::id);
+ IconItem& icon = static_cast<IconItem&>(child);
+ ASSERT_EQ(icon.GetImagePath(), "icon_path");
+}
+
+TEST_F(IconItemTest, FindByIDNullItemReturn) {
+ AbstractItem& child = IconItemTest::item->FindByID("not_existed_item");
+ ASSERT_EQ(child.GetType(), IconItem::NullObject);
+}
+
+TEST_F(IconItemTest, SerializeDeserialize) {
+ Bundle b = IconItemTest::item->Serialize();
+
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(IconItemTest::item->GetType(), gen_item->GetType());
+
+ auto gen_icon = std::static_pointer_cast<IconItem>(gen_item);
+ ASSERT_EQ(IconItemTest::item->GetImagePath(), gen_icon->GetImagePath());
+}
diff --git a/unittest/src/test_icon_text_item.cc b/unittest/src/test_icon_text_item.cc
new file mode 100644
index 0000000..91c7fc4
--- /dev/null
+++ b/unittest/src/test_icon_text_item.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/icon_text_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+class IconTextItemTest : public ::testing::Test {
+ public:
+ IconTextItem* item;
+ std::string id = "icontext_id";
+ virtual void SetUp() {
+ item = new IconTextItem(id,
+ std::make_shared<IconItem>("icon_id", "icon_path"),
+ std::make_shared<TextItem>("text_id", "title"));
+ }
+ virtual void TearDown() {
+ delete item;
+ }
+};
+
+TEST_F(IconTextItemTest, create) {
+ EXPECT_NE(IconTextItemTest::item, nullptr);
+}
+
+TEST_F(IconTextItemTest, FindByID) {
+ AbstractItem& child = IconTextItemTest::item->FindByID(IconTextItemTest::id);
+ IconTextItem& icontext = static_cast<IconTextItem&>(child);
+ ASSERT_EQ(icontext.GetIconItem().GetImagePath(), "icon_path");
+ ASSERT_EQ(icontext.GetTextItem().GetContents(), "title");
+}
+
+TEST_F(IconTextItemTest, FindByIDNullItemReturn) {
+ AbstractItem& child = IconTextItemTest::item->FindByID("not_existed_item");
+ ASSERT_EQ(child.GetType(), IconItem::NullObject);
+}
+
+TEST_F(IconTextItemTest, SerializeDeserialize) {
+ Bundle b = IconTextItemTest::item->Serialize();
+
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ auto gen_icon = std::static_pointer_cast<IconTextItem>(gen_item);
+ ASSERT_EQ(IconTextItemTest::item->GetIconItem().GetImagePath(), gen_icon->GetIconItem().GetImagePath());
+ ASSERT_EQ(IconTextItemTest::item->GetTextItem().GetContents(), gen_icon->GetTextItem().GetContents());
+}
diff --git a/unittest/src/test_image_item.cc b/unittest/src/test_image_item.cc
new file mode 100644
index 0000000..41db181
--- /dev/null
+++ b/unittest/src/test_image_item.cc
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/image_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+class ImageItemTest : public ::testing::Test {
+ public:
+ ImageItem* item;
+ std::string id = "image_id";
+ std::string imagePath = "image_path";
+ virtual void SetUp() {
+ item = new ImageItem(id, imagePath);
+ }
+ virtual void TearDown() {
+ delete item;
+ }
+};
+
+TEST_F(ImageItemTest, create) {
+ EXPECT_NE(ImageItemTest::item, nullptr);
+}
+
+TEST_F(ImageItemTest, FindByID) {
+ AbstractItem& child = ImageItemTest::item->FindByID(ImageItemTest::id);
+ ImageItem& image = static_cast<ImageItem&>(child);
+ ASSERT_EQ(image.GetImagePath(), ImageItemTest::imagePath);
+}
+
+TEST_F(ImageItemTest, FindByIDNullItemReturn) {
+ AbstractItem& child = ImageItemTest::item->FindByID("not_existed_item");
+ ASSERT_EQ(child.GetType(), ImageItem::NullObject);
+}
+
+TEST_F(ImageItemTest, SerializeDeserialize) {
+ Bundle b = ImageItemTest::item->Serialize();
+
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(ImageItemTest::item->GetType(), gen_item->GetType());
+
+ auto gen_image = std::static_pointer_cast<ImageItem>(gen_item);
+ ASSERT_EQ(ImageItemTest::item->GetImagePath(), gen_image->GetImagePath());
+}
diff --git a/unittest/src/test_input_selector_item.cc b/unittest/src/test_input_selector_item.cc
new file mode 100644
index 0000000..245f66b
--- /dev/null
+++ b/unittest/src/test_input_selector_item.cc
@@ -0,0 +1,47 @@
+// Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <gmock/gmock.h>
+
+#include "notification-ex/input_selector_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+using namespace std;
+
+namespace {
+
+class InputSelectorItemTest : public ::testing::Test {
+ protected:
+ void SetUp() override {}
+ void TearDown() override {}
+};
+
+TEST_F(InputSelectorItemTest, SerializeDeserialize) {
+ InputSelectorItem item;
+ list<string> contents;
+ contents.push_back("AA");
+ contents.push_back("BB");
+ contents.push_back("CC");
+ item.SetContents(contents);
+
+ Bundle b = item.Serialize();
+ shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(gen_item->GetType(), item.GetType());
+
+ auto gen_input = static_pointer_cast<InputSelectorItem>(gen_item);
+
+ list<string> l1 = item.GetContents();
+ list<string> l2 = gen_input->GetContents();
+ list<string>::iterator it1 = l1.begin();
+ list<string>::iterator it2 = l2.begin();
+ while(it1 != l1.end() && it2 != l2.end()) {
+ ASSERT_EQ((*it1), (*it2));
+ it1++;
+ it2++;
+ }
+}
+
+} // namespace
diff --git a/unittest/src/test_main.cc b/unittest/src/test_main.cc
new file mode 100644
index 0000000..4be05dc
--- /dev/null
+++ b/unittest/src/test_main.cc
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+int main(int argc, char** argv){
+ int ret = -1;
+ setenv("GCOV_PREFIX", "/tmp/", 1);
+ try {
+ testing::InitGoogleTest(&argc, argv);
+ } catch(...) {
+ std::cout << "Exception occurred" << std::endl;
+ }
+
+ try {
+ ret = RUN_ALL_TESTS();
+ } catch (const ::testing::internal::GoogleTestFailureException& e) {
+ ret = -1;
+ std::cout << "GoogleTestFailureException was thrown:" << e.what() << std::endl;
+ }
+
+ return ret;
+}
diff --git a/unittest/src/test_progress_item.cc b/unittest/src/test_progress_item.cc
new file mode 100644
index 0000000..6f3d5f8
--- /dev/null
+++ b/unittest/src/test_progress_item.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <gmock/gmock.h>
+
+#include "notification-ex/progress_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+using namespace std;
+
+namespace {
+
+class ProgressItemTest : public ::testing::Test {
+ protected:
+ void SetUp() override {}
+ void TearDown() override {}
+};
+
+TEST_F(ProgressItemTest, SerializeDeserializeGetTitle) {
+ ProgressItem item(1.0, 10.0, 100.0);
+ Bundle b = item.Serialize();
+ shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(gen_item->GetType(), item.GetType());
+
+ auto gen_progress = std::static_pointer_cast<ProgressItem>(gen_item);
+ ASSERT_EQ(item.GetCurrent(), gen_progress->GetCurrent());
+ ASSERT_EQ(item.GetMin(), gen_progress->GetMin());
+ ASSERT_EQ(item.GetMax(), gen_progress->GetMax());
+
+ ASSERT_EQ(gen_progress->GetMin(), 1.0);
+ ASSERT_EQ(gen_progress->GetCurrent(), 10.0);
+ ASSERT_EQ(gen_progress->GetMax(), 100.0);
+}
+
+} // namespace
diff --git a/unittest/src/test_text_item.cc b/unittest/src/test_text_item.cc
new file mode 100644
index 0000000..432a6a6
--- /dev/null
+++ b/unittest/src/test_text_item.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/text_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+namespace {
+
+class TexttItemTest : public ::testing::Test {
+ public:
+ virtual void SetUp() {
+ }
+ virtual void TearDown() {
+ }
+};
+
+TEST_F(TexttItemTest, FindByID) {
+ TextItem item("text_id", "contents", "hyperlink");
+
+ AbstractItem& child = item.FindByID("text_id");
+ TextItem& btn = static_cast<TextItem&>(child);
+ ASSERT_EQ(btn.GetContents(), "contents");
+}
+
+TEST_F(TexttItemTest, FindByIDNullItemReturn) {
+ TextItem item("text_id", "contents", "hyperlink");
+
+ AbstractItem& child = item.FindByID("not_existed_item");
+ ASSERT_EQ(child.GetType(), TextItem::NullObject);
+}
+
+TEST_F(TexttItemTest, SerializeDeserializeGetContents) {
+ TextItem item("text_id", "contents");
+ Bundle b = item.Serialize();
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(gen_item->GetType(), item.GetType());
+
+ auto gen_text = std::static_pointer_cast<TextItem>(gen_item);
+ ASSERT_EQ(item.GetContents(), gen_text->GetContents());
+}
+
+TEST_F(TexttItemTest, SetContentsGetContents) {
+ TextItem item("text_id", "contents");
+ ASSERT_EQ(item.GetContents(), "contents");
+
+ item.SetContents("changed");
+ ASSERT_EQ(item.GetContents(), "changed");
+}
+
+TEST_F(TexttItemTest, GetHyperLink) {
+ TextItem item("text_id", "contents");
+ ASSERT_TRUE(item.GetHyperLink().empty());
+
+ TextItem item2("text_id", "contents", "hyperlink2");
+ ASSERT_EQ(item2.GetHyperLink(), "hyperlink2");
+}
+
+} // namespace \ No newline at end of file
diff --git a/unittest/src/test_time_item.cc b/unittest/src/test_time_item.cc
new file mode 100644
index 0000000..fa149e5
--- /dev/null
+++ b/unittest/src/test_time_item.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/time_item.h"
+#include "notification-ex/item_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+class TimeItemTest : public ::testing::Test {
+ public:
+ TimeItem* item;
+ time_t current_time;
+ std::string id = "time_id";
+ virtual void SetUp() {
+ time(&current_time);
+ item = new TimeItem(id, current_time);
+ }
+ virtual void TearDown() {
+ delete item;
+ }
+};
+
+TEST_F(TimeItemTest, create) {
+ EXPECT_NE(TimeItemTest::item, nullptr);
+}
+
+TEST_F(TimeItemTest, FindByID) {
+ AbstractItem& child = TimeItemTest::item->FindByID(TimeItemTest::id);
+ TimeItem& time_ = static_cast<TimeItem&>(child);
+ ASSERT_EQ(time_.GetTime(), TimeItemTest::current_time);
+}
+
+TEST_F(TimeItemTest, FindByIDNullItemReturn) {
+ AbstractItem& child = TimeItemTest::item->FindByID("not_existed_item");
+ ASSERT_EQ(child.GetType(), TimeItem::NullObject);
+}
+
+TEST_F(TimeItemTest, SerializeDeserialize) {
+ Bundle b = TimeItemTest::item->Serialize();
+
+ std::shared_ptr<AbstractItem> gen_item = ItemInflator::Create(b);
+ ASSERT_EQ(TimeItemTest::item->GetType(), gen_item->GetType());
+
+ auto gen_time = std::static_pointer_cast<TimeItem>(gen_item);
+ ASSERT_EQ(item->GetTime(), gen_time->GetTime());
+}
diff --git a/unittest/src/test_visibility_action.cc b/unittest/src/test_visibility_action.cc
new file mode 100644
index 0000000..21c0c18
--- /dev/null
+++ b/unittest/src/test_visibility_action.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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 <string>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "notification-ex/visibility_action.h"
+#include "notification-ex/action_inflator.h"
+
+using namespace notification;
+using namespace notification::item;
+
+class VisibilityActionTest : public ::testing::Test {
+ public:
+ VisibilityAction* visibility;
+ std::string id = "visibility_id";
+ std::string extra = "visibility_extra";
+ bool visible = true;
+
+ virtual void SetUp() {
+ visibility = new VisibilityAction(extra);
+ visibility->SetVisibility("visibility_id", visible);
+ }
+ virtual void TearDown() {
+ delete visibility;
+ }
+};
+
+TEST_F(VisibilityActionTest, create) {
+ EXPECT_NE(VisibilityActionTest::visibility, nullptr);
+}
+
+TEST_F(VisibilityActionTest, IsLocal) {
+ ASSERT_EQ(VisibilityActionTest::visibility->IsLocal(), 1);
+}
+
+TEST_F(VisibilityActionTest, GetExtra) {
+ ASSERT_EQ(VisibilityActionTest::visibility->GetExtra(),
+ VisibilityActionTest::extra);
+}
+
+TEST_F(VisibilityActionTest, SerializeDeserialize) {
+ Bundle b = VisibilityActionTest::visibility->Serialize();
+
+ std::shared_ptr<AbstractAction> gen_action = ActionInflator::Create(b);
+ ASSERT_EQ(gen_action->GetType(), AbstractAction::Visibility);
+
+ auto gen_visibility_action =
+ std::static_pointer_cast<VisibilityAction>(gen_action);
+ EXPECT_NE(gen_visibility_action, nullptr);
+ ASSERT_EQ(gen_visibility_action->IsLocal(), true);
+ ASSERT_EQ(gen_visibility_action->GetExtra(), VisibilityActionTest::extra);
+}
+
+TEST_F(VisibilityActionTest, SetVisibility) {
+ VisibilityActionTest::visibility->SetVisibility("test_id", true);
+ Bundle b = VisibilityActionTest::visibility->Serialize();
+
+ std::shared_ptr<AbstractAction> gen_action = ActionInflator::Create(b);
+ ASSERT_EQ(gen_action->GetType(), AbstractAction::Visibility);
+
+ auto gen_visibility_action =
+ std::static_pointer_cast<VisibilityAction>(gen_action);
+ EXPECT_NE(gen_visibility_action, nullptr);
+ ASSERT_EQ(gen_visibility_action->IsLocal(), true);
+ ASSERT_EQ(gen_visibility_action->GetExtra(), VisibilityActionTest::extra);
+}