2 * Copyright (c) 2018 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.
25 #include <sys/types.h>
30 #include <bundle_internal.h>
40 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
42 struct aul_request_s {
48 typedef struct aul_request_s *aul_request_h;
50 typedef void (*dispatcher)(aul_request_h req);
52 typedef struct aul_handler_s {
53 aul_handler_fn callback;
57 typedef struct subapp_handler_s {
63 typedef struct data_control_provider_handler_s {
64 data_control_provider_handler_fn callback;
65 } data_control_provider_handler;
67 typedef struct launch_context_s {
71 subapp_handler subapp;
72 data_control_provider_handler dcp;
75 static launch_context __context;
77 static void __invoke_aul_handler(aul_type type, bundle *b)
79 if (__context.aul.callback)
80 __context.aul.callback(type, b, __context.aul.user_data);
83 static void __dispatch_app_start(aul_request_h req)
87 __invoke_aul_handler(AUL_START, req->b);
88 str = bundle_get_val(req->b, AUL_K_DATA_CONTROL_TYPE);
89 if (str && !strcmp(str, "CORE")) {
90 if (__context.dcp.callback)
91 __context.dcp.callback(req->b, 0, NULL);
95 static void __dispatch_app_resume(aul_request_h req)
97 __invoke_aul_handler(AUL_RESUME, NULL);
100 static void __dispatch_app_term_by_pid(aul_request_h req)
102 __invoke_aul_handler(AUL_TERMINATE, NULL);
105 static void __dispatch_app_term_bgapp_by_pid(aul_request_h req)
107 __invoke_aul_handler(AUL_TERMINATE_BGAPP, NULL);
110 static void __dispatch_app_term_req_by_pid(aul_request_h req)
112 if (__context.subapp.is_subapp) {
113 if (__context.subapp.callback)
114 __context.subapp.callback(__context.subapp.user_data);
116 __invoke_aul_handler(AUL_TERMINATE, NULL);
120 static void __dispatch_app_result(aul_request_h req)
125 pid_str = bundle_get_val(req->b, AUL_K_CALLEE_PID);
129 app_result(req->cmd, req->b, pid);
132 static void __dispatch_app_key_event(aul_request_h req)
134 app_key_event(req->b);
137 static void __dispatch_app_pause_by_pid(aul_request_h req)
139 __invoke_aul_handler(AUL_PAUSE, req->b);
142 static void __dispatch_app_com_message(aul_request_h req)
144 app_com_recv(req->b);
147 static void __dispatch_app_wake(aul_request_h req)
149 __invoke_aul_handler(AUL_WAKE, req->b);
152 static void __dispatch_app_suspend(aul_request_h req)
154 __invoke_aul_handler(AUL_SUSPEND, req->b);
157 static void __dispatch_widget_get_content(aul_request_h req)
159 const char *widget_id;
160 const char *instance_id;
161 const char *content_info;
165 r = aul_sock_recv_reply_sock_fd(req->clifd, &fds, 1);
167 _E("Failed to receive fds");
171 widget_id = bundle_get_val(req->b, AUL_K_WIDGET_ID);
173 _E("Failed to get widget ID");
174 aul_sock_send_raw_with_fd(fds[0], -EINVAL, 0, 0,
179 instance_id = bundle_get_val(req->b, AUL_K_WIDGET_INSTANCE_ID);
181 _E("Failed to get instance ID");
182 aul_sock_send_raw_with_fd(fds[0], -EINVAL, 0, 0,
187 __invoke_aul_handler(AUL_WIDGET_CONTENT, req->b);
189 content_info = bundle_get_val(req->b, AUL_K_WIDGET_CONTENT_INFO);
191 r = aul_sock_send_raw_with_fd(fds[0], 0,
192 (unsigned char *)content_info,
193 strlen(content_info) + 1, AUL_SOCK_NOREPLY);
195 r = aul_sock_send_raw_with_fd(fds[0], -ENOENT,
196 NULL, 0, AUL_SOCK_NOREPLY);
200 _E("Failed to send content info. fd(%d), result(%d)",
205 static void __dispatch_app_update_requested(aul_request_h req)
207 __invoke_aul_handler(AUL_UPDATE_REQUESTED, req->b);
210 static void __dispatch_watchdog_ping(aul_request_h req)
212 const char *start_time;
215 gettimeofday(&tv, NULL);
216 start_time = bundle_get_val(req->b, AUL_K_STARTTIME);
217 _W("[__WATCHDOG__] Start time: %s, response time: %ld/%ld",
218 start_time ? start_time : "Unknown",
219 tv.tv_sec, tv.tv_usec);
222 static dispatcher __dispatcher[] = {
223 [APP_START] = __dispatch_app_start,
224 [APP_START_RES] = __dispatch_app_start,
225 [APP_START_ASYNC] = __dispatch_app_start,
226 [APP_START_RES_ASYNC] = __dispatch_app_start,
227 [APP_OPEN] = __dispatch_app_resume,
228 [APP_RESUME] = __dispatch_app_resume,
229 [APP_RESUME_BY_PID] = __dispatch_app_resume,
230 [APP_TERM_BY_PID] = __dispatch_app_term_by_pid,
231 [APP_TERM_BY_PID_ASYNC] = __dispatch_app_term_by_pid,
232 [APP_TERM_BY_PID_SYNC] = __dispatch_app_term_by_pid,
233 [APP_TERM_BGAPP_BY_PID] = __dispatch_app_term_bgapp_by_pid,
234 [APP_TERM_REQ_BY_PID] = __dispatch_app_term_req_by_pid,
235 [APP_RESULT] = __dispatch_app_result,
236 [APP_CANCEL] = __dispatch_app_result,
237 [APP_KEY_EVENT] = __dispatch_app_key_event,
238 [APP_PAUSE_BY_PID] = __dispatch_app_pause_by_pid,
239 [APP_COM_MESSAGE] = __dispatch_app_com_message,
240 [APP_WAKE] = __dispatch_app_wake,
241 [APP_SUSPEND] = __dispatch_app_suspend,
242 [WIDGET_GET_CONTENT] = __dispatch_widget_get_content,
243 [APP_UPDATE_REQUESTED] = __dispatch_app_update_requested,
244 [WATCHDOG_PING] = __dispatch_watchdog_ping,
245 [APP_SEND_LAUNCH_REQUEST] = __dispatch_app_start,
248 static gboolean __aul_launch_handler(GIOChannel *io, GIOCondition condition,
251 int fd = g_io_channel_unix_get_fd(io);
252 struct aul_request_s req = { 0, };
259 pkt = aul_sock_recv_pkt(fd, &clifd, &cr);
261 _E("Failed to receive the packet");
262 return G_SOURCE_CONTINUE;
265 if (pkt->cmd != WIDGET_GET_CONTENT) {
266 if (pkt->opt & AUL_SOCK_NOREPLY) {
270 r = aul_sock_send_result(clifd, 0);
272 _E("Failed to send result. cmd(%s:%d)",
273 aul_cmd_convert_to_string(pkt->cmd),
276 return G_SOURCE_CONTINUE;;
282 if (pkt->opt & AUL_SOCK_BUNDLE) {
283 b = bundle_decode(pkt->data, pkt->len);
285 _E("Failed to decode the packet");
289 return G_SOURCE_CONTINUE;
299 if (req.cmd >= APP_START && req.cmd < ARRAY_SIZE(__dispatcher) &&
300 __dispatcher[req.cmd]) {
302 aul_cmd_convert_to_string(req.cmd), req.cmd);
303 __dispatcher[req.cmd](&req);
305 _E("Command(%s:%d) is not available",
306 aul_cmd_convert_to_string(req.cmd), req.cmd);
312 return G_SOURCE_CONTINUE;
315 static void __finalize_context(void)
317 if (__context.source) {
318 g_source_remove(__context.source);
319 __context.source = 0;
323 g_io_channel_unref(__context.io);
328 static int __initialize_context(void)
330 GIOCondition cond = G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR;
333 fd = aul_initialize();
335 _E("Failed to initialize aul");
339 __context.io = g_io_channel_unix_new(fd);
341 _E("Failed to create gio channel");
342 __finalize_context();
346 __context.source = g_io_add_watch(__context.io,
347 cond, __aul_launch_handler, NULL);
348 if (!__context.source) {
349 _E("Failed to add gio watch");
350 __finalize_context();
357 API int aul_launch_init(aul_handler_fn callback, void *user_data)
360 __context.aul.callback = callback;
361 __context.aul.user_data = user_data;
364 return __initialize_context();
367 API int aul_launch_fini(void)
369 __finalize_context();
373 static gboolean __app_start_cb(gpointer data)
375 bundle *b = (bundle *)data;
376 struct aul_request_s req = {
382 __dispatch_app_start(&req);
387 return G_SOURCE_REMOVE;
390 API int aul_launch_argv_handler(int argc, char **argv)
394 if (!aul_is_initialized()) {
395 _E("AUL is not initialized");
396 return AUL_R_ENOINIT;
399 b = bundle_import_from_argv(argc, argv);
401 _E("Bundle is nullptr");
403 if (!g_idle_add_full(G_PRIORITY_HIGH, __app_start_cb, b, NULL)) {
404 _E("Failed to add idler");
411 API int aul_launch_local(bundle *b)
413 if (!aul_is_initialized()) {
414 _E("AUL is not initialized");
415 return AUL_R_ENOINIT;
419 _E("Bundle is nullptr");
421 if (!g_idle_add(__app_start_cb, b)) {
422 _E("Failed to add idler");
429 int aul_resume_local(void)
431 if (!aul_is_initialized()) {
432 _E("AUL is not initialized");
433 return AUL_R_ENOINIT;
436 __dispatch_app_resume(NULL);
441 API int aul_set_subapp(subapp_fn callback, void *user_data)
443 __context.subapp.is_subapp = true;
444 __context.subapp.callback = callback;
445 __context.subapp.user_data = user_data;
450 API int aul_is_subapp(void)
452 return (int)__context.subapp.is_subapp;
455 API int aul_set_data_control_provider_cb(data_control_provider_handler_fn cb)
457 __context.dcp.callback = cb;
462 API int aul_unset_data_control_provider_cb(void)
464 __context.dcp.callback = NULL;