2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "core_runtime.h"
25 #include <sys/types.h>
27 #include <sys/prctl.h>
30 #include <glib-unix.h>
32 #include <launchpad.h>
35 using tizen::runtime::dotnetcore::CoreRuntime;
37 static const char* KEY_APP_TYPE = "--appType";
38 static const char* KEY_TIZEN_UIFW = "TIZEN_UIFW";
39 static const char* KEY_PROFILE = "--profile";
41 static guint __fd_handler;
42 static loader_receiver_cb __receiver;
44 // To precreate window(EFL/DALI), argc and argv should be passed.
45 // But, create callback of loader doesnot pass that to parameter.
46 // So, store argc and argv and use that to precreation.
47 // If window precreation code moves to managed, removed below code.
51 typedef struct AppInfo {
57 static AppInfo __appInfo;
59 // Collect/use multicorejit profile or not
63 GMainLoop* __loop = nullptr;
66 //################## Code for running event loop for loader ####################
68 static gboolean __process_fd_handler(int fd, GIOCondition condition, gpointer user_data)
70 if (condition & G_IO_IN) {
74 } else if (condition & (G_IO_HUP | G_IO_ERR)) {
75 _ERR("[candidate] error condition: %d", static_cast<int>(condition));
80 return G_SOURCE_REMOVE;
83 static void __adapter_loop_begin(void *user_data)
85 __loop = g_main_loop_new(nullptr, FALSE);
86 g_main_loop_run(__loop);
89 static void __adapter_loop_quit(void *user_data)
91 if (__loop != nullptr) {
92 g_main_loop_quit(__loop);
93 g_main_loop_unref(__loop);
98 static void __adapter_add_fd(void *user_data, int fd, loader_receiver_cb receiver)
100 __fd_handler = g_unix_fd_add(fd,
101 static_cast<GIOCondition>(G_IO_IN | G_IO_HUP | G_IO_ERR), __process_fd_handler, nullptr);
102 if (__fd_handler == 0) {
103 _ERR("fd_handler is NULL");
108 __receiver = receiver;
111 static void __adapter_remove_fd(void *user_data, int fd)
113 if (__fd_handler != 0) {
114 g_source_remove(__fd_handler);
120 //################## Code for managing loader life-cycle #######################
122 static void __loader_create_cb(bundle *extra, int type, void *user_data)
124 char *appType = NULL;
125 if (bundle_get_str(extra, KEY_APP_TYPE, &appType) != BUNDLE_ERROR_NONE) {
130 bundle_get_str(extra, KEY_TIZEN_UIFW, &uifw);
132 setenv(KEY_TIZEN_UIFW, uifw, 1);
133 _INFO("TIZEN_UIFW is set to %s", uifw);
136 char *profile_str = NULL;
138 bundle_get_str(extra, KEY_PROFILE, &profile_str);
139 if (profile_str != NULL) {
140 if (!strcmp(profile_str, "true")) {
142 } else if (!strcmp(profile_str, "false")) {
145 _DBG("PROFILE value %s not recognized. Valid values: true, false. Turn off PROFILE mode as default", profile_str);
149 char *ui_thread = nullptr;
150 bundle_get_str(extra, "TIZEN_UI_THREAD", &ui_thread);
151 if (ui_thread != nullptr && !strcmp(ui_thread, "true")) {
152 setenv("TIZEN_UI_THREAD", "true", 1);
153 _INFO("TIZEN_UI_THREAD is set");
156 // initialize CoreRuntime (launchmode, dlog redirection enable, root path NULL)
157 if (CoreRuntime::initialize(appType ? appType : "dotnet", LaunchMode::loader) != 0) {
158 _ERR("Failed to initialized");
160 _INFO("Success to initialized");
164 static int __loader_prelaunch_cb(int argc, char **argv, const char *app_path,
165 const char *appid, const char *pkgid, const char *pkg_type,
168 int ret = launchpad_loader_block_threads();
170 _ERR("Failed to prelaunch");
175 static int __loader_launch_cb(int argc, char **argv, const char *app_path,
176 const char *appid, const char *pkgid, const char *pkg_type,
179 const char* root_path = aul_get_app_root_path();
180 if (root_path != NULL) {
181 __appInfo.root = root_path;
183 __appInfo.app_path = app_path;
184 __appInfo.appid = appid;
185 __appInfo.pkgid = pkgid;
187 return launchpad_loader_unblock_threads();
190 static int __loader_terminate_cb(int argc, char **argv, void *user_data)
192 _INFO("launch request with app path : %s", __appInfo.app_path.c_str());
194 // The launchpad pass the name of exe file to the first argument.
195 // For the C# spec, we have to skip this first argument.
196 if (CoreRuntime::launch(__appInfo.appid.c_str(), __appInfo.root.c_str(),
197 __appInfo.app_path.c_str(), argc - 1, argv + 1, profile)) {
198 _ERR("Failed to launch");
205 //################## Main Code #################################################
207 extern "C" int realMain(int argc, char *argv[])
209 _INFO("##### Run in candidate mode #####");
211 // change cmdline from dotnet-hydra-loader to dotnet-loader
212 if (strcmp(argv[0], "/usr/bin/dotnet-hydra-loader") == 0) {
213 memset(argv[0], '\0', strlen("/usr/bin/dotnet-hydra-loader"));
214 snprintf(argv[0], strlen("/usr/bin/dotnet-loader") + 1,
215 "/usr/bin/dotnet-loader");
218 loader_lifecycle_callback_s callbacks = {
219 .create = __loader_create_cb,
220 .prelaunch = __loader_prelaunch_cb,
221 .launch = __loader_launch_cb,
222 .terminate = __loader_terminate_cb
225 loader_adapter_s adapter = {
226 .loop_begin = __adapter_loop_begin,
227 .loop_quit = __adapter_loop_quit,
228 .add_fd = __adapter_add_fd,
229 .remove_fd = __adapter_remove_fd
232 int ret = launchpad_loader_main(argc, argv, &callbacks, &adapter, NULL);
234 CoreRuntime::finalize();
239 int main(int argc, char *argv[])
244 return realMain(argc, argv);