diff options
author | jusung son <jusung07.son@samsung.com> | 2019-03-29 14:39:55 +0900 |
---|---|---|
committer | jusung son <jusung07.son@samsung.com> | 2019-03-29 14:39:55 +0900 |
commit | 8cf6ca98110b621a6f5c33bb58bc1fd68af721d8 (patch) | |
tree | 3ff2da72787fd61e9adca1cb8b5892d870f892b5 | |
parent | 727ebe6820e16937c07f77ad92d9c467afaa8430 (diff) | |
parent | 18d51ef8a88e1ace447813be77134bafc71cdb07 (diff) | |
download | notification-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
173 files changed, 39239 insertions, 164 deletions
@@ -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(¤t_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, ¤t, &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, ¬i_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, ¬i_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, ¬i_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, ¬i_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, ¬i_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, ¬i_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, ¬i_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, ¬i_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, ¬i); + 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, ¬i); + 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)", ¬i_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)", ¬i_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)", ¬i_body); + notification_ipc_make_noti_from_gvariant(noti, noti_body); + *list = notification_list_append(*list, noti); + g_variant_unref(noti_body); + g_variant_unref(reply_body); + list_count--; + } + +out: + if (ret != NOTIFICATION_ERROR_NONE) + notification_free_list(*list); + if (data) + free(data); + + return ret; +} + +int notification_ipc_request_load_noti_grouping_list(notification_type_e type, + int count, int count_per_page, notification_list_h *list, uid_t uid) +{ +#define RCV_SOCK 0 +#define SND_SOCK 1 + int result; + int sockfd[2] = { 0, }; + int list_count; + GDBusMessage *reply = NULL; + GVariant *body; + GVariant *reply_body; + + 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)", ¬i_body); + notification_ipc_make_noti_from_gvariant(noti, noti_body); + *list = notification_list_append(*list, noti); + g_variant_unref(noti_body); + } + g_variant_iter_free(iter); + } + + 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)", ¬i_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)", ¬i_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", ¬i->type); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LAYOUT, "i", ¬i->layout); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_GROUP_ID, "i", ¬i->group_id); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_INTERNAL_GROUP_ID, "i", ¬i->internal_group_id); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_ID, "i", ¬i->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", ¬i->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", ¬i->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", ¬i->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", ¬i->led_operation); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_ARGB, "i", ¬i->led_argb); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_ON_MS, "i", ¬i->led_on_ms); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_OFF_MS, "i", ¬i->led_off_ms); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TIME, "i", ¬i->time); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_INSERT_TIME, "i", ¬i->insert_time); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_FLAGS_FOR_PROPERTY, "i", ¬i->flags_for_property); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DISPLAY_APPLIST, "i", ¬i->display_applist); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PROGRESS_SIZE, "d", ¬i->progress_size); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PROGRESS_PERCENTAGE, "d", ¬i->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", ¬i->ongoing_flag); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_VALUE_TYPE, "i", ¬i->ongoing_value_type); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_CURRENT, "i", ¬i->ongoing_current); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_DURATION, "i", ¬i->ongoing_duration); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_AUTO_REMOVE, "i", ¬i->auto_remove); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DEFAULT_BUTTON, "i", ¬i->default_button_index); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_HIDE_TIMEOUT, "i", ¬i->hide_timeout); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DELETE_TIMEOUT, "i", ¬i->delete_timeout); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEXT_INPUT_MAX_LENGTH, "i", ¬i->text_input_max_length); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EVENT_FLAG, "i", ¬i->event_flag); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TRANSLATION, "i", ¬i->is_translation); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EXTENSION_IMAGE_SIZE, "i", ¬i->extension_image_size); + _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_UID, "i", ¬i->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, ¬i_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(¤t_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(¤t_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(¤t_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); +} |