svace : initialize hydracallback
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / launcher.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 "launcher.h"
18 #include "log.h"
19
20 #include <launchpad.h>
21 #include <aul.h>
22
23 #include <Ecore.h>
24 #include <bundle_internal.h>
25
26 #include <map>
27 #include <vector>
28 #include <functional>
29
30 #include <unistd.h>
31 #include <dlfcn.h>
32
33
34 namespace tizen {
35 namespace runtime {
36
37 struct FdHandler {
38         Ecore_Fd_Handler *handler;
39         loader_receiver_cb receiver;
40 };
41
42 static int __argc;
43 static char **__argv;
44
45 class LaunchpadAdapterImpl : public LaunchpadAdapter
46 {
47         public:
48                 LaunchpadAdapterImpl() :
49                         callbacks(),
50                         hydraCallbacks(),
51                         adapter(),
52                         __isLaunched(false)
53                 { }
54                 int loaderMain(int argc, char* argv[]) override;
55
56                 std::map<int, FdHandler> handlers;
57
58         private:
59                 AppInfo appInfo;
60                 loader_lifecycle_callback_s callbacks;
61                 hydra_lifecycle_callback_s hydraCallbacks;
62                 loader_adapter_s adapter;
63                 bool __isLaunched;
64                 std::string __launchPath;
65 };
66
67 LaunchpadAdapterImpl LaunchpadImpl;
68 LaunchpadAdapter& Launchpad = LaunchpadImpl;
69
70 #define WITH_SELF(data) \
71         LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
72         if (self == nullptr) \
73                 _ERR("No LaunchpadImplData"); \
74         else
75
76 static Eina_Bool fdHandler(void *data, Ecore_Fd_Handler* handler)
77 {
78         WITH_SELF(data) {
79                 int fd = ecore_main_fd_handler_fd_get(handler);
80                 if (fd == -1) {
81                         _ERR("Failed to get the Ecore FD");
82                         exit(-1);
83                 }
84
85                 if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) {
86                         if (self->handlers.find(fd) != self->handlers.end())
87                                 self->handlers[fd].receiver(fd);
88                 } else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) {
89                         _ERR("Ecore FD Handler Have Error");
90                         close(fd);
91                         exit(-1);
92                 }
93         }
94
95         return ECORE_CALLBACK_RENEW;
96 }
97
98 static void fdAdd(void *data, int fd, loader_receiver_cb receiver)
99 {
100         Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd,
101                         static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
102                         fdHandler, data, nullptr, nullptr);
103         if (handler == nullptr) {
104                 _ERR("Failed to add a FD handler to ecore main loop");
105                 close(fd);
106                 exit(-1);
107         } WITH_SELF(data) {
108                 self->handlers[fd] = {handler, receiver};
109         }
110 }
111
112 static void fdRemove(void *data, int fd)
113 {
114         WITH_SELF(data) {
115                 if (self->handlers.find(fd) != self->handlers.end()) {
116                         Ecore_Fd_Handler* handler = self->handlers[fd].handler;
117                         ecore_main_fd_handler_del(handler);
118                         self->handlers.erase(fd);
119                 }
120         }
121 }
122
123 // To run dotnet-launcher on the headless device, remove build dependency from EFL.
124 #define ELEMENTARY_PATH "/usr/lib/libelementary.so.1"
125 static void* __win;
126 typedef int (*elm_init_ptr)(int argc, char **argv);
127 typedef void (*elm_config_accel_preference_set_ptr)(const char *pref);
128 typedef void* (*elm_win_add_ptr)(void* parent, const char* name, int type);
129 typedef void (*elm_win_precreated_object_set_ptr)(void* win);
130
131 static void preCreateWindow()
132 {
133         struct stat sb;
134         if (stat(ELEMENTARY_PATH, &sb) != 0) {
135                 _ERR("[candidate] libelementary is not exist. skip precreation");
136                 return;
137         }
138
139         int elmInitCnt = 0;
140         void* handle = nullptr;
141         elm_init_ptr elm_init = nullptr;
142         elm_config_accel_preference_set_ptr elm_config_accel_preference_set = nullptr;
143         elm_win_add_ptr elm_win_add = nullptr;
144         elm_win_precreated_object_set_ptr elm_win_precreated_object_set = nullptr;
145
146         handle = dlopen(ELEMENTARY_PATH, RTLD_NOW | RTLD_GLOBAL);
147         if (handle) {
148                 elm_init = (elm_init_ptr)dlsym(handle, "elm_init");
149                 if (elm_init) {
150                         elmInitCnt = elm_init(__argc, __argv);
151
152                         if (!elmInitCnt) {
153                                 _ERR("[candidate] elm_init() failed");
154                                 return;
155                         }
156                 }
157
158                 elm_config_accel_preference_set = (elm_config_accel_preference_set_ptr)dlsym(handle, "elm_config_accel_preference_set");
159                 if (elm_config_accel_preference_set) {
160                         elm_config_accel_preference_set("hw");
161                 }
162
163                 elm_win_add = (elm_win_add_ptr)dlsym(handle, "elm_win_add");
164                 if (elm_win_add) {
165                         // enum value of "ELM_WIN_BASIC" is 0
166                         __win = elm_win_add(NULL, "package_name", 0);
167                         if (__win == NULL) {
168                                 _ERR("[candidate] elm_win_add() failed");
169                                 return;
170                         }
171                 }
172
173                 elm_win_precreated_object_set = (elm_win_precreated_object_set_ptr)dlsym(handle, "elm_win_precreated_object_set");
174                 if (elm_win_precreated_object_set) {
175                         elm_win_precreated_object_set(__win);
176                 }
177                 _INFO("elm window precreation is done");
178         }
179 }
180
181 int LaunchpadAdapterImpl::loaderMain(int argc, char* argv[])
182 {
183         __argc = argc;
184         __argv = argv;
185         callbacks.create = [](bundle *extra, int type, void *userData) {
186                 preCreateWindow();
187                 WITH_SELF(userData) {
188                         if (self->onCreate != nullptr)
189                                 self->onCreate();
190                 }
191         };
192         callbacks.launch = [](int argc, char** argv, const char* appPath,
193                                                 const char* appId, const char* pkgId,
194                                                 const char* pkgType, void* userData) -> int {
195                 WITH_SELF(userData) {
196                         const char* appRootPath = aul_get_app_root_path();
197                         if (appRootPath != nullptr) {
198                                 self->appInfo.root = std::string(appRootPath);
199                         }
200                         self->appInfo.path = appPath;
201                         self->appInfo.id = appId;
202                         self->appInfo.pkg = pkgId;
203                         self->appInfo.type = pkgType;
204                         if (self->onLaunch != nullptr)
205                                 self->onLaunch(self->appInfo, argc, argv);
206                 }
207
208                 return 0;
209         };
210         callbacks.terminate = [](int argc, char **argv, void* userData) -> int {
211                 WITH_SELF(userData) {
212                         if (self->onTerminate != nullptr)
213                                 self->onTerminate(self->appInfo, argc, argv);
214                 }
215                 return 0;
216         };
217
218         // Called before initial fork
219         hydraCallbacks.precreate = [](void* userData) {
220                 WITH_SELF(userData) {
221                         if (self->onPreCreate != nullptr)
222                                 self->onPreCreate();
223                 }
224         };
225
226         hydraCallbacks.create = [](void* userData) {
227                 ecore_init();
228         };
229
230         // Called after fork in candidate
231         hydraCallbacks.fork = [](void *userData) {
232                 ecore_fork_reset();
233         };
234
235         hydraCallbacks.terminate = [](void* userData) {
236                 ecore_shutdown();
237                 return 0;
238         };
239
240         adapter.loop_begin = [](void *data) {
241                 ecore_init();
242                 ecore_main_loop_begin();
243         };
244
245         adapter.loop_quit = [](void *data) {
246                 ecore_main_loop_quit();
247         };
248         adapter.add_fd = fdAdd;
249         adapter.remove_fd = fdRemove;
250
251         _INFO("launchpad_hydra_main is start");
252         int r = launchpad_hydra_main(argc, argv, &(this->hydraCallbacks),
253                 &(this->callbacks), &(this->adapter), this);
254         _INFO("launchpad_hydra_main is finished with [%d]", r);
255
256         return r;
257 }
258
259 #undef WITH_SELF
260
261 }  // namespace runtime
262 }  // namespace tizen