Refactor aul service codes
[platform/core/appfw/aul-1.git] / src / aul_svc.cc
1 /*
2  * Copyright (c) 2021 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 <bundle.h>
18 #include <bundle_cpp.h>
19 #include <bundle_internal.h>
20 #include <glib.h>
21 #include <iniparser.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28
29 #include <memory>
30 #include <string>
31 #include <vector>
32
33 #include "aul/app_control/resolve_info.hh"
34 #include "include/aul.h"
35 #include "include/aul_app_group.h"
36 #include "include/aul_error.h"
37 #include "include/aul_sock.h"
38 #include "include/aul_svc.h"
39 #include "include/aul_svc_internal.h"
40 #include "src/aul_api.h"
41 #include "src/aul_svc_priv_key.h"
42 #include "src/aul_util.h"
43 #include "src/launch.h"
44
45 #undef MAX_MIME_STR_SIZE
46 #define MAX_MIME_STR_SIZE 256
47
48 #undef MAX_SCHEME_STR_SIZE
49 #define MAX_SCHEME_STR_SIZE 256
50
51 #undef MAX_HOST_STR_SIZE
52 #define MAX_HOST_STR_SIZE 256
53
54 #undef DEPRECATION_WARNING
55 #define DEPRECATION_WARNING() do {                                             \
56     dlog_print(DLOG_WARN, LOG_TAG,                                             \
57         "DEPRECATION WARNING: %s() is deprecated and "                         \
58         "will be removed from next release.", __FUNCTION__);                   \
59 } while (0)
60
61 namespace {
62
63 class CbInfo {
64  public:
65   CbInfo(int request_code, aul_svc_res_fn res_fn,
66       aul_svc_err_cb err_cb, void* user_data)
67       : request_code_(request_code),
68         res_fn_(res_fn),
69         err_cb_(err_cb),
70         user_data_(user_data) {
71   }
72
73   int request_code_;
74   aul_svc_res_fn res_fn_;
75   aul_svc_err_cb err_cb_;
76   void* user_data_;
77 };
78
79 int SetBundle(bundle* b, const char* key, const char* value) {
80   if (bundle_get_type(b, key) != BUNDLE_TYPE_NONE) {
81     if (bundle_del(b, key) != BUNDLE_ERROR_NONE)
82       return AUL_SVC_RET_ERROR;
83   }
84
85   if (value == nullptr)
86     return AUL_SVC_RET_EINVAL;
87
88   if (bundle_add(b, key, value) != BUNDLE_ERROR_NONE)
89     return AUL_SVC_RET_ERROR;
90
91   SECURE_LOGD("key(%s), value(%s)", key, value);
92   return AUL_SVC_RET_OK;
93 }
94
95 int SetBundleArray(bundle* b, const char* key, const char** value,
96     int len) {
97   int is_array = aul_svc_data_is_array(b, key);
98   if (is_array) {
99     if (bundle_del(b, key) != BUNDLE_ERROR_NONE)
100       return AUL_SVC_RET_ERROR;
101   }
102
103   if (value == nullptr)
104     return AUL_SVC_RET_EINVAL;
105
106   if (bundle_add_str_array(b, key, value, len) != BUNDLE_ERROR_NONE)
107     return AUL_SVC_RET_ERROR;
108
109   SECURE_LOGD("key(%s), length(%d)", key, len);
110   return AUL_SVC_RET_OK;
111 }
112
113 std::string GetAliasAppId(const char* appid) {
114   dictionary* dic = iniparser_load("/usr/share/appsvc/alias.ini");
115   if (dic == nullptr)
116     return {};
117
118   auto dic_ptr = std::unique_ptr<dictionary, decltype(iniparser_freedict)*>(
119       dic, iniparser_freedict);
120
121   std::string key = std::string("Alias:") + appid;
122   const char* value = iniparser_getstring(dic, key.c_str(), nullptr);
123   SECURE_LOGD("appid(%s), alias_id(%s)", appid, value);
124   if (value == nullptr)
125     return {};
126
127   return std::string(value);
128 }
129
130 bool IsSpecialApp(const char* appid) {
131   if (!strcmp(appid, APP_SELECTOR) || !strcmp(appid, SHARE_PANEL))
132     return true;
133
134   return false;
135 }
136
137 bool IsSpecialOperation(const char* operation) {
138   if (operation == nullptr)
139     return false;
140
141   int ret = strcmp(operation,
142       "http://tizen.org/appcontrol/operation/guide_privacy_setting");
143   if (ret == 0)
144     return true;
145
146   return false;
147 }
148
149 std::string GetAppId(bundle* request) {
150   const char* appid = aul_svc_get_pkgname(request);
151   if (appid == nullptr) {
152     if (aul_svc_get_operation(request) == nullptr) {
153       _E("Invalid request");
154       return {};
155     }
156
157     appid = "@UNKNOWN";
158   }
159
160   int ret = bundle_get_type(request, AUL_SVC_K_SELECTOR_EXTRA_LIST);
161   if (ret != BUNDLE_TYPE_NONE) {
162     if (appid == nullptr || !strcmp(appid, "@UNKNOWN"))
163       appid = APP_SELECTOR;
164   }
165
166   ret = bundle_get_type(request, AUL_K_FORCE_LAUNCH_APP_SELECTOR);
167   if (ret != BUNDLE_TYPE_NONE)
168     appid = APP_SELECTOR;
169
170   return std::string(appid);
171 }
172
173 void SetLaunchData(bundle* request, const std::string& appid) {
174   const char* operation = aul_svc_get_operation(request);
175   if (operation == nullptr)
176     aul_svc_set_operation(request, AUL_SVC_OPERATION_DEFAULT);
177
178   if (IsSpecialApp(appid.c_str()) || IsSpecialOperation(operation)) {
179     SetBundle(request, AUL_SVC_K_CAN_BE_LEADER, "true");
180     SetBundle(request, AUL_SVC_K_REROUTE, "true");
181     SetBundle(request, AUL_SVC_K_RECYCLE, "true");
182   }
183
184   const char* launch_mode = aul_svc_get_launch_mode(request);
185   if (launch_mode && !strcmp(launch_mode, "group")) {
186     int ret = bundle_get_type(request, AUL_K_INSTANCE_ID);
187     if (ret != BUNDLE_TYPE_NONE)
188       aul_set_instance_info(appid.c_str(), request);
189   }
190 }
191
192 int AulErrorConvert(int res) {
193   switch (res) {
194   case AUL_R_EILLACC:
195     return AUL_SVC_RET_EILLACC;
196   case AUL_R_EINVAL:
197     return AUL_SVC_RET_EINVAL;
198   case AUL_R_ETERMINATING:
199     return AUL_SVC_RET_ETERMINATING;
200   case AUL_R_EREJECTED:
201     return AUL_SVC_RET_EREJECTED;
202   case AUL_R_ENOAPP:
203     return AUL_SVC_RET_ENOMATCH;
204   default:
205     return AUL_SVC_RET_ELAUNCH;
206   }
207 }
208
209 void LaunchWithResultCb(bundle* b, int is_cancel, void* data) {
210   int res;
211   if (is_cancel) {
212     res = AUL_SVC_RES_CANCEL;
213   } else {
214     const char* val = bundle_get_val(b, AUL_SVC_K_RES_VAL);
215     res = (val == nullptr) ? AUL_SVC_RES_NOT_OK : atoi(val);
216   }
217
218   bundle_del(b, AUL_SVC_K_RES_VAL);
219   auto* cb_info = static_cast<CbInfo*>(data);
220   if (cb_info->res_fn_) {
221     cb_info->res_fn_(b, cb_info->request_code_,
222         static_cast<aul_svc_result_val>(res), cb_info->user_data_);
223   }
224
225   if (cb_info->err_cb_ != nullptr)
226     return;
227
228   delete cb_info;
229 }
230
231 void ErrorCb(int error, void* data) {
232   if (error < 0)
233     error = AulErrorConvert(error);
234
235   auto* cb_info = static_cast<CbInfo*>(data);
236   if (cb_info->err_cb_) {
237     cb_info->err_cb_(cb_info->request_code_, error, cb_info->user_data_);
238     cb_info->err_cb_ = nullptr;
239   }
240
241   if (cb_info->res_fn_)
242     return;
243
244   delete cb_info;
245 }
246
247 using SendLaunchRequestCb =
248     int (*)(const std::string&, bundle*, uid_t, CbInfo*);
249 using SendLaunchRequestSyncCb =
250     int (*)(const std::string&, bundle*, uid_t, bundle**);
251
252 template <typename T, typename A>
253 int SendLaunchRequest(T cb, bundle* request, uid_t uid, A arg) {
254   if (request == nullptr) {
255     _E("Invalid parameter");
256     return AUL_SVC_RET_EINVAL;
257   }
258
259   std::string appid = GetAppId(request);
260   if (appid.empty()) {
261     _E("GetAppId() is failed");
262     return AUL_SVC_RET_EINVAL;
263   }
264
265   SetLaunchData(request, appid);
266   return cb(appid, request, uid, arg);
267 }
268
269 int SendAndReceive(int cmd, uid_t uid, bundle* request, bundle** response) {
270   int fd = aul_sock_send_bundle(AUL_UTIL_PID, uid, cmd, request,
271       AUL_SOCK_ASYNC);
272   if (fd < 0)
273     return AUL_SVC_RET_ERROR;
274
275   app_pkt_t* pkt = nullptr;
276   int ret = aul_sock_recv_reply_pkt(fd, &pkt);
277   if (ret < 0) {
278     _E("Failed to receive reply packet. error(%d)", ret);
279     return AUL_SVC_RET_ERROR;
280   }
281
282   auto ptr = std::unique_ptr<app_pkt_t, decltype(std::free)*>(pkt, std::free);
283   if (pkt->cmd != APP_GET_INFO_OK && pkt->cmd != cmd)
284     return AUL_SVC_RET_ERROR;
285
286   bundle* b = nullptr;
287   if (pkt->opt & AUL_SOCK_BUNDLE) {
288     b = bundle_decode(pkt->data, pkt->len);
289     if (b == nullptr) {
290       _E("bundle_decode() is failed");
291       return AUL_SVC_RET_ENOMEM;
292     }
293   } else {
294     _E("Invalid packet");
295     return AUL_SVC_RET_ERROR;
296   }
297
298   *response = b;
299   return AUL_SVC_RET_OK;
300 }
301
302 }  // namespace
303
304 extern "C" API int aul_svc_set_operation(bundle* b, const char* operation) {
305   if (b == nullptr) {
306     _E("Invalid parameter");
307     return AUL_SVC_RET_EINVAL;
308   }
309
310   return ::SetBundle(b, AUL_SVC_K_OPERATION, operation);
311 }
312
313 extern "C" API int aul_svc_set_uri(bundle* b, const char* uri) {
314   if (b == nullptr) {
315     _E("Invalid parameter");
316     return AUL_SVC_RET_EINVAL;
317   }
318
319   return ::SetBundle(b, AUL_SVC_K_URI, uri);
320 }
321
322 extern "C" API int aul_svc_set_mime(bundle* b, const char* mime) {
323   if (b == nullptr) {
324     _E("Invalid parameter");
325     return AUL_SVC_RET_EINVAL;
326   }
327
328   return ::SetBundle(b, AUL_SVC_K_MIME, mime);
329 }
330
331 extern "C" API int aul_svc_add_data(bundle* b, const char* key,
332     const char* value) {
333   if (b == nullptr || key == nullptr)
334     return AUL_SVC_RET_EINVAL;
335
336   return ::SetBundle(b, key, value);
337 }
338
339 extern "C" API int aul_svc_add_data_array(bundle* b, const char* key,
340     const char** value, int len) {
341   if (b == nullptr || key == nullptr)
342     return AUL_SVC_RET_EINVAL;
343
344   return ::SetBundleArray(b, key, value, len);
345 }
346
347 extern "C" API int aul_svc_set_pkgname(bundle* b, const char* pkg_name) {
348   if (b == nullptr) {
349     _E("Invalid parameter");
350     return AUL_SVC_RET_EINVAL;
351   }
352
353   return ::SetBundle(b, AUL_SVC_K_PKG_NAME, pkg_name);
354 }
355
356 extern "C" API int aul_svc_set_appid(bundle* b, const char* appid) {
357   if (b == nullptr || appid == nullptr) {
358     _E("Invalid parameter");
359     return AUL_SVC_RET_EINVAL;
360   }
361
362   std::string alias_id = ::GetAliasAppId(appid);
363   if (!alias_id.empty())
364     appid = alias_id.c_str();
365
366   return ::SetBundle(b, AUL_SVC_K_PKG_NAME, appid);
367 }
368
369 extern "C" API int aul_svc_set_category(bundle* b, const char* category) {
370   if (b == nullptr) {
371     _E("Invalid parameter");
372     return AUL_SVC_RET_EINVAL;
373   }
374
375   return ::SetBundle(b, AUL_SVC_K_CATEGORY, category);
376 }
377
378 extern "C" API int aul_svc_set_launch_mode(bundle* b, const char* mode) {
379   if (b == nullptr) {
380     _E("Invalid parameter");
381     return AUL_SVC_RET_EINVAL;
382   }
383
384   return ::SetBundle(b, AUL_SVC_K_LAUNCH_MODE, mode);
385 }
386
387 extern "C" API int aul_svc_resolve(bundle* b, uid_t uid, char*** appid_array,
388     unsigned int* len) {
389   return aul_svc_get_appid_array(b, uid, appid_array, len);
390 }
391
392 extern "C" API int aul_svc_run_service(bundle* b, int request_code,
393     aul_svc_res_fn cbfunc, void* data) {
394   return aul_svc_run_service_for_uid(b, request_code, cbfunc, data, getuid());
395 }
396
397 extern "C" API int aul_svc_run_service_for_uid(bundle* b, int request_code,
398   aul_svc_res_fn cbfunc, void* data, uid_t uid) {
399   CbInfo* cb_info = nullptr;
400   if (cbfunc)
401     cb_info = new (std::nothrow) CbInfo(request_code, cbfunc, nullptr, data);
402
403   std::tuple<aul_svc_res_fn, void*> param { cbfunc, data };
404   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
405       [](const std::string& appid, bundle* request, uid_t uid,
406           CbInfo* cb_info) -> int {
407         int ret;
408         if (cb_info) {
409           ret = aul_launch_app_with_result_for_uid(appid.c_str(), request,
410               LaunchWithResultCb, cb_info, uid);
411          } else {
412           ret = aul_launch_app_for_uid(appid.c_str(), request, uid);
413         }
414
415         return ret;
416       }, b, uid, cb_info);
417   if (ret < 0) {
418     if (cb_info)
419       delete cb_info;
420
421     ret = AulErrorConvert(ret);
422   }
423
424   return ret;
425 }
426
427 extern "C" API int aul_svc_get_list(bundle* b, aul_svc_info_iter_fn iter_fn,
428     void* data) {
429   return aul_svc_get_list_for_uid(b, iter_fn, data, getuid());
430 }
431
432 extern "C" API int aul_svc_get_list_for_uid(bundle* b,
433     aul_svc_info_iter_fn iter_fn, void* data, uid_t uid) {
434   if (b == nullptr || iter_fn == nullptr) {
435     _E("Invalid parameter");
436     return AUL_SVC_RET_EINVAL;
437   }
438
439   char** appid_array = nullptr;
440   unsigned int len = 0;
441   int ret = aul_svc_get_appid_array(b, uid, &appid_array, &len);
442   if (ret != AUL_SVC_RET_OK)
443     return ret;
444
445   if (len == 0) {
446     _E("Failed to find associated application");
447     aul_svc_free_appid_array(appid_array, len);
448     return AUL_SVC_RET_ENOMATCH;
449   }
450
451   for (unsigned int i = 0; i < len; ++i) {
452     SECURE_LOGD("APPID: %s", appid_array[i]);
453     if (iter_fn(appid_array[i], data) != 0)
454       break;
455   }
456
457   aul_svc_free_appid_array(appid_array, len);
458   return AUL_SVC_RET_OK;
459 }
460
461 extern "C" API int aul_svc_get_all_defapps(aul_svc_info_iter_fn iter_fn,
462     void* data) {
463   return aul_svc_get_all_defapps_for_uid(iter_fn, data, getuid());
464 }
465
466 extern "C" API int aul_svc_get_all_defapps_for_uid(aul_svc_info_iter_fn iter_fn,
467     void* data, uid_t uid) {
468   if (iter_fn == nullptr) {
469     _E("Invalid parameter");
470     return AUL_SVC_RET_EINVAL;
471   }
472
473   bundle* response;
474   tizen_base::Bundle request;
475   int ret = ::SendAndReceive(APP_GET_APP_CONTROL_DEFAULT_APPS, uid,
476       request.GetHandle(), &response);
477   if (ret != AUL_SVC_RET_OK)
478     return ret;
479
480   tizen_base::Bundle res(response, false, true);
481   auto appid_array = res.GetStringArray(AUL_K_APPID_LIST);
482   if (appid_array.size() == 0)
483     return AUL_SVC_RET_ERROR;
484
485   for (auto& appid : appid_array) {
486     if (iter_fn(appid.c_str(), data) != 0)
487       break;
488   }
489
490   return AUL_SVC_RET_OK;
491 }
492
493 extern "C" API const char* aul_svc_get_operation(bundle* b) {
494   return bundle_get_val(b, AUL_SVC_K_OPERATION);
495 }
496
497 extern "C" API const char* aul_svc_get_uri(bundle* b) {
498   return bundle_get_val(b, AUL_SVC_K_URI);
499 }
500
501 extern "C" API const char* aul_svc_get_mime(bundle* b) {
502   return bundle_get_val(b, AUL_SVC_K_MIME);
503 }
504
505 extern "C" API const char* aul_svc_get_data(bundle* b, const char* key) {
506   return bundle_get_val(b, key);
507 }
508
509 extern "C" API const char** aul_svc_get_data_array(bundle* b, const char* key,
510     int* len) {
511   return bundle_get_str_array(b, key, len);
512 }
513
514 extern "C" API const char* aul_svc_get_pkgname(bundle* b) {
515   return bundle_get_val(b, AUL_SVC_K_PKG_NAME);
516 }
517
518 extern "C" API const char* aul_svc_get_appid(bundle* b) {
519   return bundle_get_val(b, AUL_SVC_K_PKG_NAME);
520 }
521
522 extern "C" API const char* aul_svc_get_category(bundle* b) {
523   return bundle_get_val(b, AUL_SVC_K_CATEGORY);
524 }
525
526 extern "C" API const char* aul_svc_get_launch_mode(bundle* b) {
527   return bundle_get_val(b, AUL_SVC_K_LAUNCH_MODE);
528 }
529
530 extern "C" API int aul_svc_create_result_bundle(bundle* inb, bundle** outb) {
531   if (inb == nullptr || outb == nullptr) {
532     _E("Invalid parameter");
533     return AUL_SVC_RET_EINVAL;
534   }
535
536   int ret = aul_create_result_bundle(inb, outb);
537   if (ret != AUL_R_OK)
538     return AulErrorConvert(ret);
539
540   return AUL_SVC_RET_OK;
541 }
542
543 extern "C" API int aul_svc_send_result(bundle* b, aul_svc_result_val result) {
544   if (b == nullptr) {
545     _E("Invalid parameter");
546     return AUL_SVC_RET_EINVAL;
547   }
548
549   int ret = ::SetBundle(b, AUL_SVC_K_RES_VAL, std::to_string(result).c_str());
550   if (ret < 0)
551     return AUL_SVC_RET_ERROR;
552
553   if (result == AUL_SVC_RES_CANCEL)
554     ret = aul_send_result(b, 1);
555   else
556     ret = aul_send_result(b, 0);
557
558   bundle_del(b, AUL_SVC_K_RES_VAL);
559   return ret;
560 }
561
562 extern "C" API int aul_svc_data_is_array(bundle* b, const char* key) {
563   int type = bundle_get_type(b, key);
564   if (type <= 0)
565     return 0;
566
567   if (type & BUNDLE_TYPE_ARRAY)
568     return 1;
569
570   return 0;
571 }
572
573 extern "C" API int aul_svc_allow_transient_app(bundle* b, int wid) {
574   if (b == nullptr) {
575     _E("Invalid parameter");
576     return AUL_SVC_RET_EINVAL;
577   }
578
579   return ::SetBundle(b, AUL_SVC_K_WIN_ID, std::to_string(wid).c_str());
580 }
581
582 extern "C" API int aul_svc_request_transient_app(bundle* b, int callee_wid,
583     aul_svc_host_res_fn cbfunc, void* data) {
584   return 0;
585 }
586
587 extern "C" API int aul_svc_subapp_terminate_request_pid(int pid) {
588   int cpid = getpid();
589   int lcnt;
590   int* lpids = nullptr;
591   aul_app_group_get_leader_pids(&lcnt, &lpids);
592   for (int i = 0; i < lcnt; ++i) {
593     if (lpids[i] == cpid) {
594       int cnt;
595       int* pids = nullptr;
596       aul_app_group_get_group_pids(cpid, &cnt, &pids);
597       if (cnt == 0) {
598         free(lpids);
599         if (pids)
600           free(pids);
601
602         return aul_subapp_terminate_request_pid(pid);
603       }
604
605       if (pids != nullptr)
606         free(pids);
607       break;
608     }
609   }
610
611   if (lpids != nullptr)
612     free(lpids);
613
614   return aul_app_group_clear_top();
615 }
616
617 extern "C" API int aul_send_service_result(bundle* b) {
618   return aul_send_result(b, 0);
619 }
620
621 extern "C" API int aul_svc_subscribe_launch_result(bundle* b,
622     const char* result) {
623   if (b == nullptr) {
624     _E("Invalid parameter");
625     return AUL_SVC_RET_EINVAL;
626   }
627
628   return ::SetBundle(b, result, "1");
629 }
630
631 extern "C" API int aul_svc_set_loader_id(bundle* b, int loader_id) {
632   if (b == nullptr || loader_id <= 0) {
633     _E("Invalid parameter");
634     return AUL_SVC_RET_EINVAL;
635   }
636
637   return ::SetBundle(b, AUL_K_LOADER_ID, std::to_string(loader_id).c_str());
638 }
639
640 extern "C" API int aul_svc_set_loader_name(bundle* b, const char* loader_name) {
641   if (b == nullptr || loader_name == nullptr) {
642     _E("Invalid parameter");
643     return AUL_SVC_RET_EINVAL;
644   }
645
646   return ::SetBundle(b, AUL_K_LOADER_NAME, loader_name);
647 }
648
649 extern "C" API int aul_svc_set_background_launch(bundle* b, int enabled) {
650   if (b == nullptr) {
651     _E("Invalid parameter");
652     return AUL_SVC_RET_EINVAL;
653   }
654
655   return ::SetBundle(b, AUL_SVC_K_BG_LAUNCH, enabled ? "enable" : nullptr);
656 }
657
658 extern "C" API int aul_svc_get_appid_by_alias_appid(const char* alias_appid,
659     char** appid) {
660   return aul_svc_get_appid_by_alias_appid_for_uid(alias_appid, appid, getuid());
661 }
662
663 extern "C" API int aul_svc_get_appid_by_alias_appid_for_uid(
664     const char* alias_appid, char** appid, uid_t uid) {
665   if (alias_appid == nullptr || appid == nullptr) {
666     _E("Invalid parameter");
667     return AUL_SVC_RET_EINVAL;
668   }
669
670   bundle* response;
671   tizen_base::Bundle request;
672   request.Add(AUL_K_ALIAS_APPID, alias_appid);
673   int ret = ::SendAndReceive(APP_GET_APPID_BY_ALIAS_APPID, uid,
674       request.GetHandle(), &response);
675   if (ret != AUL_SVC_RET_OK)
676     return ret;
677
678   tizen_base::Bundle res(response, false, true);
679   auto val = res.GetString(AUL_K_APPID);
680   if (val.empty())
681     return AUL_SVC_RET_ERROR;
682
683   *appid = strdup(val.c_str());
684   if (*appid == nullptr) {
685     _E("Out of memory");
686     return AUL_SVC_RET_ENOMEM;
687   }
688
689   return AUL_SVC_RET_OK;
690 }
691
692 extern "C" API const char *aul_svc_get_instance_id(bundle* b) {
693   return bundle_get_val(b, AUL_K_INSTANCE_ID);
694 }
695
696 extern "C" API int aul_svc_set_instance_id(bundle* b, const char* instance_id) {
697   if (b == nullptr || instance_id == nullptr) {
698     _E("Invalid parameter");
699     return AUL_SVC_RET_EINVAL;
700   }
701
702   return ::SetBundle(b, AUL_K_INSTANCE_ID, instance_id);
703 }
704
705 extern "C" API int aul_svc_run_service_async(bundle* b, int request_code,
706     aul_svc_res_fn cbfunc, void* data) {
707   return aul_svc_run_service_async_for_uid(b, request_code, cbfunc, data,
708       getuid());
709 }
710
711 extern "C" API int aul_svc_run_service_async_for_uid(bundle* b,
712     int request_code, aul_svc_res_fn cbfunc, void* data, uid_t uid) {
713   CbInfo* cb_info = nullptr;
714   if (cbfunc)
715     cb_info = new (std::nothrow) CbInfo(request_code, cbfunc, nullptr, data);
716
717   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
718       [](const std::string& appid, bundle* request, uid_t uid,
719           CbInfo* info) -> int {
720         if (info) {
721           return aul_launch_app_with_result_async_for_uid(appid.c_str(),
722               request, LaunchWithResultCb, info, uid);
723         }
724
725         return aul_launch_app_async_for_uid(appid.c_str(), request, uid);
726       }, b, uid, cb_info);
727   if (ret < 0) {
728     if (cb_info)
729       delete cb_info;
730
731     ret = AulErrorConvert(ret);
732   }
733
734   return ret;
735 }
736
737 extern "C" API int aul_svc_send_launch_request(bundle* b, int request_code,
738     aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb, void* user_data) {
739   return aul_svc_send_launch_request_for_uid(b, request_code,
740       cbfunc, err_cb, user_data, getuid());
741 }
742
743 extern "C" API int aul_svc_send_launch_request_for_uid(bundle* b,
744     int request_code, aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb,
745     void* user_data, uid_t uid) {
746   if (b == nullptr || err_cb == nullptr) {
747     _E("Invalid parameter");
748     return AUL_SVC_RET_EINVAL;
749   }
750
751   CbInfo* cb_info = new (std::nothrow) CbInfo(request_code, cbfunc, err_cb,
752       user_data);
753   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
754       [](const std::string& appid, bundle* request, uid_t uid,
755         CbInfo* info) -> int {
756         return aul_send_launch_request_for_uid(appid.c_str(), request, uid,
757             info->res_fn_ ? ::LaunchWithResultCb : nullptr, ::ErrorCb, info);
758       }, b, uid, cb_info);
759   if (ret < 0) {
760     delete cb_info;
761     ret = ::AulErrorConvert(ret);
762   }
763
764   return ret;
765 }
766
767 extern "C" API int aul_svc_send_launch_request_sync_for_uid(bundle* b,
768     int request_code, bundle** res_b, aul_svc_result_val* res, uid_t uid) {
769   if (b == nullptr || res_b == nullptr || res == nullptr) {
770     _E("Invalid parameter");
771     return AUL_SVC_RET_EINVAL;
772   }
773
774   int ret = ::SendLaunchRequest<::SendLaunchRequestSyncCb, bundle**>(
775       [](const std::string& appid, bundle* request, uid_t uid,
776           bundle** response) -> int {
777         return aul_send_launch_request_sync_for_uid(appid.c_str(), request,
778             uid, response);
779       }, b, uid, res_b);
780   if (ret > 0) {
781     auto* val = bundle_get_val(*res_b, AUL_SVC_K_RES_VAL);
782     *res = static_cast<aul_svc_result_val>(
783         (val == nullptr) ? AUL_SVC_RES_NOT_OK : atoi(val));
784   } else {
785     ret = ::AulErrorConvert(ret);
786     *res = AUL_SVC_RES_CANCEL;
787   }
788
789   return ret;
790 }
791
792 extern "C" API int aul_svc_info_create(bundle* b, aul_svc_info_h* h) {
793   if (b == nullptr || h == nullptr) {
794     _E("Invalid parameter");
795     return AUL_SVC_RET_EINVAL;
796   }
797
798   aul::ResolveInfo* resolve_info = nullptr;
799   try {
800     tizen_base::Bundle kb(b, false, false);
801     resolve_info = aul::ResolveInfo::Manager::Create(kb);
802   } catch (aul::Exception& e) {
803     return AUL_SVC_RET_ERROR;
804   }
805
806   *h = static_cast<aul_svc_info_h>(resolve_info);
807   return AUL_SVC_RET_OK;
808 }
809
810 extern "C" API int aul_svc_info_get_operation(aul_svc_info_h h,
811     char** operation) {
812   if (h == nullptr || operation == nullptr) {
813     _E("Invalid parameter");
814     return AUL_SVC_RET_EINVAL;
815   }
816
817   auto* info = static_cast<aul::ResolveInfo*>(h);
818   auto& value = info->GetOperation();
819   *operation = strdup(value.empty() ? "NULL" : value.c_str());
820   if (*operation == nullptr) {
821     _E("Failed to duplicate operation");
822     return AUL_SVC_RET_ERROR;
823   }
824
825   return AUL_SVC_RET_OK;
826 }
827
828 extern "C" API int aul_svc_info_get_uri(aul_svc_info_h h, char** uri) {
829   if (h == nullptr || uri == nullptr) {
830     _E("Invalid parameter");
831     return AUL_SVC_RET_EINVAL;
832   }
833
834   auto* info = static_cast<aul::ResolveInfo*>(h);
835   auto& value = info->GetUri();
836   *uri = strdup(value.empty() ? "NULL" : value.c_str());
837   if (*uri == nullptr) {
838     _E("Failed to duplicate URI");
839     return AUL_SVC_RET_ERROR;
840   }
841
842   return AUL_SVC_RET_OK;
843 }
844
845 extern "C" API int aul_svc_info_get_uri_scheme(aul_svc_info_h h,
846     char** uri_scheme) {
847   if (h == nullptr || uri_scheme == nullptr) {
848     _E("Invalid parameter");
849     return AUL_SVC_RET_EINVAL;
850   }
851
852   auto* info = static_cast<aul::ResolveInfo*>(h);
853   auto& value = info->GetScheme();
854   *uri_scheme = strdup(value.empty() ? "NULL" : value.c_str());
855   if (*uri_scheme == nullptr) {
856     _E("Failed to duplicate URI scheme");
857     return AUL_SVC_RET_ERROR;
858   }
859
860   return AUL_SVC_RET_OK;
861 }
862
863 extern "C" API int aul_svc_info_get_uri_host(aul_svc_info_h h,
864     char** uri_host) {
865   if (h == nullptr || uri_host == nullptr) {
866     _E("Invalid parameter");
867     return AUL_SVC_RET_EINVAL;
868   }
869
870   auto* info = static_cast<aul::ResolveInfo*>(h);
871   auto& value = info->GetHost();
872   *uri_host = strdup(value.empty() ? "NULL" : value.c_str());
873   if (*uri_host == nullptr) {
874     _E("Failed to duplicate URI host");
875     return AUL_SVC_RET_ERROR;
876   }
877
878   return AUL_SVC_RET_OK;
879 }
880
881 extern "C" API int aul_svc_info_get_mime(aul_svc_info_h h, char** mime) {
882   if (h == nullptr || mime == nullptr) {
883     _E("Invalid parameter");
884     return AUL_SVC_RET_EINVAL;
885   }
886
887   auto* info = static_cast<aul::ResolveInfo*>(h);
888   auto& value = info->GetMime();
889   *mime = strdup(value.empty() ? "NULL" : value.c_str());
890   if (*mime == nullptr) {
891     _E("Failed to duplicate MIME-Type");
892     return AUL_SVC_RET_ERROR;
893   }
894
895   return AUL_SVC_RET_OK;
896 }
897
898 extern "C" API int aul_svc_info_get_mime_type(aul_svc_info_h h,
899     char** mime_type) {
900   if (h == nullptr || mime_type == nullptr) {
901     _E("Invalid parameter");
902     return AUL_SVC_RET_EINVAL;
903   }
904
905   auto* info = static_cast<aul::ResolveInfo*>(h);
906   auto& value = info->GetMType();
907   *mime_type = strdup(value.empty() ? "NULL" : value.c_str());
908   if (*mime_type == nullptr) {
909     _E("Failed to duplicate the type of MIME-Type");
910     return AUL_SVC_RET_ERROR;
911   }
912
913   return AUL_SVC_RET_OK;
914 }
915
916 extern "C" API int aul_svc_info_get_mime_subtype(aul_svc_info_h h,
917     char** mime_subtype) {
918   if (h == nullptr || mime_subtype == nullptr) {
919     _E("Invalid parameter");
920     return AUL_SVC_RET_EINVAL;
921   }
922
923   auto* info = static_cast<aul::ResolveInfo*>(h);
924   auto& value = info->GetSType();
925   *mime_subtype = strdup(value.empty() ? "NULL" : value.c_str());
926   if (*mime_subtype == nullptr) {
927     _E("Failed to duplicate the subtype of MIME-Type");
928     return AUL_SVC_RET_ERROR;
929   }
930
931   return AUL_SVC_RET_OK;
932 }
933
934 extern "C" API int aul_svc_info_destroy(aul_svc_info_h h) {
935   if (h == nullptr) {
936     _E("Invalid parameter");
937     return AUL_SVC_RET_EINVAL;
938   }
939
940   auto* info = static_cast<aul::ResolveInfo*>(h);
941   delete info;
942   return AUL_SVC_RET_OK;
943 }
944
945 extern "C" API int aul_svc_set_caller_instance_id(bundle* b,
946     const char* instance_id) {
947   if (b == nullptr) {
948     _E("Invalid parameter");
949     return AUL_SVC_RET_EINVAL;
950   }
951
952   return ::SetBundle(b, AUL_K_CALLER_INSTANCE_ID, instance_id);
953 }
954
955 extern "C" API int aul_svc_set_comp_id(bundle* b, const char* comp_id) {
956   if (b == nullptr) {
957     _E("Invalid parameter");
958     return AUL_SVC_RET_EINVAL;
959   }
960
961   return ::SetBundle(b, AUL_K_COMPONENT_ID, comp_id);
962 }
963
964 extern "C" API const char *aul_svc_get_comp_id(bundle* b) {
965   return bundle_get_val(b, AUL_K_COMPONENT_ID);
966 }
967
968 extern "C" API int aul_svc_subapp_terminate_request(bundle* b, int pid) {
969   if (b == nullptr || pid < 0) {
970     _E("Invalid parameter");
971     return AUL_SVC_RET_EINVAL;
972   }
973
974   const char* inst_id = bundle_get_val(b, AUL_K_INSTANCE_ID);
975   if (inst_id == nullptr) {
976     _E("Invalid parameter");
977     return AUL_SVC_RET_EINVAL;
978   }
979
980   char buf[512] = { 0, };
981   const char* caller_inst_id = bundle_get_val(b, AUL_K_CALLER_INSTANCE_ID);
982   if (caller_inst_id == nullptr) {
983     int ret = aul_app_get_instance_id_bypid(getpid(), buf, sizeof(buf));
984     if (ret != AUL_R_OK) {
985       _E("aul_app_get_instance_id_bypid() is failed. error(%d)", ret);
986       return AUL_SVC_RET_ERROR;
987     }
988
989     caller_inst_id = buf;
990   }
991
992   int cnt = 0;
993   aul_app_group_foreach_group_info(caller_inst_id,
994       [](aul_app_group_info_h info, void* data) {
995       int* count = static_cast<int*>(data);
996       (*count)++;
997       }, static_cast<void*>(&cnt));
998   if (cnt == 0)
999     return aul_subapp_terminate_request(inst_id, pid);
1000
1001   return aul_app_group_clear_top();
1002 }
1003
1004 extern "C" API int aul_svc_send_resume_request(bundle* b, int request_code,
1005     aul_svc_err_cb err_cb, void *user_data) {
1006   return aul_svc_send_resume_request_for_uid(b, request_code, err_cb, user_data,
1007       getuid());
1008 }
1009
1010 extern "C" API int aul_svc_send_resume_request_for_uid(bundle* b,
1011     int request_code, aul_svc_err_cb err_cb, void* user_data, uid_t uid) {
1012   if (b == nullptr || err_cb == nullptr) {
1013     _E("Invalid parameter");
1014     return AUL_SVC_RET_EINVAL;
1015   }
1016
1017   auto* cb_info = new (std::nothrow) CbInfo(request_code, nullptr, err_cb,
1018       user_data);
1019   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
1020       [](const std::string& appid, bundle* request, uid_t uid,
1021           CbInfo* info) -> int {
1022         return aul_send_resume_request_for_uid(appid.c_str(), request, uid,
1023             ErrorCb, info);
1024       }, b, uid, cb_info);
1025   if (ret < 0) {
1026     delete cb_info;
1027     ret = ::AulErrorConvert(ret);
1028   }
1029
1030   return ret;
1031 }
1032
1033 extern "C" API int aul_svc_get_appid_array(bundle* b, uid_t uid,
1034     char*** appid_array, unsigned int* len) {
1035   if (b == nullptr || appid_array == nullptr || len == nullptr) {
1036     _E("Invalid parameter");
1037     return AUL_SVC_RET_EINVAL;
1038   }
1039
1040   bundle_del(b, AUL_K_APPID);
1041   bundle_add(b, AUL_K_APPID, "@UNKNOWN");
1042
1043   bundle* response;
1044   int ret = ::SendAndReceive(APP_GET_APPID_LIST, uid, b, &response);
1045   if (ret != AUL_SVC_RET_OK)
1046     return ret;
1047
1048   tizen_base::Bundle res(response, false, true);
1049   auto str = res.GetString(AUL_SVC_K_URI_R_INFO);
1050   if (!str.empty())
1051     ::SetBundle(b, AUL_SVC_K_URI_R_INFO, str.c_str());
1052
1053   auto str_arr = res.GetStringArray(AUL_K_APPID_LIST);
1054   if (str_arr.empty()) {
1055     _E("Failed to get appid list");
1056     return AUL_SVC_RET_ERROR;
1057   }
1058
1059   *appid_array = reinterpret_cast<char**>(
1060       calloc(str_arr.size(), sizeof(char*)));
1061   if (*appid_array == nullptr) {
1062     _E("Out of memory");
1063     return AUL_SVC_RET_ENOMEM;
1064   }
1065
1066   *len = str_arr.size();
1067
1068   int i = 0;
1069   for (auto& appid : str_arr)
1070     (*appid_array)[i++] = strdup(appid.c_str());
1071
1072   return AUL_SVC_RET_OK;
1073 }
1074
1075 extern "C" API void aul_svc_free_appid_array(char** appid_array,
1076     unsigned int len) {
1077   if (appid_array == nullptr)
1078     return;
1079
1080   for (unsigned int i = 0; i < len; ++i)
1081     free(appid_array[i]);
1082
1083   free(appid_array);
1084 }
1085
1086 extern "C" API int aul_svc_set_defapp(const char* op, const char* mime_type,
1087     const char* uri, const char* defapp) {
1088   DEPRECATION_WARNING();
1089   return AUL_SVC_RET_OK;
1090 }
1091
1092 extern "C" API int aul_svc_set_defapp_for_uid(const char* op,
1093     const char* mime_type, const char* uri, const char* defapp, uid_t uid) {
1094   DEPRECATION_WARNING();
1095   return AUL_SVC_RET_OK;
1096 }
1097
1098 extern "C" API int aul_svc_unset_defapp(const char* defapp) {
1099   DEPRECATION_WARNING();
1100   return AUL_SVC_RET_OK;
1101 }
1102
1103 extern "C" API int aul_svc_unset_defapp_for_uid(const char* defapp, uid_t uid) {
1104   DEPRECATION_WARNING();
1105   return AUL_SVC_RET_OK;
1106 }
1107
1108 extern "C" API int aul_svc_unset_all_defapps(void) {
1109   DEPRECATION_WARNING();
1110   return AUL_SVC_RET_OK;
1111 }
1112
1113 extern "C" API int aul_svc_unset_all_defapps_for_uid(uid_t uid) {
1114   DEPRECATION_WARNING();
1115   return AUL_SVC_RET_OK;
1116 }
1117
1118 extern "C" API int aul_svc_is_defapp(const char* pkg_name) {
1119   DEPRECATION_WARNING();
1120   return AUL_SVC_RET_OK;
1121 }
1122
1123 extern "C" API int aul_svc_is_defapp_for_uid(const char* pkg_name, uid_t uid) {
1124   DEPRECATION_WARNING();
1125   return AUL_SVC_RET_OK;
1126 }
1127
1128 extern "C" API int aul_svc_set_alias_appid(const char* alias_appid,
1129     const char* appid) {
1130   DEPRECATION_WARNING();
1131   return AUL_SVC_RET_OK;
1132 }
1133
1134 extern "C" API int aul_svc_set_alias_appid_for_uid(const char* alias_appid,
1135     const char* appid, uid_t uid) {
1136   DEPRECATION_WARNING();
1137   return AUL_SVC_RET_OK;
1138 }
1139
1140 extern "C" API int aul_svc_unset_alias_appid(const char* alias_appid) {
1141   DEPRECATION_WARNING();
1142   return AUL_SVC_RET_OK;
1143 }
1144
1145 extern "C" API int aul_svc_unset_alias_appid_for_uid(const char* alias_appid,
1146     uid_t uid) {
1147   DEPRECATION_WARNING();
1148   return AUL_SVC_RET_OK;
1149 }
1150
1151 extern "C" API int aul_svc_foreach_alias_info(
1152     void (*callback)(const char *, const char *, void *),
1153     void* user_data) {
1154   DEPRECATION_WARNING();
1155   return AUL_SVC_RET_OK;
1156 }
1157
1158 extern "C" API int aul_svc_foreach_alias_info_for_uid(
1159     void (*callback)(const char *, const char *, void *),
1160     uid_t uid, void* user_data) {
1161   DEPRECATION_WARNING();
1162   return AUL_SVC_RET_OK;
1163 }
1164
1165 extern "C" API int aul_svc_enable_alias_info(const char* appid) {
1166   DEPRECATION_WARNING();
1167   return AUL_SVC_RET_OK;
1168 }
1169
1170 extern "C" API int aul_svc_enable_alias_info_for_uid(const char* appid,
1171     uid_t uid) {
1172   DEPRECATION_WARNING();
1173   return AUL_SVC_RET_OK;
1174 }
1175
1176 extern "C" API int aul_svc_disable_alias_info(const char* appid) {
1177   DEPRECATION_WARNING();
1178   return AUL_SVC_RET_OK;
1179 }
1180
1181 extern "C" API int aul_svc_disable_alias_info_for_uid(const char* appid,
1182     uid_t uid) {
1183   DEPRECATION_WARNING();
1184   return AUL_SVC_RET_OK;
1185 }
1186
1187 extern "C" API int aul_svc_foreach_alias_info_by_appid(
1188     int (*callback)(const char *, const char *, void *),
1189     const char* appid, void* user_data) {
1190   DEPRECATION_WARNING();
1191   return AUL_SVC_RET_OK;
1192 }
1193
1194 extern "C" API int aul_svc_foreach_alias_info_by_appid_for_uid(
1195     int (*callback)(const char *, const char *, void *),
1196     const char* appid, uid_t uid, void* user_data) {
1197   DEPRECATION_WARNING();
1198   return AUL_SVC_RET_OK;
1199 }
1200
1201 extern "C" API int aul_svc_foreach_allowed_info(
1202     int (*callback)(const char *, const char *, void *),
1203     void* user_data) {
1204   DEPRECATION_WARNING();
1205   return AUL_SVC_RET_OK;
1206 }
1207
1208 extern "C" API int aul_svc_foreach_allowed_info_for_uid(
1209     int (*callback)(const char *, const char *, void *),
1210     uid_t uid, void* user_data) {
1211   DEPRECATION_WARNING();
1212   return AUL_SVC_RET_OK;
1213 }
1214
1215 extern "C" API int aul_svc_foreach_allowed_info_by_appid(
1216     int (*callback)(const char *, const char *, void *),
1217     const char* appid, void* user_data) {
1218   DEPRECATION_WARNING();
1219   return AUL_SVC_RET_OK;
1220 }
1221
1222 extern "C" API int aul_svc_foreach_allowed_info_by_appid_for_uid(
1223     int (*callback)(const char *, const char *, void *),
1224     const char* appid, uid_t uid, void* user_data) {
1225   DEPRECATION_WARNING();
1226   return AUL_SVC_RET_OK;
1227 }