Add managed launcher part
[platform/core/dotnet/launcher.git] / NativeLauncher / src / waiter.cc
1
2 #include <poll.h>
3
4 #ifndef NO_TIZEN
5 #include <launchpad.h>
6 #include <aul.h>
7 #endif
8
9 #include <memory>
10 #include <vector>
11 #include <map>
12 #include <poll.h>
13
14 #include <iostream>
15
16 #include "waiter.h"
17 #include "log.h"
18
19 namespace dotnet {
20 namespace runtime {
21
22 struct FdHandler
23 {
24   pollfd *info;
25   Receiver receiver;
26 };
27
28 static volatile bool Waiting_;
29 static std::vector<pollfd> Fdlist_;
30 static std::map<int, FdHandler> Handlers_;
31 static Waiter::AppInfo AppInfo_;
32
33 void Waiter::OnPrepare()
34 {
35   // preload the libraries.
36   if (prepare_ != nullptr)
37     prepare_();
38 }
39
40 void Waiter::OnLaunchRequested(const AppInfo& info)
41 {
42   // do some job on user id is still system
43 }
44
45 void Waiter::OnWaiting()
46 {
47   // Start the loop
48   Waiting_ = true;
49
50   _DBG("start polling...");
51   while (Waiting_)
52   {
53     if (poll(Fdlist_.data(), Fdlist_.size(), -1) < 0)
54       continue;
55
56     for (auto &p : Fdlist_)
57     {
58       if ( (p.revents | POLLIN) != 0 )
59         Handlers_[p.fd].receiver(p.fd);
60     }
61   }
62   _DBG("end polling...");
63 }
64
65 void Waiter::Stop()
66 {
67   // Stop the loop
68
69   Waiting_ = false;
70 }
71
72
73 void Waiter::RegisterFd(int fd, Receiver receiver)
74 {
75   // register fd should be caught in event loop
76
77   _DBG("Register fd %d", fd);
78
79   pollfd info;
80   info.fd = fd;
81   info.events = POLLIN;
82   info.revents = 0;
83
84   FdHandler handler;
85   Fdlist_.push_back(info);
86   handler.info = &Fdlist_.back(); 
87   handler.receiver = receiver;
88
89   Handlers_[fd] = handler;
90 }
91
92 void Waiter::DeregisterFd(int fd)
93 {
94   // deregister fd should be caught in event loop
95   
96   pollfd *info = Handlers_[fd].info;
97   Fdlist_.erase(Fdlist_.begin() - (info - &Fdlist_.front()));
98   Handlers_.erase(fd);
99 }
100
101
102 Waiter::Waiter(Action prepare, Action requested, Executor executor)
103 {
104   prepare_ = prepare;
105   requested_ = requested;
106   executor_ = executor;
107 }
108
109 Waiter::~Waiter()
110 {
111 }
112
113 int Waiter::WaitToLaunching(int argc, char *argv[])
114 {
115 #ifndef NO_TIZEN
116   auto on_create = [](bundle *extra, int type, void *user_data)
117   {
118     _DBG("on_create..."); // XXX
119     Waiter* waiter = static_cast<Waiter*>(user_data);
120     waiter->OnPrepare();
121   };
122
123   auto on_launch = [](int argc, char **argv, const char *app_path,
124       const char *appid, const char *pkgid,
125       const char *pkg_type, void *user_data) -> int
126   {
127     _DBG("on_launch..."); // XXX
128     Waiter* waiter = static_cast<Waiter*>(user_data);
129
130     _DBG ("app path : %s", app_path);
131     _DBG ("app id : %s", appid);
132     _DBG ("pkg id : %s", pkgid);
133     _DBG ("pkg type : %s", pkg_type);
134
135     AppInfo info = {
136       AppPath : app_path,
137       AppId : appid,
138       PkgId : pkgid,
139       PkgType : pkg_type
140     };
141
142     waiter->OnLaunchRequested(info);
143     return 0;
144   };
145
146   auto on_terminate = [](int argc, char **argv, void *user_data) -> int
147   {
148     _DBG("on_terminate..."); // XXX
149     
150     string app_root(aul_get_app_root_path());
151     Waiter* waiter = static_cast<Waiter*>(user_data);
152     waiter->executor_(argv[0], app_root, argc, argv);
153     return 0;
154   };
155
156   auto on_start_loop = [](void *user_data)
157   {
158     _DBG("on_start_loop..."); // XXX
159     Waiter* waiter = static_cast<Waiter*>(user_data);
160     waiter->OnWaiting();
161   };
162
163   auto on_quit_loop = [](void *user_data)
164   {
165     _DBG("on_quit_loop..."); // XXX
166     Waiter* waiter = static_cast<Waiter*>(user_data);
167     waiter->Stop();
168   };
169
170   auto on_add_fd = [](void *user_data, int fd, loader_receiver_cb receiver)
171   {
172     _DBG("on_add_fd..."); // XXX
173     Waiter* waiter = static_cast<Waiter*>(user_data);
174     waiter->RegisterFd(fd, receiver);
175   };
176
177   auto on_remove_fd = [](void *user_data, int fd)
178   {
179     _DBG("on_remove_fd..."); // XXX
180     Waiter* waiter = static_cast<Waiter*>(user_data);
181     waiter->DeregisterFd(fd);
182   };
183
184   _DBG("launcher wait..."); // XXX
185   loader_lifecycle_callback_s callbacks = {
186     .create = on_create,
187     .launch = on_launch,
188     .terminate = on_terminate
189   };
190
191         loader_adapter_s adapter = {
192                 .loop_begin = on_start_loop,
193                 .loop_quit = on_quit_loop,
194                 .add_fd = on_add_fd,
195                 .remove_fd = on_remove_fd
196         };
197
198   return launchpad_loader_main(argc, argv, &callbacks, &adapter, this);
199 #else
200   if (argc < 2) return -1;
201   std::string app_path(argv[1]);
202   std::string app_root;
203   auto pos = app_path.find_last_of('/');
204   if (pos != std::string::npos)
205     app_root = app_path.substr(0, pos);
206   else
207     app_root = ".";
208
209   this->OnPrepare();
210     AppInfo info = {
211       AppPath : argv[1],
212       AppId : "",
213       PkgId : "",
214       PkgType : ""
215     };
216   this->OnLaunchRequested(info);
217   this->executor_(app_path, app_root, argc, argv);
218 #endif
219 }
220
221 }  // namespace runtime
222 }  // namespace dotnet