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