From: 조웅석/MDE Lab(SR)/삼성전자 Date: Mon, 26 Jun 2023 04:16:49 +0000 (+0900) Subject: Support UI Thread Separate (UTS) App Model (#464) X-Git-Tag: accepted/tizen/unified/20230627.025434^0 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fdotnet%2Flauncher.git;a=commitdiff_plain;h=e13a51071869d132412452660504c235be058aa5 Support UI Thread Separate (UTS) App Model (#464) define new apptype dotnet-uts for UI Thread Separate App Model In the UI Thread Separate App Model, the main thread operates with the gmainloop and UI-related tasks operate with the ecoreloop in a separate thread. Therefore, ecore_init() should not be called in the main thread of the candidate process for the UI Thread Separate App Model. Also, candidate process should run with the gmainloop. To run by the UI Thread Separate App Model, the environment variable "TIZEN_UI_THREAD" should be set to "true". If this environment variable is set, then NUI would work on UI Thread Separate Mode. --- diff --git a/NativeLauncher/dotnet.launcher b/NativeLauncher/dotnet.launcher index 0895e2d..b42202e 100644 --- a/NativeLauncher/dotnet.launcher +++ b/NativeLauncher/dotnet.launcher @@ -7,6 +7,18 @@ EXTRA_ARG --profile EXTRA_ARG --appType EXTRA_ARG dotnet EXTRA_ARG TIZEN_UIFW -EXTRA_ARG NUI +EXTRA_ARG NUI EXTRA_ARG --standalone +[LAUNCHER] +NAME dotnet-uts-launcher +EXE /usr/bin/dotnet-launcher +APP_TYPE dotnet-uts +EXTRA_ARG --PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE +EXTRA_ARG --profile +EXTRA_ARG --appType +EXTRA_ARG dotnet-uts +EXTRA_ARG TIZEN_UIFW +EXTRA_ARG NUI +EXTRA_ARG TIZEN_UI_THREAD +EXTRA_ARG --standalone \ No newline at end of file diff --git a/NativeLauncher/dotnet.loader b/NativeLauncher/dotnet.loader index 237b1c3..76179de 100644 --- a/NativeLauncher/dotnet.loader +++ b/NativeLauncher/dotnet.loader @@ -12,3 +12,19 @@ HYDRA OFF EXTRA --appType dotnet EXTRA TIZEN_UIFW NUI EXTRA --profile true + +[LOADER] +NAME dotnet-uts-loader +# for candidate mode +EXE /usr/bin/dotnet-uts-loader +# for hydra mode +#EXE /usr/bin/dotnet-hydra-loader +APP_TYPE dotnet-uts +DETECTION_METHOD TIMEOUT|DEMAND +TIMEOUT 5000 +ON_BOOT OFF +HYDRA OFF +EXTRA --appType dotnet-uts +EXTRA TIZEN_UIFW NUI +EXTRA --profile true +EXTRA TIZEN_UI_THREAD true \ No newline at end of file diff --git a/NativeLauncher/launcher/exec/launcher.cc b/NativeLauncher/launcher/exec/launcher.cc index d7cc8e6..2ef357f 100644 --- a/NativeLauncher/launcher/exec/launcher.cc +++ b/NativeLauncher/launcher/exec/launcher.cc @@ -42,6 +42,7 @@ static std::string PaddingOption("--PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_ static std::string AppTypeOption("--appType"); static std::string UIFWOption(KEY_TIZEN_UIFW); static std::string ProfileOption("--profile"); +static std::string UTSOption("TIZEN_UI_THREAD"); static std::string GlobalizationInvariantOption("--invariant"); int main(int argc, char *argv[]) @@ -90,6 +91,9 @@ int main(int argc, char *argv[]) } i++; UIFWType = argv[i]; + } else if (UTSOption.compare(argv[i]) == 0) { + setenv("TIZEN_UI_THREAD", "true", 1); + _INFO("TIZEN_UI_THREAD is set"); } else { vargs.push_back(argv[i]); } diff --git a/NativeLauncher/launcher/exec/loader.cc b/NativeLauncher/launcher/exec/loader.cc index af74eae..62fccdc 100644 --- a/NativeLauncher/launcher/exec/loader.cc +++ b/NativeLauncher/launcher/exec/loader.cc @@ -22,11 +22,13 @@ #include #include -#include #include #include #include +#include +#include + #include #include @@ -36,7 +38,7 @@ static const char* KEY_APP_TYPE = "--appType"; static const char* KEY_TIZEN_UIFW = "TIZEN_UIFW"; static const char* KEY_PROFILE = "--profile"; -static Ecore_Fd_Handler *__fd_handler; +static guint __fd_handler; static loader_receiver_cb __receiver; // To precreate window(EFL/DALI), argc and argv should be passed. @@ -57,49 +59,47 @@ static AppInfo __appInfo; // Collect/use multicorejit profile or not static bool profile; +namespace { +GMainLoop* __loop = nullptr; +} // namespace //################## Code for running event loop for loader #################### -static Eina_Bool __process_fd_handler(void *data, Ecore_Fd_Handler *handler) +static gboolean __process_fd_handler(int fd, GIOCondition condition, gpointer user_data) { - int fd; - - fd = ecore_main_fd_handler_fd_get(handler); - if (fd == -1) { - _ERR("[candidate] ECORE_FD_GET"); - exit(-1); - } - - if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) { - if (__receiver) + if (condition & G_IO_IN) { + if (__receiver) { __receiver(fd); - } else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) { - _ERR("[candidate] ECORE_FD_ERROR"); + } + } else if (condition & (G_IO_HUP | G_IO_ERR)) { + _ERR("[candidate] error condition: %d", static_cast(condition)); close(fd); exit(-1); } - return ECORE_CALLBACK_CANCEL; + return G_SOURCE_REMOVE; } static void __adapter_loop_begin(void *user_data) { - ecore_main_loop_begin(); + __loop = g_main_loop_new(nullptr, FALSE); + g_main_loop_run(__loop); } static void __adapter_loop_quit(void *user_data) { - ecore_main_loop_quit(); + if (__loop != nullptr) { + g_main_loop_quit(__loop); + g_main_loop_unref(__loop); + __loop = nullptr; + } } -static void __adapter_add_fd(void *user_data, int fd, - loader_receiver_cb receiver) +static void __adapter_add_fd(void *user_data, int fd, loader_receiver_cb receiver) { - __fd_handler = ecore_main_fd_handler_add(fd, - static_cast(ECORE_FD_READ | ECORE_FD_ERROR), - __process_fd_handler, NULL, NULL, NULL); - - if (__fd_handler == NULL) { + __fd_handler = g_unix_fd_add(fd, + static_cast(G_IO_IN | G_IO_HUP | G_IO_ERR), __process_fd_handler, nullptr); + if (__fd_handler == 0) { _ERR("fd_handler is NULL"); close(fd); exit(-1); @@ -110,9 +110,9 @@ static void __adapter_add_fd(void *user_data, int fd, static void __adapter_remove_fd(void *user_data, int fd) { - if (__fd_handler) { - ecore_main_fd_handler_del(__fd_handler); - __fd_handler = NULL; + if (__fd_handler != 0) { + g_source_remove(__fd_handler); + __fd_handler = 0; __receiver = NULL; } } @@ -146,6 +146,13 @@ static void __loader_create_cb(bundle *extra, int type, void *user_data) } } + char *ui_thread = nullptr; + bundle_get_str(extra, "TIZEN_UI_THREAD", &ui_thread); + if (ui_thread != nullptr && !strcmp(ui_thread, "true")) { + setenv("TIZEN_UI_THREAD", "true", 1); + _INFO("TIZEN_UI_THREAD is set"); + } + // initialize CoreRuntime (launchmode, dlog redirection enable, root path NULL) if (CoreRuntime::initialize(appType ? appType : "dotnet", LaunchMode::loader) != 0) { _ERR("Failed to initialized"); diff --git a/NativeLauncher/launcher/lib/core_runtime.cc b/NativeLauncher/launcher/lib/core_runtime.cc index 88b999c..f8c685b 100644 --- a/NativeLauncher/launcher/lib/core_runtime.cc +++ b/NativeLauncher/launcher/lib/core_runtime.cc @@ -321,9 +321,6 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode) return -1; } - // Intiailize ecore first (signal handlers, etc.) before runtime init. - ecore_init(); - // set language environment to support ICU setLang(); diff --git a/NativeLauncher/tool/privilege_common.cc b/NativeLauncher/tool/privilege_common.cc index 737a971..66f38eb 100644 --- a/NativeLauncher/tool/privilege_common.cc +++ b/NativeLauncher/tool/privilege_common.cc @@ -64,8 +64,22 @@ void checkInternetPrivilegeAndDisableIPv6(const char* pkgId, const std::string& static int checkAppPrivilegeListCb(pkgmgrinfo_appinfo_h handle, void *user_data) { + int ret = 0; + char* appType = NULL; + + ret = pkgmgrinfo_appinfo_get_apptype(handle, &appType); + if (ret != PMINFO_R_OK) { + _SERR("Failed to get apptype"); + return 0; + } + + // skip if appType is NULL or appType does not contains "dotnet", + if (appType == NULL || (appType != NULL && strstr(appType, "dotnet") == NULL)) { + return 0; + } + char *pkgId = NULL; - int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); + ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); if (ret != PMINFO_R_OK || pkgId == NULL) { _SERR("Failed to get package id"); return 0; @@ -83,40 +97,10 @@ static int checkAppPrivilegeListCb(pkgmgrinfo_appinfo_h handle, void *user_data) return 0; } -static void checkAppPrivilegeByAppType(const char* type) -{ - pkgmgrinfo_appinfo_filter_h filter; - - int ret = pkgmgrinfo_appinfo_filter_create(&filter); - if (ret != PMINFO_R_OK) { - _SERR("Failed to create appinfo filter"); - return; - } - - ret = pkgmgrinfo_appinfo_filter_add_string(filter, PMINFO_APPINFO_PROP_APP_TYPE, type); - if (ret != PMINFO_R_OK) { - pkgmgrinfo_appinfo_filter_destroy(filter); - _SERR("Failed to add appinfo filter (%s)", type); - return; - } - - ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(filter, checkAppPrivilegeListCb, NULL); - if (ret != PMINFO_R_OK) { - _SERR("Failed to pkgmgrinfo_appinfo_filter_foreach_appinfo"); - pkgmgrinfo_appinfo_filter_destroy(filter); - return; - } - - pkgmgrinfo_appinfo_filter_destroy(filter); - - return; -} - void checkAllAppPrivilege() { - std::vector appTypeList = {"dotnet", "dotnet-nui", "dotnet-inhouse"}; - - for (auto& type : appTypeList) { - checkAppPrivilegeByAppType(type); + int ret = pkgmgrinfo_appinfo_get_installed_list(checkAppPrivilegeListCb, NULL); + if (ret != PMINFO_R_OK) { + _SERR("Failed to get installed list"); } } diff --git a/NativeLauncher/tool/profile_common.cc b/NativeLauncher/tool/profile_common.cc index ace461e..91065f1 100644 --- a/NativeLauncher/tool/profile_common.cc +++ b/NativeLauncher/tool/profile_common.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2022 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. @@ -12,18 +12,18 @@ * WITHOUT 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 "log.h" -#include "utils.h" -#include "profile_common.h" -#include "launcher_env.h" - -#include -#include -#include - -static std::vector getUserIds() +#include "utils.h" +#include "profile_common.h" +#include "launcher_env.h" + +#include +#include +#include + +static std::vector getUserIds() { std::vector list; @@ -59,12 +59,12 @@ static std::string getAppDataPath(const std::string& pkgId, uid_t uid) tzplatform_reset_user(); return pDataFile; -} - -profile_error_e removeAppProfileData(const std::string& pkgId) +} + +profile_error_e removeAppProfileData(const std::string& pkgId) { if (pkgId.empty()) { - return PROFILE_ERROR_INVALID_PARAMETER; + return PROFILE_ERROR_INVALID_PARAMETER; } std::vector uidList = getUserIds(); @@ -76,68 +76,51 @@ profile_error_e removeAppProfileData(const std::string& pkgId) if (exist(pDataFile)) { if (!removeFile(pDataFile)) { - _SERR("Failed to remove profile data file (%s).", pDataFile.c_str()); - return PROFILE_ERROR_UNKNOWN; + _SERR("Failed to remove profile data file (%s).", pDataFile.c_str()); + return PROFILE_ERROR_UNKNOWN; } _SOUT("Profile data (%s) is removed successfully", pDataFile.c_str()); } } } - return PROFILE_ERROR_NONE; -} - -static int removeAppProfileListCb(pkgmgrinfo_appinfo_h handle, void *user_data) -{ - char *pkgId = NULL; - int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); - if (ret != PMINFO_R_OK || pkgId == NULL) { - _SERR("Failed to get package id"); - return 0; - } - - if (removeAppProfileData(pkgId) != PROFILE_ERROR_NONE) { - _SERR("Failed to remove profile data for (%s)", pkgId); - } - - return 0; + return PROFILE_ERROR_NONE; } -static void removeAppProfileByAppType(const char* type) +static int removeAppProfileListCb(pkgmgrinfo_appinfo_h handle, void *user_data) { - pkgmgrinfo_appinfo_filter_h filter; + int ret = 0; + char* appType = NULL; - int ret = pkgmgrinfo_appinfo_filter_create(&filter); + ret = pkgmgrinfo_appinfo_get_apptype(handle, &appType); if (ret != PMINFO_R_OK) { - _SERR("Failed to create appinfo filter"); - return; + _SERR("Failed to get apptype"); + return 0; } - ret = pkgmgrinfo_appinfo_filter_add_string(filter, PMINFO_APPINFO_PROP_APP_TYPE, type); - if (ret != PMINFO_R_OK) { - pkgmgrinfo_appinfo_filter_destroy(filter); - _SERR("Failed to add appinfo filter (%s)", type); - return; + // skip if appType is NULL or appType does not contains "dotnet", + if (appType == NULL || (appType != NULL && strstr(appType, "dotnet") == NULL)) { + return 0; } - ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(filter, removeAppProfileListCb, NULL); - if (ret != PMINFO_R_OK) { - _SERR("Failed to pkgmgrinfo_pkginfo_filter_foreach_pkginfo"); - pkgmgrinfo_appinfo_filter_destroy(filter); - return; + char *pkgId = NULL; + ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); + if (ret != PMINFO_R_OK || pkgId == NULL) { + _SERR("Failed to get package id"); + return 0; } - pkgmgrinfo_appinfo_filter_destroy(filter); + if (removeAppProfileData(pkgId) != PROFILE_ERROR_NONE) { + _SERR("Failed to remove profile data for (%s)", pkgId); + } - return; + return 0; } void removeAllAppProfileData() { - std::vector appTypeList = {"dotnet", "dotnet-nui", "dotnet-inhouse"}; - - for (auto& type : appTypeList) { - removeAppProfileByAppType(type); + int ret = pkgmgrinfo_appinfo_get_installed_list(removeAppProfileListCb, NULL); + if (ret != PMINFO_R_OK) { + _SERR("Failed to get installed list"); } -} - +} diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index a352ce5..b8d0c58 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -190,6 +190,8 @@ install -m 0755 packaging/%{_rw_dotnet_update_script} %{buildroot}/%{_rw_update_ %post mkdir -p /opt/etc/skel/.dotnet chsmack -t -a User::App::Shared /opt/etc/skel/.dotnet +ln -sf /usr/bin/dotnet-loader /usr/bin/dotnet-uts-loader +chsmack -a User /usr/bin/dotnet-uts-loader %files %manifest dotnet-launcher.manifest