From: Junghoon Park Date: Tue, 17 Nov 2020 06:07:17 +0000 (+0900) Subject: Refactor app-core X-Git-Tag: submit/tizen/20220111.072059~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F12%2F247812%2F87;p=platform%2Fcore%2Fappfw%2Fapp-core.git Refactor app-core - Redesigned by c++ Change-Id: I7659cab20ca2599c74640f2e7fe84b609166c113 Signed-off-by: Junghoon Park Signed-off-by: jh9216.park --- diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 064881e..0000000 --- a/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -Jayoun Lee -Sewook Park -Jaeho Lee diff --git a/CMakeLists.txt b/CMakeLists.txt index 038b35e..e491eaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,156 +1,62 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(appcore C) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(appcore) + +SET(CMAKE_SKIP_BUILD_RPATH true) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(EXEC_PREFIX "\${prefix}") SET(LIBDIR ${LIB_INSTALL_DIR}) SET(INCLUDEDIR "\${prefix}/include") SET(VERSION ${FULLVER}) -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +#Target +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") -ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") +SET(TARGET_APP_CORE_CPP "app-core-cpp") +SET(TARGET_APP_CORE_UI_CPP "app-core-ui-cpp") +SET(TARGET_APP_CORE_EFL_CPP "app-core-efl-cpp") +SET(TARGET_APP_CORE_MULTI_WINDOW_CPP "app-core-multi-window-cpp") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs -pie" ) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") -SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -Wall") -SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,--as-needed") -SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror") -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") - -SET(CMAKE_SKIP_BUILD_RPATH TRUE) - -################################################################# -# Build appcore-common Library -# ------------------------------ -SET(APPCORE_COMMON "appcore-common") -SET(SRCS_common - src/legacy/appcore.c - src/legacy/appcore-measure.c - src/legacy/appcore-rotation.c - src/legacy/appcore-i18n.c - src/base/appcore_base.c - src/base/appcore_base_control.c - src/watchdog/appcore_watchdog.c) - -SET(HEADERS_common - appcore-common.h - appcore_base.h - appcore_watchdog.h - appcore_base_control.h) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -Wall -Werror") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") +SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") INCLUDE(FindPkgConfig) -SET(APPCORE_PKG_CHECK_MODULES "gio-2.0 vconf sensor aul dlog capi-system-info") - -pkg_check_modules(pkg_common REQUIRED ${APPCORE_PKG_CHECK_MODULES}) - -FOREACH(flag ${pkg_common_CFLAGS}) - SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} ${flag}") -ENDFOREACH(flag) - -ADD_LIBRARY(${APPCORE_COMMON} SHARED ${SRCS_common}) -SET_TARGET_PROPERTIES(${APPCORE_COMMON} PROPERTIES SOVERSION ${MAJORVER}) -SET_TARGET_PROPERTIES(${APPCORE_COMMON} PROPERTIES VERSION ${FULLVER}) -SET_TARGET_PROPERTIES(${APPCORE_COMMON} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_common}) -TARGET_LINK_LIBRARIES(${APPCORE_COMMON} ${pkg_common_LDFLAGS} "-ldl") - -CONFIGURE_FILE(${APPCORE_COMMON}.pc.in ${APPCORE_COMMON}.pc @ONLY) - -INSTALL(TARGETS ${APPCORE_COMMON} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_COMMON}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -FOREACH(hfile ${HEADERS_common}) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION include/appcore) -ENDFOREACH(hfile) - -################################################################# -# Build appcore-ui Library -# ------------------------------ -SET(APPCORE_UI "appcore-ui") -SET(SRCS_ui src/ui_base/appcore_ui_base.c src/ui_base/appcore_ui_plugin.c) -SET(HEADERS_ui appcore_ui_base.h) - -INCLUDE(FindPkgConfig) -SET(APPCORE_UI_PKG_CHECK_MODULES "dlog ecore gobject-2.0 glib-2.0 aul bundle pkgmgr-info ttrace ecore-wl2 tizen-extension-client wayland-client") - -pkg_check_modules(pkg_ui REQUIRED ${APPCORE_UI_PKG_CHECK_MODULES}) - -FOREACH(flag ${pkg_ui_CFLAGS}) - SET(EXTRA_CFLAGS_ui "${EXTRA_CFLAGS_ui} ${flag}") -ENDFOREACH(flag) - -ADD_LIBRARY(${APPCORE_UI} SHARED ${SRCS_ui}) -SET_TARGET_PROPERTIES(${APPCORE_UI} PROPERTIES SOVERSION ${MAJORVER}) -SET_TARGET_PROPERTIES(${APPCORE_UI} PROPERTIES VERSION ${FULLVER}) -SET_TARGET_PROPERTIES(${APPCORE_UI} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_ui}) -TARGET_LINK_LIBRARIES(${APPCORE_UI} ${pkg_ui_LDFLAGS} ${APPCORE_COMMON}) - -CONFIGURE_FILE(${APPCORE_UI}.pc.in ${APPCORE_UI}.pc @ONLY) - -INSTALL(TARGETS ${APPCORE_UI} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_UI}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -FOREACH(hfile ${HEADERS_ui}) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION include/appcore) -ENDFOREACH(hfile) - -################################################################# -# Build appcore-efl Library -# ------------------------------ -SET(APPCORE_EFL "appcore-efl") -SET(SRCS_efl src/legacy/appcore-efl.c src/efl_base/appcore_efl_base.c) -SET(HEADERS_efl appcore-efl.h appcore_efl_base.h) - -INCLUDE(FindPkgConfig) -SET(APPCORE_PKG_CHECK_MODULES2 "elementary dlog aul bundle ttrace") - -pkg_check_modules(pkg_efl REQUIRED ${APPCORE_PKG_CHECK_MODULES2}) - -FOREACH(flag ${pkg_efl_CFLAGS}) - SET(EXTRA_CFLAGS_efl "${EXTRA_CFLAGS_efl} ${flag}") -ENDFOREACH(flag) - -ADD_LIBRARY(${APPCORE_EFL} SHARED ${SRCS_efl}) -SET_TARGET_PROPERTIES(${APPCORE_EFL} PROPERTIES SOVERSION ${MAJORVER}) -SET_TARGET_PROPERTIES(${APPCORE_EFL} PROPERTIES VERSION ${FULLVER}) -SET_TARGET_PROPERTIES(${APPCORE_EFL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_efl}) -TARGET_LINK_LIBRARIES(${APPCORE_EFL} ${pkg_efl_LDFLAGS} ${APPCORE_UI}) - -CONFIGURE_FILE(${APPCORE_EFL}.pc.in ${APPCORE_EFL}.pc @ONLY) - -INSTALL(TARGETS ${APPCORE_EFL} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_EFL}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -FOREACH(hfile ${HEADERS_efl}) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION include/appcore) -ENDFOREACH(hfile) - -################################################################# -# Build appcore-multiwindow Library -# ------------------------------ -SET(APPCORE_MULTIWINDOW "appcore-multiwindow") -SET(SRCS_mw src/multiwindow_base/appcore_multiwindow_base.c - src/multiwindow_base/appcore_multiwindow_base_class.c - src/multiwindow_base/appcore_multiwindow_base_instance.c - src/multiwindow_base/appcore_multiwindow_base_window.c - ) -SET(HEADERS_mw appcore_multiwindow_base.h) - -INCLUDE(FindPkgConfig) -SET(APPCORE_MULTIWINDOW_PKG_CHECK_MODULES "dlog ecore gobject-2.0 glib-2.0 aul ecore-wl2") - -pkg_check_modules(pkg_mw REQUIRED ${APPCORE_MULTIWINDOW_PKG_CHECK_MODULES}) - -FOREACH(flag ${pkg_mw_CFLAGS}) - SET(EXTRA_CFLAGS_mw "${EXTRA_CFLAGS_mw} ${flag}") -ENDFOREACH(flag) - -ADD_LIBRARY(${APPCORE_MULTIWINDOW} SHARED ${SRCS_mw}) -SET_TARGET_PROPERTIES(${APPCORE_MULTIWINDOW} PROPERTIES SOVERSION ${MAJORVER}) -SET_TARGET_PROPERTIES(${APPCORE_MULTIWINDOW} PROPERTIES VERSION ${FULLVER}) -SET_TARGET_PROPERTIES(${APPCORE_MULTIWINDOW} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_mw}) -TARGET_LINK_LIBRARIES(${APPCORE_MULTIWINDOW} ${pkg_mw_LDFLAGS} ${APPCORE_COMMON}) - -CONFIGURE_FILE(${APPCORE_MULTIWINDOW}.pc.in ${APPCORE_MULTIWINDOW}.pc @ONLY) - -INSTALL(TARGETS ${APPCORE_MULTIWINDOW} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_MULTIWINDOW}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -FOREACH(hfile ${HEADERS_mw}) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION include/appcore) -ENDFOREACH(hfile) +INCLUDE(ApplyPkgConfig) + +PKG_CHECK_MODULES(AUL_DEPS REQUIRED aul) +PKG_CHECK_MODULES(BUNDLE_DEPS REQUIRED bundle) +PKG_CHECK_MODULES(CAPI_SYSTEM_INFO_DEPS REQUIRED capi-system-info) +PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog) +PKG_CHECK_MODULES(ECORE_DEPS REQUIRED ecore) +PKG_CHECK_MODULES(ECORE_WL2_DEPS REQUIRED ecore-wl2) +PKG_CHECK_MODULES(ELEMENTARY_DEPS REQUIRED elementary) +PKG_CHECK_MODULES(GIO_2_DEPS REQUIRED gio-2.0) +PKG_CHECK_MODULES(GLIB_2_DEPS REQUIRED glib-2.0) +PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock) +PKG_CHECK_MODULES(GOBJECT_2_DEPS REQUIRED gobject-2.0) +PKG_CHECK_MODULES(PKGMGR_INFO_DEPS REQUIRED pkgmgr-info) +PKG_CHECK_MODULES(SENSOR_DEPS REQUIRED sensor) +PKG_CHECK_MODULES(TIZEN_EXTENSION_CLIENT_DEPS REQUIRED tizen-extension-client) +PKG_CHECK_MODULES(TTRACE_DEPS REQUIRED ttrace) +PKG_CHECK_MODULES(VCONF_DEPS REQUIRED vconf) +PKG_CHECK_MODULES(WAYLAND_CLIENT_DEPS REQUIRED wayland-client) +PKG_CHECK_MODULES(WAYLAND_TBM_CLIENT_DEPS REQUIRED wayland-tbm-client) + +ADD_SUBDIRECTORY(legacy) +ADD_SUBDIRECTORY(tizen-cpp) + +IF(NOT DEFINED MINIMUM_BUILD) +ENABLE_TESTING() +SET(APP_CORE_UNITTESTS app-core_unittests) +ADD_TEST(NAME ${APP_CORE_UNITTESTS} COMMAND ${APP_CORE_UNITTESTS} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unittests) +ADD_SUBDIRECTORY(unittests) +ENDIF(NOT DEFINED MINIMUM_BUILD) diff --git a/TC/build.sh b/TC/build.sh deleted file mode 100755 index 98ebeff..0000000 --- a/TC/build.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -export TET_INSTALL_PATH=/scratchbox/tetware # local tetware path -export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target -export PATH=$TET_TARGET_PATH/bin:$PATH -export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH -export TET_ROOT=$TET_TARGET_PATH - -export TET_SUITE_ROOT=`pwd` -FILE_NAME_EXTENSION=`date +%s` - -RESULT_DIR=results -HTML_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.html -JOURNAL_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.journal - -mkdir -p $RESULT_DIR - -tcc -c -p ./ -tcc -b -j $JOURNAL_RESULT -p ./ -grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/TC/execute.sh b/TC/execute.sh deleted file mode 100755 index 2d9df79..0000000 --- a/TC/execute.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -#export TET_INSTALL_PATH=/mnt/nfs/tetware -export TET_INSTALL_PATH=/scratchbox/tetware -export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target -export PATH=$TET_TARGET_PATH/bin:$PATH -export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH - -export TET_ROOT=$TET_TARGET_PATH - -export TET_SUITE_ROOT=`pwd` -FILE_NAME_EXTENSION=`date +%s` - -RESULT_DIR=results -HTML_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.html -JOURNAL_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.journal - -mkdir -p $RESULT_DIR - -tcc -e -j $JOURNAL_RESULT -p ./ -grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/TC/tet_code b/TC/tet_code deleted file mode 100644 index a2cf6c1..0000000 --- a/TC/tet_code +++ /dev/null @@ -1,12 +0,0 @@ -# TET reserved codes -0 "PASS" -1 "FAIL" -2 "UNRESOLVED" -3 "NOTINUSE" -4 "UNSUPPORTED" -5 "UNTESTED" -6 "UNINITIATED" -7 "NORESULT" - -# Test suite additional codes -33 "INSPECT" diff --git a/TC/tet_scen b/TC/tet_scen deleted file mode 100644 index 43cbc9b..0000000 --- a/TC/tet_scen +++ /dev/null @@ -1,7 +0,0 @@ -all - ^TEST -##### Scenarios for TEST ##### - -# Test scenario -TEST - :include:/unit/tslist diff --git a/TC/tetbuild.cfg b/TC/tetbuild.cfg deleted file mode 100644 index 6192c78..0000000 --- a/TC/tetbuild.cfg +++ /dev/null @@ -1,3 +0,0 @@ -TET_OUTPUT_CAPTURE=False -TET_BUILD_TOOL=make -TET_PASS_TC_NAME=True diff --git a/TC/tetclean.cfg b/TC/tetclean.cfg deleted file mode 100644 index c66eda4..0000000 --- a/TC/tetclean.cfg +++ /dev/null @@ -1,2 +0,0 @@ -TET_OUTPUT_CAPTURE=False -TET_CLEAN_TOOL=make clean diff --git a/TC/tetexec.cfg b/TC/tetexec.cfg deleted file mode 100644 index 0d9d39a..0000000 --- a/TC/tetexec.cfg +++ /dev/null @@ -1 +0,0 @@ -TET_OUTPUT_CAPTURE=False diff --git a/TC/unit/Makefile b/TC/unit/Makefile deleted file mode 100644 index f967994..0000000 --- a/TC/unit/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -CC ?= gcc - -TARGETS = \ - utc_ApplicationFW_appcore_efl_main_func \ - utc_ApplicationFW_appcore_init_func \ - utc_ApplicationFW_appcore_exit_func \ - utc_ApplicationFW_appcore_set_rotation_cb_func \ - utc_ApplicationFW_appcore_unset_rotation_cb_func \ - utc_ApplicationFW_appcore_get_rotation_state_func \ - utc_ApplicationFW_appcore_set_i18n_func \ - utc_ApplicationFW_appcore_measure_start_func \ - utc_ApplicationFW_appcore_measure_time_func \ - utc_ApplicationFW_appcore_measure_time_from_func \ - utc_ApplicationFW_appcore_set_event_callback_func - -PKGS = appcore-efl - -LDFLAGS = `pkg-config --libs $(PKGS)` -LDFLAGS += $(TET_ROOT)/lib/tet3/tcm_s.o -LDFLAGS += -L$(TET_ROOT)/lib/tet3 -ltcm_s -LDFLAGS += -L$(TET_ROOT)/lib/tet3 -lapi_s - -CFLAGS = -I. `pkg-config --cflags $(PKGS)` -CFLAGS += -I$(TET_ROOT)/inc/tet3 -CFLAGS += -Wall - -all: $(TARGETS) - -$(TARGETS): %: %.c - $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) - -clean: - rm -f $(TARGETS) diff --git a/TC/unit/tc_gen.sh b/TC/unit/tc_gen.sh deleted file mode 100755 index 54f482d..0000000 --- a/TC/unit/tc_gen.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -TMPSTR=$0 -SCRIPT=${TMPSTR##*/} - -if [ $# -lt 2 ]; then - echo "Usage) $SCRIPT module_name api_name" - exit 1 -fi - -MODULE=$1 -API=$2 -TEMPLATE=utc_MODULE_API_func.c.in -TESTCASE=utc_${MODULE}_${API}_func - -sed -e ' - s^@API@^'"$API"'^g - s^@MODULE@^'"$MODULE"'^g - ' $TEMPLATE > $TESTCASE.c - -if [ ! -e "$TESTCASE.c" ]; then - echo "Failed" - exit 1 -fi -echo "Testcase file is $TESTCASE.c" -echo "Done" -echo "please put \"$TESTCASE\" as Target in Makefile" -echo "please put \"/unit/$TESTCASE\" in tslist" diff --git a/TC/unit/tslist b/TC/unit/tslist deleted file mode 100644 index 91c8d1a..0000000 --- a/TC/unit/tslist +++ /dev/null @@ -1,11 +0,0 @@ -/unit/utc_ApplicationFW_appcore_efl_main_func -/unit/utc_ApplicationFW_appcore_init_func -/unit/utc_ApplicationFW_appcore_exit_func -/unit/utc_ApplicationFW_appcore_set_rotation_cb_func -/unit/utc_ApplicationFW_appcore_unset_rotation_cb_func -/unit/utc_ApplicationFW_appcore_get_rotation_state_func -/unit/utc_ApplicationFW_appcore_set_i18n_func -/unit/utc_ApplicationFW_appcore_measure_start_func -/unit/utc_ApplicationFW_appcore_measure_time_func -/unit/utc_ApplicationFW_appcore_measure_time_from_func -/unit/utc_ApplicationFW_appcore_set_event_callback_func diff --git a/TC/unit/utc_ApplicationFW_appcore_efl_main_func.c b/TC/unit/utc_ApplicationFW_appcore_efl_main_func.c deleted file mode 100644 index eacd09e..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_efl_main_func.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_efl_main_func_01(void); -static void utc_ApplicationFW_appcore_efl_main_func_02(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_efl_main_func_01, POSITIVE_TC_IDX }, - { utc_ApplicationFW_appcore_efl_main_func_02, NEGATIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ -} - -static int app_reset(bundle *b, void *data) -{ - elm_exit(); - return 0; -} - -/** - * @brief Positive test case of appcore_efl_main() - */ -static void utc_ApplicationFW_appcore_efl_main_func_01(void) -{ - int r = 0; - int argc = 1; - char *_argv[] = { - "Testcase", - NULL, - }; - char **argv; - struct appcore_ops ops = { - .reset = app_reset, - }; - - argv = _argv; - r = appcore_efl_main("Testcase", &argc, &argv, &ops); - printf("Return %d\n", r); - if (r) { - tet_infoline("appcore_efl_main() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} - -/** - * @brief Negative test case of ug_init appcore_efl_main() - */ -static void utc_ApplicationFW_appcore_efl_main_func_02(void) -{ - int r = 0; - int argc = 1; - char *_argv[] = { - "Testcase", - NULL, - }; - char **argv; - struct appcore_ops ops = { - .reset = app_reset, - }; - - argv = _argv; - r = appcore_efl_main("Testcase", &argc, &argv, NULL); - if (!r) { - tet_infoline("appcore_efl_main() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - r = appcore_efl_main(NULL, &argc, &argv, &ops); - if (!r) { - tet_infoline("appcore_efl_main() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - r = appcore_efl_main("Testcase", NULL, &argv, &ops); - if (!r) { - tet_infoline("appcore_efl_main() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - r = appcore_efl_main("Testcase", &argc, NULL, &ops); - if (!r) { - tet_infoline("appcore_efl_main() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - tet_result(TET_PASS); -} diff --git a/TC/unit/utc_ApplicationFW_appcore_exit_func.c b/TC/unit/utc_ApplicationFW_appcore_exit_func.c deleted file mode 100644 index b74e9a6..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_exit_func.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_exit_func_01(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_exit_func_01, POSITIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ -} - -/** - * @brief Positive test case of appcore_exit() - */ -static void utc_ApplicationFW_appcore_exit_func_01(void) -{ - appcore_exit(); - tet_result(TET_PASS); -} - diff --git a/TC/unit/utc_ApplicationFW_appcore_get_rotation_state_func.c b/TC/unit/utc_ApplicationFW_appcore_get_rotation_state_func.c deleted file mode 100644 index 45c0226..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_get_rotation_state_func.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_get_rotation_state_func_01(void); -static void utc_ApplicationFW_appcore_get_rotation_state_func_02(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_get_rotation_state_func_01, POSITIVE_TC_IDX }, - { utc_ApplicationFW_appcore_get_rotation_state_func_02, NEGATIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ -} - -/** - * @brief Positive test case of appcore_get_rotation_state() - */ -static void utc_ApplicationFW_appcore_get_rotation_state_func_01(void) -{ - int r = 0; - enum appcore_rm curr; - - r = appcore_get_rotation_state(&curr); - if (r) { - tet_infoline("appcore_get_rotation_state() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} - -/** - * @brief Negative test case of ug_init appcore_get_rotation_state() - */ -static void utc_ApplicationFW_appcore_get_rotation_state_func_02(void) -{ - int r = 0; - - r = appcore_get_rotation_state(NULL); - if (!r) { - tet_infoline("appcore_get_rotation_state() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} diff --git a/TC/unit/utc_ApplicationFW_appcore_init_func.c b/TC/unit/utc_ApplicationFW_appcore_init_func.c deleted file mode 100644 index 3c0e283..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_init_func.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -struct ui_ops { - void *data; - void (*cb_app)(int, void *, bundle *); -}; - - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_init_func_01(void); -static void utc_ApplicationFW_appcore_init_func_02(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_init_func_01, POSITIVE_TC_IDX }, - { utc_ApplicationFW_appcore_init_func_02, NEGATIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ - appcore_exit(); -} - -static void ui_cb(int evt, void *data, bundle *b) -{ -} - -/** - * @brief Positive test case of appcore_init() - */ -static void utc_ApplicationFW_appcore_init_func_01(void) -{ - int r = 0; - int argc = 1; - char *argv[] = { - "Testcase", - NULL, - }; - const struct ui_ops ops = { - .cb_app = ui_cb, - }; - - r = appcore_init("Testcase", &ops, argc, argv); - if (r) { - tet_infoline("appcore_init() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} - -/** - * @brief Negative test case of ug_init appcore_init() - */ -static void utc_ApplicationFW_appcore_init_func_02(void) -{ - int r = 0; - int argc = 1; - char *argv[] = { - "Testcase", - NULL, - }; - const struct ui_ops ops = { - .cb_app = ui_cb, - }; - - r = appcore_init(NULL, &ops, argc, argv); - if (!r) { - tet_infoline("appcore_init() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - r = appcore_init("Testcase", NULL, argc, argv); - if (!r) { - tet_infoline("appcore_init() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - r = appcore_init("Testcase", &ops, -1, argv); - if (!r) { - tet_infoline("appcore_init() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - r = appcore_init("Testcase", &ops, argc, NULL); - if (!r) { - tet_infoline("appcore_init() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - tet_result(TET_PASS); -} diff --git a/TC/unit/utc_ApplicationFW_appcore_measure_start_func.c b/TC/unit/utc_ApplicationFW_appcore_measure_start_func.c deleted file mode 100644 index 30eb144..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_measure_start_func.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_measure_start_func_01(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_measure_start_func_01, POSITIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ -} - -/** - * @brief Positive test case of appcore_measure_start() - */ -static void utc_ApplicationFW_appcore_measure_start_func_01(void) -{ - appcore_measure_start(); - tet_result(TET_PASS); -} - diff --git a/TC/unit/utc_ApplicationFW_appcore_measure_time_from_func.c b/TC/unit/utc_ApplicationFW_appcore_measure_time_from_func.c deleted file mode 100644 index 8af350b..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_measure_time_from_func.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include -#include -#include -#include - -#define APPCORE_TESTCASE "APPCORE_TESTCASE" - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_measure_time_from_func_01(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_measure_time_from_func_01, POSITIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ - struct timeval tv; - char buf[1024]; - - gettimeofday(&tv, NULL); - - snprintf(buf, sizeof(buf), "%d %d", (int)tv.tv_sec, (int)tv.tv_usec); - setenv(APPCORE_TESTCASE, buf, 1); -} - -static void cleanup(void) -{ -} - -/** - * @brief Positive test case of appcore_measure_time_from() - */ -static void utc_ApplicationFW_appcore_measure_time_from_func_01(void) -{ - int r = 0; - - r = appcore_measure_time_from(APPCORE_TESTCASE); - if (!r) { - tet_infoline("appcore_measure_time_from() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - - unsetenv(APPCORE_TESTCASE); - - r = appcore_measure_time_from(APPCORE_TESTCASE); - if (r) { - tet_infoline("appcore_measure_time_from() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - - tet_result(TET_PASS); -} - diff --git a/TC/unit/utc_ApplicationFW_appcore_measure_time_func.c b/TC/unit/utc_ApplicationFW_appcore_measure_time_func.c deleted file mode 100644 index 245cd9f..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_measure_time_func.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_measure_time_func_01(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_measure_time_func_01, POSITIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ - appcore_measure_start(); -} - -static void cleanup(void) -{ -} - -/** - * @brief Positive test case of appcore_measure_time() - */ -static void utc_ApplicationFW_appcore_measure_time_func_01(void) -{ - int r = 0; - - r = appcore_measure_time(); - if (r == 0) { - tet_infoline("appcore_measure_time() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} - diff --git a/TC/unit/utc_ApplicationFW_appcore_set_event_callback_func.c b/TC/unit/utc_ApplicationFW_appcore_set_event_callback_func.c deleted file mode 100644 index 6cb792c..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_set_event_callback_func.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_set_event_callback_func_01(void); -static void utc_ApplicationFW_appcore_set_event_callback_func_02(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_set_event_callback_func_01, POSITIVE_TC_IDX }, - { utc_ApplicationFW_appcore_set_event_callback_func_02, NEGATIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ -} - -static int cb(void *data) -{ - - return 0; -} - - -/** - * @brief Positive test case of appcore_set_event_callback() - */ -static void utc_ApplicationFW_appcore_set_event_callback_func_01(void) -{ - int r = 0; - - r = appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, cb, NULL); - if (r) { - tet_infoline("appcore_set_event_callback() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - - r = appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, NULL, NULL); - if (r) { - tet_infoline("appcore_set_event_callback() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - - tet_result(TET_PASS); -} - -/** - * @brief Negative test case of ug_init appcore_set_event_callback() - */ -static void utc_ApplicationFW_appcore_set_event_callback_func_02(void) -{ - int r = 0; - - r = appcore_set_event_callback(-1, cb, NULL); - if (!r) { - tet_infoline("appcore_set_event_callback() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} diff --git a/TC/unit/utc_ApplicationFW_appcore_set_i18n_func.c b/TC/unit/utc_ApplicationFW_appcore_set_i18n_func.c deleted file mode 100644 index 6ec6522..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_set_i18n_func.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_set_i18n_func_01(void); -static void utc_ApplicationFW_appcore_set_i18n_func_02(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_set_i18n_func_01, POSITIVE_TC_IDX }, - { utc_ApplicationFW_appcore_set_i18n_func_02, NEGATIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ -} - -/** - * @brief Positive test case of appcore_set_i18n() - */ -static void utc_ApplicationFW_appcore_set_i18n_func_01(void) -{ - int r = 0; - - r = appcore_set_i18n("Testcase", NULL); - if (r) { - tet_infoline("appcore_set_i18n() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} - -/** - * @brief Negative test case of ug_init appcore_set_i18n() - */ -static void utc_ApplicationFW_appcore_set_i18n_func_02(void) -{ - int r = 0; - - r = appcore_set_i18n(NULL, NULL); - if (!r) { - tet_infoline("appcore_set_i18n() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - - tet_result(TET_PASS); -} diff --git a/TC/unit/utc_ApplicationFW_appcore_set_rotation_cb_func.c b/TC/unit/utc_ApplicationFW_appcore_set_rotation_cb_func.c deleted file mode 100644 index 79a3738..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_set_rotation_cb_func.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_set_rotation_cb_func_01(void); -static void utc_ApplicationFW_appcore_set_rotation_cb_func_02(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_set_rotation_cb_func_01, POSITIVE_TC_IDX }, - { utc_ApplicationFW_appcore_set_rotation_cb_func_02, NEGATIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ -} - -static int rot_cb(enum appcore_rm rm, void *data) -{ - - return 0; -} - -/** - * @brief Positive test case of appcore_set_rotation_cb() - */ -static void utc_ApplicationFW_appcore_set_rotation_cb_func_01(void) -{ - int r = 0; - - r = appcore_set_rotation_cb(rot_cb, NULL); - if (r) { - tet_infoline("appcore_set_rotation_cb() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} - -/** - * @brief Negative test case of ug_init appcore_set_rotation_cb() - */ -static void utc_ApplicationFW_appcore_set_rotation_cb_func_02(void) -{ - int r = 0; - - r = appcore_set_rotation_cb(NULL, NULL); - if (!r) { - tet_infoline("appcore_set_rotation_cb() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} diff --git a/TC/unit/utc_ApplicationFW_appcore_unset_rotation_cb_func.c b/TC/unit/utc_ApplicationFW_appcore_unset_rotation_cb_func.c deleted file mode 100644 index 493315c..0000000 --- a/TC/unit/utc_ApplicationFW_appcore_unset_rotation_cb_func.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_ApplicationFW_appcore_unset_rotation_cb_func_01(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_ApplicationFW_appcore_unset_rotation_cb_func_01, POSITIVE_TC_IDX }, - { NULL, 0}, -}; - -static void startup(void) -{ -} - -static void cleanup(void) -{ -} - -/** - * @brief Positive test case of appcore_unset_rotation_cb() - */ -static void utc_ApplicationFW_appcore_unset_rotation_cb_func_01(void) -{ - int r = 0; - - r = appcore_unset_rotation_cb(); - if (r) { - tet_infoline("appcore_unset_rotation_cb() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} - diff --git a/TC/unit/utc_MODULE_API_func.c.in b/TC/unit/utc_MODULE_API_func.c.in deleted file mode 100644 index bf9f90c..0000000 --- a/TC/unit/utc_MODULE_API_func.c.in +++ /dev/null @@ -1,76 +0,0 @@ -#include - -static void startup(void); -static void cleanup(void); - -void (*tet_startup)(void) = startup; -void (*tet_cleanup)(void) = cleanup; - -static void utc_@MODULE@_@API@_func_01(void); -static void utc_@MODULE@_@API@_func_02(void); - -enum { - POSITIVE_TC_IDX = 0x01, - NEGATIVE_TC_IDX, -}; - -struct tet_testlist tet_testlist[] = { - { utc_@MODULE@_@API@_func_01, POSITIVE_TC_IDX }, - { utc_@MODULE@_@API@_func_02, NEGATIVE_TC_IDX }, -}; - -static void startup(void) -{ - int r; -/* - char *err; - r = initailze...; - if (r) { - err = "Error message......."; - tet_infoline(err); - tet_delete(POSITIVE_TC_IDX, err); - tet_delete(NEGATIVE_TC_IDX, err); - } -*/ - -} - -static void cleanup(void) -{ -} - -/** - * @brief Positive test case of @API@() - */ -static void utc_@MODULE@_@API@_func_01(void) -{ - int r = 0; - -/* - r = @API@(...); -*/ - if (r) { - tet_infoline("@API@() failed in positive test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} - -/** - * @brief Negative test case of ug_init @API@() - */ -static void utc_@MODULE@_@API@_func_02(void) -{ - int r = 0; - -/* - r = @API@(...); -*/ - if (!r) { - tet_infoline("@API@() failed in negative test case"); - tet_result(TET_FAIL); - return; - } - tet_result(TET_PASS); -} diff --git a/cmake/Modules/ApplyPkgConfig.cmake b/cmake/Modules/ApplyPkgConfig.cmake new file mode 100644 index 0000000..97679d7 --- /dev/null +++ b/cmake/Modules/ApplyPkgConfig.cmake @@ -0,0 +1,35 @@ +# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# +# This function applies external (out of source tree) dependencies +# to given target. Arguments are: +# TARGET - valid cmake target +# PRIVACY - dependency can be inherited by dependent targets or not: +# PUBLIC - this should be used by default, cause compile/link flags passing +# PRIVATE - do not passes any settings to dependent targets, +# may be usefull for static libraries from the inside of the project +# Argument ARGV2 and following are supposed to be names of checked pkg config +# packages. This function will use variables created by check_pkg_modules(). +# - ${DEP_NAME}_LIBRARIES +# - ${DEP_NAME}_INCLUDE_DIRS +# - ${DEP_NAME}_CFLAGS +# +FUNCTION(APPLY_PKG_CONFIG TARGET PRIVACY) + MATH(EXPR DEST_INDEX "${ARGC}-1") + FOREACH(I RANGE 2 ${DEST_INDEX}) + IF(NOT ${ARGV${I}}_FOUND) + MESSAGE(FATAL_ERROR "Not found dependency - ${ARGV${I}}_FOUND") + ENDIF(NOT ${ARGV${I}}_FOUND) + TARGET_LINK_LIBRARIES(${TARGET} ${PRIVACY} "${${ARGV${I}}_LIBRARIES}") + TARGET_INCLUDE_DIRECTORIES(${TARGET} ${PRIVACY} SYSTEM "${${ARGV${I}}_INCLUDE_DIRS}") + STRING(REPLACE ";" " " CFLAGS_STR "${${ARGV${I}}_CFLAGS}") + SET(CFLAGS_LIST ${CFLAGS_STR}) + SEPARATE_ARGUMENTS(CFLAGS_LIST) + FOREACH(OPTION ${CFLAGS_LIST}) + TARGET_COMPILE_OPTIONS(${TARGET} ${PRIVACY} ${OPTION}) + ENDFOREACH(OPTION) + SET_TARGET_PROPERTIES(${TARGET} PROPERTIES SKIP_BUILD_RPATH true) + ENDFOREACH(I RANGE 2 ${DEST_INDEX}) +ENDFUNCTION(APPLY_PKG_CONFIG TARGET PRIVACY) diff --git a/legacy/CMakeLists.txt b/legacy/CMakeLists.txt new file mode 100644 index 0000000..622e737 --- /dev/null +++ b/legacy/CMakeLists.txt @@ -0,0 +1,156 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(appcore C) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR ${LIB_INSTALL_DIR}) +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION ${FULLVER}) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/legacy/include) + +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -Wall") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,--as-needed") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +SET(CMAKE_SKIP_BUILD_RPATH TRUE) + +################################################################# +# Build appcore-common Library +# ------------------------------ +SET(APPCORE_COMMON "appcore-common") +SET(SRCS_common + src/legacy/appcore.c + src/legacy/appcore-measure.c + src/legacy/appcore-rotation.c + src/legacy/appcore-i18n.c + src/base/appcore_base.c + src/base/appcore_base_control.c + src/watchdog/appcore_watchdog.c) + +SET(HEADERS_common + appcore-common.h + appcore_base.h + appcore_watchdog.h + appcore_base_control.h) + +INCLUDE(FindPkgConfig) +SET(APPCORE_PKG_CHECK_MODULES "gio-2.0 vconf sensor aul dlog capi-system-info ttrace pkgmgr-info") + +pkg_check_modules(pkg_common REQUIRED ${APPCORE_PKG_CHECK_MODULES}) + +FOREACH(flag ${pkg_common_CFLAGS}) + SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${APPCORE_COMMON} SHARED ${SRCS_common}) +SET_TARGET_PROPERTIES(${APPCORE_COMMON} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${APPCORE_COMMON} PROPERTIES VERSION ${FULLVER}) +SET_TARGET_PROPERTIES(${APPCORE_COMMON} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_common}) +TARGET_LINK_LIBRARIES(${APPCORE_COMMON} ${pkg_common_LDFLAGS} "-ldl") + +CONFIGURE_FILE(${APPCORE_COMMON}.pc.in ${APPCORE_COMMON}.pc @ONLY) + +INSTALL(TARGETS ${APPCORE_COMMON} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_COMMON}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +FOREACH(hfile ${HEADERS_common}) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION include/appcore) +ENDFOREACH(hfile) + +################################################################# +# Build appcore-ui Library +# ------------------------------ +SET(APPCORE_UI "appcore-ui") +SET(SRCS_ui src/ui_base/appcore_ui_base.c src/ui_base/appcore_ui_plugin.c) +SET(HEADERS_ui appcore_ui_base.h) + +INCLUDE(FindPkgConfig) +SET(APPCORE_UI_PKG_CHECK_MODULES "dlog ecore gobject-2.0 glib-2.0 aul bundle pkgmgr-info ttrace ecore-wl2 tizen-extension-client wayland-client") + +pkg_check_modules(pkg_ui REQUIRED ${APPCORE_UI_PKG_CHECK_MODULES}) + +FOREACH(flag ${pkg_ui_CFLAGS}) + SET(EXTRA_CFLAGS_ui "${EXTRA_CFLAGS_ui} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${APPCORE_UI} SHARED ${SRCS_ui}) +SET_TARGET_PROPERTIES(${APPCORE_UI} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${APPCORE_UI} PROPERTIES VERSION ${FULLVER}) +SET_TARGET_PROPERTIES(${APPCORE_UI} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_ui}) +TARGET_LINK_LIBRARIES(${APPCORE_UI} ${pkg_ui_LDFLAGS} ${APPCORE_COMMON}) + +CONFIGURE_FILE(${APPCORE_UI}.pc.in ${APPCORE_UI}.pc @ONLY) + +INSTALL(TARGETS ${APPCORE_UI} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_UI}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +FOREACH(hfile ${HEADERS_ui}) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION include/appcore) +ENDFOREACH(hfile) + +################################################################# +# Build appcore-efl Library +# ------------------------------ +SET(APPCORE_EFL "appcore-efl") +SET(SRCS_efl src/legacy/appcore-efl.c src/efl_base/appcore_efl_base.c) +SET(HEADERS_efl appcore-efl.h appcore_efl_base.h) + +INCLUDE(FindPkgConfig) +SET(APPCORE_PKG_CHECK_MODULES2 "elementary dlog aul bundle ttrace") + +pkg_check_modules(pkg_efl REQUIRED ${APPCORE_PKG_CHECK_MODULES2}) + +FOREACH(flag ${pkg_efl_CFLAGS}) + SET(EXTRA_CFLAGS_efl "${EXTRA_CFLAGS_efl} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${APPCORE_EFL} SHARED ${SRCS_efl}) +SET_TARGET_PROPERTIES(${APPCORE_EFL} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${APPCORE_EFL} PROPERTIES VERSION ${FULLVER}) +SET_TARGET_PROPERTIES(${APPCORE_EFL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_efl}) +TARGET_LINK_LIBRARIES(${APPCORE_EFL} ${pkg_efl_LDFLAGS} ${APPCORE_UI}) + +CONFIGURE_FILE(${APPCORE_EFL}.pc.in ${APPCORE_EFL}.pc @ONLY) + +INSTALL(TARGETS ${APPCORE_EFL} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_EFL}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +FOREACH(hfile ${HEADERS_efl}) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION include/appcore) +ENDFOREACH(hfile) + +################################################################# +# Build appcore-multiwindow Library +# ------------------------------ +SET(APPCORE_MULTIWINDOW "appcore-multiwindow") +SET(SRCS_mw src/multiwindow_base/appcore_multiwindow_base.c + src/multiwindow_base/appcore_multiwindow_base_class.c + src/multiwindow_base/appcore_multiwindow_base_instance.c + src/multiwindow_base/appcore_multiwindow_base_window.c + ) +SET(HEADERS_mw appcore_multiwindow_base.h) + +INCLUDE(FindPkgConfig) +SET(APPCORE_MULTIWINDOW_PKG_CHECK_MODULES "dlog ecore gobject-2.0 glib-2.0 aul ecore-wl2") + +pkg_check_modules(pkg_mw REQUIRED ${APPCORE_MULTIWINDOW_PKG_CHECK_MODULES}) + +FOREACH(flag ${pkg_mw_CFLAGS}) + SET(EXTRA_CFLAGS_mw "${EXTRA_CFLAGS_mw} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${APPCORE_MULTIWINDOW} SHARED ${SRCS_mw}) +SET_TARGET_PROPERTIES(${APPCORE_MULTIWINDOW} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${APPCORE_MULTIWINDOW} PROPERTIES VERSION ${FULLVER}) +SET_TARGET_PROPERTIES(${APPCORE_MULTIWINDOW} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_mw}) +TARGET_LINK_LIBRARIES(${APPCORE_MULTIWINDOW} ${pkg_mw_LDFLAGS} ${APPCORE_COMMON}) + +CONFIGURE_FILE(${APPCORE_MULTIWINDOW}.pc.in ${APPCORE_MULTIWINDOW}.pc @ONLY) + +INSTALL(TARGETS ${APPCORE_MULTIWINDOW} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPCORE_MULTIWINDOW}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +FOREACH(hfile ${HEADERS_mw}) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${hfile} DESTINATION include/appcore) +ENDFOREACH(hfile) diff --git a/appcore-common.pc.in b/legacy/appcore-common.pc.in similarity index 100% rename from appcore-common.pc.in rename to legacy/appcore-common.pc.in diff --git a/appcore-efl.pc.in b/legacy/appcore-efl.pc.in similarity index 100% rename from appcore-efl.pc.in rename to legacy/appcore-efl.pc.in diff --git a/appcore-multiwindow.pc.in b/legacy/appcore-multiwindow.pc.in similarity index 100% rename from appcore-multiwindow.pc.in rename to legacy/appcore-multiwindow.pc.in diff --git a/appcore-ui.pc.in b/legacy/appcore-ui.pc.in similarity index 100% rename from appcore-ui.pc.in rename to legacy/appcore-ui.pc.in diff --git a/include/appcore-common.h b/legacy/include/appcore-common.h similarity index 100% rename from include/appcore-common.h rename to legacy/include/appcore-common.h diff --git a/include/appcore-efl.h b/legacy/include/appcore-efl.h similarity index 100% rename from include/appcore-efl.h rename to legacy/include/appcore-efl.h diff --git a/include/appcore-internal.h b/legacy/include/appcore-internal.h similarity index 100% rename from include/appcore-internal.h rename to legacy/include/appcore-internal.h diff --git a/include/appcore_base.h b/legacy/include/appcore_base.h similarity index 100% rename from include/appcore_base.h rename to legacy/include/appcore_base.h diff --git a/include/appcore_base_control.h b/legacy/include/appcore_base_control.h similarity index 100% rename from include/appcore_base_control.h rename to legacy/include/appcore_base_control.h diff --git a/include/appcore_efl_base.h b/legacy/include/appcore_efl_base.h similarity index 100% rename from include/appcore_efl_base.h rename to legacy/include/appcore_efl_base.h diff --git a/include/appcore_multiwindow_base.h b/legacy/include/appcore_multiwindow_base.h similarity index 100% rename from include/appcore_multiwindow_base.h rename to legacy/include/appcore_multiwindow_base.h diff --git a/include/appcore_ui_base.h b/legacy/include/appcore_ui_base.h similarity index 100% rename from include/appcore_ui_base.h rename to legacy/include/appcore_ui_base.h diff --git a/include/appcore_ui_plugin.h b/legacy/include/appcore_ui_plugin.h similarity index 100% rename from include/appcore_ui_plugin.h rename to legacy/include/appcore_ui_plugin.h diff --git a/include/appcore_watchdog.h b/legacy/include/appcore_watchdog.h similarity index 100% rename from include/appcore_watchdog.h rename to legacy/include/appcore_watchdog.h diff --git a/src/base/appcore_base.c b/legacy/src/base/appcore_base.c similarity index 100% rename from src/base/appcore_base.c rename to legacy/src/base/appcore_base.c diff --git a/src/base/appcore_base_control.c b/legacy/src/base/appcore_base_control.c similarity index 100% rename from src/base/appcore_base_control.c rename to legacy/src/base/appcore_base_control.c diff --git a/src/base/appcore_base_private.h b/legacy/src/base/appcore_base_private.h similarity index 100% rename from src/base/appcore_base_private.h rename to legacy/src/base/appcore_base_private.h diff --git a/src/efl_base/appcore_efl_base.c b/legacy/src/efl_base/appcore_efl_base.c similarity index 100% rename from src/efl_base/appcore_efl_base.c rename to legacy/src/efl_base/appcore_efl_base.c diff --git a/src/efl_base/appcore_efl_base_private.h b/legacy/src/efl_base/appcore_efl_base_private.h similarity index 100% rename from src/efl_base/appcore_efl_base_private.h rename to legacy/src/efl_base/appcore_efl_base_private.h diff --git a/src/legacy/appcore-efl.c b/legacy/src/legacy/appcore-efl.c similarity index 100% rename from src/legacy/appcore-efl.c rename to legacy/src/legacy/appcore-efl.c diff --git a/src/legacy/appcore-i18n.c b/legacy/src/legacy/appcore-i18n.c similarity index 100% rename from src/legacy/appcore-i18n.c rename to legacy/src/legacy/appcore-i18n.c diff --git a/src/legacy/appcore-measure.c b/legacy/src/legacy/appcore-measure.c similarity index 100% rename from src/legacy/appcore-measure.c rename to legacy/src/legacy/appcore-measure.c diff --git a/src/legacy/appcore-rotation.c b/legacy/src/legacy/appcore-rotation.c similarity index 100% rename from src/legacy/appcore-rotation.c rename to legacy/src/legacy/appcore-rotation.c diff --git a/src/legacy/appcore.c b/legacy/src/legacy/appcore.c similarity index 100% rename from src/legacy/appcore.c rename to legacy/src/legacy/appcore.c diff --git a/src/multiwindow_base/appcore_multiwindow_base.c b/legacy/src/multiwindow_base/appcore_multiwindow_base.c similarity index 100% rename from src/multiwindow_base/appcore_multiwindow_base.c rename to legacy/src/multiwindow_base/appcore_multiwindow_base.c diff --git a/src/multiwindow_base/appcore_multiwindow_base_class.c b/legacy/src/multiwindow_base/appcore_multiwindow_base_class.c similarity index 100% rename from src/multiwindow_base/appcore_multiwindow_base_class.c rename to legacy/src/multiwindow_base/appcore_multiwindow_base_class.c diff --git a/src/multiwindow_base/appcore_multiwindow_base_instance.c b/legacy/src/multiwindow_base/appcore_multiwindow_base_instance.c similarity index 100% rename from src/multiwindow_base/appcore_multiwindow_base_instance.c rename to legacy/src/multiwindow_base/appcore_multiwindow_base_instance.c diff --git a/src/multiwindow_base/appcore_multiwindow_base_private.h b/legacy/src/multiwindow_base/appcore_multiwindow_base_private.h similarity index 100% rename from src/multiwindow_base/appcore_multiwindow_base_private.h rename to legacy/src/multiwindow_base/appcore_multiwindow_base_private.h diff --git a/src/multiwindow_base/appcore_multiwindow_base_window.c b/legacy/src/multiwindow_base/appcore_multiwindow_base_window.c similarity index 100% rename from src/multiwindow_base/appcore_multiwindow_base_window.c rename to legacy/src/multiwindow_base/appcore_multiwindow_base_window.c diff --git a/src/ui_base/appcore_ui_base.c b/legacy/src/ui_base/appcore_ui_base.c similarity index 100% rename from src/ui_base/appcore_ui_base.c rename to legacy/src/ui_base/appcore_ui_base.c diff --git a/src/ui_base/appcore_ui_base_private.h b/legacy/src/ui_base/appcore_ui_base_private.h similarity index 100% rename from src/ui_base/appcore_ui_base_private.h rename to legacy/src/ui_base/appcore_ui_base_private.h diff --git a/src/ui_base/appcore_ui_plugin.c b/legacy/src/ui_base/appcore_ui_plugin.c similarity index 100% rename from src/ui_base/appcore_ui_plugin.c rename to legacy/src/ui_base/appcore_ui_plugin.c diff --git a/src/watchdog/appcore_watchdog.c b/legacy/src/watchdog/appcore_watchdog.c similarity index 100% rename from src/watchdog/appcore_watchdog.c rename to legacy/src/watchdog/appcore_watchdog.c diff --git a/src/watchdog/appcore_watchdog_private.h b/legacy/src/watchdog/appcore_watchdog_private.h similarity index 100% rename from src/watchdog/appcore_watchdog_private.h rename to legacy/src/watchdog/appcore_watchdog_private.h diff --git a/packaging/app-core.spec b/packaging/app-core.spec index 51bcaf3..bb6230a 100644 --- a/packaging/app-core.spec +++ b/packaging/app-core.spec @@ -22,9 +22,15 @@ BuildRequires: pkgconfig(gobject-2.0) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(ttrace) +BuildRequires: pkgconfig(gmock) BuildRequires: cmake BuildRequires: pkgconfig(capi-system-info) +%if 0%{?gcov:1} +BuildRequires: lcov +BuildRequires: zip +%endif + %description SLP common application basic @@ -114,11 +120,27 @@ Group: Development/Libraries %description template Application basics template + +%if 0%{?gcov:1} +%package gcov +Summary: Application Core API(gcov) +Group: Application Framework/Libraries + +%description gcov +gcov objects of a widget application library +%endif + %prep %setup -q cp %{SOURCE1001} . %build +%if 0%{?gcov:1} +export CFLAGS+=" -fprofile-arcs -ftest-coverage" +export CXXFLAGS+=" -fprofile-arcs -ftest-coverage" +export FFLAGS+=" -fprofile-arcs -ftest-coverage" +export LDFLAGS+=" -lgcov" +%endif export CFLAGS+=" -DEFL_BETA_API_SUPPORT " MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %cmake . \ @@ -128,11 +150,29 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` make %{?_smp_mflags} +%if 0%{?gcov:1} +mkdir -p gcov-obj +find . -name '*.gcno' -exec cp '{}' gcov-obj ';' +%endif %install rm -rf %{buildroot} %make_install +%if 0%{?gcov:1} +mkdir -p %{buildroot}%{_datadir}/gcov/obj +install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj +%endif + +%check +ctest -V +%if 0%{?gcov:1} +lcov -c --ignore-errors graph --no-external -q -d . -o app-core.info +genhtml app-core.info -o app-core.out +zip -r app-core.zip app-core.out +install -m 0644 app-core.zip %{buildroot}%{_datadir}/gcov/ +%endif + %post -n app-core-efl -p /sbin/ldconfig @@ -150,10 +190,13 @@ rm -rf %{buildroot} %postun -n app-core-ui -p /sbin/ldconfig - %files efl %manifest %{name}.manifest %{_libdir}/libappcore-efl.so.* + +%{_includedir}/appcore_cpp/app_core_efl_base.hh +%{_libdir}/libapp-core-efl-cpp.so* +%{_libdir}/pkgconfig/app-core-efl-cpp.pc %license LICENSE %files efl-devel @@ -166,6 +209,10 @@ rm -rf %{buildroot} %files multiwindow %manifest %{name}.manifest %{_libdir}/libappcore-multiwindow.so.* + +%{_includedir}/appcore_cpp/app_core_multi_window_base.hh +%{_libdir}/libapp-core-multi-window-cpp.so* +%{_libdir}/pkgconfig/app-core-multi-window-cpp.pc %license LICENSE %files multiwindow-devel @@ -177,6 +224,14 @@ rm -rf %{buildroot} %files common %manifest %{name}.manifest %{_libdir}/libappcore-common.so.* + +%{_includedir}/appcore_cpp/app_core_base.hh +%{_includedir}/appcore_cpp/interface_app_core.hh +%{_includedir}/appcore_cpp/interface_app_core_ui.hh +%{_includedir}/appcore_cpp/interface_main_loop.hh +%{_includedir}/appcore_cpp/interface_window.hh +%{_libdir}/libapp-core-cpp.so* +%{_libdir}/pkgconfig/app-core-cpp.pc %license LICENSE %files common-devel @@ -191,6 +246,11 @@ rm -rf %{buildroot} %files ui %manifest %{name}.manifest %{_libdir}/libappcore-ui.so.* + +%{_includedir}/appcore_cpp/app_core_ui_base.hh +%{_includedir}/appcore/appcore_ui_base.h +%{_libdir}/libapp-core-ui-cpp.so* +%{_libdir}/pkgconfig/app-core-ui-cpp.pc %license LICENSE %files ui-devel @@ -198,3 +258,8 @@ rm -rf %{buildroot} %{_includedir}/appcore/appcore_ui_base.h %{_libdir}/libappcore-ui.so %{_libdir}/pkgconfig/appcore-ui.pc + +%if 0%{?gcov:1} +%files gcov +%{_datadir}/gcov/* +%endif diff --git a/tizen-cpp/CMakeLists.txt b/tizen-cpp/CMakeLists.txt new file mode 100644 index 0000000..0814703 --- /dev/null +++ b/tizen-cpp/CMakeLists.txt @@ -0,0 +1,4 @@ +ADD_SUBDIRECTORY(app-core-efl-cpp) +ADD_SUBDIRECTORY(app-core-multi-window-cpp) +ADD_SUBDIRECTORY(app-core-cpp) +ADD_SUBDIRECTORY(app-core-ui-cpp) diff --git a/tizen-cpp/app-core-cpp/CMakeLists.txt b/tizen-cpp/app-core-cpp/CMakeLists.txt new file mode 100644 index 0000000..20fc2e6 --- /dev/null +++ b/tizen-cpp/app-core-cpp/CMakeLists.txt @@ -0,0 +1,32 @@ +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_CORE_CPP_SRCS) + +ADD_LIBRARY(${TARGET_APP_CORE_CPP} SHARED ${APP_CORE_CPP_SRCS}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CORE_CPP} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../) + +TARGET_LINK_LIBRARIES(${TARGET_APP_CORE_CPP} PUBLIC "-ldl -L/usr/lib/hal") +SET_TARGET_PROPERTIES(${TARGET_APP_CORE_CPP} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${TARGET_APP_CORE_CPP} PROPERTIES VERSION ${FULLVER}) + +APPLY_PKG_CONFIG(${TARGET_APP_CORE_CPP} PUBLIC + AUL_DEPS + BUNDLE_DEPS + CAPI_SYSTEM_INFO_DEPS + DLOG_DEPS + GIO_2_DEPS + PKGMGR_INFO_DEPS + SENSOR_DEPS + TTRACE_DEPS + VCONF_DEPS +) + +CONFIGURE_FILE(${TARGET_APP_CORE_CPP}.pc.in ${TARGET_APP_CORE_CPP}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_APP_CORE_CPP}.pc + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +INSTALL(TARGETS ${TARGET_APP_CORE_CPP} DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION include/appcore_cpp + FILES_MATCHING + PATTERN "*.hh") diff --git a/tizen-cpp/app-core-cpp/app-core-cpp.pc.in b/tizen-cpp/app-core-cpp/app-core-cpp.pc.in new file mode 100644 index 0000000..9aec6dd --- /dev/null +++ b/tizen-cpp/app-core-cpp/app-core-cpp.pc.in @@ -0,0 +1,14 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDEDIR@ + +Name: app-core-cpp +Description: Tizen application core library +Version: @VERSION@ +Requires.private: sensor vconf aul dlog +Libs: -L${libdir} -lapp-core-cpp +Cflags: -I${includedir} -I${includedir}/appcore_cpp +cppflags: I${includedir} -I${includedir}/appcore_cpp diff --git a/tizen-cpp/app-core-cpp/app_core_base.cc b/tizen-cpp/app-core-cpp/app_core_base.cc new file mode 100644 index 0000000..5adf51c --- /dev/null +++ b/tizen-cpp/app-core-cpp/app_core_base.cc @@ -0,0 +1,1255 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "app-core-cpp/app_core_base.hh" +#include "common/log_private.hh" + +extern "C" void aul_finalize(); + +namespace tizen_cpp { +namespace { + +enum TizenProfile { + Unknown = 0x00, + Mobile = 0x01, + Wearable = 0x02, + Tv = 0x04, + Ivi = 0x08, + Common = 0x10, +}; + +TizenProfile TizenProfileGet() { + static TizenProfile profile = TizenProfile::Unknown; + if (__builtin_expect(profile != TizenProfile::Unknown, 1)) + return profile; + + char* profile_name = nullptr; + system_info_get_platform_string("http://tizen.org/feature/profile", + &profile_name); + if (profile_name == nullptr) + return profile; + + switch (*profile_name) { + case 'm': + case 'M': + profile = TizenProfile::Mobile; + break; + case 'w': + case 'W': + profile = TizenProfile::Wearable; + break; + case 't': + case 'T': + profile = TizenProfile::Tv; + break; + case 'i': + case 'I': + profile = TizenProfile::Ivi; + break; + default: + profile = TizenProfile::Common; + break; + } + free(profile_name); + + return profile; +} + +constexpr const char PATH_LOCALE[] = "locale"; +constexpr int SQLITE_FLUSH_MAX = 1024 * 1024; +constexpr const char RESOURCED_FREEZER_PATH[] = + "/Org/Tizen/ResourceD/Freezer"; +constexpr const char RESOURCED_FREEZER_INTERFACE[] = + "org.tizen.resourced.freezer"; +constexpr const char RESOURCED_FREEZER_SIGNAL[] = + "FreezerState"; + +struct Rotation { + int conn; + int lock; + int ref; + tizen_cpp::AppCoreBase::RotationState rm; + int charger_status; + bool initialized; +}; + +Rotation __rotation; +GDBusConnection* __bus; +guint __suspend_dbus_handler_initialized; +AppCoreBase::DisplayState __display_state = AppCoreBase::DISPLAY_STATE_UNKNOWN; + +} // namespace + +class AppCoreBase::EventBase::Impl { + private: + friend class AppCoreBase; + Type type_ = IEvent::Type::START; + std::string str_val_; + int val_ = -1; +}; + +class AppCoreBase::Impl { + public: + explicit Impl(AppCoreBase* parent) : parent_(parent) { + if (TizenProfileGet() & TizenProfile::Wearable) + feature_ |= FEATURE_CHARGER_STATUS; + if (!(TizenProfileGet() & TizenProfile::Tv)) + feature_ |= FEATURE_BACKGROUND_MANAGEMENT; + } + + private: + void UnregisterRotationChangedEvent(); + void RegisterRotationChangedEvent(); + std::string GetAppName(const char* appid); + std::string GetLocaleResourceDir(); + void UpdateLang(); + void UpdateRegion(); + std::list SplitLanguage(const std::string& lang); + std::string GetLanguage(std::string lang); + void AppendDefaultLangs(std::set& lang_set); + std::string GetStringBefore(const char* str, const char* delim); + std::map> GetLangTable(); + void AppendLangs(const std::string& lang, std::set& lang_set, + std::map>& table); + void ChangeLang(); + void OnFreezerSignal(); + + template + void InvokeCallback(T event, IEvent::Type type) { + for (auto& i : events_) { + if (i->GetType() != type) + continue; + + if (i->GetVal(event) != event || + type == IEvent::Type::START || + type == IEvent::Type::UPDATE_REQUESTED) { + i->SetVal(event); + i->OnEvent(event); + } + } + } + + static void InitSuspendDbusHandler(gpointer data); + static gboolean InitSuspendCb(gpointer data); + static gboolean InvokeLangChangeCb(gpointer data); + static void ReceiveSuspendSignalCb(GDBusConnection*, const gchar*, + const gchar*, const gchar*, const gchar*, GVariant*, gpointer); + static void OnLowBatteryCb(keynode_t* key, void* data); + static void LockCb(keynode_t* node, void* user_data); + static void AutoRotationChangedCb(sensor_t sensor, unsigned int event_type, + sensor_data_t* data, void* user_data); + static void ChargerStatusChangedCb(keynode_t* keynode, void* user_data); + static void LanguageChangeCb(keynode_t* key, void* data); + static void RegionChangeCb(keynode_t* key, void* data); + static void LowMemoryCb(keynode_t* key, void* data); + void InitRotation(); + void FiniRotation(); + RotationState GetRm(sensor_data_t data); + void VerifyLanguage(); + void SetDefaultEvents(); + void UnsetDefaultEvents(); + + private: + friend class AppCoreBase; + AppCoreBase* parent_ = nullptr; + + int argc_ = 0; + char** argv_ = nullptr; + bool suspended_state_ = false; + bool allowed_bg_ = false; + bool dirty_ = false; + unsigned int tid_ = 0; + std::list> events_; + std::string locale_dir_; + guint sid_ = 0; + int feature_ = 0; + IAppCore* core_delegator_ = nullptr; + IMainLoop* loop_delegator_ = nullptr; +}; + +AppCoreBase::EventBase::EventBase(Type type) + : impl_(std::make_unique()) { + impl_->type_ = type; +} + +AppCoreBase::EventBase::~EventBase() = default; + +IAppCore::IEvent::Type AppCoreBase::EventBase::GetType() const { + return impl_->type_; +} + +std::string AppCoreBase::EventBase::GetVal(std::string cur) const { + return impl_->str_val_; +} + +int AppCoreBase::EventBase::GetVal(int cur) const { + return impl_->val_; +} + +void AppCoreBase::EventBase::SetVal(std::string val) { + impl_->str_val_ = std::move(val); +} + +void AppCoreBase::EventBase::SetVal(int val) { + impl_->val_ = std::move(val); +} + +AppCoreBase::AppCoreBase() : impl_(std::make_unique(this)) {} +AppCoreBase::~AppCoreBase() = default; + +void AppCoreBase::Impl::ChangeLang() { + const char* lang = getenv("LANG"); + if (lang == nullptr) + return; + + InvokeCallback(lang, IEvent::Type::LANG_CHANGE); +} + +void AppCoreBase::RaiseEvent(int event, IEvent::Type type) { + impl_->InvokeCallback(event, type); +} + +void AppCoreBase::RaiseEvent(const std::string& event, IEvent::Type type) { + impl_->InvokeCallback(event, type); +} + +void AppCoreBase::Impl::OnFreezerSignal() { + if (!allowed_bg_ && suspended_state_) { + parent_->RemoveSuspendTimer(); + InvokeCallback(SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND, + IEvent::Type::SUSPENDED_STATE_CHANGE); + suspended_state_ = false; + parent_->AddSuspendTimer(); + } +} + +AppCoreBase::RotationState AppCoreBase::Impl::GetRm(sensor_data_t data) { + if (data.value_count <= 0) { + _E("Failed to get sensor data"); + return ROTATION_UNKNOWN; + } + + int event = data.values[0]; + switch (event) { + case AUTO_ROTATION_DEGREE_0: + return ROTATION_PORTRAIT_NORMAL; + case AUTO_ROTATION_DEGREE_90: + return ROTATION_LANDSCAPE_NORMAL; + case AUTO_ROTATION_DEGREE_180: + return ROTATION_PORTRAIT_REVERSE; + case AUTO_ROTATION_DEGREE_270: + return ROTATION_LANDSCAPE_REVERSE; + default: + return ROTATION_UNKNOWN; + } +} + +void AppCoreBase::Impl::InitSuspendDbusHandler(gpointer data) { + if (__suspend_dbus_handler_initialized) + return; + + if (__bus == nullptr) { + GError* err = nullptr; + __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err); + if (__bus == nullptr) { + _E("Failed to connect to the D-BUS daemon: %s", err->message); + g_error_free(err); + return; + } + } + + __suspend_dbus_handler_initialized = g_dbus_connection_signal_subscribe( + __bus, nullptr, RESOURCED_FREEZER_INTERFACE, RESOURCED_FREEZER_SIGNAL, + RESOURCED_FREEZER_PATH, nullptr, G_DBUS_SIGNAL_FLAGS_NONE, + ReceiveSuspendSignalCb, data, nullptr); + + if (__suspend_dbus_handler_initialized == 0) { + _E("g_dbus_connection_signal_subscribe() is failed."); + return; + } + + _D("[__SUSPEND__] suspend signal initialized"); +} + +gboolean AppCoreBase::Impl::InitSuspendCb(gpointer data) { + InitSuspendDbusHandler(data); + return G_SOURCE_REMOVE; +} + +gboolean AppCoreBase::Impl::InvokeLangChangeCb(gpointer data) { + AppCoreBase* base = reinterpret_cast(data); + base->impl_->sid_ = 0; + base->impl_->ChangeLang(); + return G_SOURCE_REMOVE; +} + +void AppCoreBase::Impl::ReceiveSuspendSignalCb(GDBusConnection*, const gchar*, + const gchar*, const gchar*, const gchar* signal_name, GVariant* parameters, + gpointer user_data) { + if (g_strcmp0(signal_name, RESOURCED_FREEZER_SIGNAL) == 0) { + gint pid = -1; + gint status = 0; + g_variant_get(parameters, "(ii)", &status, &pid); + if (pid == getpid() && status == 0) { + AppCoreBase* base = reinterpret_cast(user_data); + base->impl_->OnFreezerSignal(); + } + } +} + +void AppCoreBase::Impl::LanguageChangeCb(keynode_t* key, void* user_data) { + AppCoreBase* base = reinterpret_cast(user_data); + if (base->impl_->sid_) { + g_source_remove(base->impl_->sid_); + base->impl_->sid_ = 0; + } + + char* val = vconf_keynode_get_str(key); + if (val == nullptr) + return; + + base->impl_->UpdateLang(); + base->impl_->InvokeCallback(val, IEvent::Type::LANG_CHANGE); +} + +void AppCoreBase::Impl::RegionChangeCb(keynode_t* key, void* user_data) { + const char* name = vconf_keynode_get_name(key); + if (name == nullptr) + return; + + if (strcmp(name, VCONFKEY_REGIONFORMAT) && + strcmp(name, VCONFKEY_REGIONFORMAT_TIME1224)) + return; + + char* val = vconf_get_str(VCONFKEY_REGIONFORMAT); + if (val == nullptr) + return; + std::unique_ptr region_auto(val, std::free); + + AppCoreBase* base = reinterpret_cast(user_data); + base->impl_->UpdateRegion(); + base->impl_->InvokeCallback(val, IEvent::Type::REGION_CHANGE); +} + +void AppCoreBase::Impl::LowMemoryCb(keynode_t* key, void* user_data) { + int val = vconf_keynode_get_int(key); + if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) { + AppCoreBase* base = reinterpret_cast(user_data); + base->impl_->InvokeCallback(val, IEvent::Type::LOW_MEMORY); + malloc_trim(0); + } +} + +void AppCoreBase::Impl::ChargerStatusChangedCb(keynode_t* keynode, + void* user_data) { + AppCoreBase* base = reinterpret_cast(user_data); + if (base->impl_->feature_ & FEATURE_CHARGER_STATUS) { + __rotation.charger_status = vconf_keynode_get_int(keynode); + if (__rotation.ref) { + if (__rotation.charger_status) { + base->impl_->InitRotation(); + } else { + base->impl_->FiniRotation(); + } + } + + _D("charger status(%d)", __rotation.charger_status); + } +} + +void AppCoreBase::Impl::LockCb(keynode_t* node, void* user_data) { + AppCoreBase::RotationState rm; + AppCoreBase* base = reinterpret_cast(user_data); + + __rotation.lock = !vconf_keynode_get_bool(node); + if (__rotation.lock) { + _D("Rotation locked"); + rm = ROTATION_PORTRAIT_NORMAL; + } else { + _D("Rotation unlocked"); + sensor_data_t data; + bool r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data); + if (!r) { + _E("Failed to get sensor data"); + return; + } + + rm = base->impl_->GetRm(data); + if (rm == ROTATION_UNKNOWN) { + _E("Unknown mode"); + return; + } + } + + if (__rotation.rm == rm) + return; + + _D("Rotation: %d -> %d", __rotation.rm, rm); + __rotation.rm = rm; + base->impl_->InvokeCallback(__rotation.rm, + IEvent::Type::DEVICE_ORIENTATION_CHANGED); +} + +void AppCoreBase::Impl::AutoRotationChangedCb(sensor_t sensor, + unsigned int event_type, sensor_data_t* data, void* user_data) { + if (data == nullptr) + return; + + if (__rotation.lock) + return; + + if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT) + return; + + AppCoreBase* base = reinterpret_cast(user_data); + AppCoreBase::RotationState rm = base->impl_->GetRm(*data); + if (rm == ROTATION_UNKNOWN) { + _E("Unknown mode"); + return; + } + + _D("Rotation: %d -> %d", __rotation.rm, rm); + __rotation.rm = rm; + base->impl_->InvokeCallback(__rotation.rm, + IEvent::Type::DEVICE_ORIENTATION_CHANGED); +} + +void AppCoreBase::Impl::InitRotation() { + if (__rotation.initialized) + return; + + sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR); + __rotation.conn = sensord_connect(sensor); + if (__rotation.conn < 0) { + _E("Failed to connect sensord"); + return; + } + + bool r = sensord_register_event(__rotation.conn, + AUTO_ROTATION_CHANGE_STATE_EVENT, SENSOR_INTERVAL_NORMAL, 0, + AutoRotationChangedCb, parent_); + if (!r) { + _E("Failed to register auto rotation change event"); + sensord_disconnect(__rotation.conn); + return; + } + + r = sensord_start(__rotation.conn, 0); + if (!r) { + _E("Failed to start sensord"); + sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT); + sensord_disconnect(__rotation.conn); + return; + } + + int lock = 0; + vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock); + vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb, + parent_); + + __rotation.lock = !lock; + __rotation.initialized = true; +} + +void AppCoreBase::Impl::FiniRotation() { + if (!__rotation.initialized) + return; + + vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb); + sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT); + sensord_stop(__rotation.conn); + sensord_disconnect(__rotation.conn); + + __rotation.lock = 0; + __rotation.initialized = false; +} + +void AppCoreBase::Impl::VerifyLanguage() { + const char* env_lang = getenv("LANG"); + if (env_lang == nullptr) + return; + + char* lang = vconf_get_str(VCONFKEY_LANGSET); + if (lang == nullptr) + return; + + std::unique_ptr lang_auto(lang, std::free); + + if (strcmp(env_lang, lang) != 0) { + _I("LANG(%s), LANGSET(%s)", env_lang, lang); + sid_ = g_idle_add(InvokeLangChangeCb, parent_); + } +} + +void AppCoreBase::Impl::SetDefaultEvents() { + vconf_notify_key_changed(VCONFKEY_LANGSET, LanguageChangeCb, parent_); + int r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb, + parent_); + if (r == 0) { + vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb, + parent_); + } + + vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb, parent_); +} + +void AppCoreBase::Impl::UnsetDefaultEvents() { + vconf_ignore_key_changed(VCONFKEY_LANGSET, LanguageChangeCb); + int r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb); + if (r == 0) + vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb); + + vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb); +} + +int AppCoreBase::OnReceive(aul_type type, tizen_base::Bundle b) { + switch (type) { + case AUL_START: + _D("[APP %d] AUL event: AUL_START", getpid()); + if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) { + std::string bg = b.GetString(AUL_K_ALLOWED_BG); + if (bg == "ALLOWED_BG") { + _D("[__SUSPEND__] allowed background"); + impl_->allowed_bg_ = true; + RemoveSuspendTimer(); + } + } + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET"); + if (impl_->core_delegator_) + impl_->core_delegator_->OnControl(std::move(b)); + else + OnControl(std::move(b)); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + break; + case AUL_RESUME: + _D("[APP %d] AUL event: AUL_RESUME", getpid()); + if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) { + std::string bg = b.GetString(AUL_K_ALLOWED_BG); + if (bg == "ALLOWED_BG") { + _D("[__SUSPEND__] allowed background"); + impl_->allowed_bg_ = true; + RemoveSuspendTimer(); + } + } + break; + case AUL_TERMINATE: + _D("[APP %d] AUL event: AUL_TERMINATE", getpid()); + aul_status_update(STATUS_DYING); + if (!impl_->allowed_bg_) + RemoveSuspendTimer(); + + if (impl_->loop_delegator_) + impl_->loop_delegator_->OnLoopExit(); + else + OnLoopExit(); + break; + case AUL_TERMINATE_INST: + case AUL_TERMINATE_BG_INST: + case AUL_TERMINATE_BGAPP: + _D("[APP %d] AUL event: %d", getpid(), type); + if (!impl_->allowed_bg_) + RemoveSuspendTimer(); + break; + case AUL_WAKE: + _D("[APP %d] AUL event: AUL_WAKE", getpid()); + if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) { + if (!impl_->allowed_bg_ && impl_->suspended_state_) { + RemoveSuspendTimer(); + int suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND; + impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE); + impl_->suspended_state_ = false; + } + } + break; + case AUL_SUSPEND: + _D("[APP %d] AUL event: AUL_SUSPEND", getpid()); + if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) { + if (!impl_->allowed_bg_ && !impl_->suspended_state_) { + RemoveSuspendTimer(); + FlushMemory(); + } + } + break; + case AUL_UPDATE_REQUESTED: + _D("[APP %d] AUL event: AUL_UPDATE_REQUESTED", getpid()); + impl_->InvokeCallback(0, IEvent::Type::UPDATE_REQUESTED); + break; + default: + _D("[APP %d] AUL event: %d", getpid(), type); + /* do nothing */ + break; + } + + return 0; +} + +int AppCoreBase::OnCreate() { + int ret = aul_launch_init([](aul_type type, bundle* b, void* data) -> int { + AppCoreBase* base = reinterpret_cast(data); + if (base->impl_->core_delegator_) { + return base->impl_->core_delegator_->OnReceive(type, + b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle()); + } + return base->OnReceive(type, + b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle()); + }, this); + if (ret < 0 && ret != AUL_R_ECANCELED) { + _E("aul_launch_init() is failed. error(%d)", ret); + return -1; + } + + ret = aul_launch_argv_handler(impl_->argc_, impl_->argv_); + if (ret < 0) { + _E("aul_launch_argv_handler() is failed. error(%d)", ret); + return -1; + } + + return 0; +} + +int AppCoreBase::OnControl(tizen_base::Bundle b) { + return 0; +} + +int AppCoreBase::OnTerminate() { + aul_finalize(); + return 0; +} + +void AppCoreBase::SetCoreDelegator(IAppCore* delegator) { + impl_->core_delegator_ = delegator; +} + +void AppCoreBase::SetLoopDelegator(IMainLoop* delegator) { + impl_->loop_delegator_ = delegator; +} + +std::string AppCoreBase::Impl::GetAppName(const char* appid) { + if (appid == nullptr) + return ""; + + /* com.vendor.name -> name */ + const char* name_token = strrchr(appid, '.'); + if (name_token == nullptr) + return appid; + + name_token++; + return name_token; +} + +std::string AppCoreBase::Impl::GetLocaleResourceDir() { + const char* res_path = aul_get_app_resource_path(); + if (res_path == nullptr) { + _E("Failed to get resource path"); + return ""; + } + + std::string path = std::string(res_path) + PATH_LOCALE; + if (access(path.c_str(), R_OK) != 0) + _W("%s does not exist", path.c_str()); + + return path; +} + +int AppCoreBase::OnSetI18n() { + char appid[PATH_MAX]; + int ret = aul_app_get_appid_bypid(getpid(), appid, PATH_MAX); + if (ret < 0) { + _E("aul_app_get_appid_bypid() is failed. error(%d)", ret); + return -1; + } + + std::string name = impl_->GetAppName(appid); + if (name.empty()) + return -1; + + std::string locale_dir = impl_->GetLocaleResourceDir(); + if (locale_dir.empty()) + return -1; + + return SetI18n(move(name), move(locale_dir)); +} + +void AppCoreBase::Impl::OnLowBatteryCb(keynode_t* key, void* data) { + int val = vconf_keynode_get_int(key); + if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW) { + AppCoreBase* base = reinterpret_cast(data); + base->impl_->InvokeCallback(val, IEvent::Type::LOW_BATTERY); + } +} + +void AppCoreBase::Impl::UnregisterRotationChangedEvent() { + if (!__rotation.ref) + return; + + __rotation.ref--; + if (__rotation.ref == 0) { + FiniRotation(); + if (feature_ & FEATURE_CHARGER_STATUS) { + vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS, + ChargerStatusChangedCb); + } + } +} + +void AppCoreBase::Impl::RegisterRotationChangedEvent() { + if (__rotation.ref == 0) { + if (feature_ & FEATURE_CHARGER_STATUS) { + vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &__rotation.charger_status); + vconf_notify_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS, + ChargerStatusChangedCb, parent_); + if (__rotation.charger_status) + InitRotation(); + } else { + InitRotation(); + } + } + + __rotation.ref++; +} + +int AppCoreBase::OnSetEvent(IEvent::Type event) { + switch (event) { + case IEvent::Type::LOW_BATTERY: + vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, + impl_->OnLowBatteryCb, this); + break; + case IEvent::Type::DEVICE_ORIENTATION_CHANGED: + impl_->RegisterRotationChangedEvent(); + break; + case IEvent::Type::SUSPENDED_STATE_CHANGE: + break; + default: + break; + } + + return 0; +} + +int AppCoreBase::OnUnsetEvent(IEvent::Type event) { + switch (event) { + case IEvent::Type::LOW_BATTERY: + vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, + impl_->OnLowBatteryCb); + break; + case IEvent::Type::DEVICE_ORIENTATION_CHANGED: + impl_->UnregisterRotationChangedEvent(); + break; + case IEvent::Type::SUSPENDED_STATE_CHANGE: + break; + default: + break; + } + + return 0; +} + +int AppCoreBase::OnTrimMemory() { + int (*sqlite3_free_heap_memory)(int); + + sqlite3_free_heap_memory = reinterpret_cast< + decltype(sqlite3_free_heap_memory)>( + dlsym(RTLD_DEFAULT, "sqlite3_release_memory")); + if (sqlite3_free_heap_memory) + sqlite3_free_heap_memory(SQLITE_FLUSH_MAX); + + malloc_trim(0); + return 0; +} + +void AppCoreBase::AddEvent(std::shared_ptr event) { + bool found = false; + for (auto& ev : impl_->events_) { + if (ev->GetType() == event->GetType()) { + found = true; + break; + } + } + + if (!found) { + if (impl_->core_delegator_) + impl_->core_delegator_->OnSetEvent(event->GetType()); + else + OnSetEvent(event->GetType()); + } + + impl_->events_.push_back(move(event)); +} + +bool AppCoreBase::RemoveEvent(std::shared_ptr event) { + bool found = false; + impl_->events_.remove_if([&](const std::shared_ptr& ptr)->bool { + if (event.get() == ptr.get()) { + found = true; + return true; + } + return false; + }); + + return found; +} + +void AppCoreBase::FlushMemory() { + if (impl_->core_delegator_) + impl_->core_delegator_->OnTrimMemory(); + else + OnTrimMemory(); + + impl_->tid_ = 0; + if (!impl_->allowed_bg_ && !impl_->suspended_state_) { + _D("[__SUSPEND__] flush case"); + int suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND; + impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE); + impl_->suspended_state_ = true; + } +} + +AppCoreBase::RotationState AppCoreBase::GetRotationState() { + if (!__rotation.ref) + throw std::runtime_error("invalid rotation state"); + + return __rotation.rm; +} + +bool AppCoreBase::IsBgAllowed() { + return impl_->allowed_bg_; +} + +bool AppCoreBase::IsSuspended() { + return impl_->suspended_state_; +} + +void AppCoreBase::ToggleSuspendedState() { + impl_->suspended_state_ = !impl_->suspended_state_; +} + +std::list AppCoreBase::Impl::SplitLanguage( + const std::string& lang) { + std::istringstream ss(lang); + std::list li; + std::string token; + + while (std::getline(ss, token, ':')) + li.push_back(token); + + return li; +} + +void AppCoreBase::Impl::AppendDefaultLangs(std::set& lang_set) { + lang_set.insert({"en_US", "en_GB", "en"}); +} + +std::string AppCoreBase::Impl::GetStringBefore(const char* cstr, + const char* delim) { + if (cstr == nullptr || delim == nullptr) + return ""; + + auto str = std::string(cstr); + auto idx = str.find(delim); + return str.substr(0, idx); +} + +std::map> AppCoreBase::Impl::GetLangTable() { + if (locale_dir_.empty()) + return {}; + + DIR* dp = opendir(locale_dir_.c_str()); + if (dp == nullptr) + return {}; + + std::map> table; + struct dirent *dentry; + while ((dentry = readdir(dp)) != nullptr) { + if (!strcmp(dentry->d_name, ".") || + !strcmp(dentry->d_name, "..")) + continue; + + std::string buf = locale_dir_ + "/" + dentry->d_name; + struct stat stat_buf; + int ret = stat(buf.c_str(), &stat_buf); + if (ret != 0 || !S_ISDIR(stat_buf.st_mode)) + continue; + + std::string parent_lang = GetStringBefore(dentry->d_name, "_"); + if (parent_lang.empty()) { + _E("Out of memory"); + break; + } + + table[parent_lang].insert(dentry->d_name); + } + + closedir(dp); + return table; +} + +void AppCoreBase::Impl::AppendLangs(const std::string& lang, + std::set& lang_set, + std::map>& table) { + if (lang.empty()) + return; + + lang_set.insert(lang); + std::string extract_lang = GetStringBefore(lang.c_str(), "."); + if (extract_lang.empty()) + return; + + if (lang_set.find(extract_lang) != lang_set.end()) + return; + + std::string parent_lang = GetStringBefore(extract_lang.c_str(), "_"); + if (parent_lang.empty()) + return; + + if (table.find(parent_lang) == table.end()) + return; + + auto it = table[parent_lang].find(extract_lang); + if (it != table[parent_lang].end()) { + lang_set.insert(move(*it)); + table[parent_lang].erase(it); + return; + } + + it = table[parent_lang].find(parent_lang); + if (it != table[parent_lang].end()) { + lang_set.insert(move(*it)); + table[parent_lang].erase(parent_lang); + return; + } + + if (!table[parent_lang].empty()) { + auto i = table[parent_lang].begin(); + lang_set.insert(move(*i)); + table[parent_lang].erase(i); + } +} + +std::string AppCoreBase::Impl::GetLanguage(std::string lang) { + std::list l = SplitLanguage(lang); + if (l.empty()) + return ""; + + auto table = GetLangTable(); + if (table.empty()) + return ""; + + std::set lang_set {}; + for (auto& i : l) + AppendLangs(i, lang_set, table); + + AppendDefaultLangs(lang_set); + std::string ret; + for (auto& i : lang_set) { + if (ret.empty()) { + ret = i; + } else { + ret += ":"; + ret += i; + } + } + + return ret; +} + +void AppCoreBase::Impl::UpdateLang() { + char* lang = vconf_get_str(VCONFKEY_LANGSET); + if (lang == nullptr) + return; + + std::unique_ptr lang_auto(lang, std::free); + std::string language = GetLanguage(lang); + if (!language.empty()) { + _D("*****language(%s)", language.c_str()); + setenv("LANGUAGE", language.c_str(), 1); + } else { + setenv("LANGUAGE", lang, 1); + } + setenv("LANG", lang, 1); + setenv("LC_MESSAGES", lang, 1); + setenv("LC_ALL", lang, 1); + char* r = setlocale(LC_ALL, ""); + if (r == nullptr) { + r = setlocale(LC_ALL, "en_US.UTF-8"); + if (r != nullptr) { + _D("*****appcore setlocale=%s\n", r); + } else { + _D("*****appcore setlocale=\"C\""); + setenv("LC_ALL", "C", 1); + r = setlocale(LC_ALL, ""); + if (r == nullptr) + _E("failed to setlocale"); + } + } +} + +void AppCoreBase::Impl::UpdateRegion() { + char* region = vconf_get_str(VCONFKEY_REGIONFORMAT); + if (region == nullptr) + return; + + std::unique_ptr region_auto(region, std::free); + setenv("LC_CTYPE", region, 1); + setenv("LC_NUMERIC", region, 1); + setenv("LC_TIME", region, 1); + setenv("LC_COLLATE", region, 1); + setenv("LC_MONETARY", region, 1); + setenv("LC_PAPER", region, 1); + setenv("LC_NAME", region, 1); + setenv("LC_ADDRESS", region, 1); + setenv("LC_TELEPHONE", region, 1); + setenv("LC_MEASUREMENT", region, 1); + setenv("LC_IDENTIFICATION", region, 1); + char* r = setlocale(LC_ALL, ""); + if (r != nullptr) { + _D("*****appcore setlocale=%s\n", r); + } else { + _D("*****appcore setlocale=\"C\""); + setenv("LC_ALL", "C", 1); + r = setlocale(LC_ALL, ""); + if (r == nullptr) + _E("failed to setlocale"); + } +} + +int AppCoreBase::SetI18n(std::string domain_name, std::string dir_name) { + if (domain_name.empty()) { + errno = EINVAL; + return -1; + } + + if (!dir_name.empty()) + impl_->locale_dir_ = dir_name; + + impl_->UpdateLang(); + impl_->UpdateRegion(); + + char* r = setlocale(LC_ALL, ""); + /* if locale is not set properly, try to set "en_US" again */ + if (r == nullptr) { + r = setlocale(LC_ALL, "en_US.UTF-8"); + if (r == nullptr) { + _E("appcore: setlocale() error"); + _D("*****appcore setlocale=\"C\""); + setenv("LC_ALL", "C", 1); + r = setlocale(LC_ALL, ""); + if (r == nullptr) + _E("failed to setlocale"); + } + } + + if (r != nullptr) + _D("*****appcore setlocale=%s\n", r); + + r = bindtextdomain(domain_name.c_str(), dir_name.c_str()); + if (r == nullptr) + _E("appcore: bindtextdomain() error"); + + r = textdomain(domain_name.c_str()); + if (r == nullptr) + _E("appcore: textdomain() error"); + + return 0; +} + +void AppCoreBase::Exit() { + aul_status_update(STATUS_DYING); + if (impl_->loop_delegator_) + impl_->loop_delegator_->OnLoopExit(); + else + OnLoopExit(); +} + +void AppCoreBase::AddSuspendTimer() { + impl_->tid_ = g_timeout_add_seconds(5, [](gpointer data) -> gboolean { + AppCoreBase* base = reinterpret_cast(data); + base->FlushMemory(); + return FALSE; + }, this); +} + +void AppCoreBase::RemoveSuspendTimer() { + if (impl_->tid_ > 0) { + g_source_remove(impl_->tid_); + impl_->tid_ = 0; + } +} + +void AppCoreBase::SetDisplayState(DisplayState state) { + __display_state = state; +} + +AppCoreBase::DisplayState AppCoreBase::GetDisplayState() { + return __display_state; +} + +int AppCoreBase::EnableWatchdog() { + _I("[__APPCORE_WATCHDOG__] enable"); + return aul_watchdog_enable(); +} + +int AppCoreBase::DisableWatchdog() { + _I("[__APPCORE_WATCHDOG__] disable"); + return aul_watchdog_disable(); +} + +int AppCoreBase::KickWatchdog() { + _I("[__APPCORE_WATCHDOG__] kick"); + return aul_watchdog_kick(); +} + +void AppCoreBase::Run(int argc, char** argv) { + Init(argc, argv); + Fini(); +} + +void AppCoreBase::Init(int argc, char** argv) { + impl_->tid_ = 0; + impl_->suspended_state_ = false; + impl_->allowed_bg_ = false; + impl_->argc_ = argc; + impl_->argv_ = argv; + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:OPS_INIT"); + if (impl_->loop_delegator_) + impl_->loop_delegator_->OnLoopInit(argc, argv); + else + OnLoopInit(argc, argv); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + + if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) + g_idle_add(Impl::InitSuspendCb, this); + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT"); + if (!impl_->dirty_) { + impl_->dirty_ = true; + + for (auto& e : impl_->events_) { + if (impl_->core_delegator_) + impl_->core_delegator_->OnSetEvent(e->GetType()); + else + OnSetEvent(e->GetType()); + } + } + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:VERIFY_LANG"); + impl_->VerifyLanguage(); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_DEFAULT_EVENTS"); + impl_->SetDefaultEvents(); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + + if (impl_->core_delegator_) + impl_->core_delegator_->OnSetI18n(); + else + OnSetI18n(); + + aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_INITIALIZED); + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE"); + int create = 0; + if (impl_->core_delegator_) + create = impl_->core_delegator_->OnCreate(); + else + create = OnCreate(); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + + aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_CREATED); + if (create < 0) + return; + + if (impl_->loop_delegator_) + impl_->loop_delegator_->OnLoopRun(); + else + OnLoopRun(); +} + +void AppCoreBase::Fini() { + Dispose(); +} + +void AppCoreBase::Dispose() { + aul_status_update(STATUS_DYING); + DisableWatchdog(); + aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_DESTROYED); + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE"); + if (impl_->core_delegator_) + impl_->core_delegator_->OnTerminate(); + else + OnTerminate(); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + + for (auto& e : impl_->events_) { + if (impl_->core_delegator_) + impl_->core_delegator_->OnUnsetEvent(e->GetType()); + else + OnUnsetEvent(e->GetType()); + } + + impl_->UnsetDefaultEvents(); + if (impl_->sid_) { + g_source_remove(impl_->sid_); + impl_->sid_ = 0; + } + + RemoveSuspendTimer(); + impl_->dirty_ = false; + if (impl_->loop_delegator_) + impl_->loop_delegator_->OnLoopFinish(); + else + OnLoopFinish(); +} + +void AppCoreBase::SetFeature(int feature) { + impl_->feature_ = feature; +} + +int AppCoreBase::GetFeature() const { + return impl_->feature_; +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-cpp/app_core_base.hh b/tizen-cpp/app-core-cpp/app_core_base.hh new file mode 100644 index 0000000..ebe1d97 --- /dev/null +++ b/tizen-cpp/app-core-cpp/app_core_base.hh @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_CPP_APP_CORE_BASE_HH_ +#define TIZEN_CPP_APP_CORE_CPP_APP_CORE_BASE_HH_ + +#include +#include + +#include +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API AppCoreBase : public IAppCore, public IMainLoop { + public: + enum RotationState { + ROTATION_UNKNOWN, + ROTATION_PORTRAIT_NORMAL, + ROTATION_PORTRAIT_REVERSE, + ROTATION_LANDSCAPE_NORMAL, + ROTATION_LANDSCAPE_REVERSE, + }; + + enum SuspendedState { + SUSPENDED_STATE_WILL_ENTER_SUSPEND = 0, + SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND + }; + + enum DisplayState { + DISPLAY_STATE_UNKNOWN, + DISPLAY_STATE_ON, + DISPLAY_STATE_OFF + }; + + enum Feature { + FEATURE_BACKGROUND_MANAGEMENT = 0x1, + FEATURE_CHARGER_STATUS = 0x2 + }; + + class EventBase : public IEvent { + public: + explicit EventBase(Type type); + virtual ~EventBase(); + Type GetType() const override; + std::string GetVal(std::string cur) const; + int GetVal(int cur) const; + void SetVal(std::string val); + void SetVal(int val); + + private: + class Impl; + std::unique_ptr impl_; + }; + + AppCoreBase(); + virtual ~AppCoreBase(); + + virtual void Run(int argc, char** argv); + virtual void Exit(); + virtual void Dispose(); + void Init(int argc, char** argv); + void Fini(); + int OnReceive(aul_type type, tizen_base::Bundle b) override; + int OnCreate() override; + int OnControl(tizen_base::Bundle b) override; + int OnTerminate() override; + int OnSetI18n() override; + int OnSetEvent(IEvent::Type event) override; + int OnUnsetEvent(IEvent::Type event) override; + int OnTrimMemory() override; + void AddEvent(std::shared_ptr event); + bool RemoveEvent(std::shared_ptr event); + void RaiseEvent(int event, IEvent::Type type); + void RaiseEvent(const std::string& event, IEvent::Type type); + void FlushMemory(); + bool IsBgAllowed(); + bool IsSuspended(); + void ToggleSuspendedState(); + int SetI18n(std::string domain_name, std::string dir_name); + void AddSuspendTimer(); + void RemoveSuspendTimer(); + void SetFeature(int feature); + int GetFeature() const; + static RotationState GetRotationState(); + static void SetDisplayState(DisplayState state); + static DisplayState GetDisplayState(); + static int EnableWatchdog(); + static int DisableWatchdog(); + static int KickWatchdog(); + + protected: + void SetCoreDelegator(IAppCore* delegator); + void SetLoopDelegator(IMainLoop* delegator); + + private: + class Impl; + std::unique_ptr impl_; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_CPP_APP_CORE_BASE_HH_ diff --git a/tizen-cpp/app-core-cpp/interface_app_core.hh b/tizen-cpp/app-core-cpp/interface_app_core.hh new file mode 100644 index 0000000..504abbe --- /dev/null +++ b/tizen-cpp/app-core-cpp/interface_app_core.hh @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_CPP_INTERFACE_APP_CORE_HH_ +#define TIZEN_CPP_APP_CORE_CPP_INTERFACE_APP_CORE_HH_ + +#include +#include + +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API IAppCore { + public: + class IEvent { + public: + enum class Type { + START, + LOW_MEMORY, + LOW_BATTERY, + LANG_CHANGE, + DEVICE_ORIENTATION_CHANGED, + REGION_CHANGE, + SUSPENDED_STATE_CHANGE, + UPDATE_REQUESTED, + END /* for iterate */ + }; + + virtual void OnEvent(const std::string& val) = 0; + virtual void OnEvent(int val) = 0; + virtual Type GetType() const = 0; + }; + + virtual ~IAppCore() = default; // LCOV_EXCL_LINE + + virtual int OnReceive(aul_type type, tizen_base::Bundle b) = 0; + virtual int OnCreate() = 0; + virtual int OnControl(tizen_base::Bundle b) = 0; + virtual int OnTerminate() = 0; + virtual int OnSetI18n() = 0; + virtual int OnSetEvent(IEvent::Type event) = 0; + virtual int OnUnsetEvent(IEvent::Type event) = 0; + virtual int OnTrimMemory() = 0; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_CPP_INTERFACE_APP_CORE_HH_ diff --git a/tizen-cpp/app-core-cpp/interface_app_core_ui.hh b/tizen-cpp/app-core-cpp/interface_app_core_ui.hh new file mode 100644 index 0000000..08046cc --- /dev/null +++ b/tizen-cpp/app-core-cpp/interface_app_core_ui.hh @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_CPP_INTERFACE_APP_CORE_UI_HH_ +#define TIZEN_CPP_APP_CORE_CPP_INTERFACE_APP_CORE_UI_HH_ + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API IAppCoreUi { + public: + virtual ~IAppCoreUi() = default; // LCOV_EXCL_LINE + + virtual int OnPause() = 0; + virtual int OnResume() = 0; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_CPP_INTERFACE_APP_CORE_UI_HH_ diff --git a/tizen-cpp/app-core-cpp/interface_main_loop.hh b/tizen-cpp/app-core-cpp/interface_main_loop.hh new file mode 100644 index 0000000..1d8f7ef --- /dev/null +++ b/tizen-cpp/app-core-cpp/interface_main_loop.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_CPP_INTERFACE_MAIN_LOOP_HH_ +#define TIZEN_CPP_APP_CORE_CPP_INTERFACE_MAIN_LOOP_HH_ + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API IMainLoop { + public: + virtual ~IMainLoop() = default; // LCOV_EXCL_LINE + + virtual void OnLoopInit(int argc, char** argv) = 0; + virtual void OnLoopFinish() = 0; + virtual void OnLoopRun() = 0; + virtual void OnLoopExit() = 0; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_CPP_INTERFACE_MAIN_LOOP_HH_ diff --git a/tizen-cpp/app-core-cpp/interface_window.hh b/tizen-cpp/app-core-cpp/interface_window.hh new file mode 100644 index 0000000..4a013f8 --- /dev/null +++ b/tizen-cpp/app-core-cpp/interface_window.hh @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_CPP_INTERFACE_WINDOW_HH_ +#define TIZEN_CPP_APP_CORE_CPP_INTERFACE_WINDOW_HH_ + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API IWindow { + public: + virtual ~IWindow() = default; // LCOV_EXCL_LINE + + virtual void OnShow(int type, void* event) = 0; + virtual void OnHide(int type, void* event) = 0; + virtual void OnLower(int type, void* event) = 0; + virtual void OnVisibility(int type, void* event) = 0; + virtual void OnPreVisibility(int type, void* event) = 0; + virtual void OnAuxMessage(int type, void* event) = 0; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_CPP_INTERFACE_WINDOW_HH_ diff --git a/tizen-cpp/app-core-efl-cpp/CMakeLists.txt b/tizen-cpp/app-core-efl-cpp/CMakeLists.txt new file mode 100644 index 0000000..a7c3b03 --- /dev/null +++ b/tizen-cpp/app-core-efl-cpp/CMakeLists.txt @@ -0,0 +1,38 @@ +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_CORE_EFL_CPP_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../common COMMON_SRCS) + +ADD_LIBRARY(${TARGET_APP_CORE_EFL_CPP} SHARED + ${APP_CORE_EFL_CPP_SRCS} + ${COMMON_SRCS}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CORE_EFL_CPP} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../) + +TARGET_LINK_LIBRARIES(${TARGET_APP_CORE_EFL_CPP} PUBLIC + ${TARGET_APP_CORE_UI_CPP} + ${TARGET_APP_CORE_CPP} + "-L/usr/lib/hal") + +SET_TARGET_PROPERTIES(${TARGET_APP_CORE_EFL_CPP} + PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${TARGET_APP_CORE_EFL_CPP} + PROPERTIES VERSION ${FULLVER}) + +APPLY_PKG_CONFIG(${TARGET_APP_CORE_EFL_CPP} PUBLIC + AUL_DEPS + BUNDLE_DEPS + DLOG_DEPS + ELEMENTARY_DEPS +) + +CONFIGURE_FILE(${TARGET_APP_CORE_EFL_CPP}.pc.in + ${TARGET_APP_CORE_EFL_CPP}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_APP_CORE_EFL_CPP}.pc + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +INSTALL(TARGETS ${TARGET_APP_CORE_EFL_CPP} DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION include/appcore_cpp + FILES_MATCHING + PATTERN "*_private.hh" EXCLUDE + PATTERN "*.hh") diff --git a/tizen-cpp/app-core-efl-cpp/app-core-efl-cpp.pc.in b/tizen-cpp/app-core-efl-cpp/app-core-efl-cpp.pc.in new file mode 100644 index 0000000..3eea2e4 --- /dev/null +++ b/tizen-cpp/app-core-efl-cpp/app-core-efl-cpp.pc.in @@ -0,0 +1,15 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDEDIR@ + +Name: app-core-efl-cpp +Description: Tizen application core library for EFL +Version: @VERSION@ +Requires.private: elementary dlog +Requires: app-core-cpp app-core-ui-cpp +Libs: -L${libdir} -lapp-core-efl-cpp +Cflags: -I${includedir} -I${includedir}/appcore_cpp +cppflags: I${includedir} -I${includedir}/appcore_cpp diff --git a/tizen-cpp/app-core-efl-cpp/app_core_efl_base.cc b/tizen-cpp/app-core-efl-cpp/app_core_efl_base.cc new file mode 100644 index 0000000..b69ee53 --- /dev/null +++ b/tizen-cpp/app-core-efl-cpp/app_core_efl_base.cc @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021 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 +#include +#include + +#include +#include +#include + +#include "app-core-efl-cpp/app_core_efl_base.hh" +#include "app-core-efl-cpp/voice_elm_private.hh" +#include "common/log_private.hh" + +namespace tizen_cpp { + +namespace { + +std::unique_ptr __vc_elm; + +} // namespace + +void AppCoreEflBase::OnLoopInit(int argc, char** argv) { + elm_init(argc, argv); + unsigned int hint = GetHint(); + if ((hint & HINT_HW_ACC_CONTROL) && !getenv("AUL_HWACC")) { + const char* hwacc = getenv("HWACC"); + if (hwacc == nullptr) { + _D("elm_config_accel_preference_set is not called"); + } else if (strcmp(hwacc, "USE") == 0) { + elm_config_accel_preference_set("hw"); + _D("elm_config_accel_preference_set : hw"); + } else if (strcmp(hwacc, "NOT_USE") == 0) { + elm_config_accel_preference_set("none"); + _D("elm_config_accel_preference_set : none"); + } else { + _D("elm_config_accel_preference_set is not called"); + } + } + + if (VoiceElm::IsVtAutoMode()) { + std::thread([]{ + int retry_count = 3; + do { + if (__vc_elm.get() == nullptr) + __vc_elm.reset(VoiceElm::Load()); + + if (__vc_elm.get() != nullptr) { + g_idle_add([](gpointer data) { + if (__vc_elm.get() != nullptr) + __vc_elm->Init(); + return G_SOURCE_REMOVE; + }, nullptr); + break; + } + } while (retry_count--); + }).detach(); + } +} + +void AppCoreEflBase::OnLoopFinish() { + if (__vc_elm != nullptr) + __vc_elm.reset(); + + elm_shutdown(); + + /* Check loader case */ + const char* env = getenv("AUL_LOADER_INIT"); + if (env && env[0] == '1') { + setenv("AUL_LOADER_INIT", "0", 1); + elm_shutdown(); + } +} + +void AppCoreEflBase::OnLoopRun() { + elm_run(); +} + +void AppCoreEflBase::OnLoopExit() { + elm_exit(); +} + +int AppCoreEflBase::OnTrimMemory() { + _D("Trim memory"); + elm_cache_all_flush(); + return AppCoreUiBase::OnTrimMemory(); +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-efl-cpp/app_core_efl_base.hh b/tizen-cpp/app-core-efl-cpp/app_core_efl_base.hh new file mode 100644 index 0000000..497fd43 --- /dev/null +++ b/tizen-cpp/app-core-efl-cpp/app_core_efl_base.hh @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_EFL_CPP_APP_CORE_EFL_BASE_HH_ +#define TIZEN_CPP_APP_CORE_EFL_CPP_APP_CORE_EFL_BASE_HH_ + +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API AppCoreEflBase : public AppCoreUiBase { + public: + explicit AppCoreEflBase(unsigned int hint) : AppCoreUiBase(hint) {} + + void OnLoopInit(int argc, char** argv) override; + void OnLoopFinish() override; + void OnLoopRun() override; + void OnLoopExit() override; + int OnTrimMemory() override; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_EFL_CPP_APP_CORE_EFL_BASE_HH_ diff --git a/tizen-cpp/app-core-efl-cpp/voice_elm_private.cc b/tizen-cpp/app-core-efl-cpp/voice_elm_private.cc new file mode 100644 index 0000000..9c49b7b --- /dev/null +++ b/tizen-cpp/app-core-efl-cpp/voice_elm_private.cc @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include + +#include + +#include "app-core-efl-cpp/voice_elm_private.hh" +#include "common/log_private.hh" + +namespace tizen_cpp { + +namespace { + +constexpr const char kPathLibVcElm[] = "/usr/lib/libvc-elm.so.0"; +constexpr const char kNameVcElmInitialize[] = "vc_elm_initialize"; +constexpr const char kNameVcElmDeinitialize[] = "vc_elm_deinitialize"; +constexpr const char kNameVcElmSetAutoRegisterMode[] = + "vc_elm_set_auto_register_mode"; + +} // namespace + +VoiceElm::VoiceElm(void* handle, VcElmInitializeFunc init_func, + VcElmDeinitializeFunc deinit_func, + VcElmSetAutoRegisterModeFunc set_auto_register_mode_func) + : handle_(handle), + init_func_(init_func), + deinit_func_(deinit_func), + set_auto_register_mode_func_(set_auto_register_mode_func) { +} + +VoiceElm::~VoiceElm() { + Fini(); + + if (handle_) + dlclose(handle_); +} + +VoiceElm* VoiceElm::Load() { + if (access(kPathLibVcElm, F_OK) != 0) { + _E("access() is failed. path(%s), errno(%d)", kPathLibVcElm, errno); + return nullptr; + } + + void* handle = dlopen(kPathLibVcElm, RTLD_LAZY | RTLD_LOCAL); + if (handle == nullptr) { + _E("dlopen() is failed"); + return nullptr; + } + + auto init_func = reinterpret_cast( + dlsym(handle, kNameVcElmInitialize)); + if (init_func == nullptr) { + _E("dlsym() is failed. handle(%p), symbol(%s)", + handle, kNameVcElmInitialize); + dlclose(handle); + return nullptr; + } + + auto deinit_func = reinterpret_cast( + dlsym(handle, kNameVcElmDeinitialize)); + if (deinit_func == nullptr) { + _E("dlsym() is failed. handle(%p), symbol(%s)", + handle, kNameVcElmDeinitialize); + dlclose(handle); + return nullptr; + } + + auto set_auto_register_mode_func = + reinterpret_cast( + dlsym(handle, kNameVcElmSetAutoRegisterMode)); + if (set_auto_register_mode_func == nullptr) { + _E("dlsym() is failed. handle(%p), symbol(%s)", + handle, kNameVcElmSetAutoRegisterMode); + dlclose(handle); + return nullptr; + } + + return new (std::nothrow) VoiceElm( + handle, init_func, deinit_func, set_auto_register_mode_func); +} + +bool VoiceElm::IsVtAutoMode() { + int vt_automode = 0; + vconf_get_bool(VCONFKEY_VC_VOICE_TOUCH_AUTOMODE, &vt_automode); + return vt_automode ? true : false; +} + +void VoiceElm::Init() { + vconf_notify_key_changed(VCONFKEY_VC_VOICE_TOUCH_AUTOMODE, + VconfKeyChangedCb, this); + + if (IsVtAutoMode()) { + if (!initialized_) { + init_func_(); + initialized_ = true; + } + + set_auto_register_mode_func_(2, 0); + } +} + +void VoiceElm::Fini() { + vconf_ignore_key_changed(VCONFKEY_VC_VOICE_TOUCH_AUTOMODE, + VconfKeyChangedCb); + + if (initialized_) { + deinit_func_(); + initialized_ = false; + } +} + +void VoiceElm::VconfKeyChangedCb(keynode_t* key, void* data) { + auto* handle = static_cast(data); + int vt_automode = vconf_keynode_get_bool(key); + if (vt_automode) { + if (!handle->initialized_) { + handle->init_func_(); + handle->initialized_ = true; + } + + handle->set_auto_register_mode_func_(2, 0); + } else { + handle->deinit_func_(); + handle->initialized_ = false; + } +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-efl-cpp/voice_elm_private.hh b/tizen-cpp/app-core-efl-cpp/voice_elm_private.hh new file mode 100644 index 0000000..d160627 --- /dev/null +++ b/tizen-cpp/app-core-efl-cpp/voice_elm_private.hh @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_EFL_CPP_VOICE_ELM_PRIVATE_HH +#define TIZEN_CPP_APP_CORE_EFL_CPP_VOICE_ELM_PRIVATE_HH_ + +#include + +namespace tizen_cpp { + +class VoiceElm { + public: + using VcElmInitializeFunc = int (*)(void); + using VcElmDeinitializeFunc = int (*)(void); + using VcElmSetAutoRegisterModeFunc = int (*)(int, int); + + VoiceElm(void* handle, VcElmInitializeFunc init_func, + VcElmDeinitializeFunc deinit_func, + VcElmSetAutoRegisterModeFunc set_auto_register_mode_func); + ~VoiceElm(); + + static VoiceElm* Load(); + static bool IsVtAutoMode(); + + void Init(); + void Fini(); + + private: + static void VconfKeyChangedCb(keynode_t* key, void* data); + + private: + bool initialized_ = false; + void* handle_ = nullptr; + VcElmInitializeFunc init_func_ = nullptr; + VcElmDeinitializeFunc deinit_func_ = nullptr; + VcElmSetAutoRegisterModeFunc set_auto_register_mode_func_ = nullptr; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_EFL_CPP_VOICE_ELM_PRIVATE_HH_ diff --git a/tizen-cpp/app-core-multi-window-cpp/CMakeLists.txt b/tizen-cpp/app-core-multi-window-cpp/CMakeLists.txt new file mode 100644 index 0000000..3285e7d --- /dev/null +++ b/tizen-cpp/app-core-multi-window-cpp/CMakeLists.txt @@ -0,0 +1,42 @@ +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} + APP_CORE_MULTI_WINDOW_CPP_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../common + COMMON_SRCS) + +ADD_LIBRARY(${TARGET_APP_CORE_MULTI_WINDOW_CPP} SHARED + ${APP_CORE_MULTI_WINDOW_CPP_SRCS} + ${COMMON_SRCS}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CORE_MULTI_WINDOW_CPP} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../) + +TARGET_LINK_LIBRARIES(${TARGET_APP_CORE_MULTI_WINDOW_CPP} PUBLIC + ${TARGET_APP_CORE_CPP} + "-L/usr/lib/hal") + +SET_TARGET_PROPERTIES(${TARGET_APP_CORE_MULTI_WINDOW_CPP} + PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${TARGET_APP_CORE_MULTI_WINDOW_CPP} + PROPERTIES VERSION ${FULLVER}) + +APPLY_PKG_CONFIG(${TARGET_APP_CORE_MULTI_WINDOW_CPP} PUBLIC + AUL_DEPS + DLOG_DEPS + ECORE_DEPS + ECORE_WL2_DEPS + GLIB_2_DEPS + GOBJECT_2_DEPS +) + +CONFIGURE_FILE(${TARGET_APP_CORE_MULTI_WINDOW_CPP}.pc.in + ${TARGET_APP_CORE_MULTI_WINDOW_CPP}.pc @ONLY) +INSTALL(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_APP_CORE_MULTI_WINDOW_CPP}.pc + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +INSTALL(TARGETS ${TARGET_APP_CORE_MULTI_WINDOW_CPP} + DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION include/appcore_cpp + FILES_MATCHING + PATTERN "*.hh") diff --git a/tizen-cpp/app-core-multi-window-cpp/app-core-multi-window-cpp.pc.in b/tizen-cpp/app-core-multi-window-cpp/app-core-multi-window-cpp.pc.in new file mode 100644 index 0000000..de8c26b --- /dev/null +++ b/tizen-cpp/app-core-multi-window-cpp/app-core-multi-window-cpp.pc.in @@ -0,0 +1,15 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDEDIR@ + +Name: app-core-multi-window-cpp +Description: Tizen application core library for multiwindow +Version: @VERSION@ +Requires.private: ecore-wl2 dlog +Requires: app-core-cpp +Libs: -L${libdir} -lapp-core-multi-window-cpp +Cflags: -I${includedir} -I${includedir}/appcore_cpp +cppflags: I${includedir} -I${includedir}/appcore_cpp diff --git a/tizen-cpp/app-core-multi-window-cpp/app_core_multi_window_base.cc b/tizen-cpp/app-core-multi-window-cpp/app_core_multi_window_base.cc new file mode 100644 index 0000000..df107e5 --- /dev/null +++ b/tizen-cpp/app-core-multi-window-cpp/app_core_multi_window_base.cc @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include + +#include "app-core-multi-window-cpp/app_core_multi_window_base.hh" +#include "common/ecore_handler.hh" +#include "common/log_private.hh" + +namespace tizen_cpp { + +class AppCoreMultiWindowBase::Context::Impl { + public: + Impl(std::string context_id, std::string inst_id, AppCoreMultiWindowBase* app) + : id_(inst_id), context_id_(context_id), app_(app) {} + + private: + friend class AppCoreMultiWindowBase::Context; + bool paused_ = true; + std::string id_; + std::string context_id_; + int wid_ = 0; + AppCoreMultiWindowBase* app_; +}; + +class AppCoreMultiWindowBase::Impl { + private: + friend class AppCoreMultiWindowBase; + std::shared_ptr handler_; + std::map> factory_map_; + std::list> contexts_; + std::unique_ptr trim_; +}; + +AppCoreMultiWindowBase::Context::Context(std::string context_id, + std::string inst_id, AppCoreMultiWindowBase* app) + : impl_(std::make_unique( + std::move(context_id), std::move(inst_id), app)) { +} + +AppCoreMultiWindowBase::Context::~Context() = default; + +void AppCoreMultiWindowBase::Context::Exit() { + Context::Pause(); + OnTerminate(); +} + +void AppCoreMultiWindowBase::Context::Drop() { + OnTerminate(); +} + +void AppCoreMultiWindowBase::Context::Pause() { + if (impl_->paused_) + return; + + OnPause(); + impl_->paused_ = true; +} + +void AppCoreMultiWindowBase::Context::Resume() { + if (!impl_->paused_) + return; + + OnResume(); + impl_->paused_ = false; +} + +bool AppCoreMultiWindowBase::Context::IsResumed() { + return !impl_->paused_; +} + +const std::string& AppCoreMultiWindowBase::Context::GetInstId() const { + return impl_->id_; +} + +const std::string& AppCoreMultiWindowBase::Context::GetContextId() const { + return impl_->context_id_; +} + +int AppCoreMultiWindowBase::Context::GetWindowId() const { + return impl_->wid_; +} + +void AppCoreMultiWindowBase::Context::WindowBind(Ecore_Wl2_Window* wl_win) { + if (wl_win == nullptr) { + _E("Invalid parameter"); + return; + } + + impl_->wid_ = ecore_wl2_window_id_get(wl_win); +} + +void AppCoreMultiWindowBase::Context::WindowUnbind() { + impl_->wid_ = 0; +} + +AppCoreMultiWindowBase* AppCoreMultiWindowBase::Context::GetApp() { + return impl_->app_; +} + +AppCoreMultiWindowBase::AppCoreMultiWindowBase() : + impl_(std::make_unique()) {} + +AppCoreMultiWindowBase::~AppCoreMultiWindowBase() = default; + +const std::list>& +AppCoreMultiWindowBase::GetContexts() { + return impl_->contexts_; +} + +int AppCoreMultiWindowBase::GetContextCnt() const { + return impl_->contexts_.size(); +} + +void AppCoreMultiWindowBase::ExitContext( + std::shared_ptr context) { + context->Exit(); + impl_->contexts_.remove(context); +} + +std::shared_ptr +AppCoreMultiWindowBase::CreateContext(const std::string& context_id, + const std::string& inst_id) { + auto i = impl_->factory_map_.find(context_id); + if (i == impl_->factory_map_.end()) + throw std::runtime_error("failed to find factory"); + + std::shared_ptr c = (*i).second->Create(inst_id, this); + return c; +} + +std::shared_ptr +AppCoreMultiWindowBase::RunContext( + std::shared_ptr cxt) { + impl_->contexts_.push_back(cxt); + try { + cxt->OnCreate(); + } catch (const std::runtime_error&) { + cxt->Drop(); + impl_->contexts_.remove(cxt); + return {}; + } + + return cxt; +} + +std::shared_ptr +AppCoreMultiWindowBase::RunContext(const std::string& context_id, + const std::string& inst_id) { + auto c = CreateContext(context_id, inst_id); + return RunContext(c); +} + +std::shared_ptr +AppCoreMultiWindowBase::FindById(const std::string& inst_id) { + for (auto& i : impl_->contexts_) { + if (i->GetInstId() == inst_id) { + return i; + } + } + + return {}; +} + +std::shared_ptr +AppCoreMultiWindowBase::FindByWindowId(int win_id) { + for (auto& i : impl_->contexts_) { + if (i->GetWindowId() == win_id) { + return i; + } + } + + return {}; +} + +void AppCoreMultiWindowBase::Run(int argc, char** argv) { + AppCoreBase::Run(argc, argv); +} + +void AppCoreMultiWindowBase::Dispose() { + for (auto& i : impl_->contexts_) { + i->Exit(); + } + impl_->contexts_.clear(); + impl_->factory_map_.clear(); + if (impl_->handler_.get() != nullptr) + impl_->handler_->Fini(); + AppCoreBase::Dispose(); +} + +int AppCoreMultiWindowBase::OnCreate() { + AppCoreBase::OnCreate(); + + class Trimmer : public EcoreHandler::ITrim { + public: + bool IsTrimmable() { + return base_->IsResumed(); + } + + void OnTrim() { + base_->OnTrimMemory(); + } + + explicit Trimmer(AppCoreMultiWindowBase* base) : base_(base) {} + + private: + AppCoreMultiWindowBase* base_; + }; + + impl_->trim_ = std::unique_ptr(new Trimmer(this)); + + impl_->handler_ = std::make_shared(this, impl_->trim_.get()); + impl_->handler_->Init(); + return 0; +} + +bool AppCoreMultiWindowBase::IsResumed() { + for (auto& i : impl_->contexts_) { + if (i->IsResumed()) + return true; + } + + return false; +} + +void AppCoreMultiWindowBase::OnShow(int type, void* event) { +} + +void AppCoreMultiWindowBase::OnHide(int type, void* event) { + Ecore_Wl2_Event_Window_Hide* ev = + static_cast(event); + auto cxt = FindByWindowId(ev->win); + if (cxt.get() == nullptr) + return; + + cxt->WindowUnbind(); +} + +void AppCoreMultiWindowBase::OnLower(int type, void* event) { +} + +void AppCoreMultiWindowBase::OnVisibility(int type, void* event) { + auto* ev = static_cast(event); + auto cxt = FindByWindowId(ev->win); + if (cxt.get() == nullptr) + return; + + if (ev->fully_obscured) + cxt->Context::Pause(); + else + cxt->Context::Resume(); +} + +void AppCoreMultiWindowBase::OnPreVisibility(int type, void* event) { + auto* ev = static_cast(event); + auto cxt = FindByWindowId(ev->win); + if (cxt.get() == nullptr) + return; + + if (ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) + cxt->Context::Resume(); +} + +void AppCoreMultiWindowBase::OnAuxMessage(int type, void* event) { + auto* ev = static_cast(event); + if (ev->key && !strcmp(ev->key, "dpms_wm")) { + if (ev->val && !strcmp(ev->val, "on")) { + _D("Display state: on"); + AppCoreBase::SetDisplayState(AppCoreBase::DISPLAY_STATE_ON); + } else if (ev->val && !strcmp(ev->val, "off")) { + _D("Display state: off"); + AppCoreBase::SetDisplayState(AppCoreBase::DISPLAY_STATE_OFF); + } else { + _E("Unknown state: %s", ev->val); + } + } +} + +void AppCoreMultiWindowBase::AddContextFactory( + std::shared_ptr factory, + const std::string& context_id) { + impl_->factory_map_[context_id] = std::move(factory); +} + +std::shared_ptr +AppCoreMultiWindowBase::GetContextFactory(const std::string& context_id) { + return impl_->factory_map_[context_id]; +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-multi-window-cpp/app_core_multi_window_base.hh b/tizen-cpp/app-core-multi-window-cpp/app_core_multi_window_base.hh new file mode 100644 index 0000000..d308f0b --- /dev/null +++ b/tizen-cpp/app-core-multi-window-cpp/app_core_multi_window_base.hh @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_MULTI_WINDOW_CPP_APP_CORE_MULTI_WINDOW_BASE_HH_ +#define TIZEN_CPP_APP_CORE_MULTI_WINDOW_CPP_APP_CORE_MULTI_WINDOW_BASE_HH_ + +#include + +#include +#include +#include + +#include +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API AppCoreMultiWindowBase : public AppCoreBase, public IWindow { + public: + class Context { + public: + class IFactory { + public: + virtual ~IFactory() = default; + virtual std::unique_ptr Create(std::string inst_id, + AppCoreMultiWindowBase* app) = 0; + }; + + Context(std::string context_id, std::string inst_id, + AppCoreMultiWindowBase* app); + virtual ~Context(); + + virtual void OnCreate() = 0; + virtual void OnTerminate() = 0; + virtual void OnPause() = 0; + virtual void OnResume() = 0; + virtual void Exit(); + virtual void WindowBind(Ecore_Wl2_Window* wl_win); + virtual void WindowUnbind(); + virtual void Drop(); + virtual void Pause(); + virtual void Resume(); + bool IsResumed(); + const std::string& GetInstId() const; + const std::string& GetContextId() const; + int GetWindowId() const; + AppCoreMultiWindowBase* GetApp(); + + private: + class Impl; + std::unique_ptr impl_; + }; + + AppCoreMultiWindowBase(); + virtual ~AppCoreMultiWindowBase(); + + int OnCreate() override; + void OnShow(int type, void* event) override; + void OnHide(int type, void* event) override; + void OnLower(int type, void* event) override; + void OnVisibility(int type, void* event) override; + void OnPreVisibility(int type, void* event) override; + void OnAuxMessage(int type, void* event) override; + bool IsResumed(); + int GetContextCnt() const; + const std::list>& GetContexts(); + virtual void ExitContext(std::shared_ptr context); + std::shared_ptr FindById(const std::string& inst_id); + std::shared_ptr FindByWindowId(int win_id); + void AddContextFactory(std::shared_ptr factory, + const std::string& context_id); + std::shared_ptr RunContext(const std::string& context_id, + const std::string& inst_id); + std::shared_ptr RunContext(std::shared_ptr cxt); + std::shared_ptr CreateContext(const std::string& context_id, + const std::string& inst_id); + void Run(int argc, char** argv) override; + std::shared_ptr GetContextFactory( + const std::string& context_id); + void Dispose() override; + + private: + class Impl; + std::unique_ptr impl_; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_MULTI_WINDOW_CPP__APP_CORE_MULTI_WINDOW_BASE_HH_ diff --git a/tizen-cpp/app-core-ui-cpp/CMakeLists.txt b/tizen-cpp/app-core-ui-cpp/CMakeLists.txt new file mode 100644 index 0000000..a4d55d8 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/CMakeLists.txt @@ -0,0 +1,48 @@ +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_CORE_UI_CPP_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../common COMMON_SRCS) + +ADD_LIBRARY(${TARGET_APP_CORE_UI_CPP} SHARED + ${APP_CORE_UI_CPP_SRCS} + ${COMMON_SRCS}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CORE_UI_CPP} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../) + +TARGET_LINK_LIBRARIES(${TARGET_APP_CORE_UI_CPP} PUBLIC + ${TARGET_APP_CORE_CPP} + "-L/usr/lib/hal") + +SET_TARGET_PROPERTIES(${TARGET_APP_CORE_UI_CPP} + PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${TARGET_APP_CORE_UI_CPP} + PROPERTIES VERSION ${FULLVER}) + +APPLY_PKG_CONFIG(${TARGET_APP_CORE_UI_CPP} PUBLIC + AUL_DEPS + BUNDLE_DEPS + DLOG_DEPS + ECORE_DEPS + ECORE_WL2_DEPS + GLIB_2_DEPS + GOBJECT_2_DEPS + PKGMGR_INFO_DEPS + TIZEN_EXTENSION_CLIENT_DEPS + TTRACE_DEPS + WAYLAND_CLIENT_DEPS +) + +CONFIGURE_FILE(${TARGET_APP_CORE_UI_CPP}.pc.in + ${TARGET_APP_CORE_UI_CPP}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_APP_CORE_UI_CPP}.pc + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +INSTALL(TARGETS ${TARGET_APP_CORE_UI_CPP} DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION include/appcore_cpp + FILES_MATCHING + PATTERN "*_private.hh" EXCLUDE + PATTERN "*.hh") +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ + DESTINATION include/appcore + FILES_MATCHING + PATTERN "*.h") diff --git a/tizen-cpp/app-core-ui-cpp/app-core-ui-cpp.pc.in b/tizen-cpp/app-core-ui-cpp/app-core-ui-cpp.pc.in new file mode 100644 index 0000000..20ed780 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app-core-ui-cpp.pc.in @@ -0,0 +1,15 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDEDIR@ + +Name: app-core-ui-cpp +Description: Tizen application core library for UI +Version: @VERSION@ +Requires.private: dlog +Requires: app-core-cpp +Libs: -L${libdir} -lapp-core-ui-cpp +Cflags: -I${includedir} -I${includedir}/appcore_cpp +cppflags: I${includedir} -I${includedir}/appcore_cpp diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc b/tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc new file mode 100644 index 0000000..7102c71 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc @@ -0,0 +1,788 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "app-core-cpp/app_core_base.hh" +#include "app-core-ui-cpp/app_core_ui_base.hh" +#include "app-core-ui-cpp/app_core_ui_delegator_private.hh" +#include "app-core-ui-cpp/app_core_ui_plugin_private.hh" +#include "app-core-ui-cpp/appcore_ui_base.h" +#include "app-core-ui-cpp/wayland_handler_private.hh" +#include "common/ecore_handler.hh" +#include "common/log_private.hh" + +namespace tizen_cpp { + +class AppCoreUiBase::Impl { + public: + Impl(AppCoreUiBase* parent, unsigned int hint) + : parent_(parent), + hint_(hint), + handler_(std::make_shared(parent)), + wl_handler_(new WaylandHandler()) { + } + + private: + friend class AppCoreUiBase; + AppCoreUiBase* parent_; + + enum AppState { + AS_NONE, + AS_CREATED, + AS_RUNNING, + AS_PAUSED, + AS_DYING, + }; + + enum VisibilityType { + VT_NONE, + VT_UNOBSCURED, + VT_FULLY_OBSCURED, + }; + + enum WinStatus { + WS_NONE, + WS_PAUSE, + WS_RESUME, + }; + + struct WinNode { + unsigned int win_; + unsigned int surf_; + int vis_; + WinNode(unsigned int win, unsigned int surf) + : win_(win), surf_(surf), vis_(VT_NONE) { + } + }; + + void ExitFromSuspend(); + void PrepareToSuspend(); + void DoStart(tizen_base::Bundle b); + void DoResume(); + void DoPause(); + bool CheckVisible(); + int IsLegacyLifecycle(); + std::shared_ptr FindWin(unsigned int win); + bool AddWin(unsigned int win, unsigned int surf); + bool DeleteWin(unsigned int win); + bool UpdateWin(unsigned int win, unsigned int surf, int vis); + void RaiseWin(); + void PauseWin(); + void ApplyBgState(bool bg_state); + void SetAppId(); + int InitWl(); + int FiniWl(); + void PluginInit(int argc, char** argv); + void PluginFini(); + + std::list> winnode_list_; + unsigned int hint_; + std::string below_app_; + bool first_launch_ = true; + bool bg_state_ = false; + bool resource_reclaiming_ = true; + std::string appid_; + AppState state_ = AS_NONE; + WinStatus w_status_ = WS_NONE; + std::shared_ptr handler_; + std::unique_ptr wl_handler_; + IAppCoreUi* core_ui_delegator_ = nullptr; + std::unique_ptr plugin_delegator_; + std::unique_ptr plugin_; +}; + +AppCoreUiBase::AppCoreUiBase(unsigned int hint) + : impl_(new Impl(this, hint)) { +} + +AppCoreUiBase::~AppCoreUiBase() = default; + +std::shared_ptr AppCoreUiBase::Impl::FindWin( + unsigned int win) { + for (auto& i : winnode_list_) { + if (i->win_ == win) + return i; + } + + return nullptr; +} + +bool AppCoreUiBase::Impl::AddWin(unsigned int win, unsigned int surf) { + _D("[EVENT_TEST][EVENT] __add_win WIN: %u", win); + std::shared_ptr node = FindWin(win); + if (node != nullptr) { + _D("[EVENT_TEST][EVENT] ERROR There is already window: %u", win); + return false; + } + + winnode_list_.emplace_back(new WinNode(win, surf)); + return true; +} + +bool AppCoreUiBase::Impl::DeleteWin(unsigned int win) { + std::shared_ptr node = FindWin(win); + if (node == nullptr) { + _D("[EVENT_TEST][EVENT] ERROR There is no window: %u", win); + return false; + } + + winnode_list_.remove_if( + [win](std::shared_ptr node) { + return node->win_ == win; + }); + return true; +} + +bool AppCoreUiBase::Impl::UpdateWin(unsigned int win, unsigned int surf, + int vis) { + std::shared_ptr node = FindWin(win); + if (node == nullptr) { + _D("[EVENT_TEST][EVENT] ERROR There is no window: %u", win); + return false; + } + + node->win_ = win; + if (surf != 0) + node->surf_ = surf; + if (vis != VT_NONE) + node->vis_ = vis; + + return true; +} + +void AppCoreUiBase::Impl::RaiseWin() { + if (!(hint_ & HINT_WINDOW_STACK_CONTROL)) + return; + + unsigned int win_id = parent_->GetMainWindow(); + _I("Raise window: %u", win_id); + handler_->RaiseWin(win_id); +} + +void AppCoreUiBase::Impl::PauseWin() { + if (!(hint_ & HINT_WINDOW_STACK_CONTROL)) + return; + + _D("Pause window"); + for (auto& i : winnode_list_) { + _D("Pause window: %u", i->win_); + handler_->PauseWin(i->win_); + } +} + +unsigned int AppCoreUiBase::GetMainWindow() { + if (impl_->winnode_list_.empty()) + return 0; + + return impl_->winnode_list_.begin()->get()->win_; +} + +unsigned int AppCoreUiBase::GetMainSurface() { + if (impl_->winnode_list_.empty()) + return 0; + + return impl_->winnode_list_.begin()->get()->surf_; +} + +void AppCoreUiBase::SetCoreUiDelegator(IAppCoreUi* delegator) { + impl_->core_ui_delegator_ = delegator; +} + +void AppCoreUiBase::SetWindowDelegator(IWindow* delegator) { + impl_->handler_->SetWindow(delegator); +} + +int AppCoreUiBase::Impl::InitWl() { + return wl_handler_->Init(); +} + +int AppCoreUiBase::Impl::FiniWl() { + wl_handler_->Fini(); + return 0; +} + +void AppCoreUiBase::Impl::ApplyBgState(bool bg_state) { + if (wl_handler_->Init() < 0) + return; + + if (bg_state) + wl_handler_->SetBgState(); + else + wl_handler_->UnsetBgState(); + + parent_->SetBgState(bg_state); +} + +void AppCoreUiBase::Impl::SetAppId() { + if (wl_handler_->Init() < 0) + return; + + wl_handler_->SetAppId(appid_); +} + +void AppCoreUiBase::Impl::PluginInit(int argc, char** argv) { + plugin_.reset(AppCoreUiPlugin::Load()); + if (plugin_ == nullptr) + return; + + appcore_ui_base_ops ops; + ops.base.create = [](void* data) -> int { + auto* base = reinterpret_cast(data); + return base->OnCreate(); + }; + + ops.base.control = [](bundle* b, void* data) -> int { + auto* base = reinterpret_cast(data); + return base->OnControl(tizen_base::Bundle(b)); + }; + + ops.base.terminate = [](void* data) -> int { + auto* base = reinterpret_cast(data); + return base->OnTerminate(); + }; + + ops.base.receive = [](aul_type type, bundle* b, void* data) -> int { + auto* base = reinterpret_cast(data); + return base->OnReceive(type, tizen_base::Bundle(b)); + }; + + ops.base.set_i18n = [](void* data) -> int { + auto* base = reinterpret_cast(data); + return base->OnSetI18n(); + }; + + ops.base.init = [](int argc, char** argv, void* data) { + auto* base = reinterpret_cast(data); + base->OnLoopInit(argc, argv); + }; + + ops.base.finish = [](void* data) { + auto* base = reinterpret_cast(data); + base->OnLoopFinish(); + }; + + ops.base.run = [](void* data) { + auto* base = reinterpret_cast(data); + base->OnLoopRun(); + }; + + ops.base.exit = [](void* data) { + auto* base = reinterpret_cast(data); + base->OnLoopExit(); + }; + + ops.base.set_event = [](enum appcore_base_event event, void* data) { + auto* base = reinterpret_cast(data); + base->OnSetEvent(static_cast(event)); + }; + + ops.base.unset_event = [](enum appcore_base_event event, void* data) { + auto* base = reinterpret_cast(data); + base->OnUnsetEvent(static_cast(event)); + }; + + ops.base.trim_memory = [](void* data) { + auto* base = reinterpret_cast(data); + base->OnTrimMemory(); + }; + + ops.pause = [](void* data) -> int { + auto* base = reinterpret_cast(data); + return base->OnPause(); + }; + + ops.resume = [](void* data) -> int { + auto* base = reinterpret_cast(data); + return base->OnResume(); + }; + + ops.window.show = [](int type, void* event, void* data) { + auto* base = reinterpret_cast(data); + base->OnShow(type, event); + }; + + ops.window.hide = [](int type, void* event, void* data) { + auto* base = reinterpret_cast(data); + base->OnHide(type, event); + }; + + ops.window.lower = [](int type, void* event, void* data) { + auto* base = reinterpret_cast(data); + base->OnLower(type, event); + }; + + ops.window.visibility = [](int type, void* event, void* data) { + auto* base = reinterpret_cast(data); + base->OnVisibility(type, event); + }; + + ops.window.pre_visibility = [](int type, void* event, void* data) { + auto* base = reinterpret_cast(data); + base->OnPreVisibility(type, event); + }; + + ops.window.aux_message = [](int type, void* event, void* data) { + auto* base = reinterpret_cast(data); + base->OnAuxMessage(type, event); + }; + + plugin_->Init(&ops, argc, argv, &hint_); + plugin_delegator_.reset(new AppCoreUiDelegator(ops, parent_)); + parent_->SetCoreDelegator(plugin_delegator_.get()); + parent_->SetLoopDelegator(plugin_delegator_.get()); + parent_->SetCoreUiDelegator(plugin_delegator_.get()); + parent_->SetWindowDelegator(plugin_delegator_.get()); +} + +void AppCoreUiBase::Impl::PluginFini() { + if (plugin_ == nullptr) + return; + + plugin_->Fini(); +} + +void AppCoreUiBase::Run(int argc, char** argv) { + SetCoreDelegator(nullptr); + SetLoopDelegator(nullptr); + SetCoreUiDelegator(nullptr); + SetWindowDelegator(this); + impl_->plugin_delegator_.reset(); + impl_->PluginInit(argc, argv); + + char appid[PATH_MAX] = {0, }; + int ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid)); + if (ret != 0) + _E("Fail to get appid. pid(%d)", getpid()); + + impl_->handler_->Init(); + impl_->state_ = Impl::AS_NONE; + impl_->w_status_ = Impl::WS_NONE; + impl_->appid_ = std::string(appid); + LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid); + if (impl_->hint_ & HINT_BG_LAUNCH_CONTROL) { + tizen_base::Bundle b(bundle_import_from_argv(argc, argv), false, true); + if (!b.IsEmpty()) { + std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH); + if (bg_launch.compare("enable") == 0) + impl_->ApplyBgState(true); + } + } + + if (impl_->hint_ & HINT_WINDOW_ID_CONTROL) + impl_->SetAppId(); + + AppCoreBase::Run(argc, argv); +} + +void AppCoreUiBase::Dispose() { + impl_->handler_->Fini(); + impl_->FiniWl(); + + impl_->appid_.clear(); + + AppCoreBase::Dispose(); + impl_->PluginFini(); +} + +void AppCoreUiBase::Impl::PrepareToSuspend() { + if (parent_->IsBgAllowed() && !parent_->IsSuspended()) { + SuspendedState suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND; + parent_->RaiseEvent(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE); + parent_->ToggleSuspendedState(); + } +} + +void AppCoreUiBase::Impl::ExitFromSuspend() { + if (parent_->IsSuspended()) { + SuspendedState suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND; + parent_->RaiseEvent(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE); + parent_->ToggleSuspendedState(); + } +} + +void AppCoreUiBase::Impl::DoPause() { + if (state_ == AS_RUNNING) { + aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_PAUSED); + state_ = AS_PAUSED; + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE"); + _D("Call pause callback"); + int ret; + if (core_ui_delegator_) + ret = core_ui_delegator_->OnPause(); + else + ret = parent_->OnPause(); + + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + if (ret >= 0 && resource_reclaiming_) + parent_->AddSuspendTimer(); + + PrepareToSuspend(); + } + + aul_status_update(STATUS_BG); +} + +void AppCoreUiBase::Impl::DoResume() { + if (state_ == AS_PAUSED || state_ == AS_CREATED) { + aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_RESUMED); + ExitFromSuspend(); + state_ = AS_RUNNING; + LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", appid_.c_str()); + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME"); + _D("Call resume callback"); + parent_->RemoveSuspendTimer(); + if (core_ui_delegator_) + core_ui_delegator_->OnResume(); + else + parent_->OnResume(); + + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", appid_.c_str()); + } + + aul_status_update(STATUS_VISIBLE); +} + +void AppCoreUiBase::Impl::DoStart(tizen_base::Bundle b) { + if (parent_->GetHint() & HINT_WINDOW_STACK_CONTROL) + below_app_ = b.GetString(AUL_SVC_K_RELOCATE_BELOW); + + if (first_launch_) { + first_launch_ = false; + return; + } + + if (parent_->GetHint() & HINT_BG_LAUNCH_CONTROL) { + std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH); + if (!bg_launch.empty() && bg_launch.compare("enable") == 0) { + if (!bg_state_ && state_ != AS_RUNNING) + ApplyBgState(true); + } else { + if (bg_state_) + ApplyBgState(false); + } + } + + if (parent_->GetHint() & HINT_WINDOW_AUTO_CONTROL) { + if (!bg_state_) { + std::string rpc_port = b.GetString(AUL_K_RPC_PORT); + if (rpc_port.empty()) + RaiseWin(); + } + } +} + +int AppCoreUiBase::Impl::IsLegacyLifecycle() { + static int is_legacy = -1; + if (__builtin_expect(is_legacy != -1, 1)) + return is_legacy; + + const char* api_version = getenv("TIZEN_API_VERSION"); + if (api_version) { + if (strverscmp("2.4", api_version) > 0 && + strverscmp("2.2.1", api_version) < 0) + is_legacy = 1; + else + is_legacy = 0; + } else { + is_legacy = 0; + } + + return is_legacy; +} + +int AppCoreUiBase::OnPause() { + return 0; +} + +int AppCoreUiBase::OnResume() { + return 0; +} + +int AppCoreUiBase::OnReceive(aul_type type, tizen_base::Bundle b) { + if (impl_->state_ == Impl::AS_DYING) { + _E("Skip the event in dying state"); + return 0; + } + + if ((type == AUL_TERMINATE_BGAPP || type == AUL_TERMINATE_BG_INST) && + impl_->state_ != Impl::AS_PAUSED) + return 0; + + if (type == AUL_START) + impl_->ExitFromSuspend(); + + AppCoreBase::OnReceive(type, b); + + switch (type) { + case AUL_START: + impl_->DoStart(b); + if (GetHint() & HINT_LEGACY_CONTROL) { + if (impl_->bg_state_ && impl_->IsLegacyLifecycle()) { + _D("Legacy lifecycle"); + impl_->DoResume(); + } + } + break; + case AUL_RESUME: + if (impl_->bg_state_) + impl_->ApplyBgState(false); + + impl_->RaiseWin(); + break; + case AUL_TERMINATE: + if (impl_->state_ == Impl::AS_RUNNING) { + _D("Call pause callback"); + if (impl_->core_ui_delegator_) + impl_->core_ui_delegator_->OnPause(); + else + OnPause(); + } + impl_->state_ = Impl::AS_DYING; + break; + case AUL_TERMINATE_BGAPP: + case AUL_TERMINATE_BG_INST: + case AUL_TERMINATE_INST: + _D("[APP %d] TERMINATE", getpid()); + if (impl_->state_ == Impl::AS_RUNNING) { + _D("Call pause callback"); + if (impl_->core_ui_delegator_) + impl_->core_ui_delegator_->OnPause(); + else + OnPause(); + } + impl_->state_ = Impl::AS_DYING; + aul_status_update(STATUS_DYING); + Exit(); + break; + case AUL_PAUSE: + impl_->PauseWin(); + break; + default: + break; + } + + return 0; +} + +int AppCoreUiBase::OnCreate() { + AppCoreBase::OnCreate(); + impl_->state_ = Impl::AS_CREATED; + LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]", + impl_->appid_.c_str()); + return 0; +} + +int AppCoreUiBase::OnTerminate() { + if (impl_->state_ == Impl::AS_RUNNING) { + _D("Call pause callback"); + OnPause(); + } + + impl_->state_ = Impl::AS_DYING; + AppCoreBase::OnTerminate(); + return 0; +} + +int AppCoreUiBase::OnTrimMemory() { + return AppCoreBase::OnTrimMemory(); +} + +int AppCoreUiBase::GroupAdd() { + _D("Group attach"); + static bool attached = false; + if (attached) + return 0; + + int wid = GetMainSurface(); + if (wid == 0) { + _E("window wasn't ready"); + return -1; + } + + int ret = aul_app_group_set_window(wid); + if (ret < 0) { + _E("Failed to set app group window. error(%d)", ret); + return ret; + } + + attached = true; + return 0; +} + +void AppCoreUiBase::GroupRemove() { + _D("Group lower"); + int exit = 0; + aul_app_group_lower(&exit); + if (exit) { + _W("Sub App"); + Exit(); + } +} + +void AppCoreUiBase::OnShow(int type, void* event) { + auto* ev = reinterpret_cast(event); + if (ev->parent_win != 0) + return; + + unsigned int win = static_cast(ev->win); + unsigned int surf = static_cast(ev->data[0]); + _D("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN: %u, %u", win, surf); + + if (!impl_->FindWin(win)) + impl_->AddWin(win, surf); + else + impl_->UpdateWin(win, surf, Impl::VT_NONE); + + if (surf != 0) + GroupAdd(); +} + +bool AppCoreUiBase::Impl::CheckVisible() { + _D("[EVENT_TEST][EVENT] __check_visible"); + for (auto& i : winnode_list_) { + _D("win : %u visibility : %d", i->win_, i->vis_); + if (i->vis_ == VT_UNOBSCURED) + return true; + } + + return false; +} + +void AppCoreUiBase::OnHide(int type, void* event) { + auto* ev = reinterpret_cast(event); + _D("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN :%d", ev->win); + if (impl_->FindWin((unsigned int)ev->win)) { + impl_->DeleteWin((unsigned int)ev->win); + bool bvisibility = impl_->CheckVisible(); + if (!bvisibility && impl_->w_status_ != Impl::WS_PAUSE) { + _D("Go to Pasue state"); + impl_->w_status_ = Impl::WS_PAUSE; + impl_->DoPause(); + } + } +} + +void AppCoreUiBase::OnLower(int type, void* event) { + auto* ev = reinterpret_cast(event); + if (!ev) + return; + + _D("ECORE_WL2_EVENT_WINDOW_LOWER window id: %u", ev->win); + if (!(impl_->hint_ & HINT_WINDOW_GROUP_CONTROL)) + return; + + GroupRemove(); +} + +void AppCoreUiBase::OnVisibility(int type, void* event) { + auto* ev = reinterpret_cast(event); + impl_->UpdateWin((unsigned int)ev->win, 0, + ev->fully_obscured ? Impl::VT_FULLY_OBSCURED : Impl::VT_UNOBSCURED); + bool bvisibility = impl_->CheckVisible(); + _D("bvisibility %d, w_status_ %d", bvisibility, impl_->w_status_); + + if (bvisibility && (impl_->hint_ & HINT_WINDOW_STACK_CONTROL) && + !impl_->below_app_.empty()) { + aul_app_group_activate_below(impl_->below_app_.c_str()); + impl_->below_app_.clear(); + } + + if (bvisibility && impl_->w_status_ != Impl::WS_RESUME) { + _D("Go to Resume state"); + impl_->w_status_ = Impl::WS_RESUME; + impl_->DoResume(); + } else if (!bvisibility && impl_->w_status_ != Impl::WS_PAUSE) { + _D("Go to Pasue state"); + impl_->w_status_ = Impl::WS_PAUSE; + impl_->DoPause(); + } else { + _D("No change state"); + } +} + +void AppCoreUiBase::OnPreVisibility(int type, void* event) { + auto* ev = reinterpret_cast( + event); + if (ev && ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) { + impl_->UpdateWin((unsigned int)ev->win, 0, Impl::VT_UNOBSCURED); + bool bvisibility = impl_->CheckVisible(); + + _D("bvisibility %d, w_status_ %d", bvisibility, impl_->w_status_); + if (bvisibility && impl_->w_status_ != Impl::WS_RESUME) { + _D(" Go to Resume state"); + impl_->w_status_ = Impl::WS_RESUME; + impl_->DoResume(); + } + } +} + +void AppCoreUiBase::OnAuxMessage(int type, void* event) { + auto* ev = reinterpret_cast(event); + if (ev->key && !strcmp(ev->key, "dpms_wm")) { + if (ev->val && !strcmp(ev->val, "on")) { + _D("Display state: on"); + SetDisplayState(DISPLAY_STATE_ON); + } else if (ev->val && !strcmp(ev->val, "off")) { + _D("Display state: off"); + SetDisplayState(DISPLAY_STATE_OFF); + } else { + _E("Unknown state: %s", ev->val); + } + } +} + +void AppCoreUiBase::Pause() { + impl_->DoPause(); +} + +void AppCoreUiBase::Resume() { + impl_->DoResume(); +} + +bool AppCoreUiBase::IsResumed() { + return impl_->state_ == Impl::AS_RUNNING; +} + +int AppCoreUiBase::GetHint() { + return impl_->hint_; +} + +bool AppCoreUiBase::GetBgState() { + return impl_->bg_state_; +} + +void AppCoreUiBase::SetBgState(bool bg_state) { + impl_->bg_state_ = bg_state; +} + +void AppCoreUiBase::SetSystemResourceReclaiming(bool enable) { + impl_->resource_reclaiming_ = enable; +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_base.hh b/tizen-cpp/app-core-ui-cpp/app_core_ui_base.hh new file mode 100644 index 0000000..2d06eb9 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_base.hh @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_BASE_HH_ +#define TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_BASE_HH_ + +#include + +#include +#include +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API AppCoreUiBase : public AppCoreBase, + public IAppCoreUi, + public IWindow { + public: + constexpr static int HINT_WINDOW_GROUP_CONTROL = 0x1; + constexpr static int HINT_WINDOW_STACK_CONTROL = 0x2; + constexpr static int HINT_BG_LAUNCH_CONTROL = 0x4; + constexpr static int HINT_HW_ACC_CONTROL = 0x8; + constexpr static int HINT_WINDOW_AUTO_CONTROL = 0x10; + constexpr static int HINT_LEGACY_CONTROL = 0x20; + constexpr static int HINT_WINDOW_ID_CONTROL = 0x40; + + AppCoreUiBase(unsigned int hint); + virtual ~AppCoreUiBase(); + + int OnPause() override; + int OnResume() override; + int OnReceive(aul_type type, tizen_base::Bundle b) override; + int OnCreate() override; + int OnTerminate() override; + int OnTrimMemory() override; + void OnShow(int type, void* event) override; + void OnHide(int type, void* event) override; + void OnLower(int type, void* event) override; + void OnVisibility(int type, void* event) override; + void OnPreVisibility(int type, void* event) override; + void OnAuxMessage(int type, void* event) override; + void Pause(); + void Resume(); + bool IsResumed(); + int GroupAdd(); + void GroupRemove(); + unsigned int GetMainWindow(); + unsigned int GetMainSurface(); + int GetHint(); + bool GetBgState(); + void SetBgState(bool bg_state); + void SetSystemResourceReclaiming(bool enable); + void Run(int argc, char** argv) override; + void Dispose() override; + + protected: + void SetCoreUiDelegator(IAppCoreUi* delegator); + void SetWindowDelegator(IWindow* delegator); + + private: + class Impl; + std::unique_ptr impl_; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_BASE_HH_ diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_base_legacy.cc b/tizen-cpp/app-core-ui-cpp/app_core_ui_base_legacy.cc new file mode 100644 index 0000000..1261323 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_base_legacy.cc @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2021 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 "app_core_ui_base.hh" +#include "appcore_ui_base.h" + +#undef EXPORT_API +#define EXPORT_API __attribute__ ((visibility("default"))) + +namespace tizen_cpp { + +namespace { + +class AppCoreUi : public AppCoreUiBase { + public: + AppCoreUi(unsigned int hint, appcore_ui_base_ops ops, void* data) + : AppCoreUiBase(hint), ops_(ops), data_(data) {} + + void OnLoopInit(int argc, char** argv) override { + if (ops_.base.init) + ops_.base.init(argc, argv, data_); + } + + void OnLoopFinish() override { + if (ops_.base.finish) + ops_.base.finish(data_); + } + + void OnLoopRun() override { + if (ops_.base.run) + ops_.base.run(data_); + } + + void OnLoopExit() override { + if (ops_.base.exit) + ops_.base.exit(data_); + } + + int OnReceive(aul_type type, tizen_base::Bundle b) override { + if (ops_.base.receive) + return ops_.base.receive(type, b.GetHandle(), data_); + return -1; + } + + int OnCreate() override { + if (ops_.base.create) + return ops_.base.create(data_); + return -1; + } + + int OnControl(tizen_base::Bundle b) override { + if (ops_.base.control) + return ops_.base.control(b.GetHandle(), data_); + return -1; + } + + int OnTerminate() override { + if (ops_.base.terminate) + return ops_.base.terminate(data_); + return -1; + } + + int OnSetI18n() override { + if (ops_.base.set_i18n) + return ops_.base.set_i18n(data_); + return -1; + } + + int OnSetEvent(IEvent::Type event) override { + if (!ops_.base.set_event) + return -1; + + ops_.base.set_event((appcore_base_event)event, data_); + return 0; + } + + int OnUnsetEvent(IEvent::Type event) override { + if (!ops_.base.unset_event) + return -1; + + ops_.base.unset_event((appcore_base_event)event, data_); + return 0; + } + + int OnTrimMemory() override { + if (!ops_.base.trim_memory) + return -1; + + ops_.base.trim_memory(data_); + return 0; + } + + int OnPause() override { + if (ops_.pause) + return ops_.pause(data_); + return -1; + } + + int OnResume() override { + if (ops_.resume) + return ops_.resume(data_); + return -1; + } + + void OnShow(int type, void* event) override { + if (ops_.window.show) + ops_.window.show(type, event, data_); + } + + void OnHide(int type, void* event) override { + if (ops_.window.hide) + ops_.window.hide(type, event, data_); + } + + void OnLower(int type, void* event) override { + if (ops_.window.lower) + ops_.window.lower(type, event, data_); + } + + void OnVisibility(int type, void* event) override { + if (ops_.window.visibility) + ops_.window.visibility(type, event, data_); + } + + void OnPreVisibility(int type, void* event) override { + if (ops_.window.pre_visibility) + ops_.window.pre_visibility(type, event, data_); + } + + void OnAuxMessage(int type, void* event) override { + if (ops_.window.aux_message) + ops_.window.aux_message(type, event, data_); + } + + private: + appcore_ui_base_ops ops_; + void* data_; +}; + +std::unique_ptr __context; + +int __on_control(bundle* b, void* data) { + return appcore_ui_base_on_control(b); +} + +int __on_set_i18n(void* data) { + return appcore_ui_base_on_set_i18n(); +} + +void __on_set_event(enum appcore_base_event event, void* data) { + appcore_ui_base_on_set_event(event); +} + +void __on_unset_event(enum appcore_base_event event, void* data) { + appcore_ui_base_on_unset_event(event); +} + +void __on_trim_memory(void* data) { + appcore_ui_base_on_trim_memory(); +} + +int __on_receive(aul_type type, bundle* b, void* data) { + return appcore_ui_base_on_receive(type, b); +} + +int __on_create(void* data) { + return appcore_ui_base_on_create(); +} + +int __on_terminate(void* data) { + return appcore_ui_base_on_terminate(); +} + +int __on_pause(void* data) { + return appcore_ui_base_on_pause(); +} + +int __on_resume(void* data) { + return appcore_ui_base_on_resume(); +} + +void __window_on_show(int type, void* event, void* data) { + appcore_ui_base_window_on_show(type, event); +} + +void __window_on_hide(int type, void* event, void* data) { + appcore_ui_base_window_on_hide(type, event); +} + +void __window_on_lower(int type, void* event, void* data) { + appcore_ui_base_window_on_lower(type, event); +} + +void __window_on_visibility(int type, void* event, void* data) { + appcore_ui_base_window_on_visibility(type, event); +} + +void __window_on_pre_visibility(int type, void* event, void* data) { + appcore_ui_base_window_on_pre_visibility(type, event); +} + +void __window_on_aux_message(int type, void* event, void* data) { + appcore_ui_base_window_on_aux_message(type, event); +} + +} // namespace +} // namespace tizen_cpp + +using namespace tizen_cpp; + +extern "C" EXPORT_API int appcore_ui_base_on_receive(aul_type type, bundle*b) { + if (__context.get() == nullptr) + return -1; + return __context->AppCoreUiBase::OnReceive(type, tizen_base::Bundle(b)); +} + +extern "C" EXPORT_API int appcore_ui_base_on_create(void) { + if (__context.get() == nullptr) + return -1; + return __context->AppCoreUiBase::OnCreate(); +} + +extern "C" EXPORT_API int appcore_ui_base_on_terminate(void) { + if (__context.get() == nullptr) + return -1; + return __context->AppCoreUiBase::OnTerminate(); +} + +extern "C" EXPORT_API int appcore_ui_base_on_pause(void) { + if (__context.get() == nullptr) + return -1; + return __context->AppCoreUiBase::OnPause(); +} + +extern "C" EXPORT_API int appcore_ui_base_on_resume(void) { + if (__context.get() == nullptr) + return -1; + return __context->AppCoreUiBase::OnResume(); +} + +extern "C" EXPORT_API int appcore_ui_base_on_control(bundle* b) { + if (__context.get() == nullptr) + return -1; + return __context->AppCoreUiBase::OnControl( + b ? tizen_base::Bundle(b) : tizen_base::Bundle()); +} + +extern "C" EXPORT_API int appcore_ui_base_on_trim_memory(void) { + if (__context.get() == nullptr) + return -1; + return __context->AppCoreUiBase::OnTrimMemory(); +} + +extern "C" EXPORT_API void appcore_ui_base_window_on_show(int type, + void* event) { + if (__context.get() == nullptr) + return; + __context->AppCoreUiBase::OnShow(type, event); +} + +extern "C" EXPORT_API void appcore_ui_base_window_on_hide(int type, + void* event) { + if (__context.get() == nullptr) + return; + __context->AppCoreUiBase::OnHide(type, event); +} + +extern "C" EXPORT_API void appcore_ui_base_window_on_lower(int type, + void* event) { + if (__context.get() == nullptr) + return; + __context->AppCoreUiBase::OnLower(type, event); +} + +extern "C" EXPORT_API void appcore_ui_base_window_on_visibility(int type, + void* event) { + if (__context.get() == nullptr) + return; + __context->AppCoreUiBase::OnVisibility(type, event); +} + +extern "C" EXPORT_API void appcore_ui_base_window_on_pre_visibility(int type, + void* event) { + if (__context.get() == nullptr) + return; + __context->AppCoreUiBase::OnPreVisibility(type, event); +} + +extern "C" EXPORT_API void appcore_ui_base_window_on_aux_message(int type, + void* event) { + if (__context.get() == nullptr) + return; + __context->AppCoreUiBase::OnAuxMessage(type, event); +} + +extern "C" EXPORT_API int appcore_ui_base_on_set_i18n(void) { + if (__context.get() == nullptr) + return -1; + return __context->AppCoreUiBase::OnSetI18n(); +} + +extern "C" EXPORT_API void appcore_ui_base_on_set_event( + enum appcore_base_event event) { + if (__context.get() == nullptr) + return; + __context->AppCoreUiBase::OnSetEvent( + static_cast(event)); +} + +extern "C" EXPORT_API void appcore_ui_base_on_unset_event( + enum appcore_base_event event) { + if (__context.get() == nullptr) + return; + __context->AppCoreUiBase::OnUnsetEvent( + static_cast(event)); +} + +extern "C" EXPORT_API int appcore_ui_base_init(appcore_ui_base_ops ops, + int argc, char** argv, void* data, unsigned int hint) { + __context.reset(new AppCoreUi(hint, ops, data)); + try { + __context->Init(argc, argv); + } catch (const std::runtime_error&) { + return -1; + } + + return 0; +} + +extern "C" EXPORT_API void appcore_ui_base_fini(void) { + if (__context.get() == nullptr) + return; + __context->Fini(); + __context.reset(); +} + +extern "C" EXPORT_API appcore_ui_base_ops +appcore_ui_base_get_default_ops(void) { + appcore_ui_base_ops ops; + + ops.base.create = __on_create; + ops.base.control = __on_control; + ops.base.terminate = __on_terminate; + ops.base.receive = __on_receive; + ops.base.set_i18n = __on_set_i18n; + ops.base.init = nullptr; + ops.base.finish = nullptr; + ops.base.run = nullptr; + ops.base.exit = nullptr; + ops.base.set_event = __on_set_event; + ops.base.unset_event = __on_unset_event; + ops.base. trim_memory = __on_trim_memory; + ops.pause = __on_pause; + ops.resume = __on_resume; + ops.window.show = __window_on_show; + ops.window.hide = __window_on_hide; + ops.window.lower = __window_on_lower; + ops.window.visibility = __window_on_visibility; + ops.window.pre_visibility = __window_on_pre_visibility; + ops.window.aux_message = __window_on_aux_message; + + return ops; +} + +extern "C" EXPORT_API void appcore_ui_base_pause(void) { + if (__context.get() == nullptr) + return; + __context->Pause(); +} + +extern "C" EXPORT_API void appcore_ui_base_resume(void) { + if (__context.get() == nullptr) + return; + __context->Resume(); +} + +extern "C" EXPORT_API bool appcore_ui_base_is_resumed(void) { + if (__context.get() == nullptr) + return false; + return __context->IsResumed(); +} + +extern "C" EXPORT_API void appcore_ui_base_exit(void) { + if (__context.get() == nullptr) + return; + __context->Exit(); +} + +extern "C" EXPORT_API int appcore_ui_base_group_add() { + if (__context.get() == nullptr) + return -1; + return __context->GroupAdd(); +} + +extern "C" EXPORT_API void appcore_ui_base_group_remove() { + if (__context.get() == nullptr) + return; + __context->GroupRemove(); +} + +extern "C" EXPORT_API unsigned int appcore_ui_base_get_main_window(void) { + if (__context.get() == nullptr) + return 0; + return __context->GetMainWindow(); +} + +extern "C" EXPORT_API unsigned int appcore_ui_base_get_main_surface(void) { + if (__context.get() == nullptr) + return 0; + return __context->GetMainSurface(); +} + +extern "C" EXPORT_API int appcore_ui_base_get_hint(void) { + if (__context.get() == nullptr) + return 0; + return __context->GetHint(); +} + +extern "C" EXPORT_API bool appcore_ui_base_get_bg_state(void) { + if (__context.get() == nullptr) + return false; + return __context->GetBgState(); +} + +extern "C" EXPORT_API void appcore_ui_base_set_bg_state(bool bg_state) { + if (__context.get() == nullptr) + return; + __context->SetBgState(bg_state); +} + +extern "C" EXPORT_API void appcore_ui_base_set_system_resource_reclaiming( + bool enable) { + if (__context.get() == nullptr) + return; + __context->SetSystemResourceReclaiming(enable); +} diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_delegator_private.cc b/tizen-cpp/app-core-ui-cpp/app_core_ui_delegator_private.cc new file mode 100644 index 0000000..335676b --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_delegator_private.cc @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 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 "app-core-ui-cpp/app_core_ui_delegator_private.hh" + +namespace tizen_cpp { + +AppCoreUiDelegator::AppCoreUiDelegator(appcore_ui_base_ops ops, + AppCoreUiBase* base) + : ops_(ops), base_(base) { +} + +int AppCoreUiDelegator::OnReceive(aul_type type, tizen_base::Bundle b) { + if (ops_.base.receive) + return ops_.base.receive(type, b.GetHandle(), base_); + return -1; +} + +int AppCoreUiDelegator::OnCreate() { + if (ops_.base.create) + return ops_.base.create(base_); + return -1; +} + +int AppCoreUiDelegator::OnControl(tizen_base::Bundle b) { + if (ops_.base.control) + return ops_.base.control(b.GetHandle(), base_); + return -1; +} + +int AppCoreUiDelegator::OnTerminate() { + if (ops_.base.terminate) + return ops_.base.terminate(base_); + return -1; +} + +int AppCoreUiDelegator::OnSetI18n() { + if (ops_.base.set_i18n) + return ops_.base.set_i18n(base_); + return -1; +} + +int AppCoreUiDelegator::OnSetEvent(IEvent::Type event) { + if (ops_.base.set_event) + ops_.base.set_event(static_cast(event), base_); + return 0; +} + +int AppCoreUiDelegator::OnUnsetEvent(IEvent::Type event) { + if (ops_.base.unset_event) + ops_.base.unset_event(static_cast(event), base_); + return 0; +} + +int AppCoreUiDelegator::OnTrimMemory() { + if (ops_.base.trim_memory) + ops_.base.trim_memory(base_); + return 0; +} + +void AppCoreUiDelegator::OnLoopInit(int argc, char** argv) { + if (ops_.base.init) + ops_.base.init(argc, argv, base_); +} + +void AppCoreUiDelegator::OnLoopFinish() { + if (ops_.base.finish) + ops_.base.finish(base_); +} + +void AppCoreUiDelegator::OnLoopRun() { + if (ops_.base.run) + ops_.base.run(base_); +} + +void AppCoreUiDelegator::OnLoopExit() { + if (ops_.base.exit) + ops_.base.exit(base_); +} + +int AppCoreUiDelegator::OnPause() { + if (ops_.pause) + return ops_.pause(base_); + return -1; +} + +int AppCoreUiDelegator::OnResume() { + if (ops_.resume) + return ops_.resume(base_); + return -1; +} + +void AppCoreUiDelegator::OnShow(int type, void* event) { + if (ops_.window.show) + ops_.window.show(type, event, base_); +} + +void AppCoreUiDelegator::OnHide(int type, void* event) { + if (ops_.window.hide) + ops_.window.hide(type, event, base_); +} + +void AppCoreUiDelegator::OnLower(int type, void* event) { + if (ops_.window.lower) + ops_.window.lower(type, event, base_); +} + +void AppCoreUiDelegator::OnVisibility(int type, void* event) { + if (ops_.window.visibility) + ops_.window.visibility(type, event, base_); +} + +void AppCoreUiDelegator::OnPreVisibility(int type, void* event) { + if (ops_.window.pre_visibility) + ops_.window.pre_visibility(type, event, base_); +} + +void AppCoreUiDelegator::OnAuxMessage(int type, void* event) { + if (ops_.window.aux_message) + ops_.window.aux_message(type, event, base_); +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_delegator_private.hh b/tizen-cpp/app-core-ui-cpp/app_core_ui_delegator_private.hh new file mode 100644 index 0000000..6b6dd4f --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_delegator_private.hh @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_DELEGATOR_PRIVATE_HH_ +#define TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_DELEGATOR_PRIVATE_HH_ + +#include "app-core-ui-cpp/app_core_ui_base.hh" +#include "app-core-ui-cpp/appcore_ui_base.h" + +namespace tizen_cpp { + +class AppCoreUiDelegator : public IAppCore, + public IMainLoop, + public IAppCoreUi, + public IWindow { + public: + AppCoreUiDelegator(appcore_ui_base_ops ops, AppCoreUiBase* base); + + int OnReceive(aul_type type, tizen_base::Bundle b) override; + int OnCreate(); + int OnControl(tizen_base::Bundle b); + int OnTerminate(); + int OnSetI18n(); + int OnSetEvent(IEvent::Type event); + int OnUnsetEvent(IEvent::Type event); + int OnTrimMemory(); + void OnLoopInit(int argc, char** argv); + void OnLoopFinish(); + void OnLoopRun(); + void OnLoopExit(); + int OnPause(); + int OnResume(); + void OnShow(int type, void* event); + void OnHide(int type, void* event); + void OnLower(int type, void* event); + void OnVisibility(int type, void* event); + void OnPreVisibility(int type, void* event); + void OnAuxMessage(int type, void* event); + + private: + appcore_ui_base_ops ops_; + AppCoreUiBase* base_; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_DELEGATOR_PRIVATE_HH_ diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_plugin_private.cc b/tizen-cpp/app-core-ui-cpp/app_core_ui_plugin_private.cc new file mode 100644 index 0000000..71b01e9 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_plugin_private.cc @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 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 +#include + +#include + +#include "app-core-ui-cpp/app_core_ui_plugin_private.hh" +#include "app-core-ui-cpp/appcore_ui_base.h" +#include "common/log_private.hh" + +namespace tizen_cpp { + +namespace { + +constexpr const char kPathLibAppCoreUiPlugin[] = + "/usr/share/appcore/plugins/libappcore-ui-plugin.so"; +constexpr const char kAppCoreUiPluginInit[] = "APPCORE_UI_PLUGIN_INIT"; +constexpr const char kAppCoreUiPluginFini[] = "APPCORE_UI_PLUGIN_FINI"; + +} // namespace + +AppCoreUiPlugin::AppCoreUiPlugin(void* handle, PluginInitFunc init_func, + PluginFiniFunc fini_func) + : handle_(handle), init_func_(init_func), fini_func_(fini_func) { +} + +AppCoreUiPlugin::~AppCoreUiPlugin() { + if (handle_) + dlclose(handle_); +} + +AppCoreUiPlugin* AppCoreUiPlugin::Load() { + if (access(kPathLibAppCoreUiPlugin, F_OK) != 0) + return nullptr; + + void* handle = dlopen(kPathLibAppCoreUiPlugin, RTLD_LAZY); + if (handle == nullptr) { + _E("dlopen() is failed. path(%s)", kPathLibAppCoreUiPlugin); + return nullptr; + } + + auto init_func = reinterpret_cast( + dlsym(handle, kAppCoreUiPluginInit)); + if (init_func == nullptr) + _W("dlsym() is failed. symbol(%s)", kAppCoreUiPluginInit); + + auto fini_func = reinterpret_cast( + dlsym(handle, kAppCoreUiPluginFini)); + if (fini_func == nullptr) + _W("dlsym() is failed. symbol(%s)", kAppCoreUiPluginFini); + + return new (std::nothrow) AppCoreUiPlugin(handle, init_func, fini_func); +} + +void AppCoreUiPlugin::Init(appcore_ui_base_ops* ops, int argc, char** argv, + unsigned int* hint) { + _I("[__PLUGIN__] INIT"); + if (init_func_ == nullptr) + return; + + init_func_(ops, argc, argv, hint); +} + +void AppCoreUiPlugin::Fini() { + _I("[__PLUGIN__] FINI"); + if (fini_func_ == nullptr) + return; + + fini_func_(); +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_plugin_private.hh b/tizen-cpp/app-core-ui-cpp/app_core_ui_plugin_private.hh new file mode 100644 index 0000000..77e8ce7 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_plugin_private.hh @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_PLUGIN_PRIVATE_HH_ +#define TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_PLUGIN_PRIVATE_HH_ + +#include "appcore_ui_base.h" + +namespace tizen_cpp { + +class AppCoreUiPlugin { + public: + using PluginInitFunc = + int (*)(appcore_ui_base_ops*, int, char**, unsigned int*); + using PluginFiniFunc = int (*)(void); + + AppCoreUiPlugin(void* handle, PluginInitFunc init_func, + PluginFiniFunc fini_func); + ~AppCoreUiPlugin(); + + static AppCoreUiPlugin* Load(); + + void Init(appcore_ui_base_ops* ops, int argc, char** argv, + unsigned int* hint); + void Fini(); + + private: + void* handle_ = nullptr; + PluginInitFunc init_func_ = nullptr; + PluginFiniFunc fini_func_ = nullptr; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_PLUGIN_PRIVATE_HH_ diff --git a/tizen-cpp/app-core-ui-cpp/appcore_ui_base.h b/tizen-cpp/app-core-ui-cpp/appcore_ui_base.h new file mode 100644 index 0000000..671b440 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/appcore_ui_base.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_UI_BASE_H_ +#define TIZEN_CPP_APP_CORE_UI_BASE_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum appcore_base_event { + APPCORE_BASE_EVENT_START, + APPCORE_BASE_EVENT_LOW_MEMORY, + APPCORE_BASE_EVENT_LOW_BATTERY, + APPCORE_BASE_EVENT_LANG_CHANGE, + APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED, + APPCORE_BASE_EVENT_REGION_CHANGE, + APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE, + APPCORE_BASE_EVENT_UPDATE_REQUESTED, + APPCORE_BASE_EVENT_MAX, +}; + +typedef struct _appcore_base_ops { + int (*create) (void *data); + int (*terminate) (void *data); + int (*control) (bundle *b, void *data); + int (*receive)(aul_type type, bundle *b, void *data); + int (*set_i18n)(void *data); + void (*init)(int argc, char **argv, void *data); + void (*finish)(void* data); + void (*run)(void *data); + void (*exit)(void *data); + void (*set_event)(enum appcore_base_event event, void *data); + void (*unset_event)(enum appcore_base_event event, void *data); + void (*trim_memory)(void *data); +} appcore_base_ops; + +typedef struct _appcore_ui_base_window_ops { + void (*show)(int type, void *event, void *data); + void (*hide)(int type, void *event, void *data); + void (*lower)(int type, void *event, void *data); + void (*visibility)(int type, void *event, void *data); + void (*pre_visibility)(int type, void *event, void *data); + void (*aux_message)(int type, void *event, void *data); +} appcore_ui_base_window_ops; + +typedef struct _appcore_ui_base_ops { + int (*pause) (void *data); + int (*resume) (void *data); + appcore_base_ops base; + appcore_ui_base_window_ops window; +} appcore_ui_base_ops; + +enum appcore_ui_base_hint { + APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL = 0x1, + APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL = 0x2, + APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL = 0x4, + APPCORE_UI_BASE_HINT_HW_ACC_CONTROL = 0x8, + APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL = 0x10, + APPCORE_UI_BASE_HINT_LEGACY_CONTROL = 0x20, + APPCORE_UI_BASE_HINT_WINDOW_ID_CONTROL = 0x40, +}; + +int appcore_ui_base_on_receive(aul_type type, bundle *b); +int appcore_ui_base_on_create(void); +int appcore_ui_base_on_terminate(void); +int appcore_ui_base_on_pause(void); +int appcore_ui_base_on_resume(void); +int appcore_ui_base_on_control(bundle *b); +int appcore_ui_base_on_trim_memory(void); +void appcore_ui_base_window_on_show(int type, void *event); +void appcore_ui_base_window_on_hide(int type, void *event); +void appcore_ui_base_window_on_lower(int type, void *event); +void appcore_ui_base_window_on_visibility(int type, void *event); +void appcore_ui_base_window_on_pre_visibility(int type, void *event); +void appcore_ui_base_window_on_aux_message(int type, void *event); +int appcore_ui_base_on_set_i18n(void); +void appcore_ui_base_on_set_event(enum appcore_base_event event); +void appcore_ui_base_on_unset_event(enum appcore_base_event event); +int appcore_ui_base_init(appcore_ui_base_ops ops, int argc, char **argv, + void *data, unsigned int hint); +void appcore_ui_base_fini(void); +appcore_ui_base_ops appcore_ui_base_get_default_ops(void); +void appcore_ui_base_pause(void); +void appcore_ui_base_resume(void); +bool appcore_ui_base_is_resumed(void); +void appcore_ui_base_exit(void); +int appcore_ui_base_group_add(); +void appcore_ui_base_group_remove(); +unsigned int appcore_ui_base_get_main_window(void); +unsigned int appcore_ui_base_get_main_surface(void); +int appcore_ui_base_get_hint(void); +bool appcore_ui_base_get_bg_state(void); +void appcore_ui_base_set_bg_state(bool bg_state); +void appcore_ui_base_set_system_resource_reclaiming(bool enable); + +#ifdef __cplusplus +} +#endif + +#endif // TIZEN_CPP_APP_CORE_UI_BASE_H_ diff --git a/tizen-cpp/app-core-ui-cpp/wayland_handler_private.cc b/tizen-cpp/app-core-ui-cpp/wayland_handler_private.cc new file mode 100644 index 0000000..7eb953f --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/wayland_handler_private.cc @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 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 +#include + +#include "app-core-ui-cpp/wayland_handler_private.hh" +#include "common/log_private.hh" + +namespace tizen_cpp { + +WaylandHandler::WaylandHandler() { +} + +WaylandHandler::~WaylandHandler() { + Fini(); +} + +int WaylandHandler::Init() { + _D("INIT"); + if (__builtin_expect(initialized_, 1)) + return 0; + + dsp_ = wl_display_connect(nullptr); + if (dsp_ == nullptr) { + _E("wl_display_connect() is failed"); + return -1; + } + + reg_ = wl_display_get_registry(dsp_); + if (reg_ == nullptr) { + _E("wl_display_get_registry() is failed"); + Fini(); + return -1; + } + + wl_registry_add_listener(reg_, ®_listener_, this); + wl_display_roundtrip(dsp_); + + if (tz_policy_ == nullptr) { + _E("Failed to get tizen policy interface"); + Fini(); + return -1; + } + + initialized_ = true; + return 0; +} + +void WaylandHandler::Fini() { + if (!initialized_) + return; + + if (tz_policy_) { + tizen_policy_destroy(tz_policy_); + tz_policy_ = nullptr; + } + + if (reg_) { + wl_registry_destroy(reg_); + reg_ = nullptr; + } + + if (dsp_) { + wl_display_disconnect(dsp_); + dsp_ = nullptr; + } + + initialized_ = false; +} + +void WaylandHandler::SetBgState() { + if (!initialized_) + return; + + tizen_policy_set_background_state(tz_policy_, getpid()); + wl_display_roundtrip(dsp_); + _D("Set Background State"); +} + +void WaylandHandler::UnsetBgState() { + if (!initialized_) + return; + + tizen_policy_unset_background_state(tz_policy_, getpid()); + wl_display_roundtrip(dsp_); + _D("Unset Background State"); +} + +void WaylandHandler::SetAppId(const std::string& app_id) { + if (!initialized_) + return; + + tizen_policy_set_appid(tz_policy_, getpid(), app_id.c_str()); + wl_display_roundtrip(dsp_); + _D("Set AppId: %s", app_id.c_str()); +} + +void WaylandHandler::WlListenerCb(void* data, struct wl_registry* reg, + uint32_t id, const char* interface, uint32_t ver) { + if (interface && !strcmp(interface, "tizen_policy")) { + auto* handle = static_cast(data); + if (handle->tz_policy_ == nullptr) { + handle->tz_policy_ = reinterpret_cast( + wl_registry_bind(reinterpret_cast(handle->reg_), + id, &tizen_policy_interface, 7)); + } + } +} + +void WaylandHandler::WlListenerRemoveCb(void* data, struct wl_registry* reg, + unsigned int id) { +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-ui-cpp/wayland_handler_private.hh b/tizen-cpp/app-core-ui-cpp/wayland_handler_private.hh new file mode 100644 index 0000000..16dbe67 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/wayland_handler_private.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_APP_CORE_UI_CPP_WAYLAND_HANDLER_PRIVATE_HH_ +#define TIZEN_CPP_APP_CORE_UI_CPP_WAYLAND_HANDLER_PRIVATE_HH_ + +#include +#include +#include + +#include + +namespace tizen_cpp { + +class WaylandHandler { + public: + WaylandHandler(); + ~WaylandHandler(); + + int Init(); + void Fini(); + void SetBgState(); + void UnsetBgState(); + void SetAppId(const std::string& app_id); + + private: + static void WlListenerCb(void* data, struct wl_registry* reg, + uint32_t id, const char* interface, uint32_t ver); + static void WlListenerRemoveCb(void* data, struct wl_registry* reg, + unsigned int id); + + private: + bool initialized_ = false; + struct wl_display* dsp_ = nullptr; + struct wl_registry* reg_ = nullptr; + struct tizen_policy* tz_policy_ = nullptr; + + const struct wl_registry_listener reg_listener_ = { + WlListenerCb, + WlListenerRemoveCb + }; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_UI_CPP_WAYLAND_HANDLER_PRIVATE_HH_ diff --git a/tizen-cpp/common/ecore_handler.cc b/tizen-cpp/common/ecore_handler.cc new file mode 100644 index 0000000..ace58b1 --- /dev/null +++ b/tizen-cpp/common/ecore_handler.cc @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2021 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 +#include + +#include + +#include "common/log_private.hh" +#include "common/ecore_handler.hh" + +namespace tizen_cpp { + +gboolean EcoreHandler::FlushMemoryCb(gpointer data) { + _D("Flush memory"); + EcoreHandler* base = reinterpret_cast(data); + base->GetTrim()->OnTrim(); + base->flush_timer_ = 0; + return G_SOURCE_REMOVE; +} + +void EcoreHandler::AddFlushTimer() { + if (flush_timer_ != 0) + return; + + flush_timer_ = g_timeout_add(5000, FlushMemoryCb, this); +} + +void EcoreHandler::RemoveFlushTimer() { + if (flush_timer_ == 0) + return; + + g_source_remove(flush_timer_); + flush_timer_ = 0; +} + +Eina_Bool EcoreHandler::StubShowCb(void* data, int type, void* event) { + EcoreHandler* base = reinterpret_cast(data); + base->GetWindow()->OnShow(type, event); + return ECORE_CALLBACK_RENEW; +} + +Eina_Bool EcoreHandler::StubHideCb(void* data, int type, void* event) { + EcoreHandler* base = reinterpret_cast(data); + base->GetWindow()->OnHide(type, event); + return ECORE_CALLBACK_RENEW; +} + +Eina_Bool EcoreHandler::StubVisibilityCb(void* data, int type, void* event) { + auto* ev = reinterpret_cast(event); + EcoreHandler* base = reinterpret_cast(data); + base->GetWindow()->OnVisibility(type, event); + + if (!base->GetTrim()) + return ECORE_CALLBACK_RENEW; + + if (ev && ev->fully_obscured) { + if (base->GetTrim()->IsTrimmable()) + base->AddFlushTimer(); + } else { + base->RemoveFlushTimer(); + } + + return ECORE_CALLBACK_RENEW; +} + +Eina_Bool EcoreHandler::StubLowerCb(void* data, int type, void* event) { + EcoreHandler* base = reinterpret_cast(data); + base->GetWindow()->OnLower(type, event); + return ECORE_CALLBACK_RENEW; +} + +Eina_Bool EcoreHandler::StubPreVisibilityCb(void* data, int type, void* event) { + auto* ev = reinterpret_cast( + event); + EcoreHandler* base = reinterpret_cast(data); + base->GetWindow()->OnPreVisibility(type, event); + + if (!base->GetTrim()) + return ECORE_CALLBACK_RENEW; + + if (ev && ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) + base->RemoveFlushTimer(); + + return ECORE_CALLBACK_RENEW; +} + +Eina_Bool EcoreHandler::StubAuxMessageCb(void* data, int type, void* event) { + EcoreHandler* base = reinterpret_cast(data); + base->GetWindow()->OnAuxMessage(type, event); + return ECORE_CALLBACK_RENEW; +} + +void EcoreHandler::Init() { + if (initialized_) + return; + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:ECORE_WL2_INIT"); + if (!ecore_wl2_init()) { + _E("Failed to initialize Ecore Wayland2"); + throw std::runtime_error("could not init wl2"); + } + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:DISPLAY_CONNECT"); + ecore_wl2_display_connect(nullptr); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + + hshow_ = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_SHOW, + StubShowCb, this); + if (hshow_ == nullptr) + _E("Failed to add ECORE_WL_EVENT_WINDOW_SHOW event"); + + hhide_ = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_HIDE, + StubHideCb, this); + if (hhide_ == nullptr) + _E("Failed to add ECORE_WL_EVENT_WINDOW_HIDE event"); + + hvchange_ = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, + StubVisibilityCb, this); + if (hvchange_ == nullptr) + _E("Failed to add ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE event"); + + hlower_ = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_LOWER, + StubLowerCb, this); + if (hlower_ == nullptr) + _E("Failed to add ECORE_WL_EVENT_WINDOW_LOWER event"); + + hpvchange_ = ecore_event_handler_add( + ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE, StubPreVisibilityCb, this); + if (hpvchange_ == nullptr) + _E("Failed to add ECORE_WL_EVENT_WINDOW_PRE_VISIBILITY_CHANGE event"); + + hauxmsg_ = ecore_event_handler_add(ECORE_WL2_EVENT_AUX_MESSAGE, + StubAuxMessageCb, this); + if (hauxmsg_ == nullptr) + _E("Failed to add ECORE_WL2_EVENT_AUX_MESSAGE event"); + + initialized_ = true; +} + +void EcoreHandler::Fini() { + if (!initialized_) + return; + + RemoveFlushTimer(); + + if (hshow_) { + ecore_event_handler_del(hshow_); + hshow_ = nullptr; + } + + if (hhide_) { + ecore_event_handler_del(hhide_); + hhide_ = nullptr; + } + + if (hvchange_) { + ecore_event_handler_del(hvchange_); + hvchange_ = nullptr; + } + + if (hlower_) { + ecore_event_handler_del(hlower_); + hlower_ = nullptr; + } + + if (hpvchange_) { + ecore_event_handler_del(hpvchange_); + hpvchange_ = nullptr; + } + + if (hauxmsg_) { + ecore_event_handler_del(hauxmsg_); + hauxmsg_ = nullptr; + } + + _E("Disconnect Wayland display"); + ecore_wl2_display_disconnect(ecore_wl2_connected_display_get(nullptr)); + ecore_wl2_shutdown(); + initialized_ = false; +} + +void EcoreHandler::RaiseWin(unsigned int win_id) { + auto* win = ecore_wl2_display_window_find( + ecore_wl2_connected_display_get(nullptr), win_id); + ecore_wl2_window_activate(win); +} + +void EcoreHandler::PauseWin(unsigned int win_id) { + auto* win = ecore_wl2_display_window_find( + ecore_wl2_connected_display_get(nullptr), win_id); + ecore_wl2_window_iconified_set(win, EINA_TRUE); +} + +EcoreHandler::EcoreHandler(IWindow* win) : window_(win) { +} + +EcoreHandler::EcoreHandler(IWindow* win, ITrim* trim) + : trim_(trim), window_(win) { +} + +EcoreHandler::~EcoreHandler() { + Fini(); +} + +EcoreHandler::ITrim* EcoreHandler::GetTrim() { + return trim_; +} + +IWindow* EcoreHandler::GetWindow() { + return window_; +} + +void EcoreHandler::SetWindow(IWindow* win) { + window_ = win; +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/common/ecore_handler.hh b/tizen-cpp/common/ecore_handler.hh new file mode 100644 index 0000000..04e641d --- /dev/null +++ b/tizen-cpp/common/ecore_handler.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_COMMON_ECORE_HANDLER_HH_ +#define TIZEN_CPP_COMMON_ECORE_HANDLER_HH_ + +#include +#include + +#include "app-core-cpp/interface_window.hh" + +namespace tizen_cpp { + +class EcoreHandler { + public: + class ITrim { + public: + virtual ~ITrim() = default; + virtual bool IsTrimmable() = 0; + virtual void OnTrim() = 0; + }; + + EcoreHandler(IWindow* win); + EcoreHandler(IWindow* win, ITrim* trim); + ~EcoreHandler(); + + void Init(); + void Fini(); + void RaiseWin(unsigned int win_id); + void PauseWin(unsigned int win_id); + ITrim* GetTrim(); + IWindow* GetWindow(); + void SetWindow(IWindow* win); + + private: + EcoreHandler(); + void AddFlushTimer(); + void RemoveFlushTimer(); + + static gboolean FlushMemoryCb(gpointer data); + static Eina_Bool StubShowCb(void* data, int type, void* event); + static Eina_Bool StubHideCb(void* data, int type, void* event); + static Eina_Bool StubVisibilityCb(void* data, int type, void* event); + static Eina_Bool StubLowerCb(void* data, int type, void* event); + static Eina_Bool StubPreVisibilityCb(void* data, int type, void* event); + static Eina_Bool StubAuxMessageCb(void* data, int type, void* event); + + private: + bool initialized_ = false; + Ecore_Event_Handler* hshow_ = nullptr; + Ecore_Event_Handler* hhide_ = nullptr; + Ecore_Event_Handler* hvchange_ = nullptr; + Ecore_Event_Handler* hlower_ = nullptr; + Ecore_Event_Handler* hpvchange_ = nullptr; + Ecore_Event_Handler* hauxmsg_ = nullptr; + ITrim* trim_ = nullptr; + IWindow* window_ = nullptr; + guint flush_timer_ = 0; +}; + +} // namepace tizen_cpp + +#endif // TIZEN_CPP_COMMON_ECORE_HANDLER_HH diff --git a/tizen-cpp/common/log_private.hh b/tizen-cpp/common/log_private.hh new file mode 100644 index 0000000..638f90b --- /dev/null +++ b/tizen-cpp/common/log_private.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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 TIZEN_CPP_COMMON_LOG_PRIVATE_HH_ +#define TIZEN_CPP_COMMON_LOG_PRIVATE_HH_ + +#include + +#undef LOG_TAG +#define LOG_TAG "APP_CORE_CPP" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // TIZEN_CPP_COMMON_LOG_PRIVATE_HH_ diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt new file mode 100644 index 0000000..8940982 --- /dev/null +++ b/unittests/CMakeLists.txt @@ -0,0 +1,55 @@ +SET(TARGET_UNIT_TEST "app-core_unittests") + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-cpp + LIB_APP_CORE_CPP_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-ui-cpp + LIB_APP_CORE_UI_CPP_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-efl-cpp + LIB_APP_CORE_EFL_CPP_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-multi-window-cpp + LIB_APP_CORE_MULTI_WINDOW_CPP_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/common + LIB_COMMON_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} TEST_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/mock/ MOCK_SRCS) + +ADD_EXECUTABLE(${TARGET_UNIT_TEST} + ${MOCK_SRCS} + ${TEST_SRCS} + ${LIB_APP_CORE_CPP_SRCS} + ${LIB_APP_CORE_UI_CPP_SRCS} + ${LIB_APP_CORE_EFL_CPP_SRCS} + ${LIB_APP_CORE_MULTI_WINDOW_CPP_SRCS} + ${LIB_COMMON_SRCS}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_UNIT_TEST} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/ + ${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-ui-cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-efl-cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-multi-window-cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/common +) + +APPLY_PKG_CONFIG(${TARGET_UNIT_TEST} PUBLIC + AUL_DEPS + BUNDLE_DEPS + CAPI_SYSTEM_INFO_DEPS + DLOG_DEPS + ECORE_WL2_DEPS + ELEMENTARY_DEPS + GIO_2_DEPS + GMOCK_DEPS + PKGMGR_INFO_DEPS + SENSOR_DEPS + TIZEN_EXTENSION_CLIENT_DEPS + TTRACE_DEPS + VCONF_DEPS + WAYLAND_CLIENT_DEPS +) + +TARGET_LINK_LIBRARIES(${TARGET_UNIT_TEST} PUBLIC "-L/usr/lib/hal") +SET_TARGET_PROPERTIES(${TARGET_UNIT_TEST} PROPERTIES COMPILE_FLAGS "-fPIE") +SET_TARGET_PROPERTIES(${TARGET_UNIT_TEST} PROPERTIES LINK_FLAGS "-pie") diff --git a/unittests/app_core_base_test.cc b/unittests/app_core_base_test.cc new file mode 100644 index 0000000..7d63a8d --- /dev/null +++ b/unittests/app_core_base_test.cc @@ -0,0 +1,788 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include + +#include "mock/test_fixture.h" +#include "mock/aul_mock.h" +#include "mock/sensor_mock.h" +#include "mock/vconf_mock.h" +#include "mock/dbus_mock.h" +#include "mock/dl_mock.h" +#include "mock/app_core_base_mock.h" + +#include + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::Invoke; + +namespace { +class Mocks : public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock {}; + +} // namespace + +namespace tizen_cpp { +class AppCoreBaseTest : public TestFixture { + public: + AppCoreBaseTest() : TestFixture(std::make_unique<::Mocks>()) {} + + virtual void SetUp() {} + + virtual void TearDown() {} + + static void SetUpTestCase() { + mkdir("/tmp/locale", 0777); + mkdir("/tmp/locale/cs", 0777); + mkdir("/tmp/locale/de", 0777); + mkdir("/tmp/locale/en", 0777); + mkdir("/tmp/locale/en_US", 0777); + } + + static void TearDownTestCase() { + rmdir("/tmp/locale/en_US"); + rmdir("/tmp/locale/en"); + rmdir("/tmp/locale/de"); + rmdir("/tmp/locale/cs"); + rmdir("/tmp/locale"); + } +}; + +class DummyArgs { + public: + DummyArgs() { + tizen_base::Bundle b; + b.Add("dummy", "dummy"); + argc_ = bundle_export_to_argv(b.GetHandle(), &argv_); + } + + DummyArgs(std::string key, std::string val) { + tizen_base::Bundle b; + b.Add(std::move(key), std::move(val)); + argc_ = bundle_export_to_argv(b.GetHandle(), &argv_); + } + + ~DummyArgs() { + bundle_free_exported_argv(argc_, &argv_); + } + + int GetArgc() const { + return argc_; + } + + char** GetArgv() const { + return argv_; + } + + private: + int argc_ = 0; + char** argv_ = nullptr; +}; + +class TestEvent : public AppCoreBase::EventBase { + public: + TestEvent(Type type) : EventBase(type) {} + + void OnEvent(const std::string& val) override { + SetVal(val); + } + void OnEvent(int val) override { + SetVal(val); + } +}; + +TEST_F(AppCoreBaseTest, AppCoreBase_Run_Cancel) { + testing::NiceMock core; + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + return -1; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnLoopInit(_, _)) + .Times(1); + EXPECT_CALL(core, OnLoopFinish()) + .Times(1); + EXPECT_CALL(core, OnLoopRun()) + .Times(0); + EXPECT_CALL(core, OnLoopExit()) + .Times(0); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_Run) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_Init_Fini) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.Init(da.GetArgc(), da.GetArgv()); + core.Fini(); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_Run_Again) { + testing::NiceMock core; + + ON_CALL(core, OnCreate()) + .WillByDefault(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + + EXPECT_CALL(core, OnCreate()) + .Times(2); + EXPECT_CALL(core, OnTerminate()) + .Times(2); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_OnControl) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .Times(1); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_AddEvent) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->RaiseEvent(9216, IAppCore::IEvent::Type::LOW_MEMORY); + obj->RaiseEvent("test", IAppCore::IEvent::Type::LOW_MEMORY); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + auto ev = std::shared_ptr( + new TestEvent(IAppCore::IEvent::Type::LOW_MEMORY)); + core.AddEvent(ev); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(ev->GetVal(0), 9216); + EXPECT_EQ(ev->GetVal(""), "test"); + core.RemoveEvent(ev); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_AllowBG) { + testing::NiceMock core; + bool bg = false; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnReceive(_, _)) + .WillOnce(Invoke([&core, &bg](aul_type type, tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnReceive(type, std::move(b)); + bg = core.IsBgAllowed(); + return ret; + })); + + DummyArgs da(AUL_K_ALLOWED_BG, "ALLOWED_BG"); + core.SetFeature(AppCoreBase::FEATURE_BACKGROUND_MANAGEMENT); + EXPECT_EQ(core.GetFeature(), AppCoreBase::FEATURE_BACKGROUND_MANAGEMENT); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_TRUE(bg); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_IsSuspended) { + testing::NiceMock core; + + EXPECT_FALSE(core.IsSuspended()); + core.ToggleSuspendedState(); + EXPECT_TRUE(core.IsSuspended()); + core.ToggleSuspendedState(); + EXPECT_FALSE(core.IsSuspended()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_FlushMemory) { + testing::NiceMock core; + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->FlushMemory(); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + EXPECT_CALL(core, OnTrimMemory()) + .Times(1); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_GetRotationState_N) { + bool result = false; + + try { + AppCoreBase::GetRotationState(); + } catch (const std::runtime_error& e) { + EXPECT_STREQ(e.what(), "invalid rotation state"); + result = true; + } + + EXPECT_TRUE(result); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_GetRotationState) { + testing::NiceMock core; + AppCoreBase::RotationState rst = AppCoreBase::ROTATION_UNKNOWN; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core, &rst]() -> int { + core.AppCoreBase::OnCreate(); + rst = AppCoreBase::GetRotationState(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(GetMock(), sensord_register_event(_, _, _, _, _, _)) + .WillOnce(Invoke([](int handle, unsigned int event_type, + unsigned int interval, unsigned int max_batch_latency, + sensor_cb_t cb, void *user_data) -> bool { + sensor_t sensor = { 0, }; + sensor_data_t data = { 0, }; + data.value_count = 1; + data.values[0] = AUTO_ROTATION_DEGREE_0; + cb(sensor, AUTO_ROTATION_CHANGE_STATE_EVENT, &data, user_data); + return true; + })); + + DummyArgs da; + auto ev = std::shared_ptr( + new TestEvent(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED)); + core.AddEvent(ev); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(rst, AppCoreBase::ROTATION_PORTRAIT_NORMAL); + core.RemoveEvent(ev); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_LockCb) { + testing::NiceMock core; + AppCoreBase::RotationState rst = AppCoreBase::ROTATION_UNKNOWN; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core, &rst]() -> int { + core.AppCoreBase::OnCreate(); + GetMock().ChangeBool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, true); + rst = AppCoreBase::GetRotationState(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + auto ev = std::shared_ptr( + new TestEvent(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED)); + core.AddEvent(ev); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(rst, AppCoreBase::ROTATION_PORTRAIT_NORMAL); + core.RemoveEvent(ev); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_ChargerStatusChangedCb) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + core.AppCoreBase::OnCreate(); + GetMock().ChangeInt(VCONFKEY_SYSMAN_CHARGER_STATUS, 0); + GetMock().ChangeInt(VCONFKEY_SYSMAN_CHARGER_STATUS, 1); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + auto ev = std::shared_ptr( + new TestEvent(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED)); + core.SetFeature(AppCoreBase::FEATURE_CHARGER_STATUS); + core.AddEvent(ev); + core.Run(da.GetArgc(), da.GetArgv()); + core.RemoveEvent(ev); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_AddEvent_LanguageChanged) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().ChangeStr(VCONFKEY_LANGSET, "en_US:kr:fr"); + return ret; + })); + EXPECT_CALL(GetMock(), vconf_get_str(_)) + .WillRepeatedly(Invoke([](const char* key) -> char* { + if (strcmp(key, VCONFKEY_LANGSET) == 0) { + return strdup("en_US:kr:fr"); + } + return nullptr; + })); + + DummyArgs da; + auto ev = std::shared_ptr( + new TestEvent(IAppCore::IEvent::Type::LANG_CHANGE)); + core.AddEvent(ev); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(ev->GetVal(""), "en_US:kr:fr"); + core.RemoveEvent(ev); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_AddEvent_RegionChanged) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().ChangeStr(VCONFKEY_REGIONFORMAT, "US"); + return ret; + })); + EXPECT_CALL(GetMock(), vconf_get_str(_)) + .WillRepeatedly(Invoke([](const char* key) -> char* { + if (strcmp(key, VCONFKEY_REGIONFORMAT) == 0) { + return strdup("US"); + } + return nullptr; + })); + + DummyArgs da; + auto ev = std::shared_ptr( + new TestEvent(IAppCore::IEvent::Type::REGION_CHANGE)); + core.AddEvent(ev); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(ev->GetVal(""), "US"); + core.RemoveEvent(ev); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_AddEvent_LowBattery) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().ChangeInt(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, + VCONFKEY_SYSMAN_BAT_CRITICAL_LOW); + return ret; + })); + + DummyArgs da; + auto ev = std::shared_ptr( + new TestEvent(IAppCore::IEvent::Type::LOW_BATTERY)); + core.AddEvent(ev); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(ev->GetVal(0), VCONFKEY_SYSMAN_BAT_CRITICAL_LOW); + core.RemoveEvent(ev); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_AddEvent_LowMemory) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().ChangeInt(VCONFKEY_SYSMAN_LOW_MEMORY, + VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING); + return ret; + })); + + DummyArgs da; + auto ev = std::shared_ptr( + new TestEvent(IAppCore::IEvent::Type::LOW_MEMORY)); + core.AddEvent(ev); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(ev->GetVal(0), VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING); + core.RemoveEvent(ev); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_EnableWatchdog) { + EXPECT_CALL(GetMock(), aul_watchdog_enable()) + .Times(1); + AppCoreBase::EnableWatchdog(); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_DisableWatchdog) { + EXPECT_CALL(GetMock(), aul_watchdog_disable()) + .Times(1); + AppCoreBase::DisableWatchdog(); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_KickWatchdog) { + EXPECT_CALL(GetMock(), aul_watchdog_kick()) + .Times(1); + AppCoreBase::KickWatchdog(); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_OnReceive_AUL_TERMINATE) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + return core.AppCoreBase::OnCreate(); + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(2); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().SetEvent(AUL_TERMINATE, bundle_create()); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_OnReceive_AUL_RESUME) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(2); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + bundle* kb = bundle_create(); + bundle_add_str(kb, AUL_K_ALLOWED_BG, "ALLOWED_BG"); + GetMock().SetEvent(AUL_RESUME, kb); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.SetFeature(AppCoreBase::FEATURE_BACKGROUND_MANAGEMENT); + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_OnReceive_AUL_UPDATE_REQUESTED) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(2); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().SetEvent(AUL_UPDATE_REQUESTED, bundle_create()); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_OnReceive_INVALID_EVENT) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(2); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().SetEvent((aul_type)9216, bundle_create()); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_OnReceive_AUL_TERMINATE_INST) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(2); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().SetEvent(AUL_TERMINATE_INST, bundle_create()); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_OnReceive_AUL_SUSPEND) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(2); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().SetEvent(AUL_SUSPEND, bundle_create()); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.SetFeature(AppCoreBase::FEATURE_BACKGROUND_MANAGEMENT); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_TRUE(core.IsSuspended()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_OnReceive_AUL_WAKE) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreBase::OnCreate(); + core.ToggleSuspendedState(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(2); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreBase::OnControl(std::move(b)); + GetMock().SetEvent(AUL_WAKE, bundle_create()); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + DummyArgs da; + core.SetFeature(AppCoreBase::FEATURE_BACKGROUND_MANAGEMENT); + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_FALSE(core.IsSuspended()); +} + +TEST_F(AppCoreBaseTest, AppCoreBase_RotationState) { + EXPECT_EQ(AppCoreBase::GetDisplayState(), AppCoreBase::DISPLAY_STATE_UNKNOWN); + AppCoreBase::SetDisplayState(AppCoreBase::DISPLAY_STATE_ON); + EXPECT_EQ(AppCoreBase::GetDisplayState(), AppCoreBase::DISPLAY_STATE_ON); + AppCoreBase::SetDisplayState(AppCoreBase::DISPLAY_STATE_UNKNOWN); + EXPECT_EQ(AppCoreBase::GetDisplayState(), AppCoreBase::DISPLAY_STATE_UNKNOWN); +} + +} // namespace tizen_cpp diff --git a/unittests/app_core_efl_base_test.cc b/unittests/app_core_efl_base_test.cc new file mode 100644 index 0000000..bb74996 --- /dev/null +++ b/unittests/app_core_efl_base_test.cc @@ -0,0 +1,855 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include +#include + +#include "mock/test_fixture.h" +#include "mock/aul_mock.h" +#include "mock/sensor_mock.h" +#include "mock/vconf_mock.h" +#include "mock/dbus_mock.h" +#include "mock/elm_mock.h" +#include "mock/wayland_mock.h" +#include "mock/ecore_wl2_mock.h" +#include "mock/ecore_mock.h" +#include "mock/dl_mock.h" +#include "mock/app_core_efl_base_mock.h" +#include "appcore_ui_base.h" + +#include + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::Invoke; + +namespace { +class Mocks : public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock {}; + +class DummyArgs { + public: + DummyArgs() { + tizen_base::Bundle b; + b.Add("dummy", "dummy"); + argc_ = bundle_export_to_argv(b.GetHandle(), &argv_); + } + + DummyArgs(std::string key, std::string val) { + tizen_base::Bundle b; + b.Add(std::move(key), std::move(val)); + argc_ = bundle_export_to_argv(b.GetHandle(), &argv_); + } + + ~DummyArgs() { + bundle_free_exported_argv(argc_, &argv_); + } + + int GetArgc() const { + return argc_; + } + + char** GetArgv() const { + return argv_; + } + + private: + int argc_ = 0; + char** argv_ = nullptr; +}; + +int __vc_elm_initialize(void) { + return 0; +} + +int __vc_elm_deinitialize(void) { + return 0; +} + +int __vc_elm_set_auto_register_mode(int, int) { + return 0; +} + +int __ui_plugin_init_dummy(appcore_ui_base_ops* ops, int argc, char** argv, + unsigned int *hint) { + return 0; +} + +int __ui_plugin_fini_dummy(void) { + return 0; +} + +} // namespace + +namespace tizen_cpp { + +class AppCoreEflBaseTest : public TestFixture { + public: + AppCoreEflBaseTest() : TestFixture(std::make_unique<::Mocks>()) {} + + virtual void SetUp() {} + + virtual void TearDown() {} +}; + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_Run) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(GetMock(), vconf_get_bool(_, _)) + .WillRepeatedly(Invoke([&](const char *in_key, + int* val) -> int { + if (strcmp(in_key, VCONFKEY_VC_VOICE_TOUCH_AUTOMODE) == 0) { + *val = 1; + return 0; + } + + *val = 0; + return 0; + })); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_AddEvent_OnTrimMemory) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(6000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnReceive(_, _)) + .Times(2); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + GetMock().SetEvent(AUL_SUSPEND, bundle_create()); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnTrimMemory()) + .Times(1); + + ::DummyArgs da; + core.SetFeature(AppCoreBase::FEATURE_BACKGROUND_MANAGEMENT); + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_AddEvent_SetSystemResourceReclaiming) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(6000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + core.Resume(); + core.Pause(); + return ret; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnTrimMemory()) + .Times(0); + + ::DummyArgs da; + core.SetFeature(AppCoreBase::FEATURE_BACKGROUND_MANAGEMENT); + core.SetSystemResourceReclaiming(false); + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_OnResume) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + Ecore_Wl2_Event_Window_Show ev_show; + ev_show.win = 1; + ev_show.parent_win = 0; + ev_show.data[0] = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_SHOW, &ev_show); + + Ecore_Wl2_Event_Window_Pre_Visibility_Change ev_pre; + ev_pre.type = ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED; + ev_pre.win = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE, &ev_pre); + + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + event.fully_obscured = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + Ecore_Wl2_Event_Window_Hide ev_hide; + ev_hide.win = 1; + ev_hide.parent_win = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_HIDE, &ev_hide); + + return ret; + })); + EXPECT_CALL(core, OnResume()) + .Times(1); + EXPECT_CALL(core, OnPause()) + .Times(1); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_RaiseWin) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(3000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + Ecore_Wl2_Event_Window_Show ev_show; + ev_show.win = 1; + ev_show.parent_win = 0; + ev_show.data[0] = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_SHOW, &ev_show); + + Ecore_Wl2_Event_Window_Pre_Visibility_Change ev_pre; + ev_pre.type = ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED; + ev_pre.win = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE, &ev_pre); + + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + event.fully_obscured = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + GetMock().SetEvent(AUL_START, bundle_create()); + return ret; + })) + .WillRepeatedly(Invoke([&](tizen_base::Bundle b) -> int { + return core.AppCoreEflBase::OnControl(std::move(b)); + })); + EXPECT_CALL(GetMock(), ecore_wl2_window_activate(_)) + .WillOnce(Invoke([&](Ecore_Wl2_Window* win) { + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + })); + + EXPECT_CALL(core, OnResume()) + .Times(2); + EXPECT_CALL(core, OnPause()) + .Times(2); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_PauseWin) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(3000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + Ecore_Wl2_Event_Window_Show ev_show; + ev_show.win = 1; + ev_show.parent_win = 0; + ev_show.data[0] = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_SHOW, &ev_show); + + Ecore_Wl2_Event_Window_Pre_Visibility_Change ev_pre; + ev_pre.type = ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED; + ev_pre.win = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE, &ev_pre); + + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + GetMock().SetEvent(AUL_PAUSE, bundle_create()); + return ret; + })) + .WillRepeatedly(Invoke([&](tizen_base::Bundle b) -> int { + return core.AppCoreEflBase::OnControl(std::move(b)); + })); + EXPECT_CALL(GetMock(), ecore_wl2_window_iconified_set(_, _)) + .WillOnce(Invoke([&](Ecore_Wl2_Window* win, Eina_Bool) { + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + })); + + EXPECT_CALL(core, OnResume()) + .Times(1); + EXPECT_CALL(core, OnPause()) + .Times(1); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_AUL_RESUME) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(3000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + Ecore_Wl2_Event_Window_Show ev_show; + ev_show.win = 1; + ev_show.parent_win = 0; + ev_show.data[0] = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_SHOW, &ev_show); + + GetMock().SetEvent(AUL_RESUME, bundle_create()); + return ret; + })) + .WillRepeatedly(Invoke([&](tizen_base::Bundle b) -> int { + return core.AppCoreEflBase::OnControl(std::move(b)); + })); + EXPECT_CALL(GetMock(), ecore_wl2_window_activate(_)) + .WillOnce(Invoke([&](Ecore_Wl2_Window* win) { + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + })); + + EXPECT_CALL(core, OnResume()) + .Times(1); + EXPECT_CALL(core, OnPause()) + .Times(1); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_AUL_TERMINATE_INST) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + + GetMock().SetEvent(AUL_TERMINATE_INST, bundle_create()); + return ret; + })); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_AUL_TERMINATE) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + + GetMock().SetEvent(AUL_TERMINATE, bundle_create()); + return ret; + })); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_IsResumed) { + testing::NiceMock core; + bool resumed = false; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + core.Resume(); + core.Pause(); + core.Resume(); + resumed = core.IsResumed(); + + GetMock().SetEvent(AUL_TERMINATE, bundle_create()); + return ret; + })); + EXPECT_CALL(core, OnResume()) + .Times(2); + EXPECT_CALL(core, OnPause()) + .Times(2); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_TRUE(resumed); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_VcElm) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(GetMock(), vconf_get_bool(_, _)) + .WillRepeatedly(Invoke([&](const char *in_key, + int* val) -> int { + if (strcmp(in_key, VCONFKEY_VC_VOICE_TOUCH_AUTOMODE) == 0) { + *val = 1; + return 0; + } + + *val = 0; + return 0; + })); + EXPECT_CALL(GetMock(), dlsym(_, _)) + .WillRepeatedly(Invoke([&](void* handle, const char* name) -> void* { + if (strcmp(name, "vc_elm_initialize") == 0) { + return (void*)__vc_elm_initialize; + } else if (strcmp(name, "vc_elm_deinitialize") == 0) { + return (void*)__vc_elm_deinitialize; + } else if (strcmp(name, "vc_elm_set_auto_register_mode") == 0) { + return (void*)__vc_elm_set_auto_register_mode; + } + + return nullptr; + })); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_VcElm2) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + GetMock().ChangeBool(VCONFKEY_VC_VOICE_TOUCH_AUTOMODE, false); + GetMock().ChangeBool(VCONFKEY_VC_VOICE_TOUCH_AUTOMODE, true); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(GetMock(), vconf_get_bool(_, _)) + .WillRepeatedly(Invoke([&](const char *in_key, + int* val) -> int { + if (strcmp(in_key, VCONFKEY_VC_VOICE_TOUCH_AUTOMODE) == 0) { + *val = 1; + return 0; + } + + *val = 0; + return 0; + })); + EXPECT_CALL(GetMock(), dlsym(_, _)) + .WillRepeatedly(Invoke([&](void* handle, const char* name) -> void* { + if (strcmp(name, "vc_elm_initialize") == 0) { + return (void*)__vc_elm_initialize; + } else if (strcmp(name, "vc_elm_deinitialize") == 0) { + return (void*)__vc_elm_deinitialize; + } else if (strcmp(name, "vc_elm_set_auto_register_mode") == 0) { + return (void*)__vc_elm_set_auto_register_mode; + } + + return nullptr; + })); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_Aux) { + testing::NiceMock core; + AppCoreBase::DisplayState state = AppCoreBase::DISPLAY_STATE_UNKNOWN; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + + Ecore_Wl2_Event_Aux_Message event; + event.key = "dpms_wm"; + event.val = "off"; + GetMock().SendEvent( + ECORE_WL2_EVENT_AUX_MESSAGE, &event); + event.val = "on"; + GetMock().SendEvent( + ECORE_WL2_EVENT_AUX_MESSAGE, &event); + state = AppCoreBase::GetDisplayState(); + return ret; + })); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(AppCoreBase::DISPLAY_STATE_ON, state); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_GetBgState) { + testing::NiceMock core; + + core.SetBgState(true); + EXPECT_TRUE(core.GetBgState()); + core.SetBgState(false); + EXPECT_FALSE(core.GetBgState()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_IsLegacyLifecycle) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .Times(1); + EXPECT_CALL(core, OnResume()) + .Times(1); + EXPECT_CALL(core, OnPause()) + .Times(1); + + ::DummyArgs da; + setenv("TIZEN_API_VERSION", "2.3", 1); + core.SetBgState(true); + core.Run(da.GetArgc(), da.GetArgv()); + unsetenv("TIZEN_API_VERSION"); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_ApplyBgState) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + GetMock().SetEvent(AUL_START, bundle_create()); + return ret; + })) + .WillRepeatedly(Invoke([&](tizen_base::Bundle b) -> int { + return core.AppCoreEflBase::OnControl(std::move(b)); + })); + + ::DummyArgs da(AUL_SVC_K_BG_LAUNCH, "enable"); + core.SetBgState(false); + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_OnLower) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + return core.AppCoreEflBase::OnCreate(); + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + Ecore_Wl2_Event_Window_Show ev_show; + ev_show.win = 1; + ev_show.parent_win = 0; + ev_show.data[0] = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_SHOW, &ev_show); + + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + Ecore_Wl2_Event_Window_Lower ev_lower; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_LOWER, &ev_lower); + + return ret; + })); + EXPECT_CALL(GetMock(), aul_app_group_lower(_)) + .WillOnce(Invoke([&](int* exit) { + *exit = 1; + })); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_Plugin) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(GetMock(), dlsym(_, _)) + .WillRepeatedly(Invoke([&](void* handle, const char* name) -> void* { + if (strcmp(name, "APPCORE_UI_PLUGIN_INIT") == 0) { + return (void*)__ui_plugin_init_dummy; + } else if (strcmp(name, "APPCORE_UI_PLUGIN_FINI") == 0) { + return (void*)__ui_plugin_fini_dummy; + } + + return nullptr; + })); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreEflBaseTest, AppCoreEflBase_Plugin2) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreEflBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreEflBase::OnControl(std::move(b)); + Ecore_Wl2_Event_Window_Show ev_show; + ev_show.win = 1; + ev_show.parent_win = 0; + ev_show.data[0] = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_SHOW, &ev_show); + + Ecore_Wl2_Event_Window_Pre_Visibility_Change ev_pre; + ev_pre.type = ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED; + ev_pre.win = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE, &ev_pre); + + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + event.fully_obscured = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + Ecore_Wl2_Event_Window_Hide ev_hide; + ev_hide.win = 1; + ev_hide.parent_win = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_HIDE, &ev_hide); + + return ret; + })); + EXPECT_CALL(GetMock(), dlsym(_, _)) + .WillRepeatedly(Invoke([&](void* handle, const char* name) -> void* { + if (strcmp(name, "APPCORE_UI_PLUGIN_INIT") == 0) { + return (void*)__ui_plugin_init_dummy; + } else if (strcmp(name, "APPCORE_UI_PLUGIN_FINI") == 0) { + return (void*)__ui_plugin_fini_dummy; + } + + return nullptr; + })); + EXPECT_CALL(core, OnResume()) + .Times(1); + EXPECT_CALL(core, OnPause()) + .Times(1); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + + +} // namespace tizen_cpp diff --git a/unittests/app_core_multi_window_base_test.cc b/unittests/app_core_multi_window_base_test.cc new file mode 100644 index 0000000..b00f1a0 --- /dev/null +++ b/unittests/app_core_multi_window_base_test.cc @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include + +#include "mock/test_fixture.h" +#include "mock/aul_mock.h" +#include "mock/sensor_mock.h" +#include "mock/vconf_mock.h" +#include "mock/dbus_mock.h" +#include "mock/elm_mock.h" +#include "mock/wayland_mock.h" +#include "mock/ecore_wl2_mock.h" +#include "mock/ecore_mock.h" +#include "mock/dl_mock.h" +#include "mock/app_core_multi_window_base_mock.h" +#include "mock/app_core_multi_window_base_context_mock.h" + +#include + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::Invoke; + +namespace { +class Mocks : public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock, + virtual public ::testing::NiceMock {}; + +class DummyArgs { + public: + DummyArgs() { + tizen_base::Bundle b; + b.Add("dummy", "dummy"); + argc_ = bundle_export_to_argv(b.GetHandle(), &argv_); + } + + DummyArgs(std::string key, std::string val) { + tizen_base::Bundle b; + b.Add(std::move(key), std::move(val)); + argc_ = bundle_export_to_argv(b.GetHandle(), &argv_); + } + + ~DummyArgs() { + bundle_free_exported_argv(argc_, &argv_); + } + + int GetArgc() const { + return argc_; + } + + char** GetArgv() const { + return argv_; + } + + private: + int argc_ = 0; + char** argv_ = nullptr; +}; + +} // namespace + +namespace tizen_cpp { + +class AppCoreMultiWindowBaseTest : public TestFixture { + public: + AppCoreMultiWindowBaseTest() : TestFixture(std::make_unique<::Mocks>()) {} + + virtual void SetUp() {} + + virtual void TearDown() {} +}; + +TEST_F(AppCoreMultiWindowBaseTest, AppCoreMultiWindowBase_Run) { + testing::NiceMock core; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&core]() -> int { + core.AppCoreMultiWindowBase::OnCreate(); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreMultiWindowBaseTest, AppCoreMultiWindowBase_AddContextFactory) { + testing::NiceMock core; + std::shared_ptr ret_factory; + std::string context_id = "test_context_id"; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + core.AppCoreMultiWindowBase::OnCreate(); + auto f = std::make_shared(context_id, &core); + core.AddContextFactory(f, context_id); + ret_factory = core.GetContextFactory(context_id); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_NE(ret_factory.get(), nullptr); +} + +TEST_F(AppCoreMultiWindowBaseTest, AppCoreMultiWindowBase_RunContext) { + testing::NiceMock core; + std::string context_id = "test_context_id"; + auto f = std::make_shared(context_id, &core); + auto* cxt = f->GetPreInitObj(); + std::string ret_init_id; + std::string ret_context_id; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + core.AppCoreMultiWindowBase::OnCreate(); + core.AddContextFactory(f, context_id); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreMultiWindowBase::OnControl(std::move(b)); + auto c = core.RunContext(context_id, "pre_init"); + ret_init_id = c->GetInstId(); + ret_context_id = c->GetContextId(); + return ret; + })); + EXPECT_CALL(*cxt, OnCreate()) + .Times(1); + EXPECT_CALL(*cxt, OnTerminate()) + .Times(1); + EXPECT_CALL(*cxt, OnPause()) + .Times(0); + EXPECT_CALL(*cxt, OnResume()) + .Times(0); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(ret_init_id, "pre_init"); + EXPECT_EQ(ret_context_id, context_id); +} + +TEST_F(AppCoreMultiWindowBaseTest, AppCoreMultiWindowBase_ExitContext) { + testing::NiceMock core; + std::string context_id = "test_context_id"; + auto f = std::make_shared(context_id, &core); + auto* cxt = f->GetPreInitObj(); + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + core.AppCoreMultiWindowBase::OnCreate(); + core.AddContextFactory(f, context_id); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreMultiWindowBase::OnControl(std::move(b)); + auto c = core.RunContext(context_id, "pre_init"); + core.ExitContext(c); + return ret; + })); + EXPECT_CALL(*cxt, OnCreate()) + .Times(1); + EXPECT_CALL(*cxt, OnTerminate()) + .Times(1); + EXPECT_CALL(*cxt, OnPause()) + .Times(0); + EXPECT_CALL(*cxt, OnResume()) + .Times(0); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreMultiWindowBaseTest, AppCoreMultiWindowBase_Resume) { + testing::NiceMock core; + std::string context_id = "test_context_id"; + auto f = std::make_shared(context_id, &core); + auto* cxt = f->GetPreInitObj(); + bool is_resumed = false; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + core.AppCoreMultiWindowBase::OnCreate(); + core.AddContextFactory(f, context_id); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreMultiWindowBase::OnControl(std::move(b)); + auto c = core.RunContext(context_id, "pre_init"); + c->Resume(); + is_resumed = c->IsResumed(); + c->Pause(); + return ret; + })); + EXPECT_CALL(*cxt, OnCreate()) + .Times(1); + EXPECT_CALL(*cxt, OnTerminate()) + .Times(1); + EXPECT_CALL(*cxt, OnPause()) + .Times(1); + EXPECT_CALL(*cxt, OnResume()) + .Times(1); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_TRUE(is_resumed); +} + +TEST_F(AppCoreMultiWindowBaseTest, AppCoreMultiWindowBase_OnVisibility) { + testing::NiceMock core; + std::string context_id = "test_context_id"; + auto f = std::make_shared(context_id, &core); + auto* cxt = f->GetPreInitObj(); + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + core.AppCoreMultiWindowBase::OnCreate(); + core.AddContextFactory(f, context_id); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreMultiWindowBase::OnControl(std::move(b)); + core.RunContext(context_id, "pre_init"); + return ret; + })); + EXPECT_CALL(GetMock(), ecore_wl2_window_id_get(_)) + .WillRepeatedly(Invoke([&](Ecore_Wl2_Window* win) -> int { + return 1; + })); + EXPECT_CALL(*cxt, OnCreate()) + .WillOnce(Invoke([&]() { + int dummy; + Ecore_Wl2_Window* win = reinterpret_cast(&dummy); + cxt->WindowBind(win); + + Ecore_Wl2_Event_Window_Show ev_show; + ev_show.win = 1; + ev_show.parent_win = 0; + ev_show.data[0] = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_SHOW, &ev_show); + + Ecore_Wl2_Event_Window_Pre_Visibility_Change ev_pre; + ev_pre.type = ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED; + ev_pre.win = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE, &ev_pre); + + Ecore_Wl2_Event_Window_Visibility_Change event; + event.win = 1; + event.fully_obscured = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + event.fully_obscured = 1; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, &event); + + Ecore_Wl2_Event_Window_Hide ev_hide; + ev_hide.win = 1; + ev_hide.parent_win = 0; + GetMock().SendEvent( + ECORE_WL2_EVENT_WINDOW_HIDE, &ev_hide); + })); + EXPECT_CALL(*cxt, OnTerminate()) + .WillOnce(Invoke([&]() { + cxt->WindowUnbind(); + })); + EXPECT_CALL(*cxt, OnPause()) + .Times(1); + EXPECT_CALL(*cxt, OnResume()) + .Times(1); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); +} + +TEST_F(AppCoreMultiWindowBaseTest, AppCoreMultiWindowBase_OnAuxMessage) { + testing::NiceMock core; + std::string context_id = "test_context_id"; + auto f = std::make_shared(context_id, &core); + auto* cxt = f->GetPreInitObj(); + AppCoreBase::DisplayState state = AppCoreBase::DISPLAY_STATE_UNKNOWN; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + core.AppCoreMultiWindowBase::OnCreate(); + core.AddContextFactory(f, context_id); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreMultiWindowBase::OnControl(std::move(b)); + core.RunContext(context_id, "pre_init"); + return ret; + })); + EXPECT_CALL(GetMock(), ecore_wl2_window_id_get(_)) + .WillRepeatedly(Invoke([&](Ecore_Wl2_Window* win) -> int { + return 1; + })); + EXPECT_CALL(*cxt, OnCreate()) + .WillOnce(Invoke([&]() { + Ecore_Wl2_Event_Aux_Message event; + event.key = "dpms_wm"; + event.val = "off"; + GetMock().SendEvent( + ECORE_WL2_EVENT_AUX_MESSAGE, &event); + event.val = "on"; + GetMock().SendEvent( + ECORE_WL2_EVENT_AUX_MESSAGE, &event); + state = AppCoreBase::GetDisplayState(); + })); + EXPECT_CALL(*cxt, OnTerminate()) + .Times(1); + EXPECT_CALL(*cxt, OnPause()) + .Times(0); + EXPECT_CALL(*cxt, OnResume()) + .Times(0); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_EQ(AppCoreBase::DISPLAY_STATE_ON, state); +} + +TEST_F(AppCoreMultiWindowBaseTest, AppCoreMultiWindowBase_FindById) { + testing::NiceMock core; + std::string context_id = "test_context_id"; + auto f = std::make_shared(context_id, &core); + auto* cxt = f->GetPreInitObj(); + std::shared_ptr found; + + EXPECT_CALL(core, OnCreate()) + .WillOnce(Invoke([&]() -> int { + core.AppCoreMultiWindowBase::OnCreate(); + core.AddContextFactory(f, context_id); + g_timeout_add(1000, [](gpointer data) -> gboolean { + auto* obj = static_cast*>(data); + obj->Exit(); + return G_SOURCE_REMOVE; + }, &core); + return 0; + })); + EXPECT_CALL(core, OnTerminate()) + .Times(1); + EXPECT_CALL(core, OnControl(_)) + .WillOnce(Invoke([&](tizen_base::Bundle b) -> int { + int ret = core.AppCoreMultiWindowBase::OnControl(std::move(b)); + core.RunContext(context_id, "pre_init"); + found = core.FindById("pre_init"); + return ret; + })); + EXPECT_CALL(*cxt, OnCreate()) + .Times(1); + EXPECT_CALL(*cxt, OnTerminate()) + .Times(1); + EXPECT_CALL(*cxt, OnPause()) + .Times(0); + EXPECT_CALL(*cxt, OnResume()) + .Times(0); + + ::DummyArgs da; + core.Run(da.GetArgc(), da.GetArgv()); + EXPECT_NE(found.get(), nullptr); +} + +} // namespace tizen_cpp diff --git a/unittests/main.cc b/unittests/main.cc new file mode 100644 index 0000000..db16de3 --- /dev/null +++ b/unittests/main.cc @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 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 + +//#define LOG_INTERNAL + +#ifdef LOG_INTERNAL +#include + +extern "C" int __dlog_print(log_id_t log_id, int prio, const char *tag, const char *fmt, ...) { + printf("%s:", tag); + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + + return 0; +} +#endif + +int main(int argc, char* argv[]) { + int ret = 0; + try { + ::testing::InitGoogleTest(&argc, argv); + } catch(...) { + std::cout << "Exception occured" << std::endl; + return 1; + } + + try { + return RUN_ALL_TESTS(); + } catch(const ::testing::internal::GoogleTestFailureException& e) { + std::cout << "GoogleTestFailureException occured:" << e.what() << std::endl; + ret = 1; + } + + return ret; +} diff --git a/unittests/mock/app_core_base_mock.h b/unittests/mock/app_core_base_mock.h new file mode 100644 index 0000000..a80515a --- /dev/null +++ b/unittests/mock/app_core_base_mock.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_APP_CORE_BASE_MOCK_H_ +#define UNIT_TESTS_MOCK_APP_CORE_BASE_MOCK_H_ + +#include +#include +#include + +#include "app_core_base.hh" + +class AppCoreBaseMock : public tizen_cpp::AppCoreBase { + public: + AppCoreBaseMock() { + using ::testing::_; + using ::testing::Invoke; + + ON_CALL(*this, OnLoopInit(_, _)) + .WillByDefault(Invoke([&](int argc, char** argv) { + loop_ = g_main_loop_new(NULL, FALSE); + })); + ON_CALL(*this, OnLoopFinish()) + .WillByDefault(Invoke([&]() { + g_main_loop_unref(loop_); + })); + ON_CALL(*this, OnLoopRun()) + .WillByDefault(Invoke([&]() { + g_main_loop_run(loop_); + })); + ON_CALL(*this, OnLoopExit()) + .WillByDefault(Invoke([&]() { + g_main_loop_quit(loop_); + })); + ON_CALL(*this, OnTrimMemory()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreBase::OnTrimMemory(); + })); + ON_CALL(*this, OnCreate()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreBase::OnCreate(); + })); + ON_CALL(*this, OnTerminate()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreBase::OnTerminate(); + })); + ON_CALL(*this, OnReceive(_, _)) + .WillByDefault(Invoke([&](aul_type type, tizen_base::Bundle b) -> int { + return AppCoreBase::OnReceive(type, std::move(b)); + })); + ON_CALL(*this, OnControl(_)) + .WillByDefault(Invoke([&](tizen_base::Bundle b) -> int { + return AppCoreBase::OnControl(std::move(b)); + })); + } + + virtual ~AppCoreBaseMock() = default; + + MOCK_METHOD0(OnCreate, int ()); + MOCK_METHOD2(OnReceive, int (aul_type, tizen_base::Bundle)); + MOCK_METHOD1(OnControl, int (tizen_base::Bundle)); + MOCK_METHOD0(OnTerminate, int ()); + MOCK_METHOD2(OnLoopInit, void (int, char**)); + MOCK_METHOD0(OnLoopFinish, void ()); + MOCK_METHOD0(OnLoopRun, void ()); + MOCK_METHOD0(OnLoopExit, void ()); + MOCK_METHOD0(OnTrimMemory, int ()); + + private: + GMainLoop* loop_ = nullptr; +}; + +#endif // UNIT_TESTS_MOCK_APP_CORE_BASE_MOCK_H_ + diff --git a/unittests/mock/app_core_efl_base_mock.h b/unittests/mock/app_core_efl_base_mock.h new file mode 100644 index 0000000..3148d8c --- /dev/null +++ b/unittests/mock/app_core_efl_base_mock.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_APP_CORE_EFL_BASE_MOCK_H_ +#define UNIT_TESTS_MOCK_APP_CORE_EFL_BASE_MOCK_H_ + +#include +#include +#include + +#include "app_core_efl_base.hh" + +class AppCoreEflBaseMock : public tizen_cpp::AppCoreEflBase { + public: + AppCoreEflBaseMock() : AppCoreEflBase( + HINT_WINDOW_GROUP_CONTROL | HINT_WINDOW_STACK_CONTROL | + HINT_BG_LAUNCH_CONTROL | HINT_HW_ACC_CONTROL | + HINT_WINDOW_AUTO_CONTROL | HINT_LEGACY_CONTROL | + HINT_WINDOW_ID_CONTROL) { + using ::testing::_; + using ::testing::Invoke; + + ON_CALL(*this, OnCreate()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreEflBase::OnCreate(); + })); + ON_CALL(*this, OnTerminate()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreEflBase::OnTerminate(); + })); + ON_CALL(*this, OnReceive(_, _)) + .WillByDefault(Invoke([&](aul_type type, tizen_base::Bundle b) -> int { + return AppCoreEflBase::OnReceive(type, std::move(b)); + })); + ON_CALL(*this, OnControl(_)) + .WillByDefault(Invoke([&](tizen_base::Bundle b) -> int { + return AppCoreEflBase::OnControl(std::move(b)); + })); + ON_CALL(*this, OnPause()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreEflBase::OnPause(); + })); + ON_CALL(*this, OnResume()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreEflBase::OnResume(); + })); + ON_CALL(*this, OnTrimMemory()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreEflBase::OnTrimMemory(); + })); + } + + virtual ~AppCoreEflBaseMock() = default; + + MOCK_METHOD0(OnCreate, int ()); + MOCK_METHOD2(OnReceive, int (aul_type, tizen_base::Bundle)); + MOCK_METHOD1(OnControl, int (tizen_base::Bundle)); + MOCK_METHOD0(OnPause, int ()); + MOCK_METHOD0(OnResume, int ()); + MOCK_METHOD0(OnTerminate, int ()); + MOCK_METHOD0(OnTrimMemory, int ()); +}; + +#endif // UNIT_TESTS_MOCK_APP_CORE_EFL_BASE_MOCK_H_ + diff --git a/unittests/mock/app_core_multi_window_base_context_mock.h b/unittests/mock/app_core_multi_window_base_context_mock.h new file mode 100644 index 0000000..ef97ddc --- /dev/null +++ b/unittests/mock/app_core_multi_window_base_context_mock.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_APP_CORE_MULTI_WINDOW_BASE_CONTEXT_MOCK_H_ +#define UNIT_TESTS_MOCK_APP_CORE_MULTI_WINDOW_BASE_CONTEXT_MOCK_H_ + +#include +#include + +#include "app_core_multi_window_base.hh" + +class AppCoreMultiWindowBaseContextMock : public tizen_cpp::AppCoreMultiWindowBase::Context { + public: + AppCoreMultiWindowBaseContextMock(std::string context_id, std::string inst_id, + tizen_cpp::AppCoreMultiWindowBase* app) : Context(context_id, inst_id, app) {} + + class Factory : public IFactory { + public: + Factory(std::string context_id, tizen_cpp::AppCoreMultiWindowBase* app) : context_id_(std::move(context_id)) { + pre_init_.reset(new testing::NiceMock(context_id_, "pre_init", app)); + } + + std::unique_ptr Create(std::string inst_id, tizen_cpp::AppCoreMultiWindowBase* app) override { + if (inst_id == "pre_init") + return std::move(pre_init_); + + return std::unique_ptr( + new testing::NiceMock(context_id_, std::move(inst_id), app)); + } + + testing::NiceMock* GetPreInitObj() { + return (testing::NiceMock*)(pre_init_.get()); + } + + private: + std::string context_id_; + std::unique_ptr pre_init_; + }; + + MOCK_METHOD0(OnCreate, void ()); + MOCK_METHOD0(OnTerminate, void ()); + MOCK_METHOD0(OnPause, void ()); + MOCK_METHOD0(OnResume, void ()); +}; + +#endif // UNIT_TESTS_MOCK_APP_CORE_MULTI_WINDOW_BASE_CONTEXT_MOCK_H_ + diff --git a/unittests/mock/app_core_multi_window_base_mock.h b/unittests/mock/app_core_multi_window_base_mock.h new file mode 100644 index 0000000..ddae120 --- /dev/null +++ b/unittests/mock/app_core_multi_window_base_mock.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_APP_CORE_MULTI_WINDOW_BASE_MOCK_H_ +#define UNIT_TESTS_MOCK_APP_CORE_MULTI_WINDOW_BASE_MOCK_H_ + +#include +#include + +#include "app_core_multi_window_base.hh" + +class AppCoreMultiWindowBaseMock : public tizen_cpp::AppCoreMultiWindowBase { + public: + AppCoreMultiWindowBaseMock() { + using ::testing::_; + using ::testing::Invoke; + + ON_CALL(*this, OnLoopInit(_, _)) + .WillByDefault(Invoke([&](int argc, char** argv) { + loop_ = g_main_loop_new(nullptr, FALSE); + })); + ON_CALL(*this, OnLoopFinish()) + .WillByDefault(Invoke([&]() { + g_main_loop_unref(loop_); + })); + ON_CALL(*this, OnLoopRun()) + .WillByDefault(Invoke([&]() { + g_main_loop_run(loop_); + })); + ON_CALL(*this, OnLoopExit()) + .WillByDefault(Invoke([&]() { + g_main_loop_quit(loop_); + })); + ON_CALL(*this, OnCreate()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreMultiWindowBase::OnCreate(); + })); + ON_CALL(*this, OnTerminate()) + .WillByDefault(Invoke([&]() -> int { + return AppCoreMultiWindowBase::OnTerminate(); + })); + ON_CALL(*this, OnControl(_)) + .WillByDefault(Invoke([&](tizen_base::Bundle b) -> int { + return AppCoreMultiWindowBase::OnControl(std::move(b)); + })); + } + + MOCK_METHOD0(OnCreate, int ()); + MOCK_METHOD0(OnTerminate, int ()); + MOCK_METHOD1(OnControl, int (tizen_base::Bundle)); + MOCK_METHOD2(OnLoopInit, void (int, char**)); + MOCK_METHOD0(OnLoopFinish, void ()); + MOCK_METHOD0(OnLoopRun, void ()); + MOCK_METHOD0(OnLoopExit, void ()); + + private: + GMainLoop* loop_ = nullptr; +}; + +#endif // UNIT_TESTS_MOCK_APP_CORE_MULTI_WINDOW_BASE_MOCK_H_ + diff --git a/unittests/mock/aul_mock.cc b/unittests/mock/aul_mock.cc new file mode 100644 index 0000000..332259f --- /dev/null +++ b/unittests/mock/aul_mock.cc @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 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 +#include + +#include "mock/aul_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + + +extern "C" int aul_launch_init(aul_handler_fn callback, void *user_data) { + return MOCK_HOOK_P2(AulMock, aul_launch_init, callback, user_data); +} + +extern "C" void aul_finalize(void) { + MOCK_HOOK_P0(AulMock, aul_finalize); +} + +extern "C" int aul_launch_argv_handler(int argc, char **argv) { + return MOCK_HOOK_P2(AulMock, aul_launch_argv_handler, argc, argv); +} + +extern "C" int aul_app_get_appid_bypid(int pid, char *appid, int len) { + return MOCK_HOOK_P3(AulMock, aul_app_get_appid_bypid, pid, appid, len); +} + +extern "C" const char* aul_get_app_resource_path(void) { + return MOCK_HOOK_P0(AulMock, aul_get_app_resource_path); +} + +extern "C" int aul_watchdog_enable(void) { + return MOCK_HOOK_P0(AulMock, aul_watchdog_enable); +} + +extern "C" int aul_watchdog_disable(void) { + return MOCK_HOOK_P0(AulMock, aul_watchdog_disable); +} + +extern "C" int aul_watchdog_kick(void) { + return MOCK_HOOK_P0(AulMock, aul_watchdog_kick); +} + +extern "C" void aul_app_group_lower(int* exit) { + MOCK_HOOK_P1(AulMock, aul_app_group_lower, exit); +} \ No newline at end of file diff --git a/unittests/mock/aul_mock.h b/unittests/mock/aul_mock.h new file mode 100644 index 0000000..7348693 --- /dev/null +++ b/unittests/mock/aul_mock.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_AUL_MOCK_H_ +#define UNIT_TESTS_MOCK_AUL_MOCK_H_ + +#include +#include +#include +#include + +#include "mock/module_mock.h" + +class AulMock : public virtual ModuleMock { + public: + AulMock() { + using ::testing::_; + using ::testing::Return; + using ::testing::Invoke; + + ON_CALL(*this, aul_launch_init(_, _)) + .WillByDefault(Invoke([&](aul_handler_fn callback, void *user_data) -> int { + callback_ = callback; + user_data_ = user_data; + return 0; + })); + ON_CALL(*this, aul_finalize()) + .WillByDefault(Invoke([&]() { + callback_ = nullptr; + user_data_ = nullptr; + if (timer_) { + g_source_remove(timer_); + timer_ = 0; + } + if (args_) { + bundle_free(args_); + args_ = nullptr; + } + })); + ON_CALL(*this, aul_launch_argv_handler(_, _)) + .WillByDefault(Invoke([&](int argc, char **argv) -> int { + args_ = bundle_import_from_argv(argc, argv); + timer_ = g_idle_add([](gpointer data)-> gboolean { + AulMock* obj = static_cast(data); + if (obj->callback_) + obj->callback_(AUL_START, obj->args_, obj->user_data_); + obj->timer_ = 0; + return G_SOURCE_REMOVE; + }, this); + if (timer_ <= 0) + return AUL_R_ERROR; + + return AUL_R_OK; + })); + ON_CALL(*this, aul_app_get_appid_bypid(_, _, _)) + .WillByDefault(Invoke([&](int pid, char *appid, int len) -> int { + snprintf(appid, len, "test_appid"); + return 0; + })); + ON_CALL(*this, aul_get_app_resource_path()) + .WillByDefault(Invoke([&]() -> const char* { + static const char res_path[] = "/tmp/"; + return res_path; + })); + ON_CALL(*this, aul_watchdog_enable()) + .WillByDefault(Return(0)); + ON_CALL(*this, aul_watchdog_disable()) + .WillByDefault(Return(0)); + ON_CALL(*this, aul_watchdog_kick()) + .WillByDefault(Return(0)); + } + + virtual ~AulMock() {} + + MOCK_METHOD2(aul_launch_init, int (aul_handler_fn , void*)); + MOCK_METHOD0(aul_finalize, void ()); + MOCK_METHOD2(aul_launch_argv_handler, int (int, char **)); + MOCK_METHOD3(aul_app_get_appid_bypid, int (int, char*, int)); + MOCK_METHOD0(aul_get_app_resource_path, const char* ()); + MOCK_METHOD0(aul_watchdog_enable, int ()); + MOCK_METHOD0(aul_watchdog_disable, int ()); + MOCK_METHOD0(aul_watchdog_kick, int ()); + MOCK_METHOD1(aul_app_group_lower, void (int*)); + + void SetEvent(aul_type type, bundle* b) { + if (args_) + bundle_free(args_); + args_ = b; + type_ = type; + g_idle_add([](gpointer data)-> gboolean { + AulMock* obj = static_cast(data); + tizen_base::Bundle args(obj->args_); + bundle_free(obj->args_); + obj->args_ = nullptr; + if (obj->callback_) { + obj->callback_(obj->type_, args.GetHandle(), obj->user_data_); + } + return G_SOURCE_REMOVE; + }, this); + } + + private: + aul_handler_fn callback_ = nullptr; + void* user_data_ = nullptr; + guint timer_ = 0; + bundle* args_ = nullptr; + aul_type type_ = static_cast(-1); +}; + +#endif // UNIT_TESTS_MOCK_AUL_MOCK_H_ + diff --git a/unittests/mock/dbus_mock.cc b/unittests/mock/dbus_mock.cc new file mode 100644 index 0000000..56f23d0 --- /dev/null +++ b/unittests/mock/dbus_mock.cc @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 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 + +#include "mock/dbus_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + +extern "C" GDBusConnection* g_bus_get_sync(GBusType bus_type, + GCancellable* cancellable, GError** error) { + return MOCK_HOOK_P3(DbusMock, g_bus_get_sync, bus_type, cancellable, error); +} + +extern "C" guint g_dbus_connection_signal_subscribe(GDBusConnection* arg0, + const gchar* arg1, const gchar* arg2, const gchar* arg3, const gchar* arg4, + const gchar* arg5, GDBusSignalFlags arg6, GDBusSignalCallback arg7, + gpointer arg8, GDestroyNotify arg9) { + return MOCK_HOOK_P10(DbusMock, g_dbus_connection_signal_subscribe, + arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); +} diff --git a/unittests/mock/dbus_mock.h b/unittests/mock/dbus_mock.h new file mode 100644 index 0000000..c4bf82b --- /dev/null +++ b/unittests/mock/dbus_mock.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_DBUS_MOCK_H_ +#define UNIT_TESTS_MOCK_DBUS_MOCK_H_ + +#include +#include +#include + +#include "mock/module_mock.h" + +class DbusMock : public virtual ModuleMock { + public: + DbusMock() { + using ::testing::_; + using ::testing::Return; + using ::testing::Invoke; + + static int dummy; + conn_ = (GDBusConnection*)&dummy; + + ON_CALL(*this, g_bus_get_sync(_, _, _)) + .WillByDefault(Return(conn_)); + } + + MOCK_METHOD3(g_bus_get_sync, GDBusConnection* (GBusType, GCancellable*, GError**)); + MOCK_METHOD10(g_dbus_connection_signal_subscribe, + guint(GDBusConnection*, const gchar*, const gchar*, const gchar*, + const gchar*, const gchar*, GDBusSignalFlags, GDBusSignalCallback, + gpointer, GDestroyNotify)); + + private: + GDBusConnection* conn_ = nullptr; +}; + +#endif // UNIT_TESTS_MOCK_DBUS_MOCK_H_ + diff --git a/unittests/mock/dl_mock.cc b/unittests/mock/dl_mock.cc new file mode 100644 index 0000000..c322708 --- /dev/null +++ b/unittests/mock/dl_mock.cc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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 + +#include "mock/dl_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + +int DlMock::dummy_; + +extern "C" void* dlopen(const char* name, int mode) { + return MOCK_HOOK_P2(DlMock, dlopen, name, mode); +} + +extern "C" int dlclose(void* handle) { + return MOCK_HOOK_P1(DlMock, dlclose, handle); +} + +extern "C" void* dlsym(void* handle, const char* name) { + return MOCK_HOOK_P2(DlMock, dlsym, handle, name); +} + +extern "C" int access(const char* pathname, int mode) { + return MOCK_HOOK_P2(DlMock, access, pathname, mode); +} diff --git a/unittests/mock/dl_mock.h b/unittests/mock/dl_mock.h new file mode 100644 index 0000000..3a148b7 --- /dev/null +++ b/unittests/mock/dl_mock.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_DL_MOCK_H_ +#define UNIT_TESTS_MOCK_DL_MOCK_H_ + +#include +#include + +#include "mock/module_mock.h" + +class DlMock : public virtual ModuleMock { + public: + DlMock() { + using ::testing::_; + using ::testing::Return; + using ::testing::Invoke; + + ON_CALL(*this, dlopen(_, _)) + .WillByDefault(Return((void*)&dummy_)); + ON_CALL(*this, dlclose(_)) + .WillByDefault(Return(0)); + ON_CALL(*this, dlsym(_, _)) + .WillByDefault(Return(nullptr)); + ON_CALL(*this, access(_, _)) + .WillByDefault(Return(0)); + } + + MOCK_METHOD2(dlopen, void* (const char*, int)); + MOCK_METHOD1(dlclose, int (void*)); + MOCK_METHOD2(dlsym, void* (void*, const char*)); + MOCK_METHOD2(access, int (const char*, int)); + + private: + static int dummy_; +}; + +#endif // UNIT_TESTS_MOCK_DL_MOCK_H_ + diff --git a/unittests/mock/ecore_mock.cc b/unittests/mock/ecore_mock.cc new file mode 100644 index 0000000..7812dce --- /dev/null +++ b/unittests/mock/ecore_mock.cc @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 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 + +#include "mock/ecore_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + + +extern "C" Ecore_Event_Handler* ecore_event_handler_add( + int type, Ecore_Event_Handler_Cb func, const void* data) { + return MOCK_HOOK_P3(EcoreMock, ecore_event_handler_add, type, func, data); +} + +extern "C" void* ecore_event_handler_del(Ecore_Event_Handler* event_handler) { + return MOCK_HOOK_P1(EcoreMock, ecore_event_handler_del, event_handler); +} diff --git a/unittests/mock/ecore_mock.h b/unittests/mock/ecore_mock.h new file mode 100644 index 0000000..e6e7b4d --- /dev/null +++ b/unittests/mock/ecore_mock.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_ECORE_MOCK_H_ +#define UNIT_TESTS_MOCK_ECORE_MOCK_H_ + +#include +#include + +#include "mock/module_mock.h" + +#include + +class EcoreMock : public virtual ModuleMock { + public: + EcoreMock() { + using ::testing::_; + using ::testing::Invoke; + + ON_CALL(*this, ecore_event_handler_add(_, _, _)) + .WillByDefault(Invoke([&](int type, Ecore_Event_Handler_Cb cb, const void* data) -> Ecore_Event_Handler* { + static int dummy; + events_[type] = std::pair(cb, data); + return (Ecore_Event_Handler*)&dummy; + })); + ON_CALL(*this, ecore_event_handler_del(_)) + .WillByDefault(Invoke([&](Ecore_Event_Handler*) -> void* { + return nullptr; + })); + } + + void SendEvent(int type, void* event) { + auto val = events_[type]; + val.first((void*)(val.second), type, event); + } + + MOCK_METHOD3(ecore_event_handler_add, + Ecore_Event_Handler*(int, Ecore_Event_Handler_Cb, const void*)); + MOCK_METHOD1(ecore_event_handler_del, + void*(Ecore_Event_Handler*)); + + private: + std::map> events_; +}; + +#endif // UNIT_TESTS_MOCK_ECORE_MOCK_H_ + diff --git a/unittests/mock/ecore_wl2_mock.cc b/unittests/mock/ecore_wl2_mock.cc new file mode 100644 index 0000000..3a380fe --- /dev/null +++ b/unittests/mock/ecore_wl2_mock.cc @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 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 + +#include "mock/ecore_wl2_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + + +extern "C" int ecore_wl2_init() { + return MOCK_HOOK_P0(EcoreWl2Mock, ecore_wl2_init); +} + +extern "C" Ecore_Wl2_Display* ecore_wl2_connected_display_get( + const char *display) { + return MOCK_HOOK_P1(EcoreWl2Mock, ecore_wl2_connected_display_get, display); +} + +extern "C" void ecore_wl2_window_activate(Ecore_Wl2_Window* window) { + return MOCK_HOOK_P1(EcoreWl2Mock, ecore_wl2_window_activate, window); +} + +extern "C" void ecore_wl2_window_iconified_set( + Ecore_Wl2_Window *win, Eina_Bool flag) { + return MOCK_HOOK_P2(EcoreWl2Mock, ecore_wl2_window_iconified_set, win, flag); +} + +extern "C" void ecore_wl2_window_class_set( + Ecore_Wl2_Window *win, const char *name) { + return MOCK_HOOK_P2(EcoreWl2Mock, ecore_wl2_window_class_set, win, name); +} + +extern "C" int ecore_wl2_window_id_get( + Ecore_Wl2_Window *win) { + return MOCK_HOOK_P1(EcoreWl2Mock, ecore_wl2_window_id_get, win); +} + +extern "C" void ecore_wl2_display_disconnect( + Ecore_Wl2_Display *display) { + return MOCK_HOOK_P1(EcoreWl2Mock, ecore_wl2_display_disconnect, display); +} + +extern "C" int ecore_wl2_shutdown() { + return MOCK_HOOK_P0(EcoreWl2Mock, ecore_wl2_shutdown); +} + +extern "C" Ecore_Wl2_Display *ecore_wl2_display_connect(const char *conn) { + return MOCK_HOOK_P1(EcoreWl2Mock, ecore_wl2_display_connect, conn); +} + +extern "C" struct wl_surface *ecore_wl2_window_surface_get(Ecore_Wl2_Window *window) { + return MOCK_HOOK_P1(EcoreWl2Mock, ecore_wl2_window_surface_get, window); +} + +extern "C" Ecore_Wl2_Window* ecore_wl2_display_window_find( + Ecore_Wl2_Display* display, unsigned int id) { + return MOCK_HOOK_P2(EcoreWl2Mock, ecore_wl2_display_window_find, display, id); +} \ No newline at end of file diff --git a/unittests/mock/ecore_wl2_mock.h b/unittests/mock/ecore_wl2_mock.h new file mode 100644 index 0000000..558ddd3 --- /dev/null +++ b/unittests/mock/ecore_wl2_mock.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_ECORE_WL2_MOCK_H_ +#define UNIT_TESTS_MOCK_ECORE_WL2_MOCK_H_ + +#include +#include + +#include "mock/module_mock.h" + +class EcoreWl2Mock : public virtual ModuleMock { + public: + EcoreWl2Mock() { + using ::testing::_; + using ::testing::Invoke; + + ON_CALL(*this, ecore_wl2_init()) + .WillByDefault(Invoke([&]() -> int { + ECORE_WL2_EVENT_WINDOW_SHOW = 1; + ECORE_WL2_EVENT_WINDOW_HIDE = 2; + ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE = 3; + ECORE_WL2_EVENT_WINDOW_LOWER = 4; + ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE = 5; + ECORE_WL2_EVENT_AUX_MESSAGE = 6; + return 1; + })); + } + + MOCK_METHOD0(ecore_wl2_init, int()); + MOCK_METHOD1(ecore_wl2_connected_display_get, + Ecore_Wl2_Display*(const char *)); + MOCK_METHOD2(ecore_wl2_window_iconified_set, + void(Ecore_Wl2_Window *, Eina_Bool)); + MOCK_METHOD2(ecore_wl2_window_class_set, + void(Ecore_Wl2_Window *, const char *)); + MOCK_METHOD1(ecore_wl2_window_id_get, + int(Ecore_Wl2_Window *)); + MOCK_METHOD1(ecore_wl2_display_disconnect, + void(Ecore_Wl2_Display *)); + MOCK_METHOD0(ecore_wl2_shutdown, int()); + MOCK_METHOD1(ecore_wl2_display_connect, + Ecore_Wl2_Display *(const char *)); + MOCK_METHOD1(ecore_wl2_window_surface_get, + struct wl_surface *(Ecore_Wl2_Window *)); + MOCK_METHOD1(ecore_wl2_window_activate, void (Ecore_Wl2_Window*)); + MOCK_METHOD2(ecore_wl2_display_window_find, + Ecore_Wl2_Window* (Ecore_Wl2_Display*, unsigned int)); +}; + +#endif // UNIT_TESTS_MOCK_ECORE_WL2_MOCK_H_ + diff --git a/unittests/mock/elm_mock.cc b/unittests/mock/elm_mock.cc new file mode 100644 index 0000000..eb4eef1 --- /dev/null +++ b/unittests/mock/elm_mock.cc @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 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 + +#include "mock/elm_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + +extern "C" int elm_init(int argc, char** argv) { + return MOCK_HOOK_P2(ElmMock, elm_init, argc, argv); +} + +extern "C" int elm_shutdown() { + return MOCK_HOOK_P0(ElmMock, elm_shutdown); +} + +extern "C" void elm_run() { + MOCK_HOOK_P0(ElmMock, elm_run); +} + +extern "C" void elm_exit() { + MOCK_HOOK_P0(ElmMock, elm_exit); +} + +extern "C" void elm_config_accel_preference_set(const char* arg1) { + MOCK_HOOK_P1(ElmMock, elm_config_accel_preference_set, arg1); +} + +extern "C" void elm_cache_all_flush() { + MOCK_HOOK_P0(ElmMock, elm_cache_all_flush); +} diff --git a/unittests/mock/elm_mock.h b/unittests/mock/elm_mock.h new file mode 100644 index 0000000..51f601c --- /dev/null +++ b/unittests/mock/elm_mock.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_ELM_MOCK_H_ +#define UNIT_TESTS_MOCK_ELM_MOCK_H_ + +#include +#include +#include + +#include "mock/module_mock.h" + +class ElmMock : public virtual ModuleMock { + public: + ElmMock() { + using ::testing::_; + using ::testing::Invoke; + + ON_CALL(*this, elm_init(_, _)) + .WillByDefault(Invoke([&](int argc, char **argv) -> int { + loop_ = g_main_loop_new(NULL, FALSE); + return 0; + })); + ON_CALL(*this, elm_shutdown()) + .WillByDefault(Invoke([&]() -> int { + g_main_loop_unref(loop_); + return 0; + })); + ON_CALL(*this, elm_run()) + .WillByDefault(Invoke([&]() { + g_main_loop_run(loop_); + })); + ON_CALL(*this, elm_exit()) + .WillByDefault(Invoke([&]() { + g_main_loop_quit(loop_); + })); + } + + MOCK_METHOD2(elm_init, int (int, char**)); + MOCK_METHOD0(elm_shutdown, int ()); + MOCK_METHOD0(elm_run, void ()); + MOCK_METHOD0(elm_exit, void ()); + MOCK_METHOD1(elm_config_accel_preference_set, void (const char*)); + MOCK_METHOD0(elm_cache_all_flush, void ()); + + private: + GMainLoop* loop_ = nullptr; +}; + +#endif // UNIT_TESTS_MOCK_ELM_MOCK_H_ + diff --git a/unittests/mock/mock_hook.h b/unittests/mock/mock_hook.h new file mode 100644 index 0000000..4a77577 --- /dev/null +++ b/unittests/mock/mock_hook.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 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_HOOK_H_ +#define MOCK_MOCK_HOOK_H_ + +#define MOCK_HOOK_P0(MOCK_CLASS, f) \ + TestFixture::GetMock().f() +#define MOCK_HOOK_P1(MOCK_CLASS, f, p1) \ + TestFixture::GetMock().f(p1) +#define MOCK_HOOK_P2(MOCK_CLASS, f, p1, p2) \ + TestFixture::GetMock().f(p1, p2) +#define MOCK_HOOK_P3(MOCK_CLASS, f, p1, p2, p3) \ + TestFixture::GetMock().f(p1, p2, p3) +#define MOCK_HOOK_P4(MOCK_CLASS, f, p1, p2, p3, p4) \ + TestFixture::GetMock().f(p1, p2, p3, p4) +#define MOCK_HOOK_P5(MOCK_CLASS, f, p1, p2, p3, p4, p5) \ + TestFixture::GetMock().f(p1, p2, p3, p4, p5) +#define MOCK_HOOK_P6(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6) \ + TestFixture::GetMock().f(p1, p2, p3, p4, p5, p6) +#define MOCK_HOOK_P7(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7) \ + TestFixture::GetMock().f(p1, p2, p3, p4, p5, p6, p7) +#define MOCK_HOOK_P8(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7, p8) \ + TestFixture::GetMock().f(p1, p2, p3, p4, p5, p6, p7, p8) +#define MOCK_HOOK_P10(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) \ + TestFixture::GetMock().f( \ + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) + +#endif // MOCK_MOCK_HOOK_H_ diff --git a/unittests/mock/module_mock.h b/unittests/mock/module_mock.h new file mode 100644 index 0000000..1b7b73e --- /dev/null +++ b/unittests/mock/module_mock.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021 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_MODULE_MOCK_H_ +#define MOCK_MODULE_MOCK_H_ + +class ModuleMock { + public: + virtual ~ModuleMock() {} +}; + +#endif // MOCK_MODULE_MOCK_H_ diff --git a/unittests/mock/sensor_mock.cc b/unittests/mock/sensor_mock.cc new file mode 100644 index 0000000..aa1c640 --- /dev/null +++ b/unittests/mock/sensor_mock.cc @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 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 + +#include "mock/sensor_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + + +extern "C" int sensord_connect(sensor_t sensor) { + return MOCK_HOOK_P1(SensorMock, sensord_connect, sensor); +} + +extern "C" bool sensord_disconnect(int handle) { + return MOCK_HOOK_P1(SensorMock, sensord_disconnect, handle); +} + +extern "C" bool sensord_register_event(int handle, unsigned int event_type, + unsigned int interval, unsigned int max_batch_latency, + sensor_cb_t cb, void *user_data) { + return MOCK_HOOK_P6(SensorMock, sensord_register_event, + handle, event_type, interval, max_batch_latency, cb, user_data); +} + +extern "C" bool sensord_unregister_event(int handle, unsigned int event_type) { + return MOCK_HOOK_P2(SensorMock, sensord_unregister_event, handle, event_type); +} + +extern "C" bool sensord_start(int handle, int option) { + return MOCK_HOOK_P2(SensorMock, sensord_start, handle, option); +} + +extern "C" bool sensord_stop(int handle) { + return MOCK_HOOK_P1(SensorMock, sensord_stop, handle); +} + +extern "C" bool sensord_get_data(int handle, unsigned int data_id, + sensor_data_t* sensor_data) { + return MOCK_HOOK_P3(SensorMock, sensord_get_data, handle, data_id, sensor_data); +} \ No newline at end of file diff --git a/unittests/mock/sensor_mock.h b/unittests/mock/sensor_mock.h new file mode 100644 index 0000000..90b6697 --- /dev/null +++ b/unittests/mock/sensor_mock.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_SENSOR_MOCK_H_ +#define UNIT_TESTS_MOCK_SENSOR_MOCK_H_ + +#include +#include + +#include "mock/module_mock.h" + +class SensorMock : public virtual ModuleMock { + public: + SensorMock() { + using ::testing::_; + using ::testing::Return; + using ::testing::Invoke; + + ON_CALL(*this, sensord_connect(_)) + .WillByDefault(Return(1)); + ON_CALL(*this, sensord_disconnect(_)) + .WillByDefault(Return(true)); + ON_CALL(*this, sensord_register_event(_, _, _, _, _, _)) + .WillByDefault(Return(true)); + ON_CALL(*this, sensord_unregister_event(_, _)) + .WillByDefault(Return(true)); + ON_CALL(*this, sensord_start(_, _)) + .WillByDefault(Return(true)); + ON_CALL(*this, sensord_stop(_)) + .WillByDefault(Return(true)); + ON_CALL(*this, sensord_get_data(_, _, _)) + .WillByDefault(Invoke([&](int handle, unsigned int data_id, + sensor_data_t* sensor_data) -> bool { + sensor_data->value_count = 1; + sensor_data->values[0] = AUTO_ROTATION_DEGREE_0; + return true; + })); + } + + MOCK_METHOD1(sensord_connect, int (sensor_t)); + MOCK_METHOD1(sensord_disconnect, bool (int)); + MOCK_METHOD6(sensord_register_event, bool (int, unsigned int, + unsigned int, unsigned int, sensor_cb_t, void*)); + MOCK_METHOD2(sensord_unregister_event, bool (int, unsigned int)); + MOCK_METHOD2(sensord_start, bool (int, int)); + MOCK_METHOD1(sensord_stop, bool (int)); + MOCK_METHOD3(sensord_get_data, bool (int, unsigned int, sensor_data_t*)); +}; + +#endif // UNIT_TESTS_MOCK_SENSOR_MOCK_H_ + diff --git a/unittests/mock/test_fixture.cc b/unittests/mock/test_fixture.cc new file mode 100644 index 0000000..8abae0c --- /dev/null +++ b/unittests/mock/test_fixture.cc @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021 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 "test_fixture.h" + +#include + +std::unique_ptr TestFixture::mock_; diff --git a/unittests/mock/test_fixture.h b/unittests/mock/test_fixture.h new file mode 100644 index 0000000..1bd48c9 --- /dev/null +++ b/unittests/mock/test_fixture.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 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_TEST_FIXTURE_H_ +#define MOCK_TEST_FIXTURE_H_ + +#include + +#include +#include +#include +#include + +#include "module_mock.h" + +class TestFixture : public ::testing::Test { + public: + explicit TestFixture(std::unique_ptr&& mock) { + mock_ = std::move(mock); + } + virtual ~TestFixture() { + mock_.reset(); + } + + virtual void SetUp() {} + virtual void TearDown() {} + + template + static T& GetMock() { + auto ptr = dynamic_cast(mock_.get()); + if (!ptr) + throw std::invalid_argument("The test does not provide mock of \"" + + std::string(typeid(T).name()) + "\""); + return *ptr; + } + + static std::unique_ptr mock_; +}; + +#endif // MOCK_TEST_FIXTURE_H_ diff --git a/unittests/mock/vconf_mock.cc b/unittests/mock/vconf_mock.cc new file mode 100644 index 0000000..de7d364 --- /dev/null +++ b/unittests/mock/vconf_mock.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 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 + +#include "mock/vconf_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + + +extern "C" int vconf_notify_key_changed(const char *in_key, + vconf_callback_fn cb, void *user_data) { + return MOCK_HOOK_P3(VConfMock, vconf_notify_key_changed, + in_key, cb, user_data); +} + +extern "C" int vconf_ignore_key_changed(const char *in_key, + vconf_callback_fn cb) { + return MOCK_HOOK_P2(VConfMock, vconf_ignore_key_changed, + in_key, cb); +} + +extern "C" char* vconf_get_str(const char* in_key) { + return MOCK_HOOK_P1(VConfMock, vconf_get_str, in_key); +} + +extern "C" int vconf_get_int(const char* in_key, int* val) { + return MOCK_HOOK_P2(VConfMock, vconf_get_int, in_key, val); +} + +extern "C" int vconf_get_bool(const char* in_key, int* val) { + return MOCK_HOOK_P2(VConfMock, vconf_get_bool, in_key, val); +} diff --git a/unittests/mock/vconf_mock.h b/unittests/mock/vconf_mock.h new file mode 100644 index 0000000..1c3b18c --- /dev/null +++ b/unittests/mock/vconf_mock.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_VCONF_MOCK_H_ +#define UNIT_TESTS_MOCK_VCONF_MOCK_H_ + +#include +#include + +#include "mock/module_mock.h" + +#include + +class VConfMock : public virtual ModuleMock { + public: + VConfMock() { + using ::testing::_; + using ::testing::Return; + using ::testing::Invoke; + + ON_CALL(*this, vconf_notify_key_changed(_, _, _)) + .WillByDefault(Invoke([&](const char *in_key, + vconf_callback_fn cb, void *user_data) -> int { + data_[in_key] = { cb, user_data }; + return 0; + })); + ON_CALL(*this, vconf_ignore_key_changed(_, _)) + .WillByDefault(Invoke([&](const char *in_key, + vconf_callback_fn cb) -> int { + data_.erase(in_key); + return 0; + })); + ON_CALL(*this, vconf_get_str(_)) + .WillByDefault(Return(nullptr)); + ON_CALL(*this, vconf_get_int(_, _)) + .WillByDefault(Invoke([&](const char *in_key, + int* val) -> int { + *val = 0; + return 0; + })); + ON_CALL(*this, vconf_get_bool(_, _)) + .WillByDefault(Invoke([&](const char *in_key, + int* val) -> int { + *val = 0; + return 0; + })); + } + + MOCK_METHOD3(vconf_notify_key_changed, int (const char*, + vconf_callback_fn, void*)); + MOCK_METHOD2(vconf_ignore_key_changed, int (const char*, + vconf_callback_fn)); + MOCK_METHOD1(vconf_get_str, char* (const char*)); + MOCK_METHOD2(vconf_get_int, int (const char*, int*)); + MOCK_METHOD2(vconf_get_bool, int (const char*, int*)); + + void ChangeStr(const std::string& key, const std::string& val) { + if (data_.find(key) == data_.end()) + return; + + keynode_t node; + node.type = VCONF_TYPE_STRING; + node.keyname = const_cast(key.c_str()); + node.value.s = const_cast(val.c_str()); + + data_[key].first(&node, data_[key].second); + } + + void ChangeInt(const std::string& key, int val) { + if (data_.find(key) == data_.end()) + return; + + keynode_t node; + node.type = VCONF_TYPE_INT; + node.keyname = const_cast(key.c_str()); + node.value.i = val; + + data_[key].first(&node, data_[key].second); + } + + void ChangeBool(const std::string& key, bool val) { + if (data_.find(key) == data_.end()) + return; + + keynode_t node; + node.type = VCONF_TYPE_BOOL; + node.keyname = const_cast(key.c_str()); + node.value.b = val; + + data_[key].first(&node, data_[key].second); + } + + private: + std::map> data_; +}; + +#endif // UNIT_TESTS_MOCK_VCONF_MOCK_H_ + diff --git a/unittests/mock/wayland_mock.cc b/unittests/mock/wayland_mock.cc new file mode 100644 index 0000000..9040e03 --- /dev/null +++ b/unittests/mock/wayland_mock.cc @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 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 + +#include "mock/wayland_mock.h" +#include "mock/mock_hook.h" +#include "mock/test_fixture.h" + +extern "C" wl_display* wl_display_connect(const char *name) { + return MOCK_HOOK_P1(WaylandMock, wl_display_connect, name); +} + +extern "C" void wl_display_disconnect(wl_display* display) { + MOCK_HOOK_P1(WaylandMock, wl_display_disconnect, display); +} + +extern "C" wl_proxy* wl_proxy_marshal_constructor(wl_proxy* proxy, uint32_t opcode, + const wl_interface* interface, ...) { + static int dummy; + return (wl_proxy*)&dummy; +} + +extern "C" int wl_proxy_add_listener(wl_proxy *proxy, + void (**implementation)(void), void *data) { + return MOCK_HOOK_P3(WaylandMock, wl_proxy_add_listener, proxy, + implementation, data); +} + +extern "C" int wl_display_roundtrip(wl_display* display) { + return MOCK_HOOK_P1(WaylandMock, wl_display_roundtrip, display); +} + +extern "C" void wl_proxy_marshal(wl_proxy *proxy, uint32_t opcode, ...) { +} + +extern "C" void wl_proxy_destroy(wl_proxy *proxy) { +} diff --git a/unittests/mock/wayland_mock.h b/unittests/mock/wayland_mock.h new file mode 100644 index 0000000..91ca2fe --- /dev/null +++ b/unittests/mock/wayland_mock.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 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 UNIT_TESTS_MOCK_WAYLAND_MOCK_H_ +#define UNIT_TESTS_MOCK_WAYLAND_MOCK_H_ + +#include +#include +#include +#include + +#include "mock/module_mock.h" + +class WaylandMock : public virtual ModuleMock { + public: + WaylandMock() { + using ::testing::_; + using ::testing::Invoke; + + ON_CALL(*this, wl_display_connect(_)) + .WillByDefault(Invoke([&](const char*) -> wl_display* { + static int dummy; + return (wl_display*)&dummy; + })); + } + + MOCK_METHOD1(wl_display_connect, wl_display* (const char*)); + MOCK_METHOD1(wl_display_disconnect, void (wl_display*)); + MOCK_METHOD3(wl_proxy_add_listener, int (wl_proxy*, void (**)(void), void*)); + MOCK_METHOD1(wl_display_roundtrip, int (wl_display*)); +}; + +#endif // UNIT_TESTS_MOCK_WAYLAND_MOCK_H_ +