Fix aul_svc_set_instance_id() function
[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     if (pkt->cmd == APP_GET_INFO_ERROR)
285       return AUL_SVC_RET_ERROR;
286
287     return AulErrorConvert(aul_error_convert(pkt->cmd));
288   }
289
290   bundle* b = nullptr;
291   if (pkt->opt & AUL_SOCK_BUNDLE) {
292     b = bundle_decode(pkt->data, pkt->len);
293     if (b == nullptr) {
294       _E("bundle_decode() is failed");
295       return AUL_SVC_RET_ENOMEM;
296     }
297   } else {
298     _E("Invalid packet");
299     return AUL_SVC_RET_ERROR;
300   }
301
302   *response = b;
303   return AUL_SVC_RET_OK;
304 }
305
306 }  // namespace
307
308 extern "C" API int aul_svc_set_operation(bundle* b, const char* operation) {
309   if (b == nullptr) {
310     _E("Invalid parameter");
311     return AUL_SVC_RET_EINVAL;
312   }
313
314   return ::SetBundle(b, AUL_SVC_K_OPERATION, operation);
315 }
316
317 extern "C" API int aul_svc_set_uri(bundle* b, const char* uri) {
318   if (b == nullptr) {
319     _E("Invalid parameter");
320     return AUL_SVC_RET_EINVAL;
321   }
322
323   return ::SetBundle(b, AUL_SVC_K_URI, uri);
324 }
325
326 extern "C" API int aul_svc_set_mime(bundle* b, const char* mime) {
327   if (b == nullptr) {
328     _E("Invalid parameter");
329     return AUL_SVC_RET_EINVAL;
330   }
331
332   return ::SetBundle(b, AUL_SVC_K_MIME, mime);
333 }
334
335 extern "C" API int aul_svc_add_data(bundle* b, const char* key,
336     const char* value) {
337   if (b == nullptr || key == nullptr)
338     return AUL_SVC_RET_EINVAL;
339
340   return ::SetBundle(b, key, value);
341 }
342
343 extern "C" API int aul_svc_add_data_array(bundle* b, const char* key,
344     const char** value, int len) {
345   if (b == nullptr || key == nullptr)
346     return AUL_SVC_RET_EINVAL;
347
348   return ::SetBundleArray(b, key, value, len);
349 }
350
351 extern "C" API int aul_svc_set_pkgname(bundle* b, const char* pkg_name) {
352   if (b == nullptr) {
353     _E("Invalid parameter");
354     return AUL_SVC_RET_EINVAL;
355   }
356
357   return ::SetBundle(b, AUL_SVC_K_PKG_NAME, pkg_name);
358 }
359
360 extern "C" API int aul_svc_set_appid(bundle* b, const char* appid) {
361   if (b == nullptr || appid == nullptr) {
362     _E("Invalid parameter");
363     return AUL_SVC_RET_EINVAL;
364   }
365
366   std::string alias_id = ::GetAliasAppId(appid);
367   if (!alias_id.empty())
368     appid = alias_id.c_str();
369
370   return ::SetBundle(b, AUL_SVC_K_PKG_NAME, appid);
371 }
372
373 extern "C" API int aul_svc_set_category(bundle* b, const char* category) {
374   if (b == nullptr) {
375     _E("Invalid parameter");
376     return AUL_SVC_RET_EINVAL;
377   }
378
379   return ::SetBundle(b, AUL_SVC_K_CATEGORY, category);
380 }
381
382 extern "C" API int aul_svc_set_launch_mode(bundle* b, const char* mode) {
383   if (b == nullptr) {
384     _E("Invalid parameter");
385     return AUL_SVC_RET_EINVAL;
386   }
387
388   return ::SetBundle(b, AUL_SVC_K_LAUNCH_MODE, mode);
389 }
390
391 extern "C" API int aul_svc_resolve(bundle* b, uid_t uid, char*** appid_array,
392     unsigned int* len) {
393   return aul_svc_get_appid_array(b, uid, appid_array, len);
394 }
395
396 extern "C" API int aul_svc_run_service(bundle* b, int request_code,
397     aul_svc_res_fn cbfunc, void* data) {
398   return aul_svc_run_service_for_uid(b, request_code, cbfunc, data, getuid());
399 }
400
401 extern "C" API int aul_svc_run_service_for_uid(bundle* b, int request_code,
402   aul_svc_res_fn cbfunc, void* data, uid_t uid) {
403   CbInfo* cb_info = nullptr;
404   if (cbfunc)
405     cb_info = new (std::nothrow) CbInfo(request_code, cbfunc, nullptr, data);
406
407   std::tuple<aul_svc_res_fn, void*> param { cbfunc, data };
408   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
409       [](const std::string& appid, bundle* request, uid_t uid,
410           CbInfo* cb_info) -> int {
411         int ret;
412         if (cb_info) {
413           ret = aul_launch_app_with_result_for_uid(appid.c_str(), request,
414               LaunchWithResultCb, cb_info, uid);
415          } else {
416           ret = aul_launch_app_for_uid(appid.c_str(), request, uid);
417         }
418
419         return ret;
420       }, b, uid, cb_info);
421   if (ret < 0) {
422     if (cb_info)
423       delete cb_info;
424
425     ret = AulErrorConvert(ret);
426   }
427
428   return ret;
429 }
430
431 extern "C" API int aul_svc_get_list(bundle* b, aul_svc_info_iter_fn iter_fn,
432     void* data) {
433   return aul_svc_get_list_for_uid(b, iter_fn, data, getuid());
434 }
435
436 extern "C" API int aul_svc_get_list_for_uid(bundle* b,
437     aul_svc_info_iter_fn iter_fn, void* data, uid_t uid) {
438   if (b == nullptr || iter_fn == nullptr) {
439     _E("Invalid parameter");
440     return AUL_SVC_RET_EINVAL;
441   }
442
443   char** appid_array = nullptr;
444   unsigned int len = 0;
445   int ret = aul_svc_get_appid_array(b, uid, &appid_array, &len);
446   if (ret != AUL_SVC_RET_OK)
447     return ret;
448
449   if (len == 0) {
450     _E("Failed to find associated application");
451     aul_svc_free_appid_array(appid_array, len);
452     return AUL_SVC_RET_ENOMATCH;
453   }
454
455   for (unsigned int i = 0; i < len; ++i) {
456     SECURE_LOGD("APPID: %s", appid_array[i]);
457     if (iter_fn(appid_array[i], data) != 0)
458       break;
459   }
460
461   aul_svc_free_appid_array(appid_array, len);
462   return AUL_SVC_RET_OK;
463 }
464
465 extern "C" API int aul_svc_get_all_defapps(aul_svc_info_iter_fn iter_fn,
466     void* data) {
467   return aul_svc_get_all_defapps_for_uid(iter_fn, data, getuid());
468 }
469
470 extern "C" API int aul_svc_get_all_defapps_for_uid(aul_svc_info_iter_fn iter_fn,
471     void* data, uid_t uid) {
472   if (iter_fn == nullptr) {
473     _E("Invalid parameter");
474     return AUL_SVC_RET_EINVAL;
475   }
476
477   bundle* response;
478   tizen_base::Bundle request;
479   int ret = ::SendAndReceive(APP_GET_APP_CONTROL_DEFAULT_APPS, uid,
480       request.GetHandle(), &response);
481   if (ret != AUL_SVC_RET_OK)
482     return ret;
483
484   tizen_base::Bundle res(response, false, true);
485   auto appid_array = res.GetStringArray(AUL_K_APPID_LIST);
486   if (appid_array.size() == 0)
487     return AUL_SVC_RET_ERROR;
488
489   for (auto& appid : appid_array) {
490     if (iter_fn(appid.c_str(), data) != 0)
491       break;
492   }
493
494   return AUL_SVC_RET_OK;
495 }
496
497 extern "C" API const char* aul_svc_get_operation(bundle* b) {
498   return bundle_get_val(b, AUL_SVC_K_OPERATION);
499 }
500
501 extern "C" API const char* aul_svc_get_uri(bundle* b) {
502   return bundle_get_val(b, AUL_SVC_K_URI);
503 }
504
505 extern "C" API const char* aul_svc_get_mime(bundle* b) {
506   return bundle_get_val(b, AUL_SVC_K_MIME);
507 }
508
509 extern "C" API const char* aul_svc_get_data(bundle* b, const char* key) {
510   return bundle_get_val(b, key);
511 }
512
513 extern "C" API const char** aul_svc_get_data_array(bundle* b, const char* key,
514     int* len) {
515   return bundle_get_str_array(b, key, len);
516 }
517
518 extern "C" API const char* aul_svc_get_pkgname(bundle* b) {
519   return bundle_get_val(b, AUL_SVC_K_PKG_NAME);
520 }
521
522 extern "C" API const char* aul_svc_get_appid(bundle* b) {
523   return bundle_get_val(b, AUL_SVC_K_PKG_NAME);
524 }
525
526 extern "C" API const char* aul_svc_get_category(bundle* b) {
527   return bundle_get_val(b, AUL_SVC_K_CATEGORY);
528 }
529
530 extern "C" API const char* aul_svc_get_launch_mode(bundle* b) {
531   return bundle_get_val(b, AUL_SVC_K_LAUNCH_MODE);
532 }
533
534 extern "C" API int aul_svc_create_result_bundle(bundle* inb, bundle** outb) {
535   if (inb == nullptr || outb == nullptr) {
536     _E("Invalid parameter");
537     return AUL_SVC_RET_EINVAL;
538   }
539
540   int ret = aul_create_result_bundle(inb, outb);
541   if (ret != AUL_R_OK)
542     return AulErrorConvert(ret);
543
544   return AUL_SVC_RET_OK;
545 }
546
547 extern "C" API int aul_svc_send_result(bundle* b, aul_svc_result_val result) {
548   if (b == nullptr) {
549     _E("Invalid parameter");
550     return AUL_SVC_RET_EINVAL;
551   }
552
553   int ret = ::SetBundle(b, AUL_SVC_K_RES_VAL, std::to_string(result).c_str());
554   if (ret < 0)
555     return AUL_SVC_RET_ERROR;
556
557   if (result == AUL_SVC_RES_CANCEL)
558     ret = aul_send_result(b, 1);
559   else
560     ret = aul_send_result(b, 0);
561
562   bundle_del(b, AUL_SVC_K_RES_VAL);
563   return ret;
564 }
565
566 extern "C" API int aul_svc_data_is_array(bundle* b, const char* key) {
567   int type = bundle_get_type(b, key);
568   if (type <= 0)
569     return 0;
570
571   if (type & BUNDLE_TYPE_ARRAY)
572     return 1;
573
574   return 0;
575 }
576
577 extern "C" API int aul_svc_allow_transient_app(bundle* b, int wid) {
578   if (b == nullptr) {
579     _E("Invalid parameter");
580     return AUL_SVC_RET_EINVAL;
581   }
582
583   return ::SetBundle(b, AUL_SVC_K_WIN_ID, std::to_string(wid).c_str());
584 }
585
586 extern "C" API int aul_svc_request_transient_app(bundle* b, int callee_wid,
587     aul_svc_host_res_fn cbfunc, void* data) {
588   return 0;
589 }
590
591 extern "C" API int aul_svc_subapp_terminate_request_pid(int pid) {
592   int cpid = getpid();
593   int lcnt;
594   int* lpids = nullptr;
595   aul_app_group_get_leader_pids(&lcnt, &lpids);
596   for (int i = 0; i < lcnt; ++i) {
597     if (lpids[i] == cpid) {
598       int cnt;
599       int* pids = nullptr;
600       aul_app_group_get_group_pids(cpid, &cnt, &pids);
601       if (cnt == 0) {
602         free(lpids);
603         if (pids)
604           free(pids);
605
606         return aul_subapp_terminate_request_pid(pid);
607       }
608
609       if (pids != nullptr)
610         free(pids);
611       break;
612     }
613   }
614
615   if (lpids != nullptr)
616     free(lpids);
617
618   return aul_app_group_clear_top();
619 }
620
621 extern "C" API int aul_send_service_result(bundle* b) {
622   return aul_send_result(b, 0);
623 }
624
625 extern "C" API int aul_svc_subscribe_launch_result(bundle* b,
626     const char* result) {
627   if (b == nullptr) {
628     _E("Invalid parameter");
629     return AUL_SVC_RET_EINVAL;
630   }
631
632   return ::SetBundle(b, result, "1");
633 }
634
635 extern "C" API int aul_svc_set_loader_id(bundle* b, int loader_id) {
636   if (b == nullptr || loader_id <= 0) {
637     _E("Invalid parameter");
638     return AUL_SVC_RET_EINVAL;
639   }
640
641   return ::SetBundle(b, AUL_K_LOADER_ID, std::to_string(loader_id).c_str());
642 }
643
644 extern "C" API int aul_svc_set_loader_name(bundle* b, const char* loader_name) {
645   if (b == nullptr || loader_name == nullptr) {
646     _E("Invalid parameter");
647     return AUL_SVC_RET_EINVAL;
648   }
649
650   return ::SetBundle(b, AUL_K_LOADER_NAME, loader_name);
651 }
652
653 extern "C" API int aul_svc_set_background_launch(bundle* b, int enabled) {
654   if (b == nullptr) {
655     _E("Invalid parameter");
656     return AUL_SVC_RET_EINVAL;
657   }
658
659   return ::SetBundle(b, AUL_SVC_K_BG_LAUNCH, enabled ? "enable" : nullptr);
660 }
661
662 extern "C" API int aul_svc_get_appid_by_alias_appid(const char* alias_appid,
663     char** appid) {
664   return aul_svc_get_appid_by_alias_appid_for_uid(alias_appid, appid, getuid());
665 }
666
667 extern "C" API int aul_svc_get_appid_by_alias_appid_for_uid(
668     const char* alias_appid, char** appid, uid_t uid) {
669   if (alias_appid == nullptr || appid == nullptr) {
670     _E("Invalid parameter");
671     return AUL_SVC_RET_EINVAL;
672   }
673
674   bundle* response;
675   tizen_base::Bundle request;
676   request.Add(AUL_K_ALIAS_APPID, alias_appid);
677   int ret = ::SendAndReceive(APP_GET_APPID_BY_ALIAS_APPID, uid,
678       request.GetHandle(), &response);
679   if (ret != AUL_SVC_RET_OK)
680     return ret;
681
682   tizen_base::Bundle res(response, false, true);
683   auto val = res.GetString(AUL_K_APPID);
684   if (val.empty())
685     return AUL_SVC_RET_ERROR;
686
687   *appid = strdup(val.c_str());
688   if (*appid == nullptr) {
689     _E("Out of memory");
690     return AUL_SVC_RET_ENOMEM;
691   }
692
693   return AUL_SVC_RET_OK;
694 }
695
696 extern "C" API const char *aul_svc_get_instance_id(bundle* b) {
697   return bundle_get_val(b, AUL_K_INSTANCE_ID);
698 }
699
700 extern "C" API int aul_svc_set_instance_id(bundle* b, const char* instance_id) {
701   if (b == nullptr) {
702     _E("Invalid parameter");
703     return AUL_SVC_RET_EINVAL;
704   }
705
706   return ::SetBundle(b, AUL_K_INSTANCE_ID, instance_id);
707 }
708
709 extern "C" API int aul_svc_run_service_async(bundle* b, int request_code,
710     aul_svc_res_fn cbfunc, void* data) {
711   return aul_svc_run_service_async_for_uid(b, request_code, cbfunc, data,
712       getuid());
713 }
714
715 extern "C" API int aul_svc_run_service_async_for_uid(bundle* b,
716     int request_code, aul_svc_res_fn cbfunc, void* data, uid_t uid) {
717   CbInfo* cb_info = nullptr;
718   if (cbfunc)
719     cb_info = new (std::nothrow) CbInfo(request_code, cbfunc, nullptr, data);
720
721   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
722       [](const std::string& appid, bundle* request, uid_t uid,
723           CbInfo* info) -> int {
724         if (info) {
725           return aul_launch_app_with_result_async_for_uid(appid.c_str(),
726               request, LaunchWithResultCb, info, uid);
727         }
728
729         return aul_launch_app_async_for_uid(appid.c_str(), request, uid);
730       }, b, uid, cb_info);
731   if (ret < 0) {
732     if (cb_info)
733       delete cb_info;
734
735     ret = AulErrorConvert(ret);
736   }
737
738   return ret;
739 }
740
741 extern "C" API int aul_svc_send_launch_request(bundle* b, int request_code,
742     aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb, void* user_data) {
743   return aul_svc_send_launch_request_for_uid(b, request_code,
744       cbfunc, err_cb, user_data, getuid());
745 }
746
747 extern "C" API int aul_svc_send_launch_request_for_uid(bundle* b,
748     int request_code, aul_svc_res_fn cbfunc, aul_svc_err_cb err_cb,
749     void* user_data, uid_t uid) {
750   if (b == nullptr || err_cb == nullptr) {
751     _E("Invalid parameter");
752     return AUL_SVC_RET_EINVAL;
753   }
754
755   CbInfo* cb_info = new (std::nothrow) CbInfo(request_code, cbfunc, err_cb,
756       user_data);
757   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
758       [](const std::string& appid, bundle* request, uid_t uid,
759         CbInfo* info) -> int {
760         return aul_send_launch_request_for_uid(appid.c_str(), request, uid,
761             info->res_fn_ ? ::LaunchWithResultCb : nullptr, ::ErrorCb, info);
762       }, b, uid, cb_info);
763   if (ret < 0) {
764     delete cb_info;
765     ret = ::AulErrorConvert(ret);
766   }
767
768   return ret;
769 }
770
771 extern "C" API int aul_svc_send_launch_request_sync_for_uid(bundle* b,
772     int request_code, bundle** res_b, aul_svc_result_val* res, uid_t uid) {
773   if (b == nullptr || res_b == nullptr || res == nullptr) {
774     _E("Invalid parameter");
775     return AUL_SVC_RET_EINVAL;
776   }
777
778   int ret = ::SendLaunchRequest<::SendLaunchRequestSyncCb, bundle**>(
779       [](const std::string& appid, bundle* request, uid_t uid,
780           bundle** response) -> int {
781         return aul_send_launch_request_sync_for_uid(appid.c_str(), request,
782             uid, response);
783       }, b, uid, res_b);
784   if (ret > 0) {
785     auto* val = bundle_get_val(*res_b, AUL_SVC_K_RES_VAL);
786     *res = static_cast<aul_svc_result_val>(
787         (val == nullptr) ? AUL_SVC_RES_NOT_OK : atoi(val));
788   } else {
789     ret = ::AulErrorConvert(ret);
790     *res = AUL_SVC_RES_CANCEL;
791   }
792
793   return ret;
794 }
795
796 extern "C" API int aul_svc_info_create(bundle* b, aul_svc_info_h* h) {
797   if (b == nullptr || h == nullptr) {
798     _E("Invalid parameter");
799     return AUL_SVC_RET_EINVAL;
800   }
801
802   aul::ResolveInfo* resolve_info = nullptr;
803   try {
804     tizen_base::Bundle kb(b, false, false);
805     resolve_info = aul::ResolveInfo::Manager::Create(kb);
806   } catch (aul::Exception& e) {
807     return AUL_SVC_RET_ERROR;
808   }
809
810   *h = static_cast<aul_svc_info_h>(resolve_info);
811   return AUL_SVC_RET_OK;
812 }
813
814 extern "C" API int aul_svc_info_get_operation(aul_svc_info_h h,
815     char** operation) {
816   if (h == nullptr || operation == nullptr) {
817     _E("Invalid parameter");
818     return AUL_SVC_RET_EINVAL;
819   }
820
821   auto* info = static_cast<aul::ResolveInfo*>(h);
822   auto& value = info->GetOperation();
823   *operation = strdup(value.empty() ? "NULL" : value.c_str());
824   if (*operation == nullptr) {
825     _E("Failed to duplicate operation");
826     return AUL_SVC_RET_ERROR;
827   }
828
829   return AUL_SVC_RET_OK;
830 }
831
832 extern "C" API int aul_svc_info_get_uri(aul_svc_info_h h, char** uri) {
833   if (h == nullptr || uri == nullptr) {
834     _E("Invalid parameter");
835     return AUL_SVC_RET_EINVAL;
836   }
837
838   auto* info = static_cast<aul::ResolveInfo*>(h);
839   auto& value = info->GetUri();
840   *uri = strdup(value.empty() ? "NULL" : value.c_str());
841   if (*uri == nullptr) {
842     _E("Failed to duplicate URI");
843     return AUL_SVC_RET_ERROR;
844   }
845
846   return AUL_SVC_RET_OK;
847 }
848
849 extern "C" API int aul_svc_info_get_uri_scheme(aul_svc_info_h h,
850     char** uri_scheme) {
851   if (h == nullptr || uri_scheme == nullptr) {
852     _E("Invalid parameter");
853     return AUL_SVC_RET_EINVAL;
854   }
855
856   auto* info = static_cast<aul::ResolveInfo*>(h);
857   auto& value = info->GetScheme();
858   *uri_scheme = strdup(value.empty() ? "NULL" : value.c_str());
859   if (*uri_scheme == nullptr) {
860     _E("Failed to duplicate URI scheme");
861     return AUL_SVC_RET_ERROR;
862   }
863
864   return AUL_SVC_RET_OK;
865 }
866
867 extern "C" API int aul_svc_info_get_uri_host(aul_svc_info_h h,
868     char** uri_host) {
869   if (h == nullptr || uri_host == nullptr) {
870     _E("Invalid parameter");
871     return AUL_SVC_RET_EINVAL;
872   }
873
874   auto* info = static_cast<aul::ResolveInfo*>(h);
875   auto& value = info->GetHost();
876   *uri_host = strdup(value.empty() ? "NULL" : value.c_str());
877   if (*uri_host == nullptr) {
878     _E("Failed to duplicate URI host");
879     return AUL_SVC_RET_ERROR;
880   }
881
882   return AUL_SVC_RET_OK;
883 }
884
885 extern "C" API int aul_svc_info_get_mime(aul_svc_info_h h, char** mime) {
886   if (h == nullptr || mime == nullptr) {
887     _E("Invalid parameter");
888     return AUL_SVC_RET_EINVAL;
889   }
890
891   auto* info = static_cast<aul::ResolveInfo*>(h);
892   auto& value = info->GetMime();
893   *mime = strdup(value.empty() ? "NULL" : value.c_str());
894   if (*mime == nullptr) {
895     _E("Failed to duplicate MIME-Type");
896     return AUL_SVC_RET_ERROR;
897   }
898
899   return AUL_SVC_RET_OK;
900 }
901
902 extern "C" API int aul_svc_info_get_mime_type(aul_svc_info_h h,
903     char** mime_type) {
904   if (h == nullptr || mime_type == nullptr) {
905     _E("Invalid parameter");
906     return AUL_SVC_RET_EINVAL;
907   }
908
909   auto* info = static_cast<aul::ResolveInfo*>(h);
910   auto& value = info->GetMType();
911   *mime_type = strdup(value.empty() ? "NULL" : value.c_str());
912   if (*mime_type == nullptr) {
913     _E("Failed to duplicate the type of MIME-Type");
914     return AUL_SVC_RET_ERROR;
915   }
916
917   return AUL_SVC_RET_OK;
918 }
919
920 extern "C" API int aul_svc_info_get_mime_subtype(aul_svc_info_h h,
921     char** mime_subtype) {
922   if (h == nullptr || mime_subtype == nullptr) {
923     _E("Invalid parameter");
924     return AUL_SVC_RET_EINVAL;
925   }
926
927   auto* info = static_cast<aul::ResolveInfo*>(h);
928   auto& value = info->GetSType();
929   *mime_subtype = strdup(value.empty() ? "NULL" : value.c_str());
930   if (*mime_subtype == nullptr) {
931     _E("Failed to duplicate the subtype of MIME-Type");
932     return AUL_SVC_RET_ERROR;
933   }
934
935   return AUL_SVC_RET_OK;
936 }
937
938 extern "C" API int aul_svc_info_destroy(aul_svc_info_h h) {
939   if (h == nullptr) {
940     _E("Invalid parameter");
941     return AUL_SVC_RET_EINVAL;
942   }
943
944   auto* info = static_cast<aul::ResolveInfo*>(h);
945   delete info;
946   return AUL_SVC_RET_OK;
947 }
948
949 extern "C" API int aul_svc_set_caller_instance_id(bundle* b,
950     const char* instance_id) {
951   if (b == nullptr) {
952     _E("Invalid parameter");
953     return AUL_SVC_RET_EINVAL;
954   }
955
956   return ::SetBundle(b, AUL_K_CALLER_INSTANCE_ID, instance_id);
957 }
958
959 extern "C" API int aul_svc_set_comp_id(bundle* b, const char* comp_id) {
960   if (b == nullptr) {
961     _E("Invalid parameter");
962     return AUL_SVC_RET_EINVAL;
963   }
964
965   return ::SetBundle(b, AUL_K_COMPONENT_ID, comp_id);
966 }
967
968 extern "C" API const char *aul_svc_get_comp_id(bundle* b) {
969   return bundle_get_val(b, AUL_K_COMPONENT_ID);
970 }
971
972 extern "C" API int aul_svc_subapp_terminate_request(bundle* b, int pid) {
973   if (b == nullptr || pid < 0) {
974     _E("Invalid parameter");
975     return AUL_SVC_RET_EINVAL;
976   }
977
978   const char* inst_id = bundle_get_val(b, AUL_K_INSTANCE_ID);
979   if (inst_id == nullptr) {
980     _E("Invalid parameter");
981     return AUL_SVC_RET_EINVAL;
982   }
983
984   char buf[512] = { 0, };
985   const char* caller_inst_id = bundle_get_val(b, AUL_K_CALLER_INSTANCE_ID);
986   if (caller_inst_id == nullptr) {
987     int ret = aul_app_get_instance_id_bypid(getpid(), buf, sizeof(buf));
988     if (ret != AUL_R_OK) {
989       _E("aul_app_get_instance_id_bypid() is failed. error(%d)", ret);
990       return AUL_SVC_RET_ERROR;
991     }
992
993     caller_inst_id = buf;
994   }
995
996   int cnt = 0;
997   aul_app_group_foreach_group_info(caller_inst_id,
998       [](aul_app_group_info_h info, void* data) {
999       int* count = static_cast<int*>(data);
1000       (*count)++;
1001       }, static_cast<void*>(&cnt));
1002   if (cnt == 0)
1003     return aul_subapp_terminate_request(inst_id, pid);
1004
1005   return aul_app_group_clear_top();
1006 }
1007
1008 extern "C" API int aul_svc_send_resume_request(bundle* b, int request_code,
1009     aul_svc_err_cb err_cb, void *user_data) {
1010   return aul_svc_send_resume_request_for_uid(b, request_code, err_cb, user_data,
1011       getuid());
1012 }
1013
1014 extern "C" API int aul_svc_send_resume_request_for_uid(bundle* b,
1015     int request_code, aul_svc_err_cb err_cb, void* user_data, uid_t uid) {
1016   if (b == nullptr || err_cb == nullptr) {
1017     _E("Invalid parameter");
1018     return AUL_SVC_RET_EINVAL;
1019   }
1020
1021   auto* cb_info = new (std::nothrow) CbInfo(request_code, nullptr, err_cb,
1022       user_data);
1023   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
1024       [](const std::string& appid, bundle* request, uid_t uid,
1025           CbInfo* info) -> int {
1026         return aul_send_resume_request_for_uid(appid.c_str(), request, uid,
1027             ErrorCb, info);
1028       }, b, uid, cb_info);
1029   if (ret < 0) {
1030     delete cb_info;
1031     ret = ::AulErrorConvert(ret);
1032   }
1033
1034   return ret;
1035 }
1036
1037 extern "C" API int aul_svc_get_appid_array(bundle* b, uid_t uid,
1038     char*** appid_array, unsigned int* len) {
1039   if (b == nullptr || appid_array == nullptr || len == nullptr) {
1040     _E("Invalid parameter");
1041     return AUL_SVC_RET_EINVAL;
1042   }
1043
1044   bundle_del(b, AUL_K_APPID);
1045   bundle_add(b, AUL_K_APPID, "@UNKNOWN");
1046
1047   bundle* response;
1048   int ret = ::SendAndReceive(APP_GET_APPID_LIST, uid, b, &response);
1049   if (ret != AUL_SVC_RET_OK)
1050     return ret;
1051
1052   tizen_base::Bundle res(response, false, true);
1053   auto str = res.GetString(AUL_SVC_K_URI_R_INFO);
1054   if (!str.empty())
1055     ::SetBundle(b, AUL_SVC_K_URI_R_INFO, str.c_str());
1056
1057   auto str_arr = res.GetStringArray(AUL_K_APPID_LIST);
1058   if (str_arr.empty()) {
1059     _E("Failed to get appid list");
1060     return AUL_SVC_RET_ERROR;
1061   }
1062
1063   *appid_array = reinterpret_cast<char**>(
1064       calloc(str_arr.size(), sizeof(char*)));
1065   if (*appid_array == nullptr) {
1066     _E("Out of memory");
1067     return AUL_SVC_RET_ENOMEM;
1068   }
1069
1070   *len = str_arr.size();
1071
1072   int i = 0;
1073   for (auto& appid : str_arr)
1074     (*appid_array)[i++] = strdup(appid.c_str());
1075
1076   return AUL_SVC_RET_OK;
1077 }
1078
1079 extern "C" API void aul_svc_free_appid_array(char** appid_array,
1080     unsigned int len) {
1081   if (appid_array == nullptr)
1082     return;
1083
1084   for (unsigned int i = 0; i < len; ++i)
1085     free(appid_array[i]);
1086
1087   free(appid_array);
1088 }
1089
1090 extern "C" API int aul_svc_set_defapp(const char* op, const char* mime_type,
1091     const char* uri, const char* defapp) {
1092   DEPRECATION_WARNING();
1093   return AUL_SVC_RET_OK;
1094 }
1095
1096 extern "C" API int aul_svc_set_defapp_for_uid(const char* op,
1097     const char* mime_type, const char* uri, const char* defapp, uid_t uid) {
1098   DEPRECATION_WARNING();
1099   return AUL_SVC_RET_OK;
1100 }
1101
1102 extern "C" API int aul_svc_unset_defapp(const char* defapp) {
1103   DEPRECATION_WARNING();
1104   return AUL_SVC_RET_OK;
1105 }
1106
1107 extern "C" API int aul_svc_unset_defapp_for_uid(const char* defapp, uid_t uid) {
1108   DEPRECATION_WARNING();
1109   return AUL_SVC_RET_OK;
1110 }
1111
1112 extern "C" API int aul_svc_unset_all_defapps(void) {
1113   DEPRECATION_WARNING();
1114   return AUL_SVC_RET_OK;
1115 }
1116
1117 extern "C" API int aul_svc_unset_all_defapps_for_uid(uid_t uid) {
1118   DEPRECATION_WARNING();
1119   return AUL_SVC_RET_OK;
1120 }
1121
1122 extern "C" API int aul_svc_is_defapp(const char* pkg_name) {
1123   DEPRECATION_WARNING();
1124   return AUL_SVC_RET_OK;
1125 }
1126
1127 extern "C" API int aul_svc_is_defapp_for_uid(const char* pkg_name, uid_t uid) {
1128   DEPRECATION_WARNING();
1129   return AUL_SVC_RET_OK;
1130 }
1131
1132 extern "C" API int aul_svc_set_alias_appid(const char* alias_appid,
1133     const char* appid) {
1134   DEPRECATION_WARNING();
1135   return AUL_SVC_RET_OK;
1136 }
1137
1138 extern "C" API int aul_svc_set_alias_appid_for_uid(const char* alias_appid,
1139     const char* appid, uid_t uid) {
1140   DEPRECATION_WARNING();
1141   return AUL_SVC_RET_OK;
1142 }
1143
1144 extern "C" API int aul_svc_unset_alias_appid(const char* alias_appid) {
1145   DEPRECATION_WARNING();
1146   return AUL_SVC_RET_OK;
1147 }
1148
1149 extern "C" API int aul_svc_unset_alias_appid_for_uid(const char* alias_appid,
1150     uid_t uid) {
1151   DEPRECATION_WARNING();
1152   return AUL_SVC_RET_OK;
1153 }
1154
1155 extern "C" API int aul_svc_foreach_alias_info(
1156     void (*callback)(const char *, const char *, void *),
1157     void* user_data) {
1158   DEPRECATION_WARNING();
1159   return AUL_SVC_RET_OK;
1160 }
1161
1162 extern "C" API int aul_svc_foreach_alias_info_for_uid(
1163     void (*callback)(const char *, const char *, void *),
1164     uid_t uid, void* user_data) {
1165   DEPRECATION_WARNING();
1166   return AUL_SVC_RET_OK;
1167 }
1168
1169 extern "C" API int aul_svc_enable_alias_info(const char* appid) {
1170   DEPRECATION_WARNING();
1171   return AUL_SVC_RET_OK;
1172 }
1173
1174 extern "C" API int aul_svc_enable_alias_info_for_uid(const char* appid,
1175     uid_t uid) {
1176   DEPRECATION_WARNING();
1177   return AUL_SVC_RET_OK;
1178 }
1179
1180 extern "C" API int aul_svc_disable_alias_info(const char* appid) {
1181   DEPRECATION_WARNING();
1182   return AUL_SVC_RET_OK;
1183 }
1184
1185 extern "C" API int aul_svc_disable_alias_info_for_uid(const char* appid,
1186     uid_t uid) {
1187   DEPRECATION_WARNING();
1188   return AUL_SVC_RET_OK;
1189 }
1190
1191 extern "C" API int aul_svc_foreach_alias_info_by_appid(
1192     int (*callback)(const char *, const char *, void *),
1193     const char* appid, void* user_data) {
1194   DEPRECATION_WARNING();
1195   return AUL_SVC_RET_OK;
1196 }
1197
1198 extern "C" API int aul_svc_foreach_alias_info_by_appid_for_uid(
1199     int (*callback)(const char *, const char *, void *),
1200     const char* appid, uid_t uid, void* user_data) {
1201   DEPRECATION_WARNING();
1202   return AUL_SVC_RET_OK;
1203 }
1204
1205 extern "C" API int aul_svc_foreach_allowed_info(
1206     int (*callback)(const char *, const char *, void *),
1207     void* user_data) {
1208   DEPRECATION_WARNING();
1209   return AUL_SVC_RET_OK;
1210 }
1211
1212 extern "C" API int aul_svc_foreach_allowed_info_for_uid(
1213     int (*callback)(const char *, const char *, void *),
1214     uid_t uid, void* user_data) {
1215   DEPRECATION_WARNING();
1216   return AUL_SVC_RET_OK;
1217 }
1218
1219 extern "C" API int aul_svc_foreach_allowed_info_by_appid(
1220     int (*callback)(const char *, const char *, void *),
1221     const char* appid, void* user_data) {
1222   DEPRECATION_WARNING();
1223   return AUL_SVC_RET_OK;
1224 }
1225
1226 extern "C" API int aul_svc_foreach_allowed_info_by_appid_for_uid(
1227     int (*callback)(const char *, const char *, void *),
1228     const char* appid, uid_t uid, void* user_data) {
1229   DEPRECATION_WARNING();
1230   return AUL_SVC_RET_OK;
1231 }