af74eae2711fc8c6896ea4b7a80967abfcf2fdbe
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / exec / loader.cc
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "core_runtime.h"
18 #include "utils.h"
19 #include "log.h"
20
21 #include <cstdio>
22 #include <vector>
23 #include <memory>
24
25 #include <Ecore.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <sys/prctl.h>
29
30 #include <launchpad.h>
31 #include <aul.h>
32
33 using tizen::runtime::dotnetcore::CoreRuntime;
34
35 static const char* KEY_APP_TYPE = "--appType";
36 static const char* KEY_TIZEN_UIFW = "TIZEN_UIFW";
37 static const char* KEY_PROFILE = "--profile";
38
39 static Ecore_Fd_Handler *__fd_handler;
40 static loader_receiver_cb __receiver;
41
42 // To precreate window(EFL/DALI), argc and argv should be passed.
43 // But, create callback of loader doesnot pass that to parameter.
44 // So, store argc and argv and use that to precreation.
45 // If window precreation code moves to managed, removed below code.
46 static int __argc;
47 static char **__argv;
48
49 typedef struct AppInfo {
50         std::string root;
51         std::string app_path;
52         std::string appid;
53         std::string pkgid;
54 } AppInfo;
55 static AppInfo __appInfo;
56
57 // Collect/use multicorejit profile or not
58 static bool profile;
59
60
61 //################## Code for running event loop for loader ####################
62
63 static Eina_Bool __process_fd_handler(void *data, Ecore_Fd_Handler *handler)
64 {
65         int fd;
66
67         fd = ecore_main_fd_handler_fd_get(handler);
68         if (fd == -1) {
69                 _ERR("[candidate] ECORE_FD_GET");
70                 exit(-1);
71         }
72
73         if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) {
74                 if (__receiver)
75                         __receiver(fd);
76         } else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) {
77                 _ERR("[candidate] ECORE_FD_ERROR");
78                 close(fd);
79                 exit(-1);
80         }
81
82         return ECORE_CALLBACK_CANCEL;
83 }
84
85 static void __adapter_loop_begin(void *user_data)
86 {
87         ecore_main_loop_begin();
88 }
89
90 static void __adapter_loop_quit(void *user_data)
91 {
92         ecore_main_loop_quit();
93 }
94
95 static void __adapter_add_fd(void *user_data, int fd,
96                 loader_receiver_cb receiver)
97 {
98         __fd_handler = ecore_main_fd_handler_add(fd,
99                         static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
100                         __process_fd_handler, NULL, NULL, NULL);
101
102         if (__fd_handler == NULL) {
103                 _ERR("fd_handler is NULL");
104                 close(fd);
105                 exit(-1);
106         }
107
108         __receiver = receiver;
109 }
110
111 static void __adapter_remove_fd(void *user_data, int fd)
112 {
113         if (__fd_handler) {
114                 ecore_main_fd_handler_del(__fd_handler);
115                 __fd_handler = NULL;
116                 __receiver = NULL;
117         }
118 }
119
120 //################## Code for managing loader life-cycle #######################
121
122 static void __loader_create_cb(bundle *extra, int type, void *user_data)
123 {
124         char *appType = NULL;
125         if (bundle_get_str(extra, KEY_APP_TYPE, &appType) != BUNDLE_ERROR_NONE) {
126                 appType = NULL;
127         }
128
129         char *uifw = NULL;
130         bundle_get_str(extra, KEY_TIZEN_UIFW, &uifw);
131         if (uifw != NULL) {
132                 setenv(KEY_TIZEN_UIFW, uifw, 1);
133                 _INFO("TIZEN_UIFW is set to %s", uifw);
134         }
135
136         char *profile_str = NULL;
137         profile = false;
138         bundle_get_str(extra, KEY_PROFILE, &profile_str);
139         if (profile_str != NULL) {
140                 if (!strcmp(profile_str, "true")) {
141                         profile = true;
142                 } else if (!strcmp(profile_str, "false")) {
143                         profile = false;
144                 } else {
145                         _DBG("PROFILE value %s not recognized. Valid values: true, false. Turn off PROFILE mode as default", profile_str);
146             }
147         }
148
149         // initialize CoreRuntime (launchmode, dlog redirection enable, root path NULL)
150         if (CoreRuntime::initialize(appType ? appType : "dotnet", LaunchMode::loader) != 0) {
151                 _ERR("Failed to initialized");
152         } else {
153                 _INFO("Success to initialized");
154         }
155 }
156
157 static int __loader_launch_cb(int argc, char **argv, const char *app_path,
158                 const char *appid, const char *pkgid, const char *pkg_type,
159                 void *user_data)
160 {
161         const char* root_path = aul_get_app_root_path();
162         if (root_path != NULL) {
163                 __appInfo.root = root_path;
164         }
165
166         __appInfo.app_path = app_path;
167         __appInfo.appid = appid;
168         __appInfo.pkgid = pkgid;
169
170         return 0;
171 }
172
173 static int __loader_terminate_cb(int argc, char **argv, void *user_data)
174 {
175         _INFO("launch request with app path : %s", __appInfo.app_path.c_str());
176
177         // The launchpad pass the name of exe file to the first argument.
178         // For the C# spec, we have to skip this first argument.
179         if (CoreRuntime::launch(__appInfo.appid.c_str(), __appInfo.root.c_str(),
180                                                 __appInfo.app_path.c_str(), argc - 1, argv + 1, profile)) {
181                 _ERR("Failed to launch");
182                 return -1;
183         }
184
185         return 0;
186 }
187
188 //################## Main Code #################################################
189
190 extern "C" int realMain(int argc, char *argv[])
191 {
192         _INFO("##### Run in candidate mode #####");
193
194         // change cmdline from dotnet-hydra-loader to dotnet-loader
195         if (strcmp(argv[0], "/usr/bin/dotnet-hydra-loader") == 0) {
196                 memset(argv[0], '\0', strlen("/usr/bin/dotnet-hydra-loader"));
197                 snprintf(argv[0], strlen("/usr/bin/dotnet-loader") + 1,
198                                                 "/usr/bin/dotnet-loader");
199         }
200
201         loader_lifecycle_callback_s callbacks = {
202                 .create = __loader_create_cb,
203                 .launch = __loader_launch_cb,
204                 .terminate = __loader_terminate_cb
205         };
206
207         loader_adapter_s adapter = {
208                 .loop_begin = __adapter_loop_begin,
209                 .loop_quit = __adapter_loop_quit,
210                 .add_fd = __adapter_add_fd,
211                 .remove_fd = __adapter_remove_fd
212         };
213
214         int ret = launchpad_loader_main(argc, argv, &callbacks, &adapter, NULL);
215
216         CoreRuntime::finalize();
217
218         return ret;
219 }
220
221 int main(int argc, char *argv[])
222 {
223         __argc = argc;
224         __argv = argv;
225
226         return realMain(argc, argv);
227 }