Move function definition to aul header
[platform/core/appfw/aul-1.git] / src / aul_svc.cc
index 0ad74b1..389dc50 100644 (file)
 #include <bundle.h>
 #include <bundle_cpp.h>
 #include <bundle_internal.h>
+#include <dlfcn.h>
 #include <glib.h>
 #include <iniparser.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <atomic>
 #include <memory>
+#include <mutex>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 #include "aul/app_control/resolve_info.hh"
 
 namespace {
 
+constexpr const char kPathAmdReady[] = "/run/.amd_ready";
+constexpr const char kPathLibAulServer[] = LIBDIR "/libaul-server.so.0";
+constexpr const char kAulServiceForeachUsrAliasInfo[] =
+    "aul_service_foreach_usr_alias_info";
+
 class CbInfo {
  public:
   CbInfo(int request_code, aul_svc_res_fn res_fn,
@@ -76,6 +84,64 @@ class CbInfo {
   void* user_data_;
 };
 
+class AliasInfo {
+ public:
+  explicit AliasInfo(std::string alias_appid)
+      : alias_appid_(std::move(alias_appid)) {
+  }
+
+  std::string alias_appid_;
+  std::string appid_;
+};
+
+class AppSvcAlias {
+ public:
+  AppSvcAlias() = default;
+
+  void Load() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    if (loaded_)
+      return;
+
+    dictionary* dict = iniparser_load("/usr/share/appsvc/alias.ini");
+    if (dict == nullptr) {
+      loaded_ = true;
+      return;
+    }
+
+    std::string delimiter = "Alias:";
+    for (int i = 0; i < dict->n; ++i) {
+      if (dict->key[i] == nullptr || dict->val[i] == nullptr)
+        continue;
+
+      std::string key = dict->key[i];
+      key.erase(0, key.find(delimiter) + delimiter.length() + 1);
+      std::string value = dict->val[i];
+      map_[key] = value;
+    }
+
+    iniparser_freedict(dict);
+    loaded_ = true;
+  }
+
+  std::string GetAliasAppId(const std::string& alias_appid) {
+    auto found = map_.find(alias_appid);
+    if (found == map_.end())
+      return {};
+
+    SECURE_LOGD("alias_appid: %s, appid: %s",
+        alias_appid.c_str(), found->second.c_str());
+    return found->second;
+  }
+
+ private:
+  bool loaded_ = false;
+  std::unordered_map<std::string, std::string> map_;
+  std::mutex mutex_;
+};
+
+AppSvcAlias appsvc_alias;
+
 int SetBundle(bundle* b, const char* key, const char* value) {
   if (bundle_get_type(b, key) != BUNDLE_TYPE_NONE) {
     if (bundle_del(b, key) != BUNDLE_ERROR_NONE)
@@ -111,20 +177,8 @@ int SetBundleArray(bundle* b, const char* key, const char** value,
 }
 
 std::string GetAliasAppId(const char* appid) {
-  dictionary* dic = iniparser_load("/usr/share/appsvc/alias.ini");
-  if (dic == nullptr)
-    return {};
-
-  auto dic_ptr = std::unique_ptr<dictionary, decltype(iniparser_freedict)*>(
-      dic, iniparser_freedict);
-
-  std::string key = std::string("Alias:") + appid;
-  const char* value = iniparser_getstring(dic, key.c_str(), nullptr);
-  SECURE_LOGD("appid(%s), alias_id(%s)", appid, value);
-  if (value == nullptr)
-    return {};
-
-  return std::string(value);
+  appsvc_alias.Load();
+  return appsvc_alias.GetAliasAppId(appid);
 }
 
 bool IsSpecialApp(const char* appid) {
@@ -184,7 +238,7 @@ void SetLaunchData(bundle* request, const std::string& appid) {
   const char* launch_mode = aul_svc_get_launch_mode(request);
   if (launch_mode && !strcmp(launch_mode, "group")) {
     int ret = bundle_get_type(request, AUL_K_INSTANCE_ID);
-    if (ret != BUNDLE_TYPE_NONE)
+    if (ret == BUNDLE_TYPE_NONE)
       aul_set_instance_info(appid.c_str(), request);
   }
 }
@@ -201,6 +255,10 @@ int AulErrorConvert(int res) {
     return AUL_SVC_RET_EREJECTED;
   case AUL_R_ENOAPP:
     return AUL_SVC_RET_ENOMATCH;
+  case AUL_R_ECANCELED:
+    return AUL_SVC_RET_ECANCELED;
+  case AUL_R_ETIMEOUT:
+    return AUL_SVC_RET_ETIMEOUT;
   default:
     return AUL_SVC_RET_ELAUNCH;
   }
@@ -217,9 +275,15 @@ void LaunchWithResultCb(bundle* b, int is_cancel, void* data) {
 
   bundle_del(b, AUL_SVC_K_RES_VAL);
   auto* cb_info = static_cast<CbInfo*>(data);
+  if (cb_info == nullptr) {
+    _E("Invalid parameter");
+    return;
+  }
+
   if (cb_info->res_fn_) {
     cb_info->res_fn_(b, cb_info->request_code_,
         static_cast<aul_svc_result_val>(res), cb_info->user_data_);
+    cb_info->res_fn_ = nullptr;
   }
 
   if (cb_info->err_cb_ != nullptr)
@@ -233,6 +297,11 @@ void ErrorCb(int error, void* data) {
     error = AulErrorConvert(error);
 
   auto* cb_info = static_cast<CbInfo*>(data);
+  if (cb_info == nullptr) {
+    _E("Invalid parameter");
+    return;
+  }
+
   if (cb_info->err_cb_) {
     cb_info->err_cb_(cb_info->request_code_, error, cb_info->user_data_);
     cb_info->err_cb_ = nullptr;
@@ -303,6 +372,72 @@ int SendAndReceive(int cmd, uid_t uid, bundle* request, bundle** response) {
   return AUL_SVC_RET_OK;
 }
 
+std::atomic<bool> amd_ready { false };
+bool IsAmdReady() {
+  if (amd_ready)
+    return amd_ready;
+
+  if (access(kPathAmdReady, F_OK) == 0) {
+    amd_ready.exchange(true);
+    return amd_ready;
+  }
+
+  return false;
+}
+
+using AulServiceAliasInfoCb =
+    bool (*)(const char*, const char*, void*);
+using AulServiceForeachUsrAliasInfoFunc =
+    int (*)(AulServiceAliasInfoCb, uid_t, void*);
+
+int GetAppIdByAliasAppIdFromDB(const char* alias_appid, char** app_id,
+    uid_t uid) {
+  void* handle = dlopen(kPathLibAulServer, RTLD_LAZY | RTLD_GLOBAL);
+  if (handle == nullptr) {
+    _E("dlopen() is failed. path(%s), error(%s)", kPathLibAulServer, dlerror());
+    return AUL_SVC_RET_ERROR;
+  }
+
+  auto dl_closer = [](void* ptr) {
+    dlclose(ptr);
+  };
+
+  std::unique_ptr<void, decltype(dl_closer)> handle_auto(handle, dl_closer);
+  auto* func = reinterpret_cast<AulServiceForeachUsrAliasInfoFunc>(
+      dlsym(handle, kAulServiceForeachUsrAliasInfo));
+  if (func == nullptr) {
+    _E("dlsym() is failed. error(%s)", dlerror());
+    return AUL_SVC_RET_ERROR;
+  }
+
+  AliasInfo info(alias_appid);
+  int ret = func(
+      [](const char* alias_appid, const char* appid, void* user_data) -> bool {
+        auto* info = static_cast<AliasInfo*>(user_data);
+        if (info->alias_appid_ == alias_appid) {
+          info->appid_ = appid;
+          return false;
+        }
+
+        return true;
+      }, uid, &info);
+  if (ret != 0) {
+    _E("%s() is failed. error(%d)", kAulServiceForeachUsrAliasInfo, ret);
+    return AUL_SVC_RET_ERROR;
+  }
+
+  if (info.appid_.empty())
+    return AUL_SVC_RET_ERROR;
+
+  *app_id = strdup(info.appid_.c_str());
+  if (*app_id == nullptr) {
+    _E("strdup() is failed");
+    return AUL_SVC_RET_ENOMEM;
+  }
+
+  return AUL_SVC_RET_OK;
+}
+
 }  // namespace
 
 extern "C" API int aul_svc_set_operation(bundle* b, const char* operation) {
@@ -363,9 +498,11 @@ extern "C" API int aul_svc_set_appid(bundle* b, const char* appid) {
     return AUL_SVC_RET_EINVAL;
   }
 
-  std::string alias_id = ::GetAliasAppId(appid);
-  if (!alias_id.empty())
-    appid = alias_id.c_str();
+  if (TIZEN_FEATURE_APPSVC_ALIAS) {
+    std::string alias_id = ::GetAliasAppId(appid);
+    if (!alias_id.empty())
+      return ::SetBundle(b, AUL_SVC_K_PKG_NAME, alias_id.c_str());
+  }
 
   return ::SetBundle(b, AUL_SVC_K_PKG_NAME, appid);
 }
@@ -401,8 +538,11 @@ extern "C" API int aul_svc_run_service(bundle* b, int request_code,
 extern "C" API int aul_svc_run_service_for_uid(bundle* b, int request_code,
   aul_svc_res_fn cbfunc, void* data, uid_t uid) {
   CbInfo* cb_info = nullptr;
-  if (cbfunc)
+  if (cbfunc) {
     cb_info = new (std::nothrow) CbInfo(request_code, cbfunc, nullptr, data);
+    if (cb_info == nullptr)
+      LOGE("Out of memory");
+  }
 
   std::tuple<aul_svc_res_fn, void*> param { cbfunc, data };
   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
@@ -483,9 +623,6 @@ extern "C" API int aul_svc_get_all_defapps_for_uid(aul_svc_info_iter_fn iter_fn,
 
   tizen_base::Bundle res(response, false, true);
   auto appid_array = res.GetStringArray(AUL_K_APPID_LIST);
-  if (appid_array.size() == 0)
-    return AUL_SVC_RET_ERROR;
-
   for (auto& appid : appid_array) {
     if (iter_fn(appid.c_str(), data) != 0)
       break;
@@ -671,6 +808,9 @@ extern "C" API int aul_svc_get_appid_by_alias_appid_for_uid(
     return AUL_SVC_RET_EINVAL;
   }
 
+  if (!IsAmdReady())
+    return GetAppIdByAliasAppIdFromDB(alias_appid, appid, uid);
+
   bundle* response;
   tizen_base::Bundle request;
   request.Add(AUL_K_ALIAS_APPID, alias_appid);
@@ -698,7 +838,7 @@ extern "C" API const char *aul_svc_get_instance_id(bundle* b) {
 }
 
 extern "C" API int aul_svc_set_instance_id(bundle* b, const char* instance_id) {
-  if (b == nullptr || instance_id == nullptr) {
+  if (b == nullptr) {
     _E("Invalid parameter");
     return AUL_SVC_RET_EINVAL;
   }
@@ -754,6 +894,9 @@ extern "C" API int aul_svc_send_launch_request_for_uid(bundle* b,
 
   CbInfo* cb_info = new (std::nothrow) CbInfo(request_code, cbfunc, err_cb,
       user_data);
+  if (cb_info == nullptr)
+    _E("Out of memory");
+
   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
       [](const std::string& appid, bundle* request, uid_t uid,
         CbInfo* info) -> int {
@@ -1020,6 +1163,9 @@ extern "C" API int aul_svc_send_resume_request_for_uid(bundle* b,
 
   auto* cb_info = new (std::nothrow) CbInfo(request_code, nullptr, err_cb,
       user_data);
+  if (cb_info == nullptr)
+    _E("Out of memory");
+
   int ret = ::SendLaunchRequest<::SendLaunchRequestCb, ::CbInfo*>(
       [](const std::string& appid, bundle* request, uid_t uid,
           CbInfo* info) -> int {
@@ -1087,6 +1233,58 @@ extern "C" API void aul_svc_free_appid_array(char** appid_array,
   free(appid_array);
 }
 
+extern "C" API int aul_svc_set_window_position(bundle* b,
+    int x, int y, int w, int h) {
+  if (b == nullptr) {
+    _E("Invalid parameter");
+    return AUL_SVC_RET_EINVAL;
+  }
+
+  ::SetBundle(b, AUL_K_HINT_SCREEN_POS_X, std::to_string(x).c_str());
+  ::SetBundle(b, AUL_K_HINT_SCREEN_POS_Y, std::to_string(y).c_str());
+  ::SetBundle(b, AUL_K_HINT_SCREEN_WIDTH, std::to_string(w).c_str());
+  ::SetBundle(b, AUL_K_HINT_SCREEN_HEIGHT, std::to_string(h).c_str());
+
+  return AUL_SVC_RET_OK;
+}
+
+extern "C" API int aul_svc_get_window_position(bundle* b,
+    int* x, int* y, int* w, int* h) {
+  if (b == nullptr ||
+      x == nullptr ||
+      y == nullptr ||
+      w == nullptr ||
+      h == nullptr) {
+    _E("Invalid parameter");
+    return AUL_SVC_RET_EINVAL;
+  }
+
+  char* x_str = nullptr;
+  char* y_str = nullptr;
+  char* w_str = nullptr;
+  char* h_str = nullptr;
+
+  bundle_get_str(b , AUL_K_HINT_SCREEN_POS_X, &x_str);
+  bundle_get_str(b , AUL_K_HINT_SCREEN_POS_Y, &y_str);
+  bundle_get_str(b , AUL_K_HINT_SCREEN_WIDTH, &w_str);
+  bundle_get_str(b , AUL_K_HINT_SCREEN_HEIGHT, &h_str);
+
+  if (x_str == nullptr ||
+      y_str == nullptr ||
+      w_str == nullptr ||
+      h_str == nullptr) {
+    _E("failed to get position");
+    return AUL_SVC_RET_ERROR;
+  }
+
+  *x = atoi(x_str);
+  *y = atoi(y_str);
+  *w = atoi(w_str);
+  *h = atoi(h_str);
+
+  return AUL_SVC_RET_OK;
+}
+
 extern "C" API int aul_svc_set_defapp(const char* op, const char* mime_type,
     const char* uri, const char* defapp) {
   DEPRECATION_WARNING();